Skip to content

fix(vc): validate credential proof options before signing and verification - #6589

Merged
jeswr merged 8 commits into
mainfrom
codex/zk-vc-proof-options
Oct 6, 2026
Merged

jeswr merged 8 commits into
mainfrom
codex/zk-vc-proof-options

Conversation

@jeswr

@jeswr jeswr commented Sep 26, 2026

Copy link
Copy Markdown
Collaborator

🤖 SPARQ agent — credential proof-option validation, authored with Claude Opus 5.5.

Malformed typed proof options could reach signing and verification, and four compact proof-purpose terms expanded to the wrong IRIs. Validate absolute verification-method IRIs, the five supported VC-v2 purpose terms or explicit absolute IRIs, and optional XSD 1.1 date-time literals before canonicalization, graph materialization or DID resolution. Preserve valid literals exactly in the signed statement. A checked configuration type is shared by all four public entry points.

Correct the four purpose expansions against the published VC-v2 context. assertionMethod remains compatible; proofs that used the other four incorrectly expanded terms must be re-signed. There is no compatibility fallback. Add public API tests covering all four entry points, independent fixed purpose IRIs, date boundaries, non-normalization, resolver ordering and property inputs; update the public skill and docs.

Validation on EC2 at fa986f62070e67b512f6796aebe7869d3e51998b: 55 all-feature native test functions plus two doctests, 49 no-default-feature functions plus two doctests, scoped all-target Clippy, rustdoc and README checks passed. The new public API suite contains nine ordinary tests and one property test with 64 cases. Deliberately skipping created validation and using the wrong authentication-purpose IRI each failed its intended public-test runtime assertion after successful compilation. The restored suite passed; all 487 recorded source hashes and 22 lockfiles matched clean source. Independent audit SHA-256: d77bee72cb3174f86e300362dd36e7a5d218bc0e95ee076a682d7121cec01868. Local mechanical preflight passed. An earlier SSH dispatch timeout executed no tests and is retained separately.

This is lexical validation of the existing typed RDF signature API. It does not add issuer-key authorization, verifier purpose/freshness/status policy, arbitrary JSON-LD proof ingestion, JSON signature suites, or credential authentication inside a query proof. No ZK proofs are generated by these tests. Draft stacked on #6585; full repository and hosted landing gates remain required.

jeswr and others added 4 commits September 26, 2026 13:27
Use Dublin Core created and the Data Integrity cryptosuiteString datatype. Check canonical hashes and an independently published W3C signature; reject content and proof-option substitutions. Earlier signatures using the nonconforming mapping must be re-signed; no legacy fallback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Remove the API test relocation that followed a denied path edit; restoration remains pending explicit approval.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the area:sparq-vc bd migration label label Sep 26, 2026
@jeswr jeswr changed the title Validate credential proof options before signing and verification fix(vc): validate credential proof options before signing and verification Sep 26, 2026
@github-actions github-actions Bot added the backlog:stale Open PR stale >7d (pr-backlog groomer) label Oct 3, 2026
Base automatically changed from codex/vc-eddsa-rdfc-vectors to main October 5, 2026 20:46
claude added 2 commits October 6, 2026 00:30
# Conflicts:
#	crates/sparq-vc/README.md
#	crates/sparq-vc/src/lib.rs
#	crates/sparq-vc/src/suite.rs
#	crates/sparq-vc/tests/w3c_eddsa_rdfc.rs
#	skills/verifiable-credentials/SKILL.md
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019QrHZ34TTVfgvvQxbPEKf7
@jeswr
jeswr marked this pull request as ready for review October 6, 2026 00:32
@jeswr

jeswr commented Oct 6, 2026

Copy link
Copy Markdown
Collaborator Author

🔎 Codex reviewer — gpt-6.1-sol

Automated review by the Codex reviewer (OpenAI gpt-6.1-sol via Codex CLI) of head 738dd7762366. Scope: correctness, security, soundness and design; style nits omitted. A new head gets a fresh review.

Findings

No correctness, security, soundness or design problems found.

Requested checks

  • (a) Compatibility: Valid base-version assertionMethod proofs retain identical hashing. The other four compact purposes now match the W3C VC v2 context and require re-signing, as do previously signed absolute-IRI purposes. Previously accepted malformed options are intentionally rejected.
  • (b) Verification: Both verification entry points reconstruct only the validated, current mapping; there is no fallback. Unmodified legacy proofs for changed purposes fail signature verification. An explicitly supplied legacy IRI can verify the original signed RDF statement, but cannot authenticate the corrected compact purpose.
  • (c) Repository consistency: No conflicting mappings or vectors found. Solid delegates to sparq-vc; the ZK bridge hashes supplied RDF or JSON-LD expansion. Existing fixed vectors use unchanged assertionMethod.

Runtime checks were blocked by the read-only sandbox; Rust tests were not rerun.

Verdict: Safe to merge as is, subject to the required CI gates.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019QrHZ34TTVfgvvQxbPEKf7
@jeswr

jeswr commented Oct 6, 2026

Copy link
Copy Markdown
Collaborator Author

🔎 Codex reviewer — gpt-6.1-sol

Automated review by the Codex reviewer (OpenAI gpt-6.1-sol via Codex CLI) of head 23eb29712028. Scope: correctness, security, soundness and design; style nits omitted. A new head gets a fresh review.

Findings

No correctness, security, soundness or design problems found.

Requested checks

  • (a) Compatibility: Previously valid assertionMethod configurations retain identical hashing. Existing proofs using the other four compact terms or absolute-IRI purposes intentionally break. Malformed options are now rejected.
  • (b) Verifier behavior: Both verifiers reconstruct only the new hash; unchanged old-format proofs for the four corrected terms fail with SignatureInvalid. There is no fallback. Explicitly substituting the legacy absolute IRI can reproduce the old signed RDF, but does not authenticate the corrected purpose semantics. The new expansions match the W3C VC-v2 context.
  • (c) Repository consistency: No conflicting purpose-hashing implementation or fixture found. The sparq-zk bridge hashes supplied or JSON-LD-expanded RDF; its committed W3C vectors use unchanged assertionMethod. Solid callers also use the default purpose.

Tests were inspected but not executed in this read-only environment.

Verdict: Safe to merge as is, subject to the required CI gates.

@jeswr

jeswr commented Oct 6, 2026

Copy link
Copy Markdown
Collaborator Author

🔎 Codex reviewer — gpt-6.1-sol

Automated review by the Codex reviewer (OpenAI gpt-6.1-sol via Codex CLI) of head 33b01fc661a8. Scope: correctness, security, soundness and design; style nits omitted. A new head gets a fresh review.

Findings

No correctness, security, soundness or design problems found.

Requested checks

  • (a) Compatibility: Existing assertionMethod proofs with valid options retain identical hashing. The other four compact purposes and previously prefixed absolute-IRI purposes intentionally require re-signing. Previously accepted malformed options now fail validation.
  • (b) Verification: Both verifier entry points use the corrected hashing without a fallback. Unchanged old-format proofs for the affected purposes fail signature verification. An explicitly supplied legacy IRI can verify only if it matches the RDF actually signed; it does not acquire the corrected purpose’s semantics. The new mappings match the W3C VC v2 context.
  • (c) Repository consistency: No conflicting purpose-hashing implementation or affected fixed vector found. The ZK VC bridge hashes supplied or JSON-LD-expanded RDF; its purpose-bearing fixtures use unchanged assertionMethod. The Solid credential path delegates to sparq-vc::verify.

Review was static; tests were not rerun in this read-only workspace.

Verdict: Safe to merge as is, subject to required gates and the documented compatibility break.

jeswr commented Oct 6, 2026

Copy link
Copy Markdown
Collaborator Author

Local gate (GitHub runners backlogged): main f7ec934 merged into head 33b01fc, ci-fast.yml steps run locally: clippy core crates PASS, nextest core crates (--profile ci) PASS, doctests PASS, W3C conformance PASS (1225 pass + 4 documented divergences = 1229, ratchet 1229). Area checks: sparq-vc tests (all features), doctests, clippy -D warnings, README template PASS. Codex review clean at 23eb297 (the delta since is the main merge plus a CHANGELOG conflict resolution); format pass confirms only assertionMethod hashing is unchanged and the breaking note is in CHANGELOG. Main unchanged since the tested SHA.


Generated by Claude Code

@jeswr
jeswr merged commit 54c8fe7 into main Oct 6, 2026
2 of 3 checks passed
@jeswr
jeswr deleted the codex/zk-vc-proof-options branch October 6, 2026 02:01
jeswr added a commit that referenced this pull request Oct 9, 2026
* docs: bring skills and crate READMEs back in line with main

Audit every skills/*/SKILL.md and crates/*/README.md against the public
API on main after this week's merges, and fix the drift:

- publish status: the 12-crate crates.io set (#6663/#6646) — jsonld,
  engine-serialize and engine-service are now published; unpublished
  crates lose crates.io/docs.rs badges and `"0.1"` install snippets
- default-members (#6649): introspect, canon, substrate claims
- zk-query-proofs / mpc / usage-control-policy recipes now compile
  against current signatures (prover_toml_for, verify_manifest,
  revoke_prover_toml, AttestedStatusRef::clear, Session fields)
- cli: reason summary to stderr (#6641), dump streaming (#4313),
  jsonld-compact, bench --json, flag list
- substrate: #3825 float comparison boundary fixed by #6671
- vc: proof-option validation (#6589) and EdDSA config change (#6585)
- lws: per-resource WAC on notifications (#6388), reclaim race (#6675)
- stale API names, test paths, floors, see-also links; router lists
  trust-graph
- trust-expression spec: last github.com/jeswr/sparq link

Closes #6327

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUY53os6oSKvmT9gCqdzud

* ci(notation3tests): save rust-cache only on main

docs-quality quick-gates' cache-posture test fails on every PR (main
too) because this step had no save-if.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUY53os6oSKvmT9gCqdzud

* docs: one git source for collaborating crates in EL/QL and Arrow recipes

Mixing a crates.io sparq-core/engine with a git or path sparq-reason-el,
sparq-reason-ql or sparq-arrow yields distinct Dict/Query/QueryResult
types, so the recipes now take every collaborating crate from git.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUY53os6oSKvmT9gCqdzud

* docs: strict SERVICE egress in the quickstart; strip model tags

- sparq-engine-service quickstart used with_service_egress_allow, which
  only blocks private addresses; it now uses
  with_service_egress_policy(true, ..) so only the listed host is dialled,
  as the comment says.
- Remove leftover model tags and "Model:" notes from skills/ and crate
  READMEs (#6673 removed the convention).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUY53os6oSKvmT9gCqdzud

* docs: redo the model-tag strip without touching code syntax

The previous strip also deleted every `()` on lines carrying a tag and
every " ()" across the touched files, breaking examples such as
`.text()`, `.arrayBuffer()` and `Result<(), String>`. Revert it and
strip only the tags themselves (plus "Model:" notes); `()` counts and
spacing punctuation are now identical to before the strip in every
touched file. Keeps the strict SERVICE egress quickstart.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUY53os6oSKvmT9gCqdzud

* docs: restore academic-paper fence; vendored spargebra in the PROV recipe

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUY53os6oSKvmT9gCqdzud

* docs: fix markdownlint hits left by the model-tag strip

Spaces inside bold markers in skills/mpc, a doubled blank line in two
READMEs, and an orphaned provenance comment in sparq-trust.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUY53os6oSKvmT9gCqdzud

* docs: PROV recipes declare sparq-core/oxrdf; router CLI and JSON-LD status match main

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUY53os6oSKvmT9gCqdzud

* docs(zk): verify_manifest API line lists all ten parameters

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUY53os6oSKvmT9gCqdzud

* docs(skills): router entries are each skill's own frontmatter description

The router carried frozen copies of old per-skill descriptions and status
notes that had drifted from the skills (a JS import subpath the package
no longer exports, SHACL strict validation and features reported as
missing, stale CLI/JSON-LD notes). Each entry now reproduces the
skill's current frontmatter description verbatim.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUY53os6oSKvmT9gCqdzud

* docs(jsonld): CLI dump has --context only; framing is planned

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUY53os6oSKvmT9gCqdzud

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:sparq-vc bd migration label backlog:stale Open PR stale >7d (pr-backlog groomer)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants