Skip to content

feat(demo): add optional OpenCRVS v2 interoperability proof - #22

Open
jeremi wants to merge 6 commits into
mainfrom
agent/opencrvs-v2-demo
Open

feat(demo): add optional OpenCRVS v2 interoperability proof#22
jeremi wants to merge 6 commits into
mainfrom
agent/opencrvs-v2-demo

Conversation

@jeremi

@jeremi jeremi commented Jul 29, 2026

Copy link
Copy Markdown
Member

Summary

  • add an isolated, opt-in OpenCRVS v2 interoperability demo that is not part of the normal Solmara topology
  • author strict no-expiry client-credentials OAuth and native POST /events/events/search through Registry Relay
  • minimize the source response to six booleans, evaluate five top-level Notary predicates, issue a holder-bound dc+sd-jwt, and verify its signature, canonical credential identity, validity, exact predicate disclosures, and holder binding in memory
  • add offline fixtures, exact negative controls, exact running-service provenance checks, sanitized evidence generation, docs, and credential-independent cleanup recipes

Release boundary

Released Registry Stack v0.15.2 cannot complete this live path. It lacks project authoring for the explicit no-expiry response profile, durable no-cache completion handling, and active worker-time accounting for bounded Relay-owned backend waits. The final paired pre-release proof used exact Registry Stack candidate d840f2b70b74a83c76c947f997b62d5a70fc7237 from registrystack/registry-stack#569.

This demo remains deployment-gated until those changes ship in a coordinated Registry Stack release and versions.env is updated through the normal release-adoption process. It is safe to release the current Solmara version first. The candidate image is local development evidence only and must not be deployed or substituted for release pins.

Security and privacy invariants

  • OAuth accepts exactly access_token plus case-correct token_type: Bearer; no expiry is inferred from unsigned JWT claims and no token is cached across consultations
  • live credentials, selectors, origins, runtime keys, raw OpenCRVS responses, bearer tokens, and issued credentials remain outside tracked source and sanitized evidence
  • before any OpenCRVS query, the proof binds the declared compiler/runtime identity to the running Relay container’s exact image reference, image ID, OCI source revision, and canonical feature label, and binds the running Notary image reference and ID to its pinned digest
  • both the known-record and syntactically valid no-match consultations must perform exactly one credential dispatch and one source dispatch
  • public authored bounds are reported separately from effective private runtime limits; the proof asserts effective four-per-minute, burst-two limits
  • the three pre-dispatch controls require their exact status and stable problem code with zero dispatches: invalid caller 401/auth.missing_credential, wrong purpose 403/purpose.not_allowed, and invalid selector 409/evidence.not_available
  • Notary predicate values must be actual JSON booleans or null; the no-match control requires birth-record-exists: false and every dependent predicate null
  • credential acceptance requires the canonical CRA issuer and KID, the expected VCT, a currently valid exact 600-second lifetime with 30 seconds of clock skew, and exactly five signed predicate disclosures whose embedded claim IDs match and whose value and satisfied members are both true
  • evidence and logs are scanned before output is written; cleanup does not read operator or generated credentials, and removes the disposable topology, volumes, and runtime closure even after credentials are missing, incomplete, or rotated

Verification

  • just lint
  • just test (6 generator, 40 scenario, 175 portal, 78 home, 138 script tests with 1 skip, 33 demo unit tests)
  • just review
  • just opencrvs-demo-test with the exact development compiler (33 unit tests and 73 fixture cases)
  • just opencrvs-demo-compose
  • shellcheck demos/opencrvs-v2/build-candidate.sh demos/opencrvs-v2/postgres-init.sh
  • ruff check and ruff format --check for the runner and tests
  • exact-commit host-native Relay candidate build with canonical release features and OCI revision labels
  • final repeated live proof against candidate d840f2b70b74a83c76c947f997b62d5a70fc7237: running Relay and Notary provenance, strict OAuth, native flattened OpenCRVS search, six minimized outputs, five true typed predicates, direct holder-bound credential issuance, current exact-lifetime and canonical issuer/KID/VCT verification, exact disclosures, exact no-match and pre-dispatch negative contracts, exact dispatch counts, sanitized evidence scan, and successful cleanup
  • clean-context staff review found no remaining actionable correctness, documentation, privacy, provenance, or security issue

Explicit non-goals

This is not OpenCRVS certification, OID4VCI wallet delivery, OpenCRVS-triggered issuance, public DID-resolution proof, production CRA key proof, or proof that the credential holder is the child's parent or informant.

Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
@jeremi
jeremi marked this pull request as ready for review July 29, 2026 20:48

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 84942c09ea

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread demos/opencrvs-v2/project/environments/local.yaml Outdated
Comment thread demos/opencrvs-v2/runner.py
Comment thread demos/opencrvs-v2/runner.py
@jeremi
jeremi marked this pull request as draft July 29, 2026 21:05
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
@jeremi
jeremi marked this pull request as ready for review July 29, 2026 21:28

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 776bff7f6b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread demos/opencrvs-v2/runner.py Outdated
Comment thread demos/opencrvs-v2/runner.py Outdated
@jeremi
jeremi marked this pull request as draft July 29, 2026 21:34
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
@jeremi
jeremi marked this pull request as ready for review July 29, 2026 21:41

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ba9db373e5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread demos/opencrvs-v2/runner.py
Comment thread demos/opencrvs-v2/runner.py
@jeremi
jeremi marked this pull request as draft July 29, 2026 21:47
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
@jeremi
jeremi marked this pull request as ready for review July 29, 2026 21:58

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cf78b64993

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread demos/opencrvs-v2/runner.py
Comment thread demos/opencrvs-v2/runner.py
@jeremi
jeremi marked this pull request as draft July 29, 2026 22:04
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
@jeremi
jeremi marked this pull request as ready for review July 29, 2026 22:10

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d8c766f7b7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

write_runtime_env(runtime)
ensure_postgres_tls()
environment = compose_environment(external, runtime)
run(compose_command("up", "-d", "--build"), env=environment)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Recreate services after replacing the runtime project

When up is rerun without a preceding down—for example after changing the OpenCRVS host or authored project—prepare_runtime_project deletes and recreates the bind-mounted project, but this command can leave Relay and Notary running because their Compose configuration and images are unchanged. Those containers retain the old bind mounts while proof() reads hashes from the newly generated project, so the evidence can attribute requests to artifacts that were not exercised. Add --force-recreate or explicitly tear down the existing topology; the Compose up reference documents that --force-recreate recreates containers even when their configuration and image have not changed.

Useful? React with 👍 / 👎.

Comment on lines +1233 to +1237
header.get("alg") != "EdDSA"
or header.get("kid") != ISSUER_KID
or issuer_jwk.get("kid") != ISSUER_KID
or header.get("kid") != issuer_jwk.get("kid")
or payload.get("_sd_alg") != "sha-256"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require the dc+sd-jwt protected type

When Notary signs an otherwise valid token whose protected header omits typ or sets it to another JWT type, this check still accepts it and records the format as application/dc+sd-jwt. Require header["typ"] == "dc+sd-jwt" alongside alg and kid; otherwise the proof does not actually verify the credential format it claims to have exercised.

Useful? React with 👍 / 👎.

Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant