Released docs. You are viewing the documentation published with v0.20.0. Development docs are available at Latest.
Trusted context constraints are policy facts whose meaning must survive the boundary between a caller, the product that answers the caller, and the source registry behind it: why the operation is permitted, what purpose it serves, who may receive the result, and what safeguards apply.
Read one thing before the rest: Registry Relay and Evidence Gateway do not share an authorization model, a policy vocabulary, or a source path. No service in this stack authorizes a caller and then consults another service on its behalf. Each product enforces its own boundary against its own configured sources, under its own closed contract names.
There is no shared runtime policy vocabulary
Section titled “There is no shared runtime policy vocabulary”Earlier versions of this page described a shared policy vocabulary in a
registry-platform-pdp crate,
covering legal basis, consent, jurisdiction, assurance, and source freshness, which Registry Relay
consumed at request time. That is no longer the model. Registry Relay carries no policy decision
point, evaluates no external policy, and reads none of that vocabulary. The retired crate has
been removed.
What replaced it is narrower and easier to review: each product declares its own constraints in its own governed contract, and each enforces only what its own runtime can actually check. Where the two products use the same word, treat it as a coincidence of English rather than a shared control.
Relay records governance in the contract and enforces purpose in the token
Section titled “Relay records governance in the contract and enforces purpose in the token”Registry Relay separates two things that a shared vocabulary used to blur.
Declared governance. A registry contract carries a processingDescriptions block: one entry
per governed processing activity, each naming an identifier, the operations it covers, a purpose,
a recipient class, a reference to a legal-basis document, a reference to a DPV processing profile,
and a list of safeguards. These are closed, required fields of the contract, so a contract cannot
compile without them and cannot carry an unrecognized extra field. They are a reviewed declaration
sealed into the package, not a check the runtime performs on a request. Their visibility on the API
is set by metadataVisibility.processing, which is public, operation-bound, or operator-only.
Enforced purpose. Separately, an operation’s access profile may declare a purpose constraint: a claim name plus a closed list of allowed values. Relay reads that claim from the verified access token and denies the request when the value is absent or outside the list. The caller does not declare a purpose in the request, so a purpose is authority the issuer granted rather than a label the caller chose. The same is true of the authority row binding: where an operation declares one, the value that pins every returned row comes from a token claim or from the token’s principal identifier, never from a request field.
Two constraints that used to be Relay’s are simply gone, and no replacement exists: there is no consent-reference check and no jurisdiction check in the runtime. A contract can declare a jurisdiction in its authoritative scope and can name a consent-related safeguard in a processing entry, but those are review material for a human, not a gate the process applies.
Relay owns its source, and its source is a local file
Section titled “Relay owns its source, and its source is a local file”Relay owns source identity, the reviewed views it may read, the compiled statements it may run, and the properties a disclosure profile may return. In this version that ownership is much narrower than it used to be: the source is one read-only SQLite file per binding, opened in place, so Relay holds no source credential, negotiates no protocol, and adapts to no external system. See Records stay home for how that boundary is enforced.
There is no source-observation contract and no observed_at semantics. A Relay response carries
the values the reviewed view returns and states nothing about when the underlying record was
observed.
Evidence Gateway owns its own boundary
Section titled “Evidence Gateway owns its own boundary”Evidence Gateway authenticates the caller itself. It validates the bearer token against exactly one
configured issuer with exact audience, token type, and algorithm allowlists, and it reads the
principal from one configured claim with no client_id, azp, header, or request fallback.
Unsigned headers and caller request fields never substitute for authenticated authority, even
behind a gateway (invariant V1-I04,
Evidence Gateway operator contract).
Authorization is a single decision, not a series of separately satisfied checks. One exact
entitlement match binds requester, optional actor, requirement revision, purpose, every
role/selector-profile/value-origin tuple, subject authority, and audience together, and it happens
before audit, credential resolution, or source access. A request that does not match completely
contacts no source at all (invariant V1-I05).
Two consequences of that decision are worth stating separately, because they are the places where authorization is most often assumed rather than enforced:
- A selector is a provider-lookup input, never proof of authority. Selector validation happens
inside an already matched subject-authority path, so holding an identifier or a demographic tuple
does not entitle a caller to ask about that subject (invariant
V1-I06). - A consent, approval, or grant reference supplied by the caller never creates authority. Grant
identifiers are accepted only from authenticated context and must be bound to the complete
entitlement (invariant
V1-I07).
Evidence Gateway has no notion of a Relay operation or a compiled evidence mode selecting one. It
declares a closed single or search-then-fetch acquisition over HTTP sources with fixed origins,
methods, fixed or tagged selector or prior-fact-bound paths, fixed non-secret headers, denied
redirects, and client-side response projection. The core, not a script or response, executes the
sequence and enforces one request per configured stage (invariants V1-I09 and V1-I40). The source
boundary belongs entirely to Evidence Gateway and its authoritative sources.
Freshness has no counterpart in either product
Section titled “Freshness has no counterpart in either product”An assertion carries observedAt, which is when Evidence Gateway evaluated the requirement. It is
not a source-declared observation time, and Evidence Gateway Version 1 has no source freshness
family: there is no maximum accepted observation age, no freshness field, and no configuration for
one. The request nonce is uninterpreted correlation data and is explicitly not a freshness proof
(products/evidence/contracts/cccev-field-mapping.yaml).
Registry Relay has no freshness family either. A snapshot source is pinned to the exact bytes
captured at startup, so its answers are as current as the file an operator placed there and no more;
a live-read-only source reflects the file as other processes commit to it. Neither profile
attaches an observation time to a response, and neither bounds how stale the underlying data may be.
A deployment that needs an age bound on the underlying record has to define and enforce it outside these products: in the authoritative source contract for Evidence Gateway, and in the operational procedure that produces the SQLite file for Relay. Neither response carries one.
Reports and audit evidence
Section titled “Reports and audit evidence”Relay has no diagnostics command and no configuration report. What is inspectable about a running deployment is what its own metadata routes serve, under the visibility its contract compiled, plus its audit log. The processing entries described above are the deployment’s declaration of legal basis, purpose, recipient class, and safeguards, and an operator can choose to publish them, bind them to the operations they cover, or withhold them entirely.
Relay’s audit records the resource, the operation, the contract revision, the access and disclosure profile names, the transform identifiers applied, and the principal kind. It records no row value, no selector value, and no raw identifier, and the same discipline applies to operational logs, where each request URI is mapped onto a closed set of literal route shapes before anything is written.
Presence and allow-list checks remain distinct concepts even though only the allow-list form is
enforced here. Requiring that a purpose claim be present is not the same as approving every value
it might carry, which is why the purpose constraint carries an explicit allowed list rather than
a presence flag. Authentication-derived authority also remains distinct from an assurance value
asserted somewhere in a token: Relay checks the claims its contract names and attributes no meaning
to any other claim.
Review questions
Section titled “Review questions”- Does the contract’s
processingDescriptionsblock match what the deployment actually does, and has a human reviewed the legal-basis and DPV documents it references? - Is
metadataVisibility.processingset deliberately, rather than left at whatever the starter contract produced? - Does every operation that should be purpose-bound carry a purpose constraint, and does the issuer actually populate that claim?
- Does Evidence Gateway deny an unauthorized request before it contacts any source?
- Is every dimension of the Evidence Gateway entitlement matched as one decision rather than one at a time?
- Are Registry Relay and Evidence Gateway sources, credentials, authorization decisions, and audit trails kept separate?
- Where the deployment needs a freshness bound, is it enforced outside these products, and is that written down?