@agenticprimitives/agent-naming 0.1.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/AUDIT.md +86 -0
  2. package/CLAUDE.md +180 -0
  3. package/LICENSE +21 -0
  4. package/README.md +158 -0
  5. package/dist/abis.d.ts +1532 -0
  6. package/dist/abis.d.ts.map +1 -0
  7. package/dist/abis.js +417 -0
  8. package/dist/abis.js.map +1 -0
  9. package/dist/client.d.ts +102 -0
  10. package/dist/client.d.ts.map +1 -0
  11. package/dist/client.js +299 -0
  12. package/dist/client.js.map +1 -0
  13. package/dist/constants.d.ts +8 -0
  14. package/dist/constants.d.ts.map +1 -0
  15. package/dist/constants.js +7 -0
  16. package/dist/constants.js.map +1 -0
  17. package/dist/custody.d.ts +133 -0
  18. package/dist/custody.d.ts.map +1 -0
  19. package/dist/custody.js +214 -0
  20. package/dist/custody.js.map +1 -0
  21. package/dist/errors.d.ts +15 -0
  22. package/dist/errors.d.ts.map +1 -0
  23. package/dist/errors.js +30 -0
  24. package/dist/errors.js.map +1 -0
  25. package/dist/index.d.ts +10 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +22 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/namehash.d.ts +31 -0
  30. package/dist/namehash.d.ts.map +1 -0
  31. package/dist/namehash.js +46 -0
  32. package/dist/namehash.js.map +1 -0
  33. package/dist/normalize.d.ts +28 -0
  34. package/dist/normalize.d.ts.map +1 -0
  35. package/dist/normalize.js +68 -0
  36. package/dist/normalize.js.map +1 -0
  37. package/dist/records.d.ts +88 -0
  38. package/dist/records.d.ts.map +1 -0
  39. package/dist/records.js +193 -0
  40. package/dist/records.js.map +1 -0
  41. package/dist/types.d.ts +117 -0
  42. package/dist/types.d.ts.map +1 -0
  43. package/dist/types.js +2 -0
  44. package/dist/types.js.map +1 -0
  45. package/docs/api.md +110 -0
  46. package/docs/concepts.md +159 -0
  47. package/docs/migration.md +93 -0
  48. package/docs/security.md +127 -0
  49. package/docs/troubleshooting.md +116 -0
  50. package/examples/basic.ts +31 -0
  51. package/examples/custody-rotation.ts +44 -0
  52. package/examples/records.ts +41 -0
  53. package/package.json +71 -0
  54. package/spec.md +14 -0
package/AUDIT.md ADDED
@@ -0,0 +1,86 @@
1
+ # @agenticprimitives/agent-naming — package audit
2
+
3
+ **Status:** Phase 1 (SDK skeleton + spec + pure helpers).
4
+ **Last refreshed:** 2026-05-23.
5
+ **Owner:** [security-auditor](../../docs/agents/security-auditor.md) +
6
+ [technical-architect-auditor](../../docs/agents/technical-architect-auditor.md).
7
+ **System audit cross-ref:** see
8
+ [`docs/architecture/product-readiness-audit.md`](../../docs/architecture/product-readiness-audit.md)
9
+ and the [evidence checklist](../../docs/audits/evidence-checklist.md).
10
+
11
+ This audit is Phase-1 scope only. Findings against contract behavior,
12
+ on-chain authority paths, and demo integration land in Phase 3+.
13
+
14
+ ## Charter (what's audit-relevant in this package)
15
+
16
+ - Pure helpers (`normalizeAgentName`, `labelhash`, `namehash`): MUST
17
+ be deterministic + match the reference ENS algorithm + reject
18
+ malformed input.
19
+ - Record schema (`AgentNameRecords` + `records` subpath): MUST
20
+ refuse unknown keys on encode (fail-loud write) AND drop unknown
21
+ keys on decode (fail-closed read).
22
+ - `AgentNamingClient` (Phase 1 skeleton): MUST throw clearly when
23
+ invoked before contract wiring, so a Phase-1 consumer can't
24
+ silently get a no-op call.
25
+ - Vocabulary firewall against `delegation`, `account-custody`, `mcp-runtime`,
26
+ `tool-policy`, `key-custody`, `audit`, and MCP transport.
27
+
28
+ ## Findings (Phase 1)
29
+
30
+ | ID | Severity | Finding | Evidence | Status |
31
+ | --- | --- | --- | --- | --- |
32
+ | **AN-1** | P2 | Lowercase normalization uses `String.prototype.toLowerCase`, which has Turkish-locale-specific edge cases for `İ → i` mapping. Phase 1 labels are ASCII-only so the practical risk is zero, but the locale-sensitivity is worth either documenting OR replacing with a locale-explicit map. | `src/normalize.ts:21` | open — Phase 1 acceptable (ASCII-only labels in `LABEL_RE`). Revisit when Phase 2 expands to Punycode/IDN. |
33
+ | **AN-2** | P2 | The package depends on `@agenticprimitives/agent-account` for ERC-1271 verification, but the Phase 1 client doesn't yet exercise it (writes throw). The dependency is declared early to lock the boundary; verify in Phase 2 that the import remains narrow (`AgentAccountClient` only, no transitive widening). | `package.json` peerDependencies; `capability.manifest.json:imports` | open — track in Phase 2 review. |
34
+ | **AN-3** | P3 | Multi-root TLD support exists in the contract design (per smart-agent port) but the package surface restricts to `.agent`. A future TLD addition (e.g. `.org-agent`) requires both the contract `initializeRoot` AND a surface change here. Make sure the surface change is intentional + spec'd, not snuck in. | `src/constants.ts:8` | open — design-time control; no current risk. |
35
+
36
+ ## Phase-1 security invariants (verified by tests)
37
+
38
+ - ✅ `normalize` rejects empty / leading-hyphen / trailing-hyphen /
39
+ non-ASCII / oversize labels. Throws `InvalidNameError`. Covered in
40
+ `test/normalize.test.ts`.
41
+ - ✅ `normalize` is idempotent: `normalize(normalize(x)) === normalize(x)`.
42
+ - ✅ `namehash('')` = `ZERO_NODE` (`0x00…00`) per the ENS sentinel
43
+ convention.
44
+ - ✅ `namehash` matches the ENS reference algorithm under an
45
+ in-band independent reimplementation (`test/namehash.test.ts`
46
+ golden-vector table).
47
+ - ✅ `namehash` rejects malformed input by delegating to `normalize`.
48
+ - ✅ `decodeRecords` silently drops unknown predicate keys
49
+ (fail-closed read).
50
+ - ✅ `encodeRecordValue` rejects unknown predicate keys (fail-loud
51
+ write).
52
+ - ✅ `decodeRecords` drops invalid `agent-kind` values that don't
53
+ match the closed enum.
54
+ - ✅ `AgentNamingClient` throws `NS Phase 2 — wire to …` from every
55
+ read method (so silent no-op calls are impossible in Phase 1).
56
+ - ✅ `AgentNamingClient` throws `NS Phase 4 — wire to …` from every
57
+ write method.
58
+
59
+ ## Audit events this package emits (Phase 2+)
60
+
61
+ | Action | When | Severity in audit context |
62
+ | --- | --- | --- |
63
+ | `agent-naming.resolve.{accept,reject}` | demo-mcp uses name in audit context | telemetry |
64
+ | `agent-naming.register` | on subname registration | forensic-critical |
65
+ | `agent-naming.records.update` | on resolver-record writes | forensic-critical |
66
+ | `agent-naming.primary-name.update` | on reverse-record writes | forensic-critical |
67
+ | `agent-naming.subregistry.update` | on subregistry-delegation changes | forensic-critical |
68
+
69
+ These are spec-declared in `specs/215-agent-naming.md` § 9. The
70
+ client doesn't yet take an `auditSink`; Phase 2 will add the optional
71
+ `opts.auditSink` and emit through it.
72
+
73
+ ## Out-of-scope (won't audit here)
74
+
75
+ - Contract source — lives in `packages/contracts/src/naming/` (Phase 3).
76
+ - On-chain authority paths (subregistry delegation, owner rotation
77
+ via custody) — Phase 3 contract Forge tests + Phase 4 client
78
+ integration tests.
79
+ - Demo wiring — Phase 5; per-demo audit lives in the demo's
80
+ integration evidence rows, not in this package.
81
+
82
+ ## Change log
83
+
84
+ | Date | Wave | What changed |
85
+ | --- | --- | --- |
86
+ | 2026-05-23 | NS Phase 1 | Initial audit. AN-1/2/3 open; security invariants verified by unit tests. |
package/CLAUDE.md ADDED
@@ -0,0 +1,180 @@
1
+ # @agenticprimitives/agent-naming — Claude guide
2
+
3
+ ## Naming facet, not identity
4
+ Names are a **facet registration** pointing AT the canonical Smart Agent ([ADR-0010](../../docs/architecture/decisions/0010-smart-agent-canonical-identifier.md)). Forced-unique labels: [spec 220 § 5](../../specs/220-agent-identity-bootstrap.md). `addr` + `nativeId` MUST reference the same SA.
5
+
6
+ ## What this package owns
7
+
8
+ - The `.agent` TLD constant (`AGENT_TLD`).
9
+ - Name normalization (`normalizeAgentName`) — NFC + lowercase + label
10
+ validation. Rejects empty / hyphen-prefixed / non-ASCII labels in v0.
11
+ - `labelhash` + `namehash` — ENS-compatible keccak256 hashes for
12
+ identifier nodes.
13
+ - Record schemas (`AgentNameRecords`) and predicate constants
14
+ (subpath `/records`).
15
+ - `AgentNamingClient` — read API (resolve / reverse-resolve / get
16
+ records) + write API skeleton (Phase 1 writes throw `NS Phase 2`).
17
+ - Pure encoded call builders for name-owner rotation that compose
18
+ into custody-policy ceremonies (subpath `/custody`).
19
+
20
+ ## What this package does NOT own
21
+
22
+ - Smart-account internals → [`agent-account`](../agent-account)
23
+ (we consume `AgentAccountClient` for ERC-1271 verification +
24
+ counterfactual address derivation).
25
+ - Custody policy, scheduling, quorum → [`custody`](../account-custody).
26
+ We expose call builders only — never import.
27
+ - Delegation / caveat / mint → [`delegation`](../delegation).
28
+ - Passkey ceremonies → [`connect-auth`](../connect-auth).
29
+ - MCP / A2A transport → demo apps + future `a2a-runtime`.
30
+ - Contract source — that lives in `packages/contracts/src/naming/`
31
+ (Phase 3+); this package ships ABIs + client only.
32
+
33
+ ## Vocabulary
34
+
35
+ **Owns:** `AgentName`, `Label`, `Node` (namehash), `NameRecord`,
36
+ `AgentNamingClient`, `Subregistry`, `Resolver`, `PrimaryName`,
37
+ `AGENT_TLD`.
38
+ **Disambiguation:**
39
+
40
+ - **"resolver"** here = on-chain ENS-v2 resolver. Distinct from
41
+ any other package.
42
+ - **"registry"** here = `AgentNameRegistry` contract. Distinct from
43
+ the factory deploy-registry in `agent-account`.
44
+ - **"primary name"** = reverse-record on a Smart Agent address.
45
+ Distinct from `connect-auth.sessionId` and `delegation.SessionRow`.
46
+ **Does not use:** `Delegation`, `Caveat`, `Steward`, `Custodian`,
47
+ `Trustee`, `KMS`, `RiskTier`, `JtiStore`, MCP / A2A transport.
48
+ See `capability.manifest.json:forbiddenTerms`.
49
+
50
+ ## Read these first (in order)
51
+
52
+ 1. `capability.manifest.json` — boundary.
53
+ 2. `src/index.ts` — public API.
54
+ 3. `../../specs/215-agent-naming.md` — the spec.
55
+ 4. `src/namehash.ts` + `src/normalize.ts` — the pure substrate.
56
+ 5. `src/client.ts` — the client skeleton.
57
+
58
+ ## Stable public exports
59
+
60
+ **Constants + helpers:** `AGENT_TLD`, `normalizeAgentName`,
61
+ `labelhash`, `namehash`.
62
+ **Types:** `AgentNameRecords`, `RegisterSubnameInput`,
63
+ `SetPrimaryNameInput`, `SetAgentRecordsInput`,
64
+ `SetSubregistryInput`.
65
+ **Client:** `AgentNamingClient`.
66
+ **Errors:** `InvalidNameError`, `NameNotFoundError`,
67
+ `UnauthorizedNameOwnerError`.
68
+ **Subpaths:**
69
+
70
+ - `/records` — predicate constants + encoders/decoders.
71
+ - `/custody` — pure encoded call builders for custody-gated name
72
+ rotation (no `@agenticprimitives/account-custody` import).
73
+
74
+ ## Allowed imports
75
+
76
+ `@agenticprimitives/types`, `@agenticprimitives/connect-auth`
77
+ (`Signer` type only), `@agenticprimitives/agent-account`
78
+ (`AgentAccountClient`), `viem`, `@noble/hashes` (transitive via viem).
79
+
80
+ ## Forbidden imports
81
+
82
+ - `apps/*`
83
+ - `@agenticprimitives/delegation`, `mcp-runtime`, `tool-policy`,
84
+ `key-custody`, `audit`, `account-custody`
85
+ - `@modelcontextprotocol/sdk`
86
+
87
+ ## Drift triggers — STOP and route
88
+
89
+ - "Add `getLogs` / `queryFilter` / `watchContractEvent` for a product read" —
90
+ **STOP.** [ADR-0012](../../docs/architecture/decisions/0012-no-eth-getlogs-in-product-read-paths.md):
91
+ use `readContract`, on-chain stored fields, or an indexer. There is NO log
92
+ walker left here — `reverseResolve` is a single `reverseResolveString` call.
93
+ - "Add a `try fast path / catch → slower different path` fallback" — **STOP.**
94
+ [ADR-0013](../../docs/architecture/decisions/0013-no-silent-fallbacks.md): one
95
+ mechanism per read. Empty/null is the answer; don't escalate to a log walk or
96
+ second contract.
97
+ - "Add a delegation-token mint or verify path" — **STOP.** Belongs
98
+ in [`delegation`](../delegation).
99
+ - "Add a CustodyAction to gate name rotation" — **STOP.** Belongs
100
+ in [`custody`](../account-custody). Compose via `agent-naming/custody`
101
+ call builders here without importing.
102
+ - "Add a passkey ceremony" — **STOP.** Belongs in [`connect-auth`](../connect-auth).
103
+ - "Reach for an MCP transport" — **STOP.** Out of scope.
104
+ - "Auto-resolve name via a system-wide hook in the worker" — **STOP.**
105
+ Demo-app integration only; the package itself is transport-agnostic.
106
+
107
+ ## Decision Tree
108
+
109
+ - Adding a new record field? Start in `src/types.ts` and
110
+ `src/records.ts`; update tests and `docs/api.md`.
111
+ - Adding resolver reads? Start in `src/client.ts`.
112
+ - Adding name rotation calls? Start in `src/custody.ts`; do not import
113
+ `@agenticprimitives/account-custody`.
114
+ - Adding passkey behavior? Stop. Route to `connect-auth`.
115
+ - Adding delegation or caveat behavior? Stop. Route to `delegation`.
116
+ - Adding MCP/A2A transport? Stop. Route to app/runtime packages.
117
+
118
+ ## Before you write code
119
+
120
+ - [ ] Is the change in the resolver-records / namehash / normalize /
121
+ client surface?
122
+ - [ ] Did I avoid importing from `delegation`, `account-custody`,
123
+ `mcp-runtime`, `tool-policy`, `key-custody`, `audit`?
124
+ - [ ] Did I keep `normalize` deterministic (NFC + lowercase + label
125
+ validation)?
126
+ - [ ] Did I write golden-vector tests for any namehash / labelhash
127
+ change?
128
+ - [ ] Did I update `specs/215-agent-naming.md` if the public API or
129
+ records schema changed?
130
+
131
+ ## Security invariants (DO NOT BREAK)
132
+
133
+ - **Name normalization is deterministic.** Two strings that normalize
134
+ identically MUST produce identical namehashes.
135
+ - **No raw passkey material in records.** Only `credentialIdDigest`
136
+ (a hash) is ever stored in `passkey-credential-digest`.
137
+ - **Reverse resolution requires round-trip.** `reverseResolve(agent)`
138
+ returns a name only when `resolveName(name) === agent`.
139
+ - **Fail-closed on unknown predicates.** Unknown record keys decode
140
+ to `undefined`; encoders refuse unknown keys.
141
+ - **Write methods require the name owner.** Verified via the owner
142
+ Smart Agent's ERC-1271 `isValidSignature` (Phase 2+).
143
+
144
+ ## Validate the package
145
+
146
+ ```bash
147
+ pnpm --filter @agenticprimitives/agent-naming typecheck
148
+ pnpm --filter @agenticprimitives/agent-naming test
149
+ pnpm check:forbidden-terms
150
+ ```
151
+
152
+ ## Common task routing
153
+
154
+ - New record predicate → `src/records.ts` (encoder/decoder + constant)
155
+ - update `AgentNameRecords` type in `src/types.ts` + add a test.
156
+ - New client method → `src/client.ts` (Phase 1 stub with
157
+ `throw new Error('NS Phase 2')`; wire in Phase 2).
158
+ - New custody-rotation call builder → `src/custody.ts` (subpath
159
+ `/custody`; pure encoded call — no `@agenticprimitives/account-custody`
160
+ import).
161
+
162
+ ## Capabilities this package participates in
163
+
164
+ - **Agent identity + service discovery** — the naming graph IS the
165
+ on-chain authority for "which Smart Agent answers to which
166
+ human-readable name." Demos use it to resolve service endpoints
167
+ (`a2a-endpoint`, `mcp-endpoint`) without hardcoded URLs.
168
+ - **Audit / forensics trail** — emits (via consumer-supplied
169
+ `AuditSink`): `agent-naming.{resolve,register,records.update,
170
+ primary-name.update,subregistry.update}`.
171
+ - Index of cross-cutting capabilities:
172
+ [`docs/architecture/cross-cutting-capabilities.md`](../../docs/architecture/cross-cutting-capabilities.md).
173
+
174
+ ## Documentation map
175
+
176
+ [`README.md`](README.md) · [`docs/concepts.md`](docs/concepts.md) · [`docs/api.md`](docs/api.md) · [`docs/security.md`](docs/security.md) · [`docs/troubleshooting.md`](docs/troubleshooting.md) · [`docs/migration.md`](docs/migration.md)
177
+
178
+ ## Generated files (ignore)
179
+
180
+ `dist/`, `node_modules/`, `coverage/`, `*.tsbuildinfo`.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Agentic Trust Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,158 @@
1
+ # @agenticprimitives/agent-naming
2
+
3
+ Human-readable `.agent` **naming facets** for Smart Agents.
4
+
5
+ The canonical identifier is the Smart Agent address
6
+ (`@agenticprimitives/agent-account`). This package registers names and records
7
+ that point **at** that address — it does not create or own identity.
8
+
9
+ > **Layer:** Discover — a naming **facet** (not canonical identity — that is `agent-account`).
10
+ > **Canonical key:** the Smart Agent address the name resolves to.
11
+
12
+ Use this package to resolve names like `alice.agent`, `acme.agent`, and
13
+ `treasury.acme.agent` to Smart Agent addresses, read typed service-discovery
14
+ records, and build encoded calls for name-management transactions.
15
+
16
+ ## Use This When
17
+
18
+ - You need forward resolution: `alice.agent -> 0x...`.
19
+ - You need reverse resolution from a Smart Agent address to its primary name.
20
+ - You need typed records such as `displayName`, `a2aEndpoint`, `mcpEndpoint`,
21
+ `nativeId`, or `metadataUri`.
22
+ - You need pure call builders for name registration, resolver updates, primary
23
+ name updates, or owner rotation.
24
+
25
+ ## Do Not Use This For
26
+
27
+ - Passkey ceremonies or auth flows. Use `@agenticprimitives/connect-auth`.
28
+ - Smart-account deployment or UserOps. Use `@agenticprimitives/agent-account`.
29
+ - Account safety policy and approval scheduling. Use `@agenticprimitives/account-custody`.
30
+ - Permission-token minting or attenuation. Use `@agenticprimitives/delegation`.
31
+ - MCP/A2A transport wiring. Use demo apps or runtime packages.
32
+
33
+ ## Install
34
+
35
+ This package is workspace-internal and not yet published.
36
+
37
+ ```bash
38
+ pnpm add @agenticprimitives/agent-naming
39
+ ```
40
+
41
+ ## 60-Second Quickstart
42
+
43
+ ```ts
44
+ import {
45
+ AgentNamingClient,
46
+ labelhash,
47
+ namehash,
48
+ normalizeAgentName,
49
+ } from '@agenticprimitives/agent-naming';
50
+
51
+ normalizeAgentName(' ALICE.AGENT '); // "alice.agent"
52
+ labelhash('alice'); // 0x...
53
+ namehash('treasury.acme.agent'); // 0x...
54
+
55
+ const naming = new AgentNamingClient({
56
+ rpcUrl: 'https://base-sepolia.example/rpc',
57
+ chainId: 84532,
58
+ registry: '0x0000000000000000000000000000000000000001',
59
+ universalResolver: '0x0000000000000000000000000000000000000002',
60
+ });
61
+
62
+ const address = await naming.resolveName('alice.agent');
63
+ const primaryName = await naming.reverseResolve('0x0000000000000000000000000000000000000003');
64
+ const records = await naming.getRecords('treasury.acme.agent');
65
+ ```
66
+
67
+ ## Main Concepts
68
+
69
+ - **Canonical SA**: the ERC-4337 address every name must reference (`addr`,
70
+ `nativeId`). Owned by `agent-account`, not this package.
71
+ - **AgentName**: a normalized dotted name under `.agent` (a facet label).
72
+ - **Label**: one segment of a name, such as `treasury`.
73
+ - **Node**: ENS-compatible `namehash(name)`.
74
+ - **Registry**: owns name records: owner, resolver, parent, subregistry.
75
+ - **Resolver**: stores typed records for a node.
76
+ - **Primary name**: reverse record for a Smart Agent address.
77
+ - **Records**: typed data such as endpoints, display name, CAIP-10 `nativeId`,
78
+ and public-safe passkey credential digest.
79
+
80
+ See [`docs/concepts.md`](docs/concepts.md).
81
+
82
+ ## Common Recipes
83
+
84
+ ```ts
85
+ import {
86
+ decodeRecords,
87
+ encodeRecords,
88
+ PREDICATE_ID,
89
+ } from '@agenticprimitives/agent-naming/records';
90
+
91
+ const encoded = encodeRecords({
92
+ addr: '0x0000000000000000000000000000000000000003',
93
+ agentKind: 'service', // a treasury is a service agent; 'treasury' is a profile subtype
94
+ displayName: 'Acme Treasury',
95
+ nativeId: 'eip155:84532:0x0000000000000000000000000000000000000003',
96
+ });
97
+
98
+ const decoded = decodeRecords({
99
+ strings: { [PREDICATE_ID.displayName]: 'Acme Treasury' },
100
+ addresses: { [PREDICATE_ID.addr]: '0x0000000000000000000000000000000000000003' },
101
+ bytes32s: {},
102
+ });
103
+ ```
104
+
105
+ More examples:
106
+
107
+ - [`examples/basic.ts`](examples/basic.ts)
108
+ - [`examples/records.ts`](examples/records.ts)
109
+ - [`examples/custody-rotation.ts`](examples/custody-rotation.ts)
110
+
111
+ ## Runtime Support
112
+
113
+ Pure helpers and record encoders work in browser, Node, and Workers. The client
114
+ uses `viem` public and wallet clients and requires an RPC URL for chain reads or
115
+ transaction submission.
116
+
117
+ ## Subpath Exports
118
+
119
+ - `@agenticprimitives/agent-naming` — public helpers, client, ABIs, and types.
120
+ - `@agenticprimitives/agent-naming/records` — predicate ids and typed
121
+ record encode/decode helpers.
122
+ - `@agenticprimitives/agent-naming/custody` — pure encoded call builders for
123
+ name-management transactions.
124
+
125
+ ## Security Invariants
126
+
127
+ - Product reads use `readContract`; no `eth_getLogs` in hot paths
128
+ ([ADR-0012](../../docs/architecture/decisions/0012-no-eth-getlogs-in-product-read-paths.md)).
129
+ `reverseResolve` string reconstruction is transitional log debt — do not copy.
130
+ - Name normalization is deterministic.
131
+ - Reverse resolution must round-trip before it is trusted.
132
+ - Unknown predicates are ignored on decode and rejected by typed encoders.
133
+ - Raw passkey credential IDs are never stored.
134
+ - Endpoint records are discovery hints, not proof of endpoint control.
135
+
136
+ See [`docs/security.md`](docs/security.md) and [`AUDIT.md`](AUDIT.md).
137
+
138
+ ## Documentation Map
139
+
140
+ - [`docs/concepts.md`](docs/concepts.md) — naming model and vocabulary.
141
+ - [`docs/api.md`](docs/api.md) — human-readable public API guide.
142
+ - [`docs/security.md`](docs/security.md) — security posture and invariants.
143
+ - [`docs/troubleshooting.md`](docs/troubleshooting.md) — common errors.
144
+ - [`docs/migration.md`](docs/migration.md) — version and migration notes.
145
+ - [`CLAUDE.md`](CLAUDE.md) — agent routing and drift prevention.
146
+ - [`spec.md`](spec.md) — canonical spec pointer.
147
+
148
+ ## Validation
149
+
150
+ ```bash
151
+ pnpm check:agent-naming
152
+ pnpm check:public-exports
153
+ pnpm check:forbidden-terms
154
+ ```
155
+
156
+ ## License
157
+
158
+ UNLICENSED.