did-resolution icon indicating copy to clipboard operation
did-resolution copied to clipboard

Address incompatible entries in extensions registry

Open jandrieu opened this issue 7 months ago • 10 comments

Current extension properties such as https://www.w3.org/TR/did-extensions-properties/#linkedresource specify particular parsing of DID URLs.

In linkedResources, a did URL with a path part, e.g., did:abc/path is taken to be a URL that is intended to be retrieved while did:abc#fragment is taken refer to a node in the DID Document's JSON object. Both are defined in the linkedResource property.

Whereas, in did-linked resources (a CCG work item led by Cheqd), https://w3c-ccg.github.io/did-linked-resources/, they use a path to indicate a resource, followed by the id of that resource, e.g., did:example:entity123/resources/41c0f0fe-cd4e-45aa-aec5-754db4a63865

In contrast, folks working on did:webvh are proposing that did:abc/whois refer to a service endpoint for looking up verifiable credentials about the DID subject.

Unfortunately, there is no restriction on adding these properties to various DID methods, which makes it almost impossible to have a uniform parsing of DID URLs across DID methods.

I'd like to see convergence on the meaning of different DID-URL components so that, e.g., a path part in one method is expected to operate similarly to path parts in other DID URLs.

My proposal:

DID Document DID URL Description
{"path" = "/path"} did:example/path intended to download as a resource. look up node in DID document graph with the path property in did doc == path value in DID URL
{"id" = "#fragment"}` did:example#fragment intended to refer to the JSON node containing an id property equal to the fragment part of the DID URL
{"service" : [{ "id" : "myserviceID"}]} did:example?serviceID intended to invoke a particular service endpoint as described in the service section of the DID doc.

This is just a strawman. I realize this is incompatible with both Cheqd and did:webvh's use.

Hence my interest in finding a way to align these different efforts (and see if there are others we need to incorporate).

jandrieu avatar May 20 '25 19:05 jandrieu

I guess one option would be to require all new properties to be compatible with existing entries.

That would fix the ambiguity, but it would favor my approach simply because it was first to register. That doesn't seem like the right answer, although it's the easiest for me to get behind. ;)

jandrieu avatar May 20 '25 20:05 jandrieu

One other FAQ: what's the difference between a linked resource and a service endpoint?

They both could perform the same function of retrieving an asset, but in practice, services are not expected to return a canonical resource of the kind that might be secured with a integrity hash. Rather, I expect a service endpoint is returning dynamic information or performing a function. In contrast, both forms of linkedResources are designed to make sure the resource you retrieve, in fact, is the resource the DID Controller wanted to you get.

jandrieu avatar May 20 '25 20:05 jandrieu

Below is the position we follow for the did:ixo Method.  The same conventions are implemented consistently by our SDKs, resolvers, and content-addressing middleware, so client developers can rely on deterministic parsing rules.


1  Linked resources vs. internal document nodes

DID-URL component Semantics in did:ixo Resolution rule Typical use-case
Fragment “#” References a JSON node that already exists inside the DID Document graph. Resolver selects the object whose id property matches the fragment, exactly as required by § 3.2 of the core DID spec. Verification methods, services, proofs, linked data resources already embedded in the doc.
Path “/” References an external, content-addressed resource controlled by the DID subject. Resolver builds a URL of the form did:ixo:/resources/ and fetches the resource from IPFS, Matrix, or another address that is specified on-chain in the Resources Registry. Certificates, firmware blobs, models, large JSON-LD manifests – i.e., anything where integrity is guaranteed by the CID and size makes in-document embedding impractical.
Service array Declares dynamic or interactive endpoints. Client picks the entry whose id or type it understands, then performs the protocol indicated in the serviceEndpoint object (HTTP(S), Matrix room, DIDComm V2, etc.). Agent negotiation, VC issuance APIs, webhook callbacks, discovery endpoints such as whois.

We never overload these meanings: a path segment never resolves to a service; a fragment never dereferences an external file.


2  Why this mapping works for us

  • Clarity for implementers.  Every delimiter has one job:

    • # → internal graph node

    • / → external immutable resource

    • serviceEndpoint → live service interface

  • Security & integrity.  Paths always point to CIDs stored on-chain, so the client can verify byte-level integrity before use.  Services intentionally remain off-chain and dynamic.

  • Interoperability.  Our handling of fragments is exactly what the Core DID Rec 1.0 text prescribes, so any conformant resolver will succeed.  For paths, we stay close to the did-linked-resources draft while keeping Cheqd’s UUID segment optional (the CID already guarantees uniqueness).

  • Minimal cognitive load.  A verifier can decide, by simple pattern-matching, whether it is processing a claim (fragment), retrieving evidence (path), or invoking a live oracle (service).


3  Implications for the broader convergence effort

  • If DID methods agree that fragment → document node and path → external resource, client libraries gain a stable two-step resolution algorithm that works regardless of the underlying chain.

  • Service discovery then remains an orthogonal concern handled inside the document (where richer protocol metadata is available), rather than being inferred from URL shape alone.

  • Namespaces such as /resources/ or /vc/ are method-specific but do not introduce ambiguity; they simply indicate which external registry is authoritative.


Open question for this community:


Would a collective test-suite that validates the three behaviours above (fragment node, content-addressed path, dynamic service) across at least two independent DID methods give us the empirical grounding we need to lock these rules into a shared extension spec?

ig-shaun avatar May 21 '25 05:05 ig-shaun

Minor edit @jandrieu

For service: did:example?serviceID is actually did:example?service=serviceID

I was also confused by your description of service

intended to invoke a particular service endpoint as described in the service section of the DID doc.

The spec defines the service parameter as:

Identifies a service from the DID document by service ID. If present, the associated value MUST be an ASCII string.

A DID URL like did:example?service=serviceID dereferences to either the whole service JSON object or the serviceEndpoint URL depending on the mediaType requested.

What did you mean by invoke a particular service?

wip-abramson avatar May 21 '25 12:05 wip-abramson

What did you mean by invoke a particular service?

I mean that dereferencing the service endpoint URL is not expected to return a particular, integrity checked resource, but is more generally expected to act like any URL: triggering a process on a server and returning whatever result the server decides. Invoking a particular service is the dereferencing of that URL to its resource.

The semantics mattered for DIDs that refer to NFTs because some NFT properties, IMO, should be invariant, e.g., the image of a NFT collectible should NOT be an arbitrary image that can be changed at any time by the source of the NFT. Rather, we want to memorialize that a particular image (with a particular hash) is linked by this NFT (as described in the NFT's DID Document).

So I expect you'll have service endpoints that have indeterminate responses, likely because they simply accept a message, like a NOSTR service endpoint, which lets you send a message to a particular pubkey via a relay, but the reply itself is not an integrity-secured resource in the way an associated image might be.

jandrieu avatar May 21 '25 17:05 jandrieu

@wip-abramson also said

A DID URL like did:example?service=serviceID dereferences to either the whole service JSON object or the serviceEndpoint URL depending on the mediaType requested.

I would disagree.

The DID URL like that resolves to the JSON object and/or the URL.

Dereferencing that DID URL, I believe, means dereferencing that service endpoint URL.

That is, when I put a did:example:abc/path.img as the src atribute in a tag in HTML, dereferencing that DID URL must return the actual image, not a string URL, which would not be an image and could not be used in the rendering of that HTML element.

jandrieu avatar May 21 '25 17:05 jandrieu

I think we're overcomplicating this discussion about paths. I actually think that everything is basically fine the way it works now, including the algorithm in https://www.w3.org/TR/did-resolution/#dereferencing-algorithm-resource.

@jandrieu wrote:

a path part in one method is expected to operate similarly to path parts in other DID URLs.

I disagree with that, I don't think we should have rules about how a path must be processed uniformly across all DID methods and all DIDs. It should be up to the DID method to decide what is returned when you dereference a DID with a path, just like every HTTP authority can decide what paths it supports and what is returned at certain paths.

  • It's fine that there are extensions like DID Linked Resources which some DID methods such as did:cheqd support, to define what is returned at certain paths, e.g. /resources.
  • It's fine that webvh defines a /whois path which returns something from a #whois service endpoint.
  • It's fine for did:ixo to behave as described in https://github.com/w3c/did-resolution/issues/150#issuecomment-2896585165.
  • It's fine that some DID methods may even allow every DID controller to control the paths under their own DID independently, e.g. did:ex:123/mypath could return an image, whereas did:ex:345/mypath could return a PDF, if that is a functionality enabled by the did:ex method.

I don't think there's a need or value in "aligning" or "converging" anything here. We should not touch the structure, meaning, and behavior of the DID URL path on the DID Core and DID Resolution level, but leave this open for DID methods and extensions to use and innovate how they want.

(If we had kept the matrix parameters feature a few years ago, we could have also left the DID URL query untouched and open for DID methods to use and innovate).

If some DID methods decide to converge their use of the path in certain ways, like did:cheqd and others decide to support DID Linked Resources, great, we can register this as an extension, but this wouldn't be "forced" upon all other DID methods.

If we want to define any "global" dereferencing behaviors that apply to all DIDs and DID methods, we should do that only with DID parameters and options like service, verificationRelationship, etc. E.g. the use of the service DID parameter works uniformly across all DID methods, it's method-independent.

In my opinion, the only step we should potentially take is add a bit more language to the DID URL Dereferencing algorithm, which points out that DID methods may decide to support extensions such as DID Linked Resources, which define how to dereference paths.

peacekeeper avatar May 22 '25 14:05 peacekeeper

This was discussed during the #did meeting on 31 July 2025.

View the transcript

w3c/did-resolution#150

JoeAndrieu: We currently allow open ended additions to extensions registry -- you can have properties that modify parsing for DID Method, we have an avenue for incompatibility where a naieve DID controller could add properties from extensions and not realize they're breaking each other... one might use frament identifier, one might use query parameter... issue with linkedResources... different properties and different ways to put item in DID Document or

DID Document metadata.

manu: this might be limitting innovation a bit, even if it is friendly to implementers...

<Zakim> JoeAndrieu, you wanted to suggest self-labeling on submission

manu: We could limit the extensions that conflit to specific DID Methods.

JoeAndrieu: Maybe when we do the registration, we allow self-labeling on submission of the extension -- point out the conflicts.

Wip: Maybe we should add an issue on DID Extensions registry.

Wip: With that, we're done with today. We're going to do test suite discussion next wednesday, we'll also discuss horizontal review.

Wip: Thanks all, have a great week/weekend, see you next week!


w3cbot avatar Jul 31 '25 15:07 w3cbot

Also related: https://github.com/w3c/did-resolution/issues/181

msporny avatar Aug 21 '25 15:08 msporny

This was discussed during the #did meeting on 04 September 2025.

View the transcript

Address incompatible entries in extensions registry #150

<ottomorac> w3c/did-resolution#150

<ottomorac> We had some prior discussion of how to address this between Joe and Manu. Will discussed maybe adding an issue on the DID Extensions registry.

Wip: we do need manu for that, and can happen on the special topic call

JoeAndrieu: agreed
… all these options need to coalesce

markus_sabadello: agreed. this can be in the special topic call
… in my mind, the examples that are here are quite different than the syntactic sugar scenarios
… and what we have here is completely did method dependent
… the differences can be discussed on the special topic call

ottomorac: would it make sense to add the folks from did:cheqd to the special topic call?

markus_sabadello: yes. I will do that
… they were some of the first to explore that

JoeAndrieu: just to clarify, we were in the registry before them ;)
… but it would be good to get someone from there to join the call

ottomorac: anyone else we need to add?

JoeAndrieu: yes. I will reach out to others

ottomorac: 10 Eastern on September 24th

ottomorac: any other pressing issues?

JoeAndrieu: yes. maybe pchampin can help us clarify


w3cbot avatar Sep 04 '25 16:09 w3cbot