Preview release. These docs are a work in progress. Pages are still being written, links may break, and structure may shift without notice. Treat everything here as a draft and report issues on GitHub.
Registry Lab reference
Use this page to look up port numbers, credential names, and script entry points when setting up or debugging the topology.
This reference is hand-maintained; the source links in each table are the authoritative check.
Compose service inventory
Section titled “Compose service inventory”Full Compose file: compose.yaml.
| Service | Image / build | Role | Host port |
|---|---|---|---|
civil-registry-relay | registry-relay:demo (local build) | Registry Relay for civil domain; serves CSV-backed civil registry data | 4311 |
social-protection-registry-relay | registry-relay:demo (local build) | Registry Relay for social protection domain; serves XLSX-backed data | 4312 |
health-registry-relay | registry-relay:demo (local build) | Registry Relay for health domain; serves Parquet-backed data | 4313 |
postgres | postgres:16-alpine (pulled) | Live Postgres service for Relay database-source scenarios | 54329 |
zitadel | ghcr.io/zitadel/zitadel:v2.66.4 (pulled) | Live Zitadel identity provider for Relay OIDC scenarios | 4380 |
zitadel-seed-init | alpine:3.20 (pulled) | One-shot volume permission initializer for Zitadel bootstrap state | None |
zitadel-init | alpine:3.20 (pulled) | One-shot Zitadel bootstrap script that writes output/zitadel.env via scripts/check-relay-zitadel.sh | None |
civil-notary | registry-notary:demo (local build) | Registry Notary for civil claims; reads civil facts from civil-registry-relay over HTTP | 4321 |
social-protection-notary | registry-notary:demo (local build) | Registry Notary for social protection claims; reads social facts from social-protection-registry-relay over HTTP | 4322 |
shared-eligibility-notary | registry-notary:demo (local build) | Registry Notary for cross-authority claims spanning civil, social, and health registries | 4323 |
openfn-mock-registry | registry-notary-openfn-sidecar:demo (local build) | Private registry-like HTTP API used by the OpenFn sidecar smoke path | None |
openfn-civil-sidecar | registry-notary-openfn-sidecar:demo (local build) | Private OpenFn adaptor sidecar that exposes a Registry Data API-shaped lookup surface to Notary | None |
openfn-civil-notary | registry-notary:demo (local build) | Registry Notary for civil claims sourced through openfn-civil-sidecar | 4324 |
static-metadata-publisher | python:3.12.3-slim-bookworm (pulled) | Python HTTP server serving the portable metadata static bundle at /srv/static | 4331 |
demo-client | python:3.12.3-slim-bookworm (pulled) | Narrated demo client (one-shot, --profile client only); runs scripts/demo-flow.py | None |
Relay and Notary build contexts include vendor/registry-platform plus the owning service source
submodule, vendor/registry-relay or vendor/registry-notary.
All core Relay and Notary services use env_file: .env, RUST_LOG: info, and restart: unless-stopped.
Relay services have a healthcheck (registry-relay --help, 30 s interval, 10 s timeout, 3 retries).
Core Notary services have no healthcheck in the compose file.
openfn-civil-sidecar has an HTTP readiness healthcheck, and openfn-civil-notary
waits for that healthcheck before starting.
Inside the compose network, services reach each other via DNS names on port 8080.
The OpenFn sidecar and mock registry are attached only to the private openfn-internal network.
Named volumes: civil-registry-cache, social-protection-registry-cache,
health-registry-cache, postgres-data, and zitadel-seed.
Fixture file layout
Section titled “Fixture file layout”Source: scripts/generate-fixtures.py.
Run with uv run scripts/generate-fixtures.py from the repo root.
Output lands under data/. The directory is gitignored; only data/.gitignore is committed.
| File | Format | Domain | Contents |
|---|---|---|---|
data/civil/civil_registry.csv | CSV | Civil | Children, caregivers, living adults, and deceased adults across five districts |
data/social-protection/social_protection_registry.xlsx | XLSX | Social protection | Households, household members, and enrollments with active, inactive, suspended, and review-required cases |
data/health/health_registry.parquet | Parquet | Health | Active, suspended, pending-renewal, and partially-serviceable facilities |
All timestamps are deterministic (2026-01-01). The generator validates that a successful subject, failed predicates, deceased-member cases, cross-source subjects, and health-linked support cases are all present before writing.
Smoke-check scripts
Section titled “Smoke-check scripts”Run scripts/smoke.sh after docker compose -f compose.yaml up -d to confirm the topology is healthy.
All smoke requests use the correlation ID decentralized-demo-correlation-001
(overridable via DEMO_CORRELATION_ID).
smoke.sh
Section titled “smoke.sh”Source: scripts/smoke.sh
More than 30 checks:
- Health and ready endpoints on all Relay services
- Discovery endpoints on all Notary services with bearer-token and
x-api-keycredentials - OpenAPI endpoints on all services
- Evidence-offering endpoints
- Authorization scope denial (403
auth.scope_denied) - Positive row-read and aggregate-read on social Relay
- Claim evaluation on civil, social, and shared Notaries
- Cross-authority
source_count >= 2 - Credential-bound SD-JWT VC evaluation
- Demo-client artifact presence
- Audit event log entries
- Absence of generated raw secrets in service logs
release-check.sh
Section titled “release-check.sh”Source: scripts/release-check.sh
Full release wrapper that runs in sequence: fixture generation, secret generation, static metadata publication, compose build, compose up, core smoke run, demo client run, live Postgres check, live Zitadel check, OIDC Relay smoke, OpenFn smoke, live-service story runner, and compose down with -v.
Set REGISTRY_LAB_CHECK_RELAY_POSTGRES=0, REGISTRY_LAB_CHECK_RELAY_ZITADEL=0,
REGISTRY_LAB_CHECK_OIDC_RELAY=0, REGISTRY_LAB_CHECK_OPENFN=0, or
REGISTRY_LAB_RUN_LIVE_STORIES=0 to skip the matching release-check phase.
The cleanup trap removes named volumes; run the focused scripts when you want to keep local state.
OpenFn and live-service checks
Section titled “OpenFn and live-service checks”| Script | Source path | What it verifies |
|---|---|---|
scripts/smoke-openfn.sh | scripts/smoke-openfn.sh | openfn-civil-notary can issue evidence from a one-item OpenFn sidecar lookup while the sidecar and mock registry remain off host ports |
scripts/check-relay-postgres.sh | scripts/check-relay-postgres.sh | Relay’s ignored live Postgres integration tests pass against the lab Postgres service |
scripts/check-relay-zitadel.sh | scripts/check-relay-zitadel.sh | Relay’s ignored Zitadel OIDC integration test passes against the lab Zitadel service |
scripts/smoke-oidc-relay.sh | scripts/smoke-oidc-relay.sh | A temporary OIDC-protected Relay verifies a real Zitadel access token, then returns either row access or a scope denial |
scripts/demo-live-stories.sh | scripts/demo-live-stories.sh | Narrated Postgres, Zitadel/OIDC, and OpenFn stories write artifacts under output/live-stories/ |
Generated local credentials
Section titled “Generated local credentials”Source: scripts/generate-demo-secrets.py.
Run directly as an executable (scripts/generate-demo-secrets.py).
Output is written to .env (gitignored).
The committed .env.example contains inert placeholder values only.
| Credential class | Env var pattern | Used by |
|---|---|---|
| Metadata client token (civil) | CIVIL_METADATA_CLIENT_RAW / CIVIL_METADATA_CLIENT_HASH | Smoke checks (/health, /ready, /openapi.json, /metadata/* on civil Relay) |
| Metadata client token (social) | SOCIAL_METADATA_CLIENT_RAW / SOCIAL_METADATA_CLIENT_HASH | Smoke checks on social protection Relay |
| Metadata client token (health) | HEALTH_METADATA_CLIENT_RAW / HEALTH_METADATA_CLIENT_HASH | Smoke checks on health Relay |
| Evidence source token (civil) | CIVIL_EVIDENCE_SOURCE_RAW | civil-notary when fetching civil facts from civil-registry-relay (config/notary/civil-notary.yaml L29) |
| Evidence source token (social) | SOCIAL_EVIDENCE_SOURCE_RAW | social-protection-notary when fetching social facts (config/notary/social-protection-notary.yaml L29) |
| Evidence source token (civil, shared) | SHARED_CIVIL_EVIDENCE_SOURCE_RAW | shared-eligibility-notary civil source reads (config/notary/shared-eligibility-notary.yaml L33) |
| Evidence source token (social, shared) | SHARED_SOCIAL_EVIDENCE_SOURCE_RAW | shared-eligibility-notary social source reads (config/notary/shared-eligibility-notary.yaml L36) |
| Evidence source token (health, shared) | SHARED_HEALTH_EVIDENCE_SOURCE_RAW | shared-eligibility-notary health source reads (config/notary/shared-eligibility-notary.yaml L39) |
| Evidence-only token (civil) | CIVIL_EVIDENCE_ONLY_RAW | Scope denial proof: has evidence scope, no row or aggregate scope |
| Evidence-only token (social) | SOCIAL_EVIDENCE_ONLY_RAW | Scope denial proof: has evidence scope, no row or aggregate scope |
| Evidence-only token (health) | HEALTH_EVIDENCE_ONLY_RAW | Scope denial proof: has evidence scope, no row or aggregate scope |
| Row-reader token (social) | SOCIAL_ROW_READER_RAW | Protected row read in scenario 2 and scope denial checks |
| Aggregate-reader token (social) | SOCIAL_AGGREGATE_READER_RAW | Aggregate consultation in scenario 2 and scope denial checks |
| OpenFn sidecar caller token | OPENFN_SIDECAR_TOKEN_RAW / OPENFN_SIDECAR_TOKEN_HASH | openfn-civil-notary authenticates to openfn-civil-sidecar with the raw token; the sidecar config reads only the hash |
| OpenFn mock registry token | OPENFN_MOCK_REGISTRY_TOKEN_RAW | Private target token injected into the OpenFn sidecar credential JSON for openfn-mock-registry |
| Notary client API key (civil) | CIVIL_EVIDENCE_CLIENT_TOKEN / CIVIL_EVIDENCE_CLIENT_TOKEN_HASH | Smoke checks x-api-key auth on civil-notary |
| Notary client API key (social) | SOCIAL_EVIDENCE_CLIENT_TOKEN / SOCIAL_EVIDENCE_CLIENT_TOKEN_HASH | Smoke checks x-api-key auth on social-protection-notary |
| Notary client API key (shared) | SHARED_EVIDENCE_CLIENT_TOKEN / SHARED_EVIDENCE_CLIENT_TOKEN_HASH | Smoke checks x-api-key auth on shared-eligibility-notary |
| Notary client bearer (civil) | CIVIL_EVIDENCE_CLIENT_BEARER | Demo client and smoke: discovery and evaluation on civil-notary |
| Notary client bearer (social) | SOCIAL_EVIDENCE_CLIENT_BEARER | Demo client and smoke: discovery and evaluation on social-protection-notary |
| Notary client bearer (shared) | SHARED_EVIDENCE_CLIENT_BEARER | Demo client and smoke: discovery and evaluation on shared-eligibility-notary |
| Audit hash secret (Relay) | REGISTRY_RELAY_AUDIT_HASH_SECRET | Relay audit redaction and keyed hashes |
| Audit hash secret (Notary) | REGISTRY_NOTARY_AUDIT_HASH_SECRET | Notary audit redaction and keyed hashes |
| Issuer JWK (all Notaries) | REGISTRY_NOTARY_ISSUER_JWK | SD-JWT VC signing key; Notary configs use issuer_key_env: REGISTRY_NOTARY_ISSUER_JWK (config/notary/civil-notary.yaml L43) |
Relay configs reference only *_HASH env vars (SHA-256 fingerprints of the raw tokens).
Notary auth configs reference *_HASH env vars for client credentials.
Notary upstream source connections still reference token_env names for outbound calls to Relay.
The OpenFn sidecar auth config references OPENFN_SIDECAR_TOKEN_HASH; plaintext sidecar token
config is rejected by the sidecar.
No raw token is committed to the repository.
Static metadata publisher endpoints
Section titled “Static metadata publisher endpoints”Source: scripts/publish-static-metadata.sh,
manifest at config/static-metadata/metadata.yaml,
served by static-metadata-publisher at 127.0.0.1:4331.
No authentication is required for any of these endpoints.
| Path | Content | Format |
|---|---|---|
/metadata/index.json | Static publication index listing all produced artifacts | JSON |
/metadata/catalog.json | DCAT (Data Catalog Vocabulary) catalog for the demo registry | JSON |
/metadata/cpsv-ap | Core Public Service Vocabulary Application Profile (CPSV-AP) service catalogue for Atlas service-first discovery | JSON-LD |
/metadata/cpsv-ap.jsonld | CPSV-AP service catalogue for clients that require a file extension | JSON-LD |
/metadata/evidence-offerings.json | Evidence offering descriptors pointing to Notary services | JSON |
/metadata/forms/health_linked_child_support_form/schema.json | JSON Schema for the linked demo form | JSON Schema |
/metadata/policies.jsonld | ODRL (Open Digital Rights Language) policy documents | JSON-LD |
The bundle is produced by registry-manifest-cli publish from the portable manifest.
It does not include any Relay runtime details (source paths, table identifiers, scopes, cache paths).
The static manifest identifier decentralized-demo-static-publication is an intentionally stable
value set in config/static-metadata/metadata.yaml and is not renamed when the repository moves
to registry-lab.
Configuration files
Section titled “Configuration files”Source: config/.
| File | Configures |
|---|---|
config/relay/civil-registry-relay.yaml | Civil Relay: source binding to data/civil/civil_registry.csv, scope definitions, entity routes |
config/relay/social-protection-registry-relay.yaml | Social protection Relay: source binding to data/social-protection/social_protection_registry.xlsx, separate row and aggregate scopes |
config/relay/health-registry-relay.yaml | Health Relay: source binding to data/health/health_registry.parquet, entity routes |
config/relay/civil-registry-relay.metadata.yaml | Portable metadata for the civil Relay (separate from runtime binding) |
config/relay/social-protection-registry-relay.metadata.yaml | Portable metadata for the social protection Relay |
config/relay/health-registry-relay.metadata.yaml | Portable metadata for the health Relay |
config/openfn/openfn-civil-sidecar.yaml.template | OpenFn sidecar manifest with hashed sidecar auth, pinned OpenFn runtime/adaptor versions, target allowlist, and smoke lookup |
config/postgres/init.sql | Postgres database initialization for lab database-source scenarios |
config/zitadel/zitadel-init.sh | Zitadel bootstrap script for OIDC Relay scenarios |
config/zitadel/zitadel-bootstrap.md | Operator notes for the Zitadel bootstrap process |
config/notary/civil-notary.yaml | Civil Notary: hashed client auth, claim definitions, source connector URL, private-network source opt-in, disclosure policy |
config/notary/social-protection-notary.yaml | Social protection Notary: hashed client auth, claim definitions, source connector URL, private-network source opt-in, disclosure policy |
config/notary/shared-eligibility-notary.yaml | Shared eligibility Notary: hashed client auth, cross-authority claim definitions, multiple private-network source connectors |
config/notary/openfn-civil-notary.yaml | OpenFn-backed civil Notary: uses registry_data_api against the private OpenFn sidecar |
config/static-metadata/metadata.yaml | Portable metadata manifest (registry-manifest/v1) used by the static publisher |