Skip to content

Decide whether this node issues passports as SD-JWT VCs, now that core reads array elements #449

Open

Description

@LKSNDRTMLKV

#359 left this as "a capability decision for later": whether this node ever issues a passport as an SD-JWT VC and lets a holder present part of it without us being reachable. Nothing here has changed that, and this records what core now offers, what it still lacks, and what has to be decided. It is not actionable until a dpp-core release carries the changes below.

Where this repository stands

It has no SD-JWT surface at all: sd-jwt, sd_jwt and selective disclos appear in no file. The only credential path is X-DPP-Credential, a compact JWS of a DppAccessCredential (VC-JWT), in crates/dpp-vault/src/middleware/credential.rs. #70 is the other credential door (UNTP, application/vc+jwt).

What core has done since #359

Neither is a reason to build the door. They make the primitive trustworthy.

What core says is still missing for a credential worth issuing

From dpp_vc::sd_jwt_vc's own documentation, restated here so the decision does not need it open:

Decisions

  1. Does the node issue them at all? Core's own framing: it does not replace the audience-scoped read, it is the other shape, for holders who want to prove things without the node. Is there a holder in the product who does?
  2. Where does it live? A route and a media type, and how it sits beside UNTP DPP credential as a second door #70 and the negotiation seam.
  3. When is it issued? A passport's signed views freeze at publish; core's design conceals every non-public claim at issuance, so that a later reclassification costs nothing. Issue once at publish, or on request?
  4. How is the key found? Core publishes issuer metadata keyed by the thumbprint URI that is also the kid, and the node already publishes a did:web document. Two discovery paths to one key needs one answer.
  5. Withdrawal. Given the first gap above, is issuing acceptable before a status mechanism exists? My recommendation is no, because the credential cannot be recalled.
  6. Who presents? The node holds no holder keys, so presentation is somebody else's act. See Decide how part of an SD-JWT VC is presented: who chooses the Disclosures, and where #450.

Merge gate for any implementation

Written now so it is not discovered late:

Done when

A decision on each point above is recorded here. If the answer to 1 is yes, the implementation is split into issues of its own.

Activity

  1. added
    type/decisionNeeds a call; analysis alone will not close it
    surface/schemaMoves a JSON schema, instrument manifest or product group
    on Oct 7, 2026
  2. LKSNDRTMLKV commented on Oct 12, 2026

    @LKSNDRTMLKV
    MemberAuthor

    What dpp-core 0.22.0 changes for this decision

    Lands here only after core 0.22.0 is released. The repin itself needs no SD-JWT change, because this repository still has no SD-JWT surface.

    Key binding exists in core now (odal-node/dpp-core#428, in PR odal-node/dpp-core#429, stacked on odal-node/dpp-core#426). Three things, one per role of RFC 9901:

    • An Issuer names the Holder's Ed25519 key in cnf (dpp_crypto::sd_jwt::holder_key_confirmation).
    • A Holder binds a presentation to that key: SdJwt::present_with_key_binding signs a Key Binding JWT with iat, aud, nonce and the sd_hash of what is presented.
    • A Verifier whose policy requires it reads with SdJwt::disclosed_payload_with_key_binding and a KeyBindingPolicy: the nonce it issued, its audience, and an instant it supplies.

    Both independent implementations in core's sdjwt-oracle.yml judge it, and core validates the Key Binding JWTs they issue. That removes the "no key binding" line from the gaps listed above. Nothing about who holds the keys has changed: the node still holds no holder keys.

    What core still does not do for a credential (dpp_vc::sd_jwt_vc):

    • It neither names a Holder key when it issues nor requires Key Binding when it verifies. If decision 1 is yes and holders bind, that wiring is a core change, a holder key at issuance and a verify that takes a KeyBindingPolicy, and it would ship in a core release after 0.22.0. It was left out on purpose, so as not to build an API before this decision.
    • No status claim and no exp, no Type Metadata, and EdDSA only, as before.

    The merge gate above, updated. "Finding one that accepts EdDSA" is done: @sd-jwt/core 0.22.0 and eudi-lib-jvm-sdjwt-kt 0.20.2 both verify core's EdDSA tokens and Key Binding JWTs, so an implementation here can be judged by the same two.

    When this is decided: whatever implementation follows starts from core 0.22.0 or later and lands after it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    surface/schemaMoves a JSON schema, instrument manifest or product grouptype/decisionNeeds a call; analysis alone will not close iturgency/backlogOwed, unscheduled

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions