@enbox/agent 0.3.1 → 0.5.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 (81) hide show
  1. package/dist/browser.mjs +12 -30
  2. package/dist/browser.mjs.map +4 -4
  3. package/dist/esm/dwn-api.js +149 -22
  4. package/dist/esm/dwn-api.js.map +1 -1
  5. package/dist/esm/dwn-discovery-file.js +1 -1
  6. package/dist/esm/dwn-discovery-payload.js +20 -21
  7. package/dist/esm/dwn-discovery-payload.js.map +1 -1
  8. package/dist/esm/dwn-key-delivery.js.map +1 -1
  9. package/dist/esm/{oidc.js → enbox-connect-protocol.js} +219 -251
  10. package/dist/esm/enbox-connect-protocol.js.map +1 -0
  11. package/dist/esm/enbox-user-agent.js +19 -12
  12. package/dist/esm/enbox-user-agent.js.map +1 -1
  13. package/dist/esm/hd-identity-vault.js +11 -0
  14. package/dist/esm/hd-identity-vault.js.map +1 -1
  15. package/dist/esm/index.js +4 -4
  16. package/dist/esm/index.js.map +1 -1
  17. package/dist/esm/local-dwn.js +21 -51
  18. package/dist/esm/local-dwn.js.map +1 -1
  19. package/dist/esm/permissions-api.js.map +1 -1
  20. package/dist/esm/store-data.js.map +1 -1
  21. package/dist/esm/sync-engine-level.js +1 -1
  22. package/dist/esm/sync-engine-level.js.map +1 -1
  23. package/dist/esm/sync-messages.js +1 -1
  24. package/dist/esm/sync-messages.js.map +1 -1
  25. package/dist/esm/test-harness.js +2 -3
  26. package/dist/esm/test-harness.js.map +1 -1
  27. package/dist/esm/types/dwn.js.map +1 -1
  28. package/dist/types/dwn-api.d.ts +46 -6
  29. package/dist/types/dwn-api.d.ts.map +1 -1
  30. package/dist/types/dwn-discovery-file.d.ts +1 -1
  31. package/dist/types/dwn-discovery-payload.d.ts +18 -19
  32. package/dist/types/dwn-discovery-payload.d.ts.map +1 -1
  33. package/dist/types/enbox-connect-protocol.d.ts +206 -0
  34. package/dist/types/enbox-connect-protocol.d.ts.map +1 -0
  35. package/dist/types/enbox-user-agent.d.ts +13 -8
  36. package/dist/types/enbox-user-agent.d.ts.map +1 -1
  37. package/dist/types/hd-identity-vault.d.ts +7 -0
  38. package/dist/types/hd-identity-vault.d.ts.map +1 -1
  39. package/dist/types/index.d.ts +1 -4
  40. package/dist/types/index.d.ts.map +1 -1
  41. package/dist/types/local-dwn.d.ts +16 -32
  42. package/dist/types/local-dwn.d.ts.map +1 -1
  43. package/dist/types/test-harness.d.ts.map +1 -1
  44. package/dist/types/types/agent.d.ts +2 -7
  45. package/dist/types/types/agent.d.ts.map +1 -1
  46. package/dist/types/types/dwn.d.ts +0 -10
  47. package/dist/types/types/dwn.d.ts.map +1 -1
  48. package/dist/types/types/sync.d.ts +6 -0
  49. package/dist/types/types/sync.d.ts.map +1 -1
  50. package/package.json +14 -16
  51. package/src/dwn-api.ts +175 -29
  52. package/src/dwn-discovery-file.ts +1 -1
  53. package/src/dwn-discovery-payload.ts +23 -24
  54. package/src/dwn-key-delivery.ts +1 -1
  55. package/src/enbox-connect-protocol.ts +753 -0
  56. package/src/enbox-user-agent.ts +31 -18
  57. package/src/hd-identity-vault.ts +21 -0
  58. package/src/index.ts +4 -4
  59. package/src/local-dwn.ts +22 -53
  60. package/src/permissions-api.ts +3 -3
  61. package/src/store-data.ts +1 -1
  62. package/src/sync-engine-level.ts +1 -1
  63. package/src/sync-messages.ts +1 -1
  64. package/src/test-harness.ts +2 -3
  65. package/src/types/agent.ts +3 -14
  66. package/src/types/dwn.ts +1 -13
  67. package/src/types/sync.ts +7 -0
  68. package/dist/esm/connect.js +0 -180
  69. package/dist/esm/connect.js.map +0 -1
  70. package/dist/esm/oidc.js.map +0 -1
  71. package/dist/esm/sync-api.js +0 -64
  72. package/dist/esm/sync-api.js.map +0 -1
  73. package/dist/types/connect.d.ts +0 -88
  74. package/dist/types/connect.d.ts.map +0 -1
  75. package/dist/types/oidc.d.ts +0 -250
  76. package/dist/types/oidc.d.ts.map +0 -1
  77. package/dist/types/sync-api.d.ts +0 -40
  78. package/dist/types/sync-api.d.ts.map +0 -1
  79. package/src/connect.ts +0 -285
  80. package/src/oidc.ts +0 -864
  81. package/src/sync-api.ts +0 -75
@@ -3,6 +3,7 @@ import type { BearerDid } from '@enbox/dids';
3
3
  import type { EnboxPlatformAgent } from './types/agent.js';
4
4
  import type { EnboxRpc } from '@enbox/dwn-clients';
5
5
  import type { LocalDwnStrategy } from './local-dwn.js';
6
+ import type { SyncEngine } from './types/sync.js';
6
7
  import type { DidInterface, DidRequest, DidResponse } from './did-api.js';
7
8
  import type { DwnInterface, DwnResponse, ProcessDwnRequest, SendDwnRequest } from './types/dwn.js';
8
9
  import type { ProcessVcRequest, SendVcRequest, VcResponse } from './types/vc.js';
@@ -13,7 +14,6 @@ import { AgentDidResolverCache } from './agent-did-resolver-cache.js';
13
14
  import { AgentDwnApi } from './dwn-api.js';
14
15
  import { AgentIdentityApi } from './identity-api.js';
15
16
  import { AgentPermissionsApi } from './permissions-api.js';
16
- import { AgentSyncApi } from './sync-api.js';
17
17
  import { DwnDidStore } from './store-did.js';
18
18
  import { DwnIdentityStore } from './store-identity.js';
19
19
  import { DwnKeyStore } from './store-key.js';
@@ -85,11 +85,21 @@ export type AgentParams<TKeyManager extends AgentKeyManager = LocalKeyManager> =
85
85
  /** Remote procedure call (RPC) client used to communicate with other Enbox services. */
86
86
  rpcClient: EnboxRpc;
87
87
  /** Facilitates data synchronization of DWN records between nodes. */
88
- syncApi: AgentSyncApi;
88
+ syncApi: SyncEngine;
89
89
  };
90
90
 
91
91
  export type CreateUserAgentParams = Partial<AgentParams> & {
92
92
  localDwnStrategy?: LocalDwnStrategy;
93
+
94
+ /**
95
+ * When set, the agent operates in "remote mode": no in-process DWN is
96
+ * created. All `processRequest()` calls are routed through RPC to
97
+ * this endpoint instead.
98
+ *
99
+ * Typically set by `AuthManager.create()` after standalone discovery
100
+ * determines that a local DWN server is running.
101
+ */
102
+ localDwnEndpoint?: string;
93
103
  };
94
104
 
95
105
  export class EnboxUserAgent<TKeyManager extends AgentKeyManager = LocalKeyManager> implements EnboxPlatformAgent<TKeyManager> {
@@ -100,7 +110,7 @@ export class EnboxUserAgent<TKeyManager extends AgentKeyManager = LocalKeyManage
100
110
  public keyManager: TKeyManager;
101
111
  public permissions: AgentPermissionsApi;
102
112
  public rpc: EnboxRpc;
103
- public sync: AgentSyncApi;
113
+ public sync: SyncEngine;
104
114
  public vault: HdIdentityVault;
105
115
 
106
116
  private _agentDid?: BearerDid;
@@ -146,6 +156,7 @@ export class EnboxUserAgent<TKeyManager extends AgentKeyManager = LocalKeyManage
146
156
  public static async create({
147
157
  dataPath = 'DATA/AGENT',
148
158
  localDwnStrategy,
159
+ localDwnEndpoint,
149
160
  agentDid, agentVault, cryptoApi, didApi, dwnApi, identityApi, keyManager, permissionsApi, rpcClient, syncApi
150
161
  }: CreateUserAgentParams = {}
151
162
  ): Promise<EnboxUserAgent> {
@@ -163,10 +174,22 @@ export class EnboxUserAgent<TKeyManager extends AgentKeyManager = LocalKeyManage
163
174
  store : new DwnDidStore()
164
175
  });
165
176
 
166
- dwnApi ??= new AgentDwnApi({
167
- dwn : await AgentDwnApi.createDwn({ dataPath, didResolver: didApi }),
168
- localDwnStrategy : localDwnStrategy ?? 'prefer',
169
- });
177
+ if (!dwnApi) {
178
+ if (localDwnEndpoint) {
179
+ // Remote mode: no in-process DWN. All operations route through
180
+ // RPC to the local DWN server.
181
+ dwnApi = new AgentDwnApi({
182
+ localDwnEndpoint,
183
+ localDwnStrategy: localDwnStrategy ?? 'prefer',
184
+ });
185
+ } else {
186
+ // Local mode: create an in-process DWN with LevelDB stores.
187
+ dwnApi = new AgentDwnApi({
188
+ dwn : await AgentDwnApi.createDwn({ dataPath, didResolver: didApi }),
189
+ localDwnStrategy : localDwnStrategy ?? 'prefer',
190
+ });
191
+ }
192
+ }
170
193
  if (localDwnStrategy) {
171
194
  dwnApi.setLocalDwnStrategy(localDwnStrategy);
172
195
  }
@@ -179,7 +202,7 @@ export class EnboxUserAgent<TKeyManager extends AgentKeyManager = LocalKeyManage
179
202
 
180
203
  rpcClient ??= new EnboxRpcClient();
181
204
 
182
- syncApi ??= new AgentSyncApi({ syncEngine: new SyncEngineLevel({ dataPath }) });
205
+ syncApi ??= new SyncEngineLevel({ dataPath });
183
206
 
184
207
  // Instantiate the Agent using the provided or default components.
185
208
  return new EnboxUserAgent({
@@ -261,13 +284,3 @@ export class EnboxUserAgent<TKeyManager extends AgentKeyManager = LocalKeyManage
261
284
  this.agentDid = await this.vault.getDid();
262
285
  }
263
286
  }
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;
@@ -150,6 +150,14 @@ export class HdIdentityVault implements IdentityVault<{ InitializeResult: string
150
150
  /** The cryptographic key used to encrypt and decrypt the vault's content securely. */
151
151
  private _contentEncryptionKey: Jwk | undefined;
152
152
 
153
+ /**
154
+ * Cached initialization state. Once read from the store, avoids redundant LevelDB reads on
155
+ * subsequent checks. The `initialized` flag is write-once (false → true) and never reverts,
156
+ * making it safe to cache indefinitely. Mirrors the pattern used by {@link _contentEncryptionKey}
157
+ * for the synchronous {@link isLocked} check.
158
+ */
159
+ private _cachedInitialized: boolean | undefined;
160
+
153
161
  /**
154
162
  * Constructs an instance of `HdIdentityVault`, initializing the key derivation factor and data
155
163
  * store. It sets the default key derivation work factor and initializes the internal data store,
@@ -337,6 +345,13 @@ export class HdIdentityVault implements IdentityVault<{ InitializeResult: string
337
345
  throw new Error('HdIdentityVault: Invalid IdentityVaultStatus object in store');
338
346
  }
339
347
 
348
+ // Only cache the `true` state — `initialized` is write-once (false → true) and never reverts,
349
+ // so a cached `true` is always valid. Leaving `false` uncached ensures a subsequent
350
+ // `isInitialized()` call after `initialize()` correctly reads the updated store.
351
+ if (vaultStatus.initialized) {
352
+ this._cachedInitialized = true;
353
+ }
354
+
340
355
  return vaultStatus;
341
356
  }
342
357
 
@@ -595,6 +610,9 @@ export class HdIdentityVault implements IdentityVault<{ InitializeResult: string
595
610
  * @returns A promise that resolves to `true` if the vault has been initialized, otherwise `false`.
596
611
  */
597
612
  public async isInitialized(): Promise<boolean> {
613
+ if (this._cachedInitialized === true) {
614
+ return true;
615
+ }
598
616
  return this.getStatus().then(({ initialized }) => initialized);
599
617
  }
600
618
 
@@ -851,6 +869,9 @@ export class HdIdentityVault implements IdentityVault<{ InitializeResult: string
851
869
  // Write the changes to the store.
852
870
  await this._store.set('vaultStatus', JSON.stringify(vaultStatus));
853
871
 
872
+ // Update the in-memory cache so subsequent reads skip the store.
873
+ this._cachedInitialized = vaultStatus.initialized;
874
+
854
875
  return true;
855
876
  }
856
877
  }
package/src/index.ts CHANGED
@@ -17,7 +17,9 @@ export * from './dwn-discovery-file.js';
17
17
  export * from './dwn-discovery-payload.js';
18
18
  export * from './dwn-encryption.js';
19
19
  export * from './dwn-key-delivery.js';
20
- export * from './dwn-record-upgrade.js';
20
+ // NOTE: dwn-record-upgrade.js is intentionally NOT exported — the module
21
+ // is disabled (see TODO in dwn-api.ts postWriteKeyDelivery). Keeping the
22
+ // source file for reference until the redesign in a future PR.
21
23
  export * from './dwn-type-guards.js';
22
24
  export * from './protocol-utils.js';
23
25
  export * from './hd-identity-vault.js';
@@ -29,10 +31,8 @@ export * from './store-data.js';
29
31
  export * from './store-did.js';
30
32
  export * from './store-identity.js';
31
33
  export * from './store-key.js';
32
- export * from './sync-api.js';
33
34
  export * from './sync-engine-level.js';
34
35
  export * from './test-harness.js';
35
36
  export * from './utils.js';
36
- export * from './connect.js';
37
- export * from './oidc.js';
37
+ export * from './enbox-connect-protocol.js';
38
38
  export * from './enbox-user-agent.js';
package/src/local-dwn.ts CHANGED
@@ -7,10 +7,11 @@
7
7
  * 2. **Discovery file** (`~/.enbox/dwn.json`) — written by `electrobun-dwn`
8
8
  * on startup. Fast filesystem read, no network. Available for CLI and
9
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.
10
+ * 3. **Injected endpoint** — in browsers, the `dwn://connect` redirect
11
+ * flow delivers the endpoint, which is injected via
12
+ * {@link LocalDwnDiscovery.setCachedEndpoint | setCachedEndpoint()}.
12
13
  *
13
- * @see https://github.com/enboxorg/enbox/issues/585
14
+ * @see https://github.com/enboxorg/enbox/issues/677
14
15
  * @module
15
16
  */
16
17
 
@@ -18,31 +19,11 @@ import type { EnboxRpc } from '@enbox/dwn-clients';
18
19
 
19
20
  import type { DwnDiscoveryFile } from './dwn-discovery-file.js';
20
21
 
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
22
  /**
42
23
  * Controls how the agent discovers and routes to a local DWN server.
43
24
  *
44
25
  * - `'off'` — (default) skip local discovery entirely.
45
- * - `'prefer'` — probe localhost first; fall back to DID-document endpoints.
26
+ * - `'prefer'` — try local DWN first; fall back to DID-document endpoints.
46
27
  * - `'only'` — require a local server; throw if none is found.
47
28
  */
48
29
  export type LocalDwnStrategy = 'prefer' | 'only' | 'off';
@@ -61,7 +42,7 @@ export function normalizeBaseUrl(url: string): string {
61
42
  * Results are cached for {@link _cacheTtlMs} milliseconds (default 10 s) to
62
43
  * avoid repeated I/O on hot paths such as sync.
63
44
  *
64
- * @example Discovery with file-based channel
45
+ * @example Discovery with file-based channel (CLI / native)
65
46
  * ```ts
66
47
  * import { DwnDiscoveryFile } from './dwn-discovery-file.js';
67
48
  *
@@ -70,7 +51,7 @@ export function normalizeBaseUrl(url: string): string {
70
51
  * const endpoint = await discovery.getEndpoint();
71
52
  * ```
72
53
  *
73
- * @example Browser: inject cached endpoint from `dwn://register` redirect
54
+ * @example Browser: inject cached endpoint from `dwn://connect` redirect
74
55
  * ```ts
75
56
  * const discovery = new LocalDwnDiscovery(rpcClient);
76
57
  * discovery.setCachedEndpoint('http://127.0.0.1:55557');
@@ -95,7 +76,14 @@ export class LocalDwnDiscovery {
95
76
  * 2. `~/.enbox/dwn.json` discovery file (if a {@link DwnDiscoveryFile}
96
77
  * was provided). The endpoint from the file is validated via
97
78
  * `GET /info` to ensure the server is still running.
98
- * 3. Sequential port probing on well-known localhost ports (fallback).
79
+ *
80
+ * If neither channel finds an endpoint, the result (`undefined`) is
81
+ * cached to avoid repeated discovery file reads on hot paths.
82
+ *
83
+ * In browser environments (where no discovery file is available), the
84
+ * endpoint must be injected externally via
85
+ * {@link setCachedEndpoint | setCachedEndpoint()} — typically after a
86
+ * `dwn://connect` redirect delivers the endpoint in the URL fragment.
99
87
  */
100
88
  public async getEndpoint(): Promise<string | undefined> {
101
89
  const now = Date.now();
@@ -103,22 +91,21 @@ export class LocalDwnDiscovery {
103
91
  return this._cachedEndpoint;
104
92
  }
105
93
 
106
- // Channel 1: file-based discovery.
94
+ // File-based discovery (CLI / native — skipped when no file is configured).
107
95
  const fileEndpoint = await this._tryDiscoveryFile();
108
96
  if (fileEndpoint !== undefined) {
109
97
  this._setCacheEntry(fileEndpoint, now);
110
98
  return fileEndpoint;
111
99
  }
112
100
 
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;
101
+ // No endpoint found. Cache the negative result to avoid repeated
102
+ // discovery file reads within the TTL window.
103
+ this._setCacheEntry(undefined, now);
104
+ return undefined;
118
105
  }
119
106
 
120
107
  /**
121
- * Inject a cached endpoint (e.g. from a `dwn://register` browser redirect
108
+ * Inject a cached endpoint (e.g. from a `dwn://connect` browser redirect
122
109
  * or from `localStorage`). The endpoint is validated via `GET /info` before
123
110
  * caching.
124
111
  *
@@ -142,7 +129,7 @@ export class LocalDwnDiscovery {
142
129
  this._cacheExpiry = 0;
143
130
  }
144
131
 
145
- // ─── Private discovery channels ────────────────────────────────
132
+ // ─── Private ──────────────────────────────────────────────────
146
133
 
147
134
  /**
148
135
  * Try the `~/.enbox/dwn.json` discovery file. Returns the endpoint if
@@ -168,24 +155,6 @@ export class LocalDwnDiscovery {
168
155
  }
169
156
  }
170
157
 
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
158
  /**
190
159
  * Call `GET /info` on the endpoint and check that
191
160
  * `serverInfo.server === '@enbox/dwn-server'`.
@@ -263,7 +263,7 @@ export class AgentPermissionsApi implements PermissionsApi {
263
263
  target : author,
264
264
  messageType : DwnInterface.RecordsWrite,
265
265
  messageParams,
266
- dataStream : new Blob([ permissionsGrantBytes ])
266
+ dataStream : new Blob([ permissionsGrantBytes as BlobPart ])
267
267
  });
268
268
 
269
269
  if (reply.status.code !== 202) {
@@ -309,7 +309,7 @@ export class AgentPermissionsApi implements PermissionsApi {
309
309
  target : author,
310
310
  messageType : DwnInterface.RecordsWrite,
311
311
  messageParams,
312
- dataStream : new Blob([ permissionRequestBytes ])
312
+ dataStream : new Blob([ permissionRequestBytes as BlobPart ])
313
313
  });
314
314
 
315
315
  if (reply.status.code !== 202) {
@@ -352,7 +352,7 @@ export class AgentPermissionsApi implements PermissionsApi {
352
352
  target : author,
353
353
  messageType : DwnInterface.RecordsWrite,
354
354
  messageParams,
355
- dataStream : new Blob([ permissionRevocationBytes ])
355
+ dataStream : new Blob([ permissionRevocationBytes as BlobPart ])
356
356
  });
357
357
 
358
358
  if (reply.status.code !== 202) {
package/src/store-data.ts CHANGED
@@ -194,7 +194,7 @@ export class DwnDataStore<TStoreObject extends Record<string, any> = Jwk> implem
194
194
  target : tenantDid,
195
195
  messageType : DwnInterface.RecordsWrite,
196
196
  messageParams : { ...this._recordProperties, ...messageParams },
197
- dataStream : new Blob([dataBytes], { type: 'application/json' }),
197
+ dataStream : new Blob([dataBytes as BlobPart], { type: 'application/json' }),
198
198
  ...(encryptionActive ? { encryption: true } : {}),
199
199
  });
200
200
 
@@ -521,7 +521,7 @@ export class SyncEngineLevel implements SyncEngine {
521
521
  try {
522
522
  // Process the message locally.
523
523
  const dataStream = this.extractDataStream(event);
524
- await this.agent.dwn.node.processMessage(did, event.message, { dataStream });
524
+ await this.agent.dwn.processRawMessage(did, event.message, { dataStream });
525
525
  } catch (error: any) {
526
526
  console.error(`SyncEngineLevel: Error processing live-pull event for ${did}`, error);
527
527
  }
@@ -75,7 +75,7 @@ export async function pullMessages({ did, dwnUrl, delegateDid, protocol, message
75
75
  const failedCids: string[] = [];
76
76
 
77
77
  for (const entry of pending) {
78
- const pullReply = await agent.dwn.node.processMessage(did, entry.message, { dataStream: entry.dataStream });
78
+ const pullReply = await agent.dwn.processRawMessage(did, entry.message, { dataStream: entry.dataStream });
79
79
  if (!syncMessageReplyIsSuccessful(pullReply)) {
80
80
  const cid = await getMessageCid(entry.message);
81
81
  failedCids.push(cid);
@@ -16,7 +16,6 @@ import { AgentDidResolverCache } from './agent-did-resolver-cache.js';
16
16
  import { AgentDwnApi } from './dwn-api.js';
17
17
  import { AgentIdentityApi } from './identity-api.js';
18
18
  import { AgentPermissionsApi } from './permissions-api.js';
19
- import { AgentSyncApi } from './sync-api.js';
20
19
  import { EnboxRpcClient } from '@enbox/dwn-clients';
21
20
  import { HdIdentityVault } from './hd-identity-vault.js';
22
21
  import { LocalKeyManager } from './local-key-manager.js';
@@ -107,6 +106,7 @@ export class PlatformAgentTestHarness {
107
106
  await this.dwnResumableTaskStore.clear();
108
107
  await this.syncStore.clear();
109
108
  await this.vaultStore.clear();
109
+ (this.agent.vault as any)['_cachedInitialized'] = undefined;
110
110
  await this.agent.permissions.clear();
111
111
  this.dwnStores.clear();
112
112
 
@@ -282,8 +282,7 @@ export class PlatformAgentTestHarness {
282
282
 
283
283
  // Instantiate Agent's Sync API using a custom LevelDB-backed store.
284
284
  const syncStore = new Level(testDataPath('SYNC_STORE'));
285
- const syncEngine = new SyncEngineLevel({ db: syncStore });
286
- const syncApi = new AgentSyncApi({ syncEngine });
285
+ const syncApi = new SyncEngineLevel({ db: syncStore });
287
286
 
288
287
  // Create EnboxPlatformAgent instance
289
288
  const agent = new agentClass({
@@ -5,10 +5,9 @@ import type { AgentDwnApi } from '../dwn-api.js';
5
5
  import type { AgentIdentityApi } from '../identity-api.js';
6
6
  import type { AgentKeyManager } from './key-manager.js';
7
7
  import type { AgentPermissionsApi } from '../permissions-api.js';
8
- import type { AgentSyncApi } from '../sync-api.js';
9
8
  import type { EnboxRpc } from '@enbox/dwn-clients';
10
9
  import type { IdentityVault } from './identity-vault.js';
11
- import type { LocalKeyManager } from '../local-key-manager.js';
10
+ import type { SyncEngine } from './sync.js';
12
11
  import type { AgentDidApi, DidInterface, DidRequest, DidResponse } from '../did-api.js';
13
12
  import type { DwnInterface, DwnResponse, ProcessDwnRequest, SendDwnRequest } from './dwn.js';
14
13
  import type { ProcessVcRequest, SendVcRequest, VcResponse } from './vc.js';
@@ -168,7 +167,7 @@ export interface EnboxPlatformAgent<TKeyManager extends AgentKeyManager = AgentK
168
167
  * The synchronization API, responsible for managing the consistency and real-time update of the
169
168
  * agent's data with the state of the distributed network.
170
169
  */
171
- sync: AgentSyncApi;
170
+ sync: SyncEngine;
172
171
 
173
172
  /**
174
173
  * An instance of {@link IdentityVault}, providing secure storage and management of an Enbox Agent's
@@ -193,14 +192,4 @@ export interface EnboxPlatformAgent<TKeyManager extends AgentKeyManager = AgentK
193
192
  * normal operation and readiness to process requests.
194
193
  */
195
194
  start(params: unknown): Promise<unknown>;
196
- }
197
-
198
- // ---------------------------------------------------------------------------
199
- // Deprecated aliases — migration aid
200
- // ---------------------------------------------------------------------------
201
-
202
- /** @deprecated Use {@link EnboxAgent} instead. Will be removed in a future version. */
203
- export type Web5Agent = EnboxAgent;
204
-
205
- /** @deprecated Use {@link EnboxPlatformAgent} instead. Will be removed in a future version. */
206
- export type Web5PlatformAgent<TKeyManager extends AgentKeyManager = LocalKeyManager> = EnboxPlatformAgent<TKeyManager>;
195
+ }
package/src/types/dwn.ts CHANGED
@@ -72,19 +72,7 @@ import {
72
72
  *
73
73
  * @see {@link https://github.com/enboxorg/dwn-spec | Enbox DWN Specification}
74
74
  */
75
- export interface DwnDidService extends DidService {
76
- /**
77
- * @deprecated Optional legacy field. Resolve encryption keys from the DID document's
78
- * `keyAgreement` verification methods instead.
79
- */
80
- enc?: string | string[];
81
-
82
- /**
83
- * @deprecated Optional legacy field. Resolve signing keys from the DID document's
84
- * `authentication` or `assertionMethod` verification methods instead.
85
- */
86
- sig?: string | string[];
87
- }
75
+ export interface DwnDidService extends DidService {}
88
76
 
89
77
  export enum DwnInterface {
90
78
  MessagesRead = DwnInterfaceName.Messages + DwnMethodName.Read,
package/src/types/sync.ts CHANGED
@@ -106,4 +106,11 @@ export interface SyncEngine {
106
106
  * @throws {Error} if the sync operation fails to stop before the timeout.
107
107
  */
108
108
  stopSync(timeout?: number): Promise<void>;
109
+
110
+ /**
111
+ * Release all resources held by the sync engine (LevelDB handles, timers,
112
+ * WebSocket subscriptions). After calling `close()`, the engine should not
113
+ * be reused.
114
+ */
115
+ close(): Promise<void>;
109
116
  }
@@ -1,180 +0,0 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- import { CryptoUtils } from '@enbox/crypto';
11
- import { DidJwk } from '@enbox/dids';
12
- import { Oidc } from './oidc.js';
13
- import { pollWithTtl } from './utils.js';
14
- import { Convert, logger } from '@enbox/common';
15
- import { DwnInterfaceName, DwnMethodName } from '@enbox/dwn-sdk-js';
16
- /**
17
- * Initiates the wallet connect process. Used when a client wants to obtain
18
- * a did from a provider.
19
- */
20
- function initClient(_a) {
21
- return __awaiter(this, arguments, void 0, function* ({ displayName, connectServerUrl, walletUri, permissionRequests, onWalletUriReady, validatePin, }) {
22
- // ephemeral client did for ECDH, signing, verification
23
- const clientDid = yield DidJwk.create();
24
- // TODO: properly implement PKCE. this implementation is lacking server side validations and more.
25
- // https://github.com/enboxorg/enbox/issues/829
26
- // Derive the code challenge based on the code verifier
27
- // const { codeChallengeBytes, codeChallengeBase64Url } =
28
- // await Oidc.generateCodeChallenge();
29
- const encryptionKey = CryptoUtils.randomBytes(32);
30
- // build callback URL to pass into the auth request
31
- const callbackEndpoint = Oidc.buildOidcUrl({
32
- baseURL: connectServerUrl,
33
- endpoint: 'callback',
34
- });
35
- // build the PAR request
36
- const request = yield Oidc.createAuthRequest({
37
- client_id: clientDid.uri,
38
- scope: 'openid did:jwk',
39
- redirect_uri: callbackEndpoint,
40
- // custom properties:
41
- // code_challenge : codeChallengeBase64Url,
42
- // code_challenge_method : 'S256',
43
- permissionRequests: permissionRequests,
44
- displayName,
45
- });
46
- // Sign the Request Object using the Client DID's signing key.
47
- const requestJwt = yield Oidc.signJwt({
48
- did: clientDid,
49
- data: request,
50
- });
51
- if (!requestJwt) {
52
- throw new Error('Unable to sign requestObject');
53
- }
54
- // Encrypt the Request Object JWT using the code challenge.
55
- const requestObjectJwe = yield Oidc.encryptAuthRequest({
56
- jwt: requestJwt,
57
- encryptionKey,
58
- });
59
- const pushedAuthorizationRequestEndpoint = Oidc.buildOidcUrl({
60
- baseURL: connectServerUrl,
61
- endpoint: 'pushedAuthorizationRequest',
62
- });
63
- const parResponse = yield fetch(pushedAuthorizationRequestEndpoint, {
64
- body: JSON.stringify({ request: requestObjectJwe }),
65
- method: 'POST',
66
- headers: {
67
- 'Content-Type': 'application/json',
68
- },
69
- signal: AbortSignal.timeout(30000),
70
- });
71
- if (!parResponse.ok) {
72
- throw new Error(`${parResponse.status}: ${parResponse.statusText}`);
73
- }
74
- const parData = yield parResponse.json();
75
- // a deeplink to a compatible wallet. if the wallet scans this link it should receive
76
- // a route to its Connect provider flow and the params of where to fetch the auth request.
77
- logger.log(`Wallet URI: ${walletUri}`);
78
- const generatedWalletUri = new URL(walletUri);
79
- generatedWalletUri.searchParams.set('request_uri', parData.request_uri);
80
- generatedWalletUri.searchParams.set('encryption_key', Convert.uint8Array(encryptionKey).toBase64Url());
81
- // call user's callback so they can send the URI to the wallet as they see fit
82
- onWalletUriReady(generatedWalletUri.toString());
83
- const tokenUrl = Oidc.buildOidcUrl({
84
- baseURL: connectServerUrl,
85
- endpoint: 'token',
86
- tokenParam: request.state,
87
- });
88
- // subscribe to receiving a response from the wallet with default TTL. receive ciphertext of {@link EnboxConnectAuthResponse}
89
- const authResponse = yield pollWithTtl(() => fetch(tokenUrl, { signal: AbortSignal.timeout(30000) }));
90
- if (authResponse) {
91
- const jwe = yield (authResponse === null || authResponse === void 0 ? void 0 : authResponse.text());
92
- // get the pin from the user and use it as AAD to decrypt
93
- const pin = yield validatePin();
94
- const jwt = yield Oidc.decryptAuthResponse(clientDid, jwe, pin);
95
- const verifiedAuthResponse = (yield Oidc.verifyJwt({
96
- jwt,
97
- }));
98
- return {
99
- delegateGrants: verifiedAuthResponse.delegateGrants,
100
- delegatePortableDid: verifiedAuthResponse.delegatePortableDid,
101
- connectedDid: verifiedAuthResponse.iss,
102
- };
103
- }
104
- });
105
- }
106
- /**
107
- * Creates a set of Dwn Permission Scopes to request for a given protocol.
108
- *
109
- * If no permissions are provided, the default is to request all relevant record permissions (write, read, delete, query, subscribe).
110
- * 'configure' is not included by default, as this gives the application a lot of control over the protocol.
111
- */
112
- function createPermissionRequestForProtocol({ definition, permissions }) {
113
- const requests = [];
114
- // Add the ability to query for the specific protocol
115
- requests.push({
116
- protocol: definition.protocol,
117
- interface: DwnInterfaceName.Protocols,
118
- method: DwnMethodName.Query,
119
- });
120
- // A Messages.Read grant is a unified scope that covers MessagesRead, MessagesSync, and MessagesSubscribe.
121
- // This single grant enables sync and real-time subscriptions for the protocol.
122
- requests.push({
123
- protocol: definition.protocol,
124
- interface: DwnInterfaceName.Messages,
125
- method: DwnMethodName.Read,
126
- });
127
- // We also request any additional permissions the user has requested for this protocol
128
- for (const permission of permissions) {
129
- switch (permission) {
130
- case 'write':
131
- requests.push({
132
- protocol: definition.protocol,
133
- interface: DwnInterfaceName.Records,
134
- method: DwnMethodName.Write,
135
- });
136
- break;
137
- case 'read':
138
- requests.push({
139
- protocol: definition.protocol,
140
- interface: DwnInterfaceName.Records,
141
- method: DwnMethodName.Read,
142
- });
143
- break;
144
- case 'delete':
145
- requests.push({
146
- protocol: definition.protocol,
147
- interface: DwnInterfaceName.Records,
148
- method: DwnMethodName.Delete,
149
- });
150
- break;
151
- case 'query':
152
- requests.push({
153
- protocol: definition.protocol,
154
- interface: DwnInterfaceName.Records,
155
- method: DwnMethodName.Query,
156
- });
157
- break;
158
- case 'subscribe':
159
- requests.push({
160
- protocol: definition.protocol,
161
- interface: DwnInterfaceName.Records,
162
- method: DwnMethodName.Subscribe,
163
- });
164
- break;
165
- case 'configure':
166
- requests.push({
167
- protocol: definition.protocol,
168
- interface: DwnInterfaceName.Protocols,
169
- method: DwnMethodName.Configure,
170
- });
171
- break;
172
- }
173
- }
174
- return {
175
- protocolDefinition: definition,
176
- permissionScopes: requests,
177
- };
178
- }
179
- export const WalletConnect = { initClient, createPermissionRequestForProtocol };
180
- //# sourceMappingURL=connect.js.map