@agenticprimitives/identity-directory 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.
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,48 @@
1
+ # @agenticprimitives/identity-directory
2
+
3
+ An **evidence-backed read model** over canonical agents and their facets — the
4
+ read side of the identity stack ([ADR-0015](../../docs/architecture/decisions/0015-identity-directory-is-an-evidence-backed-read-model.md);
5
+ [spec 223](../../specs/223-identity-directory.md)).
6
+
7
+ It answers *"which agent(s) does this name / credential / OIDC subject resolve to,
8
+ and on what evidence?"* — keyed on `CanonicalAgentId` (CAIP-10), with provenance +
9
+ assurance on every association. It is **not an authority**: it accelerates
10
+ discovery; the consumer re-reads on-chain for custody decisions.
11
+
12
+ ## Ports + adapters
13
+
14
+ The core declares the ports; the implementations live in
15
+ [`@agenticprimitives/identity-directory-adapters`](../identity-directory-adapters):
16
+
17
+ ```
18
+ NamingPort forward/reverse name ↔ agent (wraps agent-naming)
19
+ OnChainReadPort resolveAgent / credentialsOf — readContract only, NEVER getLogs
20
+ IndexerPort agentsByCredential / agentsByOidcSubject — the "indexed registry" home
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ ```ts
26
+ import { createDirectory } from '@agenticprimitives/identity-directory';
27
+ import { makeAdapters } from '@agenticprimitives/identity-directory-adapters'; // (separate pkg)
28
+
29
+ const dir = createDirectory(makeAdapters({ /* viem client, naming, indexer */ }));
30
+ const r = await dir.resolveByCredential(principal); // 0 | 1 | many agents, each with evidence
31
+ ```
32
+
33
+ ## Doctrine (load-bearing)
34
+
35
+ - **No fallback** ([ADR-0013](../../docs/architecture/decisions/0013-no-silent-fallbacks.md)):
36
+ one mechanism per query; a `null`/empty port result is terminal.
37
+ - **No `eth_getLogs`** ([ADR-0012](../../docs/architecture/decisions/0012-no-eth-getlogs-in-product-read-paths.md)):
38
+ indexed reads go through `IndexerPort`.
39
+ - **Indexer proposes, on-chain confirms:** `resolveByCredential` /
40
+ `resolveByOidcSubject` upgrade to `onchain-confirmed` only when the credential is
41
+ in the agent's *current* on-chain set — a revoked credential is dropped.
42
+ - **Not an authority** ([ADR-0015](../../docs/architecture/decisions/0015-identity-directory-is-an-evidence-backed-read-model.md)):
43
+ resolution output never grants custody or value.
44
+
45
+ ## Convergence
46
+
47
+ `Resolution.agents.length` is the convergence cardinality the broker (spec 224)
48
+ branches on: **0** → bootstrap, **1** → the common case, **many** → disambiguate.
@@ -0,0 +1,5 @@
1
+ import type { Assurance } from '@agenticprimitives/types';
2
+ import { type DirectoryPorts, type DirectoryOpts, type IdentityDirectory } from './types';
3
+ export declare function createDirectory(ports: DirectoryPorts, opts?: DirectoryOpts): IdentityDirectory;
4
+ export type { Assurance };
5
+ //# sourceMappingURL=directory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directory.d.ts","sourceRoot":"","sources":["../src/directory.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAyC,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACjG,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EAOvB,MAAM,SAAS,CAAC;AAMjB,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,EAAE,IAAI,GAAE,aAAkB,GAAG,iBAAiB,CA8FlG;AAGD,YAAY,EAAE,SAAS,EAAE,CAAC"}
@@ -0,0 +1,112 @@
1
+ // createDirectory — composes the ports into the query API (spec 223 §6/§7).
2
+ //
3
+ // Discipline (load-bearing):
4
+ // - No fallback (ADR-0013): each query uses ONE mechanism; a null/empty result
5
+ // is terminal — never an escalation to a second port.
6
+ // - Authoritative-port designation (audit P2-4): for session-relevant queries
7
+ // (credential / oidc) the IndexerPort only PROPOSES candidates; the
8
+ // OnChainReadPort is authoritative — a candidate is only `onchain-confirmed`
9
+ // if the credential is in the agent's CURRENT on-chain set. A credential
10
+ // revoked on-chain (spec 221) is dropped, never riding a stale index edge
11
+ // (audit P1-3).
12
+ // - Not an authority (ADR-0015): the directory accelerates discovery; it never
13
+ // grants anything. The broker re-reads on-chain for custody decisions.
14
+ import { buildEvent, nowIso } from '@agenticprimitives/audit';
15
+ import { CLASS, PREDICATE } from '@agenticprimitives/ontology';
16
+ import { maxAssurance, } from './types';
17
+ function oidcPrincipal(iss, sub) {
18
+ return { kind: 'oidc', id: `${iss}#${sub}`, assurance: 'asserted' };
19
+ }
20
+ export function createDirectory(ports, opts = {}) {
21
+ const auditSink = opts.auditSink;
22
+ async function emit(action, subjectId, predicate, resultCount) {
23
+ if (!auditSink)
24
+ return;
25
+ try {
26
+ await auditSink.write(buildEvent({
27
+ action,
28
+ outcome: 'success',
29
+ actor: { type: 'system', id: 'identity-directory' },
30
+ subject: { type: CLASS.Agent, id: subjectId },
31
+ context: { predicate, resultCount },
32
+ }));
33
+ }
34
+ catch {
35
+ /* audit is fail-soft; never block a read on the sink */
36
+ }
37
+ }
38
+ /**
39
+ * For each candidate link, CONFIRM the principal is in the agent's current
40
+ * on-chain credential set. Confirmed → `onchain-confirmed` (with both the
41
+ * indexer evidence and the on-chain confirmation evidence). Unconfirmed
42
+ * (revoked / stale / never-real) → dropped.
43
+ */
44
+ async function confirmCandidates(links, principal) {
45
+ const out = [];
46
+ for (const link of links) {
47
+ // Authoritative membership CHECK (isCustodian/isTrustee), not enumeration.
48
+ if (!(await ports.onChain.confirmsCredential(link.agent, principal)))
49
+ continue; // not currently a custodian → drop
50
+ const evidence = [
51
+ {
52
+ source: 'indexer',
53
+ assurance: link.assurance,
54
+ observedAt: link.observedAt ?? nowIso(),
55
+ ref: link.ref,
56
+ blockNumber: link.blockNumber,
57
+ },
58
+ {
59
+ source: 'onchain',
60
+ assurance: 'onchain-confirmed',
61
+ observedAt: nowIso(),
62
+ ref: `credentialsOf:${link.agent}`,
63
+ },
64
+ ];
65
+ out.push({ id: link.agent, evidence, assurance: maxAssurance(evidence.map((e) => e.assurance)) });
66
+ }
67
+ return out;
68
+ }
69
+ return {
70
+ async resolveByName(name) {
71
+ const id = await ports.naming.forward(name);
72
+ // null is THE answer (no such name) — never escalate to another port (ADR-0013).
73
+ if (!id) {
74
+ await emit('identity-directory.resolveByName', name, PREDICATE.resolvesTo, 0);
75
+ return { agents: [] };
76
+ }
77
+ const evidence = [
78
+ { source: 'naming', assurance: 'onchain-read', observedAt: nowIso(), ref: name },
79
+ ];
80
+ await emit('identity-directory.resolveByName', name, PREDICATE.resolvesTo, 1);
81
+ return { agents: [{ id, evidence, assurance: 'onchain-read' }] };
82
+ },
83
+ async resolveByCredential(principal) {
84
+ const links = await ports.indexer.agentsByCredential(principal);
85
+ const agents = await confirmCandidates(links, principal);
86
+ await emit('identity-directory.resolveByCredential', `${principal.kind}:${principal.id}`, PREDICATE.controls, agents.length);
87
+ return { agents };
88
+ },
89
+ async resolveByOidcSubject(iss, sub) {
90
+ const links = await ports.indexer.agentsByOidcSubject(iss, sub);
91
+ const agents = await confirmCandidates(links, oidcPrincipal(iss, sub));
92
+ await emit('identity-directory.resolveByOidcSubject', `${iss}#${sub}`, PREDICATE.controls, agents.length);
93
+ return { agents };
94
+ },
95
+ async agent(id) {
96
+ if (!(await ports.onChain.exists(id)))
97
+ return null;
98
+ // Composition (NOT fallback): existence + reverse name are different facets
99
+ // of the SAME agent, each from its declared port. (Credential enumeration is
100
+ // not an on-chain primitive — confirmation is per-credential via the membership
101
+ // check; a full credential list, if ever needed, is an indexer concern.)
102
+ const name = await ports.naming.reverse(id);
103
+ const evidence = [
104
+ { source: 'onchain', assurance: 'onchain-read', observedAt: nowIso(), ref: `exists:${id}` },
105
+ ];
106
+ if (name)
107
+ evidence.push({ source: 'naming', assurance: 'onchain-read', observedAt: nowIso(), ref: name });
108
+ return { id, facets: { name: name ?? undefined }, evidence };
109
+ },
110
+ };
111
+ }
112
+ //# sourceMappingURL=directory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directory.js","sourceRoot":"","sources":["../src/directory.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,EAAE;AACF,6BAA6B;AAC7B,iFAAiF;AACjF,0DAA0D;AAC1D,gFAAgF;AAChF,wEAAwE;AACxE,iFAAiF;AACjF,6EAA6E;AAC7E,8EAA8E;AAC9E,oBAAoB;AACpB,iFAAiF;AACjF,2EAA2E;AAE3E,OAAO,EAAE,UAAU,EAAE,MAAM,EAAkB,MAAM,0BAA0B,CAAC;AAC9E,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE/D,OAAO,EASL,YAAY,GACb,MAAM,SAAS,CAAC;AAEjB,SAAS,aAAa,CAAC,GAAW,EAAE,GAAW;IAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,GAAG,IAAI,GAAG,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAqB,EAAE,OAAsB,EAAE;IAC7E,MAAM,SAAS,GAA0B,IAAI,CAAC,SAAS,CAAC;IAExD,KAAK,UAAU,IAAI,CAAC,MAAc,EAAE,SAAiB,EAAE,SAAiB,EAAE,WAAmB;QAC3F,IAAI,CAAC,SAAS;YAAE,OAAO;QACvB,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,KAAK,CACnB,UAAU,CAAC;gBACT,MAAM;gBACN,OAAO,EAAE,SAAS;gBAClB,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,oBAAoB,EAAE;gBACnD,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE;gBAC7C,OAAO,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE;aACpC,CAAC,CACH,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,wDAAwD;QAC1D,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,KAAK,UAAU,iBAAiB,CAAC,KAAqB,EAAE,SAA8B;QACpF,MAAM,GAAG,GAAwB,EAAE,CAAC;QACpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,2EAA2E;YAC3E,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;gBAAE,SAAS,CAAC,mCAAmC;YACnH,MAAM,QAAQ,GAAe;gBAC3B;oBACE,MAAM,EAAE,SAAS;oBACjB,SAAS,EAAE,IAAI,CAAC,SAAS;oBACzB,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,MAAM,EAAE;oBACvC,GAAG,EAAE,IAAI,CAAC,GAAG;oBACb,WAAW,EAAE,IAAI,CAAC,WAAW;iBAC9B;gBACD;oBACE,MAAM,EAAE,SAAS;oBACjB,SAAS,EAAE,mBAAmB;oBAC9B,UAAU,EAAE,MAAM,EAAE;oBACpB,GAAG,EAAE,iBAAiB,IAAI,CAAC,KAAK,EAAE;iBACnC;aACF,CAAC;YACF,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC;QACpG,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,OAAO;QACL,KAAK,CAAC,aAAa,CAAC,IAAY;YAC9B,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC5C,iFAAiF;YACjF,IAAI,CAAC,EAAE,EAAE,CAAC;gBACR,MAAM,IAAI,CAAC,kCAAkC,EAAE,IAAI,EAAE,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;gBAC9E,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;YACxB,CAAC;YACD,MAAM,QAAQ,GAAe;gBAC3B,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE;aACjF,CAAC;YACF,MAAM,IAAI,CAAC,kCAAkC,EAAE,IAAI,EAAE,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;YAC9E,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC;QACnE,CAAC;QAED,KAAK,CAAC,mBAAmB,CAAC,SAA8B;YACtD,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;YAChE,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;YACzD,MAAM,IAAI,CAAC,wCAAwC,EAAE,GAAG,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,EAAE,EAAE,EAAE,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YAC7H,OAAO,EAAE,MAAM,EAAE,CAAC;QACpB,CAAC;QAED,KAAK,CAAC,oBAAoB,CAAC,GAAW,EAAE,GAAW;YACjD,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAChE,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YACvE,MAAM,IAAI,CAAC,yCAAyC,EAAE,GAAG,GAAG,IAAI,GAAG,EAAE,EAAE,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YAC1G,OAAO,EAAE,MAAM,EAAE,CAAC;QACpB,CAAC;QAED,KAAK,CAAC,KAAK,CAAC,EAAoB;YAC9B,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;YACnD,4EAA4E;YAC5E,6EAA6E;YAC7E,gFAAgF;YAChF,yEAAyE;YACzE,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAC5C,MAAM,QAAQ,GAAe;gBAC3B,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE;aAC5F,CAAC;YACF,IAAI,IAAI;gBAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1G,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,IAAI,SAAS,EAAE,EAAE,QAAQ,EAAE,CAAC;QAC/D,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ export type { EvidenceSource, Evidence, AgentWithEvidence, Resolution, AgentView, EvidenceLink, OnChainReadPort, NamingPort, IndexerPort, DirectoryPorts, DirectoryOpts, IdentityDirectory, } from './types';
2
+ export { ASSURANCE_ORDER, compareAssurance, maxAssurance } from './types';
3
+ export { createDirectory } from './directory';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,YAAY,EACV,cAAc,EACd,QAAQ,EACR,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,YAAY,EACZ,eAAe,EACf,UAAU,EACV,WAAW,EACX,cAAc,EACd,aAAa,EACb,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE1E,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ // @agenticprimitives/identity-directory — evidence-backed read model (spec 223).
2
+ //
3
+ // Public surface: the domain model, the ports (implemented in
4
+ // identity-directory-adapters), the assurance ordering, and createDirectory.
5
+ //
6
+ // See:
7
+ // - capability.manifest.json — boundary (types + audit + ontology only)
8
+ // - ../../specs/223-identity-directory.md — the contract
9
+ // - ../../docs/architecture/decisions/0015-identity-directory-is-an-evidence-backed-read-model.md
10
+ export { ASSURANCE_ORDER, compareAssurance, maxAssurance } from './types';
11
+ export { createDirectory } from './directory';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,EAAE;AACF,8DAA8D;AAC9D,6EAA6E;AAC7E,EAAE;AACF,OAAO;AACP,0EAA0E;AAC1E,2DAA2D;AAC3D,oGAAoG;AAiBpG,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE1E,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,101 @@
1
+ import type { CanonicalAgentId, Assurance, CredentialPrincipal } from '@agenticprimitives/types';
2
+ export type { CanonicalAgentId, Assurance, CredentialPrincipal };
3
+ /** Which source asserted an association. */
4
+ export type EvidenceSource = 'naming' | 'onchain' | 'indexer';
5
+ /**
6
+ * Provenance for an asserted association (spec 223 §4). `blockNumber` is present
7
+ * and load-bearing for `onchain-read` evidence so a consumer can enforce a
8
+ * max-staleness bound (audit P1-3) — a credential revoked on-chain must not ride
9
+ * a stale read.
10
+ */
11
+ export interface Evidence {
12
+ source: EvidenceSource;
13
+ observedAt: string;
14
+ assurance: Assurance;
15
+ /** Opaque source reference (name, tx, index key, "credentialsOf:<id>", …). */
16
+ ref: string;
17
+ /** Required for `onchain-read`/`onchain-confirmed`; the block the read reflects. */
18
+ blockNumber?: bigint;
19
+ }
20
+ /** An agent in a Resolution, with its provenance + the effective assurance. */
21
+ export interface AgentWithEvidence {
22
+ id: CanonicalAgentId;
23
+ evidence: Evidence[];
24
+ /** Highest assurance across `evidence`. */
25
+ assurance: Assurance;
26
+ }
27
+ /** The result of a resolution query. Convergence cardinality is `agents.length`. */
28
+ export interface Resolution {
29
+ agents: AgentWithEvidence[];
30
+ }
31
+ /** A view of one agent + provenance (from `agent(id)`). */
32
+ export interface AgentView {
33
+ id: CanonicalAgentId;
34
+ facets: {
35
+ name?: string;
36
+ };
37
+ evidence: Evidence[];
38
+ }
39
+ /**
40
+ * A candidate link from a (non-authoritative) IndexerPort. The directory
41
+ * CONFIRMS it against the authoritative on-chain read before treating it as
42
+ * `onchain-confirmed` (audit P2-4 / P1-3).
43
+ */
44
+ export interface EvidenceLink {
45
+ agent: CanonicalAgentId;
46
+ assurance: Assurance;
47
+ ref: string;
48
+ observedAt?: string;
49
+ blockNumber?: bigint;
50
+ }
51
+ /**
52
+ * Authoritative on-chain reads. `readContract` only — NEVER `eth_getLogs`.
53
+ *
54
+ * Shaped around what the custody/account contracts actually expose: membership
55
+ * CHECKS (`isCustodian`/`isTrustee`), not credential enumeration. So confirmation
56
+ * is `confirmsCredential` (a check), not a `credentialsOf` (a list) — the on-chain
57
+ * surface has no "list this agent's credentials" getter.
58
+ */
59
+ export interface OnChainReadPort {
60
+ /** Does this agent exist as a deployed account on this chain? */
61
+ exists(id: CanonicalAgentId): Promise<boolean>;
62
+ /** Authoritative: is `principal` CURRENTLY a control credential of `id`? */
63
+ confirmsCredential(id: CanonicalAgentId, principal: CredentialPrincipal): Promise<boolean>;
64
+ }
65
+ /** Wraps `agent-naming`. The adapter lifts `Address → CanonicalAgentId` by binding a chainId. */
66
+ export interface NamingPort {
67
+ forward(name: string): Promise<CanonicalAgentId | null>;
68
+ reverse(id: CanonicalAgentId): Promise<string | null>;
69
+ }
70
+ /** The home for "indexed registry" reads (HCS-2 *indexed* → here, never a log walk). */
71
+ export interface IndexerPort {
72
+ agentsByCredential(principal: CredentialPrincipal): Promise<EvidenceLink[]>;
73
+ agentsByOidcSubject(iss: string, sub: string): Promise<EvidenceLink[]>;
74
+ }
75
+ export interface DirectoryPorts {
76
+ naming: NamingPort;
77
+ onChain: OnChainReadPort;
78
+ indexer: IndexerPort;
79
+ }
80
+ import type { AuditSink } from '@agenticprimitives/audit';
81
+ export interface DirectoryOpts {
82
+ /** Injectable clock (ms). Defaults to Date.now. */
83
+ now?: () => number;
84
+ /** Optional sink — a `identity-directory.resolve` event is emitted per query. */
85
+ auditSink?: AuditSink;
86
+ }
87
+ /** The directory query API (spec 223 §6). */
88
+ export interface IdentityDirectory {
89
+ resolveByName(name: string): Promise<Resolution>;
90
+ /** Session-relevant: indexer proposes, on-chain CONFIRMS (audit P2-4/P1-3). */
91
+ resolveByCredential(principal: CredentialPrincipal): Promise<Resolution>;
92
+ resolveByOidcSubject(iss: string, sub: string): Promise<Resolution>;
93
+ agent(id: CanonicalAgentId): Promise<AgentView | null>;
94
+ }
95
+ /** Ordered low→high. Consumers (e.g. the broker session-issuance floor) compare on this. */
96
+ export declare const ASSURANCE_ORDER: readonly Assurance[];
97
+ /** Negative / 0 / positive like a comparator. */
98
+ export declare function compareAssurance(a: Assurance, b: Assurance): number;
99
+ /** The highest assurance across a non-empty list (defaults to 'unverified' if empty). */
100
+ export declare function maxAssurance(values: Assurance[]): Assurance;
101
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEjG,YAAY,EAAE,gBAAgB,EAAE,SAAS,EAAE,mBAAmB,EAAE,CAAC;AAEjE,4CAA4C;AAC5C,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,cAAc,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,SAAS,CAAC;IACrB,8EAA8E;IAC9E,GAAG,EAAE,MAAM,CAAC;IACZ,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,+EAA+E;AAC/E,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,gBAAgB,CAAC;IACrB,QAAQ,EAAE,QAAQ,EAAE,CAAC;IACrB,2CAA2C;IAC3C,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,oFAAoF;AACpF,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,iBAAiB,EAAE,CAAC;CAC7B;AAED,2DAA2D;AAC3D,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,gBAAgB,CAAC;IACrB,MAAM,EAAE;QACN,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,QAAQ,EAAE,QAAQ,EAAE,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,gBAAgB,CAAC;IACxB,SAAS,EAAE,SAAS,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AASD;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,MAAM,CAAC,EAAE,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,EAAE,gBAAgB,EAAE,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5F;AAED,iGAAiG;AACjG,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACxD,OAAO,CAAC,EAAE,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACvD;AAED,wFAAwF;AACxF,MAAM,WAAW,WAAW;IAC1B,kBAAkB,CAAC,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAC5E,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;CACxE;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,eAAe,CAAC;IACzB,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D,MAAM,WAAW,aAAa;IAC5B,mDAAmD;IACnD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,iFAAiF;IACjF,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,6CAA6C;AAC7C,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACjD,+EAA+E;IAC/E,mBAAmB,CAAC,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACzE,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACpE,KAAK,CAAC,EAAE,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;CACxD;AAID,4FAA4F;AAC5F,eAAO,MAAM,eAAe,EAAE,SAAS,SAAS,EAKtC,CAAC;AAEX,iDAAiD;AACjD,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,GAAG,MAAM,CAEnE;AAED,yFAAyF;AACzF,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,CAI3D"}
package/dist/types.js ADDED
@@ -0,0 +1,27 @@
1
+ // Domain model + ports for the identity directory (spec 223).
2
+ //
3
+ // The directory is a READ MODEL keyed on CanonicalAgentId. Every association it
4
+ // returns carries Evidence (provenance + assurance). It is NOT an authority
5
+ // (ADR-0015), uses no eth_getLogs (ADR-0012), and never falls back between
6
+ // mechanisms (ADR-0013).
7
+ // ─── Assurance ordering ───────────────────────────────────────────────
8
+ /** Ordered low→high. Consumers (e.g. the broker session-issuance floor) compare on this. */
9
+ export const ASSURANCE_ORDER = [
10
+ 'unverified',
11
+ 'asserted',
12
+ 'onchain-read',
13
+ 'onchain-confirmed',
14
+ ];
15
+ /** Negative / 0 / positive like a comparator. */
16
+ export function compareAssurance(a, b) {
17
+ return ASSURANCE_ORDER.indexOf(a) - ASSURANCE_ORDER.indexOf(b);
18
+ }
19
+ /** The highest assurance across a non-empty list (defaults to 'unverified' if empty). */
20
+ export function maxAssurance(values) {
21
+ let best = 'unverified';
22
+ for (const v of values)
23
+ if (compareAssurance(v, best) > 0)
24
+ best = v;
25
+ return best;
26
+ }
27
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,EAAE;AACF,gFAAgF;AAChF,4EAA4E;AAC5E,2EAA2E;AAC3E,yBAAyB;AAsHzB,yEAAyE;AAEzE,4FAA4F;AAC5F,MAAM,CAAC,MAAM,eAAe,GAAyB;IACnD,YAAY;IACZ,UAAU;IACV,cAAc;IACd,mBAAmB;CACX,CAAC;AAEX,iDAAiD;AACjD,MAAM,UAAU,gBAAgB,CAAC,CAAY,EAAE,CAAY;IACzD,OAAO,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,YAAY,CAAC,MAAmB;IAC9C,IAAI,IAAI,GAAc,YAAY,CAAC;IACnC,KAAK,MAAM,CAAC,IAAI,MAAM;QAAE,IAAI,gBAAgB,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC;YAAE,IAAI,GAAG,CAAC,CAAC;IACpE,OAAO,IAAI,CAAC;AACd,CAAC"}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@agenticprimitives/identity-directory",
3
+ "version": "0.1.0-alpha.2",
4
+ "description": "Evidence-backed read model over canonical agents and their facets (ADR-0015 / spec 223). Declares the ports (NamingPort / OnChainReadPort / IndexerPort) + the query API with provenance + assurance. Not an authority; no eth_getLogs; no fallback. Adapters live in identity-directory-adapters.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/agentictrustlabs/agenticprimitives.git",
9
+ "directory": "packages/identity-directory"
10
+ },
11
+ "homepage": "https://github.com/agentictrustlabs/agenticprimitives/tree/master/packages/identity-directory",
12
+ "bugs": {
13
+ "url": "https://github.com/agentictrustlabs/agenticprimitives/issues"
14
+ },
15
+ "type": "module",
16
+ "main": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js"
22
+ }
23
+ },
24
+ "files": [
25
+ "LICENSE",
26
+ "dist",
27
+ "spec.md",
28
+ "README.md"
29
+ ],
30
+ "scripts": {
31
+ "build": "tsc -p tsconfig.build.json",
32
+ "typecheck": "tsc -p tsconfig.json --noEmit",
33
+ "test": "vitest run",
34
+ "test:unit": "vitest run test/unit",
35
+ "test:integration": "vitest run test/integration --passWithNoTests",
36
+ "test:watch": "vitest",
37
+ "clean": "rm -rf dist"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "peerDependencies": {
43
+ "@agenticprimitives/audit": "workspace:*",
44
+ "@agenticprimitives/ontology": "workspace:*",
45
+ "@agenticprimitives/types": "workspace:*"
46
+ },
47
+ "devDependencies": {
48
+ "vitest": "^2.1.0"
49
+ },
50
+ "keywords": [
51
+ "identity",
52
+ "directory",
53
+ "read-model",
54
+ "knowledge-graph",
55
+ "agentic"
56
+ ]
57
+ }
package/spec.md ADDED
@@ -0,0 +1,16 @@
1
+ # Spec — @agenticprimitives/identity-directory
2
+
3
+ The authoritative spec is [`specs/223-identity-directory.md`](../../specs/223-identity-directory.md)
4
+ (domain model, ports, query API + convergence, doctrine compliance, phased plan).
5
+
6
+ Decision record: [ADR-0015 — identity-directory is an evidence-backed read model](../../docs/architecture/decisions/0015-identity-directory-is-an-evidence-backed-read-model.md).
7
+ Conforms to the ontology in [spec 225](../../specs/225-ontology.md); keys on the
8
+ CAIP-10 `CanonicalAgentId` of [ADR-0016](../../docs/architecture/decisions/0016-canonical-agent-id-is-the-sso-subject.md).
9
+
10
+ This file is the per-package pointer required by `check:package-docs`; do not
11
+ duplicate the spec here — edit spec 223.
12
+
13
+ > Reconciliation note: spec 223 §5 sketched an `OidcPort`; OIDC *verification*
14
+ > lives in `connect-auth` (ADR-0017), so the directory core ships three ports
15
+ > (Naming / OnChainRead / Indexer) and `resolveByOidcSubject(iss, sub)` takes an
16
+ > already-verified subject. The broker wires connect-auth → directory.