Skip to content
Registry StackDocsv0.38.0

What you need to run Base Registry Engine

View as Markdown

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, which starts disposable versions of everything on your machine.

  • 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.
  • 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 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.

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.

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.

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.

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.

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 and the 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.