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

# Prove an Evidence Gateway project

> Add fixtures that describe your own requirement and run them through the Evidence Gateway evaluator before a production build.

Start with an editable project: the directory `evidencectl init` created, holding `questions/`,
`derivations/`, `fixtures/`, and its source objects. It has no `runtime.yaml` and no `bundle/`;
those belong to the candidate `evidencectl package` produces later. If you need to create a project,
[connect an institution source from OpenAPI](../connect-an-institution-source/) or
[get your first assertion](../first-evidence-assertion/) before adding fixtures. Fixtures are
executable claims about your own Evidence Gateway project. They are not sample data for a first
run and they must not be generated from an unrelated domain.

Use them when your source, requirement, and derivation are ready for review. Local assurance lets a
project load without them, but the run below is not a formality you can pass with an empty suite: a
run that evaluated no case refuses with `no case was evaluated, so this run proves nothing: every
fixture the project references must declare at least one case`. Production and evidence-grade
assurance require complete fixture coverage before the bundle loads.

## Add the governance each question hands off

The fixture runner compiles the editable project the way a production build compiles it, so the
governance a candidate needs is required before the first fixture run, not at build time. Give
every question a `governance` block and every answer a stable concept identifier:

```yaml
answers:
  - concept: is_adult
    id: urn:example:concept:adult-status:v1
    type: boolean
governance:
  requirement: urn:example:requirement:adult-status:v1
  kind: criterion
  referenceFrameworks: [urn:example:framework:adult-status:v1]
  evidenceType: urn:example:evidence-type:adult-status:v1
  validitySeconds: 300
  observationTimezone: UTC
  fixtures: fixtures/adult-status.yaml
  disclosureFamilies: [urn:example:disclosure-family:adult-status]
```

Three rules decide whether the run starts at all:

- A question with no `governance` block stops the run with `evidencectl: compiling editable project
  for fixture evaluation: every production question requires governance`.
- An answer with no `id` stops it with `every production answer requires one stable concept id`.
- `governance.fixtures` must be exactly `fixtures/<name>.yaml`, a path inside the project. No
  requirement, framework, Evidence Type, disclosure family, or concept identifier may be one of the
  disposable `urn:registrystack:evidence:local:` URIs that a local generation issues.

The project a local tutorial leaves behind satisfies none of this, so adding governance is the
first change to make here. The Evidence authoring form reference states these three beside the
other refusals a project meets on the way to a candidate, under
[Rules that block a build](../../products/registry-evidence/authoring-form/#rules-that-block-a-build).

## Write cases for your requirement

Place the fixture file under `fixtures/` in the editable project and name it from the question's
`governance.fixtures`. Keep every value synthetic and sanitized.

Cover behavior your reviewers need to approve:

- one ordinary positive result;
- one legitimate negative value, or an unresolved case when false would be misleading;
- each important boundary in the derivation;
- missing required facts, which the extractor generated from OpenAPI fails as
  `source.unavailable` rather than as a `no_match` or `ambiguous` outcome; get a real `no_match` or
  `ambiguous` by hand-editing the extractor, as
  [Finish extraction and facts](../connect-an-institution-source/#finish-extraction-and-facts)
  covers;
- mistyped required facts;
- malformed and unavailable source responses;
- output outside the governed codelist or schema;
- privacy expectations proving source fields and selector values stay out of evidence and
  diagnostics;
- anti-reconstruction cases for concepts that must not be released together.

The fixture format is closed. Start from the
[fixture contract](https://github.com/registrystack/registry-stack/blob/main/products/evidence/reference/request-adapter/deployment-projects/FIXTURES.md),
then keep only cases that express your project.

## Run the project suite

From any directory, run:

```sh
evidencectl check "<evidence-project>" --deny-findings
evidencectl test "<evidence-project>"
```

The first command validates authored completeness without contacting a source, identity provider,
or database. It reports each gap with its file path and a corrective action. The second command
asks the `evidence` binary for its version first and refuses one that is not its own,
then compiles the editable project into a private staging bundle, runs `evidence bundle-check`
against it, discovers the fixture files the compiled bundle captured, and drives each one through
`evidence bundle-evaluate`; pass `--evidence-bin` when the matching binary is not the first
`evidence` on `PATH`. The run does not start HTTP, resolve a source credential, call the source, or
write the production audit log. The served HTTP path remains a separate integration check.

A passing run reports the check and one line per fixture:

```text
PASS: check
PASS: fixtures/adult-status.yaml (8 cases)
2 passed, 0 failed (8 cases evaluated)
```

Use JSON output in CI:

```sh
evidencectl test "<evidence-project>" --format json > fixture-report.json
```

Treat any failed case, missing reference, unknown field, or unsupported expectation as a failed
build input. Do not convert a real failure into an ignored case.

## Read a failed case

A failure names the contract that broke, which says a case failed but not where it stopped. Ask the
run to explain itself:

```sh
evidencectl test "<evidence-project>" --explain
```

Each fixture prints one JSON trace after its result line. The trace holds one entry per case, with
the case `id`, its `expectedResult` and `observedResult`, the `reasonCode` the run settled on, and
one `stages` entry for every stage that case reached: `prepare`, `acquire`, `extract`, `derive`,
`validate`, and `sign`. Every stage carries its own `status` and a short `note`, such as the keys a
response was projected to or the concepts the output gate accepted. A failed case adds `failure` and
`findingCodes`, and its `stages` list stops at the stage that ended the case, so read that last entry
first.

To explain one fixture on its own, or one case inside it, name them. The paths are the ones the
compiled bundle captured, which are the project's own `fixtures/` paths:

```sh
evidencectl test "<evidence-project>" \
  --fixture "fixtures/<cases>.yaml" --case "<case-id>" --explain
```

The trace reports shapes: member names, counts, and identifiers. It never prints a response, fact,
derived, or selector value, and a run whose trace holds a value the fixture declared under
`privacy_expectation.diagnostics_exclude` is refused before the trace is printed. The flag changes
no outcome, exit code, or message, and it is offline only: a served request is diagnosed from its
public problem and the audit log instead.

## Check the deployable inputs

An editable project has no runtime document to check. Its deployment target keeps `runtime.yaml`
outside the package and points `package.root` at the installed package. Run `evidence check`
against that target runtime after installing the package:

```sh
evidence check --runtime-config "<deployment-target>/runtime.yaml"
```

This validates the complete captured bundle, scripts, schemas, codelists, key references, and
runtime bindings, and it initializes the configured signer, so a production or evidence-grade
candidate needs its Transit proxy already running. Source credentials are checked by readiness when
the service starts, not by the offline fixture runner.

During local authoring, keep the project writable so changes are convenient. Freeze inputs only
for the deployable revision: make the runtime and bundle non-writable to the service identity, or
mount them read-only, then rerun the check against those exact bytes.

## Hand off the reviewed inputs

Evidencectl has no generic `promote` command. Your deployment system owns approval, artifact
transport, rollback, and environment binding. Use `evidencectl package` to create a new candidate
from the editable project and one explicit production target.

Build and hand off only when these facts are recorded together:

1. The fixture suite passed against the editable inputs and generated package.
2. `evidence check` accepted the exact installed package and target runtime.
3. A reviewer approved the source projection, cardinality mapping, requirement, derivation,
   codelists, purposes, audiences, and privacy expectations.
4. The environment supplies a governed public signing key and matching Transit binding, plus
   independent owner-only subject-binding and audit secrets.
5. The deployed package digest matches the reviewed package and the runtime pins it with
   `package.expectedDigest`.
6. Readiness passes, followed by one authorized HTTP-path check using synthetic data.

Build a complete governed bundle for each environment. Each target owns its identities, endpoints,
audiences, public keys, authority bindings, runtime paths, secret references, audit storage,
listener settings, and trust files. Promote the reviewed editable source revision, then build
staging and production candidates separately. [Build and deploy an Evidence Gateway project](../build-and-deploy-evidence-project/)
covers the target-host ceremony.

## Next

- [Verify an assertion as a consumer](../verify-an-assertion-as-a-consumer/)
- [Rotate Evidence Gateway signing keys](../rotate-evidence-signing-keys/)
- [Build and deploy an Evidence Gateway project](../build-and-deploy-evidence-project/)