Skip to content

feat(vc): upgrade to W3C VC Data Model v2.0 (Phase 1, dual-accept)#72

Merged
MoltyCel merged 1 commit into
mainfrom
feat/vc-v2-phase1
May 25, 2026
Merged

feat(vc): upgrade to W3C VC Data Model v2.0 (Phase 1, dual-accept)#72
MoltyCel merged 1 commit into
mainfrom
feat/vc-v2-phase1

Conversation

@MoltyCel
Copy link
Copy Markdown
Owner

Summary

  • Newly issued credentials are now W3C VC Data Model v2.0: @context points to https://www.w3.org/ns/credentials/v2, timestamp fields are validFrom / validUntil.
  • verify_credential is dual-accept: still recognises legacy v1 envelopes (issuanceDate / expirationDate) so credentials minted before this PR keep verifying until the dataset rotates.
  • Two helpers (vc_valid_from, vc_valid_until) replace direct field reads at every DB-insert call-site.

Wire-Check (before)

@context: ["https://www.w3.org/2018/credentials/v1", "https://api.moltrust.ch/contexts/trust/v1"]
issuanceDate / expirationDate

Wire-Check (after)

@context: ["https://www.w3.org/ns/credentials/v2", "https://api.moltrust.ch/contexts/trust/v1"]
validFrom / validUntil

Touched files

File Change
app/credentials.py v2 emit + vc_valid_from / vc_valid_until helpers + dual-read in verify_credential
app/swarm/endorsement.py SkillEndorsementCredential emitted as v2
app/main.py VerifiedMusicCredential (both build paths) as v2; DB-insert call-sites switched to helpers
backfill_credentials.py, agent/ambassador.py Helper-based reads
tests/test_credentials_vc_v2.py New — 10 tests (helpers + roundtrip + v1 legacy verify + expiry)

Out of scope (intentional)

  • credentialSubject.provenance.issuanceDate on Music VCs — internal MolTrust vocabulary, not the W3C VC core field.
  • ViolationRecord (@context: https://moltrust.ch/ns/violation/v1) — not a W3C VC, no VerifiableCredential type.

Test plan

  • pytest tests/test_credentials_vc_v2.py — 10/10 pass (server scratch checkout w/ venv)
  • Import-smoke (CI-style env): from app.main import app → OK
  • Syntax check: python -m compileall on all touched files → clean
  • Post-merge: smoke a real /credentials/issue against staging, confirm response carries validFrom/validUntil not issuanceDate/expirationDate
  • Post-merge: smoke /credentials/verify against a legacy v1 credential pulled from the credentials table — confirm it still validates

Notes for review

  • Phase 1 = backwards-compat. Phase 2 (later sprint) would: drop v1 verify path, migrate existing raw_vc rows in credentials table, retire helpers.
  • DB schema unchanged — issued_at / expires_at columns absorb the v2 timestamps just fine via the helpers.

🤖 Generated with Claude Code

Newly issued credentials use VC v2: @context points to
https://www.w3.org/ns/credentials/v2 and the timestamp fields are
`validFrom` / `validUntil`. Verification is dual-accept — it still
recognises legacy v1 envelopes (`issuanceDate` / `expirationDate`)
so credentials minted before this migration keep verifying until
the dataset rotates.

Changes:
- app/credentials.py: emit v2, add vc_valid_from/vc_valid_until helpers,
  verify_credential reads expiry via helper (accepts both shapes).
- app/swarm/endorsement.py: SkillEndorsementCredential issued as v2.
- app/main.py: VerifiedMusicCredential (both build paths) issued as v2.
  All DB-insert call-sites that used to parse vc["issuanceDate"] /
  vc["expirationDate"] now go through the helpers.
- backfill_credentials.py, agent/ambassador.py: same helper-based read.
- tests/test_credentials_vc_v2.py: 10 tests covering helper fallback
  semantics, v2 issuance shape, v1 legacy verify, v2 roundtrip, expiry.

Out of scope (intentional):
- credentialSubject.provenance.issuanceDate on Music VCs — internal
  moltrust vocabulary, not the W3C VC core field.
- ViolationRecord — separate @context (moltrust/ns/violation/v1),
  not a W3C VC, no VerifiableCredential type.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@MoltyCel MoltyCel merged commit 9767d6f into main May 25, 2026
12 checks passed
@MoltyCel MoltyCel deleted the feat/vc-v2-phase1 branch May 25, 2026 10:53
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