M8c: conformance + interop (the M8 finale)#10
Conversation
Empirical W3C VCDM 2.0 conformance + cross-implementation interop (NFR-007). - Credentials.Conformance.VcApi: minimal ASP.NET VC-API shim over IIssuer/IVerifier (issue/verify/presentations-verify; GET / returns the shim did:key). Issues eddsa-rdfc-2022, validates structure before signing, maps non-conforming input to HTTP >=400. The suite injects the shim's own did:key as credential.issuer, so issuance satisfies issuer-binding with no rewriting. - Credentials.Conformance.Tests: boots the shim on loopback, runs the w3c/vc-data-model-2.0-test-suite, asserts a passing baseline of 36 (SkippableFact, Category=Conformance; skips visibly without the suite). Honest result: 36/59 passing (structural/issue/verify core); the 23 not-yet-passing are documented known limitations (JSON-LD term mapping, relatedResource integrity, name/description language objects, a VP authentication-proof interop gap) in docs/conformance.md — a regression baseline, not a fake green. - Credentials.InteropTests (NFR-007): SD-JWT VC disclosure digests cross-checked against the spec base64url(SHA-256(ascii(disclosure))) algorithm + tampered/unmatched-disclosure negatives + dc+sd-jwt drift sentinel; bbs-2023 (IsAvailable-gated) pins the bbs-2023/multibase-proofValue drift sentinels, verifies a derived proof, rejects a tampered mandatory value. - conformance.yml (PR + nightly): clones + installs the Node suite, runs the harness. - FrCoverage NFR-007 deferral removed (now tagged); docs/conformance.md added. Build 0-warning; 357 tests green (+5 interop) plus the conformance harness. M8 complete (A+B+C). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
moisesja
left a comment
There was a problem hiding this comment.
M8c review — non-blocking but four concrete things to address before or shortly after merge.
The overall approach here is excellent: honest conformance reporting, a regression-guarding baseline rather than a fake green, correct SkippableFact skip semantics, independent SD-JWT digest recomputation against the RFC, and the RequireHolderBinding = false note explaining why the VP path is wired that way. The issuer-binding bridge (configuring the suite with the shim's own did:key rather than rewriting documents) is particularly clean.
1. conformance.yml triggers on ALL PRs — contradicts its own comment (fix or remove the comment)
# so it runs on PRs that touch the engine, nightly, and on demand — not in the main build matrix.
on:
pull_request:
branches: [main] # no paths: filterThe header comment says "runs on PRs that touch the engine", but there is no paths: filter — it fires on every PR to main, including docs, task tracking, and CHANGELOG updates. Either add a filter that matches the comment:
paths:
- 'src/**'
- 'tests/**'
- '.github/workflows/conformance.yml'…or drop the misleading clause from the comment. As-is, a docs-only PR clones the Node suite and runs an 8-minute test.
2. LocateShimDll hard-codes net10.0 — will silently break on a TFM bump
// W3cVcdm2SuiteTests.cs
var dll = Path.Combine(root, "tests", "Credentials.Conformance.VcApi", "bin", c, "net10.0", "Credentials.Conformance.VcApi.dll");When the project moves to net11.0 (or whatever comes next) this throws a FileNotFoundException with no hint why. Replace with a glob:
var candidates = Directory.GetFiles(
Path.Combine(root, "tests", "Credentials.Conformance.VcApi", "bin", c),
"Credentials.Conformance.VcApi.dll",
SearchOption.AllDirectories);
if (candidates.Length > 0) return candidates[0];3. SdJwtVcInteropTests.Roles() leaks ServiceProvider
private static (IIssuer Issuer, IVerifier Verifier) Roles()
{
var provider = new ServiceCollection().AddCredentials(b => b.UseNetDid()).BuildServiceProvider();
return (provider.GetRequiredService<IIssuer>(), provider.GetRequiredService<IVerifier>());
// provider is never disposed
}Bbs2023InteropTests correctly uses using var provider = Provider(). Here the ServiceProvider is built, services extracted, and then abandoned. Fine in practice (process exit cleans it up), but it's inconsistent with the same codebase and will flag in leak detectors. The fix is either to expose a using-shaped wrapper or hold the provider alongside the services in a disposable fixture. At minimum: consistency with the Bbs tests.
4. VP authentication-proof gap — "Tracked engine bug" should have a tracking issue
docs/conformance.md says the VP authentication-proof interop gap is a "Tracked engine bug" but no issue number is referenced. Given this is a genuine hole in the verification path (VP proof found as NoProof when it exists), it deserves a GitHub issue so it doesn't get buried. Please open one and link it from both the docs table and conformance.md.
Minor observations (not blocking)
W3C suite cloned unpinned from HEAD—git clone --depth 1 https://github.com/w3c/vc-data-model-2.0-test-suiteis the right call for now (pinning a specific SHA would require manual bumps), but a breaking upstream change could cause nightly failures that look like regressions. Worth a note in the workflow or the conformance doc.RunSuiteAsyncexit code is discarded —var (output, _) = await RunSuiteAsync(...). SinceParseCountreturns 0 on no match and 0 < 36 would fail the gate, the right behavior still triggers, but the discard is a yellow flag for readers.- Shim logging cleared —
builder.Logging.ClearProviders()makes the shim completely dark during CI. When the shim misbehaves (hangs, crashes after startup) there's nothing in the redirected stderr to diagnose. Consider leaving a minimal console provider or at least a comment explaining why silence is correct here.
Summary: Issues 1 and 2 are straightforward fixes; 3 is a cleanup; 4 is a tracking discipline item. Nothing here is a correctness or security defect — the conformance gate itself is correct and the honest 36/59 baseline is exactly the right call. Approve after addressing #1 and #2 at minimum.
Generated by Claude Code
…, dispose providers, track VP gap Addresses the PR #10 review: - conformance.yml: add a paths: filter (src/**, tests/**, the workflow) so a docs-only PR doesn't clone the Node suite + run the ~8-min conformance suite (matching the header comment); note the unpinned-from-HEAD clone so a nightly drop is checked against upstream before assuming a regression. - W3cVcdm2SuiteTests.LocateShimDll: glob the TFM directory instead of hardcoding net10.0, so a framework bump can't silently break it; surface the mocha exit code in the diagnostic line. - SdJwtVcInteropTests: dispose the ServiceProvider (using var provider = Provider()), consistent with the Bbs tests — no leaked provider. - Conformance shim: keep warnings/errors on the console (not fully dark) so a crash-after-startup is diagnosable in CI; comment explains the suppression. - VP authentication-proof NoProof gap: opened tracking issue #11 and linked it from docs/conformance.md (was an untracked "engine bug"). Build 0-warning; InteropTests 5 green; conformance harness green (baseline 36). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks — all four plus the three minors addressed in 1. conformance.yml triggers on all PRs ✅Added a 2. LocateShimDll hardcodes net10.0 ✅Replaced with a glob: 3. SdJwtVcInteropTests leaks ServiceProvider ✅Refactored 4. VP auth-proof gap needs a tracking issue ✅Opened #11 (with the Minors ✅
Build 0-warning; InteropTests 5 green; conformance harness green (baseline 36). Ready for another look. |
The last of three M8 PRs (after M8a #8, M8b #9): empirical W3C VCDM 2.0 conformance + cross-implementation interop, closing NFR-007.
Verification: build 0-warning; 357 tests green (+5 interop) plus the conformance harness (passes against the prepared suite, skips otherwise).
What's in it
Credentials.Conformance.VcApi— a minimal ASP.NET VC-API shim overIIssuer/IVerifier(POST /credentials/issue,/credentials/verify,/presentations/verify;GET /returns the shim'sdid:key). Issueseddsa-rdfc-2022, validates structure before signing (so negative issue cases reject), maps non-conforming input to HTTP ≥ 400. The suite injects the shim's owndid:keyascredential.issuer, so issuance satisfies the engine's issuer-binding with no field rewriting.Credentials.Conformance.Tests— boots the shim on loopback, runs thew3c/vc-data-model-2.0-test-suite, asserts a passing baseline of 36 (SkippableFact,Category=Conformance; skips visibly without the Node suite).Credentials.InteropTests(NFR-007) — SD-JWT VC disclosure digests cross-checked against the spec'sbase64url(SHA-256(ascii(disclosure)))algorithm + tampered/unmatched-disclosure negatives +dc+sd-jwtdrift sentinel; bbs-2023 (IsAvailable-gated) pinsbbs-2023/multibase-proofValuedrift sentinels, verifies a derived proof, rejects a tampered mandatory value.conformance.yml(PR + nightly) clones + installs the Node suite and runs the harness;docs/conformance.mdrecords the honest status; the FrCoverage NFR-007 deferral is removed (now tagged).Honest conformance outcome
Empirically the engine passes 36 / 59 W3C suite tests — the structural / issue / verify core. The 23 not-yet-passing are documented known limitations, not a hidden failure: full JSON-LD term mapping (the engine is STJ-only, no JSON-LD expansion — NFR-002),
relatedResourceintegrity,name/descriptionlanguage-value-object validation, and a VP authentication-proof interop gap (the DI mechanism reports the suite'seddsa-rdfc-2022VP proof asNoProof). The harness asserts a regression-guarding baseline rather than faking a clean run — raising it as the engine improves is expected. This is deliberate: report the real conformance level + categorized gaps (see docs/conformance.md), never a false green.Decisions
_sd) — proves digest-algorithm interop without foreign-key vector resolution.IsAvailable/SkippableFact-gated so a host without the native lib / Node suite skips visibly.M8 complete — all three PRs landed (A quality+release gates, B samples+coverage, C conformance+interop).
🤖 Generated with Claude Code