Skip to content
Registry StackDocsv0.46.0

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 binds a reviewed Adapter pack route to a named connection and only the authorized selector fields it needs. The route acquires and normalizes facts, using HTTP reads or a reviewed statement over a read-only SQLite extract.
  • 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 route input takes its value only from that field.
  • Functions. A Function is a small Rhai script with the assertion-derive/v1 interface. It turns the route’s validated facts into declared outputs. Provider response normalization belongs to the pack. 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, named connections with permitted endpoints and credential references, 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.

Every assertion also states how its facts were obtained, in a signed channel member. source means Evidence read an authoritative source. holder-presented means the holder presented a credential from a wallet and Evidence verified it; that assertion also carries a presentedCredential member naming the trusted-issuer entry that matched, the credential’s issuer and type, its own issue time, and how the subject was linked, and no claim value. A definition chooses its channel in acquisition: the source block reads a source, and an optional holderPresented block reads a wallet presentation, with the request’s selector profile choosing exactly one and no fallback between them. A relying party’s verification policy decides which channels it accepts. The default accepts source only, so a holder-presented assertion is refused unless the relying party opts in with acceptedChannels, and maximumCredentialAgeSeconds can bound how old the presented credential may be. The wallet side is Verify a wallet presentation.

Definition discovery lists one entry per definition handle. When a caller is entitled to both channels of one definition, the entry keeps the source channel’s request shape and carries the holder-presented shape under alternatives, so a client that ignores the member requests as it always did. A channel the caller is not entitled to is never listed, and a caller entitled to the source channel alone receives the same entry, without a channel member, that a source-only definition produces.

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.

Can a holder check a certificate without an account?

Section titled “Can a holder check a certificate without an account?”

Yes, when the operator turns that on. A certificate carries a QR code with its number and a random check code. A static page sends both to one route, POST /v1/public-check, and Evidence answers the status (valid, suspended, revoked, or expired), the printed fields, and the time it checked, read from the source at that moment. The holder hands over the code, so no registration is needed. A wrong number and a wrong code get the same not-found answer. The answer is not signed; an institution that needs a provable answer uses the signed relying-service path on the same definition. The route is experimental.

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.