Config stability tiers

July 29, 2026 ยท View on GitHub

Last modified: 2026-07-28

This page defines the stability tiers and applies them to representative or high-impact configuration leaves. It also lists the current reviewed config-only registry. It is not an exhaustive field matrix: configuration.md is the complete field inventory.

An unlisted field has no implicit stability promise. Before depending on one, review its Rust source and the changelog for the release you plan to run.


Stability tiers

stable

A stable field is part of the committed public API of SBproxy.

  • The field name, type, and default value will not change in a minor or patch release.
  • Removing or renaming a stable field requires a major version bump (e.g. v1 -> v2) and a migration guide.
  • Behavioral changes to a stable field require at least a minor version bump and a changelog entry.

beta

A beta field is functional and tested but may still change.

  • Available for production use. Monitor the changelog before upgrading.
  • Renames or semantic changes may happen in a minor release with a deprecation notice.
  • Beta fields are not silently removed. A one-release deprecation period applies.

alpha

An alpha field is experimental.

  • May be renamed, restructured, or removed in any release without prior notice.
  • Do not depend on alpha fields in critical production paths.
  • Feedback on alpha fields is welcome and influences their stabilization.

disabled

A disabled field is retained in the schema but cannot activate runtime behavior today.

  • An omitted block or its disabled value remains valid for config compatibility.
  • Attempting to enable unavailable behavior fails config compilation instead of being ignored.
  • Currently applies to the http3 block. Native HTTP/3 support is tracked in WOR-1969.

config-only

A config-only field remains parseable for compatibility but has no live consumer in the open-source runtime.

  • Do not use it to satisfy an operational requirement.
  • An explicitly authored config-only key emits a boot/config-validation warning naming the complete schema path and the reason it has no effect.
  • The build-time config-reader guard requires an explicit registry entry and an operator-facing reason for every such field.
  • The field is removed from examples that purport to demonstrate working behavior. Its reference entry states the live alternative, when one exists.

Stabilization rules

  1. A field moves from alpha to beta once its interface is reviewed, it has integration tests, and it has been in at least one release.
  2. A field moves from beta to stable once it has been in production use by at least one internal deployment for one full release cycle without interface changes.
  3. Stable fields are never silently removed. The process is: deprecate (the config compiler logs a structured deprecation warning at load time naming the legacy and canonical field), then remove in the next major version. A schema-level x-deprecated annotation is planned but not shipped.

Build-time reader coverage

CI walks the generated ConfigFile JSON Schema and requires every key to have either a non-test Rust field read or a reviewed entry in CONFIG_KEY_OVERRIDES. Indirect serde consumers name their concrete runtime consumer. Deliberately inert fields are marked config-only with a reason. Run the same lane locally with:

scripts/check-config-readers.sh

Adding a key to types.rs without wiring it now fails with the complete dotted schema path. Adding a reviewed ConfigOnly entry makes the exception explicit and stale entries fail when their schema path is removed or renamed.

Current config-only compatibility fields

Field or subtreeWhat happens today
agent_classes.hosted_feed.url, .bootstrap_keysThe OSS resolver uses builtin or inline catalogs; it does not fetch or verify a hosted feed.
audit.sinkAdmin-action rows always use the in-memory ring and tracing mirror; this selector has no effect.
origins.*.agent_skills[].max_clock_skew_secsReserved for signed artifact freshness headers that are not emitted yet.
origins.*.connection_poolPingora's built-in upstream pool is used; these per-origin limits are not applied.
origins.*.compression.levelCompression libraries use their runtime defaults; this parsed level is not applied.
origins.*.cors.enableThe presence of cors: enables CORS; the legacy boolean value is ignored.
origins.*.credentials[].attrs.budget.resetReserved reset hint; no credential reset schedule is installed. The same leaf is config-only at proxy and tenant credential scopes.
origins.*.credentials[].attrs.teamParsed with a warning but not copied into the virtual-key principal. The same leaf is config-only at proxy and tenant credential scopes; use live attrs.tags or attrs.metadata attribution instead.
origins.*.forward_rules[].origin.hostname, .workspace_id, .versionInline forward-origin metadata is accepted but not copied into the compiled child origin.
origins.*.rate_limit_headersUse the live rate-limit policy's headers block instead.
origins.*.response_modifiers[].status.textThe status code is applied; the compatibility reason text is ignored.
origins.*.sessions.ttl_secondsReserved retention hint; the in-process request ring does not expire entries from it.
origins.*.traffic_captureNo OSS capture consumer; use mirror for live fire-and-forget request mirroring.
proxy.device_parser_fileThe current pure-Rust device parser does not load this catalog override.
proxy.key_management.governance.key_introspectionThe caller-only introspection route is not installed.
proxy.key_management.store.redis_source_of_truthRedis is authoritative whenever store.backend: redis; this legacy boolean changes nothing.
proxy.observability.log.level, .format, .samplingProcess logging uses CLI/environment selection and fixed sampling defaults. Sink-local format remains live.
proxy.scripting.javascript.sandbox.budget_ms, .memory_mb, .stack_kbQuickJS engines use built-in sandbox defaults; these YAML leaves are not installed.
proxy.secrets.backend, .hashicorp, .map, .rotation, .fallbackLegacy single-backend surface. Use named proxy.secrets.backends and provider URI references.

Selected field stability reference

The tables below cover representative and high-impact leaves. They do not assign a tier to every property accepted by the configuration parser. Use the tier definitions above only where a field is listed explicitly.

Top-level fields

FieldTypeStabilityNotes
proxyobjectstableServer configuration block.
originsobject (map)stableMap of hostname to origin config.

proxy - ProxyServerConfig

FieldTypeDefaultStabilityNotes
http_bind_portinteger8080stablePlain HTTP listener port.
https_bind_portinteger-stableTLS listener port. Optional.
tls_cert_filestring-stablePath to PEM cert for manual TLS.
tls_key_filestring-stablePath to PEM key for manual TLS.
acmeobject-betaAutomatic TLS via ACME.
http3object-disabledReserved HTTP/3 (QUIC) listener shape. enabled: true is rejected.

proxy.acme - AcmeConfig

FieldTypeDefaultStabilityNotes
enabledbooleanfalsebetaActivates ACME.
emailstring""betaContact email for the ACME account.
directory_urlstringLet's Encrypt prodbetaACME directory endpoint URL.
challenge_typesarray[http-01]betaChallenge method preference list. tls-alpn-01 is accepted in the list but not yet served.
storage_backendstringredbbetaCert persistence backend.
storage_pathstring/var/lib/sbproxy/certsbetaFilesystem path for cert storage.
renew_before_daysinteger30betaDays before expiry to renew.

proxy.http3 - Http3Config

HTTP/3 is not served by this build. The block is retained for forward compatibility: omission or enabled: false compiles, while enabled: true fails config compilation with a reference to WOR-1969.

FieldTypeDefaultStabilityNotes
enabledbooleanfalsedisabledMust remain false until HTTP/3 is served.
max_streamsinteger100disabledReserved max concurrent QUIC streams per connection.
idle_timeout_secsinteger30disabledReserved QUIC idle timeout in seconds.

Origin Config (each entry under origins:)

FieldAliasTypeDefaultStabilityNotes
action-objectrequiredstableWhat the proxy does with requests.
authenticationauthobject-stableAuth plugin config.
policies-array[]stablePolicy plugin list.
transforms-array[]betaBody transform plugin list.
request_modifiers-array[]stableRequest modification steps.
response_modifiers-array[]stableResponse modification steps.
cors-object-stableCORS policy.
hsts-object-stableHSTS policy.
compression-object-stableResponse compression.
sessionsession_configobject-betaSession cookie management.
force_ssl-booleanfalsestableRedirect HTTP to HTTPS.
allowed_methods-array[] (all)stableHTTP method allowlist.
forward_rules-array[]betaConditional routing rules.
fallback_origin-object-betaSecondary origin on primary failure.
response_cache-object-betaResponse caching config.
variables-object{}betaNamed template variables.
on_request-array[]alphaRequest event hook plugins.
on_response-array[]alphaResponse event hook plugins.
bot_detection-object-alphaBot detection config.
threat_protection-object-alphaDynamic threat blocklist config.
rate_limit_headers-object-config-onlyUse the live rate-limit policy's headers block.
error_pages-array-betaCustom error page entries, each matching one status or a list of statuses.
traffic_capture-object-config-onlyNo OSS consumer; use mirror for request mirroring.
connection_pool-object-config-onlyRetained for compatibility; Pingora's built-in pool settings apply.
message_signatures-object-alphaHTTP message signing config.

CORS Config (cors:)

FieldAliasTypeDefaultStability
allowed_originsallow_originsarray[]stable
allowed_methodsallow_methodsarray[]stable
allowed_headersallow_headersarray[]stable
expose_headers-array[]stable
max_age-integer-stable
allow_credentials-booleanfalsestable
enableenabledboolean-config-only

HSTS Config (hsts:)

FieldTypeDefaultStability
max_ageinteger31536000stable
include_subdomainsbooleanfalsestable
preloadbooleanfalsestable

Compression Config (compression:)

FieldAliasTypeDefaultStability
enabledenablebooleantruestable
algorithms-array[]stable
min_size-integer0stable
level-integer-config-only

level is parsed but not applied: the encoders use their library default levels (gzip and zstd defaults, brotli quality 4).

Session Config (session:, alias session_config:)

FieldAliasTypeDefaultStability
cookie_name-string-beta
max_agecookie_max_ageinteger-beta
http_only-booleanfalsebeta
secure-booleanfalsebeta
same_sitecookie_same_sitestring-beta
allow_non_ssl-booleanfalsebeta

Request Modifier (request_modifiers[])

FieldTypeStabilityNotes
headersobjectstableHeader set/add/remove.
urlobjectstablePath rewrite.
queryobjectstableQuery param set/add/remove.
methodstringstableOverride HTTP method.
bodyobjectstableBody replacement.
lua_scriptstringbetaDynamic modification via Lua.

Response Modifier (response_modifiers[])

FieldTypeStabilityNotes
headersobjectstableHeader set/add/remove.
statusobjectstableStatus code override.
bodyobjectstableBody replacement.
lua_scriptstringbetaDynamic modification via Lua.

Header Modifiers

FieldAliasTypeDefaultStability
set-object{}stable
add-object{}stable
removedeletearray[]stable

Path Replace (url.path.replace)

FieldTypeStability
oldstringstable
newstringstable

Query Modifier

FieldAliasTypeDefaultStability
set-object{}stable
add-object{}stable
removedeletearray[]stable

Body Modifier (request)

FieldTypeStability
replacestringstable
replace_jsonanystable

Response Body Modifier

FieldTypeStability
replacestringstable
replace_jsonanystable

Status Override

FieldTypeStability
codeintegerstable
textstringconfig-only

text is retained for schema-v1 compatibility. The response modifier applies code; the runtime does not emit or preserve a custom reason phrase.