@enbox/agent 0.2.1 → 0.3.0

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 (139) hide show
  1. package/dist/browser.mjs +9 -9
  2. package/dist/browser.mjs.map +4 -4
  3. package/dist/esm/agent-did-resolver-cache.js.map +1 -1
  4. package/dist/esm/anonymous-dwn-api.js +1 -1
  5. package/dist/esm/bearer-identity.js +1 -1
  6. package/dist/esm/connect.js +3 -3
  7. package/dist/esm/connect.js.map +1 -1
  8. package/dist/esm/did-api.js +3 -3
  9. package/dist/esm/did-api.js.map +1 -1
  10. package/dist/esm/dwn-api.js +150 -10
  11. package/dist/esm/dwn-api.js.map +1 -1
  12. package/dist/esm/dwn-discovery-file.js +244 -0
  13. package/dist/esm/dwn-discovery-file.js.map +1 -0
  14. package/dist/esm/dwn-discovery-payload.js +253 -0
  15. package/dist/esm/dwn-discovery-payload.js.map +1 -0
  16. package/dist/esm/dwn-encryption.js.map +1 -1
  17. package/dist/esm/dwn-key-delivery.js +6 -5
  18. package/dist/esm/dwn-key-delivery.js.map +1 -1
  19. package/dist/esm/dwn-protocol-cache.js +6 -7
  20. package/dist/esm/dwn-protocol-cache.js.map +1 -1
  21. package/dist/esm/dwn-record-upgrade.js.map +1 -1
  22. package/dist/esm/{web5-user-agent.js → enbox-user-agent.js} +18 -9
  23. package/dist/esm/enbox-user-agent.js.map +1 -0
  24. package/dist/esm/identity-api.js +4 -5
  25. package/dist/esm/identity-api.js.map +1 -1
  26. package/dist/esm/index.js +4 -1
  27. package/dist/esm/index.js.map +1 -1
  28. package/dist/esm/local-dwn.js +197 -0
  29. package/dist/esm/local-dwn.js.map +1 -0
  30. package/dist/esm/local-key-manager.js +2 -2
  31. package/dist/esm/local-key-manager.js.map +1 -1
  32. package/dist/esm/oidc.js +11 -11
  33. package/dist/esm/oidc.js.map +1 -1
  34. package/dist/esm/permissions-api.js.map +1 -1
  35. package/dist/esm/store-data.js.map +1 -1
  36. package/dist/esm/sync-api.js +2 -2
  37. package/dist/esm/sync-api.js.map +1 -1
  38. package/dist/esm/sync-engine-level.js +3 -4
  39. package/dist/esm/sync-engine-level.js.map +1 -1
  40. package/dist/esm/test-harness.js +5 -4
  41. package/dist/esm/test-harness.js.map +1 -1
  42. package/dist/esm/utils-internal.js +2 -2
  43. package/dist/types/agent-did-resolver-cache.d.ts +7 -7
  44. package/dist/types/agent-did-resolver-cache.d.ts.map +1 -1
  45. package/dist/types/anonymous-dwn-api.d.ts +3 -3
  46. package/dist/types/anonymous-dwn-api.d.ts.map +1 -1
  47. package/dist/types/bearer-identity.d.ts +1 -1
  48. package/dist/types/connect.d.ts +8 -8
  49. package/dist/types/connect.d.ts.map +1 -1
  50. package/dist/types/did-api.d.ts +12 -11
  51. package/dist/types/did-api.d.ts.map +1 -1
  52. package/dist/types/dwn-api.d.ts +58 -11
  53. package/dist/types/dwn-api.d.ts.map +1 -1
  54. package/dist/types/dwn-discovery-file.d.ts +122 -0
  55. package/dist/types/dwn-discovery-file.d.ts.map +1 -0
  56. package/dist/types/dwn-discovery-payload.d.ts +105 -0
  57. package/dist/types/dwn-discovery-payload.d.ts.map +1 -0
  58. package/dist/types/dwn-encryption.d.ts +8 -8
  59. package/dist/types/dwn-encryption.d.ts.map +1 -1
  60. package/dist/types/dwn-key-delivery.d.ts +9 -7
  61. package/dist/types/dwn-key-delivery.d.ts.map +1 -1
  62. package/dist/types/dwn-protocol-cache.d.ts +6 -5
  63. package/dist/types/dwn-protocol-cache.d.ts.map +1 -1
  64. package/dist/types/dwn-record-upgrade.d.ts +2 -2
  65. package/dist/types/dwn-record-upgrade.d.ts.map +1 -1
  66. package/dist/types/{web5-user-agent.d.ts → enbox-user-agent.d.ts} +21 -13
  67. package/dist/types/enbox-user-agent.d.ts.map +1 -0
  68. package/dist/types/identity-api.d.ts +10 -10
  69. package/dist/types/identity-api.d.ts.map +1 -1
  70. package/dist/types/index.d.ts +4 -1
  71. package/dist/types/index.d.ts.map +1 -1
  72. package/dist/types/local-dwn.d.ts +121 -0
  73. package/dist/types/local-dwn.d.ts.map +1 -0
  74. package/dist/types/local-key-manager.d.ts +9 -9
  75. package/dist/types/local-key-manager.d.ts.map +1 -1
  76. package/dist/types/oidc.d.ts +23 -19
  77. package/dist/types/oidc.d.ts.map +1 -1
  78. package/dist/types/permissions-api.d.ts +4 -4
  79. package/dist/types/permissions-api.d.ts.map +1 -1
  80. package/dist/types/store-data.d.ts +3 -3
  81. package/dist/types/store-data.d.ts.map +1 -1
  82. package/dist/types/store-did.d.ts +2 -2
  83. package/dist/types/store-did.d.ts.map +1 -1
  84. package/dist/types/store-identity.d.ts +2 -2
  85. package/dist/types/store-identity.d.ts.map +1 -1
  86. package/dist/types/store-key.d.ts +2 -2
  87. package/dist/types/store-key.d.ts.map +1 -1
  88. package/dist/types/sync-api.d.ts +9 -9
  89. package/dist/types/sync-api.d.ts.map +1 -1
  90. package/dist/types/sync-engine-level.d.ts +9 -9
  91. package/dist/types/sync-engine-level.d.ts.map +1 -1
  92. package/dist/types/sync-messages.d.ts +5 -5
  93. package/dist/types/sync-messages.d.ts.map +1 -1
  94. package/dist/types/test-harness.d.ts +4 -4
  95. package/dist/types/test-harness.d.ts.map +1 -1
  96. package/dist/types/types/agent.d.ts +24 -19
  97. package/dist/types/types/agent.d.ts.map +1 -1
  98. package/dist/types/types/identity.d.ts +1 -1
  99. package/dist/types/types/key-manager.d.ts +2 -2
  100. package/dist/types/types/key-manager.d.ts.map +1 -1
  101. package/dist/types/types/sync.d.ts +2 -2
  102. package/dist/types/types/sync.d.ts.map +1 -1
  103. package/dist/types/utils-internal.d.ts +4 -4
  104. package/dist/types/utils-internal.d.ts.map +1 -1
  105. package/package.json +6 -6
  106. package/src/agent-did-resolver-cache.ts +8 -8
  107. package/src/anonymous-dwn-api.ts +4 -4
  108. package/src/bearer-identity.ts +1 -1
  109. package/src/connect.ts +12 -12
  110. package/src/did-api.ts +13 -11
  111. package/src/dwn-api.ts +196 -16
  112. package/src/dwn-discovery-file.ts +305 -0
  113. package/src/dwn-discovery-payload.ts +308 -0
  114. package/src/dwn-encryption.ts +8 -8
  115. package/src/dwn-key-delivery.ts +11 -8
  116. package/src/dwn-protocol-cache.ts +9 -8
  117. package/src/dwn-record-upgrade.ts +2 -2
  118. package/src/{web5-user-agent.ts → enbox-user-agent.ts} +39 -19
  119. package/src/identity-api.ts +12 -13
  120. package/src/index.ts +4 -1
  121. package/src/local-dwn.ts +207 -0
  122. package/src/local-key-manager.ts +10 -10
  123. package/src/oidc.ts +40 -30
  124. package/src/permissions-api.ts +5 -5
  125. package/src/store-data.ts +7 -7
  126. package/src/store-did.ts +2 -2
  127. package/src/store-identity.ts +2 -2
  128. package/src/store-key.ts +2 -2
  129. package/src/sync-api.ts +10 -10
  130. package/src/sync-engine-level.ts +13 -14
  131. package/src/sync-messages.ts +5 -5
  132. package/src/test-harness.ts +11 -10
  133. package/src/types/agent.ts +31 -20
  134. package/src/types/identity.ts +1 -1
  135. package/src/types/key-manager.ts +2 -2
  136. package/src/types/sync.ts +2 -2
  137. package/src/utils-internal.ts +4 -4
  138. package/dist/esm/web5-user-agent.js.map +0 -1
  139. package/dist/types/web5-user-agent.d.ts.map +0 -1
@@ -6,7 +6,7 @@ import type {
6
6
  RecordsReadReply,
7
7
  } from '@enbox/dwn-sdk-js';
8
8
 
9
- import type { Web5PlatformAgent } from './types/agent.js';
9
+ import type { EnboxPlatformAgent } from './types/agent.js';
10
10
  import type {
11
11
  DwnMessage,
12
12
  DwnMessageReply,
@@ -22,7 +22,6 @@ import {
22
22
  Records,
23
23
  } from '@enbox/dwn-sdk-js';
24
24
 
25
- import { getDwnServiceEndpointUrls } from './utils.js';
26
25
  import { KeyDeliveryProtocolDefinition } from './store-data-protocols.js';
27
26
  import { buildEncryptionInput, encryptAndComputeCid, getEncryptionKeyDeriver, getKeyDecrypter, ivLength } from './dwn-encryption.js';
28
27
  import { DwnInterface, dwnMessageConstructors } from './types/dwn.js';
@@ -66,7 +65,7 @@ type ProcessRequestFn = <T extends DwnInterface>(
66
65
  * @param installedCache - Cache for installation status
67
66
  */
68
67
  export async function ensureKeyDeliveryProtocol(
69
- agent: Web5PlatformAgent,
68
+ agent: EnboxPlatformAgent,
70
69
  tenantDid: string,
71
70
  processRequest: ProcessRequestFn,
72
71
  getProtocolDefinition: (tenantDid: string, protocolUri: string) => Promise<any>,
@@ -121,7 +120,7 @@ export async function ensureKeyDeliveryProtocol(
121
120
  * @returns The recordId of the written contextKey record
122
121
  */
123
122
  export async function writeContextKeyRecord(
124
- agent: Web5PlatformAgent,
123
+ agent: EnboxPlatformAgent,
125
124
  params: WriteContextKeyParams,
126
125
  processRequest: ProcessRequestFn,
127
126
  ensureProtocol: (tenantDid: string) => Promise<void>,
@@ -219,17 +218,19 @@ export async function writeContextKeyRecord(
219
218
  * @param contextKeyMessage - The context key message to send
220
219
  * @param getDwnMessage - Function to read a full message from local DWN
221
220
  * @param sendDwnRpcRequest - Function to send a DWN RPC request
221
+ * @param getDwnEndpointUrlsForTarget - Function to resolve DWN endpoint URLs (with local discovery)
222
222
  */
223
223
  export async function eagerSendContextKeyRecord(
224
- agent: Web5PlatformAgent,
224
+ agent: EnboxPlatformAgent,
225
225
  tenantDid: string,
226
226
  contextKeyMessage: DwnMessage[DwnInterface.RecordsWrite],
227
227
  getDwnMessage: (params: { author: string; messageType: DwnInterface; messageCid: string }) => Promise<{ message: any; data?: Blob }>,
228
228
  sendDwnRpcRequest: (params: { targetDid: string; dwnEndpointUrls: string[]; message: any; data?: Blob }) => Promise<any>,
229
+ getDwnEndpointUrlsForTarget: (targetDid: string) => Promise<string[]>,
229
230
  ): Promise<void> {
230
231
  let dwnEndpointUrls: string[];
231
232
  try {
232
- dwnEndpointUrls = await getDwnServiceEndpointUrls(tenantDid, agent.did);
233
+ dwnEndpointUrls = await getDwnEndpointUrlsForTarget(tenantDid);
233
234
  } catch {
234
235
  // DID resolution or endpoint lookup failed — not fatal, sync will handle it.
235
236
  return;
@@ -266,14 +267,16 @@ export async function eagerSendContextKeyRecord(
266
267
  * @param processRequest - The agent's processRequest method (bound)
267
268
  * @param getSigner - Function to get a signer for a DID
268
269
  * @param sendDwnRpcRequest - Function to send a DWN RPC request
270
+ * @param getDwnEndpointUrlsForTarget - Function to resolve DWN endpoint URLs (with local discovery)
269
271
  * @returns The decrypted `DerivedPrivateJwk`, or `undefined` if no matching record found
270
272
  */
271
273
  export async function fetchContextKeyRecord(
272
- agent: Web5PlatformAgent,
274
+ agent: EnboxPlatformAgent,
273
275
  params: FetchContextKeyParams,
274
276
  processRequest: ProcessRequestFn,
275
277
  getSigner: (author: string) => Promise<any>,
276
278
  sendDwnRpcRequest: (params: { targetDid: string; dwnEndpointUrls: string[]; message: any; data?: Blob }) => Promise<any>,
279
+ getDwnEndpointUrlsForTarget: (targetDid: string) => Promise<string[]>,
277
280
  ): Promise<DerivedPrivateJwk | undefined> {
278
281
  const { ownerDid, requesterDid, sourceProtocol, sourceContextId } = params;
279
282
  const protocolUri = KeyDeliveryProtocolDefinition.protocol;
@@ -323,7 +326,7 @@ export async function fetchContextKeyRecord(
323
326
  } else {
324
327
  // Remote query: participant queries the context owner's DWN
325
328
  const signer = await getSigner(requesterDid);
326
- const dwnEndpointUrls = await getDwnServiceEndpointUrls(ownerDid, agent.did);
329
+ const dwnEndpointUrls = await getDwnEndpointUrlsForTarget(ownerDid);
327
330
 
328
331
  const recordsQuery = await dwnMessageConstructors[DwnInterface.RecordsQuery].create({
329
332
  signer,
@@ -7,7 +7,6 @@
7
7
  * @module
8
8
  */
9
9
 
10
- import type { DidUrlDereferencer } from '@enbox/dids';
11
10
  import type { PublicKeyJwk } from '@enbox/crypto';
12
11
  import type { TtlCache } from '@enbox/common';
13
12
  import type {
@@ -26,13 +25,15 @@ import type {
26
25
 
27
26
  import { KeyDerivationScheme } from '@enbox/dwn-sdk-js';
28
27
 
29
- import { getDwnServiceEndpointUrls } from './utils.js';
30
28
  import { DwnInterface as DwnInterfaceEnum, dwnMessageConstructors } from './types/dwn.js';
31
29
 
32
30
  // ---------------------------------------------------------------------------
33
31
  // Dependency signatures — keep the extracted code free of `this` references.
34
32
  // ---------------------------------------------------------------------------
35
33
 
34
+ /** Callback to resolve DWN endpoint URLs for a target DID (with local discovery). */
35
+ type GetDwnEndpointUrlsFn = (targetDid: string) => Promise<string[]>;
36
+
36
37
  /** Callback to obtain a DWN signer for a given DID. */
37
38
  type GetSignerFn = (author: string) => Promise<DwnSigner>;
38
39
 
@@ -106,7 +107,7 @@ export async function getProtocolDefinition(
106
107
  *
107
108
  * @param targetDid - The remote DWN owner
108
109
  * @param protocolUri - The protocol URI to look up
109
- * @param didDereferencer - A DID URL dereferencer for resolving service endpoints
110
+ * @param getDwnEndpointUrls - Callback to resolve DWN endpoint URLs (with local discovery)
110
111
  * @param sendDwnRpcRequest - Callback to send the RPC query
111
112
  * @param cache - The shared protocol definition cache
112
113
  * @returns The protocol definition
@@ -115,7 +116,7 @@ export async function getProtocolDefinition(
115
116
  export async function fetchRemoteProtocolDefinition(
116
117
  targetDid: string,
117
118
  protocolUri: string,
118
- didDereferencer: DidUrlDereferencer,
119
+ getDwnEndpointUrls: GetDwnEndpointUrlsFn,
119
120
  sendDwnRpcRequest: SendDwnRpcRequestFn,
120
121
  cache: TtlCache<string, ProtocolDefinition>,
121
122
  ): Promise<ProtocolDefinition> {
@@ -131,7 +132,7 @@ export async function fetchRemoteProtocolDefinition(
131
132
 
132
133
  const reply = await sendDwnRpcRequest({
133
134
  targetDid,
134
- dwnEndpointUrls : await getDwnServiceEndpointUrls(targetDid, didDereferencer),
135
+ dwnEndpointUrls : await getDwnEndpointUrls(targetDid),
135
136
  message : protocolsQuery.message,
136
137
  }) as ProtocolsQueryReply;
137
138
 
@@ -158,7 +159,7 @@ export async function fetchRemoteProtocolDefinition(
158
159
  * @param protocolUri - The protocol URI to search
159
160
  * @param rootContextId - The root context ID
160
161
  * @param requesterDid - The DID of the requester (used for signing the query)
161
- * @param didDereferencer - A DID URL dereferencer for resolving service endpoints
162
+ * @param getDwnEndpointUrls - Callback to resolve DWN endpoint URLs (with local discovery)
162
163
  * @param getSigner - Callback to obtain the signer for `requesterDid`
163
164
  * @param sendDwnRpcRequest - Callback to send the RPC query
164
165
  * @returns The rootKeyId and derivedPublicKey, or `undefined` if no
@@ -169,7 +170,7 @@ export async function extractDerivedPublicKey(
169
170
  protocolUri: string,
170
171
  rootContextId: string,
171
172
  requesterDid: string,
172
- didDereferencer: DidUrlDereferencer,
173
+ getDwnEndpointUrls: GetDwnEndpointUrlsFn,
173
174
  getSigner: GetSignerFn,
174
175
  sendDwnRpcRequest: SendDwnRpcRequestFn,
175
176
  ): Promise<{ rootKeyId: string; derivedPublicKey: PublicKeyJwk } | undefined> {
@@ -184,7 +185,7 @@ export async function extractDerivedPublicKey(
184
185
  },
185
186
  });
186
187
 
187
- const dwnEndpointUrls = await getDwnServiceEndpointUrls(targetDid, didDereferencer);
188
+ const dwnEndpointUrls = await getDwnEndpointUrls(targetDid);
188
189
  const queryReply = await sendDwnRpcRequest<DwnInterfaceEnum.RecordsQuery>({
189
190
  targetDid,
190
191
  dwnEndpointUrls,
@@ -8,7 +8,7 @@ import type {
8
8
  } from '@enbox/dwn-sdk-js';
9
9
 
10
10
  import type { DwnSigner } from './types/dwn.js';
11
- import type { Web5PlatformAgent } from './types/agent.js';
11
+ import type { EnboxPlatformAgent } from './types/agent.js';
12
12
 
13
13
  import {
14
14
  Encoder,
@@ -42,7 +42,7 @@ import { DwnInterface, dwnMessageConstructors } from './types/dwn.js';
42
42
  * @param contextKeyCache - Cache for context key info
43
43
  */
44
44
  export async function upgradeExternalRootRecord(
45
- agent: Web5PlatformAgent,
45
+ agent: EnboxPlatformAgent,
46
46
  tenantDid: string,
47
47
  recordsWrite: RecordsWriteMessage,
48
48
  dwn: Dwn,
@@ -1,7 +1,8 @@
1
1
  import type { AgentKeyManager } from './types/key-manager.js';
2
2
  import type { BearerDid } from '@enbox/dids';
3
- import type { Web5PlatformAgent } from './types/agent.js';
4
- import type { Web5Rpc } from '@enbox/dwn-clients';
3
+ import type { EnboxPlatformAgent } from './types/agent.js';
4
+ import type { EnboxRpc } from '@enbox/dwn-clients';
5
+ import type { LocalDwnStrategy } from './local-dwn.js';
5
6
  import type { DidInterface, DidRequest, DidResponse } from './did-api.js';
6
7
  import type { DwnInterface, DwnResponse, ProcessDwnRequest, SendDwnRequest } from './types/dwn.js';
7
8
  import type { ProcessVcRequest, SendVcRequest, VcResponse } from './types/vc.js';
@@ -16,15 +17,15 @@ import { AgentSyncApi } from './sync-api.js';
16
17
  import { DwnDidStore } from './store-did.js';
17
18
  import { DwnIdentityStore } from './store-identity.js';
18
19
  import { DwnKeyStore } from './store-key.js';
20
+ import { EnboxRpcClient } from '@enbox/dwn-clients';
19
21
  import { HdIdentityVault } from './hd-identity-vault.js';
20
22
  import { LevelStore } from '@enbox/common';
21
23
  import { LocalKeyManager } from './local-key-manager.js';
22
24
  import { SyncEngineLevel } from './sync-engine-level.js';
23
- import { Web5RpcClient } from '@enbox/dwn-clients';
24
25
  import { DidDht, DidJwk } from '@enbox/dids';
25
26
 
26
27
  /**
27
- * Initialization parameters for {@link Web5UserAgent}, including an optional recovery phrase that
28
+ * Initialization parameters for {@link EnboxUserAgent}, including an optional recovery phrase that
28
29
  * can be used to derive keys to encrypt the vault and generate a DID.
29
30
  */
30
31
  export type AgentInitializeParams = {
@@ -45,10 +46,10 @@ export type AgentInitializeParams = {
45
46
  recoveryPhrase?: string;
46
47
 
47
48
  /**
48
- * Optional dwnEndpoints to register didService endpoints during Web5UserAgent initialization
49
+ * Optional dwnEndpoints to register didService endpoints during EnboxUserAgent initialization
49
50
  *
50
51
  * The dwnEndpoints are used to register DWN endpoints against the agent DID created during
51
- * Web5UserAgent.initialize() => DidDht.create(). This allows the
52
+ * EnboxUserAgent.initialize() => DidDht.create(). This allows the
52
53
  * agent to properly recover connectedDids from DWN. Also, this pattern can be used on the server
53
54
  * side in place of the agentDid-->connectedDids pattern.
54
55
  */
@@ -63,7 +64,7 @@ export type AgentStartParams = {
63
64
  };
64
65
 
65
66
  export type AgentParams<TKeyManager extends AgentKeyManager = LocalKeyManager> = {
66
- /** Optional. The Decentralized Identifier (DID) representing this Web5 User Agent. */
67
+ /** Optional. The Decentralized Identifier (DID) representing this Enbox User Agent. */
67
68
  agentDid?: BearerDid;
68
69
  /** Encrypted vault used for managing the Agent's DID and associated keys. */
69
70
  agentVault: HdIdentityVault;
@@ -81,20 +82,24 @@ export type AgentParams<TKeyManager extends AgentKeyManager = LocalKeyManager> =
81
82
  keyManager: TKeyManager;
82
83
  /** Facilitates fetching, requesting, creating, revoking and validating revocation status of permissions */
83
84
  permissionsApi: AgentPermissionsApi;
84
- /** Remote procedure call (RPC) client used to communicate with other Web5 services. */
85
- rpcClient: Web5Rpc;
85
+ /** Remote procedure call (RPC) client used to communicate with other Enbox services. */
86
+ rpcClient: EnboxRpc;
86
87
  /** Facilitates data synchronization of DWN records between nodes. */
87
88
  syncApi: AgentSyncApi;
88
89
  };
89
90
 
90
- export class Web5UserAgent<TKeyManager extends AgentKeyManager = LocalKeyManager> implements Web5PlatformAgent<TKeyManager> {
91
+ export type CreateUserAgentParams = Partial<AgentParams> & {
92
+ localDwnStrategy?: LocalDwnStrategy;
93
+ };
94
+
95
+ export class EnboxUserAgent<TKeyManager extends AgentKeyManager = LocalKeyManager> implements EnboxPlatformAgent<TKeyManager> {
91
96
  public crypto: AgentCryptoApi;
92
97
  public did: AgentDidApi<TKeyManager>;
93
98
  public dwn: AgentDwnApi;
94
99
  public identity: AgentIdentityApi<TKeyManager>;
95
100
  public keyManager: TKeyManager;
96
101
  public permissions: AgentPermissionsApi;
97
- public rpc: Web5Rpc;
102
+ public rpc: EnboxRpc;
98
103
  public sync: AgentSyncApi;
99
104
  public vault: HdIdentityVault;
100
105
 
@@ -124,7 +129,7 @@ export class Web5UserAgent<TKeyManager extends AgentKeyManager = LocalKeyManager
124
129
  get agentDid(): BearerDid {
125
130
  if (this._agentDid === undefined) {
126
131
  throw new Error(
127
- 'Web5UserAgent: The "agentDid" property is not set. Ensure the agent is properly ' +
132
+ 'EnboxUserAgent: The "agentDid" property is not set. Ensure the agent is properly ' +
128
133
  'initialized and a DID is assigned.'
129
134
  );
130
135
  }
@@ -140,9 +145,10 @@ export class Web5UserAgent<TKeyManager extends AgentKeyManager = LocalKeyManager
140
145
  */
141
146
  public static async create({
142
147
  dataPath = 'DATA/AGENT',
148
+ localDwnStrategy,
143
149
  agentDid, agentVault, cryptoApi, didApi, dwnApi, identityApi, keyManager, permissionsApi, rpcClient, syncApi
144
- }: Partial<AgentParams> = {}
145
- ): Promise<Web5UserAgent> {
150
+ }: CreateUserAgentParams = {}
151
+ ): Promise<EnboxUserAgent> {
146
152
 
147
153
  agentVault ??= new HdIdentityVault({
148
154
  keyDerivationWorkFactor : 210_000,
@@ -158,8 +164,12 @@ export class Web5UserAgent<TKeyManager extends AgentKeyManager = LocalKeyManager
158
164
  });
159
165
 
160
166
  dwnApi ??= new AgentDwnApi({
161
- dwn: await AgentDwnApi.createDwn({ dataPath, didResolver: didApi })
167
+ dwn : await AgentDwnApi.createDwn({ dataPath, didResolver: didApi }),
168
+ localDwnStrategy : localDwnStrategy ?? 'prefer',
162
169
  });
170
+ if (localDwnStrategy) {
171
+ dwnApi.setLocalDwnStrategy(localDwnStrategy);
172
+ }
163
173
 
164
174
  identityApi ??= new AgentIdentityApi({ store: new DwnIdentityStore() });
165
175
 
@@ -167,12 +177,12 @@ export class Web5UserAgent<TKeyManager extends AgentKeyManager = LocalKeyManager
167
177
 
168
178
  permissionsApi ??= new AgentPermissionsApi();
169
179
 
170
- rpcClient ??= new Web5RpcClient();
180
+ rpcClient ??= new EnboxRpcClient();
171
181
 
172
182
  syncApi ??= new AgentSyncApi({ syncEngine: new SyncEngineLevel({ dataPath }) });
173
183
 
174
184
  // Instantiate the Agent using the provided or default components.
175
- return new Web5UserAgent({
185
+ return new EnboxUserAgent({
176
186
  agentDid,
177
187
  agentVault,
178
188
  cryptoApi,
@@ -196,7 +206,7 @@ export class Web5UserAgent<TKeyManager extends AgentKeyManager = LocalKeyManager
196
206
  *
197
207
  * This method is typically called once, the first time the Agent is launched, and is responsible
198
208
  * for setting up the agent's operational environment, cryptographic key material, and readiness
199
- * for processing Web5 requests.
209
+ * for processing requests.
200
210
  *
201
211
  * The password is used to secure the Agent vault, and the recovery phrase is used to derive the
202
212
  * cryptographic keys for the vault. If a recovery phrase is not provided, a new recovery phrase
@@ -250,4 +260,14 @@ export class Web5UserAgent<TKeyManager extends AgentKeyManager = LocalKeyManager
250
260
  // Set the Agent's DID.
251
261
  this.agentDid = await this.vault.getDid();
252
262
  }
253
- }
263
+ }
264
+
265
+ // ---------------------------------------------------------------------------
266
+ // Deprecated aliases — migration aid
267
+ // ---------------------------------------------------------------------------
268
+
269
+ /** @deprecated Use {@link EnboxUserAgent} instead. Will be removed in a future version. */
270
+ export const Web5UserAgent = EnboxUserAgent;
271
+
272
+ /** @deprecated Use {@link EnboxUserAgent} instead. Will be removed in a future version. */
273
+ export type Web5UserAgent = EnboxUserAgent;
@@ -3,17 +3,16 @@ import type { RequireOnly } from '@enbox/common';
3
3
  import type { AgentDataStore } from './store-data.js';
4
4
  import type { AgentKeyManager } from './types/key-manager.js';
5
5
  import type { DidMethodCreateOptions } from './did-api.js';
6
- import type { Web5PlatformAgent } from './types/agent.js';
6
+ import type { EnboxPlatformAgent } from './types/agent.js';
7
7
  import type { IdentityMetadata, PortableIdentity } from './types/identity.js';
8
8
 
9
9
  import { isPortableDid } from '@enbox/dids';
10
10
 
11
11
  import { BearerIdentity } from './bearer-identity.js';
12
- import { getDwnServiceEndpointUrls } from './utils.js';
13
12
  import { InMemoryIdentityStore } from './store-identity.js';
14
13
 
15
14
  export interface IdentityApiParams<TKeyManager extends AgentKeyManager> {
16
- agent?: Web5PlatformAgent<TKeyManager>;
15
+ agent?: EnboxPlatformAgent<TKeyManager>;
17
16
 
18
17
  store?: AgentDataStore<IdentityMetadata>;
19
18
  }
@@ -37,7 +36,7 @@ export function isPortableIdentity(obj: unknown): obj is PortableIdentity {
37
36
  }
38
37
 
39
38
  /**
40
- * This API is used to manage and interact with Identities within the Web5 Agent framework.
39
+ * This API is used to manage and interact with Identities within the Enbox Agent framework.
41
40
  * An Identity is a DID that is associated with metadata that describes the Identity.
42
41
  * Metadata includes A name(label), and whether or not the Identity is connected (delegated to act on the behalf of another DID).
43
42
  *
@@ -48,12 +47,12 @@ export function isPortableIdentity(obj: unknown): obj is PortableIdentity {
48
47
  */
49
48
  export class AgentIdentityApi<TKeyManager extends AgentKeyManager = AgentKeyManager> {
50
49
  /**
51
- * Holds the instance of a `Web5PlatformAgent` that represents the current execution context for
52
- * the `AgentIdentityApi`. This agent is used to interact with other Web5 agent components. It's
50
+ * Holds the instance of a `EnboxPlatformAgent` that represents the current execution context for
51
+ * the `AgentIdentityApi`. This agent is used to interact with other Enbox agent components. It's
53
52
  * vital to ensure this instance is set to correctly contextualize operations within the broader
54
- * Web5 Agent framework.
53
+ * Enbox Agent framework.
55
54
  */
56
- private _agent?: Web5PlatformAgent<TKeyManager>;
55
+ private _agent?: EnboxPlatformAgent<TKeyManager>;
57
56
 
58
57
  private _store: AgentDataStore<IdentityMetadata>;
59
58
 
@@ -65,12 +64,12 @@ export class AgentIdentityApi<TKeyManager extends AgentKeyManager = AgentKeyMana
65
64
  }
66
65
 
67
66
  /**
68
- * Retrieves the `Web5PlatformAgent` execution context.
67
+ * Retrieves the `EnboxPlatformAgent` execution context.
69
68
  *
70
- * @returns The `Web5PlatformAgent` instance that represents the current execution context.
69
+ * @returns The `EnboxPlatformAgent` instance that represents the current execution context.
71
70
  * @throws Will throw an error if the `agent` instance property is undefined.
72
71
  */
73
- get agent(): Web5PlatformAgent<TKeyManager> {
72
+ get agent(): EnboxPlatformAgent<TKeyManager> {
74
73
  if (this._agent === undefined) {
75
74
  throw new Error('AgentIdentityApi: Unable to determine agent execution context.');
76
75
  }
@@ -78,7 +77,7 @@ export class AgentIdentityApi<TKeyManager extends AgentKeyManager = AgentKeyMana
78
77
  return this._agent;
79
78
  }
80
79
 
81
- set agent(agent: Web5PlatformAgent<TKeyManager>) {
80
+ set agent(agent: EnboxPlatformAgent<TKeyManager>) {
82
81
  this._agent = agent;
83
82
  }
84
83
 
@@ -226,7 +225,7 @@ export class AgentIdentityApi<TKeyManager extends AgentKeyManager = AgentKeyMana
226
225
  * @throws An error if the DID is not found, or no DWN service exists.
227
226
  */
228
227
  public getDwnEndpoints({ didUri }: { didUri: string; }): Promise<string[]> {
229
- return getDwnServiceEndpointUrls(didUri, this.agent.did);
228
+ return this.agent.dwn.getDwnEndpointUrlsForTarget(didUri);
230
229
  }
231
230
 
232
231
  /**
package/src/index.ts CHANGED
@@ -13,6 +13,8 @@ export * from './bearer-identity.js';
13
13
  export * from './crypto-api.js';
14
14
  export * from './did-api.js';
15
15
  export * from './dwn-api.js';
16
+ export * from './dwn-discovery-file.js';
17
+ export * from './dwn-discovery-payload.js';
16
18
  export * from './dwn-encryption.js';
17
19
  export * from './dwn-key-delivery.js';
18
20
  export * from './dwn-record-upgrade.js';
@@ -20,6 +22,7 @@ export * from './dwn-type-guards.js';
20
22
  export * from './protocol-utils.js';
21
23
  export * from './hd-identity-vault.js';
22
24
  export * from './identity-api.js';
25
+ export * from './local-dwn.js';
23
26
  export * from './local-key-manager.js';
24
27
  export * from './permissions-api.js';
25
28
  export * from './store-data.js';
@@ -32,4 +35,4 @@ export * from './test-harness.js';
32
35
  export * from './utils.js';
33
36
  export * from './connect.js';
34
37
  export * from './oidc.js';
35
- export * from './web5-user-agent.js';
38
+ export * from './enbox-user-agent.js';
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Local DWN discovery — discovers a running `@enbox/dwn-server` instance
3
+ * so the agent can route traffic to it.
4
+ *
5
+ * Discovery channels (tried in order):
6
+ * 1. **In-memory cache** — serves a recent positive or negative result.
7
+ * 2. **Discovery file** (`~/.enbox/dwn.json`) — written by `electrobun-dwn`
8
+ * on startup. Fast filesystem read, no network. Available for CLI and
9
+ * native apps; skipped in browsers.
10
+ * 3. **Port probing** (fallback) — sequential HTTP `GET /info` on well-known
11
+ * localhost ports. Works everywhere but is slower.
12
+ *
13
+ * @see https://github.com/enboxorg/enbox/issues/585
14
+ * @module
15
+ */
16
+
17
+ import type { EnboxRpc } from '@enbox/dwn-clients';
18
+
19
+ import type { DwnDiscoveryFile } from './dwn-discovery-file.js';
20
+
21
+ /**
22
+ * Well-known ports the local DWN desktop app may bind to.
23
+ *
24
+ * Per the DWN Transport Spec, clients probe ports `55500` through `55509`
25
+ * (inclusive). Port `3000` is included as a development convenience.
26
+ *
27
+ * @see https://identity.foundation/dwn-transport/#port-probing
28
+ */
29
+ export const localDwnPortCandidates = [3000, 55500, 55501, 55502, 55503, 55504, 55505, 55506, 55507, 55508, 55509] as const;
30
+
31
+ /**
32
+ * Hosts probed when discovering a local DWN server.
33
+ *
34
+ * Per the DWN Transport Spec, clients MUST use `127.0.0.1` rather than
35
+ * `localhost` to avoid DNS resolution ambiguity.
36
+ *
37
+ * @see https://identity.foundation/dwn-transport/#port-probing
38
+ */
39
+ export const localDwnHostCandidates = ['127.0.0.1'] as const;
40
+
41
+ /**
42
+ * Controls how the agent discovers and routes to a local DWN server.
43
+ *
44
+ * - `'off'` — (default) skip local discovery entirely.
45
+ * - `'prefer'` — probe localhost first; fall back to DID-document endpoints.
46
+ * - `'only'` — require a local server; throw if none is found.
47
+ */
48
+ export type LocalDwnStrategy = 'prefer' | 'only' | 'off';
49
+
50
+ /** The `server` field returned by `GET /info` on `@enbox/dwn-server`. */
51
+ export const localDwnServerName = '@enbox/dwn-server';
52
+
53
+ /** Strips a trailing slash from a URL so endpoint comparisons are consistent. */
54
+ export function normalizeBaseUrl(url: string): string {
55
+ return url.endsWith('/') ? url.slice(0, -1) : url;
56
+ }
57
+
58
+ /**
59
+ * Discovers a running local DWN server.
60
+ *
61
+ * Results are cached for {@link _cacheTtlMs} milliseconds (default 10 s) to
62
+ * avoid repeated I/O on hot paths such as sync.
63
+ *
64
+ * @example Discovery with file-based channel
65
+ * ```ts
66
+ * import { DwnDiscoveryFile } from './dwn-discovery-file.js';
67
+ *
68
+ * const discoveryFile = new DwnDiscoveryFile();
69
+ * const discovery = new LocalDwnDiscovery(rpcClient, 10_000, discoveryFile);
70
+ * const endpoint = await discovery.getEndpoint();
71
+ * ```
72
+ *
73
+ * @example Browser: inject cached endpoint from `dwn://register` redirect
74
+ * ```ts
75
+ * const discovery = new LocalDwnDiscovery(rpcClient);
76
+ * discovery.setCachedEndpoint('http://127.0.0.1:55557');
77
+ * ```
78
+ */
79
+ export class LocalDwnDiscovery {
80
+ private _cachedEndpoint?: string;
81
+ private _cacheExpiry = 0;
82
+
83
+ constructor(
84
+ private _rpcClient: EnboxRpc,
85
+ private _cacheTtlMs = 10_000,
86
+ private _discoveryFile?: DwnDiscoveryFile,
87
+ ) {}
88
+
89
+ /**
90
+ * Returns the base URL of a local DWN server, or `undefined` if none
91
+ * is discoverable.
92
+ *
93
+ * The discovery order is:
94
+ * 1. In-memory cache (if not expired).
95
+ * 2. `~/.enbox/dwn.json` discovery file (if a {@link DwnDiscoveryFile}
96
+ * was provided). The endpoint from the file is validated via
97
+ * `GET /info` to ensure the server is still running.
98
+ * 3. Sequential port probing on well-known localhost ports (fallback).
99
+ */
100
+ public async getEndpoint(): Promise<string | undefined> {
101
+ const now = Date.now();
102
+ if (now < this._cacheExpiry) {
103
+ return this._cachedEndpoint;
104
+ }
105
+
106
+ // Channel 1: file-based discovery.
107
+ const fileEndpoint = await this._tryDiscoveryFile();
108
+ if (fileEndpoint !== undefined) {
109
+ this._setCacheEntry(fileEndpoint, now);
110
+ return fileEndpoint;
111
+ }
112
+
113
+ // Channel 2: sequential port probing (fallback).
114
+ const probeEndpoint = await this._probePortCandidates();
115
+ // Cache both positive and negative results.
116
+ this._setCacheEntry(probeEndpoint, now);
117
+ return probeEndpoint;
118
+ }
119
+
120
+ /**
121
+ * Inject a cached endpoint (e.g. from a `dwn://register` browser redirect
122
+ * or from `localStorage`). The endpoint is validated via `GET /info` before
123
+ * caching.
124
+ *
125
+ * @returns `true` if the endpoint was validated and cached, `false` otherwise.
126
+ */
127
+ public async setCachedEndpoint(endpoint: string): Promise<boolean> {
128
+ const normalized = normalizeBaseUrl(endpoint);
129
+ const valid = await this._validateEndpoint(normalized);
130
+ if (valid) {
131
+ this._setCacheEntry(normalized, Date.now());
132
+ }
133
+ return valid;
134
+ }
135
+
136
+ /**
137
+ * Clear the in-memory cache, forcing the next {@link getEndpoint} call
138
+ * to perform a fresh discovery.
139
+ */
140
+ public clearCache(): void {
141
+ this._cachedEndpoint = undefined;
142
+ this._cacheExpiry = 0;
143
+ }
144
+
145
+ // ─── Private discovery channels ────────────────────────────────
146
+
147
+ /**
148
+ * Try the `~/.enbox/dwn.json` discovery file. Returns the endpoint if
149
+ * the file exists, is valid, and the endpoint passes `GET /info`
150
+ * validation. Returns `undefined` otherwise.
151
+ */
152
+ private async _tryDiscoveryFile(): Promise<string | undefined> {
153
+ if (!this._discoveryFile) {
154
+ return undefined;
155
+ }
156
+
157
+ try {
158
+ const record = await this._discoveryFile.read();
159
+ if (!record) {
160
+ return undefined;
161
+ }
162
+
163
+ // Validate that the server is actually alive and is ours.
164
+ const valid = await this._validateEndpoint(record.endpoint);
165
+ return valid ? record.endpoint : undefined;
166
+ } catch {
167
+ return undefined;
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Sequential HTTP probe on well-known localhost port candidates.
173
+ * Returns the first endpoint whose `GET /info` response identifies
174
+ * as `@enbox/dwn-server`, or `undefined` if none is found.
175
+ */
176
+ private async _probePortCandidates(): Promise<string | undefined> {
177
+ for (const port of localDwnPortCandidates) {
178
+ for (const host of localDwnHostCandidates) {
179
+ const endpoint = `http://${host}:${port}`;
180
+ const valid = await this._validateEndpoint(endpoint);
181
+ if (valid) {
182
+ return normalizeBaseUrl(endpoint);
183
+ }
184
+ }
185
+ }
186
+ return undefined;
187
+ }
188
+
189
+ /**
190
+ * Call `GET /info` on the endpoint and check that
191
+ * `serverInfo.server === '@enbox/dwn-server'`.
192
+ */
193
+ private async _validateEndpoint(endpoint: string): Promise<boolean> {
194
+ try {
195
+ const serverInfo = await this._rpcClient.getServerInfo(endpoint);
196
+ return serverInfo.server === localDwnServerName;
197
+ } catch {
198
+ return false;
199
+ }
200
+ }
201
+
202
+ /** Update the in-memory cache entry. */
203
+ private _setCacheEntry(endpoint: string | undefined, now: number): void {
204
+ this._cachedEndpoint = endpoint;
205
+ this._cacheExpiry = now + this._cacheTtlMs;
206
+ }
207
+ }