{
  "type": "object",
  "properties": {
    "profile": {
      "type": [
        "string",
        "null"
      ],
      "default": null,
      "description": "Deployment name identifying this cluster, and the label its telemetry carries: every Prometheus series, every structured log line and every exported trace of every role.",
      "x-gdsgate-roles": [
        "authority",
        "proxy",
        "connector",
        "agent-host",
        "client"
      ]
    },
    "security": {
      "$ref": "#/$defs/Security",
      "description": "What this deployment is held to (`[security]`).",
      "x-gdsgate-roles": [
        "authority",
        "proxy",
        "connector",
        "agent-host"
      ]
    },
    "endpoints": {
      "$ref": "#/$defs/Endpoints",
      "description": "Service network addresses.",
      "x-gdsgate-roles": [
        "authority",
        "proxy",
        "connector",
        "agent-host",
        "client"
      ]
    },
    "store_url": {
      "type": [
        "string",
        "null"
      ],
      "default": null,
      "description": "State backend connection URL consumed by Authority.",
      "x-gdsgate-roles": [
        "authority"
      ],
      "x-gdsgate-profiles": [
        "pilot",
        "production"
      ]
    },
    "store_password_file": {
      "type": [
        "string",
        "null"
      ],
      "default": null,
      "description": "Path to a file holding the state backend's password, kept out of `store_url`.",
      "x-gdsgate-roles": [
        "authority"
      ]
    },
    "store_auto_migrate": {
      "type": "boolean",
      "default": true,
      "description": "Whether a starting service may bring the store's schema up to date itself.",
      "x-gdsgate-roles": [
        "authority"
      ]
    },
    "enroll": {
      "$ref": "#/$defs/Enroll",
      "description": "Node-enrollment settings (standalone `proxy`/`connector`).",
      "x-gdsgate-roles": [
        "proxy",
        "connector",
        "agent-host"
      ]
    },
    "authority": {
      "$ref": "#/$defs/Authority",
      "description": "Authority's own listeners: the certificate the registration listener presents, and the emergency socket.",
      "x-gdsgate-roles": [
        "authority"
      ]
    },
    "transport": {
      "$ref": "#/$defs/Transport",
      "description": "Transport (`HostTls`) identity issuance, consumed by Authority.",
      "x-gdsgate-roles": [
        "authority",
        "proxy",
        "connector"
      ]
    },
    "client": {
      "$ref": "#/$defs/Client",
      "description": "Client-side settings (`login`/`ssh`/`ca`).",
      "x-gdsgate-roles": [
        "client",
        "proxy"
      ]
    },
    "proxy": {
      "$ref": "#/$defs/Proxy",
      "description": "Proxy listener mode (separate listeners by default; optional single-port ALPN/SNI multiplex).",
      "x-gdsgate-roles": [
        "proxy"
      ]
    },
    "policy": {
      "$ref": "#/$defs/Policy",
      "description": "Authorization policy source consumed by Authority (deny-all bootstrap if unset).",
      "x-gdsgate-roles": [
        "authority"
      ]
    },
    "mcp": {
      "$ref": "#/$defs/Mcp",
      "description": "MCP per-tool policy settings (`[mcp].destructive_patterns`).",
      "x-gdsgate-roles": [
        "authority"
      ]
    },
    "mfa": {
      "$ref": "#/$defs/Mfa",
      "description": "Gateway step-up MFA factors (`[mfa]`).",
      "x-gdsgate-roles": [
        "authority"
      ]
    },
    "oidc": {
      "$ref": "#/$defs/Oidc",
      "description": "External OIDC identity provider (dev issuer if unset).",
      "x-gdsgate-roles": [
        "authority",
        "proxy",
        "client"
      ]
    },
    "identity": {
      "$ref": "#/$defs/Identity",
      "description": "Identity-claim sanitisation policy.",
      "x-gdsgate-roles": [
        "authority"
      ]
    },
    "workload": {
      "$ref": "#/$defs/Workload",
      "description": "Workload identity establishment (trusted platform issuers → SPIFFE identities; disabled by default).",
      "x-gdsgate-roles": [
        "authority"
      ]
    },
    "ca_rotation": {
      "$ref": "#/$defs/CaRotation",
      "description": "Automatic User SSH CA rotation (disabled by default).",
      "x-gdsgate-roles": [
        "authority"
      ]
    },
    "ha": {
      "$ref": "#/$defs/Ha",
      "description": "High-availability (audit write-leader election; disabled by default).",
      "x-gdsgate-roles": [
        "authority"
      ]
    },
    "approvals": {
      "$ref": "#/$defs/Approvals",
      "description": "JIT access-request approval thresholds.",
      "x-gdsgate-roles": [
        "authority"
      ]
    },
    "discovery": {
      "$ref": "#/$defs/Discovery",
      "description": "Resource catalog + label import-rules Authority seeds on startup.",
      "x-gdsgate-roles": [
        "authority"
      ]
    },
    "connector": {
      "$ref": "#/$defs/Connector",
      "description": "Connector settings (identity + the resources this connector serves).",
      "x-gdsgate-roles": [
        "connector"
      ]
    },
    "agent_host": {
      "$ref": "#/$defs/AgentHost",
      "description": "Agent-host settings (the identity this node runs agents under).",
      "x-gdsgate-roles": [
        "agent-host"
      ]
    },
    "recording": {
      "$ref": "#/$defs/Recording",
      "description": "Session-recording sink: local disk, or the Authority-backed central store.",
      "x-gdsgate-roles": [
        "connector"
      ]
    },
    "admin": {
      "$ref": "#/$defs/Admin",
      "description": "Operator-workstation settings: where the admin CLI sends its mTLS-authenticated RPCs (`create-token`, `revoke-node`, `list-nodes`) and where its enrolled identity material lives.",
      "x-gdsgate-roles": [
        "client"
      ]
    },
    "audit": {
      "$ref": "#/$defs/Audit",
      "description": "Audit chain anchoring + off-cluster export.",
      "x-gdsgate-roles": [
        "authority"
      ]
    },
    "telemetry": {
      "$ref": "#/$defs/Telemetry",
      "description": "Operational observability surface (Prometheus `/metrics` + health).",
      "x-gdsgate-roles": [
        "authority",
        "proxy",
        "connector",
        "agent-host"
      ]
    },
    "doctor": {
      "$ref": "#/$defs/Doctor",
      "description": "Periodic self-diagnosis that publishes `gdsgate_doctor_*` gauges when the observability surface is on (daemon commands only).",
      "x-gdsgate-roles": [
        "authority",
        "proxy",
        "connector",
        "agent-host"
      ]
    },
    "agent_profiles": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/AgentProfile"
      },
      "description": "The agent-profile registry `gdsgate delegate --exec` wires a named program up from.",
      "x-gdsgate-roles": [
        "client"
      ]
    },
    "delegation_profiles": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/DelegationProfile"
      },
      "description": "Saved `gdsgate delegate` invocations (`[[delegation_profiles]]`), each selected by `--profile <name>`.",
      "x-gdsgate-roles": [
        "client"
      ]
    },
    "kms_keys": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/KmsKey"
      },
      "description": "The external keys this deployment's wrapped material sits under (`[[kms_keys]]`).",
      "x-gdsgate-roles": [
        "authority"
      ]
    }
  },
  "$defs": {
    "Security": {
      "type": "object",
      "properties": {
        "profile": {
          "anyOf": [
            {
              "$ref": "#/$defs/SecurityProfile"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Deployment profile: `dev`, `pilot` or `production`; unset, start-up checks nothing."
        },
        "integrity": {
          "$ref": "#/$defs/Integrity",
          "description": "The two keyrings the seals on this cluster's rows are put under (`[security.integrity]`)."
        }
      },
      "description": "Deployment profile and seal keyrings (`[security]`).",
      "additionalProperties": false
    },
    "SecurityProfile": {
      "oneOf": [
        {
          "type": "string",
          "const": "dev",
          "description": "A development deployment: nothing is refused; the start logs one warning."
        },
        {
          "type": "string",
          "const": "pilot",
          "description": "A trial cluster: `PostgreSQL` store, TLS on every hop, separate services."
        },
        {
          "type": "string",
          "const": "production",
          "description": "A production cluster: everything `pilot` requires, plus both keyrings, protected key files and an identity provider."
        }
      ],
      "description": "Deployment profile: `dev`, `pilot` or `production`."
    },
    "Integrity": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "control_keyring": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "The keyring approvals, revocations, delegations and inventory receipts are sealed under.",
          "x-gdsgate-profiles": [
            "production"
          ]
        },
        "audit_keyring": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "The keyring the audit chain's anchors are sealed under.",
          "x-gdsgate-profiles": [
            "production"
          ]
        }
      },
      "description": "Where the keys that seal this cluster's rows come from."
    },
    "Endpoints": {
      "type": "object",
      "properties": {
        "authority": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Authority service gRPC listener (mTLS once the cluster is enrolled)."
        },
        "authority_failover": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Additional Authority endpoints (HA): the proxy dials `authority` plus these, and follows the audit write-leader across failover (a follower answers `Unavailable`; the proxy retries the next)."
        },
        "authority_enroll": {
          "type": "string",
          "default": "127.0.0.1:50050",
          "description": "Authority bootstrap enrollment listener (plaintext; node join)."
        },
        "authority_enroll_failover": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Additional registration listeners, tried before sending a registration RPC."
        },
        "proxy_public": {
          "type": "string",
          "default": "127.0.0.1:50061",
          "description": "Public, client-facing Proxy listener (`RequestAccess`, `OpenSession`, Health)."
        },
        "proxy_internal": {
          "type": "string",
          "default": "127.0.0.1:50062",
          "description": "Connector-facing internal Proxy listener (the reverse tunnel)."
        },
        "proxy_ws": {
          "type": "string",
          "default": "127.0.0.1:50063",
          "description": "Connector-facing WebSocket fallback listener."
        },
        "proxy_join": {
          "type": "string",
          "default": "",
          "description": "Proxy listener that relays a node's *join* traffic (registration and token-less renewal) to Authority, for nodes that reach only the Proxy."
        }
      },
      "description": "Network addresses of the cluster's services (bind / dial targets, `host:port`).",
      "additionalProperties": false
    },
    "Enroll": {
      "type": "object",
      "properties": {
        "endpoint": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Authority registration endpoint URL, e.g. `https://authority.example.com:50050`.",
          "x-gdsgate-profiles": [
            "pilot",
            "production"
          ]
        },
        "token": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "One-time provision token authorizing the join.",
          "x-gdsgate-profiles": [
            "pilot",
            "production"
          ]
        },
        "state_dir": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "State directory holding the persisted transport identity."
        },
        "renew_endpoint": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Authority control-plane mTLS endpoint URL for token-less renewals."
        },
        "background_renewal": {
          "type": "boolean",
          "default": true,
          "description": "Whether the node keeps its transport leaf current in the background."
        },
        "transport_ca": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path to the PEM anchor this node verifies the **registration** listener against, for an `https://` `endpoint`."
        },
        "transport_sni": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "TLS server name this node verifies the registration listener against; default: the host in `endpoint`."
        },
        "node_name": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "What this node calls itself in the cluster's node registry — a host name, an inventory label, whatever the operator matches rows against."
        }
      },
      "description": "Node-enrollment settings.",
      "additionalProperties": false
    },
    "Authority": {
      "type": "object",
      "properties": {
        "enroll_cert_file": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "PEM certificate chain the **registration listener** (`[endpoints].authority_enroll`) presents.",
          "x-gdsgate-profiles": [
            "pilot",
            "production"
          ]
        },
        "enroll_key_file": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "PEM private key for `enroll_cert_file`.",
          "x-gdsgate-profiles": [
            "pilot",
            "production"
          ]
        },
        "enroll_cert_from_cluster_ca": {
          "type": "boolean",
          "default": false,
          "description": "Authority issues the registration certificate itself, from the cluster CA, and keeps it current."
        },
        "emergency_socket": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path of the **emergency administrative socket**: a Unix socket on this host for administrative calls without a certificate; access to the socket file is the credential."
        },
        "ca_kms_key": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Which `[[kms_keys]]` entry the CA signing seeds in `ca_private_key` are wrapped under."
        },
        "agent_declaration_version": {
          "$ref": "#/$defs/AgentDeclarationVersion",
          "default": "optional",
          "description": "Whether rewriting an agent declaration has to name the version it was edited from."
        }
      },
      "description": "Authority's own listeners (`[authority]`).",
      "additionalProperties": false
    },
    "AgentDeclarationVersion": {
      "oneOf": [
        {
          "type": "string",
          "const": "optional",
          "description": "A rewrite without a version replaces what is there."
        },
        {
          "type": "string",
          "const": "required",
          "description": "A rewrite without a version is refused."
        }
      ],
      "description": "Whether rewriting an agent declaration has to name the version it was edited from: `optional` or `required`."
    },
    "Transport": {
      "type": "object",
      "properties": {
        "cert_ttl_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 86400,
          "description": "Validity of an issued node transport leaf (seconds)."
        },
        "front_sni": {
          "type": "string",
          "default": "",
          "description": "**The server name this cluster answers to on a front shared by several clusters.**"
        }
      },
      "description": "Issuance settings for the **transport** (`HostTls`) identity every node runs internal mutual TLS on.",
      "additionalProperties": false
    },
    "Client": {
      "type": "object",
      "properties": {
        "transport_ca": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path to the cluster's transport CA (PEM) the client verifies the Proxy's public TLS listener against."
        },
        "transport_sni": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "TLS server name the CLI verifies the Proxy's public listener against; default: the shared internal name with `transport_ca`, else the dialled host."
        },
        "allow_insecure_http": {
          "type": "boolean",
          "default": false,
          "description": "Whether the client may talk to the gateway over plaintext `http://`."
        },
        "access": {
          "$ref": "#/$defs/AccessMode",
          "default": "auto",
          "description": "**Where** the resident client puts the addresses resources answer on."
        },
        "local_user_only": {
          "type": [
            "boolean",
            "null"
          ],
          "default": null,
          "description": "Restricts resource connections to the resident owner's OS UID on Linux."
        },
        "resolver": {
          "$ref": "#/$defs/ResolverMode",
          "default": "auto",
          "description": "**How** resource names are served."
        },
        "warm_access": {
          "type": "boolean",
          "default": true,
          "description": "Whether the resident client obtains each resource's access certificate during the catalog pass, before the first connection."
        },
        "notify": {
          "type": "boolean",
          "default": true,
          "description": "Whether a refusal is announced with a notification from the operating system."
        },
        "step_up_on_denial": {
          "type": "boolean",
          "default": false,
          "description": "Whether the resident client raises the step-up a refusal offers."
        },
        "intercept_names": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Domains this machine hands to gdsgate: names an application already answers on (`app.example.com`) that the resident client will answer for locally, so a browser reaches the application through the gateway under the application's own name."
        },
        "agent_resources": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/AgentResource"
          },
          "description": "Resources this machine will serve the user's SSH agent to, one entry per resource."
        },
        "agent_key_source": {
          "$ref": "#/$defs/AgentKeySource",
          "default": "proxy",
          "description": "Where the keys the agent offers come from."
        },
        "agent_signatures_per_process": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0,
          "default": 64,
          "description": "Working budget: signatures one local `ssh` process may get for one resource."
        },
        "agent_signatures_per_resource": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0,
          "default": 512,
          "description": "Ceiling: signatures served for one resource inside `agent_signature_window`, across every channel and every process."
        },
        "agent_signature_window": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 600,
          "description": "Width of that ceiling's sliding window, in seconds."
        },
        "agent_identities_max": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0,
          "default": 5,
          "description": "Identities the agent lists at most, in the declared order."
        },
        "agent_auth_attempts_max": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0,
          "default": 5,
          "description": "Signatures served on one connection to the agent socket — one downstream authentication attempt."
        },
        "agent_frame_max": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 32768,
          "description": "Largest agent frame read, in bytes."
        },
        "agent_channel_ttl": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 600,
          "description": "Absolute life of one connection to the agent socket, in seconds, counted from when it was opened."
        },
        "direct": {
          "$ref": "#/$defs/ClientDirect",
          "description": "Settings of the loopback levels, `access = \"basic\"` and `\"direct\"`."
        },
        "transparent": {
          "$ref": "#/$defs/ClientTransparent",
          "description": "Settings of the virtual-address level, `access = \"transparent\"`."
        }
      },
      "description": "Client-side settings for the `login`/`ssh`/`ca` commands and for the resident client.",
      "additionalProperties": false
    },
    "AccessMode": {
      "oneOf": [
        {
          "type": "string",
          "const": "off",
          "description": "No local listeners at all."
        },
        {
          "type": "string",
          "const": "basic",
          "description": "A resource is addressed **by port**: one listener per resource on `127.0.0.1`, each on its own port out of `[client.direct].basic_port_range`."
        },
        {
          "type": "string",
          "const": "direct",
          "description": "A resource is addressed **by address**: its own address out of `[client.direct].v4_pool`, on the protocol's own port."
        },
        {
          "type": "string",
          "const": "transparent",
          "description": "A resource is addressed **by name**, on a virtual address of its own."
        },
        {
          "type": "string",
          "const": "auto",
          "description": "Probe for the most capable level this host allows and use it, reporting which one was chosen."
        }
      ],
      "description": "Where a resident client puts the addresses resources answer on: `off`, `basic`, `direct`, `transparent` or `auto`."
    },
    "ResolverMode": {
      "oneOf": [
        {
          "type": "string",
          "const": "off",
          "description": "No names."
        },
        {
          "type": "string",
          "const": "hosts",
          "description": "Names go into the hosts file of the operating system."
        },
        {
          "type": "string",
          "const": "system",
          "description": "The zone is served to the system resolver, so names work for every protocol."
        },
        {
          "type": "string",
          "const": "auto",
          "description": "Use `system` where the client can set it up, else `hosts`, else `off`."
        }
      ],
      "description": "How resource names are served to the resolver of the operating system."
    },
    "AgentResource": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "resource": {
          "type": "string",
          "description": "Resource id, spelled exactly as the catalog spells it."
        },
        "key": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Key file offered first for this resource; the rest follow in the order the source lists them."
        }
      },
      "required": [
        "resource"
      ],
      "description": "One resource the person at this machine agrees to lend their SSH key to."
    },
    "AgentKeySource": {
      "oneOf": [
        {
          "type": "string",
          "const": "proxy",
          "description": "Requests are passed to the agent already running for this user (`SSH_AUTH_SOCK`)."
        },
        {
          "type": "string",
          "const": "key_files",
          "description": "Key files under `~/.ssh` are read and held in the resident process's memory."
        }
      ],
      "description": "Where the keys a resident client's agent offers come from."
    },
    "ClientDirect": {
      "type": "object",
      "properties": {
        "v4_pool": {
          "type": "string",
          "default": "127.70.0.0/16",
          "description": "Address pool `access = \"direct\"` gives resources addresses out of."
        },
        "basic_port_range": {
          "type": "string",
          "default": "15000-15999",
          "description": "Port range `access = \"basic\"` gives resources ports out of, as `first-last`."
        },
        "privileged_port_offset": {
          "type": "integer",
          "format": "uint16",
          "minimum": 0,
          "maximum": 65535,
          "default": 10000,
          "description": "Added to protocol ports 1–1023 at the direct level."
        },
        "catalog_sync_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 60,
          "description": "How often the resident client re-reads the catalog, in seconds."
        }
      },
      "description": "Settings of the loopback levels, `access = \"basic\"` and `\"direct\"` (`[client.direct]`).",
      "additionalProperties": false
    },
    "ClientTransparent": {
      "type": "object",
      "properties": {
        "v4_pool": {
          "type": "string",
          "default": "198.18.0.0/15",
          "description": "Address pool virtual addresses are handed out of."
        },
        "v6_pool": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "IPv6 pool, **recognised but unused**: this release hands out IPv4 addresses only."
        },
        "dns_zone": {
          "type": "string",
          "default": "gds",
          "description": "Zone resource names are published under — one label, e.g. `gds` for `pg-prod.gds`."
        },
        "reuse_grace_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 86400,
          "description": "How long a released address is held before it may be handed to another resource, in seconds."
        }
      },
      "description": "Settings of `access = \"transparent\"` (`[client.transparent]`).",
      "additionalProperties": false
    },
    "Proxy": {
      "type": "object",
      "properties": {
        "peer_addr": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Individual HTTPS address used to publish durable connector routes."
        },
        "peer_listen": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Dedicated internal mutual-TLS listener for Proxy peer streams."
        },
        "single_port": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "When set, the Proxy multiplexes the client-facing gRPC API and the connector-facing WebSocket fallback onto this **single** address by peeking each connection's first bytes (TLS `ClientHello` ALPN/SNI, or an HTTP upgrade) and routing accordingly."
        },
        "max_sessions": {
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 0,
          "description": "Maximum number of concurrent client sessions the proxy relays at once."
        },
        "abandoned_session_grace_secs": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0,
          "default": null,
          "description": "How long the Proxy holds a departed connector's live sessions before reporting them to Authority as unaccounted for, in seconds."
        },
        "max_streams_per_tunnel": {
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 0,
          "description": "Maximum number of concurrent backend streams a single connector tunnel may hold open."
        },
        "max_public_connections": {
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 0,
          "description": "Maximum number of concurrent connections on the **public, client-facing** gRPC listener."
        },
        "max_peer_connections": {
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 0,
          "description": "Dedicated peer listener socket cap; `0` uses the built-in cap of 128."
        },
        "max_peer_requests": {
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 0,
          "description": "Concurrent peer discovery/admission calls; `0` uses 32."
        },
        "max_peer_sessions": {
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 0,
          "description": "Concurrent peer streams, including pending opens; `0` uses 128."
        },
        "internal_accept_rate_per_ip": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0,
          "default": 0,
          "description": "Per-peer-IP accept rate (tokens/second) on the **connector-facing** internal gRPC + WebSocket listeners."
        },
        "internal_accept_burst": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0,
          "default": 0,
          "description": "Token-bucket burst size for `internal_accept_rate_per_ip`."
        },
        "public_anonymous_rate_per_ip": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0,
          "default": 0,
          "description": "Per-source-IP **call** rate (calls/second) for the two RPCs on the public, client-facing listener that answer before the caller has been authenticated: `Bootstrap.GetBundle` (the settings bundle `gdsgate connect` fetches) and `Health.Check`."
        },
        "public_anonymous_burst": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0,
          "default": 0,
          "description": "Token-bucket burst size for `public_anonymous_rate_per_ip`."
        },
        "max_bytes_per_second_per_session": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 0,
          "description": "Sustained bytes/second a single relayed session may push through the proxy, **combined across both directions**."
        },
        "session_rate_burst_bytes": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 0,
          "description": "Token-bucket burst, in bytes, for `max_bytes_per_second_per_session`: how much a momentarily-idle session may relay back-to-back before pacing engages."
        },
        "public_join": {
          "type": "boolean",
          "default": false,
          "description": "Whether the **public, client-facing** listener also carries a node's join: registration, and the token-less renewal that follows it for the rest of the node's life."
        },
        "public_join_rate_per_ip": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint32",
          "minimum": 0,
          "default": null,
          "description": "Per-source-IP **call** rate (calls/second) for the registration forwarded off the public listener."
        },
        "public_join_burst": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint32",
          "minimum": 0,
          "default": null,
          "description": "Token-bucket burst for `public_join_rate_per_ip`: joins one address may make back to back."
        },
        "public_renewal_max_connections": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint",
          "minimum": 0,
          "default": null,
          "description": "Ceiling on concurrent node renewals relayed off the client-facing listener — the fleet's lane of the relayed branch."
        },
        "public_admin_max_connections": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint",
          "minimum": 0,
          "default": null,
          "description": "Ceiling on concurrent administrative connections relayed off the client-facing listener — the operator's lane of the same branch, told apart by the server name (`auth.gdsgate.internal` against the shared one)."
        },
        "join_max_connections": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint",
          "minimum": 0,
          "default": null,
          "description": "Ceiling on concurrent relayed joins on the join relay."
        },
        "join_accept_rate_per_ip": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint32",
          "minimum": 0,
          "default": null,
          "description": "Per-source-IP accept rate (tokens/second) on the join relay."
        },
        "join_accept_burst": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint32",
          "minimum": 0,
          "default": null,
          "description": "Token-bucket burst for `join_accept_rate_per_ip`: connections one address may open back to back."
        },
        "join_peek_timeout_secs": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0,
          "default": null,
          "description": "How long a connection to the join relay may stay silent before it is classified, in seconds."
        },
        "join_idle_timeout_secs": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0,
          "default": null,
          "description": "Idle ceiling on an established relay, in seconds."
        },
        "public_origin": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "The gateway's public browser origin (e.g. `https://gate.example.com`), the base of the `WebAuthn` step-up confirmation URL."
        },
        "web_addr": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Address the browser-facing `WebAuthn` web-origin listens on (HTTPS)."
        },
        "web_cert_file": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "PEM certificate chain for the web-origin's TLS."
        },
        "web_key_file": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "PEM private key for `web_cert_file`."
        },
        "webapps_zone": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Zone the web lane's applications are published under for a browser with nothing installed — `webapps.gate.example.com`, reached as `<application>.<zone>`."
        },
        "webapps_addr": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Address the clientless browser entry listens on (HTTPS)."
        },
        "webapps_cert_file": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "PEM certificate chain the clientless browser entry presents — a **browser-trusted wildcard for `*.<webapps_zone>`**."
        },
        "webapps_key_file": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "PEM private key for `webapps_cert_file`."
        },
        "webapps_session_ttl_secs": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0,
          "default": null,
          "description": "How long a browser session lasts, in seconds."
        },
        "webapps_proxy_protocol_from": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Addresses the clientless browser entry accepts a **PROXY protocol** header from — the front(s) it is published through."
        },
        "public_proxy_protocol_from": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Addresses the **public, client-facing gRPC listener** accepts a **PROXY protocol** header from — the front(s) it is published through."
        },
        "public_cert_file": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "PEM certificate chain the **public, client-facing gRPC listener** presents: a certificate from an authority clients already trust.",
          "x-gdsgate-profiles": [
            "pilot",
            "production"
          ]
        },
        "public_key_file": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "PEM private key for `public_cert_file`.",
          "x-gdsgate-profiles": [
            "pilot",
            "production"
          ]
        }
      },
      "description": "Proxy listener mode.",
      "additionalProperties": false
    },
    "Policy": {
      "type": "object",
      "properties": {
        "path": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path to a Cedar policy file."
        },
        "editor": {
          "$ref": "#/$defs/PolicyEditor",
          "description": "Quorum + lockout-recovery knobs for the policy editor."
        }
      },
      "description": "Authorization policy source.",
      "additionalProperties": false
    },
    "PolicyEditor": {
      "type": "object",
      "properties": {
        "min_approvers": {
          "type": "integer",
          "format": "uint32",
          "minimum": 0,
          "default": 1,
          "description": "Quorum threshold for `editPolicy` proposals."
        },
        "break_glass_policy_file": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path to a Cedar policy file that, when present on disk at Authority startup, atomically replaces the active stored policy as the new Active version (proposer `break-glass:<hostname>`) — the documented recovery from `editPolicy` lockout."
        }
      },
      "description": "Quorum + lockout-recovery configuration for `editPolicy`.",
      "additionalProperties": false
    },
    "Mcp": {
      "type": "object",
      "properties": {
        "destructive_patterns": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Glob patterns (`*delete*`, `drop_*`, `*_admin`, …) marking a tool name as destructive."
        }
      },
      "description": "MCP per-tool policy settings (`[mcp]`).",
      "additionalProperties": false
    },
    "Mfa": {
      "type": "object",
      "properties": {
        "webauthn": {
          "anyOf": [
            {
              "$ref": "#/$defs/MfaWebauthn"
            },
            {
              "type": "null"
            }
          ],
          "description": "`WebAuthn` relying-party settings."
        }
      },
      "description": "Gateway step-up MFA factor configuration (`[mfa]`).",
      "additionalProperties": false
    },
    "MfaWebauthn": {
      "type": "object",
      "properties": {
        "rp_id": {
          "type": "string",
          "description": "The relying-party id — the domain a passkey is bound to."
        },
        "origins": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Allowed browser origins (`scheme://host[:port]`)."
        },
        "rp_origin": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Legacy single-origin key (pre-multi-origin)."
        },
        "allow_localhost": {
          "type": "boolean",
          "default": false,
          "description": "Dev only: permit `http://localhost` origins."
        },
        "allow_any_port": {
          "type": "boolean",
          "default": false,
          "description": "Dev only: accept any port on the origin host (the loopback ceremony picks a fresh port per run)."
        }
      },
      "required": [
        "rp_id"
      ],
      "description": "`WebAuthn` relying-party settings (`[mfa.webauthn]`).",
      "additionalProperties": false
    },
    "Oidc": {
      "type": "object",
      "properties": {
        "issuer": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Issuer base URL, e.g. `https://idp.example/realms/gdsgate`.",
          "x-gdsgate-profiles": [
            "production"
          ]
        },
        "client_id": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "OAuth client id registered for gdsgate at the `IdP`.",
          "x-gdsgate-profiles": [
            "production"
          ]
        },
        "audience": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Expected identity-token audience (`aud`)."
        },
        "allow_insecure_http": {
          "type": "boolean",
          "default": false,
          "description": "Allow `http://` URLs for discovery / JWKS / device-code / token-exchange requests."
        },
        "jwks_refresh_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 3600,
          "description": "How often to re-fetch the `IdP`'s JWKS (seconds)."
        },
        "request_timeout_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 15,
          "description": "Per-request timeout for `IdP` HTTP calls (seconds)."
        },
        "id_token_signing_algs": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [
            "RS256",
            "RS384",
            "RS512",
            "PS256",
            "PS384",
            "PS512",
            "ES256",
            "ES384",
            "EdDSA"
          ],
          "description": "`id_token` signing-algorithm whitelist (JWS `alg`)."
        },
        "display_name_claims": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [
            "preferred_username",
            "email"
          ],
          "description": "Claims a person's display name is taken from, in order: the first one the token carries as a string wins."
        }
      },
      "description": "External OIDC identity provider.",
      "additionalProperties": false
    },
    "Identity": {
      "type": "object",
      "properties": {
        "allow_system_groups": {
          "type": "boolean",
          "default": false,
          "description": "Allow `IdP` claims and impersonation values starting with `system:` (or matching the bare `kubernetes-admin` / `cluster-admin` literals)."
        },
        "max_length": {
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 253,
          "description": "Maximum length (bytes) of a sanitised value (`sub` or one group)."
        },
        "max_groups": {
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 64,
          "description": "Maximum count of group memberships per identity."
        }
      },
      "description": "Identity claim-sanitisation policy.",
      "additionalProperties": false
    },
    "Workload": {
      "type": "object",
      "properties": {
        "trust_domain": {
          "type": "string",
          "default": "",
          "description": "SPIFFE trust domain of this cluster (lowercase `[a-z0-9._-]`)."
        },
        "cert_ttl_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 900,
          "description": "Validity of issued workload certificates (seconds)."
        },
        "issuers": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/WorkloadIssuer"
          },
          "description": "Trusted workload issuers (`[[workload.issuers]]`) — platform token issuers such as a GitLab instance or a Kubernetes cluster, kept separate from the human `[oidc]` `IdP`."
        }
      },
      "description": "Workload identity establishment: which platform issuers may bootstrap a machine/AI-agent identity and how their token claims are templated into SPIFFE IDs.",
      "additionalProperties": false
    },
    "WorkloadIssuer": {
      "type": "object",
      "properties": {
        "slug": {
          "type": "string",
          "description": "Short unique slug (`[A-Za-z0-9._-]`)."
        },
        "issuer": {
          "type": "string",
          "description": "Issuer URL — the `iss` claim of this platform's tokens."
        },
        "audience": {
          "type": "string",
          "description": "Expected token audience (`aud`) — the gateway's own origin, e.g. `https://gdsgate.corp`."
        },
        "path_template": {
          "type": "string",
          "default": "",
          "description": "SPIFFE path template rendered from token claims, e.g. `project/{project_path}/ref/{ref}`."
        },
        "groups": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Cedar groups granted to this issuer's workloads (`Connector in Group::\"…\"`)."
        },
        "owner_claim": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Claim naming the human the workload acts for (e.g. GitLab `user_login`); when the proof carries it, the workload's owner is `User::\"<value>\"`."
        },
        "owner_service": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Static service-account owner used when `owner_claim` is unset or the claim is absent from the proof; the owner becomes `Service::\"<value>\"`."
        },
        "single_use_jti": {
          "type": "boolean",
          "default": true,
          "description": "Refuse a second exchange of the same proof token (`jti` single-use)."
        }
      },
      "required": [
        "slug",
        "issuer",
        "audience"
      ],
      "description": "One trusted workload issuer (a `[[workload.issuers]]` table).",
      "additionalProperties": false
    },
    "CaRotation": {
      "type": "object",
      "properties": {
        "enabled": {
          "type": "boolean",
          "default": false,
          "description": "Master switch for automatic rotation."
        },
        "interval_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 2592000,
          "description": "Rotate on this cadence (seconds)."
        },
        "proactive_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 604800,
          "description": "Also rotate when the active generation has fewer than this many seconds of validity left."
        },
        "propagation_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 300,
          "description": "Wait this long after publishing the candidate — letting verifiers refresh their trust bundle — before promoting it to the signing CA (seconds)."
        },
        "retire_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 3600,
          "description": "Wait this long after promoting the new signer before retiring the old CA (seconds)."
        },
        "check_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 3600,
          "description": "How often the controller evaluates whether a rotation is due (seconds)."
        }
      },
      "description": "Automatic User SSH CA rotation, driven by Authority.",
      "additionalProperties": false
    },
    "Ha": {
      "type": "object",
      "properties": {
        "enabled": {
          "type": "boolean",
          "default": false,
          "description": "Master switch."
        },
        "owner": {
          "type": "string",
          "default": "",
          "description": "This instance's lease owner id."
        },
        "lease_ttl_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 15,
          "description": "Lease validity (seconds): a follower may take over this long after the leader last renewed."
        },
        "renew_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 5,
          "description": "How often the leader renews (and a follower retries acquiring), seconds."
        },
        "authority_peers": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "default": {},
          "description": "Individual Authority endpoints indexed by stable lease owner."
        },
        "keyring_sync": {
          "$ref": "#/$defs/KeyringSync",
          "description": "Built-in encrypted keyring distribution and first-boot bootstrap."
        },
        "max_cluster_sessions": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 1024,
          "description": "Cluster-wide concurrent session ceiling."
        }
      },
      "description": "High-availability: run several Authority instances against one shared store and elect a single **audit write-leader** via a DB lease.",
      "additionalProperties": false
    },
    "KeyringSync": {
      "type": "object",
      "properties": {
        "enabled": {
          "type": "boolean",
          "default": false,
          "description": "Enables the canonical encrypted snapshot and live reload."
        },
        "initialize": {
          "type": "boolean",
          "default": false,
          "description": "Explicitly initializes an empty cluster from this node's existing rings."
        },
        "state_dir": {
          "type": "string",
          "default": "/var/lib/gdsgate/authority/keyring-sync",
          "description": "Protected directory for the root credential and revision watermark."
        },
        "bootstrap_endpoint": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Trusted registration listener used only when this Authority has no root."
        },
        "bootstrap_fingerprint": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Pinned registration CA fingerprint for first boot."
        },
        "bootstrap_token": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "One-time owner-bound grant, supplied through a secret reference."
        },
        "generation_kms_key": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Declared KMS key used to generate rotation material; required by production."
        },
        "root_kms_key": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Declared wrapping provider for the protected distribution root file."
        },
        "poll_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 5,
          "description": "How frequently the canonical snapshot is checked."
        }
      },
      "description": "Automatic integrity material delivery for Authority replicas.",
      "additionalProperties": false
    },
    "Approvals": {
      "type": "object",
      "properties": {
        "min_approvers": {
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 1,
          "description": "Global default number of distinct approvers required."
        },
        "per_environment": {
          "type": "object",
          "additionalProperties": {
            "type": "integer",
            "format": "uint",
            "minimum": 0
          },
          "default": {},
          "description": "Per-environment overrides (e.g. `prod = 2`), keyed by environment name."
        }
      },
      "description": "JIT access-request approval thresholds.",
      "additionalProperties": false
    },
    "Discovery": {
      "type": "object",
      "properties": {
        "resources": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/DiscoveryResource"
          },
          "description": "Declared resources (the catalog)."
        },
        "import_rules": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ImportRule"
          },
          "description": "Label rules applied to declared resources whose id matches a glob, in order (later rules override `environment`; labels merge, later wins)."
        },
        "auto_scopes": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/AutoScope"
          },
          "description": "Boundaries inside which a named connector writes catalog rows itself, each row holding a lease it has to renew."
        },
        "lease_sweep_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 60,
          "description": "How often Authority drops leased rows whose leases have run out (seconds)."
        }
      },
      "description": "Resource catalog declaration + label import-rules.",
      "additionalProperties": false
    },
    "DiscoveryResource": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "description": "Resource id (routing key / certificate scope)."
        },
        "kind": {
          "type": "string",
          "description": "Resource kind: `ssh`, `tcp`, `postgres`, `mysql`, `cockroach` (`cockroachdb` accepted for it), `kubernetes` (`k8s` accepted for it), `rdp`, `mcp`, `llm`, `web`, `web-egress`."
        },
        "project": {
          "type": "string",
          "default": "default",
          "description": "Owning project."
        },
        "min_approvers": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint",
          "minimum": 0,
          "default": null,
          "description": "Resource-local JIT approval threshold."
        },
        "hostname": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Name clients may address this resource by, published to them in the catalog listing."
        },
        "aliases": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Further names for the same resource, same rules as `hostname`."
        },
        "native_name": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "The domain the application itself answers on (`app.example.com`): at least two labels, outside the client's own zone."
        },
        "port": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint16",
          "minimum": 0,
          "maximum": 65535,
          "default": null,
          "description": "Port a native client connects to on the resource's own address."
        },
        "pin_tool_descriptors": {
          "type": "boolean",
          "default": false,
          "description": "Whether this MCP server's tool descriptors are pinned: the first descriptor seen for a tool becomes its baseline, and a `tools/call` on a tool whose descriptor has changed since is refused until the change is re-approved."
        },
        "ssh_profile": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "What a session on this ssh resource may run: `general` or `git`."
        },
        "web_profile": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "What this web resource serves: `general` or `git`."
        },
        "onward_auth": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "How a session on this ssh resource authenticates onward: `local`, `certificate` or `client_key`."
        }
      },
      "required": [
        "id",
        "kind"
      ],
      "description": "A declared catalog resource.",
      "additionalProperties": false
    },
    "ImportRule": {
      "type": "object",
      "properties": {
        "match": {
          "type": "string",
          "description": "Glob over resource id (`*` matches any run of characters)."
        },
        "environment": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Environment to set on a match (overrides earlier matches)."
        },
        "labels": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "default": {},
          "description": "Labels to merge on a match (later match wins per-key)."
        }
      },
      "required": [
        "match"
      ],
      "description": "A label import-rule: applies `environment`/`labels` to resources whose id matches `match` (a glob with `*` wildcards), e.g. `*_prod` → prod.",
      "additionalProperties": false
    },
    "AutoScope": {
      "type": "object",
      "properties": {
        "id_prefix": {
          "type": "string",
          "description": "Prefix every id written inside this boundary starts with."
        },
        "node": {
          "type": "string",
          "description": "Enrolled node id of the connector allowed to publish here."
        },
        "kinds": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Kinds a target inside this boundary may be published as."
        },
        "project": {
          "type": "string",
          "default": "default",
          "description": "Owning project for every row written here."
        },
        "environment": {
          "type": "string",
          "description": "Deployment environment stamped on every row written here."
        },
        "labels": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "default": {},
          "description": "Labels stamped on every row written here, over whatever the source claimed for the same key."
        },
        "accept_label_keys": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Label keys accepted from the source."
        },
        "max_live": {
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "description": "Ceiling on live rows in this boundary."
        },
        "lease_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "description": "How long a row lives after the snapshot that carried it."
        },
        "fallback": {
          "$ref": "#/$defs/ScopeFallback",
          "default": "parent",
          "description": "What the absence of a row means inside this boundary."
        },
        "ssh_host_key": {
          "$ref": "#/$defs/ScopeSshHostKey",
          "default": "annotation",
          "description": "Where the host key of an `ssh` target published here comes from."
        },
        "onward_auth": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Onward modes an `ssh` target published here may name: `local`, `certificate`, `client_key` (`ONWARD_AUTH_MODES`)."
        },
        "enabled": {
          "type": "boolean",
          "default": true,
          "description": "Whether the boundary admits publishes at all."
        }
      },
      "required": [
        "id_prefix",
        "node",
        "kinds",
        "environment",
        "max_live",
        "lease_secs"
      ],
      "description": "A boundary a person declares once, inside which a named connector writes catalog rows on its own.",
      "additionalProperties": false
    },
    "ScopeFallback": {
      "oneOf": [
        {
          "type": "string",
          "const": "parent",
          "description": "Whatever decided before the boundary existed decides still — for a database sub-resource, its host."
        },
        {
          "type": "string",
          "const": "deny",
          "description": "The boundary is the only source of truth: a target it holds no row for is not reachable."
        }
      ],
      "description": "What it means that a boundary holds no row for a target."
    },
    "ScopeSshHostKey": {
      "oneOf": [
        {
          "type": "string",
          "const": "annotation",
          "description": "The source states the fingerprint (a `gdsgate.io/ssh-host-key` annotation on the object)."
        },
        {
          "type": "string",
          "const": "tofu",
          "description": "The fingerprint is learned on first contact and holds for the lease."
        }
      ],
      "description": "Where the host key of an `ssh` target published into a boundary comes from."
    },
    "Connector": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "default": "local",
          "description": "Identifier this connector registers under at the proxy."
        },
        "proxy_connection_count": {
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 1,
          "description": "Desired distinct Proxy nodes behind the tunnel address, in `1..=16`."
        },
        "backends": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/BackendConfig"
          },
          "description": "Resources this connector serves."
        },
        "discovery_sources": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/DiscoverySourceConfig"
          },
          "description": "Discovery-only sources."
        },
        "authority_transport": {
          "$ref": "#/$defs/AuthorityTransport",
          "default": "direct",
          "description": "Route the connector's Authority control-plane RPC take."
        },
        "git": {
          "$ref": "#/$defs/GitPrograms",
          "description": "Absolute paths to the git programs this node runs on behalf of a session."
        }
      },
      "description": "Connector settings: the identity it registers under and the resources it serves.",
      "additionalProperties": false
    },
    "BackendConfig": {
      "type": "object",
      "properties": {
        "resource": {
          "type": "string",
          "description": "Logical resource id clients request and the proxy routes on."
        },
        "kind": {
          "$ref": "#/$defs/BackendKind",
          "description": "Wire protocol the backend speaks."
        },
        "addr": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Local backend `host:port`."
        },
        "url": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "The endpoint URL of what this backend talks to — a remote MCP server, or the upstream of an HTTP(S) application."
        },
        "allow": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "The host names a `kind = \"web-egress\"` backend may reach, and nothing else: required, and refused empty."
        },
        "routed_ranges": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Non-public address ranges a `kind = \"web-egress\"` backend may dial, as `address/prefix`."
        },
        "inspect": {
          "type": "boolean",
          "default": false,
          "description": "Whether a `kind = \"web-egress\"` backend ends TLS and decides each request."
        },
        "forwarded_headers": {
          "type": "boolean",
          "default": false,
          "description": "Whether a `kind = \"web\"` application receives `X-Forwarded-*` headers."
        },
        "allow_encoded_separator": {
          "type": "boolean",
          "default": false,
          "description": "Whether a path segment of a `kind = \"web\"` request may percent-encode a `/`."
        },
        "websocket": {
          "type": "boolean",
          "default": false,
          "description": "Whether a `kind = \"web\"` application may have a WebSocket channel opened through it."
        },
        "routes": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/WebRoute"
          },
          "description": "The named path families of a `kind = \"web\"` application (`[[connector.backends.routes]]`)."
        },
        "max_request_bytes": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 0,
          "description": "The largest request body a `kind = \"web\"` or `\"web-egress\"` backend carries, in bytes."
        },
        "audit": {
          "anyOf": [
            {
              "$ref": "#/$defs/WebAudit"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "How much of a web backend's traffic reaches the audit chain request by request: `sampled` or `full`."
        },
        "identity": {
          "$ref": "#/$defs/WebIdentity",
          "default": "none",
          "description": "What a `kind = \"web\"` application is told about who is calling: `none`, `signed` or `headers`."
        },
        "identity_headers_trust_the_network": {
          "type": "boolean",
          "default": false,
          "description": "`true` states that this application is reachable only through this gateway; required for `identity = \"headers\"`."
        },
        "decision_cache_ttl_secs": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0,
          "default": null,
          "description": "How long a **permit** on a `kind = \"web\"` backend is reused before the gate is asked again, in seconds."
        },
        "command": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "The MCP server to run as a child process, argv-style: the program by absolute path, then its arguments."
        },
        "command_env": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "default": {},
          "description": "Environment variables a `command` server is given, on top of the small set every process needs."
        },
        "allowed_tools": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Tool allowlist enforced on MCP `tools/call`."
        },
        "enforce_tool_policy": {
          "type": "boolean",
          "default": false,
          "description": "Opt-in per-tool-call Cedar authorization for an MCP backend."
        },
        "allowed_input_requests": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Server-initiated asks this MCP backend may make of the client: `sampling/createMessage`, `elicitation/create`, `roots/list`."
        },
        "allow_elicitation_url": {
          "type": "boolean",
          "default": false,
          "description": "Whether a permitted `elicitation/create` may use `mode = \"url\"`, which renders a link the *server* chose in front of the person."
        },
        "pin_tool_descriptors": {
          "type": "boolean",
          "default": false,
          "description": "Moved: set to `true`, the connector refuses to start; set `pin_tool_descriptors` on the `[[discovery.resources]]` row or with `gdsgate authority set-resource --pin-tool-descriptors`."
        },
        "refuse_unfiltered_tool_listing": {
          "type": "boolean",
          "default": false,
          "description": "What to do with a `tools/list` result whose per-caller visibility decision (Cedar `viewTools`) could not be obtained — Authority unreachable, or answering with an error."
        },
        "decider_url": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "An external decider asked, synchronously, before anything on a data path (`tools/call`, `resources/read`, `prompts/get`) reaches this backend — as one `POST` per call to this URL."
        },
        "decider_command": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "The same decider as a program this connector runs, argv-style: the program by absolute path, then its arguments."
        },
        "decider_command_env": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "default": {},
          "description": "Environment variables a `decider_command` is given, on top of the small set every process needs."
        },
        "decider_ca_path": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "PEM CA bundle verifying an `https` `decider_url`."
        },
        "decider_timeout_ms": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0,
          "default": null,
          "description": "How long a caller's call is held while the decider thinks, in milliseconds."
        },
        "decider_fail_closed": {
          "type": [
            "boolean",
            "null"
          ],
          "default": null,
          "description": "What a decider that did not answer costs."
        },
        "cage": {
          "anyOf": [
            {
              "$ref": "#/$defs/CageConfig"
            },
            {
              "type": "null"
            }
          ],
          "description": "The cage the programs this backend starts on this node run inside."
        },
        "session": {
          "anyOf": [
            {
              "$ref": "#/$defs/SessionFrameConfig"
            },
            {
              "type": "null"
            }
          ],
          "description": "The frame a session of this backend runs inside on this node, and what is written into it."
        },
        "api_url": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Cluster API base URL (e.g. `https://k8s:6443`)."
        },
        "ca_path": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path to the PEM CA bundle verifying the upstream's serving certificate."
        },
        "token_path": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path to the gateway service-account bearer token (the impersonator)."
        },
        "login_user": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Login user on the downstream host for a jump-host (model B) `ssh` backend — the principal the onward certificate is minted for."
        },
        "login_users": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "The logins a model A backend in `host_user` will serve sessions under, when there is more than one."
        },
        "login_mode": {
          "$ref": "#/$defs/LoginMode",
          "default": "connector",
          "description": "Whose account a model A session runs as on this node."
        },
        "shell": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "The shell a model A session's `shell` and `exec` run under, as an absolute path."
        },
        "ssh_profile": {
          "$ref": "#/$defs/SshProfileConfig",
          "default": "general",
          "description": "What this node lets a session on this backend run: `general` or `git`."
        },
        "audit_command": {
          "$ref": "#/$defs/CommandAudit",
          "default": "off",
          "description": "Whether the `exec` request itself is recorded, and how."
        },
        "onward_auth": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "How this node expects a session on this backend to authenticate onward: `local`, `certificate` or `client_key`."
        },
        "repository_root": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Directory the repositories this backend serves live under."
        },
        "host_key_fingerprints": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Pinned downstream `sshd` host-key fingerprints (`SHA256:<base64>` strings, the form `ssh-keyscan` prints) for jump-host (model B) backends."
        },
        "host_key_fingerprints_file": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path to a file holding one `SHA256:<base64>` fingerprint per line, appended to `host_key_fingerprints` at startup."
        },
        "allow_unpinned_upstream": {
          "type": "boolean",
          "default": false,
          "description": "Opts a backend into the legacy TOFU branch when the fingerprints it would be checked against resolve to an empty list — both `host_key_fingerprints` and `host_key_fingerprints_file` on an SSH jump host, both `host_cert_fingerprints` and `host_cert_fingerprints_file` on a terminating desktop."
        },
        "host_cert_fingerprints": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Pinned certificate fingerprints of the Windows host a terminating `kind = \"rdp\"` backend logs in to (`sha256:<hex>`, the form `gdsgate ca learn-host-cert` prints)."
        },
        "host_cert_fingerprints_file": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path to a file holding one `sha256:<hex>` fingerprint per line, appended to `host_cert_fingerprints` at startup."
        },
        "agent_identities_max": {
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 5,
          "description": "How many of the identities a forwarded agent names this node offers to the host beyond a jump."
        },
        "agent_auth_attempts_max": {
          "type": "integer",
          "format": "uint",
          "minimum": 0,
          "default": 5,
          "description": "How many signatures one authentication to the host beyond may cost, whatever the identity list holds."
        },
        "allow_port_forward": {
          "type": "boolean",
          "default": false,
          "description": "Opt-in escape hatch for `kubectl port-forward` on this Kubernetes backend."
        },
        "allow_local_forward": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Allow-list of `host:port`/`host:lo-hi`/`*:port` patterns the connector will let `ssh -L` (`channel_open_direct_tcpip`) hit on this SSH backend."
        },
        "allow_remote_forward": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Allow-list of `bind:port`/`bind:lo-hi` patterns the connector will let `ssh -R` bind a listener on."
        },
        "allow_agent_forward": {
          "type": "boolean",
          "default": false,
          "description": "Opt-in escape hatch for `ssh -A` on this SSH backend."
        },
        "admin": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Admin credential for this resource (one per resource)."
        },
        "db_roles": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/DbRoleProfile"
          },
          "description": "Declared session-role profiles: each maps a **logical** role name — the one Cedar authorizes via `context.db_role` — to a real, pre-created database user/role."
        },
        "auth_mode": {
          "$ref": "#/$defs/DbAuthMode",
          "default": "passthrough",
          "description": "DB authentication mode: `passthrough` or `session_role`."
        },
        "enforce_query_categories": {
          "type": "boolean",
          "default": false,
          "description": "Opt-in per-query category enforcement for a **passthrough** Postgres backend."
        },
        "statement_timeout_ms": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0,
          "default": null,
          "description": "Optional server-side `statement_timeout` in **milliseconds**, set by the connector on the backend session in `session_role` mode."
        },
        "settable_parameters": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Extra `PostgreSQL` session parameters a client may `SET` in a `session_role` session, on top of the built-in list of driver parameters (`client_encoding`, `search_path`, `TimeZone`, …)."
        },
        "allow_fastpath_function": {
          "type": "boolean",
          "default": false,
          "description": "Allow the Postgres fast-path `FunctionCall` (`F`) message in a **restricted** session (`session_role`, or passthrough with `enforce_query_categories`)."
        },
        "service_account": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Service-account connection string (no password) used in `session_role` mode, e.g. `postgres://gdsgate_sa@pg-prod/analytics`."
        },
        "service_account_password_file": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path to a file holding the service-account password (vault/secrets manager mount)."
        },
        "service_account_tls_ca_file": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path to a PEM CA bundle used to verify the backend's TLS certificate when the `service_account` DSN sets `sslmode=verify-full` (e.g. the RDS / `CloudSQL` root bundle)."
        },
        "discovery": {
          "anyOf": [
            {
              "$ref": "#/$defs/DiscoveryProbe"
            },
            {
              "type": "null"
            }
          ],
          "description": "Live discovery probe: when set, the connector periodically enumerates this backend's sub-resources (e.g. database names) under a **read-only** account and publishes the inventory to Authority."
        },
        "allowed_backend_hosts": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Allow-list of `host:port` / `host:lo-hi` / `*:port` / `CIDR:port` patterns the backend's dialled address must match, for a `tcp`, `postgres`, `mysql`, `mcp` or `llm` backend (same grammar as `allow_local_forward`)."
        },
        "record": {
          "$ref": "#/$defs/RecordPolicy",
          "default": "best_effort",
          "description": "What happens on this backend when a session cannot be recorded."
        },
        "graphics": {
          "$ref": "#/$defs/GraphicsMode",
          "default": "redraw",
          "description": "How a terminating desktop gets the host's picture to the caller."
        },
        "clipboard": {
          "$ref": "#/$defs/ClipboardPolicy",
          "default": "both",
          "description": "Which way copy and paste may travel on a `kind = \"rdp\"` backend."
        },
        "audio": {
          "type": "boolean",
          "default": true,
          "description": "Whether the desktop's sound reaches the caller, on a `kind = \"rdp\"` backend."
        },
        "drives": {
          "type": "boolean",
          "default": false,
          "description": "Whether the caller's own disks appear in the desktop, on a `kind = \"rdp\"` backend."
        },
        "printers": {
          "type": "boolean",
          "default": false,
          "description": "Whether the caller's printers appear in the desktop, on a `kind = \"rdp\"` backend."
        },
        "ports": {
          "type": "boolean",
          "default": false,
          "description": "Whether the caller's serial and parallel ports appear in the desktop, on a `kind = \"rdp\"` backend."
        },
        "smart_cards": {
          "type": "boolean",
          "default": false,
          "description": "Whether the caller's smart card readers appear in the desktop, on a `kind = \"rdp\"` backend."
        },
        "clipboard_files": {
          "$ref": "#/$defs/ClipboardPolicy",
          "default": "off",
          "description": "Which way the clipboard may carry files, on a `kind = \"rdp\"` backend."
        },
        "record_max_bytes": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 4294967296,
          "description": "The most one session's recording may hold, in bytes."
        },
        "windows_user": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "The Windows account a desktop session logs in as (`kind = \"rdp\"`)."
        },
        "windows_users": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/WindowsAccount"
          },
          "default": [],
          "description": "The Windows accounts this desktop offers, when it offers more than one (`[[connector.backends.windows_users]]`)."
        },
        "credential": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "An inline provider credential."
        },
        "credential_file": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path to a file holding the credential this backend presents to whatever it talks to."
        },
        "credential_header": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Header the credential is presented in."
        },
        "credential_format": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Template for the credential's header value, carrying the placeholder `{credential}` exactly once."
        },
        "allowed_request_headers": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Request headers a caller may send that this backend passes on **in substitution mode**, on top of the content-negotiation defaults (`accept`, `accept-encoding`, `content-type`)."
        },
        "allowed_query_params": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Query parameters a caller may send **in substitution mode**."
        },
        "allowed_models": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Models this `kind = \"llm\"` backend serves; applied in addition to the Cedar decision."
        },
        "record_request": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "How much of what a caller **sends** to a `kind = \"llm\"` backend is written into the session recording: `off`, `digest`, `redacted` or `full`."
        },
        "record_response": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "How much of what a `kind = \"llm\"` backend **answers** with is written into the session recording."
        }
      },
      "required": [
        "resource",
        "kind"
      ],
      "description": "One resource a connector serves, from a `[[connector.backends]]` table.",
      "additionalProperties": false
    },
    "BackendKind": {
      "oneOf": [
        {
          "type": "string",
          "const": "ssh",
          "description": "SSH session, terminated and recorded by the connector (needs no `addr`)."
        },
        {
          "type": "string",
          "const": "tcp",
          "description": "Raw TCP byte forward to `addr`."
        },
        {
          "type": "string",
          "const": "postgres",
          "description": "`PostgreSQL` wire stream forwarded to `addr` with a query-log tap."
        },
        {
          "type": "string",
          "const": "mysql",
          "description": "`MySQL` wire stream forwarded to `addr` with a query-log tap."
        },
        {
          "type": "string",
          "const": "cockroach",
          "description": "`CockroachDB`, which speaks the `PostgreSQL` wire protocol: the same relay, tap, session-role impersonation and per-statement gate as `postgres`, on its own well-known port."
        },
        {
          "type": "string",
          "const": "mcp",
          "description": "MCP (`JSON-RPC`) stream forwarded to `addr` with tool-call enforcement."
        },
        {
          "type": "string",
          "const": "kubernetes",
          "description": "Kubernetes API, reverse-proxied with identity impersonation (needs `api_url`, `ca_path` and `token_path`; no `addr`)."
        },
        {
          "type": "string",
          "const": "llm",
          "description": "A model service, reverse-proxied with a policy decision on every call."
        },
        {
          "type": "string",
          "const": "web",
          "description": "An HTTP(S) application, reverse-proxied to the one upstream `url` names."
        },
        {
          "type": "string",
          "const": "web-egress",
          "description": "The way out of the protected zone: a forward proxy whose target the request names itself, admitted only against `allow`."
        },
        {
          "type": "string",
          "const": "rdp",
          "description": "A Windows host reached over RDP, forwarded to `addr` as a stream."
        }
      ],
      "description": "Wire protocol a connector backend speaks."
    },
    "WebRoute": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "description": "The name policy sees (`context.route`)."
        },
        "match": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "The path patterns this route claims, `*` matching any run of characters."
        },
        "audit": {
          "anyOf": [
            {
              "$ref": "#/$defs/WebAudit"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "How much of this route reaches the audit chain; overrides the backend's own `audit`."
        }
      },
      "required": [
        "name",
        "match"
      ],
      "description": "A named family of paths inside a `kind = \"web\"` application: one `[[connector.backends.routes]]` table.",
      "additionalProperties": false
    },
    "WebAudit": {
      "oneOf": [
        {
          "type": "string",
          "const": "sampled",
          "description": "Successful `GET`s are folded into the session's close row; everything else is written in its own right."
        },
        {
          "type": "string",
          "const": "full",
          "description": "Every request gets a row."
        }
      ],
      "description": "How much of a web backend's traffic is written to the audit chain request by request: `sampled` or `full`."
    },
    "WebIdentity": {
      "oneOf": [
        {
          "type": "string",
          "const": "none",
          "description": "Nothing at all."
        },
        {
          "type": "string",
          "const": "signed",
          "description": "A short-lived assertion signed by Authority, naming the caller, their groups and the one resource it is good at."
        },
        {
          "type": "string",
          "const": "headers",
          "description": "`X-Remote-User` and `X-Remote-Groups` headers, unsigned."
        }
      ],
      "description": "What a `kind = \"web\"` application is told about who is calling: `none`, `signed` or `headers`."
    },
    "CageConfig": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "private_network": {
          "type": "boolean",
          "default": false,
          "description": "An empty network namespace for the program: no interfaces, no route, no DNS."
        },
        "protect_home": {
          "type": "boolean",
          "default": true,
          "description": "Keep the connector user's home directory out of the cage; the program gets a private one."
        },
        "private_tmp": {
          "type": "boolean",
          "default": true,
          "description": "Give the program a private temporary directory, hiding the host's `/tmp`."
        },
        "read_only_paths": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Extra paths the program may read and execute."
        },
        "read_write_paths": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Extra paths the program may read, write and execute."
        },
        "restrict_address_families": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "The socket address families the program may still create a socket in."
        },
        "memory_max": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "The memory ceiling for the program and everything it starts, as a byte count with an optional `K`/`M`/`G` suffix (`\"512M\"`)."
        },
        "tasks_max": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0,
          "default": null,
          "description": "How many processes the program and its descendants may hold at once."
        },
        "cpu_quota": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "The CPU ceiling as a percentage of one core (`\"100%\"` is one core, `\"400%\"` is four)."
        },
        "report_denied_paths": {
          "type": "boolean",
          "default": false,
          "description": "Report every path the program opens that this cage does not allow."
        },
        "allow_degraded": {
          "type": "boolean",
          "default": false,
          "description": "Run even when this host cannot deliver something this table asks for."
        }
      },
      "description": "The cage a backend's own programs run inside on the connector's node."
    },
    "SessionFrameConfig": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "memory_max": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "The memory ceiling for the session and everything it starts, as a byte count with an optional `K`/`M`/`G` suffix (`\"2G\"`)."
        },
        "tasks_max": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0,
          "default": null,
          "description": "How many processes the session may hold at once."
        },
        "cpu_quota": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "The CPU ceiling as a percentage of one core (`\"100%\"` is one core, `\"200%\"` is two)."
        },
        "kill_on_close": {
          "type": [
            "boolean",
            "null"
          ],
          "default": null,
          "description": "Empty the frame when the session closes: everything the session started and left running is killed, and nothing of it stays on the node."
        }
      },
      "description": "The frame a model A SSH session's processes are held in on this node."
    },
    "LoginMode": {
      "oneOf": [
        {
          "type": "string",
          "const": "connector",
          "description": "The account the connector itself runs as."
        },
        {
          "type": "string",
          "const": "host_user",
          "description": "An account the host already knows, named by `login_user`."
        }
      ],
      "description": "Whose account a model A session runs as on the connector's own host."
    },
    "SshProfileConfig": {
      "oneOf": [
        {
          "type": "string",
          "const": "general",
          "description": "Anything the policy allows, run through the login the node gives it."
        },
        {
          "type": "string",
          "const": "git",
          "description": "The recognised git commands, run directly without a login shell."
        }
      ],
      "description": "What a node lets a session on one backend run."
    },
    "CommandAudit": {
      "oneOf": [
        {
          "type": "string",
          "const": "off",
          "description": "The request string is not recorded."
        },
        {
          "type": "string",
          "const": "text",
          "description": "The request string is recorded, capped in length and encoded structurally."
        },
        {
          "type": "string",
          "const": "fingerprint",
          "description": "Only a fingerprint of the request string is recorded."
        }
      ],
      "description": "Whether an `exec` request is written to the chain, and in what form."
    },
    "DbRoleProfile": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "description": "Logical role name Cedar authorizes (`context.db_role`), e.g. `readonly`."
        },
        "db_user": {
          "type": "string",
          "description": "Real, pre-created database user/role the connector connects as for this profile, e.g. `ro_login`."
        },
        "read_only": {
          "type": "boolean",
          "default": false,
          "description": "Declares that `db_user` is a **reading** role: it is not supposed to hold `INSERT`/`UPDATE`/`DELETE`/`TRUNCATE` on anything in the database."
        }
      },
      "required": [
        "name",
        "db_user"
      ],
      "description": "A session-role profile on a database backend: a logical role name authorized by policy, bound to a concrete pre-created DB user.",
      "additionalProperties": false
    },
    "DbAuthMode": {
      "oneOf": [
        {
          "type": "string",
          "const": "passthrough",
          "description": "Client brings its own DB credentials; the connector byte-relays and taps queries for audit."
        },
        {
          "type": "string",
          "const": "session_role",
          "description": "The connector connects as the service account and `SET ROLE`s to the policy-chosen logical role."
        }
      ],
      "description": "Database authentication mode for a backend."
    },
    "DiscoveryProbe": {
      "type": "object",
      "properties": {
        "mode": {
          "type": "string",
          "description": "What to enumerate: `list_databases` (Postgres) or `list_tools` (MCP — the connector sends `tools/list` to the backend and publishes the names)."
        },
        "connection": {
          "type": "string",
          "default": "",
          "description": "Read-only connection string (user + database) for the discovery account, e.g. `postgres://disc_ro@host/postgres`."
        },
        "password_file": {
          "type": "string",
          "default": "",
          "description": "Path to a file holding the discovery account's password."
        },
        "interval_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 300,
          "description": "Probe interval in seconds."
        },
        "allowlist": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Glob allow-list (`app_*`, `analytics`) applied connector-side before publishing."
        },
        "denylist": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Glob deny-list applied after `allowlist`."
        },
        "freshness_secs": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0,
          "default": null,
          "description": "Inventory validity window in seconds."
        },
        "label_selector": {
          "type": "string",
          "default": "",
          "description": "Label selector the cluster filters on, for a `list_kube_targets` probe (`gdsgate.io/expose=true`)."
        },
        "sources": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Which kinds of cluster object a `list_kube_targets` probe enumerates: `service`, `pod`, `node`."
        },
        "scope": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Boundary this probe publishes its findings into, as a catalog row per target, on top of the observational inventory it always publishes."
        }
      },
      "required": [
        "mode"
      ],
      "description": "Live discovery probe config for a backend.",
      "additionalProperties": false
    },
    "RecordPolicy": {
      "oneOf": [
        {
          "type": "string",
          "const": "off",
          "description": "Do not record this backend at all."
        },
        {
          "type": "string",
          "const": "best_effort",
          "description": "Record, and carry on if the recording cannot be made or kept."
        },
        {
          "type": "string",
          "const": "required",
          "description": "Record, and end the session when the recording cannot be made or kept."
        }
      ],
      "description": "What a backend does when its session cannot be recorded."
    },
    "GraphicsMode": {
      "oneOf": [
        {
          "type": "string",
          "const": "redraw",
          "description": "Decode what the host sent and draw it again for the client, with whatever codec the two of them agreed on."
        },
        {
          "type": "string",
          "const": "passthrough",
          "description": "Carry the Windows graphics pipeline (MS-RDPEGFX, on a dynamic channel) to the caller unread, with no decoding or re-encoding in between."
        }
      ],
      "description": "How a terminating desktop's picture reaches the caller."
    },
    "ClipboardPolicy": {
      "oneOf": [
        {
          "type": "string",
          "const": "off",
          "description": "No clipboard."
        },
        {
          "type": "string",
          "const": "in",
          "description": "Into the desktop only: the caller may paste, the desktop may not copy out."
        },
        {
          "type": "string",
          "const": "out",
          "description": "Out of the desktop only: the caller may copy from it, and may not paste into it."
        },
        {
          "type": "string",
          "const": "both",
          "description": "Both ways."
        }
      ],
      "description": "Which way copy and paste may travel on a desktop."
    },
    "WindowsAccount": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "account": {
          "type": "string",
          "description": "The account, as Windows spells it: `DOMAIN\\\\name` for a domain account, a bare name for one local to the host."
        },
        "credential_file": {
          "type": "string",
          "description": "Path to the file holding this account's password, or a `${env:…}`, `${file:…}` or `${exec:…}` reference."
        }
      },
      "required": [
        "account",
        "credential_file"
      ],
      "description": "One Windows account a desktop backend offers — one `[[connector.backends.windows_users]]` table."
    },
    "DiscoverySourceConfig": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "id": {
          "type": "string",
          "description": "Stable local source name used for target sets and snapshot generations."
        },
        "kind": {
          "$ref": "#/$defs/DiscoverySourceKind",
          "description": "Protocol used to enumerate targets."
        },
        "api_url": {
          "type": "string",
          "description": "Kubernetes API server base URL."
        },
        "ca_path": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Public CA bundle verifying the API server; absent uses system roots."
        },
        "token_path": {
          "type": "string",
          "description": "Projected service-account token file or secret reference."
        },
        "discovery": {
          "$ref": "#/$defs/DiscoveryProbe",
          "description": "Target selector, catalog scope and polling interval."
        }
      },
      "required": [
        "id",
        "kind",
        "api_url",
        "token_path",
        "discovery"
      ],
      "description": "Discovery-only cluster connection, separate from routed backends."
    },
    "DiscoverySourceKind": {
      "oneOf": [
        {
          "type": "string",
          "const": "kubernetes",
          "description": "Enumerate targets using the Kubernetes API; the API is not a routed resource."
        }
      ],
      "description": "Protocol supported by a discovery-only source."
    },
    "AuthorityTransport": {
      "oneOf": [
        {
          "type": "string",
          "const": "direct",
          "description": "Connector dials Authority directly — two outbound channels (Proxy and Authority)."
        },
        {
          "type": "string",
          "const": "fronted",
          "description": "Connector dials Authority through a shared network front (one egress address)."
        },
        {
          "type": "string",
          "const": "tunneled",
          "description": "Connector reaches Authority only through the reverse tunnel to the Proxy."
        }
      ],
      "description": "How the connector's control-plane RPC reach Authority."
    },
    "GitPrograms": {
      "type": "object",
      "properties": {
        "git_upload_pack": {
          "type": "string",
          "default": "/usr/bin/git-upload-pack",
          "description": "Serves `fetch`."
        },
        "git_receive_pack": {
          "type": "string",
          "default": "/usr/bin/git-receive-pack",
          "description": "Serves `push`."
        },
        "git_upload_archive": {
          "type": "string",
          "default": "/usr/bin/git-upload-archive",
          "description": "Serves `archive`."
        },
        "git_lfs_authenticate": {
          "type": "string",
          "default": "",
          "description": "Serves `lfs-download` and `lfs-upload`."
        },
        "lfs_batch_body_max": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 0,
          "description": "The largest LFS Batch API body a web backend reads **before** deciding the request, in bytes."
        }
      },
      "description": "Absolute paths to the git programs this node runs.",
      "additionalProperties": false
    },
    "AgentHost": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "default": "agents",
          "description": "Identifier this node registers under."
        },
        "scope": {
          "type": "string",
          "default": "",
          "description": "`id_prefix` of the catalog boundary this host publishes its works' faces into."
        }
      },
      "description": "Agent-host settings: the identity this node registers under.",
      "additionalProperties": false
    },
    "Recording": {
      "type": "object",
      "properties": {
        "mode": {
          "$ref": "#/$defs/RecordingMode",
          "default": "disk",
          "description": "Sink mode: `disk` (default) or `central`."
        },
        "sweep_interval_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 900,
          "description": "How often, in seconds, the connector walks `${enroll.state_dir}/recordings` and uploads the casts an earlier session close could not deliver."
        },
        "capture_stdin": {
          "type": "boolean",
          "default": false,
          "description": "Whether to capture client→server **stdin** bytes into the asciicast."
        }
      },
      "description": "Session-recording sink configuration.",
      "additionalProperties": false
    },
    "RecordingMode": {
      "oneOf": [
        {
          "type": "string",
          "const": "disk",
          "description": "Local disk under `${enroll.state_dir}/recordings/<uid>.cast`."
        },
        {
          "type": "string",
          "const": "central",
          "description": "Central Authority-backed store: the connector uploads through `Authority.StoreRecording`."
        }
      ],
      "description": "Where the connector persists session recordings."
    },
    "Admin": {
      "type": "object",
      "properties": {
        "endpoint": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Running Authority's gRPC endpoint URL — `https://host:port`."
        },
        "identity_dir": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Directory holding `cert.pem` / `key.pem` / `ca.pem` issued to the `gdsgate-admin` workstation at bootstrap time."
        },
        "transport": {
          "$ref": "#/$defs/AdminTransport",
          "default": "direct",
          "description": "What `endpoint` is: Authority itself, or a gateway that routes to it by TLS server name."
        }
      },
      "description": "Operator-workstation (admin CLI) configuration.",
      "additionalProperties": false
    },
    "AdminTransport": {
      "oneOf": [
        {
          "type": "string",
          "const": "direct",
          "description": "The endpoint is Authority's own control plane."
        },
        {
          "type": "string",
          "const": "fronted",
          "description": "The endpoint is a front — a gateway carrying the relayed control-plane branch, or any router that sorts connections by server name."
        }
      ],
      "description": "What `[admin].endpoint` names, which sets the TLS server name the CLI pins on it: `direct` or `fronted`."
    },
    "Audit": {
      "type": "object",
      "properties": {
        "anchor_key_path": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path to the 32-byte HMAC anchor-key file (hex encoded)."
        },
        "approval_key_path": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path to the 32-byte HMAC approval-key file (hex encoded)."
        },
        "revocation_key_path": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path to the 32-byte HMAC revocation-key file (hex encoded)."
        },
        "delegation_key_path": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path to the 32-byte HMAC delegation-key file (hex encoded)."
        },
        "inventory_key_path": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path to the 32-byte HMAC inventory-key file (hex encoded)."
        },
        "export_path": {
          "type": [
            "string",
            "null"
          ],
          "default": null,
          "description": "Path to the append-only audit export file (JSON-lines)."
        },
        "verify_interval_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 300,
          "description": "Cadence (seconds) the background verifier re-runs at."
        },
        "checkpoint_interval_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 3600,
          "description": "Cadence (seconds) Authority signs the audit chain head at."
        }
      },
      "description": "Audit chain anchoring and off-cluster export.",
      "additionalProperties": false
    },
    "Telemetry": {
      "type": "object",
      "properties": {
        "metrics_listen": {
          "type": "string",
          "default": "",
          "description": "Address for the observability HTTP server (e.g. `127.0.0.1:9090`)."
        },
        "otel_endpoint": {
          "type": "string",
          "default": "",
          "description": "OTLP/HTTP endpoint of an OpenTelemetry collector (e.g. `http://otel-collector:4318`)."
        }
      },
      "description": "Operational observability surface (`[telemetry]`).",
      "additionalProperties": false
    },
    "Doctor": {
      "type": "object",
      "properties": {
        "check_interval_secs": {
          "type": "integer",
          "format": "uint64",
          "minimum": 0,
          "default": 300,
          "description": "How often (seconds) a daemon re-runs the checklist for the metrics gauges."
        }
      },
      "description": "Periodic self-diagnosis (`[doctor]`).",
      "additionalProperties": false
    },
    "AgentProfile": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "default": "",
          "description": "The agent's name, matched against the file name of the program `--exec` names — `--exec /usr/local/bin/codex` looks for `codex`."
        },
        "source": {
          "type": "string",
          "default": "",
          "description": "The documentation page every field below was read off."
        },
        "checked": {
          "type": "string",
          "default": "",
          "description": "The day that page was read, `YYYY-MM-DD`."
        },
        "model_url_env": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Environment variables set to the base URL of the model endpoint, for an agent whose vendor documents one."
        },
        "model_url_path": {
          "type": "string",
          "default": "",
          "description": "Appended to `http://127.0.0.1:<port>` before the variables above are set — `/v1` for an agent whose base URL includes the API version."
        },
        "config_path": {
          "type": "string",
          "default": "",
          "description": "Where the agent's own configuration file lives, relative to its `$HOME`."
        },
        "config_env": {
          "type": "string",
          "default": "",
          "description": "A variable the agent reads the path of an *additional* configuration file from."
        },
        "config_dir_env": {
          "type": "string",
          "default": "",
          "description": "A variable the agent reads the directory `config_path` is in from, in place of finding it under its home."
        },
        "config_format": {
          "type": "string",
          "default": "",
          "description": "`json` or `toml` — the syntax of the file named above."
        },
        "tools_key": {
          "type": "string",
          "default": "",
          "description": "The dotted key holding the map of MCP servers in that file: `mcpServers`, `mcp_servers`, `mcp.servers`, `mcp`."
        },
        "tools_entry": {
          "type": "string",
          "default": "",
          "description": "One server's entry, as a JSON object, with `${url}` (the endpoint's Streamable HTTP address), `${endpoint}` (its `host:port`) and `${command}` (this binary's own path) substituted."
        },
        "model_config_key": {
          "type": "string",
          "default": "",
          "description": "The dotted key in the same file that takes the model endpoint's base URL, for an agent that has no environment variable for it."
        },
        "config_args": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Arguments put **before** the caller's own, for an agent that reads an arbitrary configuration file only through a command-line flag."
        },
        "note": {
          "type": "string",
          "default": "",
          "description": "Printed verbatim with the run: what this profile could not do for this agent and what a person has to do by hand."
        }
      },
      "description": "One entry of the agent-profile registry (`[[agent_profiles]]`): how to tell a *named* program where the endpoints `gdsgate delegate --exec` opened for it are.",
      "additionalProperties": false
    },
    "DelegationProfile": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "default": "",
          "description": "What `--profile` names."
        },
        "can": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Capabilities, in the `--can` spelling."
        },
        "ttl_secs": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0,
          "default": null,
          "description": "Validity window in seconds."
        },
        "exec": {
          "type": "string",
          "default": "",
          "description": "The program `--exec` runs when it is given no value of its own."
        },
        "exec_args": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Args for that program, as `--` would pass them."
        },
        "agent_profile": {
          "type": "string",
          "default": "",
          "description": "Which agent profile to wire the program up with, where the program's own name is not the one to look up."
        },
        "model": {
          "type": "string",
          "default": "",
          "description": "`gateway`, `direct` or `off`."
        },
        "sandbox": {
          "type": "string",
          "default": "",
          "description": "`none`, `basic` or `strict`."
        },
        "sandbox_allow": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "Paths the caged program may also read and execute."
        },
        "sandbox_listen": {
          "type": "array",
          "items": {
            "type": "integer",
            "format": "uint16",
            "minimum": 0,
            "maximum": 65535
          },
          "default": [],
          "description": "Ports the caged program listens on that this machine may reach."
        },
        "sandbox_memory": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0,
          "default": null,
          "description": "Memory ceiling for a `strict` run, in MiB."
        },
        "sandbox_processes": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0,
          "default": null,
          "description": "Process ceiling for a `strict` run."
        },
        "sandbox_cpu": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0,
          "default": null,
          "description": "CPU ceiling for a `strict` run, as a percentage of one core."
        },
        "renewable": {
          "type": [
            "boolean",
            "null"
          ],
          "default": null,
          "description": "Whether the agent-bound certificate is rolled forward within the window."
        },
        "env": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "default": {},
          "description": "Environment for the program, on top of whatever its agent profile sets."
        }
      },
      "description": "One saved `gdsgate delegate` invocation (`[[delegation_profiles]]`).",
      "additionalProperties": false
    },
    "KmsKey": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "name": {
          "type": "string",
          "description": "What a reference points at: the `<name>` in `${kms.<name>+…}`."
        },
        "provider": {
          "$ref": "#/$defs/KmsProvider",
          "description": "Which kind of key this is, and therefore which of the fields below it reads."
        },
        "command": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": [],
          "description": "For `provider = \"exec\"`: the words to run, the program first."
        },
        "key": {
          "type": "string",
          "default": "",
          "description": "For the native kinds: which key of the service this row means."
        },
        "address": {
          "type": "string",
          "default": "",
          "description": "Where the service answers, as a base URL."
        },
        "mount": {
          "type": "string",
          "default": "",
          "description": "For `provider = \"vault\"`: where the transit engine is mounted."
        },
        "region": {
          "type": "string",
          "default": "",
          "description": "For `provider = \"aws\"`: which region the key lives in."
        }
      },
      "required": [
        "name",
        "provider"
      ],
      "description": "One key of an external service this deployment's material is wrapped with (`[[kms_keys]]`)."
    },
    "KmsProvider": {
      "oneOf": [
        {
          "type": "string",
          "const": "exec",
          "description": "A command the operator wrote."
        },
        {
          "type": "string",
          "const": "vault",
          "description": "The transit engine of Vault or `OpenBao`."
        },
        {
          "type": "string",
          "const": "aws",
          "description": "The key service of AWS."
        },
        {
          "type": "string",
          "const": "gcp",
          "description": "The key service of Google Cloud."
        }
      ],
      "description": "Which kind of external key service a `[[kms_keys]]` entry uses: `exec`, `vault`, `aws` or `gcp`."
    }
  },
  "$id": "https://gate.gds.dev/docs/reference/config.schema.json",
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "description": "gdsgate configuration",
  "additionalProperties": false
}
