Released docs. You are viewing the documentation published with v0.20.0. Development docs are available at Latest.
This document defines the HTTP protocol contract that Relay exposes: the sealed deployment model that fixes a service’s surface before it accepts traffic, the fixed route set, how a caller authenticates and selects an access profile, how a disclosure profile bounds what a response may carry, the Registry Core response envelope and its wire formats, cursor pagination, the Point and SDMX read profiles, and the audit and error behavior every request carries.
It refines the Relay component defined in RS-ARC-G Section 3 one level of detail down, from architectural boundary to wire behavior. Where this document and RS-ARC-G state the same constraint, RS-ARC-G is the general invariant and this document is its protocol-level form. The adopter tooling that produces the sealed package a Relay service serves is specified by RS-PR-RELAYCTL.
The key words in this document are interpreted per RS-DOC Section 2. Defined terms are used per RS-TERMS.
Version history
Section titled “Version history”| Version | Date | Status | Change |
|---|---|---|---|
| 0.1.0 | 2026-06-13 | draft | Initial protocol contract, distilled from the Registry Relay API reference, the publishing-pipeline explanation, the boundary map, and the generated OpenAPI document. |
| 0.1.1 | 2026-06-20 | draft | Document governed Relay PDP enforcement, aggregate authorization ordering, metadata filtering boundaries, and PDP audit provenance. |
| 0.1.2 | 2026-06-21 | draft | Clarified aggregate disclosure limits and privacy-budget boundaries. |
| 0.2.0 | 2026-07-07 | draft | Corrected REQ-PR-RELAY-020’s trust-context header names to the actual wire names, and clarified that the signed response credential surfaces of Section 8 are gated by runtime configuration (the provenance key), not a Cargo feature, distinguishing them from the genuinely feature-gated OGC and SP DCI adapters. |
| 0.2.1 | 2026-07-07 | draft | Documented additional request-context headers alongside REQ-PR-RELAY-020, noting they are not currently wired to any Relay policy decision. |
| 0.2.2 | 2026-07-09 | draft | Clarified that x-registry-source-observed-at-unix-seconds is scope guarded trust context, leaving four additional request-context headers outside Relay policy decisions. |
| 0.3.0 | 2026-07-09 | draft | Removed Relay-local signed response credential requirements and made Registry Notary the only credential issuance surface. |
| 0.3.1 | 2026-07-10 | draft | Scope-gated the remaining client-supplied trust-context headers, documented the policy-authoring boundary, and replaced exact trust values in audit records with keyed field-bound handles. |
| 0.3.2 | 2026-08-04 | draft | Recorded that Registry Notary is retired: Sections 7 and 8 no longer name it as the destination of an evidence offering or as the credential issuer, and REQ-PR-RELAY-012 now states the registry-notary access kind that the runtime binding still requires. No Relay behavior changed. |
| 1.0.0 | 2026-08-11 | draft | Rewritten for the Relay V2 runtime that replaced the V1 gateway. REQ-PR-RELAY-001 through REQ-PR-RELAY-023 are retired in full and MUST NOT be reused: they described a configuration-driven gateway over CSV, XLSX, Parquet, and PostgreSQL sources, per-dataset scopes, governed PDP enforcement, /metadata/* publication, evidence offerings, OGC and SP DCI adapters, and an admin listener, none of which exist in the current runtime. The V2 contract is numbered from REQ-PR-RELAY-101 so that no retired identifier carries a second meaning. |
1. Scope and references
Section titled “1. Scope and references”This specification covers Relay’s externally observable protocol behavior:
- The sealed deployment model and its fail-closed startup.
- The fixed route set and the not-found behavior around it.
- Authentication, access profiles, purpose, and row binding.
- Disclosure profiles, field selection, and record transforms.
- The Registry Core response envelope and its wire formats.
- Cursor pagination.
- The CRS84 Point profile and the SDMX read profile.
- Metadata, generated artifacts, and the per-deployment OpenAPI description.
- The audit obligation, the error format, and readiness.
This specification does not define:
- Exact schemas: each deployment generates its own OpenAPI 3.1.0 description from its compiled contract. There is no product-wide OpenAPI document, so this specification states behavior a schema cannot and does not restate request and response shapes that vary by deployment.
- The authoring form: the governed
registry.yamlgrammar an adopter writes, and the tooling that compiles and seals it, belong to RS-PR-RELAYCTL and the Relay authoring guide. - Security model internals: token verification, audit chain integrity, and cursor key handling belong to RS-SEC-G.
- Per-deployment shape: concrete resource identifiers, operation identifiers, access profile names, scope strings, and statistical dataset identifiers are contract data, not protocol data.
Relay returns unsigned responses. Portable, signed, minimum-disclosure assertions are a separate product specified by RS-PR-EVIDENCE. Media types and standards names are used per RS-TERMS and the standards register.
2. Sealed deployment model
Section titled “2. Sealed deployment model”A Relay service serves exactly one sealed package. The package is the governed trust root: it carries the authored contract, the compiled Registry derived from it, and every generated artifact, each bound to a SHA-256 digest over its canonical bytes.
REQ-PR-RELAY-101: A Relay process MUST verify its sealed package before it opens an identity issuer connection, an audit sink, a SQLite source, or a listener. A package that fails verification MUST prevent the process from serving rather than degrade it.
REQ-PR-RELAY-102: Package verification MUST re-derive the compiled Registry from the authored contract and the packaged source schema observations, and MUST re-derive every generated artifact from that compiled Registry, comparing both byte for byte against the packaged bytes. A mismatch MUST fail verification.
REQ-PR-RELAY-103: The package revision MUST be a SHA-256 digest over the canonical JSON of the package manifest. It is an integrity digest, not an authenticity proof: any party can recompute it. Relay packages are unsigned, and a deployment MUST NOT treat a matching package revision as evidence of who produced the package.
REQ-PR-RELAY-104: Governed contract input and deployment binding MUST be separate closed documents. The contract is kind: RegistryContract, the binding is kind: RelayRuntime, both at apiVersion: relay.registrystack.org/v2alpha1, and both MUST reject unknown fields at every nested structure rather than ignore them. A governed field MUST NOT be accepted from the deployment binding.
REQ-PR-RELAY-105: Every source MUST be a SQLite database read through the shared bounded read-only boundary, opened read-only, and MUST declare exactly one source profile, either snapshot or live-read-only. Each resource MUST bind to one named view in one declared source. Table names, SQL text, and hidden source columns MUST NOT appear on the public surface.
REQ-PR-RELAY-106: Relay MUST NOT write to a source. Statement execution runs behind an authorizer that denies every action other than the reviewed read set, and every caller-supplied value MUST reach SQLite as a bound parameter, never as statement text.
3. Route set
Section titled “3. Route set”Relay serves a fixed route set. A deployment’s contract decides which resource identifiers, lookup names, search names, artifact identifiers, and statistical datasets resolve inside that set; it never adds a route shape.
| Method | Path | Purpose |
|---|---|---|
| GET | /health | Unauthenticated liveness. |
| GET | /ready | Unauthenticated readiness. |
| GET | /openapi.json | The deployment’s public OpenAPI description. |
| GET | /v2 | Service metadata and the visible capability list. |
| GET | /v2/resources | Visible resource collection. |
| GET | /v2/resources/{resource} | One resource description and its visible operations. |
| GET | /v2/resources/{resource}/records | Record list. |
| GET | /v2/resources/{resource}/records/{recordIdentifier} | Single record read. |
| POST | /v2/resources/{resource}/lookups/{lookup} | Exact lookup by declared match values. |
| GET | /v2/resources/{resource}/searches/{search} | Declared bounded search. |
| GET | /v2/artifacts/{artifactIdentifier} | One generated artifact. |
| GET | /sdmx/v2/data/dataflow/{agency}/{dataflow}/{version}/{key} | Keyed statistical data. |
| GET | /sdmx/v2/data/dataflow/{agency}/{dataflow}/{version} | Statistical data with the key omitted. |
| GET | /sdmx/v2/structure/{artefactType}/{agency}/{resource}/{version} | Dataflow or data structure definition, where {artefactType} is dataflow or datastructure. |
REQ-PR-RELAY-107: Relay MUST expose only the route shapes in the preceding table. An unmatched path and an unmatched method on a matched path MUST produce the same not-found response, so a caller cannot use method probing to learn that a path exists.
REQ-PR-RELAY-108: The lookup route MUST be the only route that accepts a request body, MUST require the application/json media type, and MUST accept only the exact match values its operation declares. It performs an exact match, not a similarity match or a record-linkage decision.
REQ-PR-RELAY-109: A request URI longer than 16384 bytes MUST be refused with internal.uri_too_long, before the operation reads any source row.
4. Authentication, access profiles, and row binding
Section titled “4. Authentication, access profiles, and row binding”An operation carries one or more access profiles. Each access profile pairs an access rule with a disclosure profile, so the authorization decision and the disclosure decision are one compiled unit rather than two independent runtime lookups.
REQ-PR-RELAY-110: An access rule MUST be exactly one of two kinds. A Public rule requires no credential. A Protected rule requires an OIDC bearer access token carrying the rule’s scope, and MAY additionally require a declared purpose and a row binding.
REQ-PR-RELAY-111: A caller MAY select an access profile with the accessProfile query parameter. Where the parameter is absent, the operation’s default access profile MUST apply. Relay MUST NOT widen a caller’s reach beyond the selected profile at request time.
REQ-PR-RELAY-112: A row binding MUST restrict the rows an operation can return to those the authenticated caller is entitled to. The binding authority MUST come from the verified token, either from the principal itself or from one named verified claim. A caller-supplied request value MUST NOT satisfy a row binding.
REQ-PR-RELAY-113: Purpose MUST be contract-declared, not caller-asserted. A request carrying a Purpose or X-Purpose header MUST be refused as an invalid request.
REQ-PR-RELAY-114: Denials MUST NOT disclose the existence of a surface the caller cannot reach. An unauthenticated request that explicitly names a protected access profile, and an authenticated request whose token lacks the required scope, MUST both receive the same resource.not_found response an unknown resource receives. Only a purpose or row-binding denial on a profile the caller was otherwise entitled to select MUST return consultation.denied, and only a missing credential on the default profile MUST return auth.missing_credential.
REQ-PR-RELAY-115: Metadata visibility MUST be governed independently for the service, resource, statistical dataset, semantics, classification, and processing surfaces. A metadata surface marked operator-only MUST NOT appear in any caller-visible response, and an operation-bound surface MUST appear only to a caller entitled to the operation it describes.
5. Disclosure profiles and field selection
Section titled “5. Disclosure profiles and field selection”A disclosure profile names the exact properties a response may carry and the maximum handling those properties permit. It bounds the response before any caller preference is applied.
REQ-PR-RELAY-116: A disclosure profile MUST enumerate the properties it discloses. A property outside the selected profile MUST NOT appear in a response, whatever the caller requests.
REQ-PR-RELAY-117: The fields query parameter MUST narrow the response within the selected disclosure profile and MUST NOT widen it. A field selection naming a property the profile does not disclose MUST be refused with request.fields_invalid.
REQ-PR-RELAY-118: fields MUST narrow only the record’s domain data. The Registry Core record context defined in Section 6 MUST remain complete in every record a response returns, so a caller cannot receive a value without the identity, revision, lifecycle, schema, and authority context that qualifies it.
REQ-PR-RELAY-119: Where a disclosure profile declares a transform, the transform MUST be applied before the value leaves the process, and the transform inventory MUST be recorded in the request’s audit record.
6. Response envelope and wire formats
Section titled “6. Response envelope and wire formats”Every record Relay returns carries the same Registry Core record context: registryIdentifier, recordIdentifier, revisionIdentifier, lifecycleState, schemaReference, semanticModelReference, authorityIdentifier, recordedAt, and domainData.
REQ-PR-RELAY-120: A collection response MUST place its records under items. A single-record response, and a single resource description, MUST place its payload under data. A response MUST NOT use both keys.
REQ-PR-RELAY-121: Every record MUST carry the complete Registry Core record context, with the deployment’s domain payload confined to domainData. Registry Core context property names MUST NOT be used for domain values.
REQ-PR-RELAY-122: Relay MUST negotiate exactly three record wire formats: application/json, application/ld+json, and application/geo+json. A caller requesting a format the resource and selected access profile do not offer MUST receive format.unsupported.
REQ-PR-RELAY-123: A response MUST NOT be signed. A caller MUST NOT be able to make Relay produce a signed or credential-shaped response by content negotiation or by any other request-side choice.
7. Pagination
Section titled “7. Pagination”REQ-PR-RELAY-124: List and search responses MUST paginate with an opaque cursor returned as pageInfo.nextCursor, and MUST report no cursor once the page set is exhausted. A caller MUST NOT construct a cursor.
REQ-PR-RELAY-125: A cursor MUST be integrity-protected under the deployment cursor key, MUST expire, and MUST be bound to the request it continues, including the operation, the contract revision, the access profile, the field selection, and the wire format. A cursor that is malformed, expired, or presented against a different request MUST be refused with query.cursor_invalid.
REQ-PR-RELAY-126: Page size MUST be bounded by the operation’s compiled default and maximum. A pageSize outside that bound MUST be refused rather than silently clamped.
REQ-PR-RELAY-127: A query parameter the operation does not declare MUST be refused with filter.unknown_field. Relay MUST NOT ignore an unrecognized parameter.
8. Point profile
Section titled “8. Point profile”REQ-PR-RELAY-128: Where a resource declares a primary geometry, Relay MUST serve it as a CRS84 Point in exact longitude and latitude order, as an RFC 7946 Feature for a single record and a FeatureCollection for a collection, under application/geo+json. The formatProfile query parameter MUST select between rfc7946 and jsonfg, where jsonfg adds the JSON-FG identifiers and feature type to the same Point wire format.
REQ-PR-RELAY-129: Spatial search MUST be limited to the declared inclusive point-within-bounding-box predicate, evaluated with a bbox parameter on a search operation that declares it. Relay MUST NOT offer a general geospatial query language, tiles, or an environmental data retrieval surface.
REQ-PR-RELAY-130: The geometry MUST be subject to the selected disclosure profile in the same way as any other property. Where the profile does not disclose the primary geometry, the GeoJSON representation MUST NOT carry a coordinate.
9. SDMX read profile
Section titled “9. SDMX read profile”A deployment MAY declare governed, pre-aggregated statistical datasets. These are served through a narrow aligned subset of SDMX, not a general SDMX registry.
REQ-PR-RELAY-131: The SDMX surface MUST be read-only and MUST be limited to keyed dataflow data, dataflow data with the key omitted, dataflow structure, and data structure definition. Relay MUST NOT offer the remaining SDMX REST resources, schema resources, or availability resources.
REQ-PR-RELAY-132: Statistical responses MUST use the pinned exchange versions: application/vnd.sdmx.data+json;version=2.1.0, application/vnd.sdmx.data+csv;version=2.1.0, and application/vnd.sdmx.structure+json;version=2.1.0, aligned to SDMX REST 2.2.2.
REQ-PR-RELAY-133: A statistical dataset MUST carry one fixed access rule for the whole dataset. It MUST NOT carry record access profiles, disclosure profiles, field selection, or row binding, which are Record-surface constructs. Relay MUST NOT claim SDMX conformance or certification.
REQ-PR-RELAY-134: A deployment that declares no statistical dataset MUST report the aggregate-data capability family as unsupported.
10. Metadata, artifacts, and OpenAPI
Section titled “10. Metadata, artifacts, and OpenAPI”REQ-PR-RELAY-135: Relay MUST publish a capability inventory naming, for every visible operation and access profile, the capability family, the pattern, the route, and the schema, semantic model, and context references that describe the response. The inventory MUST also name the families the runtime does not support: provisioning, evidence, write, notification, access-transparency, identity-federation, and aggregate-data where no statistical dataset is declared.
REQ-PR-RELAY-136: Every generated artifact MUST be derived from the compiled Registry and carried inside the sealed package. Relay MUST NOT generate an artifact at request time. An operator-only artifact MUST NOT be served on /v2/artifacts/{artifactIdentifier}, and an operation-bound artifact MUST be served only to a caller the bound operation and access profile authorize.
REQ-PR-RELAY-137: Each deployment MUST generate its own OpenAPI 3.1.0 description in two projections: a package-only operator projection carrying every operation, and a public projection served at /openapi.json carrying only the publicly reachable surface. /openapi.json MUST NOT reveal an operation the caller could not otherwise discover.
11. Audit, errors, and readiness
Section titled “11. Audit, errors, and readiness”REQ-PR-RELAY-138: Relay MUST record an attempt event before it reads a source, and a refusal or terminal event when the request concludes. Audit MUST fail closed: where an audit event cannot be appended, Relay MUST return audit.unavailable and MUST NOT return the data the request asked for.
REQ-PR-RELAY-139: Audit events MUST be value-free. An event MUST carry the closed vocabulary of the audit event schema, including the operation surface, the access and disclosure profile identifiers, the selected property names, the transform inventory, the row boundary kind, the contract revision, and the principal kind. An event MUST NOT carry a record value, a filter value, a token, a URI, or a request header.
REQ-PR-RELAY-140: Error responses MUST use application/problem+json per RFC 9457, MUST carry a stable code from the closed problem vocabulary, MUST carry the effective W3C Trace Context trace identifier, and MUST NOT echo a rejected value back to the caller.
REQ-PR-RELAY-141: GET /health and GET /ready MUST be the service’s only operational probes. GET /ready MUST report ready only when audit-sink readiness, SQLite source readiness, and identity issuer readiness are all satisfied. GET /health MUST report liveness without authentication and without consulting those dependencies. Relay MUST NOT expose an administrative listener, an administrative route, or a posture document. This is the protocol-level form of the readiness composition specified by RS-OP-POSTURE.
REQ-PR-RELAY-142: Relay MUST apply a per-operation quota where the deployment configures one, and MUST refuse an exhausted quota with consultation.rate_limited or aggregate-data.rate_limited rather than by degrading the response.
12. Limitations
Section titled “12. Limitations”These constraints are stated so a reader does not infer a capability from the route list that the reviewed implementation does not provide.
- No writes and no provisioning: Relay reads governed SQLite views and nothing else (REQ-PR-RELAY-106, REQ-PR-RELAY-135).
- No signatures: Relay responses are unsigned, and the package revision proves integrity, not authorship (REQ-PR-RELAY-103, REQ-PR-RELAY-123).
- No general geospatial API: the Point profile covers exact CRS84 points and one inclusive bounding-box predicate (REQ-PR-RELAY-128, REQ-PR-RELAY-129).
- No SDMX registry: the statistical surface is a four-resource read profile over pre-aggregated datasets (REQ-PR-RELAY-131, REQ-PR-RELAY-133).
- No record linkage: the lookup route matches declared values exactly and returns no similarity score (REQ-PR-RELAY-108).
- No administration surface: readiness is the whole operational surface a deployment exposes over HTTP (REQ-PR-RELAY-141).
- No product-wide OpenAPI document: each deployment describes only itself (REQ-PR-RELAY-137).
Conformance
Section titled “Conformance”A Relay deployment conforms to this specification when it:
- verifies and re-derives its sealed package before serving, and refuses to serve on a mismatch (REQ-PR-RELAY-101, REQ-PR-RELAY-102, REQ-PR-RELAY-103);
- keeps governed contract and deployment binding in separate closed documents, reads SQLite views read-only through the shared boundary, and binds every caller value as a parameter (REQ-PR-RELAY-104, REQ-PR-RELAY-105, REQ-PR-RELAY-106);
- exposes only the fixed route set, answers unmatched paths and methods identically, bounds the lookup body and the request URI (REQ-PR-RELAY-107, REQ-PR-RELAY-108, REQ-PR-RELAY-109);
- enforces the two access-rule kinds, honors the selected access profile, binds rows from verified token material only, refuses caller-asserted purpose, and conceals surfaces a caller cannot reach (REQ-PR-RELAY-110 through REQ-PR-RELAY-115);
- bounds disclosure by profile, narrows rather than widens with
fields, keeps the Registry Core record context complete, and applies declared transforms before disclosure (REQ-PR-RELAY-116 through REQ-PR-RELAY-119); - returns the Registry Core envelope with
itemsordata, negotiates the three record wire formats, and never signs a response (REQ-PR-RELAY-120 through REQ-PR-RELAY-123); - paginates with bound, expiring, integrity-protected cursors, bounds page size, and refuses undeclared parameters (REQ-PR-RELAY-124 through REQ-PR-RELAY-127);
- serves the CRS84 Point profile with its two format profiles and its single spatial predicate, under disclosure control (REQ-PR-RELAY-128, REQ-PR-RELAY-129, REQ-PR-RELAY-130);
- limits the SDMX surface to the four pinned read resources with fixed dataset access, and reports
aggregate-dataas unsupported when no dataset is declared (REQ-PR-RELAY-131 through REQ-PR-RELAY-134); - publishes the capability inventory and unsupported families, serves only packaged artifacts under their access binding, and generates its own two OpenAPI projections (REQ-PR-RELAY-135, REQ-PR-RELAY-136, REQ-PR-RELAY-137);
- audits fail-closed with a value-free vocabulary, reports errors as problem+json with a trace identifier, composes readiness from its three dependencies, exposes no administrative surface, and refuses an exhausted quota (REQ-PR-RELAY-138 through REQ-PR-RELAY-142).
Conformance to this specification does not imply conformance to any external standard cited in the standards_referenced frontmatter field. Each standard’s adoption mode and scope are documented in the standards register.
Evidence
Section titled “Evidence”This specification is verified: every requirement describes shipped behavior a reader can inspect, per RS-DOC REQ-DOC-014.
- The governed SQLite publication tutorial walks one contract from authoring to a served deployment, exercising the routes, envelope, and access profiles specified here.
- The Relay authoring guide is the key-by-key reference for the governed contract and the deployment binding that Sections 2, 4, and 5 constrain.
- Relay semantics and disclosure explains why access profiles and disclosure profiles are one compiled unit, which Sections 4 and 5 make precise.
- Governed registry publication explains the sealed package and the review it records, which Section 2 makes precise.
- Operating Relay covers readiness, audit, quotas, and logging, which Section 11 makes precise.
- The retirement decision record records why the V1 requirements in the version history are retired rather than revised.
- RS-PR-RELAYCTL specifies the adopter tooling that produces the sealed package this document assumes.
- RS-PR-EVIDENCE specifies Evidence, the separate runtime that returns signed, minimum-disclosure assertions.
- RS-ARC-G places Relay in the registry stack architecture.
- RS-TERMS defines the consultation, disclosure, and packaging vocabulary used here.