Released docs. You are viewing the documentation published with v0.25.0. Development docs are available at Latest.
This page is for a reviewer or auditor who already reasons in terms of assets, trust boundaries, and adversaries, but does not yet know where the Registry Stack’s boundaries actually sit. It answers one question: why does this design produce the security properties it claims: which threats does the architecture consider, what does it actually mitigate, and where do the residual risks lie? It is deliberately a map of boundaries and limits, not a runbook. Hardening procedures belong to the hardening checklist, and the invariant-by-invariant statement of what the Evidence Gateway runtime enforces belongs to the Evidence Gateway security model. Here the goal is a defensible threat model: the boundaries the design draws, the threats it places in and out of scope, and the residual risks.
The two-layer architecture and its primary trust boundary
Section titled “The two-layer architecture and its primary trust boundary”The stack is a two-layer design, and the split between the layers is the first trust boundary the model relies on. A portable metadata layer only describes: it carries no production data, no authentication, and no secrets. A runtime services layer enforces: it is where authentication, authorization, and disclosure actually happen.
The consequence for a reviewer is that the metadata layer authorizes nothing, enforces nothing, and does not assert that any record exists or satisfies a question. Publishing a dataset, a policy, or an offering does not grant access and is not proof that a record exists. Read this strictly for policy documents: a published ODRL policy describes intent and nothing enforces it. Registry Manifest can carry an ODRL policy reference and an enforcement profile identifier, but no current runtime service reads them, so treat a published policy as a statement about a deployment rather than a control the stack applies.
This also closes one threat directly: because the metadata layer is meant to be distributed and inspected, secrets are never embedded in it. The operator injects them at deployment, which keeps secret material out of the portable artifact entirely.
Components and where they sit on the boundaries
Section titled “Components and where they sit on the boundaries”Four formal components sit on or beside the trust boundaries, with one supporting service beside them. A separate adopter demo sits outside the production trust boundary:
- Registry Manifest: the offline metadata producer. No production data, no auth, no secrets. It lives entirely on the describe side of the primary boundary.
- Registry Relay: a contract-compiled read-only API over local read-only SQLite sources. It makes no outbound source call, holds no source credential, and signs nothing.
- Evidence Gateway: a minimum-disclosure assertion service. It answers one bounded, predefined question about one subject with a signed assertion carrying the answer and not the record.
- Registry Platform: the shared security primitives that the runtime services build on.
- Registry Mint: a supporting service, not a pattern of its own. It issues the short-lived access tokens a resource server such as Evidence Gateway verifies, for a deployment with no identity provider. The dependency runs one way: Evidence Gateway does not depend on Registry Mint.
- Solmara Lab: a separate adopter demo, running on synthetic data and demo configuration. Treat Solmara Lab as out of scope for production trust. Its demo and template integrations are integration examples, not a production freshness or replay-protection profile, and a team copying them into production must add request freshness, expiry, or nonce checks itself.
This model has no credential-issuance or peer-federation boundary, because no product here has one: Evidence Gateway issues no credential lifecycle and evaluates nothing on a peer’s behalf.
Security-critical primitives are concentrated in Registry Platform so that the behavior is identical across services and reviewable in one place. This is a deliberate attack-surface decision: it removes the risk of divergent, per-service security code that would each need auditing separately.
Trust boundaries in detail
Section titled “Trust boundaries in detail”The service edge (authentication). Authentication is the trust boundary at the service
edge, and each service authenticates every record- or assertion-bearing route before
responding. Registry Relay has exactly one authentication mode, OIDC bearer, and it is
per-operation rather than per-route: an operation whose compiled access profile is Protected
requires a verified token carrying the declared scope, and one whose profile is Public does
not. A Relay contract with any protected operation refuses to start without a configured issuer,
so a deployment cannot leave a protected operation unauthenticated by omission. There is no
static-credential mode and no API-key mode; the runtime reads no credential from configuration.
Evidence Gateway runs one reviewed OIDC bearer profile with exactly one trusted
issuer and exact audience, token type, and algorithm allowlists, and one configured principal
claim with no client_id, azp, header, or request fallback: missing data denies rather than
falling back to another claim (V1-I04). Evidence Gateway’s unauthenticated surfaces are operational
and discovery only: /health, /ready, /openapi.json,
/.well-known/evidence/jwks.json, and /.well-known/jwt-vc-issuer. None of them reveals
which evidence definitions are enabled or which requesters may invoke them. Evidence Gateway never
trusts a proxy-supplied identity header, whatever the gateway in front of it asserts.
Caller to Evidence Gateway. This is the boundary the whole product exists to draw. The caller crosses it with a bearer access token, a declared purpose, a named requirement revision, and selector values for the subject roles that requirement declares; what comes back is the answer, not the record. Four properties hold it:
- Only predefined, versioned requirement revisions are evaluable, and the request schema is
closed. A caller cannot supply thresholds, expressions, scripts, paths, headers, source
fields, relationship types, adapter parameters, or response projections (
V1-I01,V1-I02). - One authorization decision binds requester tags, optional actor, requirement revision,
purpose, every role, profile, and origin tuple, authority, and audience together. Partial
matches across separate grants cannot be unioned into access, and exactly one authority
path must match: zero paths and two or more paths both deny (
V1-I05). - Possession is not authority. A selector value, a demographic tuple, or a caller-supplied
consent, approval, or grant reference is a lookup input, never proof that the caller may
ask (
V1-I06,V1-I07). - What is released is constructed by the core after full output validation, from declared
typed concept values only. A script cannot inject envelope fields, subject identifiers, or
unsupported claims (
V1-I12,V1-I25).
Purpose is enforced rather than advisory: an unauthorized purpose is denied before credential acquisition and source contact, purpose is an input to every subject binding and audit pseudonym, and purpose sits inside the signed payload where a verifier can reject a mismatch. A reviewer should still read a declared purpose as the caller’s authorized selection from the granted set rather than an identity-provider attestation, unless the operator has issued a distinct requester tag per purpose.
Evidence Gateway to its fixed sources. Evidence Gateway’s outbound edge is deliberately not
general-purpose. A source reaches its data over one of two coequal transports, a fixed HTTP JSON
request or one reviewed SQL statement against a read-only SQLite extract file mounted beside the
process, and the core owns both. Source calls are fixed by trusted bundle configuration and
executed only by the core, which owns the closed single or search-then-fetch sequence, the limits,
and the one-request-per-stage ceiling on either transport, and on the HTTP transport also the
origin, method, fixed or tagged selector or prior-fact-bound path, fixed headers, authentication,
TLS, projection, redirect denial, and proxy denial; this is what closes SSRF, credential
forwarding, script-directed networking, and response-led routing (V1-I09, V1-I40). A preparation
script renders only ordered query pairs and at most one JSON body on the HTTP transport, or a
bounded map of scalar parameters on the statement transport, and Rust validates that output
before a credential is resolved or a row is read. Every source declares a response schema
that Rust validates the projected response against before any extraction script runs, so a
response outside its reviewed shape is a source-protocol failure rather than an input to fact
construction. Lookup collapses to match, no_match, or ambiguous: Evidence Gateway never fetches
broad candidate sets, follows pages, scores candidates, or exposes counts (V1-I10). Raw
source responses are never persisted or logged (V1-I14). Hostname and fixed-origin
verification stay mandatory, there is no trust-all mode, and ambient HTTP_PROXY-family
variables are ignored.
The statement transport has none of those fields to fix: a statement source has no origin, scheme,
host, port, method, path, request or response media type, redirect policy, or header, and Evidence
Gateway holds no database credential for it.
What trusted configuration fixes there is the one reviewed SQL statement with its declared result
columns and parameter bindings, the read-only extract file the runtime binds by logical profile,
and the row, cell, statement-step, timeout, response-byte, and concurrency limits.
Registry Relay and Evidence Gateway remain separate. A deployment may operate both products, and neither inherits the other’s decisions. Evidence Gateway reaches its own configured authoritative sources over either transport: a fixed HTTP JSON request, which does cross a network boundary, or one reviewed SQL statement against a read-only SQLite extract file mounted beside the process, which does not. Relay reaches no source over the network at all, and reads its own local SQLite file. The two local reads are still not the same thing: Relay compiles a whole registry contract into the fixed route set it serves over its source, while an Evidence Gateway statement source runs one reviewed statement and returns one assertion. Each product owns its own credentials, authorization decision, audit trail, and readiness checks. One composition is supported, and it runs one way only: a Relay-served API is an ordinary protected HTTP endpoint, so an Evidence bundle may name one as a fixed HTTP source. That is a deployment choice, not a feature either product declares. Relay does not know it is being read, and Evidence Gateway still makes its own authorization and disclosure decision. A reviewer should reject a deployment description that treats Relay authorization as Evidence Gateway authorization.
Registry Mint to Evidence Gateway. Registry Mint issues access tokens; Evidence Gateway verifies them as
an ordinary resource server. The dependency runs one way, and Evidence Gateway’s only knowledge of
Registry Mint is an issuer URL and a key set: it reads every claim by the name in its own
authentication block, so any issuer writing those claims serves equally well. Registry
Mint’s tests drive Evidence Gateway’s authenticator, and Evidence Gateway does not depend on Registry Mint.
What a reviewer checks depends on which of the two shapes the deployment runs:
- With Registry Mint. The client registry becomes part of the trust boundary. Registry
Mint verifies the registered client’s selected authentication method, a signed assertion
against only that client’s public keys by default, or an explicitly enabled secret against
only that standard client’s fingerprints, then writes the authority from the registry and
never from the request. Secret credentials must be Mint-generated, unique per managed
installation, delivered outside configuration, and treated as lower assurance because a
native client can expose them to its operator. The
consequence is that whoever can write a registration file into
clients.directorycan mint a token carrying any requester tags, and the running process re-reads that directory onSIGHUPwithout a restart. Treat the registry directory as sensitive as the signing key. Registry Mint serves plain HTTP behind operator-terminated TLS, while Evidence Gateway requires an HTTPS issuer and key set with no loopback exception, so the TLS terminator is load-bearing. - Without Registry Mint. A deployment that already has an identity provider does not run Registry Mint at all; Evidence Gateway points at the provider’s issuer and JWKS directly. Tag issuance, client lifecycle, and revocation move entirely to that provider, and Evidence Gateway’s residual exposure is its trust in one issuer’s key set.
Both shapes share one property worth stating plainly: Evidence Gateway has no token revocation. A
minted or issued token is accepted until it expires, which is why token lifetime is bounded
short. If the issuer’s key set becomes unreachable, an already-retrieved key set keeps being
accepted for a bounded allowance and then every request is rejected with the same closed 401
a bad token receives, with the reason recorded only in the deployment’s own log.
Operator to signing key material, and consumer to the published key set. Private signing
material is core-owned and stays out of bundle values, Rhai, logs, audit, and errors
(V1-I23). Local development resolves a private JWK through the file secret provider, which
accepts only a regular, owner-only, non-symlink, single-hard-link file of the expected mode and
size. Production and evidence-grade deployments instead sign through a workload-local
Vault/OpenBao Transit proxy over a Unix socket, so the process receives no provider token or
exportable private key.
The operator governs one active ES256/P-256 public JWK whose kid is its RFC 7638
thumbprint, and retains each previous public key in the published JWKS for at least the maximum assertion
validity plus allowed clock skew. Signing is mandatory and fail-closed: a missing or failed
signer returns a safe transient failure and never falls back to unsigned output (V1-I22).
On the consumer’s side, the published JWKS is discovery, not a trust anchor. A verifier obtains
the provider identity and key-set location through governed configuration, pins that trust,
allowlists the expected algorithm, and resolves kid only within the trusted set; it never
follows a key URL supplied inside a message. Strict verification compares the response against
independently retained expectations, the expected nonce, the expected unordered set of unique
role-bound subject bindings, and the expected concept identifiers, forms, and cardinalities,
and reports one generic policy mismatch so verification is not itself an oracle (V1-I31).
A valid signature authenticates the provider and the payload; it does not assert legal-signature
status or that the underlying source fact is true (V1-I24).
Relay to its registry source. Registry Relay owns its own source boundary, and in this
version that boundary is a local file rather than a network edge. A Relay deployment binds one
or more SQLite files by path in its runtime file, opens each with SQLITE_OPEN_READ_ONLY,
observes only the SQL views in it, and executes only the statements the compiler produced from
the reviewed contract. Four properties hold it:
- The runtime rejects a symlinked database, a non-regular file, and a database carrying a
-walor-journalsidecar, so it never binds a database another process is mid-write on, and never follows a path an attacker redirected. - A
snapshotsource must be immutable to this process, either on a read-only filesystem or with no write bits, and is pinned by content digest plus device, inode, length, mode, and modification and change times. Alive-read-onlysource is pinned by device and inode. A replaced or altered file is refused rather than read. - A SQLite authorizer callback gates every caller-supplied statement as defense in depth behind the compiler, and positional SQL parameters are refused outright: only the named parameters the contract declared are accepted, bound by pre-resolved ordinal.
- Failures are categorical. The SQLite error type carries a kind and no value, so a source problem cannot leak a row, a path, or a statement into a response.
Assets protected by the design
Section titled “Assets protected by the design”The assets the design sets out to protect are:
- Private signing keys: The private signing key never leaves the service; only the public half is published through the JWKS route. A verifier needs no credential and no protected access to verify a stored response, which keeps verification off the protected side entirely.
- Person-level source data: The source is read in place and is never copied out wholesale. What crosses is bounded differently per surface, and the difference matters: behind an Evidence Gateway assertion no source row crosses at all, only a computed, disclosure-shaped answer; behind a Relay response the properties a compiled disclosure profile declares do cross, to a caller the operation’s access profile authorized.
- Audit integrity: Audit is treated as a security control rather than best-effort logging (see Audit as a control).
- Secret material: Bearer tokens, raw credentials, and key material are kept out of both the portable layer and client-facing surfaces.
The design treats these threat classes as security-relevant: authentication bypass, credential disclosure, audit redaction or integrity failure, signing-key handling bugs, source data leakage through a governed read, and privacy regressions that expose raw subject identifiers.
Threats the design considers and mitigates
Section titled “Threats the design considers and mitigates”- Secret material in deployment configuration: Relay holds no source credential, because its
source is a local file. The only secrets it resolves are the audit chain integrity key and the
optional cursor integrity key, and both are named indirectly as
secret:env/<NAME>orsecret:file/<name>rather than written inline. The file provider accepts only a single flat filename under the runtime root, refuses traversal and nesting, opens withO_NOFOLLOW, and requires a regular file owned by the effective user, with mode0400or0600, and exactly one hard link. An Evidence Gateway statement source resolves no source credential either: that transport has no connection string, no secret reference, and no authentication kind, so it is credential-free by construction rather than by profile, and a credential that does not exist cannot leak, expire unnoticed, or be widened. An Evidence Gateway HTTP source is the case where a source credential does exist, and the bundle names it by logical secret reference rather than writing it inline. The one HTTP source that resolves none is thenoneauthentication kind, and it is credential-free by allowance rather than by construction: only alocalassurance bundle may declare it, only at a canonical numeric-loopback origin, and production and evidence-grade bundles reject that kind. - Token forgery or acceptance of untrusted tokens: A token is trusted only after signature verification against the configured issuer JWKS, plus issuer, audience, token type, and algorithm checks. The service still owns its route scopes and grants regardless of what the token asserts.
- A sender-constrained token replayed as a bearer token: Evidence Gateway denies an access token
carrying an RFC 7800 proof-of-possession confirmation claim rather than accepting it as an
ordinary bearer, because it validates no sender proof and accepting one would silently
discard the constraint the token was issued under (
V1-I32). - Privilege escalation or over-reach: Authorization is deny-by-default. Relay refuses unauthorized callers before source work; Evidence Gateway requires exactly one complete entitlement match before audit, credential resolution, or source access. Reach is never widened at request time.
- An existence or matching oracle: No-match, ambiguous, missing-fact, and
inconsistent-derivation outcomes collapse by default to one public problem shape, with the
granular category kept in audit without counts, so response shape, message, or timing cannot
be used to probe registry membership (
V1-I16). Every authorization refusal likewise collapses to one genericevidence.deniedproblem that does not reveal which check failed. - Cross-purpose or cross-relying-party tracking: Subject bindings are derived with a keyed,
domain-separated function over audience, purpose, role, profile, key version, and the
complete canonical selector bundle, so the same person is not linkable across purposes or
relying parties (
V1-I17). - Information leakage in error, log, and telemetry surfaces:
problem+jsonbodies carry stable codes only. Selector, source, and disclosed values never appear in logs or native audit (V1-I15), and operational telemetry is off by default, served only on a separate operator-private listener, with every series label drawn from a closed set rather than from request content (V1-I33). Relay exposes no metrics endpoint at all, maps each request URI onto a closed set of literal route shapes before logging it so no identifier or query value can reach a log line, and accepts only six fixed values forRELAY_LOG, collapsing anything else toinfoso the variable cannot switch on a dependency’s own logging of URLs or headers. - Over-collection through the request: The caller names a requirement and supplies only the
selector values that requirement’s named profiles admit. Undeclared concepts, extra fields,
and values violating type, codelist, cardinality, precision, or size bounds are rejected
before evidence construction (
V1-I12). - Payload substitution and unsigned success masquerading as verified evidence: The signed
flattened JWS is mandatory, available to every authorized grant issuing under the
audience-scoped subject binding, and the default response.
Unsigned output exists only through its own exact media type, and only when both the
immutable bundle and the one matched grant permit it; requesting a format creates no
permission of its own (
V1-I21,V1-I28). The unsigned envelope is self-identifying and is rejected by the strict JWS verifier, so it cannot be stored and later mistaken for signed evidence. - A release with no accountability record: The final immutable response bytes exist before the
disclosure-release audit is durably accepted, and those exact bytes are what is released
afterward. Every authorized-material native audit event records the closed response-protection
mode, with a signing key identity present exactly for a cryptographically protected release,
while the minimal authorization-refusal event records neither field (
V1-I29,V1-I30). - Unreviewed hot mutation of policy: Configuration is immutable for the life of the serving
process. There is no runtime override, reload, merge, or fallback path, and the closed
runtime file cannot reach any governed field (
V1-I18). - Cross-tenant confusion: One process serves one operator-controlled trust domain, with one
service trust domain, issuer governance boundary, bundle lifecycle, signer, and audit
boundary (
V1-I19). - SSRF and uncontrolled egress: Relay closes this by construction rather than by policy. It
reaches no source over the network, so there is no source origin, no destination, and no
request an attacker could steer. Its only outbound traffic is OIDC discovery and JWKS
retrieval against the one configured issuer, over an
httpsdiscovery URL with no userinfo, query, or fragment, which must be byte-identical to its canonical form and must end in/.well-known/openid-configuration. The health-check subcommand refuses a URL carrying userinfo, a password, a query, or a fragment, disables proxies, and follows no redirect. Evidence Gateway’s fixed executor closes the same class for its own HTTP sources: origin, method, path authority, headers, authentication, TLS, projection, redirect denial, proxy denial, and a one-request-per-stage ceiling, with scripts controlling request flow only inside that host-enforced authority. Evidence Gateway’s statement transport closes the class the way Relay does, by construction rather than by policy: that transport opens one local extract file and has no origin, no scheme, no host, no port, and no network path into a registry data tier, so there is nothing for a URL security rule or a redirect denial to govern and no destination an attacker could steer. - A hostile or defective reviewed script: Evidence Gateway’s script engine has no filesystem, environment, network, process, or module access, no ambient clock or randomness, and a normative operation ceiling that terminates a runaway invocation with a closed, value-free error. On the statement transport a script additionally never receives the statement text, a SQL fragment or constructed SQL, the extract path, the file handle, or the database connection, and Rust binds every value into the prepared statement by index rather than rendering it into statement text, so a statement’s shape is identical for every request it serves. Statement parameters are named only, and a positional parameter is refused.
- A caller widening its own read (Relay side): a Relay caller supplies only the named parameters
the compiled operation declares, and cannot add a filter, a projection, a source column, or a
statement. Where an operation declares an authority row binding, every row it returns is pinned
to a value taken from the caller’s verified token, either a named claim or the principal
identifier, injected as a bound SQL parameter under an exact-equality
COLLATE BINARYpredicate rather than concatenated into a statement. A caller cannot substitute that value, because it is never read from the request. - Tampering with the governed contract on disk (Relay side): at startup Relay re-runs the compiler and the artifact generator over the sealed authored inputs and requires byte-for-byte equality with what the package claims, before it opens a source, an audit sink, or a listener. It also refuses a package or runtime file whose path contains a symlink or a component owned by a third party or writable by group or other. This detects a modified package; it does not authenticate one, because the package is not signed.
Audit as a control. Evidence Gateway writes one mandatory access-attempt record before every actual acquisition stage, plus one disclosure-release record per successful response. Each access-attempt event must be durably accepted before its source read, and the disclosure-release event must be durably accepted after signing and before the response is released. Either failure blocks the corresponding action. The chain is keyed and hash-linked, has no severity levels and no way to turn records off, and carries reviewed identifiers and decision categories only: never raw selector values, per-field selector hashes, source values, credentials, tokens, or raw subject identifiers. Where correlation is required, one keyed, domain-separated, versioned pseudonym covers the complete canonical selector bundle and is deliberately not globally stable across purposes or audiences.
Relay audits on the same principle under its own schema, registry.relay.audit/v2alpha1. It
records an attempt phase, a refusal phase, and a terminal phase, carrying resource, operation,
contract revision, access and disclosure profile names, transform identifiers, and the principal
kind, and never a row value or a selector value. Failure to durably accept a record refuses the
request with a 503 audit.unavailable problem, and this is not configurable: there is no
best-effort mode to fall back to. Readiness re-verifies the sink, so replacing the audit file
under a running process takes the deployment out of /ready.
Three caveats for the auditor. First, exactly one Evidence Gateway process may write a given audit
path: the sink takes an exclusive advisory lock, because the chain head lives in process
memory and two writers would interleave records and destroy tamper evidence. That makes the
supported shape one replica per audit path, active/passive rather than active/active. Second,
startup recovers the chain head from the newest sealed segment and fully verifies only the
active segment, so corruption inside an already sealed segment is not detected at startup;
only an out-of-band evidence verify-audit pass over the whole directory detects it. Third,
audit records hashed principals and correlation identifiers, so operator-side investigation
depends on retaining the hashing secret and request context.
Residual risks and what is left to the operator
Section titled “Residual risks and what is left to the operator”The canonical inventory of every current limit is Known limitations and non-guarantees; the residual risks in this section are the subset a threat model must weigh.
These are the risks the design does not close:
- Key custody is not certified by health checks: Readiness, liveness, and offline validation confirm that governed key material and the selected signer agree. They do not independently certify the Transit service, workload-local proxy, or operator policy. A local-assurance deployment using demo-generated software keys can be reachable and internally consistent yet not production-secure. Custody, rotation, and provider approval remain operator responsibilities.
- The combined disclosure surface is a human review: The runtime validates one bundle at
startup and refuses two simultaneously enabled requirements that declare the same disclosure
family, but a declared family is a trusted operator attestation, not a semantic classifier.
Threshold ladders, overlapping categories, increasingly precise regions, and coexisting
revisions that together reconstruct a protected value are caught by the operator’s review of
the whole enabled bundle or not at all. Rate controls do not make an unsafe bundle safe
(
V1-I03,V1-I20). - Overlapping authority paths are not detected at startup: Startup validation does not detect two authority paths covering the same requirement, purpose, and subject tuple. At request time that ambiguity denies, which fails safe but presents as an unexplained refusal; the operator owns the review that prevents it.
- Rate limits are per process and in memory: The configured request, burst, and failed-selector budgets are tracked in one process’s memory, never shared across replicas, so running N instances behind a load balancer multiplies every limit by N and a restart resets each budget to full. This matters most for the failed-selector budget, because that budget, not throughput, is the selector-enumeration defense.
- A released assertion cannot be recalled: Evidence Gateway has no revocation, status list, or presentation-time check. The only levers over a released assertion are its declared validity window and signing-key rotation, and rotation does not invalidate assertions a retained public key still verifies.
- The request nonce is not replay protection: It is uninterpreted correlation data echoed into the payload. Reuse is not rejected, and no uniqueness check exists.
- The operator boundary is where coverage ends: Secret and key provisioning, key custody and rotation, audit retention, backup, restore and access control, tenant isolation, TLS termination and certificates, edge rate limiting, per-client quotas, deployment configuration, and incident response are operator responsibilities, not behavior the model defines.
- Aggregate data is not a privacy budget: Relay’s SDMX aggregate-data routes serve compiled statistical datasets and track no cumulative disclosure across repeated or overlapping queries. Per-operation quotas bound request rate, not information released. Do not describe a Relay aggregate as privacy-budgeted unless a separate deployed control provides it. This is a residual disclosure risk left to the operator.
- Relay quotas are per process and in memory: the configured requests-per-minute and burst budgets are a token bucket per compiled operation held in one process’s memory, never shared across replicas, so running N instances multiplies every budget by N and a restart resets each bucket. Treat them as an availability control, not an enumeration defense.
- A Relay package is not authenticated:
packageRevisionis a SHA-256 integrity digest that any holder of the package can recompute. Startup detects drift and tampering by re-deriving every artifact, but it cannot tell a legitimate package from a well-formed forgery. Package provenance is an operator duty: the delivery path, the filesystem ownership checks, and the release verification procedure carry it, not the package format. - Project approval remains a semantic control: Schemas and validators reject malformed configuration, duplicate identifiers, and unsupported modes. They cannot decide whether an institution selected the correct source fields, lawful purpose, derivation rule, or disclosure default. Those decisions require project review and fixture evidence.
- Admin reload is not a capability: neither product has an admin listener, a reload route, a posture endpoint, or a configuration apply path. Relay serves a fixed route set with no administrative surface at all, and Evidence Gateway has none either. A configuration change is a new reviewed revision and a restart, in both cases.
What is explicitly out of scope
Section titled “What is explicitly out of scope”These are non-goals for this version. None of them should be read into a Registry Stack conformance claim:
- A credential lifecycle: Evidence Gateway’s SD-JWT VC output is a second serialization of the same stateless assertion. There is no issuance session, credential offer, status list, revocation, reissuance, persisted credential state, or OID4VCI endpoint of any kind, in either subject binding mode. Under the default audience-scoped mode there is no holder binding ceremony either, and an optional caller-supplied holder key is echoed unverified into a confirmation claim rather than proved. A requirement that declares the holder-bound mode adds a proof of possession the relying party checks at presentation, and nothing else: the service appends no key-binding JWT, issues no challenge, and retains no presentation or replay state.
- Delegated or federated evaluation between peers: no service in this model evaluates a question on another deployment’s behalf, and there is no trust-chain discovery, peer registry, or cross-institution evaluation route.
- Identity resolution: lookup is match, no-match, or ambiguous. Evidence Gateway is not an identity-resolution or record-linkage engine and returns no candidate material.
- Cross-verifier credential use under the default binding mode: an audience-scoped subject binding makes an assertion meaningful to one relying party and correlatable across none. A requirement that declares the holder-bound mode opts out of this non-goal deliberately, and accepts the correlation that follows: holder key reuse links a holder across every verifier that sees it, and the service can neither prevent nor detect that. Batch issuance under distinct keys reduces the deterministic key-based link; it does not make credentials unlinkable, because members still share an issuance timestamp, purpose, requirement, Evidence Type, configuration revision, and disclosed values.
- Replay prevention at presentation: a relying party verifying a key-binding JWT compares the nonce from the challenge it issued, and comparing a nonce is not consuming it. The same presentation bytes verify again under the same stateless policy. RFC 9901 section 7.3 places the challenge lifecycle in the surrounding protocol, so issuing a nonce, retaining it, and retiring it are the relying party’s own duties.
- External policy enforcement of any kind: no runtime service in this stack evaluates an external policy. There is no policy decision point, no ODRL term enforcement, and no policy discovery. Registry Manifest can publish a policy reference, and that reference describes intent rather than naming a control the stack applies.
- Certified standards compliance: Aligning with a standard is not conforming to it. Speaking the shape of OIDC, OAuth 2.0, SD-JWT VC, CCCEV, or the rest does not certify conformance to any of them, and CCCEV-shaped output is not conformant to CCCEV 2.00. Relay’s aggregate-data routes speak a narrow aligned subset of SDMX REST 2.2.2 and its geospatial responses use CRS84 points; it is explicitly not conformant to OGC API Features, CQL2, EDR, or tiles.
- Adapters, connectors, and feature-gated protocol surfaces: Relay has none. Its route set is fixed by the compiled contract and does not vary by build feature, so there is no OGC API Features, Records, or EDR adapter and no SP-DCI synchronization surface to reason about.
- Non-Unix targets: both runtimes are Unix-only, and both fail closed rather than degrading. Evidence Gateway’s secret and audit invariants depend on owner, mode, no-follow, link-count, and open-file identity checks. Relay refuses to start on a non-Unix target outright, because its package and runtime trust checks have no equivalent there, and its published binary is built for Linux amd64 only.
Related
Section titled “Related”- RS-SEC-G: the security model
- RS-PR-EVIDENCE, RS-PR-RELAY: protocol contracts
- RS-ARC-G: the two-layer architecture
- Evidence Gateway security model: the invariant matrix and its tests
- Harden a production deployment: hardening procedures
- Data minimization and purpose limitation