Skip to content

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

FieldTypeRequiredDefaultDescription
audit_enabledbooleanNotrue

Record management and OAuth audit events. Read at startup; existing rows remain queryable.

cacheCacheBackendConfigNo{"kind":"memory"}
consoleConsoleConfigNo{"enabled":true,"path":null}
cors_originsArray<string>No[]

Browser origins allowed to call the APIs. Empty means same-origin only.

data_dirstring | nullNonull

Root for instance state a backend resolves relative paths against: the SQLite file, the local file-storage root, downloaded vocabularies.

file_storageFileStorageConfig | nullNonull

None keeps file-backed resources (publications, vocabularies) disabled; core refuses those operations rather than inventing a location.

hoststringNo"127.0.0.1"

Listen address of a native host. Ignored by the edge host, which is given its socket by the runtime.

master_keyMasterKeyConfigNo{"key":{"kind":"none"},"next":{"kind":"none"},"rotate":false}
oauthOAuthIssuerConfigNo{"access_ttl_secs":3600,"cli_client_ids":[],"code_ttl_secs":300,"device_ttl_secs":900,"refresh_ttl_secs":2592000}
portintegerNo8787
public_base_urlstring | nullNonull

Absolute external origin, e.g. https://gproxy.example.com. Used to mint publication URLs and the OAuth issuer identifier when the request itself cannot be trusted to name the instance.

session_ttl_secsintegerNo2592000
storeStoreBackendConfigNo{"kind":"sqlite","path":"gproxy.db"}
trusted_proxiesArray<string>No[]

Peers whose x-forwarded-for / x-forwarded-proto are believed. Empty means the socket address is the client address, which is the safe default: a spoofed client IP is a spoofed rate-limit bucket.

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

FieldTypeRequiredDefaultDescription
kind"memory"Yes—

redis

FieldTypeRequiredDefaultDescription
kind"redis"Yes—
namespacestring | nullNo—
urlstringYes—

store

The database itself as the cache, for edge deployments with no Redis.

FieldTypeRequiredDefaultDescription
kind"store"Yes—

ConsoleConfig

FieldTypeRequiredDefaultDescription
enabledbooleanNotrue
pathstring | nullNonull

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.

FieldTypeRequiredDefaultDescription
kind"fs"Yes—
rootstringYes—

s3

FieldTypeRequiredDefaultDescription
access_key_idstring | nullNo—
bucketstringYes—
endpointstring | nullNo—

Set for S3-compatible services that are not AWS.

kind"s3"Yes—
regionstring | nullNo—
rootstring | nullNo—

Key prefix inside the bucket; empty uses the bucket root.

secret_access_keystring | nullNo—

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

FieldTypeRequiredDefaultDescription
kind"none"Yes—

hex

FieldTypeRequiredDefaultDescription
kind"hex"Yes—
valuestringYes—

base64

Standard or URL-safe alphabet, with or without padding.

FieldTypeRequiredDefaultDescription
kind"base64"Yes—
valuestringYes—

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.

FieldTypeRequiredDefaultDescription
keyMasterKeyNo{"kind":"none"}
nextMasterKeyNo{"kind":"none"}

The key to re-seal to. Configured on its own it does nothing; the instance keeps using key.

rotatebooleanNofalse

Perform the rotation at startup. Ignored without next.

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.

FieldTypeRequiredDefaultDescription
access_ttl_secsintegerNo3600
cli_client_idsArray<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 admission::permission.

code_ttl_secsintegerNo300
device_ttl_secsintegerNo900
refresh_ttl_secsintegerNo2592000

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.

FieldTypeRequiredDefaultDescription
kind"sqlite"Yes—
pathstringYes—

url

Any SeaORM connection string (`postgres://`, `mysql://`, `sqlite://`).

FieldTypeRequiredDefaultDescription
dsnstringYes—
kind"url"Yes—

d1

A Cloudflare D1 binding name, resolved from the Worker environment.

FieldTypeRequiredDefaultDescription
bindingstringYes—
kind"d1"Yes—

libsql

FieldTypeRequiredDefaultDescription
kind"libsql"Yes—
tokenstring | nullNo—
urlstringYes—

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"
          ]
        }
      ]
    }
  }
}