Skip to content
Registry StackDocsDevelopment (unreleased)

How Evidence works

View as Markdown

If you have run Your first assertion and want the model behind it before you design questions of your own, five questions settle most of it.

You define an Evidence project: an evidence.yaml file and the scripts it names, kept in version control. It declares four things.

  • Assertion definitions. Each entry under assertionDefinitions is one question with its Requirement URI, the purpose it serves, the subject roles a caller names, the source it reads, the outputs it may return, and the grant ceiling no caller can exceed.
  • Sources. Each entry under sources is one source, a fixed read, an HTTP request or one SQL statement over a read-only SQLite extract, with the response shape it accepts.
  • Selector profiles. A selector profile bounds what a caller may send to identify a subject. record-by-id admits one string field of 1 to 64 bytes, and a source’s path takes its value only from that field.
  • Functions. A Function is a small Rhai script with a declared interface. A source-extract/v1 Function turns the source response into facts; an assertion-derive/v1 Function turns facts into outputs. Functions run under fixed operation and size limits and cannot import code.

Evidence has no built-in domain: adult status exists only because a project declares it.

Beside the project sit two files an operator owns. A target, such as local-target.yaml, binds the project to one deployment: the token issuer, the source endpoints and their credentials, the signer, and the audit path. A target authority, such as dev-authority.yaml, names the access profiles that may call and the grants each holds. A grant can only narrow a definition’s grant ceiling; Registry Evidence refuses to activate one that widens it.

An answer is a value the definition declared, computed from the source, never the record. Each output names a concept URI and one of twelve types, and the type decides what the source value may become before it leaves. A boolean says only true or false: adult-status derives one from a birth date the caller never sees. A controlled-category or controlled-code says which entry of a reviewed list applies, a date-bucket which reviewed period, and a bounded number stays inside declared bounds. reviewed-structured-value, a small structure under a closed schema, is the widest type and the one to justify hardest. An output whose value falls outside its declaration is refused.

How much a definition reveals is fixed when it is written and reviewed, and it is the same for every caller and purpose allowed to ask. A request carries a nonce, the Requirement URI, the purpose, and one selector per subject role; nothing in it chooses a disclosure level. The representations a definition permits, a signed JWS or an SD-JWT VC, change the encoding, not the values.

Two refusals protect what the answer leaves out. No match, an ambiguous match, a missing fact, and an unresolved input all reach the caller as one problem, evidence.unavailable, so a refusal does not reveal whether a record exists; the audit keeps the outcomes distinct for the operator. A subject appears in the answer only as an opaque subject binding scoped to the audience that asked, so two relying parties asking about the same person cannot join their answers.

Minimization is modelled, not automatic: two definitions each defensible alone can reconstruct a protected value between them, so the operator reviews the enabled definitions together.

evidencectl package compiles the project and its target into an immutable bundle, a runtime file, and a compiled authority; evidence authority activate records the authority. One evidence process serves them as read at startup, so a change means a new package or activation and a restart.

Each request passes five stages: the selectors are checked, the source is read, the Functions run, only declared outputs are accepted, and the assertion is signed with its definition’s configurationRevision.

Registry Evidence keeps no database and no copy of a source response. Two things it keeps are durable. The audit trail records an access event before the source is read and a release event before the response leaves; if the release event cannot be written, the caller gets a 503 and no assertion. The authority state file, authority-state.json, holds the active target authority and the history of every activation.

Your institution keeps the record. The relying service verifies the answer and owns the decision made from it; an assertion grants no approval and no right to write anywhere. Registry Evidence inherits no authority from its sources: a Base Registry Engine route is one more HTTP endpoint, reached with Registry Evidence’s own credentials. Authors own the project and its fixtures. Operators own the target, the target authority, the signing keys, and audit retention.

evidencectl checks a project and runs its synthetic fixtures before anything serves, and verifies a retained response or reads a stopped session’s audit afterwards; the evidencectl reference lists each command.

Relying services pin the configurationRevision. It moves when you edit what a definition does, such as its source, selector profiles, Functions, codelists, or outputs, and stays put for question text, fixtures, endpoints, credentials, grants, and signing keys. A change in meaning gets a new Requirement URI, published beside the old one for an announced period; a clarification keeps the URI, and relying services read the new revision from GET /v1/evidence-definitions and re-pin. When you cannot tell which kind of change it is, treat it as a change in meaning.