Skip to content
Registry stack docs v0 · draft

Configure a claim

Author a new claim definition in the Registry Notary YAML config. By the end, you will have a claim that fetches a value from a source registry, evaluates a rule, and returns a result at the disclosure level you choose. The same procedure covers changing disclosure policy, switching source connectors, and adding CEL-based derived claims.

  • A running Registry Notary instance. See run locally if you need one.
  • Access to edit the YAML config file loaded by registry-notary-bin.
  • A source registry (Registry Data API or SP DCI endpoint) reachable from the Notary host, or a local stub for testing.
  • The environment variable named by token_env for your source connection set in the shell where Registry Notary runs.

Source connections are declared once under evidence.source_connections and referenced by any number of claims.

Registry Data API connector:

evidence:
source_connections:
my_registry:
base_url: http://my-relay.example.com
token_env: MY_REGISTRY_SOURCE_TOKEN

The source_connections entry declares a base URL and token variable. Use HTTPS for production source registries. For a local Docker Compose source registry on a private network, add allow_insecure_private_network: true; leave it unset for production. The connector kind is set per binding, not per connection: each source_bindings entry carries an explicit connector field (registry_data_api or dci) that determines which HTTP client path the runtime uses.

SP DCI connector:

evidence:
source_connections:
crvs:
base_url: http://my-relay.example.com
allow_insecure_private_network: true
token_env: CRVS_SOURCE_TOKEN
dci:
search_path: /dci/crvs/registry/sync/search
query_type: idtype-value
records_path: /message/search_response/0/data/reg_records
field_paths:
birth_date: /birth_date

Set the environment variable before starting or restarting the service:

Terminal window
export MY_REGISTRY_SOURCE_TOKEN=<source-bearer-token>

Add an entry to evidence.claims. The minimum required fields are id, title, version, subject_type, rule, and at least one entry in source_bindings if the rule reads from a source.

evidence:
claims:
- id: my-claim
title: My claim
version: 2026-05
subject_type: person
value:
type: date
inputs:
- name: subject_id
type: string
source_bindings:
my_source:
connector: registry_data_api
connection: my_registry
dataset: my_dataset
entity: my_entity
lookup:
input: subject_id
field: NATIONAL_ID
op: eq
cardinality: one
fields:
date_field:
field: date_field
type: date
required: true
rule:
type: extract
source: my_source
field: date_field
disclosure:
default: value
allowed:
- value
- redacted
formats:
- application/vnd.registry-notary.claim-result+json

Key fields explained:

  • source_bindings.<name>.connector: registry_data_api or dci.
  • source_bindings.<name>.connection: must match a key under evidence.source_connections.
  • source_bindings.<name>.lookup.input: must match a name in inputs.
  • rule.type: extract reads rule.field from the source binding named rule.source.
  • disclosure.default sets the mode used when the caller does not specify one.
  • disclosure.allowed lists modes the caller may request. Omitting value from allowed means callers can never receive the raw value.

Three disclosure modes are available.

Full value (value): The evaluated value is returned to the caller. Use for claims where the caller is entitled to the raw data.

disclosure:
default: value
allowed:
- value
- redacted

Predicate only (predicate): The caller receives only true or false. Use for derived boolean claims (for example, farmer-under-4ha) where the underlying metric must not leave the service.

disclosure:
default: predicate
allowed:
- predicate
- redacted

Redacted (redacted): The claim is present in the response but carries no data. This is the fail-closed default when no disclosure block is provided.

disclosure:
default: redacted
allowed:
- redacted
downgrade: deny

The downgrade field controls what happens when a caller requests a mode not in allowed: deny (default) returns an error; default falls back to disclosure.default; redacted forces the result to Redacted.

A CEL claim composes results from one or more upstream claims without re-fetching source data. Declare depends_on to ensure the upstream claims are evaluated first.

- id: my-derived-claim
title: My derived claim
version: 2026-05
subject_type: person
value:
type: boolean
inputs:
- name: subject_id
type: string
depends_on:
- my-claim
rule:
type: cel
expression: "claims.my_claim.value != nil"
bindings:
claims:
my_claim:
claim: my-claim
disclosure:
default: predicate
allowed:
- predicate
- redacted
formats:
- application/vnd.registry-notary.claim-result+json

CEL bindings under bindings.claims map a local variable name to a claim ID. The expression receives the claim result under claims.<binding_name>.value.

To enable /credentials/issue for your claim, declare a credential profile and reference it from the claim.

evidence:
credential_profiles:
my_profile:
format: application/dc+sd-jwt
issuer: did:web:my-issuer.example.gov
issuer_key_env: REGISTRY_NOTARY_ISSUER_JWK
vct: https://my-issuer.example.gov/credentials/my-claim/v1
validity_seconds: 86400
holder_binding:
mode: did
proof_of_possession: required
allowed_did_methods:
- did:jwk
allowed_claims:
- my-derived-claim
disclosure:
allowed:
- predicate

Then reference the profile from the claim:

credential_profiles:
- my_profile

Set the issuer key environment variable before starting or restarting the service:

Terminal window
export REGISTRY_NOTARY_ISSUER_JWK='{"kty":"OKP","crv":"Ed25519","d":"<private>","x":"<public>","alg":"EdDSA"}'

Caution: The issuer private key must not be committed to source control or logged. Load it only from a secret manager at runtime.

Registry Notary loads config at startup. After editing the YAML, restart the process. The config validator runs before the listener binds.

Terminal window
cargo run -p registry-notary-bin -- --config <your-config>.yaml

If the process exits immediately, check the tracing output for a startup error. See Troubleshooting for the full list of startup and runtime errors.

Confirm the claim appears in the claims list:

Terminal window
curl -s -H "x-api-key: <api-key>" \
http://<host>:<port>/claims | grep my-claim

Evaluate the claim against a test subject:

Terminal window
curl -s -X POST \
-H "x-api-key: <api-key>" \
-H "Content-Type: application/json" \
-d '{"subject":{"id":"<test-id>"},"claims":["my-claim"]}' \
http://<host>:<port>/claims/evaluate

A 200 response with a claim_results array confirms that evaluation reached the rule stage. If the source registry is unreachable, the API returns 503 Service Unavailable with an application/problem+json body. The code field in the body is source.unavailable.

A successful response looks like:

{
"subject": { "id": "<test-id>" },
"claim_results": [
{
"claim_id": "my-claim",
"outcome": "satisfied",
"disclosure": "value",
"value": "1998-04-12",
"evidence_summary": {
"source": "my_source",
"rows_read": 1
}
}
]
}

To verify CCCEV rendering:

Terminal window
curl -s -X POST \
-H "x-api-key: <api-key>" \
-H "Content-Type: application/json" \
-H "Accept: application/ld+json; profile=\"cccev\"" \
-d '{"subject":{"id":"<test-id>"},"claims":["my-claim"]}' \
http://<host>:<port>/claims/evaluate

MissingSourceConnection at startup. The connection field in a source binding does not match any key in evidence.source_connections. Check spelling in both places.

DependsOnUnknownClaim at startup. A depends_on entry references a claim id that does not exist in evidence.claims. Add the missing claim or remove the reference.

DependsOnCycle at startup. The depends_on graph contains a cycle. The error message lists the cycle path. Restructure the claims so that dependencies are acyclic.

UnsupportedDidMethodsForProofOfPossession at startup. A credential profile sets proof_of_possession: required but allowed_did_methods contains a method other than did:jwk. Remove the unsupported method or set proof_of_possession to a non-required value.

Claim evaluation returns DisclosureNotAllowed. The caller requested a disclosure mode that is not in disclosure.allowed for the claim, and disclosure.downgrade is deny. Either add the mode to allowed or change downgrade to default or redacted.

Source fetch returns an auth error. Confirm the environment variable named by token_env is set and contains a valid bearer token for the source registry.