dpp-vc 0.21.0

W3C Verifiable Credentials, did:web documents and status lists for Odal Node
Documentation

dpp-vc

crates.io docs.rs License: Apache-2.0

The trust layer for the Odal Node Digital Product Passport system: W3C Verifiable Credentials, did:web documents, Bitstring Status List revocation, and the JSON-LD context those are expressed in.

Pure Rust, no I/O, no network calls. Not a wasm32-unknown-unknown target — it depends on dpp-crypto, whose RNG requires a platform entropy source.

When to use this crate

  • You are issuing or verifying a credential that proves a supply-chain actor's role — an authorised repairer, a recycler, a market-surveillance authority.

  • You need to publish or resolve a did:web document for a manufacturer or operator.

  • You need to check whether a credential has been revoked against a Bitstring Status List.

  • You are building the JSON-LD envelope for a passport or a credential.

  • You are reading a copy of a passport's public view and need to know whether its time bound still holds — see snapshot.

  • You are issuing a passport as an SD-JWT VC so a holder can present part of it to a third party without the issuing node being reachable — see sd_jwt_vc. That door is keyed by JWT VC Issuer Metadata rather than did:web, because the credential profile defines no DID mechanism.

    It does not resolve those keys, and nothing in this crate does: there is no I/O here. build_issuer_metadata produces the document an issuer publishes, and verify takes the key the caller has already chosen. Fetching the metadata, deciding whether to trust it, and picking the key out of it are the application's, which is also where a network policy belongs.

What this crate is not

Three neighbouring concerns live elsewhere, and the boundaries are deliberate:

Concern Home Why not here
Cryptographic primitives — JWS, keys, keystore dpp-crypto Signing bytes is a different job from deciding whose signature means what
The disclosure contract — Audience, Disclosure, the per-field map and its filter dpp-domain Which fields a role may see describes what a passport is, not who is asking
Projections — GS1, AAS dpp-digital-link, dpp-aas Rendering a passport for an ecosystem says nothing about trust

The seam this crate sits on: a credential establishes which Audience a caller holds; the disclosure policy maps that Audience to fields. Two questions, two places.

Example

use dpp_vc::{CredentialBuilder, CredentialRole, DppCredentialSubject};

let subject = DppCredentialSubject {
    id: "did:web:repairer.greenfix.de".into(),
    name: "GreenFix Repair GmbH".into(),
    role: CredentialRole::AuthorisedRepairer,
    country: "DE".into(),
    product_groups: vec!["textile".into()],
    product_categories: vec![],
};

let credential = CredentialBuilder::new(
    "did:web:authority.trade-registry.europa.eu".into(),
    subject,
)
.expires_in_days(365)
.build();

A runnable version covering issuance and transfer is in examples/credential_and_transfer.rs.

Relationship to other crates

Crate Role
dpp-domain Provides Audience, Disclosure, PassportId and IdentityPort — required by this crate
dpp-crypto Provides JWS signing/verification and the keystore — required by this crate

The HTTP surface that issues and verifies these credentials is not here and is not part of this workspace: it belongs to the application consuming this crate. Everything below that boundary — the credential shapes, the signing, the status lists — is what this crate provides, and it is usable without one.

Minimum Rust version

1.96 (MSRV is enforced in CI)

License

Apache-2.0 — see LICENSE