Address incompatible entries in extensions registry
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).
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. ;)
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.
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: |
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?
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?
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.
@wip-abramson also said
A DID URL like
did:example?service=serviceIDdereferences 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.
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:cheqdsupport, to define what is returned at certain paths, e.g./resources. - It's fine that
webvhdefines a/whoispath which returns something from a#whoisservice endpoint. - It's fine for
did:ixoto 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/mypathcould return an image, whereasdid:ex:345/mypathcould return a PDF, if that is a functionality enabled by thedid:exmethod.
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.
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!
Also related: https://github.com/w3c/did-resolution/issues/181
This was discussed during the #did meeting on 04 September 2025.
View the transcript
Address incompatible entries in extensions registry #150
<ottomorac> w3c/
<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