Registry stack documentation: machine-readable Markdown.
Index of all pages: https://docs.registrystack.org/v/0.38.0/llms.txt
Full corpus: https://docs.registrystack.org/v/0.38.0/llms-full.txt

# Changelog

> Notable changes to the Registry Stack documentation and the documented product versions.

This page records notable changes to the documentation site and the product versions it
documents.
Per-product release notes live in each product repository; the entries below link to the
relevant product pages on this site rather than duplicating release notes.

## Unreleased

## v0.38.0 beta-50

- BREAKING: a Base Registry Engine (BReg) direct create, patch, or batch item whose resulting row
  falls outside the caller's row boundary answers `412 precondition.failed` before any write,
  where it answered `503 service.unavailable`. Retrying the unchanged request cannot succeed, a
  batch carrying one such item commits none of them, and a genuine PostgreSQL privilege failure
  still answers `503`. Handle a `412` on a create as a boundary refusal, not a retryable outage.

{/* Evidence: crates/registry-breg/tests/postgres_mutation.rs,
    real_postgres_row_boundary_refusals_reveal_no_hidden_row_and_batches_write_nothing;
    products/breg/CHANGELOG.md. */}

- BREAKING: the generated BReg OpenAPI document lists `412 precondition.failed` on every create
  and batch operation reachable through a profile with `rowBoundaries`, so such a project compiles
  to a new `registryRevision` and a package an earlier release built for it no longer loads.
  Rebuild it unchanged with the v0.38.0 `bregctl test` and `bregctl package`, each naming the
  deployed package with `--baseline-package`, as
  [test and package the successor](../operate/breg-changes/#test-and-package-the-successor)
  gives in full, and apply it with `bregctl plan` and `bregctl apply`, then repin
  any Registry Casework BReg source for it with `caseworkctl source add ... --apply` and package,
  plan, and apply the Casework project once.

{/* Evidence: crates/registry-breg/src/tests/artifacts_response_schema_tests.rs,
    prospective_row_boundary_refusal_is_documented_only_where_it_can_apply;
    products/breg/CHANGELOG.md. */}

- A BReg entity may declare `accessLog` to keep a subject-facing log of reads of its records. The
  record subject reads it at `GET /v1/records/{route}/{id}/access-log`, retention defaults to 90
  days, `trustedIntermediaries` may forward the original requester and purpose, and `exemptions`
  delay a documented entry without omitting it. The log is stored apart from the operational
  audit, and a failed log insert refuses the read.

{/* Evidence: crates/registry-breg/src/api/access_log.rs, routes;
    products/breg/ACCESS-LOG.md. */}

- BReg automatic review executors can renew credentials with `privateKeyJwt`, and
  `bregctl review-recovery retry-application` requeues an executor-denied job. Webhook dead letters
  keep a closed failure reason, and `bregctl webhook discard` closes eligible work captured under a
  superseded binding without replaying it.

{/* Evidence: products/breg/CHANGELOG.md;
    crates/registry-platform-hooks/src/delivery_schema.rs, dead_letter_reason. */}

- BREAKING: Registry Casework and Registry Scheduling activation (`plan`, `apply`, and `status`)
  and runtime startup refuse a PostgreSQL server older than 17, before any migration or activation
  write. Upgrade the database server before upgrading either product.

{/* Evidence: crates/registry-platform-activation/src/lib.rs, UnsupportedPostgres;
    crates/registry-casework/src/activation.rs, UnsupportedPostgres. */}

- BREAKING: Registry Scheduling publishes the `v1alpha2` HTTP contract. Holds and appointments
  carry a required `externalReferences` array of opaque `{product, recordType, identifier}`
  links, a hold or direct booking may send it, and a reschedule must omit it.
  `GET /v1/appointments` lists the caller's own appointments carrying one exact reference.
  Migration 10 stores the references, so run `schedulingctl plan` and `apply` before restarting,
  and upgrade the runtime before any client sends the field.

{/* Evidence: crates/registry-scheduling-core/src/wire.rs, ExternalReference;
    crates/registry-scheduling/src/http.rs, list_appointments and bounded_external_reference;
    crates/registry-scheduling/migrations/0010_external_references.sql. */}

- BREAKING: an Evidence requirement's `subjectRoles[].role` is limited to 64 bytes instead of 128,
  in the bundle schema and at startup. Shorten a longer role and every input that names it before
  upgrading.

{/* Evidence: crates/registry-evidence/src/config.rs, SubjectRole. */}

- An Evidence `http-json` source may declare `evidence` to read one predefined assertion from
  another Evidence deployment, verified against pinned `trustedJwks` before projection.
  Separately, a source that does not declare `evidence` may set `forwardAccessAttribution` to send
  the verified requester and purpose to a source that trusts this service as an intermediary;
  startup refuses a source that sets both. `evidence-oid4vci` validates its whole catalog and every offer
  before an offer secret exists.

{/* Evidence: crates/registry-evidence/src/source_evidence.rs, EvidenceSourceConfig;
    products/evidence/reference/request-adapter/deployment-projects/CONFIG.md. */}

- The release publishes a `discoveryctl` Linux amd64 binary and a standalone Registry Scheduling
  Linux amd64 runtime binary beside the Scheduling image and `schedulingctl` binaries.

{/* Evidence: release/scripts/release_roster.py, DISCOVERYCTL_FIRST_RELEASE and
    SCHEDULING_BINARY_FIRST_RELEASE. */}

- Registry Messaging and Registry Render ship for the first time, each as release binaries and a
  `ghcr.io/registrystack/<name>` image, and the Evidence OID4VCI adapter gains the
  `ghcr.io/registrystack/evidence-oid4vci` image. The unified Node.js and Python clients add a
  `messaging` namespace. See [deploy Registry Messaging](../operate/messaging/) and
  [run Registry Render in serve mode](../operate/registry-render/).

{/* Evidence: release/scripts/release_roster.py, MESSAGING_FIRST_RELEASE, RENDER_FIRST_RELEASE,
    and EVIDENCE_OID4VCI_IMAGE_FIRST_RELEASE;
    crates/registry-stack-client-node/index.d.ts. */}



- `breg-mcp` ships for the first time, a supporting service beside BReg: an MCP gateway a chat
  host uses to act for one verified citizen. It reads the citizen's own
  record and creates or patches change-request drafts for it, and has no
  code path to submit, revise, cancel, or apply one. It verifies the chat
  host's token as an OAuth protected resource and, for every tool call,
  exchanges it (RFC 8693) for a registry token with the gateway as actor,
  so the chat host's token never reaches BReg. It takes a draft's target
  from the citizen's own linked record, never from a tool argument.
  `breg-mcp check` validates the runtime configuration and `breg-mcp serve`
  runs the gateway.
  This release publishes `breg-mcp` and `breg-review` as binaries for Linux amd64, Linux arm64,
  and macOS arm64, and as the `ghcr.io/registrystack/breg-mcp` and
  `ghcr.io/registrystack/breg-review` images; the BReg installer does not
  install them. See [operate the citizen chat assistant](../operate/breg-mcp/).

{/* Evidence: release/scripts/release_roster.py, BREG_SERVICES_FIRST_RELEASE;
    crates/registry-breg-mcp/src/cli.rs, Command;
    crates/registry-breg-mcp/src/tools.rs;
    crates/registry-breg-mcp/src/inbound.rs;
    crates/registry-breg-mcp/src/outbound.rs;
    crates/registry-breg-mcp/clippy.toml;
    products/breg/MCP-GATEWAY.md. */}

- `breg-review` ships for the first time, a server-rendered review page beside the gateway. The
  citizen signs in with an authorization code and PKCE, reads the draft BReg
  holds under their own token, and submits it; the page holds no authority
  of its own. `breg-review check` validates the runtime configuration and
  resolves its secrets without opening a socket, and `breg-review serve`
  listens at its explicit private `listener.bind` and stops cleanly on SIGINT or
  SIGTERM. Its shared audit stream records the action, the
  `changeRequestId`, keyed `principalPseudonym` and `clientPseudonym`
  values, and the outcome, never a field value or token.

{/* Evidence: crates/registry-breg-review/src/lib.rs, command, check, and serve;
    crates/registry-platform-config/src/blocks.rs, PrivateListenerConfig;
    crates/registry-breg-review/src/signin.rs;
    crates/registry-breg-review/src/journal.rs;
    crates/registry-breg-review/tests/binary.rs;
    products/breg/MCP-GATEWAY.md. */}



- The VS Code and Zed integrations cover every maintained product, and the language server reads
  only `.yaml`, `.yml`, and `.json` product documents.

{/* Evidence: editors/vscode/package.json; crates/registry-language-server/src/products/mod.rs. */}

## v0.37.0 beta-49

- BREAKING: Base Registry Engine (BReg) refuses to compile a standing
  agent profile, one with `actorKind: agent` and no `taskGrant`, that
  holds `submit_request`,
  `revise_request`, `cancel_request`, or `apply_request`, with
  `access_profile.standing_agent.operation_forbidden`, or that holds
  `create` or `patch` on an entity without a `changeRequest`, or
  `import`, `tombstone`, or `batch` on any entity, with
  `access_profile.standing_agent.direct_mutation_forbidden`. A standing
  agent carries no human approval, so it may read and author
  change-request drafts while a human submits them; move the lifecycle
  operations to a profile the person uses directly.

{/* Evidence: crates/registry-breg/src/compiler.rs, validate_profiles and is_direct_target_mutation;
    crates/registry-breg/tests/standing_agent_ceiling.rs;
    products/breg/TASK_GRANTS.md. */}

- BREAKING: BReg refuses to compile a standing agent profile that holds an
  immediate-action permission, with
  `access_profile.standing_agent.action_forbidden`. An immediate action
  commits its effects at once, with no draft for the person to confirm, so
  a token carrying a trusted `act` no longer reaches any immediate action.
  Move the action permission to a profile the person uses directly.

{/* Evidence: crates/registry-breg/src/compiler.rs, expand_project_access;
    crates/registry-breg/tests/standing_agent_ceiling.rs;
    crates/registry-breg/src/api/tests/immediate_action_tests.rs;
    products/breg/TASK_GRANTS.md. */}

- BREAKING: BReg refuses to compile a module that contributes an access
  profile declaring a `taskGrant`, whether on an entity it adds or on one it
  extends, with `access_profile.task_grant.module_forbidden`. Task-grant
  ceilings are checked only where grants are authored, in project
  `accessProfiles`; declare the task-grant profile there.

{/* Evidence: crates/registry-breg/src/compiler.rs, validate_module_access_profile_task_grants;
    crates/registry-breg/tests/standing_agent_ceiling.rs, module_contributed_profiles_cannot_declare_a_task_grant;
    products/breg/TASK_GRANTS.md. */}

- BREAKING: BReg accepts an `act` claim of exactly `{sub, iss}` when `iss`
  equals the verified token issuer, as a token exchange writes it, beside
  exactly `{sub}`. A token whose `act.sub` is the trusted actor for its
  client is an agent token whatever its `registry_actor_kind` claim says,
  so it no longer satisfies a profile that declares `actorKind: human`.

{/* Evidence: crates/registry-breg/src/auth.rs, optional_actor_subject and authenticate;
    crates/registry-breg/tests/http_auth.rs;
    products/breg/TASK_GRANTS.md. */}

- BREAKING: BReg admits a token carrying a trusted `act` only on an access
  profile that declares `actorKind: agent`. A profile that declares no `actorKind` refuses such a
  token, so a delegated caller cannot borrow the operations of a profile
  written for people using BReg directly. Tokens without `act` are admitted
  as before.

{/* Evidence: crates/registry-breg/src/api/mod.rs, authorize_profile_claims;
    crates/registry-breg/src/api/actions.rs, authorize_action;
    crates/registry-breg/src/api/tests/change_request_action_tests.rs;
    crates/registry-breg/src/api/tests/immediate_action_tests.rs;
    products/breg/TASK_GRANTS.md. */}

- BReg's audit journal records the agent behind a delegated request. A
  request carrying a trusted `act` writes the shared `authorization` object
  on its refusal, mutation, and request lifecycle records, with actor kind
  `agent` and a keyed `actorPseudonym` scoped to the package revision beside
  the principal and client pseudonyms. The raw actor identifier is never
  stored, and task-grant records without `act` are unchanged.

{/* Evidence: crates/registry-breg/src/audit.rs, GrantAuditContext;
    crates/registry-breg/tests/postgres_task_grants.rs;
    products/breg/TASK_GRANTS.md. */}

- BReg's audit journal records delegated authority on reads. A read's
  terminal record, for records, lists, lookups, revisions, history, and
  snapshots, now carries the `authorization` object for a task-grant or
  delegated token. Direct tokens record no such object, as before.

{/* Evidence: crates/registry-breg/src/postgres/read.rs;
    crates/registry-breg/tests/postgres_task_grants.rs;
    products/breg/TASK_GRANTS.md. */}

- `registry-platform-ratelimit` is a new shared crate with two in-memory
  keyed limiters, `TokenBucketLimiter` and `FixedWindowCounter`, each capped
  at a fixed number of tracked keys. Evidence now uses it for its request
  budget and failed-selector counter with no change in behavior: the same
  refill, key cap, pruning, and refusals.

{/* Evidence: crates/registry-platform-ratelimit/src/lib.rs, MAX_TRACKED_KEYS;
    crates/registry-platform-ratelimit/src/token_bucket.rs, TokenBucketLimiter;
    crates/registry-platform-ratelimit/src/fixed_window.rs, FixedWindowCounter;
    crates/registry-evidence/src/rate_limit.rs. */}

- Platform crates gain token exchange, sign-in, and security header primitives.
  `ExchangeAuthorization::upstream` sends an optional actor token with an
  RFC 8693 exchange. `PrivateKeyJwt::redeem_authorization_code` redeems an
  authorization code with PKCE and the configured resource, and returns any
  ID token unverified. `CspBuilder::deny_by_default` starts a policy from
  `default-src 'none'`, and `with_form_action` and `with_style_src` add
  directives to it. `AuthorizationAuditEvent::without_purpose` builds an
  allowed or denied event for a product that records no purpose. The
  `test-authorization-server` feature of `registry-platform-testing` adds a
  local authorization server for authorization code, client credentials,
  and token exchange tests.

{/* Evidence: crates/registry-platform-httputil/src/client/exchange_authorization.rs, ExchangeAuthorization::upstream;
    crates/registry-platform-httputil/src/client/private_key_jwt.rs, redeem_authorization_code and RedeemedAuthorizationCode;
    crates/registry-platform-httpsec/src/server.rs, CspBuilder;
    crates/registry-platform-audit/src/authorization.rs, AuthorizationAuditEvent::without_purpose;
    crates/registry-platform-testing/src/authorization_server.rs, TestAuthorizationServer. */}

- BREAKING: a Base Registry Engine (BReg) record or query `400` names the member or parameter at
  fault in `fieldPath`, where it carried none before; `detail` and `code` are unchanged. A create
  body names `/data` or `/data/<apiName>`, a JSON Patch document names `/<n>` and its members, a
  batch body names `/items`, `/changeContext`, and each item's members, a malformed
  `Idempotency-Key` and a batch `If-Match` name the header, and a `query.invalid` refusal names the
  parameter. An unknown and a withheld name answer the same problem and are never echoed. The
  v0.37.0 Rust, Node.js, and Python BReg clients accept `fieldPath` on `request.invalid` and
  `query.invalid`; upgrade a client that rejects unfamiliar problem members with the runtime. See
  [Mutations](../reference/breg-api/#mutations).

{/* Evidence: crates/registry-breg/src/problem_location.rs, is_record_request_location() and
    is_query_parameter_location(); crates/registry-breg-client/src/client.rs,
    valid_record_request_problem_path() and BREG_QUERY_PARAMETERS. */}

- BREAKING: a BReg JSON Patch `test` of a field the grant does not let the caller read answers
  `400 request.invalid` at `/<n>/path` before the record is read, like a `test` of an unknown
  field, instead of a `404` or `412` first. Test only fields the grant lists in `readableFields`.
  A read path whose target entity has no permission entry in the caller's profile answers with the
  records the path grant authorizes instead of `503 source.unavailable`.

{/* Evidence: crates/registry-breg/src/mutation.rs, patch_location();
    crates/registry-breg/tests/postgres_client_relationships.rs,
    read_path_answers_when_the_profile_has_no_entry_for_its_target_entity. */}

- BREAKING: Registry Casework selects the source profile only by the `Registry-Source-Profile`
  header on decide and both attempt recovery routes. `DecideRequest` no longer carries
  `sourceProfileId`, `RecoverAttemptRequest` is a closed empty object, and a body that still sends
  `sourceProfileId` is refused with 422 `request.unprocessable`; the Rust, Node.js, and Python
  clients follow. `caseworkctl dev token` writes the `Registry-Casework-Profile` line into a profile
  client's header file, and a review inbox left empty only because that header is missing answers
  400 `source-profile.required`. See
  [Revisions, actions, and recovery](../reference/client-api/#revisions-actions-and-recovery).

{/* Evidence: crates/registry-casework-core/src/http.rs, DecideRequest and RecoverAttemptRequest;
    crates/registry-caseworkctl/src/dev/mod.rs, header_file();
    crates/registry-casework/tests/review_http.rs,
    an_inbox_emptied_only_by_the_missing_source_profile_says_so. */}

- BREAKING: every Casework mutating route parses its JSON body strictly: a duplicate object member at
  any depth, or a raw integer IEEE 754 binary64 cannot represent exactly, is refused with 422
  `request.unprocessable`, and a `Content-Type` that does not parse whole as `application/json` or
  `application/*+json` is refused with 415 `request.unsupported-media-type`. Send such an integer
  as a string.

{/* Evidence: crates/registry-casework/src/http.rs, StrictJson. */}

- Registry Casework refuses a zero or over-maximum page `limit` with the new closed problem code
  `request.limit-out-of-range`, and `ReviewTaskPage` carries a required `status`. A plain item,
  history, or clocks read across a moved source binding returns the retained item without actions
  instead of 409 `work-item.proposal-changed`. A source binding or policy field an adapter refuses
  is named by its key path. See [Problem codes](../reference/apis/registry-casework/#problem-codes).

{/* Evidence: crates/registry-casework-core/src/http.rs, REQUEST_LIMIT_OUT_OF_RANGE_PROBLEM;
    crates/registry-casework-core/src/review.rs, ReviewTaskPage;
    crates/registry-casework/src/service.rs, retained_without_actions();
    crates/registry-casework-breg/src/config.rs, validate_binding_input() and
    check_description_input(). */}

- Registry Scheduling starts a hold's time to live once its capacity transaction takes its locks,
  so a hold created under contention keeps its whole `holdPolicy.ttlMinutes`, and answers
  availability for a horizon or `start` past the last representable instant instead of panicking
  the request.

{/* Evidence: crates/registry-scheduling/src/service.rs, saturating_later();
    crates/registry-scheduling/tests/postgres_commitments.rs,
    a_hold_that_waited_for_the_supply_lock_keeps_its_whole_ttl and
    a_start_at_the_edge_of_representable_time_answers_instead_of_panicking. */}

## v0.36.0 beta-48

- BREAKING: Base Registry Engine (BReg) records every activation in a database ledger and ships
  unsigned, environment-neutral packages named by their package digest. Package signing is removed,
  so upgrade to v0.35.0 first: this release does not read a predecessor package without a
  `SHA256SUMS` envelope. `bregctl plan` and `bregctl status` report what an apply would change and
  what the database activated, and `bregctl apply` without `--initial` adopts a database an earlier
  release installed. `package.environment` and `package.instanceId` move to the runtime file's
  `identity`, `package.sequence` is removed, and the runtime `package` block keeps only `root` and
  `expectedDigest`. Every package's schema fingerprint changes, and a project that declared a
  package identity compiles to a new `registryRevision`, so rebuild each package with the v0.36.0
  `bregctl package`. In split-role mode, plan, apply, and startup refuse a runtime role that can
  write the ledger or the registry state. After upgrading BReg, re-import each BReg source into
  Evidence once and repin each BReg source in Casework. See
  [Upgrade in this order](../operate/advanced/upgrade-and-retire/#upgrade-in-this-order).

{/* Evidence: crates/registry-breg/src/migration.rs, package_ledger_entry(), adopt_verified_package(),
    and read_activation_status(); crates/registry-bregctl/src/apply_lifecycle.rs, plan() and status();
    crates/registry-breg/src/contract.rs, removed_project_field_diagnostics(). */}

- The shared audit writer recovers an active file whose final line a crash tore: the next start
  moves those bytes to the owner-only side file `<audit.path>.torn`, truncates to the last complete
  line, and logs it, instead of refusing to start. A configured `audit.path` ending in a companion
  suffix is refused. Evidence Gateway and Scheduling write operational logs to standard error, so a
  `stdout` audit destination carries audit entries alone, and `evidencectl audit show` reads
  histories with request-batch entries and names denials, transient failures, and earlier
  operations left without an outcome. See [Audit retention](../operate/retention-and-persistent-state/#audit-retention)
  and [Read and ship the Evidence Gateway audit log](../operate/evidence-audit/).

{/* Evidence: crates/registry-platform-audit/src/writer.rs, recover_torn_tail and
    reserved_companion_collision; crates/registry-evidence/src/main.rs, install_operational_logging;
    crates/registry-scheduling/src/main.rs, main; crates/registry-evidencectl/src/audit_view.rs,
    render_unreleased. */}

- BREAKING: `evidencectl` follows the shared ctl report and exit contract.
  Under `--format json` each command writes one object on standard output
  opening with `ok`, `command`, and `status`, all member names camelCase, and nothing
  on standard error; `command` replaces the former `operation` member, and
  fixture reports use `evaluatedCases`, `failingCase`, `expectedClass`, and
  `observedClass`. An unreadable file or a missing local dev session exits
  `3` instead of `1`. Commands that read one project take it as a positional
  `<project>`; the former `--project` flag stays accepted but hidden on them.
  `source import`, `source diff`, `source update`, and `target new` keep
  their documented `--project`, the `access` commands and `audit show` still
  act on the current directory, and `doctor` keeps its `--project` option.
  `test`
  and `fixtures run` accept `--format junit`, and `dev start --name-prefix`
  sets the local issuer container name prefix. Update scripts that read
  `operation` or snake_case fixture keys. See
  [evidencectl](../reference/evidencectl/#project-workflow).

{/* Evidence: crates/registry-evidencectl/src/report.rs, the exit constants, success(), refused(), and failure();
    crates/registry-evidencectl/src/junit.rs, render();
    crates/registry-evidencectl/src/dev.rs, StartArgs and issuer_label();
    crates/registry-evidencectl/tests/ctl_convention.rs, usage_errors_use_the_envelope_and_exit_two;
    crates/registry-evidencectl/tests/ctl_convention.rs, refusals_name_the_command_that_refused;
    crates/registry-evidencectl/tests/ctl_convention.rs, the_retired_project_flag_still_selects_the_project;
    crates/registry-evidencectl/tests/fixtures.rs, junit_output_carries_one_testcase_per_traced_case_on_stdout. */}

- BREAKING: Registry Casework activates a package in the database with
  `caseworkctl plan` and `caseworkctl apply`, recorded in an activation
  ledger, and `casework serve` only reads that activation. `casework migrate`
  and `caseworkctl db migrate` are removed and exit 2 naming the two
  commands. `runtime.yaml` requires `identity.databaseId`. In split-role mode,
  apply, plan, and startup refuse a runtime role that owns a Casework object,
  can create in the schema, or holds TRIGGER, and any trigger no Casework
  migration creates, naming the statement to run. Startup refuses a Base
  Registry Engine (BReg) source whose pinned `sourceRevision` differs from the
  registry revision it serves, and `caseworkctl check PROJECT --against-breg-package DIR`
  compares a pin with a closed BReg package before deployment. `plan` refuses
  a runtime role that cannot read the ledger, naming `caseworkctl apply`. A
  `caseworkctl dev` session created by this release connects with one
  database role. To upgrade, add `identity.databaseId`, repin each BReg
  source after upgrading BReg, then plan and apply once before starting the
  runtime; with split roles, a trigger an operator added to a Casework table
  blocks startup until it is dropped. See
  [plan, apply, and serve](../operate/casework/#plan-apply-and-serve).

{/* Evidence: crates/registry-casework/src/activation.rs, plan_activation() and
    apply_activation(); crates/registry-casework/src/runtime.rs,
    check_source_revisions(); crates/registry-caseworkctl/src/breg_package.rs,
    compare(); crates/registry-casework/tests/activation_postgres.rs. */}

- BREAKING: Registry Scheduling activates a package with `schedulingctl plan`
  and `schedulingctl apply`, recorded in an activation ledger, and
  `scheduling serve` writes no activation state. `scheduling migrate` is
  removed and exits 2 naming the two commands. `runtime.yaml` requires
  `identity.databaseId`. In split-role mode, plan, apply, and startup refuse a
  runtime role that owns a Scheduling object, can create in the schema, or
  holds TRIGGER, and any trigger attached to a `scheduling_*` table, naming
  the statement to run; apply never revokes TRIGGER itself. `plan` refuses a
  runtime role that cannot read the ledger, naming `schedulingctl apply`. To
  upgrade, add `identity.databaseId` and run `schedulingctl apply` once before
  starting the runtime; with split roles, a trigger an operator added to a
  Scheduling table blocks startup until it is dropped. See
  `products/scheduling/CHANGELOG.md`.

{/* Evidence: crates/registry-scheduling/src/store/activation.rs;
    crates/registry-schedulingctl/src/activation.rs;
    crates/registry-schedulingctl/tests/activation_postgres.rs. */}

- BREAKING: every `caseworkctl` and `schedulingctl` `--format json` report
  opens with `ok`, `command`, and `status`, in that order, as `evidencectl`
  reports do. `ok` is true exactly when the exit code is 0, and a failure
  without a report of its own names its exit class as `domain-refusal`,
  `usage-error`, or `operational-failure` with at least one diagnostic.
  `caseworkctl` reports move to `caseworkctl/v1alpha3`, and the
  `schedulingctl` records report's command is `records apply`. See
  `products/casework/CHANGELOG.md` and `products/scheduling/CHANGELOG.md`.

{/* Evidence: crates/registry-caseworkctl/src/report.rs;
    crates/registry-schedulingctl/src/report.rs;
    products/casework/contracts/cli/. */}

- `schedulingctl` is published as a release binary for `linux-amd64`, `linux-arm64`, and
  `macos-arm64`, like `caseworkctl`. The BReg, Casework, and Scheduling images each carry their
  operator tool beside the runtime, at `/usr/local/bin/bregctl`, `/usr/local/bin/caseworkctl`, and
  `/usr/local/bin/schedulingctl`, built from the same source. The entrypoint stays the runtime, so a
  serving container is unchanged; run `plan`, `apply`, and `status` from the image you serve by
  overriding the entrypoint, or from a Kubernetes Job `command:`. The Scheduling runtime stays an
  image-only artifact and has no installer. See
  [Activate from the image](../operate/breg/#activate-from-the-image) and
  [Run plan, apply, and status from the image](../operate/casework/#run-plan-apply-and-status-from-the-image).

{/* Evidence: release/docker/Dockerfile.breg; release/docker/Dockerfile.casework;
    release/docker/Dockerfile.scheduling; release/scripts/release_candidate.py,
    OPERATOR_TOOL_MINIMUM_VERSION and IMAGE_OPERATOR_TOOLS;
    release/scripts/merge-release-binary-shards.py, OPERATOR_TOOL_VERSION;
    release/scripts/merge-release-native-platform-shards.py, SCHEDULINGCTL_MINIMUM_VERSION. */}

## v0.35.0 beta-47

- BREAKING: Base Registry Engine (BReg) gives every `reference` field a btree
  index unless a declared index or a unique constraint without `when` already
  leads with it, and `bregctl check` reports `entity.list.unindexed_filter`
  and `entity.list.unindexed_sort` for a filterable or sortable list field no
  index leads with. The findings fail a check only under `--deny-findings`,
  so a pipeline that runs `bregctl check --deny-findings` fails until those
  fields are indexed. An upgraded engine refuses an active package whose
  project has a reference field no index
  leads with, because its compiler now derives a different schema: `doctor`
  reports `startup.package.refused` with `the package compiler derivation
  failed`. Build and apply a successor with the upgraded `bregctl` before
  starting the upgraded `breg`; the plan classes each new index as compatible
  additive, and its plain `CREATE INDEX` blocks writes to that table until the
  migration commits. See [indexes](../reference/breg-configuration/#indexes)
  and [deploy a registry](../operate/breg/#troubleshooting).

{/* Evidence: crates/registry-breg/src/compiler.rs, compile_entities() and unindexed_list_findings();
    crates/registry-breg/src/package.rs, rederive() and load_predecessor_package();
    crates/registry-breg/tests/reference_indexes.rs, every_reference_column_gets_a_btree_index_after_its_foreign_key;
    crates/registry-breg/tests/reference_indexes.rs, unindexed_list_filters_and_sorts_are_authoring_findings_at_the_declaring_field;
    crates/registry-breg/tests/postgres_reference_indexes.rs, a_successor_adds_reference_indexes_to_a_database_activated_without_them. */}

- BReg sessions name themselves in `pg_stat_activity`: `breg` for the runtime
  and `bregctl` for operator commands, unless the connection URL sets
  `application_name`. Runtime sessions carry
  `idle_in_transaction_session_timeout` of 120 seconds as a startup option, so
  PostgreSQL ends a session left idle inside an open transaction and the pool
  replaces it. Poolers must run in session mode; one that drops the startup
  options needs the bound set on the runtime role. See
  [set a PostgreSQL baseline](../operate/breg/#set-a-postgresql-baseline).

{/* Evidence: crates/registry-breg/src/postgres/config.rs, name_session() and with_idle_in_transaction_session_timeout();
    crates/registry-breg/src/startup.rs, SERVER_IDLE_IN_TRANSACTION_TIMEOUT;
    crates/registry-breg/tests/postgres_kernel.rs, runtime_sessions_are_named_and_bounded_across_recycling;
    crates/registry-breg/tests/postgres_kernel.rs, idle_in_transaction_bound_rolls_back_and_the_pool_recovers. */}

- BReg runtime sessions carry `jit=off` as a startup option placed before any
  options in the connection URL. Row-level security made the planner's cost
  estimate for a short filtered collection page cross the JIT thresholds, and
  compiling that plan took several times longer than running it. An operator
  who wants JIT back adds `-c jit=on` to the URL `options`. Poolers must run in
  session mode; one that drops the startup options needs `jit = off` set on the
  runtime role. See
  [set a PostgreSQL baseline](../operate/breg/#set-a-postgresql-baseline).

{/* Evidence: crates/registry-breg/src/postgres/config.rs, with_jit_disabled() and
    jit_is_disabled_before_operator_options_so_an_operator_can_enable_it;
    crates/registry-breg/src/startup.rs, prepare_database_startup();
    crates/registry-breg/tests/postgres_startup.rs,
    prepared_server_sessions_are_named_bounded_and_pg_stat_statements_stays_unavailable_until_preloaded. */}

- `breg` logs, and `bregctl doctor` reports under a new `advisories` list,
  value-free PostgreSQL advisories: the connection numbers one replica's pool
  is compared with, a warning when that pool may take more than half of the
  usable connections, warnings when `autovacuum` or `track_counts` is off,
  and a note when `pg_stat_statements` is not installed or not loaded through
  `shared_preload_libraries`. Advisories never refuse startup or change
  `doctor`'s exit status, and need no extra grant.
  See [deploy a registry](../operate/breg/#activate-and-serve).

{/* Evidence: crates/registry-breg/src/postgres/baseline.rs, advise() and connection_budget();
    crates/registry-breg/src/startup.rs, OperationalEvent::PostgresBaselineAdvisory;
    crates/registry-bregctl/src/lib.rs, write_doctor_success();
    crates/registry-bregctl/src/lib.rs, doctor_reports_postgres_advisories_after_the_passing_checks_without_failing;
    crates/registry-breg/tests/postgres_startup.rs, prepared_server_sessions_are_named_bounded_and_pg_stat_statements_stays_unavailable_until_preloaded. */}

- Breaking audit change: all six runtimes use the shared per-process file or stdout writer.
  Documented rotation, retention, shipping to append-only storage, and the mutation crash gap.
  Removed procedures for the retired audit verification, export, and prune commands. See
  [Base Registry Engine audit retention](../operate/breg-retention/#keep-the-audit-journal),
  [Evidence audit](../operate/evidence-audit/), and
  [audit upgrades](../operate/retention-and-persistent-state/#upgrade-casework-and-scheduling-audit).

- BREAKING: published Base Registry Engine packages now carry the shared
  `SHA256SUMS` envelope. `bregctl package` reports its `packageDigest` and can
  add a hash-covered `REVISION` with `--revision`. `breg` verifies every listed
  file at startup in addition to the existing BReg signatures and deployment
  bindings, and `package.expectedDigest` can pin the shared digest. Rebuild old
  package directories with `bregctl package` before starting this version.

{/* Evidence: crates/registry-breg/src/package.rs, PreparedPackage::publish_to_directory_with_revision;
    crates/registry-breg/src/runtime_config.rs, RuntimeConfig::verify_package_envelope;
    crates/registry-breg/tests/runtime_config.rs, shared_package_envelope_and_pin_are_checked_before_startup. */}

- BREAKING: `evidencectl package` now publishes one environment-neutral package
  directory with `SHA256SUMS` and an optional hash-covered `REVISION`; it no
  longer copies `runtime.yaml` into the output. Evidence Gateway verifies every
  listed file at startup and `package.expectedDigest` pins the package digest.
  The separate Evidence bundle and runtime revisions are removed, while each
  requirement's package-derived `configurationRevision` remains. The retired
  `evidencectl build` spelling is refused with `evidencectl package` as the fix.

{/* Evidence: crates/registry-evidence/src/bundle.rs, DeploymentInputs::load;
    crates/registry-evidencectl/src/build.rs, run_package_with_format;
    crates/registry-evidencectl/src/authoring.rs, write_bundle. */}

- `evidence check --require-runtime-dependencies` and `evidence serve` name
  the fault that stopped a Transit signer from initializing, after the
  unchanged `evidence: runtime signing initialization failed:` prefix: no
  answer on the Unix socket, a refused key read, a provider server error such
  as a sealed provider, a malformed response, a key whose custody is unsafe, a
  `keyVersion` above the key's `latest_version` or below its
  `min_encryption_version`, a public key that is not the governed one, or a
  failed self-test. No cause carries a path, provider response, or key
  material. See
  [activate the new version](../tutorials/rotate-evidence-signing-keys/#activate-the-new-version).

{/* Evidence: crates/registry-evidence/src/runtime.rs, SigningInitializationFault::cause();
    crates/registry-platform-crypto/src/lib.rs, TransitInitializationError and transit_signer_initialization_names_the_fault_it_met;
    crates/registry-evidence/src/runtime_tests.rs, signing_initialization_faults_name_distinct_causes. */}

- An Evidence access-token issuer that serves its key set under a private
  certificate authority can be trusted through a named `tlsTrustProfile` on
  the bundle's `authentication` block, bound in `runtime.yaml` exactly like a
  source's profile. The CA is trusted beside the system roots for the
  `jwksUri` connection alone, hostname verification stays on, and a local
  HTTP `jwksUri` cannot name a profile. A profile bound on one side only is
  refused, and `evidence check --require-runtime-dependencies` fetches the key
  set through it before the listener binds. See
  [an issuer behind a private CA](../configure/evidence/#an-issuer-behind-a-private-ca).

{/* Evidence: crates/registry-evidence/src/runtime.rs, issuer_trust_roots();
    crates/registry-evidence/src/bundle.rs, the_issuer_trust_profile_is_bound_exactly_like_a_source_profile;
    crates/registry-evidence/src/config.rs, an_issuer_trust_profile_is_a_local_id_for_an_https_key_set_only;
    crates/registry-evidence/tests/cli.rs, dependency_check_trusts_a_private_ca_issuer_only_through_its_named_profile;
    crates/registry-platform-httputil/src/lib.rs, a_pinned_get_trusts_a_private_ca_only_when_it_is_named. */}

- `evidencectl doctor --runtime-config <file> --without-audit-lock`, and the
  runtime's `evidence check --require-runtime-dependencies
  --without-audit-lock`, check a candidate staged beside the Evidence instance
  it will replace. Without the option the check opens the audit destination as
  startup does, so it refuses while that instance holds the destination's
  single-writer lock, and the refusal now names the option. With it, the audit
  hash key is checked as startup checks it, and the audit directory and files
  are checked for ownership, mode, write access, and a complete final entry,
  without taking the lock. A second writer is not detected; the JSON
  `proofBoundary` says so. See
  [evidencectl](../reference/evidencectl/#project-workflow).

{/* Evidence: crates/registry-platform-audit/src/writer.rs, FileDestination::check_writable();
    crates/registry-evidence/src/runtime.rs, assemble() and check_dependencies_without_audit_lock();
    crates/registry-evidence/src/audit.rs, EvidenceAuditLog::preflight();
    crates/registry-evidencectl/src/runtime.rs, the_lock_free_form_states_its_own_proof_boundary;
    crates/registry-evidence/tests/cli.rs, dependency_check_without_the_audit_lock_passes_beside_a_running_writer. */}

- BREAKING: `evidencectl` refuses a derivation whose `answer` reads a fact
  its question's source does not declare, as
  `evidence.authoring.derivation-fact-undeclared` against the derivation
  file. The declared facts are an inline operation's `source.facts[].name`,
  or the properties of a referenced source's closed `factSchema`. `check`,
  `test`, `package`, `source diff`, and `source update` all refuse, as do the
  compatibility spellings `fixtures run` and `build`, so a Base Registry
  Engine (BReg) field rename that a derivation still reads under its old name
  is refused before `source update` installs it or a candidate is packaged.
  The check reads the project, not the running registry: a field renamed in a
  registry that already serves a deployed candidate still fails every request
  that reads it while `/ready` reports ready, so change the registry and
  deploy the rebuilt candidate together. Only literal reads such as
  `facts["status"]` and `facts.status` are checked, and a `??` fallback
  between names passes when any of them is declared. See
  [evidencectl](../reference/evidencectl/#project-workflow).

{/* Evidence: crates/registry-evidence-authoring/src/derivation.rs, validate_answer_fact_reads();
    crates/registry-evidencectl/src/authoring.rs, declared_fact_names() and read_inputs();
    crates/registry-evidence-authoring/tests/derivation_fact_reads.rs;
    crates/registry-evidencectl/src/source_cli.rs, diff_and_apply_refuse_a_next_fact_schema_that_drops_a_fact_a_derivation_reads;
    products/breg/evidence/tests/verify-composition.py, verify(). */}

- BREAKING: `bregctl test --baseline-runtime-config` rehearses the successor
  migration before it writes a receipt. It rebuilds the active package's
  schema from its signed sources on the disposable test database, runs the
  migration in apply order, requires the candidate schema, and rolls back.
  A plan that used to fail only at `apply` now fails `test`, so `package`
  cannot sign it, and a predecessor this `bregctl` cannot rebuild is refused
  as `migration.rehearsal.baseline_unavailable` or
  `migration.rehearsal.baseline_not_reproducible`. The rehearsal runs over
  empty tables, so it does not prove data-dependent steps. A failure reports
  the SQLSTATE and the object names, never the PostgreSQL message. See
  [what `test` rehearses](../operate/breg-changes/#what-test-rehearses).

{/* Evidence: crates/registry-breg/src/postgres/rehearsal.rs;
    crates/registry-bregctl/src/test_lifecycle.rs;
    crates/registry-breg/tests/postgres_migration.rs, real_postgres_rehearsal_refuses_a_reviewed_plan_activation_would_refuse. */}

- BREAKING: when PostgreSQL refuses a statement after `bregctl apply` began
  maintenance, the report is `apply.migration.statement_failed` instead of
  `apply.migration.failed`, and its message names the SQLSTATE, its class,
  and the table, column, or constraint PostgreSQL reported, never the
  PostgreSQL message or a stored value. `registry-breg` reports it as
  `MigrationError::StatementFailed`, from the new
  `PostgresKernelError::Statement` variant, so an exhaustive match on either
  enum needs the new arm; `PostgresFailure` is exported from
  `registry_breg::postgres` under every feature set. A lost connection,
  including a session the server ended (SQLSTATE class 08, 57P01 to 57P05,
  25P03), still reports `apply.migration.failed`, while a compiler or
  reviewed statement that times out is a refused statement with SQLSTATE
  57014. The target stays pinned as before. See
  [troubleshooting](../operate/breg-changes/#troubleshooting).

{/* Evidence: crates/registry-breg/src/postgres/mod.rs, PostgresKernelError::from_statement_error(), a_server_ended_session_is_a_connection_failure_not_a_refused_statement;
    crates/registry-breg/src/migration.rs, MigrationError::StatementFailed;
    crates/registry-bregctl/src/lib.rs, apply_reports_a_refused_statement_with_its_sqlstate_and_objects;
    crates/registry-breg/tests/postgres_migration.rs, refused_step_reports_its_sqlstate. */}

- BREAKING: `bregctl history rebaseline` no longer refuses a registry holding
  more than 1,000 live rows. It verifies every live row against its journal
  head in pages of 1,000 inside one transaction, so a registry of any size
  can regain snapshot coverage after an erasure. The codes
  `history.rebaseline.live_rows.budget_exceeded` and
  `field_encryption.erase_history.rebaseline.live_rows_budget_exceeded` are
  gone, and so are `HistoryRebaselineError::LiveRowBudgetExceeded` and
  `MAX_REBASELINE_LIVE_ROWS` in `registry-breg`. The run holds every entity
  table exclusively, reads included, until it commits, so a larger registry
  means a longer read and write outage: size a maintenance window from a
  rehearsal. See
  [restore snapshot coverage after an erasure](../operate/breg-retention/#restore-snapshot-coverage-after-an-erasure).

{/* Evidence: crates/registry-breg/src/history_migration.rs, verify_every_live_row_matches_its_journal_head();
    crates/registry-breg/tests/postgres_history_rebaseline.rs, rebaseline_refuses_a_mismatch_on_a_later_page. */}

- Raising a `text` field's `maxLength` is a compatible additive change,
  `field_length_widened`, applied live: the successor replaces the column's
  length check and validates the stored rows, with no reviewed migration.
  Revisions recorded under the lower limit stay readable, and an action over
  the entity stays additive as `action_target_fields_widened`. A `string`
  field's `maxLength` is its column type, so raising it still needs a
  reviewed migration. See
  [review and apply changes](../operate/breg-changes/#test-and-package-the-successor).

{/* Evidence: crates/registry-breg/src/package.rs, CompiledRegistryChangeCode::FieldLengthWidened;
    crates/registry-breg/src/generated_ddl.rs, replace_length_check_statement();
    crates/registry-breg/tests/package_change_plan.rs, text_length_widening_is_additive_and_replaces_the_length_check;
    crates/registry-breg/tests/action_vocabulary_codes.rs, a_raised_text_limit_on_a_targeted_entity_keeps_the_action_contracts;
    crates/registry-breg/tests/postgres_compiled_schema.rs, text_length_widening_replaces_the_length_check_and_keeps_existing_rows. */}

- Lowering a `string` field's `minLength` under the same `maxLength` is also
  `field_length_widened`, applied live: the successor replaces the column's
  minimum check, or drops it when the minimum falls to 0, with no reviewed
  migration. Revisions recorded under the higher minimum stay readable, and an
  action over the entity stays additive. Raising a `minLength`, changing a
  `string` field's `maxLength`, and widening a `decimal` still need a reviewed
  migration. See
  [review and apply changes](../operate/breg-changes/#test-and-package-the-successor).

{/* Evidence: crates/registry-breg/src/contract.rs, FieldTypeSource::lowers_string_min_length_of();
    crates/registry-breg/src/generated_ddl.rs, replace_length_check_statement();
    crates/registry-breg/tests/package_change_plan.rs, string_minimum_lowering_is_additive_and_replaces_or_drops_the_length_check;
    crates/registry-breg/tests/action_vocabulary_codes.rs, a_lowered_string_minimum_on_a_targeted_entity_keeps_the_action_contracts;
    crates/registry-breg/tests/postgres_compiled_schema.rs, string_minimum_lowering_replaces_or_drops_the_length_check_and_keeps_existing_rows. */}

- `bregctl diff` reports every removed field or entity as
  `diff.history.removed_values_retained`. Removing one from the package drops
  the live column or table, but the values stay in every revision snapshot
  recorded before the change and in every database backup; only
  `bregctl history erase` removes them, whole revisions of one record at a
  time. See
  [review and apply changes](../operate/breg-changes/#compare-the-candidate-with-the-active-package).

{/* Evidence: crates/registry-bregctl/src/lib.rs, removed_value_findings();
    crates/registry-bregctl/tests/diff.rs, a_removed_field_is_reported_as_retained_in_history_not_erased. */}

- BREAKING: a reviewed `chunked_backfill` step now appends one history
  revision for every row each chunk changes, in the same commit as the chunk,
  so snapshot and as-of reads agree with the backfilled rows. Its `chunkSize`
  cap falls from 10,000 to 1,000, and its SQL must be a single `UPDATE` of the declared
  entity that names no record metadata column, uses no Unicode-escape
  identifier or string, and names no other statement word outside comments
  and plain string literals; the journal also refuses a step that changed
  `created_at` or `updated_at`. A plan outside those limits that `test` and `package`
  used to accept is now refused, and `test` reports a journaled step whose
  SQL the history journal refuses as
  `migration.rehearsal.history_step_refused`. See
  [reviewed migration files](../operate/breg-changes/#reviewed-migration-files).

{/* Evidence: crates/registry-breg/src/history_migration.rs, check_reviewed_history_step(), a_reviewed_step_that_changes_any_record_metadata_is_detected;
    crates/registry-breg/src/postgres/interlock.rs, execute_reviewed_chunk();
    crates/registry-breg/src/migration_plan.rs, MAX_CHUNK_SIZE;
    crates/registry-breg/tests/migration_plan.rs, reviewed_chunked_backfill_refuses_a_chunk_size_beyond_the_commit_budget;
    crates/registry-breg/tests/postgres_migration.rs, reviewed_migration_history(). */}

- Base Registry Engine (BReg) reports an accepted review whose result lookup
  answers an empty `404` as `recovery.code: result-unknown-to-authority`
  instead of leaving the code empty. The result poller serves a review that has a pending webhook
  completion first and one its authority no longer knows last, and a pending
  completion makes its review due at once. The new
  `bregctl review-recovery resubmit` submits the exact retained review
  request again under its original idempotency key, and
  `bregctl review-recovery close` stops waiting on a review the authority will
  never answer, reporting `operator-closed`. See
  [operate Base Registry Engine](../operate/breg/#resubmit-or-close-a-review-the-authority-lost).

{/* Evidence: crates/registry-breg/src/review_store.rs, poll_one_result and receive_completion;
    crates/registry-breg/src/review_recovery.rs;
    crates/registry-breg/tests/postgres_review_executor.rs, a_live_review_is_polled_before_one_its_authority_does_not_know and a_webhook_completion_makes_its_review_due_and_first_in_the_poll_queue;
    crates/registry-breg/tests/postgres_change_requests.rs, an_operator_resubmits_or_closes_a_review_its_authority_lost. */}

- BREAKING: Evidence Gateway reads `runtime.yaml` through the shared
  runtime configuration loader and declares its access-token issuer and
  audit key through the shared blocks. The runtime file now opens with
  `apiVersion: registry.registrystack.org/evidence-runtime/v1alpha1` and
  `kind: EvidenceRuntimeConfig` instead of `version: 1`;
  `bundleDirectory` is `package.root`, with an optional
  `package.expectedDigest` pin; and `listener.bindHost` with
  `listener.port` is one `listener.bind: host:port` value, as it is for
  `metricsListener`. `secretProviders.environment: {}` enables
  `secret:env/NAME` references beside `secret:file/name`, and runtime string
  values accept `${VAR}` outside secret references and `secretProviders`,
  while a `${...}` expression in the governed bundle is refused with the
  field that holds it.
  In the governed bundle, the flat `authentication` fields move under
  `authentication.oidc`, `kind: oidc-access-token` is dropped, the one-entry
  `audiences` list is a single `audience`, `jwksUri` is
  `jwksSource: {kind: uri, uri: ...}`, and `audit.hashSecretRef` is
  `audit.hashKeyRef`; `audit.hashKeyVersion` is unchanged. Every subcommand
  that reads the runtime file takes the required
  `--runtime-config FILE` after the subcommand; the global `--runtime`
  flag, the `REGISTRY_EVIDENCE_RUNTIME` variable, and the default path are
  gone, and the container image passes the flag in its default command. A
  removed key, flag, or variable is refused with the name of its
  replacement. To migrate, rewrite the project's `governance.yaml` and
  `runtime.yaml` with the new keys, rebuild the candidate with the matching
  `evidencectl`, and replace `--runtime FILE` with
  `<subcommand> --runtime-config FILE` in service definitions. See
  [configure Evidence Gateway](../configure/evidence/#the-runtime-file).

{/* Evidence: crates/registry-evidence/src/config.rs, EVIDENCE_RUNTIME_REMOVED_KEYS,
    every_removed_runtime_key_is_refused_with_its_replacement_named,
    every_removed_bundle_authentication_and_audit_key_is_refused_with_its_replacement_named,
    environment_substitution_fills_values_and_never_a_secret_reference and
    the_environment_secret_provider_is_enabled_only_by_declaration and
    an_authored_bundle_carrying_an_environment_expression_is_refused;
    crates/registry-evidence/tests/cli.rs, the_removed_runtime_inputs_are_refused_with_their_replacement_named;
    release/docker/Dockerfile.evidence. */}

- BREAKING: Registry Casework reads `runtime.yaml` through the shared
  runtime configuration loader and declares its secret providers, database,
  listener bind, OpenID Connect issuer and clients, and audit key through the
  shared blocks. The runtime file may not pass through a symbolic link and is
  at most 1 MiB. `${VAR}`, `${VAR:-default}`, and `${VAR:?message}` are
  substituted in string values after parsing; an expression in a field ending
  in `Ref` or under `secretProviders` is refused, and one in `casework.yaml`
  is refused by the runtime and by `caseworkctl check`. `listener.bind` is
  required. `authentication.oidc.issuer` must be an `https` URL without
  credentials, query, or fragment, with plain `http` accepted only on an IPv4
  loopback host under `development-loopback`, and `audience` is at most 512
  characters. Under `operator-controlled-upstream`,
  `authentication.oidc.allowedClients` must name at least one client, because
  an empty list admits every client the issuer verifies;
  `development-loopback` still accepts an empty list.
  `authentication.oidc.jwksUri` is removed: declare `jwksSource`
  with `kind: uri` and the same URL as `uri`. `audit.hashKeyRef` must be an
  exact secret reference. To migrate, add `listener.bind` if it was omitted,
  list the admitted clients in `allowedClients` for a production deployment,
  replace `jwksUri`, and move any environment expression out of
  `casework.yaml`. See
  [configure the runtime](../operate/casework/).

{/* Evidence: crates/registry-casework/src/config.rs, the_runtime_configuration_is_read_through_the_shared_loader,
    a_removed_jwks_uri_names_its_replacement, the_oidc_issuer_and_clients_are_the_shared_blocks,
    production_names_its_allowed_clients_while_loopback_may_leave_them_empty,
    environment_expressions_substitute_values_but_never_secret_references and
    an_authored_project_carrying_an_environment_expression_is_refused;
    crates/registry-caseworkctl/src/lib.rs, removed_runtime_keys_name_the_replacement_path_and_action and
    check_refuses_an_environment_expression_in_the_authored_project. */}

- BREAKING: Base Registry Engine reads `runtime.yaml` through the shared
  runtime configuration loader and declares its OpenID Connect issuer, audit
  key, listeners, and secret providers through the shared blocks. `breg`
  takes the runtime file as `--runtime-config FILE`; `--config` is refused
  with the replacement named, `bregctl request-retention cleanup-attachments`
  no longer accepts its `--config` alias, and the container image passes the
  new flag in its default command. `${VAR}`, `${VAR:-default}`, and
  `${VAR:?message}` are substituted in string values after parsing, so a
  substituted value is always text and never a number, boolean, or YAML
  structure; a `${...}` expression in a field ending in `Ref` or under
  `secretProviders` is refused as
  `runtime_config.substitution_in_reference`, and one in the authored project
  or module files is refused as `source.environment_expression`. An empty
  YAML scalar is now null rather than an empty string, so quote `""` where an
  empty string is meant. `authentication.oidc.issuer` must be an `https` URL
  without credentials, query, or fragment, with plain `http` accepted only on
  an IPv4 loopback host, `audience` is at most 512 characters, and `jwksSource`
  gains `kind: uri` beside `discovery` and `static`. A file missing
  `apiVersion` or `kind` is refused as `runtime_config.invalid_api_version`
  or `runtime_config.invalid_kind`. To migrate, replace `--config FILE` with
  `--runtime-config FILE` in service definitions and write any number or
  boolean that came from a variable directly in the file. See
  [deploy a registry](../operate/breg/#write-the-runtime-configuration).

{/* Evidence: crates/registry-breg/src/runtime_config.rs, parse_runtime_config_with_env and runtime_config_error_from_loader;
    crates/registry-breg/src/cli.rs, removed_config_flag;
    crates/registry-breg/src/contract.rs, reject_authored_environment_expression;
    crates/registry-breg/tests/runtime_config.rs, a_substitution_inside_a_secret_reference_is_refused,
    substituted_values_stay_strings, a_substituted_value_cannot_inject_document_structure,
    oidc_issuer_and_audience_follow_the_shared_issuer_block and
    jwks_source_uri_kind_skips_discovery_under_the_shared_rules;
    crates/registry-breg/tests/compiler_contract.rs, an_authored_project_carrying_an_environment_expression_is_refused;
    release/docker/Dockerfile.breg. */}

- BREAKING: Registry Relay reads `runtime.yaml` through the shared
  runtime configuration loader. The file now opens with
  `apiVersion: registry.registrystack.org/relay-runtime/v1alpha1` and
  `kind: RelayRuntimeConfig`; `server.bind` is `listener.bind`,
  `packagePath` is an absolute `package.root` with an optional
  `package.expectedDigest` pin, and `authentication.issuer` is `authentication.oidc`
  with `issuer` and a `jwksSource` of `kind: discovery` or `kind: uri`. A
  `secret:file/` reference resolves under the declared
  `secretProviders.file.root` instead of beside the runtime file, and
  `secret:env/` needs `secretProviders.environment`. `relay check` and
  `relay serve` take the required absolute `--runtime-config FILE`; the
  `--runtime` flag, the `RELAY_RUNTIME` variable, and the default path are
  gone. A removed key is refused with the name of its replacement, and an
  environment expression such as `${VAR}` in the authored `registry.yaml`
  is refused as `contract.environment_expression`. See
  [operate Registry Relay](../operate/relay/#bind-deployment-inputs-without-editing-the-package).

{/* Evidence: crates/registry-relay-v2/src/contract.rs, RELAY_REMOVED_RUNTIME_KEYS and
    removed_runtime_keys_are_refused_with_their_replacement;
    crates/registry-relay-v2/src/cli.rs, the_runtime_configuration_is_named_explicitly_on_every_command;
    crates/registry-relay-v2/src/contract.rs, an_authored_contract_carrying_an_environment_expression_is_refused;
    release/docker/Dockerfile.relay. */}

- BREAKING: Registry Discovery reads `runtime.yaml` through the shared
  runtime configuration loader. The file now opens with
  `apiVersion: registry.registrystack.org/discovery-runtime/v1alpha1` and
  `kind: DiscoveryRuntimeConfig` instead of `schemaVersion`, and
  `listener.address` is `listener.bind`. The binary takes
  `--runtime-config FILE`, an absolute path free of symbolic links, in
  place of `--runtime`, and the container image passes it in its default
  command. A removed key is refused with the name of its replacement. See
  [configure Registry Discovery](../configure/discovery/#deploy-and-restart-the-service).

{/* Evidence: crates/registry-discovery/src/startup.rs, load_runtime() and
    removed_runtime_keys_name_their_replacements;
    release/docker/Dockerfile.discovery. */}

- BREAKING: Registry Render reads `runtime.yaml` through the shared
  runtime configuration loader. The file now opens with
  `apiVersion: registry.registrystack.org/render-runtime/v1alpha1` and
  `kind: RenderRuntimeConfig`; `server.bind` is `listener.bind` and is
  required, `server.shutdownGraceSeconds` is
  `listener.shutdownGraceSeconds`, `bundle.path` is `package.root`, and
  secret providers are declared under `secretProviders`. Paths, including
  `audit.path`, must be absolute, and a removed key, among them
  `audit.directory`, `audit.integrityKeyRef`, and `audit.maxSegmentBytes`,
  is refused with the name of its replacement. `serve`, `healthcheck`, and
  `check` take `--runtime-config FILE`, and none reads a default
  path or the `REGISTRY_RENDER_RUNTIME` variable. An environment
  expression such as `${VAR}` in the authored bundle `manifest.yaml` is
  refused with the field that holds it. See
  [run Registry Render in serve mode](../operate/registry-render/).

{/* Evidence: crates/registry-render/src/runtime.rs, RENDER_REMOVED_KEYS and load();
    crates/registry-render/src/cli.rs, Command::Serve;
    crates/registry-render/src/runtime.rs, removed_keys_name_their_replacements;
    crates/registry-render/src/manifest.rs, an_authored_manifest_carrying_an_environment_expression_is_refused. */}

- BREAKING: Registry Scheduling reads `runtime.yaml` through the shared
  runtime configuration loader. `authentication.oidc.jwksUri` is removed
  and refused with the name of its replacement, a `jwksSource` of
  `kind: uri`; `listener.bind` is required and no longer defaults to a
  loopback port; the file and every configured path are refused when they
  pass through a symbolic link; and an environment expression such as
  `${VAR}` in the authored `scheduling.yaml`, records, or fixtures is
  refused with the field that holds it. `runtime.yaml` string values
  accept `${VAR}` outside `*Ref` fields and `secretProviders`, and an optional
  `package.expectedDigest` pins the policy the runtime starts on.

{/* Evidence: crates/registry-scheduling/src/config.rs, SCHEDULING_REMOVED_KEYS and
    a_removed_jwks_uri_names_its_replacement; products/scheduling/RUNTIME-CONFIG.md. */}

- Base Registry Engine (BReg) adds the `import` operation and import authorities, so a governed
  entity can take a bulk load without granting `batch`, `create`, or `patch`
  to a direct-write profile. `import` is create-only, is served only through
  ingestion runs, and is not a direct write for change control, so
  `change_control.direct_write_grant` accepts it on a controlled entity. An
  import run is created only inside an open import authority that an operator
  opens with `bregctl import-authority open` for one entity and one profile,
  with a window of at most 30 days, a maximum item count, and optional pinned
  input digests. Every chunk counts against the authority; closing it, its
  expiry, its exhaustion, or a successor package activation stops the run with
  `blockedReason` `importAuthorityClosed`. Opening, closing, expiry,
  exhaustion, and supersession each append an audit record, and every run
  audit record carries `importAuthorityId`. The compiler refuses `import`
  without entity batch bounds (`import.batch_bounds.required`), without an
  authenticated principal (`import.principal.required`), and beside a `batch`
  grant on the same entity (`import.batch.redundant`). `bregctl data
  validate` reports the source's `inputDigest` for pinning; the digest is a
  label the client announces with the run and the server records, never
  recomputed over the written items. The runtime
  installs a new internal table and a run column on its next apply. See
  [load a governed entity through an import window](../operate/breg-data/#load-a-governed-entity-through-an-import-window).

- BREAKING: the ingestion-run `blockedReason` gains the value
  `importAuthorityClosed`, and the Rust `BRegIngestionBlockedReason` enum
  gains `ImportAuthorityClosed`; a client that matched the only previous value
  exhaustively must handle the new one. The attempt that blocks a run on its
  authority is recorded as `lastAttempt.outcome` `importAuthorityClosed`, not
  `bindingChanged`, so the Rust `BRegIngestionAttemptOutcome` enum and the
  Node.js `BRegIngestionAttemptOutcome` type gain the same value. The `ingestion.run_blocked` problem
  detail now reads "The ingestion run is blocked and refuses further chunks."
  because the run's `blockedReason`, not the detail, names the cause.

- BREAKING: `bregctl data import` reports a run creation the server refuses
  with `412` as `data.import.ingestion_run.import_authority_required` when the
  grant is `import`, and `data.import.ingestion_run.precondition_failed`
  otherwise, instead of `data.import.operation.refused`. A blocked run reports
  `data.import.ingestion_run.import_authority_closed` or
  `data.import.ingestion_run.blocked` with its reason.

{/* Evidence: crates/registry-breg/src/import_authority.rs, admit_run() and admit_chunk();
    crates/registry-breg/src/compiler.rs, import checks;
    crates/registry-breg/tests/postgres_import_authority.rs;
    crates/registry-breg/tests/import_grant_compiler.rs;
    crates/registry-bregctl/src/import_authority_lifecycle.rs;
    crates/registry-bregctl/src/data_lifecycle.rs, a_run_blocked_by_its_import_authority_names_that_reason. */}

- BREAKING: the Base Registry Engine runtime refuses to serve a database that
  is not the one its instance claim names. The claim records the PostgreSQL
  system identifier and database object identifier at the first apply, so a
  logically restored copy (`pg_dump` and `pg_restore`) or a registry moved by
  `pg_upgrade` no longer starts: `breg` refuses with the new `StartupError`
  variant `InstanceClaimMismatch`, `GET /ready` answers `503`, and
  `bregctl doctor` reports `startup.instance_claim.mismatch`. This keeps a
  restored copy from serving beside its original as a divergent writer of
  the same registry. Once the original is stopped for good, the new command
  `bregctl instance-claim adopt --acknowledge-original-retired` moves the
  claim to the copy with a raised epoch and, once that commits, appends an
  audit entry naming the previous and the adopted claim;
  `bregctl instance-claim status` reports whether the claim matches. A
  physical copy (base backup, point-in-time recovery, snapshot, or promoted
  replica) keeps its identity and is not refused. The claim is recorded only
  into a fresh database, one with no committed revision and no commit head,
  so an existing registry
  records none when its next apply installs the new internal table: run
  `instance-claim adopt` once after that apply, before starting the server.
  Adopting also supersedes every open import authority, with its own audit
  record, so a restored backup brings no authority back. On a managed
  PostgreSQL service that withholds `pg_control_system()`, the claim compares
  the database object identifier alone. The claim is checked at startup and
  on readiness, not per request. A Rust `match` over `StartupError` must
  handle the new variant. See
  [back up and restore the database](../operate/breg-changes/#back-up-and-restore-the-database).

{/* Evidence: release/notes/v0.35.0.md. */}

## v0.34.0 beta-46

- `bregctl apply` reports a migration database it could not reach, or an
  apply lock another session held past the lock timeout, before maintenance
  began as `apply.database.unavailable`, with the suggested action
  `verify_migration_authority`, instead of `apply.migration.failed`. Nothing
  was changed, so the message says to retry the same apply once the database
  is reachable rather than to reconcile. The same holds when confirming an
  already-active package. A failure after maintenance began still reports
  `apply.migration.failed`. A reachable database that has never been
  activated, such as a first apply run without `--initial`, is not
  unavailable: it reports `apply.package.active_mismatch`, whose message now
  names `--initial`. See
  [review and apply changes](../operate/breg-changes/#troubleshooting).

{/* Evidence: release/notes/v0.34.0.md. */}

- `bregctl apply` treats the already-active package as a no-op, so a repeated
  deploy exits 0 with `activation: already_active` and changes nothing. The
  package is verified in full as the configured active package, and the
  database must record exactly that package (revision digest, schema
  fingerprint, sequence, and deployment identity) as active with no
  maintenance pending; otherwise `apply` refuses with
  `apply.package.active_mismatch`. A different package at the active sequence
  still refuses. Package binding refusals now report
  `apply.package.binding_mismatch` with the differing runtime key as the
  diagnostic path, such as `identity.databaseId` or `package.activeSequence`,
  instead of the generic `apply.package.refused`, and never either value. See
  [review and apply changes](../operate/breg-changes/#activate-the-successor).

{/* Evidence: release/notes/v0.34.0.md. */}

- `bregctl apply` reports a successor refused because retained history coverage
  does not admit it as `apply.history.coverage_incomplete`, with the suggested
  action `prepare_history_rebaseline_request`, instead of
  `apply.migration.failed`. The refusal leaves maintenance state unchanged, and
  its message names the recovery: finish a pending
  `field-encryption erase-history` run or run `history rebaseline`, then apply
  the same package again. See
  [retain, erase, and audit](../operate/breg-retention/#restore-snapshot-coverage-after-an-erasure).

{/* Evidence: crates/registry-breg/src/migration.rs, MigrationError::HistoryCoverage and apply_verified_package();
    crates/registry-breg/src/postgres/interlock.rs, verify_history_coverage_can_begin_successor();
    crates/registry-breg/tests/postgres_history_migration.rs, unrecorded_coverage_gap_still_freezes_the_next_package;
    crates/registry-bregctl/src/lib.rs, apply_reports_a_history_coverage_refusal_with_its_recovery. */}

- `bregctl apply` reports a successor package with nothing to apply as
  `apply.package.empty_plan`, with the suggested action
  `correct_package_build`, instead of a package binding refusal. See
  [review and apply changes](../operate/breg-changes/#troubleshooting).

{/* Evidence: crates/registry-bregctl/src/lib.rs, apply_lifecycle_failure() and
    apply_reports_an_empty_successor_plan_as_nothing_to_apply;
    crates/registry-bregctl/tests/cli/reviewed_migrations.rs, apply_reports_an_unchanged_successor_as_nothing_to_apply. */}

- Base Registry Engine (BReg) no longer fails an accepted review that the
  review authority still reports as pending. A `202` from the result resource
  no longer spends the result-poll attempt budget and clears an earlier
  `result-lookup-uncertain`,
  and the submission recovery deadline no longer ends an accepted review, so
  an approval that arrives days later is still reconciled and, in automatic
  mode, applied. Failed lookups and empty `404` answers still exhaust the
  budget as `result-poll-attempts-exhausted`, and a `410` still fails the
  review as `result-expired`; BReg no longer reports
  `result-recovery-expired`. See
  [operate Base Registry Engine](../operate/breg/).

{/* Evidence: crates/registry-breg/src/review_store.rs, poll_one_result and run_one;
    crates/registry-breg/tests/postgres_review_executor.rs, a_review_the_authority_keeps_pending_outlives_the_poll_budget_and_recovery_deadline. */}

- BReg clears a submission's recorded error when it reconciles the terminal
  review result, so the review projection of a settled review reports
  `recovery.state: none` instead of `operatorAttention` for a result lookup
  that failed before the result arrived. See
  [operate Base Registry Engine](../operate/breg/).

{/* Evidence: crates/registry-breg/src/review_store.rs, reconcile_result and read_projection;
    crates/registry-breg/src/review_store.rs, a_reconciled_result_clears_the_lookup_failure_it_outlived_from_the_projection. */}

- BREAKING: `caseworkctl source add --apply` writes one lifecycle hook per
  paired BReg request entity, `casework-lifecycle-v1-<entity>`, because BReg
  requires hook ids to be unique across a registry. The Casework BReg source
  binding no longer accepts `eventType`. Remove `eventType` from each
  `*.breg-runtime.yaml` binding and every bare `casework-lifecycle-v1` hook
  from the BReg `registry.yaml`, then repeat `caseworkctl source add --apply`.
  See [deploy Registry Casework](../operate/casework/#write-the-runtime-file).

{/* Evidence: crates/registry-casework-breg/src/lib.rs, LIFECYCLE_EVENT_TYPE_PREFIX;
    crates/registry-caseworkctl/src/source_add.rs, LEGACY_LIFECYCLE_HOOK_ID. */}

- BREAKING: Base Registry Engine (BReg) drops the `superseded` change-request
  state, which no transition ever wrote. A request is `draft`, `submitted`, `cancelled`, or
  `applied`; the `bregState` enum in generated OpenAPI and the Rust, Node.js,
  and Python clients loses the value, and a hook `when` condition naming
  `superseded` no longer compiles. The review result status `superseded` is
  unchanged. See [change requests](../reference/breg-api/#change-requests).

{/* Evidence: crates/registry-breg/src/request_workflow.rs, RequestState;
    crates/registry-breg/src/request_store.rs, install();
    crates/registry-breg/src/compiler.rs, REQUEST_LIFECYCLE_STATES. */}

- BReg decides the change-request actions it offers from the settled review
  result. A rejected request offers only `cancel_request`. A send-back, or an
  approval whose `availableUntil` passed before it was applied, offers
  `revise_request` with `rebase: false` and `cancel_request`, and no longer
  offers `apply_request`. An `answered`, `cancelled`, or `superseded` result
  keeps revise and cancel but no longer offers `apply_request`, which it
  could never pass. BReg refuses the shapes it does not offer: a revise
  after a rejection, or a rebase after a send-back or an expired approval,
  answers `409 mutation.conflict`. The review projection reports an expired
  approval as application state `expired`, including one whose automatic
  application is queued but not yet `applying`, which the Rust, Node.js, and
  Python clients accept, and request lists whose profile discloses
  `review_state` can filter on `reviewOutcome`. The automatic application
  worker leaves a queued job unclaimed once its cached approval's
  `availableUntil` has passed, rather than spend a retry on a request that no
  longer offers `apply_request`. Such a job also no longer holds its review
  authority or executor binding: the activation check that refuses to drop a
  binding with durable work outstanding no longer counts it, so an operator
  may remove a binding an expired, queued job no longer needs. `bregctl
  explain lifecycle` reports the check as its `review_outcome` layer. See
  [change requests](../reference/breg-api/#change-requests).

{/* Evidence: crates/registry-breg/src/postgres/request_read.rs, action_is_available and revise_rebase_available;
    crates/registry-breg/src/mutation/request.rs, execute_request_action_transaction;
    crates/registry-breg/src/postgres/read.rs, REQUEST_REVIEW_OUTCOME_SQL;
    crates/registry-breg/src/review_store.rs, run_one, run_one_application, and verify_retained_bindings;
    crates/registry-breg/src/lifecycle.rs, request_lifecycle;
    crates/registry-breg-client/src/lifecycle.rs, BRegExternalReviewApplicationState. */}

- BREAKING: BReg refuses to compile an access profile with a `taskGrant`
  that holds `apply_request`, with
  `access_profile.task_grant.operation_forbidden`. Applying a reviewed
  request needs a profile of its own without delegated authority; move
  `apply_request` there.

{/* Evidence: crates/registry-breg/src/compiler.rs, access_profile.task_grant.operation_forbidden;
    crates/registry-breg/tests/http_auth.rs, task-grant apply_request compile refusal;
    products/breg/TASK_GRANTS.md. */}

- BReg no longer contacts the review authority for an apply made under a
  revoked or expired task grant, whether the caller's or the one frozen on
  the proposal: it checks both grants first and records the refused apply
  in the audit journal. The apply itself was already refused under such a
  grant, so this closes an early outbound call, not an authorization bypass.

{/* Evidence: crates/registry-breg/src/postgres/mutation.rs, request_reviewed_apply;
    crates/registry-breg/tests/postgres_task_grants.rs, review_apply_checks_original_task_before_authority_and_before_commit. */}

- Base Registry Engine (BReg) read permissions can require the subject's
  recorded consent with
  `requireConsent`. A row reaches a declared recipient organization only while
  a live give for that recipient, purpose, and profile is recorded; PostgreSQL
  checks it on every read, and a withdrawal applies to the next request.
  `bregctl module add consent` generates the consent records, actions, and
  profiles for one subject entity. `bregctl check` reports
  `access.consent.ungated_client` for an ungated profile that reads the same
  rows. Access preview scenarios accept `actorKind` and `requesterClient` and
  report the derived `recipients`. See
  [require consent for a read](../configure/breg-access/#require-consent-for-a-read)
  and [membership and consent read boundaries](../explanation/membership-read-boundaries/).

{/* Evidence: crates/registry-breg/src/consent.rs;
    crates/registry-bregctl/src/consent_module.rs, plan();
    crates/registry-breg/src/access_preview.rs, ScenarioClaims and AccessPreview. */}

- A code added to a BReg field vocabulary is now a compatible additive
  migration, so it needs no reviewed migration evidence; `bregctl diff`
  classifies it `lock_or_rewrite_risk` because the column check is replaced
  under a table lock. An action input that starts accepting codes is additive
  only when each gained code is new to its vocabulary in the same successor.
  `bregctl diff` attaches a review `reason` to consent-related access changes.
  See [change an active registry](../operate/breg-changes/).

{/* Evidence: crates/registry-breg/src/package.rs, FieldVocabularyCodesAdded and ActionVocabularyCodesAdded;
    crates/registry-breg/src/immediate_actions.rs, contract_only_widens();
    crates/registry-breg/src/tooling.rs, ACTION_CODES_ADDED. */}

- BREAKING: `bregctl init --from publicschema` and the four BReg starters
  follow PublicSchema `main` at commit `e5cfbbc`, version 0.3.0. The
  `agricultural-holdings` starter takes PublicSchema's agricultural holder
  names: its `*-holding-operator-role` entities and routes become
  `*-agricultural-holder-role`, and the `operatedHolding` and
  `holdingOperator*` fields become `holderFarm` and `holderPerson`,
  `holderOrganization`, or `holderGroup`. A project copied from that starter
  keeps working as written; initialize it again to take the new names, which
  come without a data migration. The `seed-lots` starter aligns its fields
  to renamed PublicSchema concepts. PublicSchema retired `public_mandate`, so
  the `public-organizations` starter aligns its free-text `description`
  field to PublicSchema's `description` instead. Neither starter changes a
  field, route, or record. PublicSchema defines `end_date` as the last day
  a period applies, so a period includes its end date. See
  [derive a registry from PublicSchema](../tutorials/derive-a-registry-from-publicschema/).

{/* Evidence: crates/registry-linkml/publicschema/PIN.yaml;
    crates/registry-linkml/tests/snapshot.rs;
    crates/registry-linkml/publicschema/schema/common.yaml, slots.end_date;
    products/breg/starters/agricultural-holdings/core/registry.yaml;
    products/breg/starters/seed-lots/core/registry.yaml;
    products/breg/starters/public-organizations/core/registry.yaml;
    products/breg/starters/public-organizations/core/MODEL.md;
    products/breg/starters/README.md. */}

- A `--selection` document for `bregctl init --from publicschema` may now name
  a `modelRevision` alongside `modelVersion`. PublicSchema can keep one
  version label across structurally different revisions, so `modelVersion`
  alone does not pin one; `modelRevision` pins the upstream commit the
  embedded snapshot was copied from, and `init` refuses a selection naming a
  different one. The wizard, the `household` starter selection, and the
  Evidence tutorial's selection write it, and the generated README's
  attribution section states it beside the version. See
  [derive a registry from PublicSchema](../tutorials/derive-a-registry-from-publicschema/).

{/* Evidence: crates/registry-bregctl/src/init_from_model/selection.rs, Selection;
    crates/registry-bregctl/src/init_from_model/resolve.rs, ModelFacts and resolve();
    crates/registry-bregctl/src/init_from_model/render.rs, readme();
    crates/registry-bregctl/src/init_from_model/wizard.rs, assemble();
    crates/registry-linkml/publicschema/starters/household.yaml;
    products/breg/evidence/organization-selection.yaml. */}

## v0.33.0 beta-45

- Registry Scheduling joins the release with published openings, exact-time
  offerings, arrival windows, holds, and accountable appointments. Each
  commitment requires a task grant bounded to the offering's service,
  location, and action. The release publishes a Scheduling container image,
  without a binary or installer asset. See the
  [Registry Scheduling API](../reference/apis/registry-scheduling/).

{/* Evidence: crates/registry-scheduling/src/service.rs;
    crates/registry-scheduling/src/auth.rs;
    release/scripts/release_candidate.py, _candidate_image_names() and _relay_v2_payload_inventory(). */}

- BREAKING: Registry Casework replaces hosted decisions with source-neutral
  review requests, tasks, kinds, results, and accountability. Base Registry
  Engine (BReg) delegates governed change-request review to Casework through a
  review authority binding. The Casework migration drops the experimental
  hosted tables without carrying their data forward. See
  [review BReg changes in Casework](../tutorials/review-breg-changes-in-casework/).

{/* Evidence: crates/registry-casework/migrations/0015_unified_reviews.sql;
    crates/registry-casework/src/review.rs;
    crates/registry-breg/src/review_store.rs. */}

- BREAKING: BReg entity `events` are now shared `hooks`, and deliveries carry a
  signed hook envelope instead of the earlier bare body. Rewrite each entity
  declaration, drain the existing outbox before upgrading, update receivers,
  and regenerate project locks. BReg now requires PostgreSQL 17 or newer.

{/* Evidence: crates/registry-breg/src/contract.rs, EntitySource;
    crates/registry-platform-hooks/src/envelope.rs;
    crates/registry-breg/src/postgres/schema.rs, verify_postgres_17_or_newer(). */}

- BReg ships WebAssembly action handlers enabled by default, field encryption
  for restricted fields, and durable resumable ingestion runs. Existing Rhai
  and declarative action handlers keep working. See
  [field encryption for restricted fields](../explanation/breg-field-encryption/)
  and the [BReg client capabilities](../reference/breg-client-capabilities/).

{/* Evidence: crates/registry-breg/Cargo.toml, features;
    crates/registry-breg/src/field_encryption.rs;
    crates/registry-breg/src/api/ingestion.rs. */}

- Registry Render is available from source with offline CLI, HTTP service, and
  Rust library modes for deterministic Typst PDF rendering. v0.33.0 does not
  publish a Render release asset or container image. See the
  [Registry Render overview](../start/registry-render/).

{/* Evidence: crates/registry-render/src/cli.rs, Command;
    crates/registry-render/src/lib.rs, render;
    release/manifests/registry-stack-beta-45.yaml, artifacts. */}

- Evidence tooling adds machine-readable reports, an offline-complete starter,
  and self-checking local target generation. Object answer schemas must now
  declare `properties` and `additionalProperties: false`.

{/* Evidence: crates/registry-evidencectl/src/lib.rs, OutputFormat;
    crates/registry-evidence-authoring/src/validate.rs;
    products/breg/evidence/offline-starter/. */}

- The BReg clients expose typed applied-request results and durable ingestion
  runs. `bregctl explain` and `caseworkctl` machine-readable output now use
  versioned, closed JSON report contracts.

{/* Evidence: crates/registry-breg-client/src/lifecycle.rs;
    crates/registry-breg-client/src/ingestion.rs;
    products/breg/contracts/explain/;
    products/casework/contracts/cli/. */}

## v0.32.0 beta-44

- Exchanged access tokens carry `registry_assertion_issuer`, derived from the
  verified subject-token issuer. Evidence, Base Registry Engine (BReg), and
  Casework can pair each client with the assertion issuers it may present and
  refuse any other. Without that configuration no pairing rule applies.

{/* Evidence: crates/registry-platform-oidc/src/lib.rs, with_assertion_issuers();
    crates/registry-evidence/src/auth.rs, assertion_issuers. */}

- BReg governed request application can re-check fresh Evidence and
  linked-record preconditions at Apply, and BReg Evidence providers can use
  `privateKeyJwt` to refresh credentials instead of a static `tokenRef`. See
  [operate Base Registry Engine](../operate/breg/).

{/* Evidence: crates/registry-breg/src/request_workflow.rs, FrozenApplicationPreconditions;
    crates/registry-breg/src/action_evidence_config.rs, EvidencePrivateKeyJwtConfig. */}

- Evidence questions can answer with a governed `bounded-identifier` value.
  The Rust, Node.js, and Python Evidence clients can authenticate through token
  exchange, and the BReg, Relay, and Casework clients can obtain person- or
  task-grant-bound exchanged tokens. See
  [disclosure modes and computed answers](../explanation/disclosure-modes-and-computed-answers/)
  and the [client API](../reference/client-api/).

{/* Evidence: products/evidence/contracts/supported-value-forms.yaml, bounded-identifier;
    crates/registry-evidence-client/src/client.rs, from_profile_with_authorization();
    crates/registry-platform-httputil/src/client/exchange_authorization.rs, ExchangeAuthorization;
    crates/registry-casework-client/src/task_assertion_source.rs. */}

- Local development can compose BReg, Evidence, and Casework under one shared
  issuer. `evidencectl access client add` adds task-grant and first-party
  exchange modes, and `bregctl examples run` runs the scenarios a project
  authors in `examples/scenarios.json`. See [evidencectl](../reference/evidencectl/).

{/* Evidence: crates/registry-evidencectl/src/access.rs, grant_bootstrap_scope;
    crates/registry-bregctl/src/dev/examples.rs, Scenario. */}

- Local ThunderID development containers are now named per state root. After
  upgrading, remove a container started by v0.31.0 once with
  `docker rm -f thunderid-<label>-<id prefix>` and start the session again.
  Retained state is untouched.

{/* Evidence: crates/registry-thunderid-tooling/src/container.rs, container_name(). */}

## v0.31.0 beta-43

- Registry Mint retired; the `mint` config key and retired CLI flags are refused.

{/* Evidence: crates/registry-bregctl/src/dev/mod.rs, DevArgs;
    crates/registry-caseworkctl/src/dev/mod.rs, read_state();
    crates/registry-evidencectl/src/dev.rs, RetiredMintDevelopment. */}

- Grant authority removed: Base Registry Engine (BReg) `taskGrant.authority` and task status client
  `authority`, Casework `taskAuthority.id`, and Evidence's `grantAuthority`
  claim name. BReg status clients are keyed by source issuer only.

{/* Evidence: crates/registry-breg/src/contract.rs, TaskGrantSource;
    crates/registry-breg/src/task_grant/config.rs, TaskGrantStatusConfig;
    crates/registry-casework/src/config.rs, TaskAuthorityConfig;
    crates/registry-platform-oidc/src/authorization_claims.rs, ClaimNames. */}

- Casework task assertions no longer carry `registry_grant_authority` or
  `registry_grant_source_issuer`; ThunderID derives the source issuer from the
  verified `iss`.

{/* Evidence: crates/registry-casework/src/task_grants.rs, task_assertion_pseudonymizes_approver_and_keeps_evidence_context_explicit();
    crates/registry-thunderid-tooling/src/description.rs, GRANT_ATTRIBUTES;
    crates/registry-thunderid-tooling/src/render.rs, render(). */}

- Local dev databases holding grants or drafts from before #1044 no longer load;
  reset local dev state.

{/* Evidence: crates/registry-casework-core/src/task_grant.rs, TaskGrant;
    crates/registry-casework/src/task_grants.rs, PostgresStore::task_grant();
    crates/registry-breg/src/request_workflow.rs, RequestWorkflow. */}

- `@registrystack/client` exposes `breg.verifyWebhookDelivery()` for Node
  receivers. The helper delegates the Version 1 signature contract to the
  shared Rust verifier and returns the authenticated CloudEvents attributes,
  delivery metadata, and exact body. Receivers still bound clock skew, validate
  the expected event contract, and deduplicate before applying an effect. See
  [verify a webhook delivery](../reference/client-api/#verify-a-webhook-delivery).

{/* Evidence: crates/registry-breg-client/src/webhook.rs, verify_webhook_delivery();
    crates/registry-breg-client-node/src/lib.rs, verify_webhook_delivery();
    crates/registry-platform-crypto/src/delivery_signature.rs, verify_v1(). */}

## v0.30.0 beta-42

- Registry Casework ships with Registry Stack 0.30.0 and has a documentation set
  of its own: an [overview](../start/casework/), the
  [decide your first work item](../tutorials/first-casework/) tutorial that a
  CI gate replays, [how Casework works](../explanation/how-casework-works/),
  [author a Casework policy](../configure/casework/),
  [deploy Registry Casework](../operate/casework/),
  [retain, erase, and settle](../operate/casework-retention/), the
  [API contract](../reference/apis/registry-casework/), and a Casework section
  in the [client API reference](../reference/client-api/). The installer
  `casework-install.sh` installs `casework` and `caseworkctl`, and
  `caseworkctl dev start` starts a retained local runtime with its PostgreSQL
  container, pinned stock issuer, and seeded directory.

{/* Evidence: crates/registry-casework/install.sh; crates/registry-caseworkctl/src/dev/mod.rs;
    docs/site/scripts/run-tutorial.mjs. */}

- Registry Casework names the failing secret reference and the rule it broke
  when a database, audit, or static JWKS secret cannot be resolved, without
  echoing the value; the operator file accepts
  `authentication.oidc.jwksSource: {kind: static, documentRef: …}` beside
  issuer discovery; and the two work-item history routes are documented
  separately: `hosted-history` for hosted work and `history` for source-scoped
  reads under `Registry-Source-Profile`. See
  [deploy Registry Casework](../operate/casework/).

{/* Evidence: crates/registry-casework/src/config.rs, describe_secret_failure;
    crates/registry-casework/tests/secret_diagnostics.rs; products/casework/README.md. */}

- Base Registry Engine warns about unknown or disallowed access-token key
  identifiers in its JSON log messages, at most once per minute
  per authenticator. Caller refusals remain value-free. The warning does
  not establish provider key rotation. The operations guide describes how
  to confirm rotation and replace a static `documentRef` pin supplied by
  either a file or an environment variable. Automated coverage verifies
  authentication refusal, bounded diagnostics, and recovery after replacing
  an in-memory key set; it does not execute the operational runbook. See
  [operating Base Registry Engine](../operate/breg/).

{/* Evidence: crates/registry-breg/src/auth.rs, RegistryAuthenticator::authenticate;
    crates/registry-breg/tests/http_auth.rs,
    static_jwks_key_refusal_is_bounded_and_repinning_restores_authentication;
    docs/site/src/content/docs/operate/breg.mdx, static JWKS rotation. */}

- The Base Registry Engine access-token verifier admits both RFC 9068
  spellings of the access-token media type as one configured token type:
  `accessTokenType: at+jwt` and `accessTokenType: application/at+jwt` each
  accept tokens whose `typ` header carries either spelling. All `typ` matching
  remains case-insensitive, and values outside the configured token type are
  still refused. An issuer can switch between the two permitted spellings
  without an engine configuration change. ThunderID emits `at+jwt`, while
  other providers may emit the full media type. See
  [operating Base Registry Engine](../operate/breg/).

{/* Evidence: crates/registry-platform-oidc/src/lib.rs, access_token_typ_set();
    crates/registry-breg/src/auth.rs, admits_one_access_token_type();
    crates/registry-breg/src/runtime_config.rs, token_verifier_config(). */}

- `GET /v1/registry` lists each operation's `readableRequestFields` beside
  `readableFields`, so a caller can learn before a read whether its selected
  profile receives request review state, actor references, or decision reasons.
  The list follows the rule request reads apply: an anonymous profile, or an
  entity without a change request, lists no request fields. See
  [Base Registry Engine API](../reference/breg-api/).

{/* Evidence: crates/registry-breg/src/api/metadata.rs, readable_request_fields;
    crates/registry-breg/tests/http_read_only.rs, workspace_metadata_projects_request_field_disclosure_per_caller_profile. */}

- The Rust, Node.js, and Python Base Registry Engine clients accept the
  `action.refused` problem an immediate action answers a declared business rule
  with. No client registered that code, so the one refusal a caller is meant to
  act on arrived as an opaque protocol failure. The typed error carries the
  package-declared reason as `refusal_code` in Rust and Python and `refusalCode`
  in Node.js, beside the status, the code, and the trace identifier, and the
  catalogue label stays in the detail. A reason outside the published bounds, a
  missing one, or one attached to any other code fails closed. See
  [client API reference](../reference/client-api/).

{/* Evidence: crates/registry-breg-client/src/error.rs, BRegRefusalCode;
    crates/registry-breg-client/src/client.rs, parse_breg_problem();
    crates/registry-breg-client-node/client.d.ts;
    crates/registry-breg-client-py/python/registry_breg_client/__init__.pyi. */}

- The published problem-code table documents `action.evidence_failed`, the 503
  an immediate action answers when a declared Evidence dependency could not be
  acquired or accepted. The engine registers the code and answers with it, and
  the table named every other one. See
  [Base Registry Engine API](../reference/breg-api/).

{/* Evidence: docs/site/src/data/breg-api.yaml;
    crates/registry-breg/src/problem.rs, ActionEvidenceFailed. */}

- `readableRequestFields` widens to `review_state` and `actor_reference`,
  disclosing `review`, `reviewTiming`, `submitterReference`, and
  `applierReference` on a change-request record for a non-anonymous profile.
  Every change-request action response now also includes `actorReference`,
  independent of `readableRequestFields`. See
  [Base Registry Engine API](../reference/breg-api/).

{/* Evidence: crates/registry-breg/src/contract.rs, RequestMetadataFieldSource;
    crates/registry-breg/src/postgres/request_read.rs, may_disclose_review_state
    and may_disclose_actor_references;
    crates/registry-breg/src/artifacts.rs, request_record_metadata_schema. */}

## v0.29.0 beta-41

- BREAKING: request-lifecycle webhook bodies add required
  `request.reasonPresent` and optional `request.reason`. Update strict receiver
  schemas before activating this release. Deliveries that can match rejection
  or revision now need a destination `classificationCeiling` of at least
  `internal`, or lifecycle filters that exclude both outcomes. See
  [Base Registry Engine API](../reference/breg-api/) and
  [deliver declared events](../operate/breg-webhooks/).

{/* Evidence: crates/registry-breg/src/postgres/request_read.rs;
    crates/registry-breg/src/request_events.rs. */}

- Base Registry Engine adds governed request attachment slots, PostgreSQL or
  operator-bound S3 storage, and asynchronous external verification. Select
  storage and verification before the first upload, which pins both bindings.
  Request-detail erasure now includes attachment references; external cleanup
  retries remain an operator responsibility. See
  [runtime configuration](../reference/breg-configuration/) and
  [retain, erase, and audit](../operate/breg-retention/).
- Reject and request-revision actions accept an optional explanation. Request
  grants default to showing retained reason text; set `readableRequestFields`
  to `[]` to hide it. Current and retained proposal decisions follow the selected
  profile's authority. See [Base Registry Engine API](../reference/breg-api/).
- `bregctl dev events` inspects receipts from the local webhook receiver, with
  captured values available only through `--include-payload`. See
  [deliver declared events](../operate/breg-webhooks/).

{/* Evidence: crates/registry-breg/src/{attachment_storage,attachment_verification,request_retention,request_workflow}.rs;
    crates/registry-bregctl/src/dev/events.rs. */}

- `bregctl dev` reports the check that refused a start instead of only the
  private log directory. The rehearsal, package build, activation, and
  verification run inside a detached supervisor, so a refused journey step now
  reaches your terminal with its code, its `journeys[i].steps[j]` path, and its
  own message. See
  [author journeys](../configure/breg-journeys/#troubleshooting).
- `bregctl dev start` compares the `breg` it resolved against its own version
  before it starts anything, and refuses a binary from another release by name,
  giving both versions and the fix. The issuer runs from the pinned stock image.
  Previously a binary mismatch surfaced much later as a refused package or an
  unready database.
- A refused fixture logical reference names its class: a field the entity does
  not declare, a field the access profile grant does not make writable, a
  request body with no field, a step identifier that is not stable, a step
  naming both an entity and an action or neither, or a capture no earlier step
  declares. The sentence still carries no authored value.

{/* Evidence: crates/registry-bregctl/src/dev/mod.rs, refused_check(),
    start_failure(), and matching_versions();
    crates/registry-breg/src/fixtures.rs, LogicalReferenceRefusal. */}

- `bregctl check` no longer tells you to drop a row boundary field from
  `writableFields` on a grant that also creates. The boundary compiles to an
  INSERT `WITH CHECK` pinning that field to the caller's claim, so the field has
  to stay writable and each create has to send a value the claim allows.
  `access.profile.writable_row_boundary` now words its advice for the grant's
  operations, the new `access.profile.row_boundary_not_writable` reports a
  create whose boundary field is not writable, and `bregctl test` names the row
  boundary rather than reporting an anonymous reference refusal. See
  [control access per profile](../configure/breg-access/).

{/* Evidence: crates/registry-breg/src/access.rs, access_findings();
    crates/registry-breg/src/{generated_ddl,fixtures}.rs;
    crates/registry-breg/tests/access_configuration.rs. */}

- The Rust, Node.js, and Python Base Registry Engine clients select governed
  request attachment slots from caller-filtered registry metadata and run the
  upload, download, and delete exchanges. A slot carries the served size limit,
  the accepted content types, and the route authority, so an empty body, an
  oversize body, or an unaccepted media type refuses before any request. Raise
  the client's maximum response bytes when a slot serves more than the 8 MiB
  default read bound. See [client API reference](../reference/client-api/).

{/* Evidence: crates/registry-breg-client/src/attachment.rs;
    crates/registry-breg-client-node/client.d.ts;
    crates/registry-breg-client-py/python/registry_breg_client/__init__.pyi. */}

- A request attachment slot serves the `classification` its registry
  configuration authored. It travels in the `x-registry-attachment` extension,
  so it reaches `/v1/registry` and the caller-filtered OpenAPI document under
  the same filtering as the size bound and the accepted content types, and the
  Rust, Node.js, and Python clients read it off the selected slot. A caller can
  now tell restricted slot content from public before downloading any bytes.
  The value is advisory: it grants and withholds no route. See
  [Base Registry Engine API](../reference/breg-api/).

{/* Evidence: crates/registry-breg/src/artifacts.rs, attachment_metadata_schema();
    crates/registry-breg/src/api/metadata.rs, field();
    crates/registry-breg-client/src/attachment.rs, BRegAttachmentClassification;
    crates/registry-breg-client-node/client.d.ts;
    crates/registry-breg-client-py/python/registry_breg_client/__init__.pyi. */}

- The attachment download operation sends the bare `attachment` disposition in
  `Content-Disposition`. No stored slot metadata holds a filename, and the served
  OpenAPI document pins the header to that exact value. Callers choose their own
  filename when saving the bytes. See
  [Base Registry Engine API](../reference/breg-api/).

{/* Evidence: crates/registry-breg/src/attachment.rs, DOWNLOAD_CONTENT_DISPOSITION;
    crates/registry-breg/src/api/attachments.rs, download(). */}

## v0.28.0 beta-40

- BREAKING: `bregctl dev` and `bregctl dev stop` take a positional project
  directory. Replace `--project <dir>` with `<dir>` in scripts. Both commands
  still default to the current directory. See
  [create and query your first registry](../tutorials/first-breg/).
- Base Registry Engine supports bounded Rhai action handlers, linked-target
  acceptance checks, native persisted-field patterns, and membership read
  boundaries. Test new patterns against PostgreSQL before packaging; adding a
  pattern validates existing rows under a table lock, and changing or removing
  one requires a reviewed migration. See
  [governed registry actions](../explanation/governed-registry-actions/),
  [native field patterns](../explanation/native-field-patterns/), and
  [membership read boundaries](../explanation/membership-read-boundaries/).
- The trial action-handler ABI version 2 resolves declared, verified Evidence
  Gateway assertions with operator-bound providers. Accepted assertion material
  has a separate 24-hour retention period. Use
  `bregctl evidence-retention erase-expired` to erase expired assertion bytes and
  verification context while keeping receipts replayable. See
  [retain, erase, and audit](../operate/breg-retention/).

{/* Evidence: crates/registry-bregctl/src/lib.rs;
    crates/registry-breg/src/{action_handler,membership,generated_ddl}.rs;
    products/breg/{immediate-actions,native-patterns,membership-access}.md. */}

- `submitterTargets` can require current same-profile GET authority over the
  native-reference targets of a manually applied change request, including on
  exact replay. Request lists expose authorized filtering and sorting on
  `bregState`, `proposalVersion`, and `effectDigest`; ordinary field API names
  cannot reuse those names. Structured fields also accept an array schema root
  with declared `items`. See
  [declare change requests and actions](../configure/breg-change-control/).
- The unified Node.js client's Base Registry Engine namespace adds exact-JSON
  metadata, record, and lifecycle methods. Serialized JSON avoids silent
  rounding at the JavaScript number boundary, and unsupported values refuse.
  Keep exact values as JSON text or use a lossless decoder.

{/* Evidence: crates/registry-breg/src/{contract,change_request}.rs;
    crates/registry-breg/tests/compiler_submitter_targets.rs;
    crates/registry-breg-client-node/README.md;
    crates/registry-breg-client-node/__test__/exact-json.test.js. */}

- `bregctl init --from publicschema` derives a project from the embedded model
  through a wizard, selection file, or starter. Four starter projects include
  local examples that can resume or restart. Projects copied from the
  unreleased `professional-licences` starter must be initialized again because
  its correction fields changed without a migration path. See
  [derive a registry from PublicSchema](../tutorials/derive-a-registry-from-publicschema/).
- `evidencectl source add` previews a connection from a stopped local registry
  and performs it with `--apply`, preserving records, revisions, and client
  identities. It requires a matching-version `bregctl` on `PATH`. See
  [the evidencectl workflow reference](../reference/evidencectl/).
- Registry Manifest refuses duplicate concept terms on a field after IRI
  expansion and scheme/host case comparison. Remove repeated entries before
  validating or republishing. Valid manifests retain their authored spelling
  and source digest. See [contracts](../reference/contracts/).

{/* Evidence: crates/registry-bregctl/src/init_from_model/;
    crates/registry-bregctl/src/dev/examples.rs;
    products/breg/starters/professional-licences/core/MODEL.md;
    crates/registry-evidencectl/src/source_add.rs;
    products/manifest/CHANGELOG.md. */}

- Export, migration, local development, and Compose preflight failures report
  clearer recovery information. Evidence authoring validates source origins and
  runtime settings consistently with deployment checks, and bounds child
  diagnostics and version handshakes. See
  [the evidencectl workflow reference](../reference/evidencectl/) and
  [change an active registry](../operate/breg-changes/).
- Release checksums now include SLSA build provenance for the publication
  workflow that assembles `SHA256SUMS`; candidate evidence retains the binding
  to payload builds. See [OpenSSF and release trust](../security/openssf-evidence/).
- CLI reference pages and generated reference data are built from reviewed
  source inputs during the documentation build.

{/* Evidence: release/notes/v0.28.0.md; release/VERIFY.md;
    docs/site/scripts/generate-cli-reference.mjs; docs/site/package.json. */}

## Documentation present in v0.27.0

- Clarified that Discovery selection validation checks closed structure and
  capability binding, not trust or currentness, and kept the compatibility
  aliases for existing Node.js and Python adopters. The Rust crate renamed
  `validate_service_selection` to `validate_service_selection_structure` with
  no alias, because the crate is unpublished and exempt from the
  [compatibility promise](../reference/api-stability/).
- Added the adopter-owned accepted-service handoff and explicit online renewal
  workflow. Credentials and native Evidence or Relay input and output remain
  outside Discovery and follow local acceptance.
- Documented Base Registry Engine from its released installer, binaries, and
  container image instead of a build from a checkout.
- Pinned the Base Registry Engine tutorial checkouts to the installed version and
  documented the `--installed` mode of the quickstart and demo launchers.

## 2026-08-20

Documentation prepared for the v0.23.0 beta-34 release:

- Documented Registry Discovery: the curated, read-only index of public
  Evidence and Relay service descriptions, the closed
  `registry-discovery-v1alpha1` provider profile, the bounded relying-party
  search and ambiguity-safe selection, and the `discoveryctl` operator flow.
- Documented that a Discovery selection is inert public metadata, not a trust
  decision and not a native request.
- Documented the npm and PyPI distribution of the Registry Discovery client
  package alongside the existing Evidence and Relay clients.
- Documented the progressive Evidence client API across the Node and Python
  bindings and the synchronized client tutorial paths.
- Documented `relayctl`'s human-readable default output and the unchanged
  `--json` report document.
- Reorganized the sidebar by what a reader came to do, published two tutorials,
  and retired the duplicate chooser page.
- Rewrote the style guide for readers rather than runners, and stopped printing
  values a reader cannot reproduce, such as compiled contract revisions and
  installation-dependent counts.
- Added the v0.23.0 beta-34 candidate documentation archive.

## 2026-08-14

Documentation prepared for the v0.22.0 beta-33 release:

- Documented the explicit container-private Evidence listener mode, native
  Evidence, Mint, and Relay deployment checks, and the common Compose runtime
  preflight.
- Documented Relay issuer identity independently from OIDC discovery or direct
  JWKS transport while preserving canonical discovery compatibility.
- Added Registry Mint's opt-in client-secret profile for managed standard OAuth
  clients, while retaining `private_key_jwt` as the default and sole method
  for Evidence and delegated authority.
- Added owner-only client-secret provisioning, per-installation registration,
  bounded rotation and revocation guidance, and a QGIS Client Credentials
  walkthrough. The walkthrough is configuration guidance, not release-gate
  interoperability evidence.
- Documented the npm and PyPI distribution transaction for the exact
  checksum-covered Evidence and Relay client packages. Registry publication is
  accepted only when registry digests match the candidate bytes.
- Documented that the Relay installer verifies and installs matching `relay`
  and `relayctl` binaries together on Linux amd64 and preserves the previous
  pair on failure.
- Documented eager Evidence trusted-key validation, Mint's reserved `scope`
  authority boundary, categorical Relay editor diagnostics, and governed-only
  Relay project indexing.
- Hardened synchronized product documentation so it is compiled as inert
  Markdown and refuses active raw HTML or unsafe rendered destinations.
- Added the v0.22.0 beta-33 candidate documentation archive.

## 2026-08-13

Documentation updates for the v0.21.0 beta-32 release:

- Documented the official Evidence Gateway and Registry Mint runtime images
  alongside the existing Registry Relay image.
- Distinguished the source-build definitions under `docker/` from the
  reviewed release-image definitions under `release/docker/`.
- Documented operator-mounted configuration, governed packages, secrets,
  keys, and audit storage for all three runtime images.
- Added the v0.21.0 candidate documentation archive.

## 2026-08-12

Documentation updates for the v0.20.1 beta-31 patch release:

- Documented Evidence HTTP sources that treat one exact governed 404 Problem
  Details response as a neutral unresolved consultation instead of a source
  failure.
- Documented the data-free `declaredUnresolved: true` fixture case and the
  fail-closed behavior for malformed, undeclared, or mismatched responses.
- Added the v0.20.1 candidate documentation archive. Registry Mint and Relay
  V2 behavior are unchanged from v0.20.0.

Documentation updates for the v0.20.0 beta-30 release:

- BREAKING: Made `holderBoundBatchMaxSize` a required member of the
  `registry.evidence-definitions/v1` metadata response.
- Upgrade the Evidence runtime, Evidence clients, and Evidence OID4VCI adapter
  together. New clients read an older response without this member as a batch
  size of `1`; older strict clients reject responses that contain the new
  member.
- BREAKING: Removed the reserved `registry_relay` vocabulary prefix from
  `registry-manifest/v1`. Use absolute IRIs or declare an institution-owned
  active vocabulary before validating and republishing affected metadata.
- Documented the first prebuilt Relay Node.js and Python client packages, which
  are attached to the matching GitHub Release rather than published to npm or
  PyPI.
- Added the v0.20.0 candidate documentation archive and advanced maintained
  release, installation, contract, and standards references to v0.20.0.
- Added generated command references for the current CLIs, Relay V2 editor
  support, complete OID4VCI delivery guidance, and Evidence local source API
  mock guidance.
- Removed the remaining Relay V1 and `registryctl` source references from the
  current product surface while retaining their v0.19.0 retirement record.

## 2026-08-11

Documentation updates for the v0.19.0 beta-29 release, which replaced both
Relay identities:

- BREAKING: `relay` replaces the `registry-relay` runtime, and `relayctl`
  replaces `registryctl`. The legacy runtime, the Rhai worker, the
  `registryctl` binary, its installer, its image lock, and the PostgreSQL
  release closure are absent from the release.
- Rewrote the Relay documentation around the V2 model: a governed registry
  contract, a deployment-local runtime document, and generated package
  artifacts. Relay V1 configuration is not an in-place upgrade input.
- Documented the V2 read surface: bounded Record reads, named lookups and
  searches, CRS84 Point data as GeoJSON or JSON-FG, and a profiled SDMX data
  and structure read subset. Access profiles stay independent of wire-format
  selection.
- Removed the documentation for capabilities V2 does not implement:
  spreadsheet, HTTP, and PostgreSQL sources, Rhai script adapters, API-key and
  OAuth client-credentials authentication, the two-lane public and
  consultation split, materialization, and the administrative posture
  endpoint. [Known limitations](/explanation/known-limitations/) records what
  is now absent.
- Replaced the pinned Relay OpenAPI reference with the per-deployment model.
  Relay V2 generates its description from the adopter's registry contract and
  serves it at `GET /openapi.json`.
- Removed the generated authoring reference and diagnostic catalogs, which
  were produced from `registryctl` introspection commands that `relayctl` does
  not yet offer.
- Rewrote the normative RS-\* specifications for the Relay protocol, adopter
  tooling, operational posture, security, and terminology against the V2
  contracts.
- Recorded the [Relay V1 and registryctl retirement
  decision](../decisions/relay-v1-and-registryctl-retirement-2026-08-11/) and
  redirected the retired routes.
- Documented the Relay installer and the `ghcr.io/registrystack/relay:v0.19.0`
  image. `relayctl` has no installer; it is taken from the release assets or
  built from source.
- Documented the Evidence bounded multi-subject request batch, which shares one
  authorization and execution budget and returns results in request order.
  Existing single-subject clients need no wire-format migration.
- A Registry Docs archive is not part of this release, so the current
  documentation can be updated without waiting for a runtime release.

## 2026-08-09

Documentation updates for the v0.18.0 beta-28 release candidate:

- Added holder-bound Evidence issuance, bounded atomic batches, and
  presentation verification with RFC 9901 key-binding JWTs.
- Added the Evidence OID4VCI 1.0 Final wallet-delivery adapter, including its
  protected offer flow, proof validation, single-replica constraint, and
  bounded in-memory lifecycle.
- Documented reviewed immutable SQLite extraction, fixed multi-stage source
  acquisition, and private-key-JWT source authentication.
- Added the `evidence-oid4vci` binary to the Evidence installer and release
  inventory for all three supported platforms.
- Added the v0.18.0 candidate documentation archive.

## 2026-08-07

Documentation updates for the v0.17.0 beta-27 release candidate:

- Added the Evidence runtime, adopter tooling, relying-party client, portable
  verifier, and Registry Mint supporting service to the maintained product
  documentation.
- Added Evidence tutorials and operator guidance for fixed source acquisition,
  authorization, minimum-disclosure output, signing, key rotation, audit, and
  relying-party verification.
- Retired Registry Notary from the current product and release surfaces while
  preserving historical release records.
- Documented Relay scalar-only attribute-release claims and the warning for
  aggregate routes without a longitudinal privacy budget.
- Added the v0.17.0 candidate archive and the stable Registryctl installer
  served from the exact promoted documentation archive.
- Recorded Node and Python Evidence client packages as GitHub Release assets,
  without npm or PyPI publication.

## 2026-08-03

Product direction update:

- Recorded the decision to retire Registry Notary from the current product
  surface while preserving historical changelogs, decision records, and
  release manifests.
- Reframed the supported product paths around Registry Relay for scoped,
  protected reads and Evidence for minimum-disclosure assertions.
- Kept Evidence independent from the retired Notary product model, with
  Registry Mint limited to supporting token issuance.

Adopter-facing breaking change:

- Raised the registryctl approved-set schema to version `2.0` and made
  registryctl refuse an approved set issued before the retirement, including a
  version `1.0` document, a set carrying a `notary` lane, and a set binding
  cross-lane interface digests.
- Required affected deployments to re-approve their baseline from the current
  lane bundles, because the removed cross-lane interface digests are no longer
  verified and the old approval's integrity claim is no longer enforced. See
  [Approve the initial product baseline](../operate/approve-initial-baseline/).

## 2026-08-01

Stabilization updates for the v0.16.3 beta-26 release candidate:

- Recorded that v0.16.2 stopped after staging an unpublished draft and before
  public image or documentation publication.
- Added the v0.16.3 candidate archive and retained v0.16.0 through v0.16.2 as
  failed-train records.
- Simplified Beta publication recovery without changing product behavior.

Fix-forward updates for the v0.16.2 beta-25 release candidate:

- Recorded that the immutable v0.16.1 tag workflow stopped after creating an
  unpublished empty draft GitHub Release.
- Recorded that v0.16.1 has no public release, final images, assets, or
  documentation, and directed adopters to install only v0.16.2.
- Added the candidate `v0.16.2` archive while retaining the v0.16.0 and
  v0.16.1 failed-train records and v0.15.2 as the latest published release.

Fix-forward updates for the v0.16.1 beta-24 release candidate:

- Recorded that the immutable v0.16.0 tag workflow failed during startup
  before any job or public write.
- Recorded that v0.16.0 has no GitHub Release, final images, assets, or
  documentation, and directed adopters to install only v0.16.1.
- Added the candidate `v0.16.1` archive while retaining the v0.16.0 candidate
  history and v0.15.2 as the latest published release.

Documentation updates for the v0.16.0 beta-23 release candidate:

- Added the maintained spreadsheet and HTTP adopter journeys, including the
  common authoring, test, development, build, trust, and deployment workflow.
- Documented separate public and consultation Relay lanes, signed artifact
  roots, persistent audit records, and strict public Relay client validation.
- Documented Relay sensitive-read gates, snapshot recovery, no-expiry OAuth
  migration, and Script budget accounting.
- Documented Notary's registry-backed evidence requirement, structured claims,
  registrar offers, representative issuance, delegated-target enforcement,
  expiry rechecking, and state-catalog upgrade procedure.
- Added the candidate `v0.16.0` archive while retaining `v0.15.2` as the latest
  published release until promotion completes.

## 2026-07-28

Fix-forward updates for the v0.15.2 beta-22 release:

- Recorded the immutable partial v0.15.1 publication and moved forward without
  reusing its tag or public image names.
- Bound capsule validation to the exact same-digest candidate-to-public
  Registry Stack image mappings.
- Made observational promotion telemetry nonblocking and removed its obsolete
  fixed measurement count.

Fix-forward updates for the v0.15.1 beta-21 release candidate:

- Preserved the immutable failed v0.15.0 tag and recorded that its workflow
  stopped before any public release or image publication.
- Corrected exact annotated-tag binding extraction without weakening the
  closed candidate-binding parser.
- Prepared the `v0.15.1` candidate docset while retaining the failed v0.15.0
  candidate archive and v0.13.0 as the latest published release.

Documentation updates for the v0.15.0 beta-20 release candidate:

- Published the versioned Registryctl installer and the spreadsheet-first local
  API and registry-backed claim tutorials as the maintained beginner path.
- Added generated configuration, ownership, authoring, fixture, and operator
  references for the complete project-authoring surface.
- Documented all-row spreadsheet validation, stable governed attribute release,
  Relay-to-Notary consultation closure, and value-free activation diagnostics.
- Added the candidate `v0.15.0` archive while retaining `v0.13.0` as the latest
  published release until promotion completes.
- Recorded that v0.14.0 was not published and is not part of this release
  lineage.
- Kept Solmara, hosted publication, external OpenID, OpenCRVS, DHIS2, wallet,
  verifier, and country-acceptance evidence as separate gates.

## 2026-07-26

Unreleased current-source documentation updates:

- Added task-oriented Start, Connect your data, Operate, Security, and
  Reference navigation for new adopters.
- Added generated references for all five authored and both runtime
  configuration domains, with fail-closed field-intent and ownership coverage.
- Added separate generated authoring, fixture, and operator diagnostic
  references.
- Restored the released spreadsheet API and live registry-backed claim
  tutorials as the primary beginner path.
- Kept advanced operations for rotation, materialization, reapproval,
  diagnosis, Script workers, recovery, upgrade, migration, and rollback
  available from the operator handoff instead of presenting them as beginner
  journeys.

These pages describe the current source under test. They are not part of the
immutable v0.13.0 archive and do not claim candidate, hosted, country,
interoperability, or production evidence.

## 2026-07-25

Documentation updates for the v0.13.0 beta-17 release:

- Advanced current source citations, install commands, verification examples,
  contracts, projects, and standards links to Registry Stack `v0.13.0`.
- Added the `v0.13.0` archived docset while retaining every earlier release
  archive.
- Documented removal of Relay's inert `provenance.consent` result member, the
  required pre-release consultation-state re-bootstrap, and Notary's matching
  closed decoder.
- Documented the shared deployment-waiver `reference` and optional `summary`
  contract, with the retired `reason` field rejected.
- Updated Registryctl authoring examples to keep source adaptation, evidence
  policy, and consumer decisions separate, and recorded the
  `registryctl.smoke.v1` report schema.
- Kept Solmara, hosted publication, external integration, OpenID, lifecycle,
  OpenSPP holdout, and pilot evidence as separate held gates.

## 2026-07-23

- Made the Relay-to-Notary-to-evidence-consumer responsibility boundary normative for 1.0 project
  authoring. Updated Notary guidance and registryctl examples to keep reusable evidence separate
  from consumer-owned requirements, decisions, workflow, and action rules.

## 2026-07-20

Documentation updates for the v0.12.2 beta-16 fix-forward release:

- Advanced current source citations, install commands, verification examples,
  contracts, projects, and standards links to Registry Stack `v0.12.2`.
- Added the `v0.12.2` archived docset while retaining the incomplete v0.12.0
  and v0.12.1 publication records and every earlier archive.
- Recorded separate Registryctl and Relay release builds, verification of the
  shipped Relay feature set, and pinned canonical binary and image wrappers
  used to reproduce candidate hashes and ordered runtime root filesystem
  layers.
- Recorded Relay's move to `quick-xml` 0.41 and the exact `ryu-js` 1.0.3 pin,
  retiring temporary dependency exceptions without adding product features.
- Moved Registry Notary router tests to in-process transport where network
  semantics are not under test, preventing release-gate socket exhaustion
  without changing production request handling.
- Recorded the production fix that isolates each single-use eSignet
  authorization-code exchange on short-lived DNS-pinned transport, with
  redirects and proxies denied, bounded timeouts, and no transparent retry.
- Kept Solmara, hosted publication, external integration, OpenID, lifecycle,
  and pilot evidence held.

Documentation updates for the v0.12.1 beta-15 fix-forward release:

- Advanced current source citations, install commands, verification examples,
  contracts, projects, and standards links to Registry Stack `v0.12.1`.
- Added the `v0.12.1` archived docset while retaining the incomplete v0.12.0
  publication record and every earlier archive.
- Recorded the root-filesystem-bound reviews for the three non-fixable Debian
  13 `libc6` findings that stopped the v0.12.0 publication attempt.
- Recorded deterministic release plans, remote tag checks, both-image Open
  Containers Initiative label smoke, and safer release workflow routing.
- Kept Solmara, hosted publication, external integration, OpenID, lifecycle,
  and pilot evidence held.

## 2026-07-19

Documentation updates for the v0.12.0 beta-14 release:

- Advanced current source citations, install commands, verification examples,
  contracts, projects, and standards links to Registry Stack `v0.12.0`.
- Added the `v0.12.0` archived docset while retaining the v0.11.0 and earlier
  archives.
- Documented Registry Notary's issuer-initiated pre-authorized-code profile,
  bounded batch evaluation, generated runtime configuration schema, and
  fail-closed credential-status verification.
- Documented Registry Relay's intended 1.0 support roster and protected
  per-resource last-good refresh health.
- Updated Registryctl tutorials for human-readable report defaults and the
  matching v0.12.0 binary, image lock, and image generation.
- Recorded the Debian 13 runtime transition and kept candidate-only lifecycle,
  external integration, OpenID, Solmara, hosted, and pilot evidence held.

- Documented Relay's protected per-resource refresh-health metrics, restricted posture
  observation, last-good availability behavior, and default alert at three consecutive failures.
- Documented the source installer for the optional VS Code and Zed semantic-navigation
  integrations. Editor installation is user- or profile-scoped and remains separate from
  project-local schema setup through `registryctl init` or `registryctl authoring editor`.

## 2026-07-18

Documentation updates for the v0.11.0 beta-13 release:

- Advanced current source citations, install commands, verification examples,
  contracts, projects, and standards links to Registry Stack `v0.11.0`.
- Added the `v0.11.0` archived docset while retaining the v0.10.0 and earlier
  archives. The public release inventory remains eight artifacts. Registryctl
  embeds the optional preview language server; it is not a separate release
  artifact. The VS Code and Zed extensions remain source-installed developer
  previews and are not marketplace packages.
- Published the registry-backed local Notary tutorial and the maintained
  authoring-workspace catalog. Registryctl continues to expose exactly five
  public starters. The local tutorial proves evaluation only, not credential,
  wallet, presentation, or OID4VCI interoperability.
- Documented the credential-issuance migration: only fresh, non-delegated,
  registry-backed evaluations with exact Relay provenance are credential
  capable. Source-free and delegated results remain evaluation and rendering
  surfaces, and old evaluations require re-evaluation before issuance. No
  database migration is required solely for this narrowing.
- Added migration coverage for ambiguous primary credentials, strict empty
  environment expansion, Relay Script host-call diagnostics, and offline audit
  quarantine recovery.

This beta does not claim stable 1.0 completion, full OID4VCI interoperability,
hosted promotion, audit completion, or an external pilot result.

## 2026-07-16

Documentation updates for the v0.10.0 beta-12 release:

- Advanced current source citations, install commands, and deployment examples to Registry Stack
  `v0.10.0`.
- Added the `v0.10.0` archived docset with the four formal products and Crosswalk. Solmara Lab
  remains a separate adopter demo, not a released Registry Stack artifact.
- Published the Notary PostgreSQL install, role, migration, retention, backup, restore, recovery,
  supported-version, restart, and multi-instance contract.
- Added separate Relay consultation-state backup and restore guidance without sharing Relay roles,
  schemas, or tables with Notary.
- Replaced the retired monorepo Lab documentation route with a source-backed Solmara local journey.

Migration notes:

- Notary production correctness state now uses Notary-owned PostgreSQL. The pre-1.0 Redis cutover
  is a stopped-writer transition with explicit drain and credential-status gates.
- Registry project authoring now uses `registry-stack.yaml`, explicit integrations, fixtures,
  service topologies, and environment bindings. Reauthor pre-1.0 project files and review changed
  RFC 8785 canonical digests before signing.
- Deploy one Notary authority per Relay trust domain. Identical replicas may share that authority's
  Notary database, but Relay and Notary retain separate state ownership.
- Deploy the released Relay Rhai and Notary CEL workers only for their owning product's adapter
  contract. They are not a shared extension or state framework.

## 2026-07-10

Documentation updates for the v0.9.0 beta-11 release:

- Advanced the active monorepo docs and source citations to RegistryStack `v0.9.0`.
- Added the `v0.9.0` archived docset pinned to the beta-11 freeze source ref.
- Updated registryctl install examples and current deployment tutorials to the `v0.9.0` release
  tag while retaining the published v0.8.4 stale-digest workaround until tagged artifact proof
  closes it.
- Kept hosted first-run publication held while the credential failure in
  [GH#330](https://github.com/registrystack/registry-stack/issues/330) and the complete
  [GH#198](https://github.com/registrystack/registry-stack/issues/198) fresh-reader run remain open.

Migration notes:

- Registryctl project generation now requires the strict image lock from the same release beside
  the binary, or at an explicitly verified `REGISTRYCTL_IMAGE_LOCK` path. Existing projects still
  run from their stored immutable pins. See
  [GH#339](https://github.com/registrystack/registry-stack/pull/339).
- Relay passes a client-supplied trust-context header to the PDP only when the caller has the exact
  `registry:trust:<field>:<value>` scope. Update caller scopes before relying on those fields;
  their value-bearing audit scopes are now pseudonymized. See
  [GH#338](https://github.com/registrystack/registry-stack/pull/338).
- Notary federation denials now preserve their audit context. No new client request field is
  required, but operators should retain the enriched denial records. See
  [GH#337](https://github.com/registrystack/registry-stack/pull/337).

## 2026-07-04

Documentation updates for the v0.8.4 beta-10 release:

- Advanced the active monorepo docs and source citations to RegistryStack `v0.8.4`.
- Added the `v0.8.4` archived docset pinned to the beta-10 source ref.
- Updated registryctl install examples and current deployment tutorials to the `v0.8.4` release tag.
- Recorded v0.8.3 as the first provenance-bearing root release.

## 2026-06-26

Documentation updates for the v0.8.3 security and release-trust patch:

- Advanced the active monorepo docs and source citations to RegistryStack `v0.8.3`.
- Added the `v0.8.3` archived docset pinned to the beta-9 source ref.
- Updated registryctl install examples to the `v0.8.3` release tag.
- The `v0.8.2` docset remains archived; its release carries no tag-bound SLSA provenance.

## 2026-06-25

Documentation updates for the v0.8.2 fix-forward release:

- Advanced the active monorepo docs and source citations to RegistryStack `v0.8.2`.
- Added the `v0.8.2` archived docset pinned to the beta-8 source ref.
- Updated registryctl install examples to the `v0.8.2` release tag.
- Kept the `v0.8.1` docset archived (source tag only; no release artifacts were published).

Documentation updates for the v0.8.1 source release:

- Advanced the active monorepo docs and source citations to RegistryStack `v0.8.1`.
- Added the `v0.8.1` archived docset pinned to the beta-7 source ref.
- Added monorepo-aware archive handling for v0.8.x docsets while keeping older beta archives on
  their legacy source repos.
- Updated registryctl install examples to the `v0.8.1` release tag.

## 2026-06-24

Documentation updates for the beta-5 source release:

- Added the `Beta 5` docset with pinned refs for Platform, Manifest, Notary, Relay, Lab,
  registryctl, Crosswalk, and Atlas as a Lab input.
- Advanced the active product docs to Registry Relay `v0.5.0`, Registry Notary `v0.7.0`, and
  Registry Manifest `v0.2.2`.
- Updated OpenCRVS, FHIR-adjacent, and standalone deployment tutorial references to the beta-5
  release pins.

## 2026-06-22

Documentation updates for the beta-4 source release:

- Added the `Beta 4` docset with pinned refs for Platform, Manifest, Notary, Relay, Lab,
  registryctl, Crosswalk, and Atlas as a Lab input.
- Advanced the active product docs to Registry Relay `v0.4.1`, Registry Notary `v0.6.2`, and
  Registry Manifest `v0.2.2`.
- Updated source citations and tutorial install commands to beta-4 refs.

## 2026-06-21

Documentation updates for the beta-3 release candidate:

- Added the `Beta 3` docset with pinned candidate refs for Platform, Manifest, Notary, Relay,
  Lab, registryctl, Crosswalk, and Atlas as a Lab input.
- Re-pinned repo-doc imports, source links, and registryctl installer paths away from mutable
  `main` URLs.
- Added OpenCRVS and FHIR tutorial coverage for beta-3.

## 2026-06-20

Documentation updates published:

- A scannable homepage section index to orient new visitors.
- Dark mode with a theme toggle.
- Outcome-first tutorials with prerequisites and numbered steps.
- New reference pages for the registryctl CLI, error and status codes, and environment variables.
- A native, searchable, theme-aware API reference.
- A per-page footer showing the last-reviewed date, an edit link, and a feedback control.

## 2026-06-13

Documentation set: the Latest docset published from the main branch, tracking main snapshots of
[Registry Relay](../products/registry-relay/), [Registry Notary](../products/registry-notary/),
and [Registry Manifest](../products/registry-manifest/).

## 2026-06-12

Documentation set: the Beta 2026-06-12 docset frozen and archived, covering the following
product versions.

| Product | Version |
| --- | --- |
| Registry Notary | v0.3.0 |
| Registry Relay | v0.2.0 |
| Registry Manifest | v0.2.0 |
| registryctl | v0.1.0 |
| Registry Platform | v0.2.1 |
| Crosswalk | crosswalk-core-v0.2.0 |