HIP-0097: Node Identity and the did:hanzo: DID Method
Abstract
Every Hanzo node, profile, agent, and device is currently named with the
Shinkai-legacy HanzoName format: a @@-prefixed label with a network suffix
baked into the string, e.g. @@alice.sep-hanzo/main/agent/myChatGPTAgent. That
string is signed into every HanzoMessage and is the lookup key for on-chain
identity registration (Base Sepolia, contract
0x425fb20ba3874e887336aaa7f3fab32d08135ba9). It therefore is not a cosmetic
label — it is consensus- and wire-critical.
This HIP proposes one clean replacement scheme: the canonical node identity is a
did:hanzo:<name> Decentralized Identifier — the same W3C DID method this HIP
specifies for every Hanzo subject. The legacy @@…<suffix> and the
network-in-the-string design are retired. The network/chain is expressed as DID
query parameters or resolved from the registry, never embedded in the human-readable
name. A precise grammar and charset are defined, the signing and on-chain
registration impact is specified, and a backward-compatible, three-phase migration
and rollout is given so that no in-flight message or already-registered name breaks.
The same method serves every Hanzo subject — humans, agents, services and devices —
so this HIP also specifies the DID Document a did:hanzo: identifier resolves to
(§8), the resolution contract and lifecycle against the on-chain registry (§9), and
the Verifiable Credential format that carries everything which is an attribute of a
subject rather than its identity (§10).
Motivation
The @@<name>.<network>-hanzo format is inherited verbatim from Shinkai. It has
four concrete problems, all of which touch code that is live today in
hanzo-libs/hanzo-messages/src/schemas/hanzo_name.rs:
-
Network is welded into the identity string. The valid endings are hard-coded:
.hanzo,.sepolia-hanzo,.arb-sep-hanzo,.sep-hanzo(HanzoName::VALID_ENDINGS). The same node on testnet vs. mainnet has a different identity string, a different signed sender, and a different registry key. Migrating a node from Base Sepolia to the Hanzo L1 mainnet (HIP-24, chain36963) today means it is literally a different identity. This is the single worst property of the legacy scheme. -
@@is non-standard and non-interoperable. It is not a URI, not a DID, not a DNS name. Nothing outside Hanzo can resolve it. Meanwhiledid:hanzo:is the W3C-compliant identity method for every other Hanzo subject — humans, agents, services and devices — with a W3C resolver and an on-chain registry (IHanzoDIDRegistry). Node identity and DID identity are needlessly two different namespaces. -
The format is already half-migrated, inconsistently.
HanzoNamealready acceptsdid:hanzo:<network>anddid:lux:<network>(seeis_did_format,validate_did_name), but only as a network selector (did:hanzo:mainnet,did:hanzo:sepolia,did:hanzo:local:node1) — the node's own name still has no home in that form, and a separatehanzo-libs/hanzo-didcrate parses general W3C DIDs with yet another grammar. Three parsers, one concept. -
Charset and case rules are loose. The legacy regex
^@@[a-zA-Z0-9\_\.]+(\.hanzo|…)$permits embedded dots in the node label (@@a.b.c.hanzo), mixes case then lowercases at construction, and silently auto-corrects (correct_node_nameprepends@@and appends.hanzo). Loose, auto-correcting identity parsing is a security smell for something that is signed.
Specification
1. Decision: did:hanzo:<name>, not <name>.hanzo
Two candidate clean schemes were considered:
- A. ENS-like
<name>.hanzo— e.g.alice.hanzo,alice.hanzo/main/agent/x. - B. DID-style
did:hanzo:<name>— e.g.did:hanzo:alice,did:hanzo:alice/main/agent/x.
This HIP selects B, did:hanzo:<name>. Rationale:
| Criterion | <name>.hanzo (A) | did:hanzo:<name> (B) — chosen |
|---|---|---|
| Aligns with existing standard | No — new third namespace | Yes — the did:hanzo: method itself |
Already parseable by HanzoName | No | Partly — did:hanzo: path exists today |
| Network kept out of the name | Yes | Yes (query param / registry, never the label) |
| Globally resolvable / W3C interop | No (looks like a DNS host but isn't) | Yes — resolves at did.hanzo.ai, did: URI scheme |
| Collides with real DNS / TLD confusion | Yes (.hanzo reads as a gTLD) | No |
| One identity across testnet/mainnet | Yes | Yes |
Verifiable Credentials, alsoKnownAs cross-chain (did:lux:, did:ai:) | No native hook | Native (§8, §10) |
A reads more cleanly to a human, but it manufactures a third identity grammar
(after @@… and did:…) and looks deceptively like a DNS hostname while resolving
through none of DNS. B collapses node identity into the DID method the ecosystem
already standardized, makes node identity a first-class W3C DID, and gets
cross-chain alsoKnownAs, Verifiable Credentials, and the did.hanzo.ai resolver
for free. The human-friendly display form is recovered cheaply (see §6, UX) by
rendering did:hanzo:alice as alice / @alice in UIs without changing the wire
identity.
Note on
did:hanzo:mainnetlegacy usage: the existing code usesdid:hanzo:<network>where the method-specific-id is a network. Under this HIP the method-specific-id is the node name, and the network moves to a query parameter (?chain=/?network=).did:hanzo:mainnetis reinterpreted during migration as the reserved node namemainneton the default chain; deployments that used it purely as a network selector MUST migrate todid:hanzo:<node>?network=mainnet(see Migration §M0).
2. Canonical grammar (ABNF)
The canonical, signed, on-chain identity is the hanzo-id production:
hanzo-id = did-node [ "/" profile [ "/" sub-type "/" sub-name ] ]
did-node = "did:hanzo:" name [ params ]
name = label *( "_" label ) ; node name, the method-specific-id
label = lletter *( letterdigit ) ; MUST start with a letter
profile = label *( "_" label )
sub-type = "agent" / "device"
sub-name = label *( "_" label )
params = "?" param *( "&" param ) ; OPTIONAL; carried, never signed (§3)
param = pkey "=" pval
pkey = "network" / "chain" / "versionId" / "versionTime"
pval = 1*( unreserved )
letterdigit = lowletter / digit
lowletter = %x61-7A ; a-z (lowercase ONLY)
letter = lowletter
digit = %x30-39 ; 0-9
unreserved = lowletter / digit / "-" / "." / ":"
Equivalently, the node-name regex (replacing the legacy
^@@[a-zA-Z0-9\_\.]+(\.hanzo|…)$):
^did:hanzo:[a-z][a-z0-9]*(_[a-z0-9]+)*(\?[a-z]+=[a-z0-9.:-]+(&[a-z]+=[a-z0-9.:-]+)*)?$
Charset and length rules (normative)
- Lowercase only. The method-specific name and every path segment MUST match
[a-z][a-z0-9_]*. No uppercase, no auto-lowercasing at parse time — a mixed-case input is rejected, not silently corrected. (The legacy lower-casing inHanzoName::newis removed; canonicalization is now the caller's job before signing.) - No dots in names. Unlike legacy
@@a.b.hanzo, the node name MUST NOT contain.. Dots appear only insideparamsvalues (e.g. a chain RPC alias). - Separator is
_inside a segment,/between segments. Matches the existing 4-part structure (node / profile /agent|device/ name) so downstream parsing ininbox_name.rs,tool_router_key.rs, etc. keeps the samesplit('/')shape. - Length:
nameand each path segment 1–63 bytes; totalhanzo-id≤ 255 bytes (DNS-label-compatible bound, keeps registry keys bounded). - Reserved names:
localhost,mainnet,testnet,sepolia,local,node,agent,device,didMUST NOT be used as a nodenameexcept for the reserved-mapping defined in Migration §M0. The default local dev identity becomesdid:hanzo:localhost?network=local(replacing@@localhost.sep-hanzo).
Valid examples
did:hanzo:alice
did:hanzo:alice/main
did:hanzo:alice/main/agent/my_chatgpt_agent
did:hanzo:alice/main/device/my_phone
did:hanzo:alice?network=mainnet
did:hanzo:alice?chain=36963
did:hanzo:node1?network=sepolia ; Base Sepolia during migration
did:hanzo:localhost?network=local
Invalid examples (and why)
@@alice.sep-hanzo ; legacy @@ form — rejected post-migration (accepted read-only in Phase 1)
did:hanzo:Alice ; uppercase
did:hanzo:al!ce ; illegal char
did:hanzo:a.b.c ; dot in node name
did:hanzo:_alice ; must start with a letter
did:hanzo:alice/main/myPhone ; 3-part must be …/agent/… or …/device/…
did:hanzo:alice/main/agent ; agent/device requires a 4th sub-name part
did:hanzo:alice.hanzo ; no network/TLD suffix in the name
3. Network is a parameter, never part of the identity
The single most important rule: the chain/network is NOT part of the signed,
on-chain identity. did:hanzo:alice is the same node whether it is registered on
Base Sepolia (migration), the Hanzo L1 mainnet (chain 36963, HIP-24), or running
locally.
- The optional
params(?network=…,?chain=…) are a resolution hint only. - When computing the value that is signed (sender/recipient in
external_metadata) and the value used as the registry key, the params are stripped. The canonical signed form is the baredid:hanzo:<name>[/path]with no query string. - This directly fixes Motivation #1: a node moving from testnet to mainnet keeps the same identity, the same signed sender, and the same registry key.
4. Signing impact
In hanzo_message_signing.rs, the name is not hashed field-by-field; rather
external_metadata.sender / external_metadata.recipient (full HanzoName
strings) are part of the message whose hash is signed with ed25519
(sign_outer_layer / sign_inner_layer). Therefore the exact bytes of the
identity string are inside the signature preimage. Consequences:
- Changing a node's canonical string from
@@alice.sep-hanzotodid:hanzo:alicechanges the signed bytes. A verifier expecting one form will fail signatures produced under the other. This is why a flag-day rename is unacceptable and why §7 defines anIdentityProtocolVersionnegotiation. - The canonicalization rule for the preimage is fixed by this HIP: the signed
sender/recipient MUST be the params-stripped, NFC, lowercase
did:hanzo:form (§3). Because §2 forbids uppercase and auto-correction, canonicalization is now deterministic and side-effect-free — there is exactly one byte sequence per identity, removing the legacy ambiguity where@@Alice…and@@alice…could both be constructed and then lower-cased. - PQ readiness. Outer/inner signatures stay ed25519 for wire compatibility in
this HIP. The
did:hanzo:<name>DID Document MAY additionally carry anMLDSAVerificationKey2025key (HIP-5, §8) so the same node identity can be verified post-quantum without another rename. PQ message signing is deferred to a follow-up but is unblocked by using the DID form now.
5. On-chain registration impact
Registration today goes through
hanzo-bin/hanzo-node/src/managers/identity_network_manager.rs:
- RPC
https://sepolia.base.org, contract0x425fb20ba3874e887336aaa7f3fab32d08135ba9, viaHanzoRegistry::get_identity_record(identity). - Resolution special-cases the suffix: it checks
node_base.ends_with(".sepolia-hanzo")to decide proxy handling.
Changes required:
- Registry key becomes the canonical params-stripped
did:hanzo:<name>. The existing Base Sepolia registry contract is retained during Phase 1–2 (no contract redeploy needed to start), but the key string it stores transitions from@@alice.sepolia-hanzotodid:hanzo:alice. A node registers its DID form; the suffix-sniffing (.sepolia-hanzo) branch is replaced by reading the?network=/?chain=hint (defaultsepoliaduring migration,36963after). - Converge onto
IHanzoDIDRegistry. The end-state registry is thedid:hanzo:registry on Hanzo L1 (chain36963), which storesdocumentHash,controller,version,activeper DID (§9). Node registration and DID registration become the same on-chain record: a node is a DID. This removes the separate Base Sepolia identity contract entirely at end-of-life (Phase 3). - Dual-read during migration. The resolver MUST, given a query, attempt
resolution of both the new
did:hanzo:<name>key and the legacy@@<name>.<suffix>key (deterministic mapping, §M1) so that a node which has re-registered under the DID form is still reachable by peers that only know its legacy name, and vice-versa.
6. UX / display form
To preserve readability lost by dropping the short @@alice look:
- UIs render
did:hanzo:aliceasalice(or@alicein social contexts);did:hanzo:alice/main/agent/researcherrenders asalice › researcher. alsoKnownAsin the DID Document MAY listdid:lux:alice,did:ai:alice(§8 cross-chain links). These are display/interop aliases, never the signed identity.- A node MAY publish a human label and avatar in its DID Document
service/ profile credential (theHanzoAgentCredentialof §10), so the short name is a resolvable attribute, not part of the cryptographic identity.
7. HanzoName type changes (normative, Rust)
In hanzo-libs/hanzo-messages/src/schemas/hanzo_name.rs:
- Add
pub network_hint: Option<String>andpub chain_id_hint: Option<u64>toHanzoName, populated fromparamsand excluded fromDisplay,Hash,PartialEq,Serialize, and from the signing preimage (they are resolution-only). node_namenow holds the canonicaldid:hanzo:<name>(params stripped). The fieldsprofile_name,subidentity_type,subidentity_nameare unchanged.validate_namegains adid:hanzo:<name>branch (the §2 regex) and stops auto-correcting:correct_node_name's@@/.hanzoinjection is gated behind a legacy-compat flag and is off by default in Phase 2+.- Add
IdentityProtocolVersion { Legacy = 1, Did = 2 }carried in the message envelope / handshake. A peer advertises which forms it can verify. TwoDidpeers sign/verify the DID form; if either side isLegacy-only, both fall back to the legacy string for that exchange (so signatures still match) until Phase 3. default_testnet_localhost()returnsHanzoName::new("did:hanzo:localhost/main?network=local").- Equality across forms: provide
HanzoName::same_identity(a, b)that compares the canonical DID form after applying the §M1 legacy→DID mapping, so routing/dedup treat a legacy name and its migrated DID as one identity.
8. DID Document
A did:hanzo:<name> resolves to a document conforming to W3C DID Core 1.0. The
identity is the identifier; the document is the key material and the endpoints it
currently points at, and it MAY be rotated without the identity changing.
{
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/suites/jws-2020/v1",
"https://hanzo.ai/ns/did/v1"
],
"id": "did:hanzo:dev",
"controller": "did:hanzo:hanzo",
"alsoKnownAs": [
"did:lux:dev",
"did:ai:dev"
],
"verificationMethod": [
{
"id": "did:hanzo:dev#key-1",
"type": "EcdsaSecp256k1VerificationKey2019",
"controller": "did:hanzo:dev",
"blockchainAccountId": "eip155:36963:0xAgentAddress"
},
{
"id": "did:hanzo:dev#key-2",
"type": "JsonWebKey2020",
"controller": "did:hanzo:dev",
"publicKeyJwk": {
"kty": "OKP",
"crv": "Ed25519",
"x": "base64url-encoded-public-key"
}
},
{
"id": "did:hanzo:dev#key-pq",
"type": "MLDSAVerificationKey2025",
"controller": "did:hanzo:dev",
"publicKeyMultibase": "z6Mk..."
}
],
"authentication": [
"did:hanzo:dev#key-1",
"did:hanzo:dev#key-2"
],
"assertionMethod": [
"did:hanzo:dev#key-1"
],
"keyAgreement": [
{
"id": "did:hanzo:dev#key-agree-1",
"type": "X25519KeyAgreementKey2020",
"controller": "did:hanzo:dev",
"publicKeyMultibase": "z6LS..."
}
],
"capabilityInvocation": [
"did:hanzo:dev#key-1"
],
"capabilityDelegation": [
"did:hanzo:dev#key-1"
],
"service": [
{
"id": "did:hanzo:dev#rpc",
"type": "AgentRPCService",
"serviceEndpoint": "https://bot.hanzo.ai/rpc/dev"
},
{
"id": "did:hanzo:dev#wallet",
"type": "SafeWallet",
"serviceEndpoint": "safe:eip155:36963:0xSafeAddress"
},
{
"id": "did:hanzo:dev#iam",
"type": "OIDCProvider",
"serviceEndpoint": "https://hanzo.id"
}
]
}
The #key-2 ed25519 method is the node's message-signing key from §4, and
#key-pq is the MLDSAVerificationKey2025 that makes the same identity
verifiable post-quantum without a second rename.
Each verification relationship answers a different question, and a verifier MUST check the one that matches what it is about to allow:
| Relationship | Purpose | Example |
|---|---|---|
authentication | Prove you are the DID subject | Node login to another node's API |
assertionMethod | Sign Verifiable Credentials | Agent attesting it completed a task |
keyAgreement | Establish encrypted channels | Node-to-node encrypted messaging |
capabilityInvocation | Invoke capabilities on resources | Agent executing a delegated action |
capabilityDelegation | Delegate capabilities to others | Organization granting agent authority |
A single key MAY appear in several relationships. Separate keys for
authentication and keyAgreement are RECOMMENDED, so compromising one does not
hand over the other.
9. Resolution
The registry record of §5 is authoritative: documentHash, controller,
version, active, keyed by the params-stripped did:hanzo:<name>. The document
itself lives off-chain, so a resolver MUST recompute SHA-256(document) and
compare it against the registry documentHash before returning it. A document
that does not match its on-chain hash MUST NOT be returned.
Resolution follows the W3C DID Resolution specification, and the versionId and
versionTime params of §2 are its query parameters:
| Method | Endpoint | Description |
|---|---|---|
| GET | /1.0/identifiers/{did} | Resolve to the current document |
| GET | /1.0/identifiers/{did}?versionId={n} | Resolve a specific version |
| GET | /1.0/identifiers/{did}?versionTime={iso8601} | Resolve as of a point in time |
| POST | /1.0/create | Register a DID |
| POST | /1.0/update | Publish a new document version |
| POST | /1.0/deactivate | Deactivate a DID |
The response carries the document plus resolution metadata: content type, created and updated timestamps, version, and the deactivated flag. Like every other resolution hint, these params are stripped from the signed and registry-key forms (§3).
The lifecycle is four operations:
- Create. The subject generates its keypair locally or in KMS (HIP-27),
constructs the document, computes
documentHash, callsIHanzoDIDRegistry.register(did, documentHash), and publishes the document. - Resolve. The verifier fetches the document, checks it against the registry hash, and takes the verification method for the relationship it needs.
- Update. The controller publishes a new document, computes the new hash, and
calls
update(did, newDocumentHash). The version counter increments and prior versions stay in chain history, which is what makesversionIdandversionTimeanswerable. Only the controller may update; control moves only viachangeController(). - Deactivate. The controller calls
deactivate(did); resolution then returnsdeactivated=true. Credentials issued before deactivation remain historically verifiable, but a verifier MUST NOT accept a credential issued after it.
Deactivation is irreversible. A reactivated DID would leave verifiers unable to tell which validity window a credential belongs to; a subject that needs an identity after deactivation creates a new one.
10. Verifiable Credentials
Attributes that are not identity — capabilities, org membership, evaluation results — are Verifiable Credentials about the DID rather than fields inside it. IAM (HIP-26) is the issuer for identity and membership claims:
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://hanzo.ai/ns/credentials/v1"
],
"type": ["VerifiableCredential", "HanzoAgentCredential"],
"issuer": "did:hanzo:iam",
"issuanceDate": "2026-02-23T00:00:00Z",
"expirationDate": "2027-02-23T00:00:00Z",
"credentialSubject": {
"id": "did:hanzo:dev",
"type": "AIAgent",
"name": "dev",
"organization": "hanzo",
"capabilities": [
"code-generation",
"code-review",
"mcp-tool-use"
],
"safetyEvaluation": {
"framework": "HIP-0210",
"result": "pass",
"evaluatedAt": "2026-02-20T12:00:00Z"
},
"computeTier": "tier-3",
"maxTokenBudget": 1000000
},
"credentialStatus": {
"id": "https://did.hanzo.ai/credentials/status/1",
"type": "StatusList2021Entry",
"statusPurpose": "revocation",
"statusListIndex": "42",
"statusListCredential": "https://did.hanzo.ai/credentials/status-list/1"
},
"proof": {
"type": "EcdsaSecp256k1Signature2019",
"created": "2026-02-23T00:00:00Z",
"verificationMethod": "did:hanzo:iam#key-1",
"proofPurpose": "assertionMethod",
"proofValue": "z58DAdFfa9SkqZMVPxAQpic7ndTn..."
}
}
The proof.verificationMethod MUST appear in the issuer's assertionMethod set;
a credential signed by a key the issuer never listed for assertion is invalid
however well-formed it looks.
| Credential Type | Issuer | Subject | Purpose |
|---|---|---|---|
HanzoAgentCredential | IAM | Agent DID | Attest agent identity and capabilities |
SafetyEvaluationCredential | Safety framework (HIP-210) | Agent DID | Attest safety evaluation results |
OrganizationMembershipCredential | IAM | User or agent DID | Attest org membership and role |
ComputeAuthorizationCredential | Cloud (HIP-106) | Agent DID | Authorize compute resource access |
ModelTrainingCredential | Training pipeline | Model DID | Attest training data provenance |
BiasAuditCredential | Bias framework (HIP-220) | Model DID | Attest bias evaluation results |
Revocation is StatusList2021: a bitstring where flipping bit n revokes the
credential holding statusListIndex n. A verifier downloads the whole list
rather than asking about one credential, so checking revocation does not tell the
issuer which credential is being verified.
Backward Compatibility & Migration
This is a signed, on-chain identifier; the migration is explicitly versioned and phased. No flag day.
M0 — Reserved-name and network-param remap (pre-flight)
Existing did:hanzo:<network> selectors (did:hanzo:mainnet, did:hanzo:sepolia,
did:hanzo:local:node1) are reinterpreted:
did:hanzo:mainnet→ reserved; if it was a network selector it becomesdid:hanzo:<node>?network=mainnet. Operators MUST update config to name the node.did:hanzo:local:node1→did:hanzo:node1?network=local.
M1 — Deterministic legacy ↔ DID mapping (the bridge)
A pure function maps any legacy name to its canonical DID form and back:
legacy: @@<name>.<suffix>[/<profile>[/<type>/<sub>]]
canon: did:hanzo:<name>[/<profile>[/<type>/<sub>]] with params: network=<from suffix>
suffix → network/chain:
.hanzo → mainnet (chain 36963)
.sep-hanzo → sepolia (Base Sepolia) ; current default
.sepolia-hanzo → sepolia (Base Sepolia)
.arb-sep-hanzo → arb-sepolia
<name> is copied verbatim iff it already satisfies §2 (lowercase, no dots).
Legacy names containing dots or uppercase are flagged for operator-assisted rename
(they are rare; the dominant case @@alice.sep-hanzo maps cleanly to
did:hanzo:alice?network=sepolia). This mapping is the basis for dual-read (§5.3)
and same_identity (§7).
Migration tooling
hanzod identity migrate— reads the node's current@@…identity, derives thedid:hanzo:form via §M1 and re-registers it on-chain. It writes one key.- Test vectors (canonical DID, signed preimage bytes) live in
hanzo-libs/hanzo-messages/tests/hanzo_name_tests.rs.
Rollout
- Land
HanzoNamechanges (DID branch, hints,same_identity,IdentityProtocolVersion) behind a feature flag; ship in a normal node release (Phase 1 behavior default). - Update the ~60 call sites that build/validate
HanzoName(identity manager, inbox/tool-router keys, payments managers, tests) to use canonicalized DID construction helpers; behavior stays Legacy-signed. - Ship resolver dual-read +
hanzod identity migrate+did.hanzo.ailookup table. - Flip default to Phase 2 once telemetry shows quorum of capable peers.
- Announce Phase 3 cutover height/date; freeze Base Sepolia contract; converge on
IHanzoDIDRegistry(chain36963).
Security Considerations
- Signature-preimage determinism. Because §2 forbids uppercase/dots and removes auto-correction, each identity has exactly one canonical byte sequence; this closes the legacy ambiguity where multiple inputs canonicalized to the same lower-cased name, which is dangerous for a signed field.
- No silent identity coercion. Invalid identities are rejected, never
auto-completed into a valid-looking one (legacy
correct_node_namecould turn a typo into a different, valid node). - Network-confusion resistance. Stripping
?network/?chainfrom the signed and registry forms means a signature or registration cannot be replayed as if it were for a different chain by swapping a suffix — the identity is chain-agnostic by construction. - Migration window risk. Dual-read and
Legacyfallback are the only periods where two strings denote one node;same_identity(§M1 mapping) MUST be used for all auth/routing decisions to prevent a peer from being treated as two identities (or two peers as one). - PQ path. The DID form lets a node attach an
MLDSAVerificationKey2025key (HIP-5) to the same identity, so the eventual move to PQ message signing needs no further rename.
References
- HIP-5 — Post-Quantum Security (
ML-DSA-65,MLDSAVerificationKey2025) - HIP-24 — Hanzo Sovereign L1 (chain
36963) - HIP-26 — IAM (credential issuer); HIP-27 — KMS (key custody)
- W3C DID Core 1.0; W3C Verifiable Credentials Data Model 2.0
hanzo-libs/hanzo-messages/src/schemas/hanzo_name.rs(currentHanzoName)hanzo-bin/hanzo-node/src/managers/identity_network_manager.rs(Base Sepolia registration)hanzo-libs/hanzo-did/(existing W3C DID parser to converge on)