Skip to content
Registry StackDocsLatest

Configure an exact snapshot materialization

View as Markdown

Use this guide when Registry Relay must query an immutable local materialization instead of opening a source connection for each consultation. You will declare one logical entity, bind its physical source once in the private environment, and reuse the published snapshot for a governed records API and exact snapshot consultations.

Use snapshot for an exact key lookup over a separately ingested local snapshot. The consultation reports materialized_snapshot provenance and does not open a registry connection during the request.

Background ingest can acquire more data than one consultation. Record the complete materialization footprint and do not describe snapshot publication time as source observation time.

You need:

  • A Registry Stack project with an immutable CSV, XLSX, or other supported snapshot source.
  • A logical entity schema and stable primary key.
  • A private provider path and one physical column for every logical field.
  • Reviewed records API scopes, purposes, filters, pagination, relationships, and aggregates.

Keep provider paths, worksheet or table names, and physical columns out of public entity and integration files.

The starter proves an exact lookup over an immutable local materialization. Its offline fixture does not open a source connection.

Run these commands in order. The focused test prints a safe synthetic trace. The next command starts the same fixture as a watch smoke; press Ctrl+C after its initial passing report. The final three commands test every fixture, explain the redacted plan, and build the unsigned product inputs.

snapshot: Exact snapshot

An exact lookup over one immutable local materialization.

registryctl init --from snapshot --project-dir snapshot-project
registryctl test --project-dir snapshot-project --integration person-snapshot --fixture snapshot-match --trace
registryctl test --project-dir snapshot-project --integration person-snapshot --fixture snapshot-match --watch
registryctl test --project-dir snapshot-project
registryctl check --project-dir snapshot-project --environment local --explain
registryctl build --project-dir snapshot-project --environment local

Generated from the five starter workspaces compiled into registryctl.

Create entities/people.yaml with logical names only:

version: 1
id: people
revision: 1
primary_key: person_id
schema:
type: object
additionalProperties: false
required: [person_id, registration_status, eligible]
properties:
person_id: { type: string, maxLength: 64 }
registration_status: { type: [string, "null"], maxLength: 32 }
eligible: { type: [boolean, "null"] }
materialization:
max_records: 1000000
max_bytes: 256MiB
refresh: manual
retain_generations: 2

The entity owns the reusable logical schema and bounded materialization footprint. It rejects physical provider, path, table, worksheet, and column members. A records service is optional and does not change the entity used by snapshot.

Reference the entity and configure its optional records service in registry-stack.yaml:

entities:
people: { file: entities/people.yaml }
services:
people-records:
kind: records_api
entity: people
title: Population records
sensitivity: personal
access_rights: restricted
update_frequency: daily
api:
scopes:
metadata: people:metadata
rows: people:rows
purposes: [case-management]
projection: [person_id, registration_status, eligible]
pagination: { default_limit: 50, max_limit: 100 }
filters:
person_id: [eq]
registration_status: [eq]
required_principal_filters: [person_id]
standards: { ogc_features: false, sp_dci: false }

This records service is the Relay-owned records API exposure of people. It preserves only its declared scopes, purposes, projection, filters, pagination, relationships, aggregates, and standards adapters.

Create an integration that refers to logical entity fields:

version: 1
id: population-person-snapshot
revision: 1
input:
person_id:
role: selector
type: string
maxLength: 12
pattern: "^PER-[0-9]{8}$"
capability:
snapshot:
entity: people
exact:
person_id: { input: person_id }
freshness: 24h
outputs: [registration_status, eligible]

The snapshot capability applies the complete exact selector to one immutable published handle and probes at most two rows. Two matches return ambiguous; Registry Relay does not choose one.

Add an evidence service and consultation in registry-stack.yaml, mapping person_id from one declared request identifier. This Notary-owned service defines its service policy, claims, disclosure, and optional credential profiles. Claims can select only the integration’s closed outputs through their authored output field.

In environments/<environment>.yaml, bind the logical entity to its private provider:

entities:
people:
provider:
type: csv
path: /var/lib/registry/population.csv
header_row: 1
columns:
person_id: subject_key
registration_status: status_code
eligible: benefit_eligible
source_revision: population-export-v1
generation: 2026-07-12

Every logical field has one physical column, and physical columns must be unique. Change generation when the provider or mapping changes.

registryctl build emits one ingest plan and one materialization identity. The records service and compatible snapshot profiles capture the same published handle instead of creating another source path or copying the physical mapping.

Run the fixtures, semantic check, and build:

Terminal window
registryctl test --project-dir <project>
registryctl check \
--project-dir <project> \
--environment <environment> \
--explain
registryctl build \
--project-dir <project> \
--environment <environment>

The test and build JSON reports contain "status": "passed" and "status": "built". The human-readable check report marks the project valid. Confirm that the explanation names one logical materialization and that no reviewable integration pack or consultation contract contains the provider path or physical column names.

If the snapshot is absent, stale, or does not match the active generation and digest, only the dependent profiles become unready. Registry Relay does not fall back to live source access.

SymptomCauseFix
The entity schema rejects a provider or columnPhysical mapping was placed in the public definition.Move the provider and columns into the environment entity binding.
The environment rejects duplicate columnsTwo logical fields map to one physical column.Provide an injective physical mapping.
A provider change is rejectedThe mapping changed without a new generation.Advance the generation and repeat operator-security review.
Only snapshot profiles are unreadyThe shared materialization is missing, stale, or inconsistent.Publish and verify the expected immutable generation without enabling live fallback.