Create your own magic with Web 7.0 DIDLibOS™ / TDW AgenticOS™. Imagine the possibilities.
Copyright © 2026 Michael Herman (Bindloss, Alberta, Canada) – Creative Commons Attribution-ShareAlike 4.0 International Public License
Web 7.0™, Web 7.0 DILibOS™, TDW AgenticOS™, TDW™, Trusted Digital Web™ and Hyperonomy™ are trademarks of the Web 7.0 Foundation. All Rights Reserved.
DSA: Which field values of the following documents are locator DIDs and which are identity DIDs?
- DID Document
- VC Document
- DIDComm Message
In what follows, each document type is systematically and precisely mapped to the DID identity/locator framework.
DID Document
{ "id": "did:drn:z6Mk...9xEg", ← IDENTITY "controller": "did:drn:z6MkController...abc", ← IDENTITY "alsoKnownAs": ["did:drn:z6MkAka...xyz"], ← IDENTITY "verificationMethod": [{ "id": "did:drn:z6Mk...9xEg#key-1", ← LOCATOR "controller": "did:drn:z6Mk...9xEg", ← IDENTITY "type": "Ed25519VerificationKey2020", "publicKeyMultibase": "z6Mk..." }], "authentication": [ "did:drn:z6Mk...9xEg#key-1" ← LOCATOR ], "assertionMethod": [ "did:drn:z6Mk...9xEg#key-1" ← LOCATOR ], "capabilityInvocation": [ "did:drn:z6Mk...9xEg#key-1" ← LOCATOR ], "capabilityDelegation": [ "did:drn:z6Mk...9xEg#key-1" ← LOCATOR ], "keyAgreement": [ "did:drn:z6Mk...9xEg#key-2" ← LOCATOR ], "service": [{ "id": "did:drn:z6Mk...9xEg#vcregistry-1", ← LOCATOR "type": "CredentialRegistry", "serviceEndpoint": "https://registry.example.com/..." ← URL (retrieval) }, { "id": "did:drn:z6Mk...9xEg#didcomm-1", ← LOCATOR "type": "DIDCommMessaging", "serviceEndpoint": "https://agent.example.com/..." ← URL (retrieval) }]}
Pattern: id at the document root is always an identity DID. Every field that contains a fragment — verification methods, verification relationships, service entries — is always a locator DID. controller is always an identity DID. serviceEndpoint values are retrieval URLs, outside the DID identity/locator taxonomy entirely.
VC Document
{ "@context": [...], "id": "did:drn:z6MkCredential...abc", ← IDENTITY (envelope identity) "type": ["VerifiableCredential", "MembershipCredential"], "issuer": { "id": "did:drn:z6MkIssuer...3kRt", ← IDENTITY "name": "Web 7.0 Foundation" }, "validFrom": "2026-01-01T00:00:00Z", "validUntil": "2027-01-01T00:00:00Z", "credentialSubject": { "id": "did:drn:z6MkSubject...9xEg", ← IDENTITY (subject identity) "memberOf": "did:drn:z6MkOrg...7fPq", ← IDENTITY "role": "Member" }, "credentialStatus": { "id": "did:drn:z6MkStatus...8bNm", ← LOCATOR (points into status registry) "type": "StatusList2021Entry" }, "cryptoseal": [{ "type": "DataIntegrityProof", "verificationMethod": "did:drn:z6MkIssuer...3kRt#key-1", ← LOCATOR "cryptosuite": "eddsa-2022", "created": "2026-01-01T00:00:00Z", "proofValue": "z58DAdFfa..." }]}
Pattern: Top-level id, issuer.id, credentialSubject.id, and any DID references within claims are all identity DIDs — they name entities. credentialStatus.id and proof.verificationMethod are locator DIDs — they navigate to sub-resources. The credentialStatus.id is the one field that often goes unrecognized as a locator but clearly is: it points into a status registry to retrieve the current revocation state of this specific credential.
DIDComm Message
{ "id": "urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6", ← IDENTITY (message identity — URN, not DID) "type": "https://didcomm.org/basicmessage/2.0/message", ← IDENTITY (IRI naming message type) "typ": "application/didcomm-encrypted+json", "from": "did:drn:z6MkSender...abc", ← IDENTITY "to": ["did:drn:z6MkRecipient...xyz"], ← IDENTITY "thid": "urn:uuid:parent-thread-id", ← IDENTITY (thread identity) "pthid": "urn:uuid:parent-parent-thread-id", ← IDENTITY (parent thread identity) "created_time": 1704067200, "expires_time": 1704153600, "from_prior": { "iss": "did:drn:z6MkPrior...def", ← IDENTITY (prior DID — rotation) "sub": "did:drn:z6MkSender...abc", ← IDENTITY (new DID — rotation) "aud": "did:drn:z6MkRecipient...xyz" ← IDENTITY }, "body": { "content": "..." }, "attachments": [{ "id": "attachment-1", ← IDENTITY (attachment identity) "media_type": "application/vc+ld+json", "data": { "links": ["did:drn:z6MkSubject...9xEg?service=CredentialRegistry"] ← LOCATOR } }]}
Pattern: DIDComm message fields are overwhelmingly identity DIDs — from, to, from_prior.iss, from_prior.sub, from_prior.aud all name parties, not locations. The message id is typically a URN UUID — an identity token outside the DID space entirely. Locator DIDs appear only when explicitly navigating to a sub-resource — such as a CredentialRegistry service endpoint in an attachment link, or a verification method reference in an attached cryptoseal.
Cross-Document Summary
| Field | DID Doc | VC Doc | DIDComm |
|---|---|---|---|
Document id | Identity | Identity | Identity (URN) |
controller | Identity | — | — |
issuer / issuer.id | — | Identity | — |
credentialSubject.id | — | Identity | — |
from / to | — | — | Identity |
from_prior.iss / .sub | — | — | Identity |
verificationMethod.id | Locator | — | — |
| Verification relationship refs | Locator | — | — |
service.id | Locator | — | — |
proof.verificationMethod | — | Locator | — |
credentialStatus.id | — | Locator | — |
Attachment links with ?service= | — | — | Locator |
The governing rule across all three document types is consistent and clean:
A DID with no
#or?is always an identity DID — it names an entity.
A DID with#or?is always a locator DID — it navigates to a sub-resource.
This rule holds uniformly across DID Documents, VC Documents, and DIDComm Messages.