Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ __pycache__/
dist/
.cache/
projects/*/.registry-stack/
demos/opencrvs-v2/project/.registry-stack/
demos/opencrvs-v2/.runtime/
*.log
config/postgres/ssl/*
!config/postgres/ssl/.gitkeep
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ The first wave covers three journeys:
- `portal/` contains the citizen portal and BFF.
- `scenarios/`, `requests/`, and `perf/` carry guided scenarios, API examples,
and k6 smoke coverage.
- `demos/opencrvs-v2/` contains an optional, isolated OpenCRVS interoperability
demo. Its released live path is blocked; paired candidate use is
development-only. It is not part of the six-authority topology.
- `scripts/` contains root quality gates and orchestration helpers.

## Development Commands
Expand Down Expand Up @@ -95,11 +98,31 @@ just registry-projects-review # complete redacted acquisition and disclosure rep
just registry-projects-capabilities # value-free installed/used/missing capability inventory
just registry-projects-editor # version-matched VS Code and Zed schemas for all projects
just contract-generation-proof # release-only live SRO blue/mixed/successor proof
just opencrvs-demo-test # optional OpenCRVS fixture and compiler proof
just opencrvs-demo-candidate-build <worktree> # build matched pre-release compiler and Relay
just opencrvs-demo-compose # validate the isolated demo topology
just opencrvs-demo-up # start with compatible release or paired dev artifacts
just opencrvs-demo-proof # live proof with compatible release or paired dev artifacts
just opencrvs-demo-down # remove its containers, volumes, and runtime closure
just release-pins <registry-stack-tag> # compare committed versions.env pins against a candidate or release tag
just review # normal security and release-readiness checks
just review-release <registry-stack-tag> # candidate review with published pin validation
```

The OpenCRVS demo's offline compiler, fixture, Compose, and paired pre-release
live checks pass. Its released live path remains blocked. Relay v0.15.2 has the
strict no-expiry OAuth decoder, yet its durable state plane rejects this
no-cache script plan before source dispatch. Registryctl v0.15.2 also cannot
author the profile. One exact pending Registry Stack commit enables offline
compiler development only. Pre-release live development requires Registryctl
and a labeled Relay image built from one later exact candidate commit
containing the authoring, state-plane, and active script-budget fixes. Do not
deploy the demo until a Registry Stack release contains those fixes and all
coordinated pins in `versions.env` have passed release review. The safe paired
override, exact native endpoints, cleanup sequence, privacy boundary, and
direct machine issuance limits are documented in
[`demos/opencrvs-v2/README.md`](demos/opencrvs-v2/README.md).

Normal startup pulls the immutable canonical Relay image pinned in
`versions.env`; it does not clone or compile Registry Stack. Governed attribute
release is part of the canonical Registry Stack v0.15.2 Relay build. The
Expand Down
331 changes: 331 additions & 0 deletions demos/opencrvs-v2/README.md

Large diffs are not rendered by default.

108 changes: 108 additions & 0 deletions demos/opencrvs-v2/build-candidate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#!/usr/bin/env bash
set -euo pipefail

if [[ "$#" -ne 1 ]]; then
printf 'usage: %s <registry-stack-worktree>\n' "$0" >&2
exit 2
fi

stack_dir="$(cd -- "$1" && pwd -P)"
commit="$(git -C "${stack_dir}" rev-parse HEAD)"
if [[ ! "${commit}" =~ ^[0-9a-f]{40}$ ]]; then
printf 'Registry Stack HEAD must resolve to a lowercase 40-character commit SHA\n' >&2
exit 1
fi
if [[ -n "$(git -C "${stack_dir}" status --porcelain)" ]]; then
printf 'Registry Stack candidate worktree must be clean\n' >&2
exit 1
fi

builder_image='rust:1.95-trixie@sha256:f49565f188ee00bc2a18dd418183f2c5f23ef7d6e691890517ed341a598f67c3'
relay_features="$(<"${stack_dir}/crates/registry-relay/canonical-release-features.txt")"
engine_arch="$(docker version --format '{{.Server.Arch}}')"
case "${engine_arch}" in
amd64 | x86_64)
relay_arch='amd64'
;;
arm64 | aarch64)
relay_arch='arm64'
;;
*)
printf 'unsupported Docker server architecture: %s\n' "${engine_arch}" >&2
exit 1
;;
esac
relay_platform="linux/${relay_arch}"
image="registry-relay-opencrvs:${commit}-${relay_arch}"
image_version="0.15.2-opencrvs.${commit:0:12}"
linux_target="/workspace/target/opencrvs-linux-${relay_arch}"

cargo build --locked --manifest-path "${stack_dir}/Cargo.toml" \
-p registryctl --bin registryctl

docker run --rm \
--platform "${relay_platform}" \
--user "$(id -u):$(id -g)" \
--volume "${stack_dir}:/workspace" \
--workdir /workspace \
--env CARGO_HOME=/workspace/.cargo-home \
--env CARGO_INCREMENTAL=0 \
--env CARGO_TARGET_DIR="${linux_target}" \
--env HOME=/workspace \
--env REGISTRY_RELAY_FEATURES="${relay_features}" \
"${builder_image}" \
bash -c 'set -euo pipefail
cargo build --release --locked \
-p registry-relay \
--no-default-features \
--features "${REGISTRY_RELAY_FEATURES}"
python3 release/scripts/check-release-relay-features.py \
"${CARGO_TARGET_DIR}/release/registry-relay"
'

mkdir -p "${stack_dir}/dist/image-bin"
install -m 0755 \
"${stack_dir}/target/opencrvs-linux-${relay_arch}/release/registry-relay" \
"${stack_dir}/dist/image-bin/registry-relay"
install -m 0755 \
"${stack_dir}/target/opencrvs-linux-${relay_arch}/release/registry-relay-rhai-worker" \
"${stack_dir}/dist/image-bin/registry-relay-rhai-worker"

docker buildx build \
--load \
--platform "${relay_platform}" \
--file "${stack_dir}/release/docker/Dockerfile.registry-relay" \
--tag "${image}" \
--label 'org.opencontainers.image.source=https://github.com/registrystack/registry-stack' \
--label "org.opencontainers.image.revision=${commit}" \
--label "org.opencontainers.image.version=${image_version}" \
--label "org.registrystack.registry-relay.features=${relay_features}" \
--build-arg SOURCE_DATE_EPOCH=0 \
"${stack_dir}"

image_architecture="$(
docker image inspect --format '{{.Architecture}}' "${image}"
)"
image_revision="$(
docker image inspect \
--format '{{index .Config.Labels "org.opencontainers.image.revision"}}' \
"${image}"
)"
image_features="$(
docker image inspect \
--format '{{index .Config.Labels "org.registrystack.registry-relay.features"}}' \
"${image}"
)"
if [[ "${image_architecture}" != "${relay_arch}" ||
"${image_revision}" != "${commit}" ||
"${image_features}" != "${relay_features}" ]]; then
printf 'candidate Relay image identity check failed\n' >&2
exit 1
fi

printf "export OPENCRVS_DEMO_REGISTRYCTL='%s'\n" \
"${stack_dir}/target/debug/registryctl"
printf "export OPENCRVS_DEMO_REGISTRYCTL_SOURCE_COMMIT='%s'\n" "${commit}"
printf "export OPENCRVS_DEMO_RELAY_IMAGE='%s'\n" "${image}"
printf "export OPENCRVS_DEMO_RELAY_SOURCE_COMMIT='%s'\n" "${commit}"
printf "export OPENCRVS_DEMO_RELAY_PLATFORM='%s'\n" "${relay_platform}"
179 changes: 179 additions & 0 deletions demos/opencrvs-v2/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
services:
opencrvs-db:
image: ${POSTGRES_IMAGE:-postgres:16-alpine}
restart: unless-stopped
entrypoint: ["/bin/sh", "/usr/local/bin/opencrvs-postgres-entrypoint.sh"]
command:
- postgres
- -c
- ssl=on
- -c
- ssl_cert_file=/var/lib/postgresql/server-ssl/server.crt
- -c
- ssl_key_file=/var/lib/postgresql/server-ssl/server.key
environment:
POSTGRES_USER: opencrvs_admin
POSTGRES_PASSWORD: ${POSTGRES_ADMIN_PASSWORD:-compose-validation-only}
POSTGRES_DB: postgres
healthcheck:
test: ["CMD-SHELL", "pg_isready -U opencrvs_admin -d postgres"]
interval: 2s
timeout: 3s
retries: 30
volumes:
- opencrvs-db-data:/var/lib/postgresql/data
- ../../scripts/postgres-entrypoint.sh:/usr/local/bin/opencrvs-postgres-entrypoint.sh:ro
- ${OPENCRVS_RUNTIME_PROJECT_DIR:-./.runtime/project}/../postgres:/run/solmara-postgres-ssl:ro

opencrvs-db-init:
image: ${POSTGRES_IMAGE:-postgres:16-alpine}
restart: "no"
environment:
POSTGRES_ADMIN_PASSWORD: ${POSTGRES_ADMIN_PASSWORD:-compose-validation-only}
OPENCRVS_RELAY_POSTGRES_RUNTIME_PASSWORD: ${OPENCRVS_RELAY_POSTGRES_RUNTIME_PASSWORD:-compose-validation-only}
OPENCRVS_RELAY_POSTGRES_MAINTENANCE_PASSWORD: ${OPENCRVS_RELAY_POSTGRES_MAINTENANCE_PASSWORD:-compose-validation-only}
OPENCRVS_RELAY_POSTGRES_READER_PASSWORD: ${OPENCRVS_RELAY_POSTGRES_READER_PASSWORD:-compose-validation-only}
command: ["/opt/opencrvs-demo/postgres-init.sh"]
volumes:
- ./postgres-init.sh:/opt/opencrvs-demo/postgres-init.sh:ro
depends_on:
opencrvs-db:
condition: service_healthy

opencrvs-relay-bootstrap:
image: ${REGISTRY_RELAY_IMAGE}
platform: ${OPENCRVS_DEMO_RELAY_PLATFORM:-linux/amd64}
restart: "no"
command:
- consultation
- bootstrap-state
- --config
- /etc/registry-relay/relay-consultation.yaml
- --migration-database-url-env
- REGISTRY_RELAY_STATE_MIGRATION_URL
- --owner-role
- opencrvs_demo_owner
- --keyring-maintenance-database-url-env
- REGISTRY_RELAY_STATE_KEYRING_MAINTENANCE_URL
- --keyring-reader-database-url-env
- REGISTRY_RELAY_STATE_KEYRING_READER_URL
- --active-key-id
- epoch-1
- --active-write-deadline-unix-ms
- "4102444800000"
- --audit-event-retention-ms
- "2592000000"
environment:
REGISTRY_RELAY_AUDIT_HASH_SECRET: ${OPENCRVS_RELAY_AUDIT_HASH_SECRET:-compose-validation-only}
REGISTRY_RELAY_AUDIT_PSEUDONYM_EPOCH_1: ${OPENCRVS_RELAY_AUDIT_PSEUDONYM_EPOCH_1:-compose-validation-only}
REGISTRY_RELAY_CONSULTATION_DATABASE_URL: postgresql://opencrvs_demo_runtime:${OPENCRVS_RELAY_POSTGRES_RUNTIME_PASSWORD:-compose-validation-only}@opencrvs-db:5432/opencrvs_demo?sslmode=require
REGISTRY_RELAY_STATE_MIGRATION_URL: postgresql://opencrvs_admin:${POSTGRES_ADMIN_PASSWORD:-compose-validation-only}@opencrvs-db:5432/opencrvs_demo?sslmode=require
REGISTRY_RELAY_STATE_KEYRING_MAINTENANCE_URL: postgresql://opencrvs_demo_keyring_maintenance:${OPENCRVS_RELAY_POSTGRES_MAINTENANCE_PASSWORD:-compose-validation-only}@opencrvs-db:5432/opencrvs_demo?sslmode=require
REGISTRY_RELAY_STATE_KEYRING_READER_URL: postgresql://opencrvs_demo_keyring_reader:${OPENCRVS_RELAY_POSTGRES_READER_PASSWORD:-compose-validation-only}@opencrvs-db:5432/opencrvs_demo?sslmode=require
OPENCRVS_CLIENT_ID: ${OPENCRVS_CLIENT_ID:-compose-validation-only}
OPENCRVS_SECRET: ${OPENCRVS_SECRET:-compose-validation-only}
volumes:
- ${OPENCRVS_RUNTIME_PROJECT_DIR:-./.runtime/project}/.registry-stack/build/local/private/relay/config:/etc/registry-relay:ro
- ${OPENCRVS_RUNTIME_PROJECT_DIR:-./.runtime/project}/../postgres/server.crt:/etc/opencrvs-demo/postgres/root.crt:ro
depends_on:
opencrvs-db-init:
condition: service_completed_successfully

opencrvs-relay:
image: ${REGISTRY_RELAY_IMAGE}
platform: ${OPENCRVS_DEMO_RELAY_PLATFORM:-linux/amd64}
restart: unless-stopped
command:
- --config
- /etc/registry-relay/relay-consultation.yaml
- --bind
- 127.0.0.1:8080
environment:
RUST_LOG: ${RUST_LOG:-info}
REGISTRY_RELAY_BIND: 127.0.0.1:8080
REGISTRY_RELAY_AUDIT_HASH_SECRET: ${OPENCRVS_RELAY_AUDIT_HASH_SECRET:-compose-validation-only}
REGISTRY_RELAY_AUDIT_PSEUDONYM_EPOCH_1: ${OPENCRVS_RELAY_AUDIT_PSEUDONYM_EPOCH_1:-compose-validation-only}
REGISTRY_RELAY_CONSULTATION_DATABASE_URL: postgresql://opencrvs_demo_runtime:${OPENCRVS_RELAY_POSTGRES_RUNTIME_PASSWORD:-compose-validation-only}@opencrvs-db:5432/opencrvs_demo?sslmode=require
OPENCRVS_CLIENT_ID: ${OPENCRVS_CLIENT_ID:-compose-validation-only}
OPENCRVS_SECRET: ${OPENCRVS_SECRET:-compose-validation-only}
healthcheck:
test: ["CMD", "/usr/local/bin/registry-relay", "healthcheck"]
interval: 3s
timeout: 5s
retries: 30
ports:
- "${OPENCRVS_DEMO_NOTARY_PORT:-4391}:8081"
volumes:
- ${OPENCRVS_RUNTIME_PROJECT_DIR:-./.runtime/project}/.registry-stack/build/local/private/relay/config:/etc/registry-relay:ro
- ${OPENCRVS_RUNTIME_PROJECT_DIR:-./.runtime/project}/../postgres/server.crt:/etc/opencrvs-demo/postgres/root.crt:ro
- opencrvs-relay-cache:/var/lib/registry-relay/cache
depends_on:
opencrvs-relay-bootstrap:
condition: service_completed_successfully

opencrvs-workload-agent:
build:
context: ../..
dockerfile: scenario-runner/Dockerfile
image: ${SOLMARA_SCENARIO_RUNNER_IMAGE:-solmara-lab-scenario-runner:local}
command: ["python", "scripts/relay_workload_identity_agent.py"]
restart: unless-stopped
network_mode: service:opencrvs-relay
environment:
WORKLOAD_ISSUER: http://127.0.0.1:8090
WORKLOAD_IDENTITIES_JSON: >-
[{"audience":"registry-relay","azp":"opencrvs-v2-demo-notary","subject":"opencrvs-v2-demo-notary","scopes":["registry:consult:opencrvs-birth-evidence"],"token_file":"/run/secrets/opencrvs-demo-notary-relay-token","private_jwk_env":"OPENCRVS_RELAY_WORKLOAD_JWK"}]
OPENCRVS_RELAY_WORKLOAD_JWK: ${OPENCRVS_RELAY_WORKLOAD_JWK:-compose-validation-only}
healthcheck:
test:
- CMD-SHELL
- python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8090/health', timeout=3)"
interval: 3s
timeout: 5s
retries: 30
volumes:
- opencrvs-workload-token:/run/secrets
depends_on:
opencrvs-relay:
condition: service_healthy

opencrvs-notary:
image: ${REGISTRY_NOTARY_IMAGE}
platform: ${REGISTRY_STACK_PLATFORM:-linux/amd64}
user: "65534:65534"
restart: unless-stopped
command:
- --config
- /etc/registry-notary/notary.yaml
- --bind
- 0.0.0.0:8081
network_mode: service:opencrvs-relay
environment:
RUST_LOG: ${RUST_LOG:-info}
REGISTRY_NOTARY_BIND: 0.0.0.0:8081
REGISTRY_NOTARY_AUDIT_HASH_SECRET: ${OPENCRVS_NOTARY_AUDIT_HASH_SECRET:-compose-validation-only}
OPENCRVS_DEMO_CALLER_TOKEN_HASH: ${OPENCRVS_DEMO_CALLER_TOKEN_HASH:-sha256:compose-validation-only}
OPENCRVS_DEMO_ISSUER_JWK: ${OPENCRVS_DEMO_ISSUER_JWK:-compose-validation-only}
healthcheck:
test:
- CMD
- /usr/local/bin/registry-notary
- healthcheck
- --url
- http://127.0.0.1:8081/ready
interval: 3s
timeout: 5s
retries: 30
volumes:
- ${OPENCRVS_RUNTIME_PROJECT_DIR:-./.runtime/project}/.registry-stack/build/local/private/notary/config/notary.yaml:/etc/registry-notary/notary.yaml:ro
- opencrvs-workload-token:/run/secrets:ro
depends_on:
opencrvs-relay:
condition: service_healthy
opencrvs-workload-agent:
condition: service_healthy

volumes:
opencrvs-db-data:
opencrvs-relay-cache:
opencrvs-workload-token:
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: opencrvs-v2-invalid-registration-number
classification: synthetic
input:
registration_number: INVALID
child_national_id: "9999000011"
tracking_id: SYN011
interactions: []
expect:
error: input.pattern_mismatch
outputs: {}
claims: {}
Loading
Loading