Skip to content
Registry StackDocsLatest

Connect Notary to a Registry Data API source

View as Markdown

Registry Notary runs as its own project against any Registry Data API-shaped source: a source exposing the Registry Data API contract, the protected read API shape Registry Relay serves. This tutorial generates a standalone Notary project, points it at that source, and evaluates a starter claim against it.

The reproducible path in this tutorial uses the local Relay project from Run a protected registry API locally as a stand-in source.

If your source is not Registry Data API-shaped, put a source-adapter sidecar in front of it: see Adapt a custom HTTP source for the engine that fits your source.

Outcome
A standalone Notary project evaluating a starter claim against a Registry Data API source.
Time
About 10 minutes after a Registry Data API source is available
Level
Local single-node
Prerequisites
registryctlThe running local Relay project from Run a protected registry API locally, or your own Registry Data API-shaped source you already operateA Docker Compose provider

This tutorial uses synthetic data and local demo credentials. Do not use the generated local keys in production.

For a local reproducible source, complete the first tutorial and leave the Relay project running:

Terminal window
registryctl init relay my-first-api --sample benefits
cd my-first-api
registryctl start
registryctl smoke
set -a
. secrets/local.env
set +a

The set -a block exports ROW_READER_RAW, which the standalone Notary project uses once when it is generated.

From the parent directory of my-first-api, create the standalone Notary project:

Terminal window
cd ..
registryctl init notary my-standalone-notary \
--source-url http://registry-relay:8080 \
--source-network my-first-api_default \
--source-token-from-env ROW_READER_RAW
cd my-standalone-notary

--source-token-from-env ROW_READER_RAW reads the token value from your current shell and writes it into the new project’s secrets/local.env.

my-first-api_default is the Compose network name Docker derives from the Relay project directory. If you named that directory differently, use that name with the _default suffix.

Start the standalone project:

Terminal window
registryctl start

registryctl starts Notary, waits for readiness, and prints the local API URL:

Notary API: http://127.0.0.1:4255
API docs: http://127.0.0.1:4255/docs

Run the smoke check:

Terminal window
registryctl notary smoke

The smoke check lists claims, evaluates the generated starter claim, and writes a detailed report:

output/notary-smoke-results.json

Load this project’s local keys:

Terminal window
set -a
. secrets/local.env
set +a

Evaluate the starter claim:

Terminal window
curl -sS -X POST \
-H "x-api-key: $REGISTRY_NOTARY_TUTORIAL_EVALUATOR_RAW" \
-H "Content-Type: application/json" \
-H "Accept: application/vnd.registry-notary.claim-result+json" \
-d '{
"target": { "type": "person", "id": "per-2001" },
"claims": ["benefits-person-exists"],
"disclosure": "predicate",
"purpose": "https://example.local/purpose/tutorial"
}' \
http://127.0.0.1:4255/v1/evaluations

Notary returns a claim result without returning the source row.

Change the source options at project creation time. The three <...> values must match the Registry Data API lookup route your source exposes:

Terminal window
registryctl init notary my-notary \
--source-url https://api.example.com \
--source-token-env EVIDENCE_SOURCE_API_TOKEN \
--source-dataset <your-dataset-id> \
--source-entity <your-entity> \
--source-lookup-field <your-lookup-field>

Notary will read:

GET /v1/datasets/{dataset}/entities/{entity}/records?{lookup_field}={lookup_value}&fields=...&limit=2
Authorization: Bearer <source-token>
Data-Purpose: <purpose>

Successful responses must use:

{ "data": [{ "field": "value" }] }

--source-token-env names the environment variable the Notary container reads at runtime. After project creation, edit secrets/local.env and set EVIDENCE_SOURCE_API_TOKEN to the source token.

If the source API is another Compose service, pass --source-network <compose-network> so Notary can join that network.

Use a source-adapter sidecar when your source API has its own routes, auth, response envelopes, or matching behavior.

The adapter runs privately next to Notary and exposes the Registry Data API-shaped route that Notary expects.

Start with the smallest engine that fits:

EngineUse when
http_jsonOne governed HTTP JSON request can return the fields Notary needs.
http_flowYou need 2 to 5 dependent GET requests, such as search first and fetch detail second.
fhir (FHIR R4 resource projection engine)You are projecting bounded FHIR R4 resources into Notary-ready facts.
script_rhaiYou need POST, fallback behavior, or small custom branching that the built-in declarative engines cannot express.

Keep the source-specific logic in the adapter. Keep claim semantics, disclosure, caller policy, and credential issuance in Notary.

Stop the standalone Notary project from its directory:

Terminal window
registryctl stop

Stopping removes the containers and network only; the generated config, keys, and smoke results stay on disk in the project directory.

If you also started the sample Relay source, stop it from the my-first-api directory.

You generated a standalone Registry Notary project, pointed it at an existing Registry Data API-shaped source over a shared Compose network, and evaluated a starter claim through Notary’s claim evaluation API. Notary returned a claim result, not the underlying source row: the source stayed private, and only the claim’s disclosed predicate crossed the API boundary.

SymptomCauseResolution
registryctl init notary cannot read ROW_READER_RAWThe Relay keys were not exported in this shell.Run the set -a block from the Relay project directory, then retry.
registryctl start fails with network ... not foundThe source Compose network name is wrong or the source project is not running.Start the source project and pass the correct <project>_default network name.
Claim evaluation returns a source auth errorNotary cannot authenticate to the source.Confirm the source token in secrets/local.env and restart Notary.
Claim evaluation returns 409 Evidence not availableThe target id is not available from the source, or the dataset, entity, or lookup field does not match the source contract.Use a known target id or inspect the Registry Data API source contract.
registryctl start times out and the container log shows missing field \commitment“registryctl v0.8.4 pins a service image older than its own generated config format (GH#278).Pin compose.yaml to the published v0.8.4 Notary digest ghcr.io/registrystack/registry-notary@sha256:0cf05184885d7ed17dd9889e20f3797eb2a9ad07517f4ac7c05c03b774a00b8f and, when the project includes Relay, ghcr.io/registrystack/registry-relay@sha256:93e194500a3500ba3f6331d5a0a9a3069127c48a709beccb083a5fcbdbc3ec61. Then run docker compose pull; reapply the pins after a generation command rewrites compose.yaml.
With registryctl v0.9.0 or later, registryctl init notary reports that its image lock is missing or invalidThe binary is not paired with the strict image lock from the same release, or the lock failed its release and digest checks. Registryctl v0.8.4 does not use this lock.Rerun the installer from the same pinned target tag so it checksum-verifies and installs both files. If the lock is intentionally stored elsewhere, set REGISTRYCTL_IMAGE_LOCK to that exact verified file. Do not replace the digest pin with a mutable tag.