Configuration Schema
This reference is generated from AppConfig and its nested Rust types with
schemars. Field names follow Serde; defaults come from the Rust defaults.
The shape is shared by native and edge hosts. See Configuration
for CLI flags, environment variables and precedence.
Schema validation covers the serialized structure. Runtime checks, such as whether a master key decodes to 32 bytes or a backend was compiled in, still apply.
Download JSON Schema · Default configuration
AppConfig
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
audit_enabled | boolean | No | true | Record management and OAuth audit events. Read at startup; existing rows remain queryable. |
cache | CacheBackendConfig | No | {"kind":"memory"} | |
console | ConsoleConfig | No | {"enabled":true,"path":null} | |
cors_origins | Array<string> | No | [] | Browser origins allowed to call the APIs. Empty means same-origin only. |
data_dir | string | null | No | null | Root for instance state a backend resolves relative paths against: the SQLite file, the local file-storage root, downloaded vocabularies. |
file_storage | FileStorageConfig | null | No | null | None keeps file-backed resources (publications, vocabularies) disabled; core refuses those operations rather than inventing a location. |
host | string | No | "127.0.0.1" | Listen address of a native host. Ignored by the edge host, which is given its socket by the runtime. |
master_key | MasterKeyConfig | No | {"key":{"kind":"none"},"next":{"kind":"none"},"rotate":false} | |
oauth | OAuthIssuerConfig | No | {"access_ttl_secs":3600,"cli_client_ids":[],"code_ttl_secs":300,"device_ttl_secs":900,"refresh_ttl_secs":2592000} | |
port | integer | No | 8787 | |
public_base_url | string | null | No | null | Absolute external origin, e.g. |
session_ttl_secs | integer | No | 2592000 | |
store | StoreBackendConfig | No | {"kind":"sqlite","path":"gproxy.db"} | |
trusted_proxies | Array<string> | No | [] | Peers whose |
CacheBackendConfig
Shared TTL state, counters and invalidation notices. `Memory` is per process: correct for a single instance, and silently wrong for several, which is why a multi-instance deployment must name `Redis` or `Store`.
memory
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
kind | "memory" | Yes | — |
redis
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
kind | "redis" | Yes | — | |
namespace | string | null | No | — | |
url | string | Yes | — |
store
The database itself as the cache, for edge deployments with no Redis.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
kind | "store" | Yes | — |
ConsoleConfig
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
enabled | boolean | No | true | |
path | string | null | No | null | Serve the console from a directory instead of the embedded bundle. |
FileStorageConfig
Where publication and vocabulary bytes live. Unset means neither is served.
fs
A local directory, resolved against `data_dir` when relative.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
kind | "fs" | Yes | — | |
root | string | Yes | — |
s3
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
access_key_id | string | null | No | — | |
bucket | string | Yes | — | |
endpoint | string | null | No | — | Set for S3-compatible services that are not AWS. |
kind | "s3" | Yes | — | |
region | string | null | No | — | |
root | string | null | No | — | Key prefix inside the bucket; empty uses the bucket root. |
secret_access_key | string | null | No | — |
MasterKey
A 32-byte key, encoded. Two encodings because operators paste whichever their secret manager emits, and guessing between them silently is worse than naming it.
none
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
kind | "none" | Yes | — |
hex
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
kind | "hex" | Yes | — | |
value | string | Yes | — |
base64
Standard or URL-safe alphabet, with or without padding.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
kind | "base64" | Yes | — | |
value | string | Yes | — |
MasterKeyConfig
The key that seals upstream credential secrets at rest, and the rotation flow around it. Rotation is two configured keys and a switch: `key` is what the instance decrypts with today, `next` is what it re-seals to. With `rotate` set, the binary performs the rotation at startup as one management operation and the operator then promotes `next` to `key`. Leaving `key` unset stores secrets in plaintext; that is a supported deployment, not an accident, and the binary warns about it once at startup.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
key | MasterKey | No | {"kind":"none"} | |
next | MasterKey | No | {"kind":"none"} | The key to re-seal to. Configured on its own it does nothing; the
instance keeps using |
rotate | boolean | No | false | Perform the rotation at startup. Ignored without |
OAuthIssuerConfig
Lifetimes of what the OAuth issuer mints. Access tokens are short because they are bearer credentials with no revocation check on the hot path; codes and device codes are short because they are one-shot handoffs.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
access_ttl_secs | integer | No | 3600 | |
cli_client_ids | Array<string> | No | [] | Clients whose access tokens may perform any operation their permissions and granted scopes allow, rather than only the coding-agent baseline admission holds every other OAuth client to. Empty by default, which is the safe end: an access token is a
credential a user handed to somebody else’s program, so it starts able
to list models, count tokens, generate, stream and compact only when
their scopes were granted. An operator names a first-party CLI here once they accept that it
speaks for the user across the whole API. See
|
code_ttl_secs | integer | No | 300 | |
device_ttl_secs | integer | No | 900 | |
refresh_ttl_secs | integer | No | 2592000 |
StoreBackendConfig
Where the durable configuration and usage live. Which variants a build can actually open depends on the backend features the binary was built with; an unsupported one is refused when the connection is made, not here.
sqlite
A local file, resolved against `data_dir` when relative.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
kind | "sqlite" | Yes | — | |
path | string | Yes | — |
url
Any SeaORM connection string (`postgres://`, `mysql://`, `sqlite://`).
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
dsn | string | Yes | — | |
kind | "url" | Yes | — |
d1
A Cloudflare D1 binding name, resolved from the Worker environment.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
binding | string | Yes | — | |
kind | "d1" | Yes | — |
libsql
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
kind | "libsql" | Yes | — | |
token | string | null | No | — | |
url | string | Yes | — |
Default configuration
{
"host": "127.0.0.1",
"port": 8787,
"data_dir": null,
"store": {
"kind": "sqlite",
"path": "gproxy.db"
},
"cache": {
"kind": "memory"
},
"master_key": {
"key": {
"kind": "none"
},
"next": {
"kind": "none"
},
"rotate": false
},
"file_storage": null,
"public_base_url": null,
"cors_origins": [],
"trusted_proxies": [],
"console": {
"enabled": true,
"path": null
},
"audit_enabled": true,
"session_ttl_secs": 2592000,
"oauth": {
"access_ttl_secs": 3600,
"refresh_ttl_secs": 2592000,
"code_ttl_secs": 300,
"device_ttl_secs": 900,
"cli_client_ids": []
}
}Complete JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "AppConfig",
"type": "object",
"properties": {
"audit_enabled": {
"description": "Record management and OAuth audit events. Read at startup; existing rows remain queryable.",
"type": "boolean",
"default": true
},
"cache": {
"$ref": "#/$defs/CacheBackendConfig",
"default": {
"kind": "memory"
}
},
"console": {
"$ref": "#/$defs/ConsoleConfig",
"default": {
"enabled": true,
"path": null
}
},
"cors_origins": {
"description": "Browser origins allowed to call the APIs. Empty means same-origin only.",
"type": "array",
"default": [],
"items": {
"type": "string"
}
},
"data_dir": {
"description": "Root for instance state a backend resolves relative paths against: the\nSQLite file, the local file-storage root, downloaded vocabularies.",
"type": [
"string",
"null"
],
"default": null
},
"file_storage": {
"description": "None keeps file-backed resources (publications, vocabularies) disabled;\ncore refuses those operations rather than inventing a location.",
"anyOf": [
{
"$ref": "#/$defs/FileStorageConfig"
},
{
"type": "null"
}
],
"default": null
},
"host": {
"description": "Listen address of a native host. Ignored by the edge host, which is\ngiven its socket by the runtime.",
"type": "string",
"default": "127.0.0.1"
},
"master_key": {
"$ref": "#/$defs/MasterKeyConfig",
"default": {
"key": {
"kind": "none"
},
"next": {
"kind": "none"
},
"rotate": false
}
},
"oauth": {
"$ref": "#/$defs/OAuthIssuerConfig",
"default": {
"access_ttl_secs": 3600,
"cli_client_ids": [],
"code_ttl_secs": 300,
"device_ttl_secs": 900,
"refresh_ttl_secs": 2592000
}
},
"port": {
"type": "integer",
"format": "uint16",
"default": 8787,
"maximum": 65535,
"minimum": 0
},
"public_base_url": {
"description": "Absolute external origin, e.g. `https://gproxy.example.com`. Used to\nmint publication URLs and the OAuth issuer identifier when the request\nitself cannot be trusted to name the instance.",
"type": [
"string",
"null"
],
"default": null
},
"session_ttl_secs": {
"type": "integer",
"format": "uint64",
"default": 2592000,
"minimum": 0
},
"store": {
"$ref": "#/$defs/StoreBackendConfig",
"default": {
"kind": "sqlite",
"path": "gproxy.db"
}
},
"trusted_proxies": {
"description": "Peers whose `x-forwarded-for` / `x-forwarded-proto` are believed. Empty\nmeans the socket address is the client address, which is the safe\ndefault: a spoofed client IP is a spoofed rate-limit bucket.",
"type": "array",
"default": [],
"items": {
"type": "string"
}
}
},
"additionalProperties": false,
"$defs": {
"CacheBackendConfig": {
"description": "Shared TTL state, counters and invalidation notices. `Memory` is per\nprocess: correct for a single instance, and silently wrong for several,\nwhich is why a multi-instance deployment must name `Redis` or `Store`.",
"oneOf": [
{
"type": "object",
"properties": {
"kind": {
"type": "string",
"const": "memory"
}
},
"required": [
"kind"
]
},
{
"type": "object",
"properties": {
"kind": {
"type": "string",
"const": "redis"
},
"namespace": {
"type": [
"string",
"null"
]
},
"url": {
"type": "string"
}
},
"required": [
"kind",
"url"
]
},
{
"description": "The database itself as the cache, for edge deployments with no Redis.",
"type": "object",
"properties": {
"kind": {
"type": "string",
"const": "store"
}
},
"required": [
"kind"
]
}
]
},
"ConsoleConfig": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean",
"default": true
},
"path": {
"description": "Serve the console from a directory instead of the embedded bundle.",
"type": [
"string",
"null"
],
"default": null
}
},
"additionalProperties": false
},
"FileStorageConfig": {
"description": "Where publication and vocabulary bytes live. Unset means neither is served.",
"oneOf": [
{
"description": "A local directory, resolved against `data_dir` when relative.",
"type": "object",
"properties": {
"kind": {
"type": "string",
"const": "fs"
},
"root": {
"type": "string"
}
},
"required": [
"kind",
"root"
]
},
{
"type": "object",
"properties": {
"access_key_id": {
"type": [
"string",
"null"
]
},
"bucket": {
"type": "string"
},
"endpoint": {
"description": "Set for S3-compatible services that are not AWS.",
"type": [
"string",
"null"
]
},
"kind": {
"type": "string",
"const": "s3"
},
"region": {
"type": [
"string",
"null"
]
},
"root": {
"description": "Key prefix inside the bucket; empty uses the bucket root.",
"type": [
"string",
"null"
]
},
"secret_access_key": {
"type": [
"string",
"null"
]
}
},
"required": [
"kind",
"bucket"
]
}
]
},
"MasterKey": {
"description": "A 32-byte key, encoded. Two encodings because operators paste whichever\ntheir secret manager emits, and guessing between them silently is worse\nthan naming it.",
"oneOf": [
{
"type": "object",
"properties": {
"kind": {
"type": "string",
"const": "none"
}
},
"required": [
"kind"
]
},
{
"type": "object",
"properties": {
"kind": {
"type": "string",
"const": "hex"
},
"value": {
"type": "string"
}
},
"required": [
"kind",
"value"
]
},
{
"description": "Standard or URL-safe alphabet, with or without padding.",
"type": "object",
"properties": {
"kind": {
"type": "string",
"const": "base64"
},
"value": {
"type": "string"
}
},
"required": [
"kind",
"value"
]
}
]
},
"MasterKeyConfig": {
"description": "The key that seals upstream credential secrets at rest, and the rotation\nflow around it.\n\nRotation is two configured keys and a switch: `key` is what the instance\ndecrypts with today, `next` is what it re-seals to. With `rotate` set, the\nbinary performs the rotation at startup as one management operation and the\noperator then promotes `next` to `key`. Leaving `key` unset stores secrets\nin plaintext; that is a supported deployment, not an accident, and the\nbinary warns about it once at startup.",
"type": "object",
"properties": {
"key": {
"$ref": "#/$defs/MasterKey",
"default": {
"kind": "none"
}
},
"next": {
"description": "The key to re-seal to. Configured on its own it does nothing; the\ninstance keeps using `key`.",
"$ref": "#/$defs/MasterKey",
"default": {
"kind": "none"
}
},
"rotate": {
"description": "Perform the rotation at startup. Ignored without `next`.",
"type": "boolean",
"default": false
}
},
"additionalProperties": false
},
"OAuthIssuerConfig": {
"description": "Lifetimes of what the OAuth issuer mints. Access tokens are short because\nthey are bearer credentials with no revocation check on the hot path;\ncodes and device codes are short because they are one-shot handoffs.",
"type": "object",
"properties": {
"access_ttl_secs": {
"type": "integer",
"format": "uint64",
"default": 3600,
"minimum": 0
},
"cli_client_ids": {
"description": "Clients whose access tokens may perform *any* operation their\npermissions and granted scopes allow, rather than only the coding-agent\nbaseline admission holds every other OAuth client to.\n\nEmpty by default, which is the safe end: an access token is a\ncredential a user handed to somebody else's program, so it starts able\nto list models, count tokens, generate, stream and compact only when\ntheir scopes were granted. An operator names a first-party CLI here once they accept that it\nspeaks for the user across the whole API. See\n[`admission::permission`](crate::admission::permission).",
"type": "array",
"default": [],
"items": {
"type": "string"
}
},
"code_ttl_secs": {
"type": "integer",
"format": "uint64",
"default": 300,
"minimum": 0
},
"device_ttl_secs": {
"type": "integer",
"format": "uint64",
"default": 900,
"minimum": 0
},
"refresh_ttl_secs": {
"type": "integer",
"format": "uint64",
"default": 2592000,
"minimum": 0
}
},
"additionalProperties": false
},
"StoreBackendConfig": {
"description": "Where the durable configuration and usage live. Which variants a build can\nactually open depends on the backend features the binary was built with;\nan unsupported one is refused when the connection is made, not here.",
"oneOf": [
{
"description": "A local file, resolved against `data_dir` when relative.",
"type": "object",
"properties": {
"kind": {
"type": "string",
"const": "sqlite"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path"
]
},
{
"description": "Any SeaORM connection string (`postgres://`, `mysql://`, `sqlite://`).",
"type": "object",
"properties": {
"dsn": {
"type": "string"
},
"kind": {
"type": "string",
"const": "url"
}
},
"required": [
"kind",
"dsn"
]
},
{
"description": "A Cloudflare D1 binding name, resolved from the Worker environment.",
"type": "object",
"properties": {
"binding": {
"type": "string"
},
"kind": {
"type": "string",
"const": "d1"
}
},
"required": [
"kind",
"binding"
]
},
{
"type": "object",
"properties": {
"kind": {
"type": "string",
"const": "libsql"
},
"token": {
"type": [
"string",
"null"
]
},
"url": {
"type": "string"
}
},
"required": [
"kind",
"url"
]
}
]
}
}
}