Skip to content
Registry StackDocsv0.41.0

API stability and versioning

View as Markdown

Use this page to decide which Registry Stack surfaces you can build on across releases. It names the promised products and surfaces, the experimental ones, the rules a change to a covered surface follows, and how state moves from one release to the next. The promise takes effect at v1.0.0.

Every artifact of a release (binaries, container images, client packages, the docs snapshot, and the release manifest under release/manifests/) carries one stack-wide version, tagged vMAJOR.MINOR.PATCH.

From v1.0.0, 1.x follows the deprecation rules on this page, not strict SemVer:

  • A patch release (1.x.y) fixes behavior and never breaks a covered surface.
  • A minor release (1.x) may add surface, deprecate surface, and remove a configuration or HTTP surface that was deprecated in at least one earlier minor release.
  • A major release (2.0) may also remove deprecated SDK methods.

Before v1.0.0, a minor release may contain breaking changes. Each one is announced with a BREAKING: entry and concrete migration steps in the stack release note, plus the owning product CHANGELOG where one exists. A patch release is backward compatible with the latest minor line.

The promise covers five products: Base Registry Engine, Evidence Gateway, Registry Casework, Registry Discovery, and Registry Manifest. For each, it covers the configuration files, identified by their apiVersion or schema version, and the HTTP API with its OpenAPI document and its problem code values. The linked references define each surface; if this page and a reference disagree, the reference wins.

ProductConfigurationHTTP API
Base Registry Engineregistry.yaml, module.yaml, and runtime.yaml, including the Rhai action handler ABI registry.action-handler/v1Base Registry Engine API
Evidence GatewayBundle and runtime filesEvidence Gateway API and problem types, including the signed JWS, unsigned JSON envelope, SD-JWT VC, and holder-bound issuance envelope response formats
Registry CaseworkCasework policy and runtime fileCasework API
Registry DiscoveryOrigins, evidence-type mappings, and runtime fileGET /v1/services and POST /v1/evidence-types/resolve
Registry Manifestregistry-manifest/v1 metadata documentsNone

Evidence Gateway’s versioned routes are POST /v1/evidence, POST /v1/evidence/batch, and GET /v1/evidence-definitions. Its operational routes are /health, /ready, /openapi.json, /.well-known/evidence/jwks.json, and /.well-known/jwt-vc-issuer.

The promise also covers the client SDKs: the Node.js package @registrystack/client, the Python package registry-stack-client, and the Rust crate registry-stack-client taken from the release tag. In each, the breg, evidence, casework, and discovery namespaces are promised. The SDKs are additive-only across 1.x, because a version range on a published package, such as npm ^1.2.0 or pip ~=1.2, picks up minor releases automatically: a minor release may deprecate an SDK method, and its removal waits for 2.0. A member of a promised namespace that reaches an experimental surface is experimental with that surface: for example, the statistics methods of the breg namespace, and the scheduling variant of task grant bounds in the casework namespace. See the client API reference.

These surfaces ship in releases but stay outside the promise. Those with a v1alpha1 version string keep it, and each may change or be removed in any minor release without deprecation:

  • Registry Scheduling, and the scheduling namespace of the client packages
  • Registry Messaging, and the messaging namespace the client packages carry from v0.38.0
  • Registry Render
  • breg-mcp and breg-review, the citizen services beside Base Registry Engine
  • evidence-oid4vci, the wallet-facing delivery service beside Evidence Gateway, including its configuration, routes, and command-line flags
  • the Base Registry Engine statistics routes under /v1/statistics/, and the statisticalDatasets declarations behind them
  • the Base Registry Engine spatial adapter routes under /v1/gis
  • calling Evidence from a Base Registry Engine governed action handler: the action’s evidence declaration, and evidence::resolve inside the handler
  • the scheduling variant of a Casework task grant’s bounds

Before v1.0.0, one breaking release moves the promised products’ version strings from v1alpha1 to stable versions, so a v1alpha1 version string that a 1.x release reads or writes (in configuration, an API, or a schema) marks an experimental surface. The published registry-discovery-v1alpha1 profile resources stay published as history and are not an experimental surface.

Two surfaces get best effort: ctl JSON output and audit record schemas. They may change in a minor release with a release note and no deprecation window.

These surfaces are not covered:

  • Rust library crates. Every workspace crate is publish = false, and nothing is published to crates.io. A crate other than the registry-stack-client SDK may change in any release; pinning the repository by tag or commit gets exactly what you pinned.
  • Database internals.
  • Human-readable CLI text.
  • Log lines.

A surface this page does not name is outside the promise.

For an HTTP API:

  • removing or renaming a route, parameter, request field, or response field
  • changing the type, meaning, or optionality of an existing field
  • changing the status code or the media type of an existing response
  • removing or renaming a problem code, changing the stack-wide meaning of a released code, or changing an existing product-and-operation HTTP mapping for it
  • tightening authentication or scope requirements on an existing route, except as a security fix announced in the release notes

For configuration:

  • removing or renaming a key
  • narrowing the accepted values of an existing key
  • changing the meaning or the default of an existing key

For an SDK:

  • removing or renaming a method, type, or member
  • changing a method’s parameters or result incompatibly

New routes, optional request fields, response members, optional configuration keys, problem codes, and SDK methods are additive. Descriptions, summaries, and ordering inside an OpenAPI document, and problem detail strings, are not part of the contract.

Nothing changes meaning in place. The replacement ships first, then the old form is deprecated, then removed. For configuration, the replacement is a new apiVersion accepted alongside the old one.

A deprecation lasts at least one minor release. There is no time floor; a later revision of this policy may lengthen the window and never shortens it. During the window:

  • the product’s check command, or registry-manifest validate for Registry Manifest, reports the deprecated version as a warning
  • HTTP responses carry Deprecation and Sunset headers (RFC 9745 and RFC 8594), and the OpenAPI document marks the route or field deprecated: true
  • the release note carries a Deprecated entry naming the surface, its replacement, the earliest release that may remove it, and copyable upgrade steps
  • the docs page for the surface notes since vX.Y and names the replacement

A removal turns a retired configuration key into a refusal, never a silently ignored key, and its release note repeats the migration steps.

A security fix may tighten or remove surface without the full window when keeping the surface would leave deployments exploitable. The release notes document the removal, the shortened window, and the migration steps without details that put unpatched deployments at more risk.

Changes made before v1.0.0, including the Registry Relay retirement, predate these rules. A docs page with status: deprecated frontmatter is a superseded page, not a scheduled removal.

A client must ignore response members it does not recognize, and must not fail on a problem code it does not recognize; it handles that problem by its HTTP status. That rule is what lets a minor release add members and codes.

For Base Registry Engine metadata, requiredCapabilities is the must-understand gate. An engine addition that changes how an existing member must be interpreted or executed must add a new requiredCapabilities value; every other additive member is ignorable. A client disables only the operation that names a capability it does not understand. The engine still authorizes every request at execution time.

Servers stay strict on requests and configuration: an unknown request member or configuration key is refused, not ignored. A configuration file that uses a key a later release introduced fails to load on an earlier binary, so pin configuration to the release you deploy.

Evidence Gateway’s frozen Version 1 contracts under products/evidence/contracts/ are the artifacts that define its configuration and HTTP surfaces. Frozen means they change only under the rules on this page: Evidence Gateway has the same promise and the same deprecation rule as the other promised products.

A WASM action handler is promised within the limits the WASM action handler guide states:

  • the project keys handler.type: wasm, the module path, and handler ABI registry.action-handler/v1
  • the guest byte ABI: a wasm32 core module with zero imports; the exports alloc, handle, result_ptr, result_len, and memory; the handle status codes 0 (success), 1 (malformed request), and 2 (internal error); the {"inputs": ...} request document; and the one JSON outcome document
  • the runtime wasmExecution keys maximumModuleBytes, maximumGuestMemoryBytes, and backend, with their documented ranges and defaults

Raising a limit is additive; lowering one is breaking. The fuel budget, which limit stops a call first, performance, backend speed, and the Wasmtime version are not promised. WASM hook handlers and the WASM handler SDK are outside the promise.

Each release reads the state its immediate predecessor wrote, with two exceptions: v0.40.0 and v1.0.0. v1.0.0 is a fresh install, and no upgrade from a v0.x release to it is supported. For a minor release, the immediate predecessor is the last release of the previous line. For a patch release, it is the previous release of its own line; a patch release promises no direct path from a release before its line. Upgrade one release at a time, and complete each release’s upgrade steps before you start the next.

v0.40.0 does not upgrade state v0.39.0 wrote in place. Rewrite the configuration you carry over, rebuild packages, and apply them to new databases as the upgrade runbook describes. The forward state path starts at v0.40.0; subsequent pre-1.0 releases read the state their immediate predecessor wrote.

Upgrades are forward-only: no release reads state a later release wrote. To roll back, restore the backup taken before the upgrade and run the previous release, as Roll back describes.

Evidence Gateway, Registry Discovery, and Registry Manifest have no migrated state. Base Registry Engine, Casework, Scheduling, and Messaging each own migrated PostgreSQL state: bregctl apply activates a package and runs its migration, caseworkctl apply activates a Casework package and runs its migrations, and schedulingctl apply activates a Scheduling package and runs its migrations. messagingctl apply activates a Messaging package and runs its migrations. Read each release’s notes for the migration steps it needs. The v0.40.0 exception above applies to all four. The forward state path holds for an experimental surface, such as Scheduling or Messaging, while a release ships it, and a release that removes one says in its release notes what happens to the state that surface wrote. Base Registry Engine’s Beta pilot conditions are under Stability in its requirements.

The promise is machine-checked where a checker exists:

  • Evidence Gateway: root CI’s evidence-contracts job runs products/evidence/scripts/check-contracts.sh, which regenerates every contract artifact and fails on any byte difference from the committed copies. products/evidence/scripts/check-config-key-paths.sh holds the configuration reference in exact parity with the frozen schemas.
  • Registry Manifest: schema and renderer tests pin accepted inputs and deterministic artifacts.
  • Forward state path: the release upgrade rehearsal workflow runs release/scripts/rehearse-upgrade.py on every pull request that changes a release manifest, and on manual dispatch. It verifies the previous release’s binaries against the signed SHA256SUMS, writes records, review work, messages, and audit entries with them against disposable PostgreSQL, upgrades with the binaries built from the pull request, and fails when captured domain data or stored revisions change, other captured views differ, retained tables lose rows, or an audit file loses entries. It starts from the newest published release at or below the workspace version, so it rehearses the immediate predecessor, and it refuses to start from a release before v0.40.0. While no release from that floor onward is published, the rehearsal uses the binaries under test on both sides and reports that it has no published predecessor. This exercises the scenarios with the same build; it does not demonstrate compatibility between releases. Once a release on the forward state path is published, the default run downloads it. Scheduling state is not rehearsed.

A change that a gate flags as breaking lands only in a release whose version permits it, with the deprecation and migration steps this page requires.