Skip to content

M8c: conformance + interop (the M8 finale)#10

Merged
moisesja merged 2 commits into
mainfrom
feature/m8c-conformance-interop
Jun 24, 2026
Merged

M8c: conformance + interop (the M8 finale)#10
moisesja merged 2 commits into
mainfrom
feature/m8c-conformance-interop

Conversation

@moisesja

Copy link
Copy Markdown
Owner

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 over IIssuer/IVerifier (POST /credentials/issue, /credentials/verify, /presentations/verify; GET / returns the shim's did:key). Issues eddsa-rdfc-2022, validates structure before signing (so negative issue cases reject), maps non-conforming input to HTTP ≥ 400. The suite injects the shim's own did:key as credential.issuer, so issuance satisfies the engine's issuer-binding with no field 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 Node suite).
  • Credentials.InteropTests (NFR-007) — SD-JWT VC disclosure digests cross-checked against the spec's base64url(SHA-256(ascii(disclosure))) algorithm + tampered/unmatched-disclosure negatives + dc+sd-jwt drift sentinel; bbs-2023 (IsAvailable-gated) pins bbs-2023/multibase-proofValue drift 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.md records 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), relatedResource integrity, name/description language-value-object validation, and a VP authentication-proof interop gap (the DI mechanism reports the suite's eddsa-rdfc-2022 VP proof as NoProof). 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

  • Issuer-binding bridge: configure the suite with the shim's own DID (the suite injects it as the issuer) rather than rewriting documents.
  • Interop uses an independent spec-algorithm cross-check (recompute digests, match _sd) — proves digest-algorithm interop without foreign-key vector resolution.
  • bbs-2023 + the conformance run are 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

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 moisesja left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

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: filter

The 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 HEADgit clone --depth 1 https://github.com/w3c/vc-data-model-2.0-test-suite is 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.
  • RunSuiteAsync exit code is discardedvar (output, _) = await RunSuiteAsync(...). Since ParseCount returns 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 clearedbuilder.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

@moisesja moisesja self-assigned this Jun 24, 2026
…, 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>
@moisesja

Copy link
Copy Markdown
Owner Author

Thanks — all four plus the three minors addressed in c25e5df (validated each against the code first).

1. conformance.yml triggers on all PRs ✅

Added a paths: filter (src/**, tests/**, .github/workflows/conformance.yml) so a docs-only PR no longer clones the Node suite and runs the ~8-minute suite — now matching the header comment.

2. LocateShimDll hardcodes net10.0 ✅

Replaced with a glob: Directory.GetFiles(bin/<config>, "Credentials.Conformance.VcApi.dll", AllDirectories) — a TFM bump now finds the DLL instead of throwing FileNotFoundException.

3. SdJwtVcInteropTests leaks ServiceProvider ✅

Refactored Roles()Provider() and each test now uses using var provider = Provider(), consistent with Bbs2023InteropTests. No abandoned provider.

4. VP auth-proof gap needs a tracking issue ✅

Opened #11 (with the [VP-DIAG] repro, the DefaultVerifier.cs:233 NoProof path, and the likely area — incl. the DI binding path not setting Kind = SecuringDocumentKind.Presentation) and linked it from the docs/conformance.md table row (was "Tracked engine bug").

Minors ✅

  • mocha exit code is now surfaced in the diagnostic line (mocha exit {exitCode}) rather than discarded.
  • Shim logging: kept warnings/errors on the console (ClearProviders + AddConsole + SetMinimumLevel(Warning)) so a crash-after-startup is diagnosable in CI, with a comment explaining the suppression of per-request info logs.
  • Unpinned suite clone: added a workflow comment noting a sudden nightly drop should be checked against upstream history before being treated as a regression.

Build 0-warning; InteropTests 5 green; conformance harness green (baseline 36). Ready for another look.

@moisesja moisesja merged commit 7ef9732 into main Jun 24, 2026
3 checks passed
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