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

# What you need to run Base Registry Engine

> The database, token issuer, and people a production Base Registry Engine deployment needs, what it does not depend on, and what stays your job once it runs.

If you are planning a production Base Registry Engine (BReg) deployment, this is what you provide,
what the product does not depend on, and what stays your job once it runs. None of it is needed for
[your first registry](../../tutorials/first-breg/), which starts disposable versions of everything
on your machine.

## What you provide

- **PostgreSQL 17 or newer**, with two login roles: a migration role that owns the schema and
  applies packages, and a runtime role the serving process uses. The migration credential is what
  authorizes an activation; packages carry no signature, and the database records every activation
  in its own ledger. A registry with spatial fields
  also needs PostGIS 3.5 or newer. Your administrator installs the extensions the
  runtime checks for; neither role creates a schema, an extension, or a role. SQLite is not a
  target.
- **A host for one process.** The runtime is a single binary that verifies one package and serves
  its REST API against one database. It runs on the platforms in
  [platform support](../../explanation/known-limitations/#platform-support).
- **HTTPS in front of it.** The process trusts no host or forwarded header; your reverse proxy or
  ingress terminates TLS, and generated links use the public origin you configure.
- **A token issuer.** BReg verifies bearer tokens from one OpenID Connect issuer and issues none.
  Configure a compatible OAuth issuer for this role.
- **A backup of the database before every activation.** A destructive change goes further: its
  activation is refused unless you name each backup the reviewed migration requires, in a
  binding file that states the database it came from and the backup file's digest. The product
  restores nothing itself, and it refuses to serve a logically restored copy until an operator
  adopts it, as
  [back up and restore the database](../breg-changes/#back-up-and-restore-the-database)
  describes. That check reads the cluster's system identifier through `pg_control_system()`,
  which PostgreSQL grants to every role; on a managed service that withholds it, the check falls
  back to the database object identifier alone and still starts.

{/* Evidence: crates/registry-breg/src/postgres/schema.rs; crates/registry-breg/src/postgres/roles.rs,
    verify_postgres_16_or_newer and postgis_version_supported;
    crates/registry-breg/src/runtime_config.rs, SqlRoles and PublicOrigin;
    crates/registry-breg/src/auth.rs, RegistryAuthenticator;
    crates/registry-breg/src/package.rs, verify_shared_package;
    crates/registry-breg/src/instance_claim.rs; products/breg/README.md;
    crates/registry-breg/src/migration_plan.rs, ExternalBackupBinding;
    crates/registry-breg/src/migration.rs, check_backup_binding();
    products/breg/DECISIONS.md. */}

## What it does not need

Records, their history, pending change requests, and the outbox of undelivered events live in
PostgreSQL. The default audit destination needs a writable local directory per process; alternatively,
collect the best-effort `stdout` stream through your platform. Webhook delivery
runs inside the process from that outbox, so there is no message broker. No cache, object store,
or second service takes part in a request. Registry Relay and Evidence Gateway are separate
products, not dependencies.

The modeling loop needs none of this. Authoring commands check, explain, and generate a project
with no database open, so an author can work on a laptop until the project is ready to test.

{/* Evidence: crates/registry-breg/src/outbox.rs; crates/registry-breg/src/webhook.rs;
    release/docker/Dockerfile.breg; crates/registry-bregctl/src/lib.rs, Command; products/breg/README.md. */}

## How it ships

Each release publishes the `breg` runtime and the `bregctl` authoring tool as reproducible
binaries, with an installer that verifies them against the release checksums and installs them
together or not at all. Each release also publishes a
container image built on a distroless base with no shell,
running as a non-root user, that holds the runtime binary and nothing else; configuration, package,
and secrets mount read-only into it. File audit needs a separate writable volume.

The release ships no Helm chart, Compose file, or hosted offering. Scheduling, TLS termination,
and the proxy in front of the listener are yours. The Docker use in the first tutorial is a
loopback development path, not a deployment pattern.

{/* Evidence: crates/registry-breg/install.sh; release/docker/Dockerfile.breg;
    crates/registry-breg/src/postgres/catalog.rs, CatalogFingerprintVersion;
    products/breg/quickstart/README.md. */}

## What stays your job

**Secrets.** You hold two database credentials, the audit hash key, the cursor secret, one key per
webhook destination, and the issuer's key material when you pin a static key set. The runtime
file names each of them by reference and refuses one that carries a value inline.

**Every production change.** A one-line access widening takes the same path as a new registry: a
production check, a test run against a schema-test database with real tokens, packaging, and a
`plan` and an activation under the migration credential in each environment. A change the tooling classifies as
additive needs no more; one it marks for review needs a reviewed migration with a rehearsal, and a
destructive one names its backup. A failed activation holds the database in maintenance until you
reconcile or restore.

**The audit journal.** Each audited request writes minimized entries through a file or stdout writer.
You ship the streams from every process to append-only storage and verify delivery before local
retention expires. The product does not provide tamper evidence.

**Retention and erasure.** Erasing a record's history is a bounded operator command with no undo.
It removes at most 10,000 revisions per transaction. Restoring snapshot coverage afterwards
verifies every live row in one transaction that holds writes until it commits. Retained webhook
payloads expire after a configurable number of days, at most 30.

{/* Evidence: crates/registry-breg/src/runtime_config.rs, AuditConfig, CursorConfig, DatabaseConfig,
    and MAX_WEBHOOK_PAYLOAD_RETENTION_DAYS; crates/registry-bregctl/src/lib.rs, ApplyArgs and MigrationCommand;
    crates/registry-breg/src/migration_reconcile.rs; crates/registry-breg/src/audit.rs;
    crates/registry-breg/src/history_erasure.rs, MAX_ERASURE_REVISIONS;
    crates/registry-breg/src/history_rebaseline.rs. */}

## Capacity

No throughput or latency figure is committed. A load-test harness ships with the product and its
own note asks you to run it on a representative Linux host before you cite a number. What is
bounded by construction is easier to state: every request, lock, and migration runs under an
operator-set timeout, the connection pool has a maximum size, spatial responses are capped and
refuse rather than truncate, and metrics label sets are closed. The runtime applies no request rate
limit of its own, so a registry that admits anonymous reads belongs behind one.

{/* Evidence: products/breg/loadtest/README.md; crates/registry-breg/src/runtime_config.rs, OperationalTimeouts;
    crates/registry-breg/src/postgres/config.rs, PoolBounds; crates/registry-breg/src/metrics.rs;
    products/breg/SPATIAL-QUERIES.md. */}

## Stability

Registry Stack is pre-1.0, so a minor release may contain breaking changes, announced in the
release note, and security fixes land only in the latest release; see
[API stability](../../reference/api-stability/) and the
[support window](../../security/support-window/). The runtime configuration format is at its first
alpha version. The security posture is fixed: the product's invariant matrix names each package,
role, row, and claim boundary with the negative test that enforces it.

{/* Evidence: docs/site/src/content/docs/reference/api-stability.mdx;
    docs/site/src/content/docs/security/support-window.mdx;
    crates/registry-breg/src/runtime_config.rs, RUNTIME_CONFIG_API_VERSION;
    products/breg/contracts/security-invariant-matrix.yaml. */}

## Next

- [Build a production candidate](../../tutorials/build-a-breg-production-candidate/)
- [Deploy a registry](../../operate/breg/)
- [Bind webhook receivers](../breg-webhooks/)
- [Retain, erase, and audit](../breg-retention/)