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 Evidence Gateway

> The infrastructure, keys, and people a production Evidence Gateway deployment needs, what it does not depend on, and what stays your job once it runs.

If you are planning a production Evidence Gateway 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 the
local tutorials, which start disposable versions of everything on your machine.

## What you provide

- **A host for one process.** Evidence Gateway is a single binary that serves one trust domain.
  It runs on the platforms in [platform support](../../explanation/known-limitations/#platform-support).
- **HTTPS in front of it.** The process listens on a private address; your reverse proxy or
  ingress terminates TLS and routes traffic to it.
- **A token issuer.** Evidence Gateway verifies bearer tokens from one OpenID Connect issuer and
  issues none. Configure a compatible OAuth issuer for this role.
- **A signing key you control.** Production signing uses a Vault or OpenBao Transit key that never
  leaves the vault, reached through a proxy on the same host. A local development profile may use
  a key file instead.
- **Durable storage for the audit trail.** Every request appends minimized JSON lines to an audit
  file on disk, or to standard output for your log collector. The disk it lands on, and the
  append-only store you ship it to, are yours.
- **The authoritative source.** Each question makes one fixed request to a system your institution
  already operates, over HTTP or against a read-only SQLite extract. That system has to answer
  within the timeout you configure.
- **A reviewed bundle.** Your authors write the questions, sources, and derivations as a project
  and hand you an immutable bundle. You mount it read-only beside a runtime file that names the
  listener, paths, and secrets for this host.

{/* Evidence: products/evidence/OPERATOR-CONTRACT.md, "Supported deployment" and "Governed bundle
    and operator runtime"; products/evidence/CONCEPT.md; crates/registry-evidence/src/audit.rs. */}

## What it does not need

There is no database. Evidence Gateway stores no records, no requests, and no answers; the only
durable state it writes is the audit trail. There is no message broker, worker pool, cache, or
service mesh, and nothing requires Kubernetes. One process, one bundle, and one audit path make
one deployment. A second issuer, or a second customer who must not trust the first, means a second
deployment.

Registry Relay and Base Registry Engine are separate products, not dependencies. Evidence Gateway
can use either one as a source through the same fixed HTTP request it makes to any other system.

{/* Evidence: products/evidence/OPERATOR-CONTRACT.md, "Supported deployment"; products/evidence/CONCEPT.md;
    AGENTS.md. */}

## How it ships

Choose a published `<tag>` from the
[latest release](https://github.com/registrystack/registry-stack/releases/latest).

Each release publishes reproducible binaries for the runtime, the `evidencectl` authoring tool,
and the wallet delivery service, with an installer that verifies checksums before installing. It
also publishes `ghcr.io/registrystack/evidence:<tag>`, built on Distroless `cc-debian13` with no
shell and running as the nonroot user. The image runs `/usr/local/bin/evidence serve` with
`/etc/registry-evidence/runtime.yaml` and uses `/var/lib/registry-evidence` as its working
directory. Mount the runtime file, bundle, and secrets read-only, and mount the audit directory
read-write. The release manifest records the exact promoted digest. Deploy that digest instead of
the mutable tag.

Starting with v0.38.0, an eligible published release also carries the separate
`ghcr.io/registrystack/evidence-oid4vci:<tag>` image. Its installation and runtime paths are in
[Configure Evidence OID4VCI delivery](../../configure/evidence-oid4vci/#install-the-adapter).

The release ships no Helm chart or hosted offering. A Docker Compose file is a reasonable adapter
around the published image, and
[Deploy with Docker Compose](../../tutorials/integrate-evidence-candidate-with-docker-compose/)
shows the shape: the reviewed bundle mounted unchanged, a separate runtime file and secret root,
a persistent audit volume, and TLS in front.

{/* Evidence: crates/registry-evidencectl/install.sh; release/docker/Dockerfile.evidence;
    release/scripts/release_roster.py, EVIDENCE_OID4VCI_IMAGE_FIRST_RELEASE;
    release/VERIFY.md; products/evidence/README.md. */}

## What stays your job

**Keys.** You generate the signing key and the two audit and subject-binding secrets, and you
rotate them. When you rotate the signing key, the published key set has to keep every previous
public key for as long as an assertion signed with it may still be verified, or a verifier holding
an older assertion fails.

**Immutable inputs.** The runtime file and the bundle must not be writable by the service, and the
process refuses to start when they are. There is no hot reload or override layer; a change means
a new bundle, a fresh check, and a restart.

**The audit trail.** One process owns one audit path, so scaling out means several processes, each
with its own audit path, or a `stdout` destination gathered by your log collector. The file
rotates on its own and the runtime deletes sealed files after `retainDays`, so shipping each
sealed file to append-only storage before then is operator work, and that store is the only place
the log is tamper-evident.

**Readiness.** The health endpoint answers when the process is alive. The readiness endpoint fails
closed while any secret, signing provider, audit sink, or source credential is unavailable. Route
traffic on readiness. Metrics are off until you open a second, private-address listener for them.

{/* Evidence: products/evidence/OPERATOR-CONTRACT.md, "Secrets and keys", "Audit destinations,
    rotation, and retention", "Listener placement", and "Startup and readiness";
    crates/registry-evidence/src/audit.rs. */}

## Changing a published question

A deployment serves exactly one revision of each question. The bundle configures each requirement
URI once, and every assertion for it carries that requirement's `configurationRevision`, which a
relying party pins in its verification policy. Editing the requirement, its source, one of its
selector profiles, an authority grant that names it, or any script, schema, codelist, or fixture it
reaches moves that revision. From the moment the new candidate serves, assertions carry the new
revision and fail verification under the old pin. No window exists in which the same deployment
answers under both revisions, so decide what kind of change it is before you build the candidate.

**A semantic change mints a new requirement URI.** When the change alters what an answer means,
such as a different rule, threshold, concept, source of record, or disclosure, publish the new
question under a new requirement URI, for example `urn:example:requirements:adult-status:v2` beside
`...:v1`. Relying parties then choose when to move. Keep the old requirement in the bundle, with its
own grants, for an announced transition period, and remove it in a later candidate once that period
ends. A revision covers only what its own requirement reaches, so adding the new requirement leaves
the old one's revision alone, unless the two share a source, selector profile, or artifact that you
also edit. Both requirements are enabled together, so review the bundle as one disclosure surface
before the new one serves.

**A clarifying change is a re-pin event.** When the answer keeps its meaning, such as a corrected
script that returns the same answers, a tighter schema, or a moved source endpoint, keep the
requirement URI. The revision still moves, so every relying party that pinned the requirement
has to re-pin it. Announce the change before you activate the candidate: tell each relying party
that consumes the requirement what changes, why its meaning does not, and when the new revision
will serve, and leave a notice window long enough for them to review it. At the announced time,
activate the candidate. Relying parties read the new `configurationRevision` through authenticated
discovery at `GET /v1/evidence-definitions`, not from refused requests, and update their pins.

If you cannot tell which kind of change it is, treat it as semantic. A new URI costs a transition
period. A meaning change shipped as a clarification leaves a relying party accepting answers it
never reviewed.

Some edits move no requirement's revision at all: publishing, activating, retiring, or revoking a
signing key; revoking an identity-provider key; and changing runtime-only paths or listeners. They
change what relying parties trust or where the process runs, not what an answer means. The
[signing-key rotation](../../tutorials/rotate-evidence-signing-keys/) and
[verifier trust](../../tutorials/manage-evidence-verifier-trust/) procedures cover them.

{/* Evidence: crates/registry-evidence/src/bundle.rs compute_requirement_revisions canonical_projection;
    products/evidence/OPERATOR-CONTRACT.md, "Discovery of available evidence";
    products/evidence/reference/request-adapter/deployment-projects/CONFIG.md configurationRevision;
    products/evidence/contracts/security-invariant-matrix.yaml V1-I03. */}

## Capacity

No throughput or latency figure is part of the Version 1 contract. The cost that shapes throughput
is durability: a successful request pays two durable audit writes, or three when it searches before
it fetches, and the audit writer batches writes that overlap so a busy deployment amortizes the disk
barrier. Measurements taken on macOS are kept in the product's performance note, and it asks you to
measure again on the Linux host you will run before you size anything. Because each process owns
its own audit path, N processes give close to N times the throughput.

{/* Evidence: products/evidence/PERFORMANCE.md; products/evidence/OPERATOR-CONTRACT.md, "Measured throughput"
    and "Capacity planning"; crates/registry-evidence/src/audit.rs. */}

## Stability

Registry Stack is pre-1.0, so a minor release may change APIs and deployment contracts, and
security fixes land only in the latest release; see the
[support window](../../security/support-window/). Within that, the Evidence Gateway Version 1
assertion contract, runtime, and operator contract are implemented, not exploratory. Document
evidence, credential lifecycles beyond the SD-JWT VC serialization, multi-source answers, and a
public catalog are named non-goals, and a future profile would need its own approved concept.

{/* Evidence: AGENTS.md; products/evidence/README.md; products/evidence/CONCEPT.md;
    products/evidence/OPERATOR-CONTRACT.md, "Verification and release limit". */}

## Next

- [Test with fixtures](../../tutorials/prove-an-evidence-project/)
- [Configure a deployment](../../configure/evidence/)
- [Build a production candidate](../../tutorials/build-and-deploy-evidence-project/)
- [Configure Transit signing](../../tutorials/move-evidence-to-production-signing/)
- [Evidence Gateway security model](../../security/evidence/)