Config File
Authoritative reference for gestaltd configuration.
Top-Level Shape
auth: {}
datastore: {}
secrets: {}
telemetry: {}
providers: {}
bindings: {}
server: {}
egress: {}
ui: {}Load Semantics
${ENV_VAR}expansion happens before YAML decode- If
${ENV_VAR}is unset andENV_VAR_FILEis set, Gestalt reads the value from that file path - Unknown YAML fields are rejected
server.portdefaults to8080secrets.providerdefaults toenvtelemetry.providerdefaults tostdout- Relative paths resolve relative to the config file directory
secret://...values are resolved during bootstrap, not during YAML parsing
server
server:
port: 8080
base_url: https://gestalt.example.com
encryption_key: secret://gestalt-encryption-key
api_token_ttl: 30d| Field | Required | Default | Purpose |
|---|---|---|---|
port | No | 8080 | HTTP listen port. |
base_url | No | — | Derives OAuth callback URLs when explicit redirect URLs are omitted. |
encryption_key | Yes | — | Root deployment secret. Used for encryption and derived session material. |
api_token_ttl | No | 30d | Lifetime of newly issued API tokens. Accepts Go duration strings (1h, 720h) and day suffixes (30d). |
auth
none
auth:
provider: noneDisables platform authentication. Every request is treated as a single anonymous user.
local
auth:
provider: local
config:
email: local@example.com| Field | Required | Default | Purpose |
|---|---|---|---|
email | No | local@gestalt.local | Identity of the single local user. |
google
auth:
provider: google
config:
client_id: ${GOOGLE_CLIENT_ID}
client_secret: secret://google-client-secret
redirect_url: https://gestalt.example.com/api/v1/auth/login/callback
allowed_domains:
- example.com| Field | Required | Default | Purpose |
|---|---|---|---|
client_id | Yes | — | Google OAuth client ID. |
client_secret | Yes | — | Google OAuth client secret. |
redirect_url | No | Derived from server.base_url | Login callback URL. |
allowed_domains | No | — | Restrict login to specific email domains. |
Google checks email_verified on every login. Unverified accounts are rejected.
oidc
auth:
provider: oidc
config:
issuer_url: https://login.example.com
client_id: ${OIDC_CLIENT_ID}
client_secret: secret://oidc-client-secret
redirect_url: https://gestalt.example.com/api/v1/auth/login/callback
allowed_domains:
- example.com
scopes:
- openid
- email
- profile
session_secret: secret://oidc-session-secret
session_ttl: 24h
pkce: true
display_name: Company SSO| Field | Required | Default | Purpose |
|---|---|---|---|
issuer_url | Yes | — | OIDC discovery base URL. |
client_id | Yes | — | OIDC client ID. |
client_secret | Conditional | — | OIDC client secret. May be omitted for PKCE-only public clients. |
redirect_url | No | Derived from server.base_url | Login callback URL. |
allowed_domains | No | — | Email-domain allowlist. |
scopes | No | openid, email, profile | OIDC scopes to request. |
session_secret | Yes | — | Secret for signing session tokens. |
session_ttl | No | 24h | Session token lifetime. |
pkce | No | false | Enable PKCE for the login flow. |
display_name | No | SSO | Name shown in the login UI. |
OIDC checks email_verified when the claim is present. Unverified accounts are rejected.
datastore
datastore:
provider: postgres
config:
dsn: ${DATABASE_URL}| Provider | Config fields | Purpose |
|---|---|---|
sqlite | path | Defaults to ./gestalt.db. Single-node deployments. |
postgres | dsn | Recommended production datastore. |
mysql | dsn | SQL-backed production option. |
dynamodb | table, region, endpoint | table defaults to gestalt. |
mongodb | uri, database | database defaults to gestalt. |
oracle | dsn | Enterprise SQL option. |
firestore | project_id, database | Firestore-backed deployment. |
sqlserver | dsn | SQL Server-backed deployment. |
secrets
secrets:
provider: file
config:
dir: /etc/gestalt-secrets| Provider | Config fields | Purpose |
|---|---|---|
env | prefix | Reads secrets from environment variables. |
file | dir | Reads one secret per file from a base directory. Works with Kubernetes volume-mounted secrets. |
google_secret_manager | project, version | Google Cloud Secret Manager. version defaults to latest. |
aws_secrets_manager | region, version_stage, endpoint | AWS Secrets Manager. version_stage defaults to AWSCURRENT. |
vault | address, token, mount_path, namespace | HashiCorp Vault KV v2. mount_path defaults to secret. |
azure_key_vault | vault_url, version | Azure Key Vault. version defaults to latest. |
telemetry
Controls distributed traces, metrics, and structured logs. Gestalt uses OpenTelemetry under the hood. Every HTTP request, broker invocation, and plugin gRPC call is automatically traced.
stdout
telemetry:
provider: stdout
config:
format: text
level: info| Field | Required | Default | Purpose |
|---|---|---|---|
format | No | text | text or json. |
level | No | info | debug, info, warn, or error. |
Outputs structured logs to standard output. Traces and metrics use noop providers to keep terminal output clean. Default provider when telemetry is omitted.
otlp
telemetry:
provider: otlp
config:
endpoint: otel-collector:4317
protocol: grpc
service_name: gestaltd
insecure: false
headers:
Authorization: Bearer ${OTEL_TOKEN}
resource_attributes:
deployment.environment: production
service.version: "1.0.0"
traces:
sampling_ratio: 1.0
metrics:
interval: 60s
logs:
level: info| Field | Required | Default | Purpose |
|---|---|---|---|
endpoint | No | SDK default | OTLP collector address. |
protocol | No | grpc | grpc or http. |
service_name | No | gestaltd | OpenTelemetry service name. |
insecure | No | false | Skip TLS verification. |
headers | No | — | Extra headers on every export request. |
resource_attributes | No | — | Key-value pairs attached as resource attributes. |
traces.sampling_ratio | No | 1.0 | Fraction of traces to sample, 0.0 to 1.0. |
metrics.interval | No | 60s | Metric export interval. |
logs.level | No | info | Minimum exported log level. |
Exports to any OpenTelemetry-compatible collector (Jaeger, Grafana Alloy, Datadog Agent).
noop
telemetry:
provider: noopDisables all telemetry. Instrumentation points remain but produce zero overhead.
Trace spans
| Layer | Span name | Key attributes |
|---|---|---|
| HTTP | gestaltd: {method} {route} | Standard HTTP semantic conventions |
| Broker | broker.invoke | gestalt.provider, gestalt.operation, gestalt.user_id, gestalt.connection_mode |
| gRPC plugin | Per-RPC spans | Standard gRPC semantic conventions |
Audit logs
Audit records are emitted as structured log entries with log.type=audit. Route them to a dedicated audit backend using OTel Collector attribute-based filtering. See Observability for details.
providers
Config uses a top-level providers: map. Each provider entry is provider-shaped
directly: there is no nested plugin: block anymore.
providers:
github:
display_name: GitHub
description: Public GitHub operations
icon_file: ./icons/github.svg
connections:
public:
mode: none
auth:
type: none
surfaces:
openapi:
document: ./openapi/github.yaml
connection: public
allowed_operations:
repos.get:
alias: get_repo
mcp:
enabled: true
tool_prefix: github_The config key is providers, but the HTTP API and client CLI still refer to
these named entries as integrations.
Provider fields
| Field | Purpose |
|---|---|
display_name | UI and API display name override. |
description | UI and API description override. |
icon_file | SVG icon path resolved from the config directory. |
config | Provider-specific config passed into packaged providers. |
from | Optional packaged/executable source. Omit it for fully inline providers. |
connections | Named connections. default is the primary connection entry. |
headers | Static headers applied to declarative or spec-backed requests. |
managed_parameters | Fixed header or path values injected before exposure. |
response_mapping | Data and pagination mapping for OpenAPI or GraphQL providers. |
allowed_operations | Surface allowlist plus alias and description overrides. |
surfaces | Declarative REST, OpenAPI, GraphQL, and MCP surfaces. |
expose | MCP exposure settings such as tool prefix. |
providers.*.from
Use from when the provider is backed by an executable or packaged plugin.
from:
command: ./bin/provider
args:
- --debug
env:
LOG_LEVEL: debug| Field | Purpose |
|---|---|
command | Execute a local binary directly. |
package | Load a local directory, local archive, or HTTPS archive. |
source | Resolve a versioned plugin source during init. Format: github.com/<org>/<repo>/<plugin>. |
version | Required with source. Invalid with command or package. |
args | Extra process arguments for command. |
env | Extra environment variables for executable providers. |
allowed_hosts | Optional network allowlist for sandboxed plugin processes. |
command, package, and source are mutually exclusive.
Auth shapes inside connections
Every connection auth block uses the same shape:
connections:
default:
auth:
type: oauth2
authorization_url: https://provider.example.com/oauth/authorize
token_url: https://provider.example.com/oauth/token
client_id: ${CLIENT_ID}
client_secret: ${CLIENT_SECRET}
client_auth: body
token_exchange: form
scopes:
- read
- write
scope_param: user_scope
scope_separator: ","
pkce: true
authorization_params:
audience: https://api.example.com
token_params:
resource: api
refresh_params: {}
accept_header: application/json
token_metadata:
- workspace_id| Field | Purpose |
|---|---|
type | oauth2, manual, bearer, none, or mcp_oauth. |
authorization_url | OAuth authorization endpoint. |
token_url | OAuth token endpoint. |
client_id, client_secret | OAuth client credentials. |
redirect_url | Override the derived callback URL. |
client_auth | How client credentials are sent: body (default) or header. |
token_exchange | Token request encoding: form (default) or json. |
scopes | OAuth scopes to request. |
scope_param | Query parameter name for scopes. Defaults to scope. Set to user_scope for Slack and other providers that use a non-standard parameter. |
scope_separator | Separator between scope values. Defaults to space. |
pkce | Enable Proof Key for Code Exchange. |
authorization_params | Extra query parameters on the authorization request. |
token_params | Extra parameters on the token exchange request. |
refresh_params | Extra parameters on the token refresh request. |
accept_header | Accept header for the token endpoint. |
token_metadata | Fields to extract from the token response and store as connection metadata. |
mcp_oauth is an advanced mode for MCP-driven OAuth discovery. It delegates
authorization URL and token URL resolution to the upstream MCP server.
Manual auth with custom credential fields
For manual-auth connections, you can customize the credential input form with
credentials. Each entry defines a field the user must fill in, with an
optional label, description, and help URL.
Single credential with a custom label:
connections:
default:
auth:
type: manual
credentials:
- name: token
label: API Access Token
help_url: https://app.example.com/settings/tokensMultiple credentials require auth_mapping to map each field to an HTTP
header:
connections:
default:
auth:
type: manual
credentials:
- name: api_key
label: API Key
help_url: https://us5.datadoghq.com/organization-settings/api-keys
- name: app_key
label: Application Key
help_url: https://us5.datadoghq.com/organization-settings/application-keys
auth_mapping:
headers:
DD-API-KEY: api_key
DD-APPLICATION-KEY: app_key| Field | Notes |
|---|---|
credentials[].name | Internal identifier for the field. Must be unique, lowercase with underscores. |
credentials[].label | Display label shown in the UI. Falls back to name if omitted. |
credentials[].description | Hint text shown below the label. Supports inline links via [text](url). |
credentials[].help_url | Link displayed next to the label for where to find the credential. |
auth_mapping.headers | Maps credential field names to HTTP headers. Required when multiple credentials are declared. |
credentials is required when auth.type is manual.
connections
connections:
default:
mode: user
auth:
type: oauth2
authorization_url: https://accounts.example.com/oauth/authorize
token_url: https://accounts.example.com/oauth/token
client_id: ${CLIENT_ID}
client_secret: ${CLIENT_SECRET}
params:
tenant:
required: true
description: Tenant identifier
mcp:
mode: user
auth:
type: mcp_oauthOnly connections.default may define:
paramsdiscovery
Connection modes:
noneuseridentityeither
If you omit connections.default and use only named connections, every
configured surface must set its own connection.
Post-connect discovery
connections:
default:
mode: user
auth:
type: oauth2
authorization_url: https://accounts.example.com/oauth/authorize
token_url: https://accounts.example.com/oauth/token
params:
workspace_id:
required: true
description: Workspace chosen after connect
from: discovery
discovery:
url: https://api.example.com/workspaces
id_path: id
name_path: name
metadata:
workspace_id: idsurfaces
surfaces.rest, surfaces.openapi, and surfaces.graphql are mutually
exclusive. surfaces.mcp can be added alongside any of them.
Declarative REST
surfaces:
rest:
base_url: https://api.support.example.com
operations:
- name: list_tickets
method: GET
path: /tickets
- name: get_ticket
method: GET
path: /tickets/{ticket_id}Each declarative operation accepts:
namedescriptionmethodpathparameters
Parameter locations can be query, body, or path.
OpenAPI, GraphQL, and MCP
surfaces:
openapi:
document: ./openapi/workspace.yaml
connection: default
mcp:
url: https://mcp.example.com/mcp
connection: mcp| Surface field | Purpose |
|---|---|
surfaces.rest.base_url | Base URL for declarative REST operations. |
surfaces.rest.operations | Inline declarative REST operations. |
surfaces.openapi.document | OpenAPI document URL or local file path. |
surfaces.openapi.base_url | Optional runtime base URL override for OpenAPI. |
surfaces.graphql.url | GraphQL endpoint URL. |
surfaces.mcp.url | Upstream MCP endpoint URL. |
surfaces.*.connection | Connection name for that surface. |
Managed parameters
connections:
default:
mode: none
auth:
type: none
surfaces:
openapi:
document: https://api.example.com/openapi.json
managed_parameters:
- in: header
name: X-API-Version
value: "2026-04-01"
- in: path
name: account_id
value: primaryManaged parameter locations can be header or path.
Response mapping
connections:
default:
auth:
type: bearer
credentials:
- name: token
label: API Token
surfaces:
graphql:
url: https://api.example.com/graphql
response_mapping:
data_path: data.items
pagination:
has_more_path: pageInfo.hasNextPage
cursor_path: pageInfo.endCursormcp
mcp:
enabled: true
tool_prefix: github_bindings
bindings:
inbound:
type: webhook
providers:
- github
config:
path: /events/github
provider: github
operation: issues_listForAuthenticatedUser
auth_mode: signed
signing_secret: secret://webhook-secretbindings:
outbound_proxy:
type: proxy
providers:
- github
config:
path: /proxy
instance: defaultCommon binding fields
| Field | Purpose |
|---|---|
type | webhook or proxy. |
providers | Allowlist of providers the binding can access. |
config | Binding-type-specific config. |
Webhook binding config
| Field | Purpose |
|---|---|
path | Required. Must start with /. |
provider | Optional target provider for forwarding. |
instance | Optional provider instance. |
operation | Optional target operation. |
auth_mode | public, signed, or trusted_user_header. |
signing_secret | Required for signed. |
signature_header | Header carrying the HMAC signature. Defaults to X-Signature. |
user_header | Required for trusted_user_header. |
trusted_sources | Source IP allowlist for trusted_user_header. |
Proxy binding config
| Field | Purpose |
|---|---|
path | Required. Must start with /. |
Proxy bindings may declare zero or one provider in bindings.<name>.providers. Webhook forwarding requires the forwarded provider to be present in the binding allowlist.
egress
egress:
default_action: deny
policies:
- action: allow
subject_kind: user
provider: github
method: GET
host: api.github.com
path_prefix: /repos
credentials:
- host: api.github.com
secret_ref: github-api-key
auth_style: bearer
- host: api.openai.com
secret_ref: openai-api-key
auth_style: bearerpolicies
| Field | Purpose |
|---|---|
action | allow or deny. |
subject_kind | Match a subject kind. |
subject_id | Match a specific subject. |
provider | Match a provider name. |
operation | Match an operation name. |
method | Match an HTTP method. |
host | Match an outbound host. |
path_prefix | Match a path prefix. |
credentials
| Field | Purpose |
|---|---|
secret_ref | Required. Secret manager key resolved at request time. |
auth_style | How the resolved secret is injected: bearer, basic, or raw. Defaults to bearer. |
subject_kind | Optional subject filter. |
subject_id | Optional subject filter. |
operation | Optional operation filter. |
method | Optional HTTP-method filter. |
host | Optional host filter. |
path_prefix | Optional path filter. |
ui
ui:
plugin:
package: ./my-ui-pluginui:
plugin:
source: github.com/your-org/your-repo/console
version: 1.0.0| Field | Purpose |
|---|---|
plugin.package | Local directory, local archive, or HTTPS URL. Mutually exclusive with source. |
plugin.source | Managed plugin source address. Requires version. |
plugin.version | Required with source. Must be valid SemVer without leading v. |
When ui is omitted, gestaltd serves the embedded frontend. When ui.plugin is configured, the plugin’s assets are served instead. See UI Plugins for the full workflow.
Validation Rules
Structural validation runs at config load time (init, validate, serve). Runtime validation runs only at serve time.
Structural
- Provider entries are decoded directly; there is no nested
pluginblock - Exactly one of
from.command,from.package, orfrom.sourceper packaged provider from.versionis required withfrom.sourceand invalid withfrom.commandorfrom.packagefrom.argsare only valid withfrom.command- Plain
http://package URLs are rejected surfaces.rest,surfaces.openapi, andsurfaces.graphqlare mutually exclusive- Only
connections.defaultmay defineparamsordiscovery - All connections in a provider must share the same mode
surfaces.*.connectionmust reference a declared connection when present- URL templates in spec surfaces and auth URLs must reference required params
egress.default_actionand policyactionmust beallowordenyui.pluginrequires exactly one ofpackageorsourceui.plugin.versionis required withsourceand invalid withpackage
Runtime
auth.provideris requireddatastore.provideris requiredserver.encryption_keyis required