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.
Run Registry Relay locally
This page walks you through building Registry Relay from source, pointing it at the bundled XLSX fixture, and confirming that entity and metadata routes respond correctly.
When to use this
Section titled “When to use this”Use this guide when you need a running instance of Registry Relay on your laptop for local development, integration testing, or exploration. For a full multi-service topology that also starts Registry Notary and a static metadata publisher, see the Registry Lab tutorial instead.
Prerequisites
Section titled “Prerequisites”- Rust stable toolchain. Install via rustup.
justtask runner. Install withcargo install justor your platform package manager.curlfor the verification steps.
The example config and fixture files are already present in the
registry-relay repository.
Clone it if you have not already done so.
1. Build the release binary
Section titled “1. Build the release binary”just setupjust buildjust setup installs the Rust toolchain dependencies.
just build compiles the release binary to target/release/registry-relay.
Source: README build section.
2. Copy the fixture data into place
Section titled “2. Copy the fixture data into place”The default config (config/example.yaml) expects an XLSX file at
./data/social_registry.xlsx:
mkdir -p datacp fixtures/example_social_registry.xlsx data/social_registry.xlsxThe bundled fixture is a synthetic social registry with about 20 individual records you can page through. Source: README run-locally section.
3. Generate API-key fingerprints
Section titled “3. Generate API-key fingerprints”Registry Relay never stores raw API keys. Each configured key points at an environment variable that holds the SHA-256 fingerprint of the raw key. Source: docs/configuration.md API keys section.
Generate three keys for the three principals in the example config:
# Run once per key; first line = raw key, second line = SHA-256 fingerprint:openssl rand -base64 32 | tee /dev/stderr | shasum -a 256 | awk '{print "sha256:" $1}'Run the command three times (once for program_system, statistics_office, and
verification_service).
Store the raw keys somewhere you can retrieve them for curl calls. Export the fingerprints as environment variables:
export PROGRAM_SYSTEM_API_KEY_HASH='sha256:<64 lowercase hex chars>'export STATS_OFFICE_API_KEY_HASH='sha256:<64 lowercase hex chars>'export VERIFICATION_SERVICE_API_KEY_HASH='sha256:<64 lowercase hex chars>'export REGISTRY_RELAY_AUDIT_HASH_SECRET='<at least 32 random bytes>'Replace each <64 lowercase hex chars> with the fingerprint output from generate_key.
Set REGISTRY_RELAY_AUDIT_HASH_SECRET to deployment-specific random secret material.
For a local demo value, run openssl rand -base64 32.
4. Start the server
Section titled “4. Start the server”just run 2>relay.logRunning with 2>relay.log separates audit records (stdout) from operational logs
(stderr) in your terminal, so the JSON audit stream isn’t mixed with startup messages.
just run starts the binary with config/example.yaml as the default config.
Registry Relay binds the data-plane listener on 0.0.0.0:8080 as set in
config/example.yaml.
You can also pass a config path explicitly:
./target/release/registry-relay --config config/example.yamlOr set the REGISTRY_RELAY_CONFIG environment variable instead of using the flag.
Source: src/main.rs config resolution.
Operational logs go to stderr.
Audit records go to stdout (as configured by audit.sink: stdout in the example config).
5. Confirm readiness
Section titled “5. Confirm readiness”In a second terminal, check the readiness probe:
curl -i http://127.0.0.1:8080/ready/ready returns 200 only after all configured sources have ingested successfully.
/health is a liveness probe and returns 200 as long as the process is running.
Source: docs/ops.md probes section.
Verification
Section titled “Verification”Check an entity route
Section titled “Check an entity route”Set the raw key you noted for program_system:
PROGRAM_SYSTEM_API_KEY='<raw key from step 3>'List individuals from the social registry:
curl -si \ -H "Authorization: Bearer $PROGRAM_SYSTEM_API_KEY" \ http://127.0.0.1:8080/datasets/social_registry/individualA successful response returns 200 with a JSON array of individual records.
The program_system key has social_registry:rows scope, so row reads are
permitted.
Source: config/example.yaml; docs/api.md entity reads section.
Check a metadata route
Section titled “Check a metadata route”Fetch the Data Catalog Vocabulary (DCAT) metadata document:
curl -si \ -H "Authorization: Bearer $PROGRAM_SYSTEM_API_KEY" \ http://127.0.0.1:8080/metadata/dcatA successful response returns 200 with a JSON-LD DCAT catalog document.
The response Content-Type is application/ld+json.
Fetch the BRegDCAT-AP profile variant:
curl -si \ -H "Authorization: Bearer $PROGRAM_SYSTEM_API_KEY" \ http://127.0.0.1:8080/metadata/dcat/bregdcat-apSource: docs/metadata.md relay endpoints section.
Check the OpenAPI document
Section titled “Check the OpenAPI document”curl -si \ -H "Authorization: Bearer $PROGRAM_SYSTEM_API_KEY" \ http://127.0.0.1:8080/openapi.jsonThe OpenAPI document is auth-gated and filtered to the scopes of the caller.
The unauthenticated GET /docs route serves a Scalar HTML viewer that asks for
a bearer token before fetching openapi.json.
Confirm an unauthenticated request is rejected
Section titled “Confirm an unauthenticated request is rejected”curl -si http://127.0.0.1:8080/datasets/social_registry/individualRegistry Relay returns 401 with a Problem Details body whose code is
auth.missing_credential.
If you prefer Docker
Section titled “If you prefer Docker”Build the image and run it with the same example config and fixture:
docker buildx build --load \ --build-context registry-platform=../registry-platform \ -t registry-relay:local \ .docker run --rm -p 8080:8080 \ -e PROGRAM_SYSTEM_API_KEY_HASH \ -e STATS_OFFICE_API_KEY_HASH \ -e VERIFICATION_SERVICE_API_KEY_HASH \ -e REGISTRY_RELAY_AUDIT_HASH_SECRET \ -v "$PWD/config/example.yaml:/etc/registry-relay/config.yaml:ro" \ -v "$PWD/fixtures:/var/lib/registry-relay/data:ro" \ registry-relay:localThe container exposes port 8080 and reads config from /etc/registry-relay/config.yaml
by default.
The build context must include a sibling registry-platform checkout because Relay consumes
shared platform crates through path dependencies.
Source: README container image section.
Troubleshooting
Section titled “Troubleshooting”The process exits immediately at startup.
Check that all three *_API_KEY_HASH environment variables are set and each value
is in the exact format sha256:<64 lowercase hex chars>.
The binary exits non-zero if required hash env vars are missing.
Source: docs/ops.md troubleshooting section.
/ready returns 503.
Inspect the stderr output for ingest errors.
Confirm the XLSX file exists at ./data/social_registry.xlsx relative to your working
directory.
If the sheet name or range is wrong, adjust format.xlsx.sheet or format.xlsx.data_range
in the config.
Source: docs/ops.md readiness 503 troubleshooting.
Entity route returns 403.
Confirm the key you are using has the social_registry:rows scope in the example config.
The statistics_office key has only metadata and aggregate scopes; it cannot read
rows.
Source: config/example.yaml; docs/api.md scopes table.
Metadata route returns 403.
Confirm the key has social_registry:metadata scope.
The verification_service key has only evidence_verification scope.
Port 8080 is already in use.
Edit server.bind in config/example.yaml to a different address or port,
such as 127.0.0.1:8090.
Source: docs/configuration.md server section.
Audit records are missing from stdout.
The process writes audit JSONL to stdout and operational logs to stderr.
If you are redirecting stdout, check that destination.
Set audit.include_health: true in the config to also capture health-probe records.
Source: docs/ops.md audit troubleshooting.