@zanii/vc
v0.1.0
Published
W3C Verifiable Credentials 2.0 bridge - export Zanii credentials and AgentCVs as spec-conformant VCs with genuine eddsa-jcs-2022 DataIntegrityProofs (Zanii already speaks did:key + Ed25519 + JCS, which IS that cryptosuite), and verify any did:key eddsa-jc
Readme
@zanii/vc
The W3C Verifiable Credentials 2.0 bridge — and it is not cosmetic. Zanii already
signs with did:key + Ed25519 over JCS, which is exactly the W3C Data Integrity
cryptosuite eddsa-jcs-2022. So toVC emits spec-conformant VCs with genuine
DataIntegrityProofs that a standards wallet can verify with no Zanii code at all —
and verifyVC verifies any did:key eddsa-jcs-2022 VC from anyone.
npm install @zanii/vc @zanii/core @zanii/credentials @zanii/cvimport { toVC, cvToVC, signVC, verifyVC } from '@zanii/vc';
// a university exports a Zanii diploma credential as a W3C VC (same issuer key):
const vc = toVC(zaniiCredential, issuerPrivateKey, { created: now });
// → { "@context": ["https://www.w3.org/ns/credentials/v2"],
// type: ["VerifiableCredential", "ZaniiCredential"],
// issuer: "did:key:z6Mk…", validFrom, validUntil,
// credentialSubject: { id: holderDid, scope, claim, issuerDomain },
// proof: { type: "DataIntegrityProof", cryptosuite: "eddsa-jcs-2022", proofValue: "z…" } }
// an agent exports its CV as a self-issued VC:
const cvVc = cvToVC(signedCv, agentPrivateKey, { created: now });
// verify anyone's did:key eddsa-jcs-2022 VC:
const r = verifyVC(vc, { at: now }); // window checked only when `at` is passed
r.ok; r.issuer;
// or sign your own custom VC types with the generic engine:
signVC({ '@context': [...], type: ['VerifiableCredential'], issuer, credentialSubject }, keypair, { created });Python: from zanii.vc import to_vc, cv_to_vc, verify_vc, ... — byte-identical:
the same credential + key + timestamp produces the exact same VC (proofValue included)
in both languages, locked by parity vectors.
Guardrails
toVC/cvToVCverify the Zanii artifact first — a forged credential or altered CV is refused, so the bridge can never launder a broken artifact into a valid-looking VC.verifyVCis deterministic: the validity window is checked only against an explicitat, never a hidden "now".
The limit, stated up front
This bridges the format, not the trust model. A VC produced here proves what the
Zanii artifact proved — no more. Revocation with its explicit freshness window, the
domain-bound issuer root-of-trust, and ledger-backed history remain Zanii-side checks
(@zanii/credentials, @zanii/kya); W3C StatusList is deliberately not implemented —
mapping it would claim a liveness this bridge cannot provide. And verifyVC checks
the proof, not the issuer's institutional identity — say what it does, never more.
