@enbox/agent 0.5.16 → 0.6.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 (43) hide show
  1. package/dist/browser.mjs +11 -11
  2. package/dist/browser.mjs.map +4 -4
  3. package/dist/esm/dwn-api.js +433 -33
  4. package/dist/esm/dwn-api.js.map +1 -1
  5. package/dist/esm/dwn-encryption.js +131 -12
  6. package/dist/esm/dwn-encryption.js.map +1 -1
  7. package/dist/esm/dwn-key-delivery.js +64 -47
  8. package/dist/esm/dwn-key-delivery.js.map +1 -1
  9. package/dist/esm/enbox-connect-protocol.js +400 -3
  10. package/dist/esm/enbox-connect-protocol.js.map +1 -1
  11. package/dist/esm/permissions-api.js +11 -1
  12. package/dist/esm/permissions-api.js.map +1 -1
  13. package/dist/esm/sync-engine-level.js +407 -6
  14. package/dist/esm/sync-engine-level.js.map +1 -1
  15. package/dist/esm/sync-messages.js +10 -3
  16. package/dist/esm/sync-messages.js.map +1 -1
  17. package/dist/types/dwn-api.d.ts +159 -0
  18. package/dist/types/dwn-api.d.ts.map +1 -1
  19. package/dist/types/dwn-encryption.d.ts +39 -2
  20. package/dist/types/dwn-encryption.d.ts.map +1 -1
  21. package/dist/types/dwn-key-delivery.d.ts +1 -9
  22. package/dist/types/dwn-key-delivery.d.ts.map +1 -1
  23. package/dist/types/enbox-connect-protocol.d.ts +166 -1
  24. package/dist/types/enbox-connect-protocol.d.ts.map +1 -1
  25. package/dist/types/permissions-api.d.ts.map +1 -1
  26. package/dist/types/sync-engine-level.d.ts +45 -1
  27. package/dist/types/sync-engine-level.d.ts.map +1 -1
  28. package/dist/types/sync-messages.d.ts +2 -2
  29. package/dist/types/sync-messages.d.ts.map +1 -1
  30. package/dist/types/types/permissions.d.ts +9 -0
  31. package/dist/types/types/permissions.d.ts.map +1 -1
  32. package/dist/types/types/sync.d.ts +70 -2
  33. package/dist/types/types/sync.d.ts.map +1 -1
  34. package/package.json +5 -4
  35. package/src/dwn-api.ts +494 -38
  36. package/src/dwn-encryption.ts +160 -11
  37. package/src/dwn-key-delivery.ts +73 -61
  38. package/src/enbox-connect-protocol.ts +575 -6
  39. package/src/permissions-api.ts +13 -1
  40. package/src/sync-engine-level.ts +368 -4
  41. package/src/sync-messages.ts +14 -5
  42. package/src/types/permissions.ts +9 -0
  43. package/src/types/sync.ts +86 -2
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/types/sync.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/types/sync.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enbox/agent",
3
- "version": "0.5.16",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "main": "./dist/esm/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -12,8 +12,9 @@
12
12
  "build": "bun run clean && bun run build:esm && bun run build:browser",
13
13
  "lint": "eslint . --max-warnings 0",
14
14
  "lint:fix": "eslint . --fix",
15
- "test:node": "bun test --timeout 10000 .spec.ts",
16
- "test:node:coverage": "bun test --timeout 10000 --coverage --coverage-reporter=text --coverage-reporter=lcov --coverage-dir=coverage .spec.ts",
15
+ "test:node": "bun test --timeout 10000 $(find tests -name '*.spec.ts' -not -path 'tests/e2e/*')",
16
+ "test:node:coverage": "bun test --timeout 10000 --coverage --coverage-reporter=text --coverage-reporter=lcov --coverage-dir=coverage $(find tests -name '*.spec.ts' -not -path 'tests/e2e/*')",
17
+ "test:e2e": "bun test --timeout 120000 tests/e2e/*.e2e.spec.ts",
17
18
  "test:browser": "bunx --bun vitest --config vitest.browser.config.ts --run",
18
19
  "test:browser:coverage": "bunx --bun vitest --config vitest.browser.config.ts --run --coverage --coverage.provider=istanbul"
19
20
  },
@@ -71,7 +72,7 @@
71
72
  },
72
73
  "dependencies": {
73
74
  "@scure/bip39": "1.2.2",
74
- "@enbox/dwn-clients": "0.2.6",
75
+ "@enbox/dwn-clients": "0.3.0",
75
76
  "@enbox/dwn-sdk-js": "0.3.2",
76
77
  "@enbox/common": "0.1.0",
77
78
  "@enbox/crypto": "0.1.0",
package/src/dwn-api.ts CHANGED
@@ -13,7 +13,6 @@ import type {
13
13
  import type { DwnSubscriptionHandler, ResubscribeFactory } from '@enbox/dwn-clients';
14
14
  import type { KeyIdentifier, PrivateKeyJwk, PublicKeyJwk } from '@enbox/crypto';
15
15
 
16
- import { TtlCache } from '@enbox/common';
17
16
  import {
18
17
  Cid,
19
18
  ContentEncryptionAlgorithm,
@@ -31,6 +30,7 @@ import {
31
30
  ResumableTaskStoreLevel,
32
31
  StateIndexLevel,
33
32
  } from '@enbox/dwn-sdk-js';
33
+ import { Convert, TtlCache } from '@enbox/common';
34
34
  import { CryptoUtils, X25519 } from '@enbox/crypto';
35
35
  import { DidDht, DidJwk, DidResolverCacheLevel, UniversalResolver } from '@enbox/dids';
36
36
 
@@ -49,6 +49,7 @@ import type {
49
49
  SendDwnRequest,
50
50
  } from './types/dwn.js';
51
51
 
52
+ import { AgentPermissionsApi } from './permissions-api.js';
52
53
  import { DwnDiscoveryFile } from './dwn-discovery-file.js';
53
54
  import { KeyDeliveryProtocolDefinition } from './store-data-protocols.js';
54
55
  import { LocalDwnDiscovery } from './local-dwn.js';
@@ -165,6 +166,55 @@ export class AgentDwnApi {
165
166
  ttl: 30 * 60 * 1000
166
167
  });
167
168
 
169
+ /**
170
+ * Delegate decryption key cache — stores scope-aware decryption keys
171
+ * delivered to delegates during the connect flow. These keys enable
172
+ * delegates to decrypt encrypted records without possessing the owner's
173
+ * root X25519 private key.
174
+ *
175
+ * Keyed by `ddk~${delegateDid}`. Each entry is an array covering all
176
+ * granted read scopes for that delegate session.
177
+ * TTL 24 hours (keys are re-populated on session restore).
178
+ */
179
+ private _delegateDecryptionKeyCache = new TtlCache<string, {
180
+ protocol: string;
181
+ scope: { kind: 'protocol' } | { kind: 'protocolPath'; protocolPath: string; match: 'exact' };
182
+ derivedPrivateKey: DerivedPrivateJwk;
183
+ }[]>({
184
+ ttl: 24 * 60 * 60 * 1000
185
+ });
186
+
187
+ /**
188
+ * Delegate context key cache — stores ProtocolContext decryption keys for
189
+ * multi-party encrypted protocols. Each key is scoped to one rootContextId.
190
+ * Keyed by `dctx~${delegateDid}~${protocol}~${rootContextId}`.
191
+ * TTL 24 hours (re-populated on session restore).
192
+ */
193
+ private _delegateContextKeyCache = new TtlCache<string, DerivedPrivateJwk>({
194
+ ttl: 24 * 60 * 60 * 1000
195
+ });
196
+
197
+ /** Tracks which context key cache entries belong to which delegate DID. */
198
+ private _delegateContextKeyCacheIndex = new Map<string, string[]>();
199
+
200
+ /**
201
+ * Explicit registry of which multi-party protocols each delegate has
202
+ * protocol-wide read-like access to. Populated at connect time (even
203
+ * when zero contexts exist) and used by postWriteKeyDelivery() to
204
+ * decide whether to deliver new context keys.
205
+ *
206
+ * Keyed by delegateDid. Each entry is a Set of protocol URIs.
207
+ * Unlike the context key cache, this registry is NOT time-limited —
208
+ * it persists for the lifetime of the session.
209
+ */
210
+ private _delegateMultiPartyProtocols = new Map<string, Set<string>>();
211
+
212
+ /**
213
+ * Optional callback invoked when post-connect context keys are delivered
214
+ * to a delegate. The auth layer sets this to persist updated keys.
215
+ */
216
+ private _onDelegateContextKeysChanged?: (delegateDid: string) => void;
217
+
168
218
  /**
169
219
  * Cache of locally-managed DIDs (agent DID + identities). Used to decide
170
220
  * whether a target DID should be routed through the local DWN server.
@@ -312,6 +362,15 @@ export class AgentDwnApi {
312
362
  return [...uniqueEndpoints];
313
363
  }
314
364
 
365
+ /**
366
+ * Returns only the DWN service endpoints from the DID document (no local
367
+ * discovery endpoint). Use this when you need to confirm that a message
368
+ * reached the owner's actual remote DWN, not just the delegate's local server.
369
+ */
370
+ public async getRemoteDwnEndpointUrls(targetDid: string): Promise<string[]> {
371
+ return getDwnServiceEndpointUrls(targetDid, this.agent.did);
372
+ }
373
+
315
374
  /** Lazily retrieves the local DWN server endpoint via discovery. */
316
375
  private async getLocalDwnEndpoint(): Promise<string | undefined> {
317
376
  // In remote mode, the endpoint is always known.
@@ -686,12 +745,19 @@ export class AgentDwnApi {
686
745
  authorDid : isExternallyAuthored ? authorDid : undefined,
687
746
  });
688
747
 
689
- if (newParticipants.size > 0) {
690
- // Derive the context key to deliver to participants
691
- const rootContextId = recordsWriteMessage.contextId?.split('/')[0]
692
- || recordsWriteMessage.contextId
693
- || recordsWriteMessage.recordId;
748
+ // Compute rootContextId for both participant and delegate delivery.
749
+ const rootContextId = recordsWriteMessage.contextId?.split('/')[0]
750
+ || recordsWriteMessage.contextId
751
+ || recordsWriteMessage.recordId;
752
+
753
+ // Determine if delegate delivery is needed: new multi-party root
754
+ // record created by the owner with active delegate sessions.
755
+ const needsDelegateDelivery = isMultiParty && isRootRecord
756
+ && !isExternallyAuthored
757
+ && this.hasEligibleDelegatesForProtocol(writeParams.protocol);
694
758
 
759
+ if (newParticipants.size > 0 || needsDelegateDelivery) {
760
+ // Derive the context key once (shared for participant + delegate delivery).
695
761
  const { keyId, keyUri } = await getEncryptionKeyInfoFn(this.agent, request.target);
696
762
  const contextDerivationPath = [
697
763
  KeyDerivationScheme.ProtocolContext,
@@ -711,36 +777,79 @@ export class AgentDwnApi {
711
777
  derivedPrivateKey : contextDerivedPrivateJwk as PrivateKeyJwk,
712
778
  };
713
779
 
714
- // Extract the author's key delivery public key from the record
715
- // so we can encrypt the contextKey directly to the external author.
716
- const authorKeyDeliveryPubKey =
717
- recordsWriteMessage.authorization?.authorKeyDeliveryPublicKey;
718
-
719
- for (const participantDid of newParticipants) {
720
- try {
721
- // Use the author's key delivery public key when delivering
722
- // to the external author; for other participants (e.g.
723
- // recipient, role holders) fall back to owner-key encryption.
724
- const recipientKey = (participantDid === authorDid && authorKeyDeliveryPubKey)
725
- ? authorKeyDeliveryPubKey
726
- : undefined;
727
-
728
- await this.writeContextKeyRecord({
729
- tenantDid : request.target,
730
- recipientDid : participantDid,
731
- contextKeyData : contextKeyPayload,
732
- sourceProtocol : writeParams.protocol,
733
- sourceContextId : rootContextId,
734
- recipientKeyDeliveryPublicKey : recipientKey,
735
- });
736
- } catch (keyDeliveryError: any) {
737
- console.warn(
738
- `AgentDwnApi: Key delivery to '${participantDid}' for context ` +
739
- `'${rootContextId}' failed: ${keyDeliveryError.message}. ` +
740
- `The participant may not be able to decrypt records in this context.`
741
- );
780
+ // --- Participant key delivery (existing) ---
781
+ if (newParticipants.size > 0) {
782
+ // Extract the author's key delivery public key from the record
783
+ // so we can encrypt the contextKey directly to the external author.
784
+ const authorKeyDeliveryPubKey =
785
+ recordsWriteMessage.authorization?.authorKeyDeliveryPublicKey;
786
+
787
+ for (const participantDid of newParticipants) {
788
+ try {
789
+ // Use the author's key delivery public key when delivering
790
+ // to the external author; for other participants (e.g.
791
+ // recipient, role holders) fall back to owner-key encryption.
792
+ const recipientKey = (participantDid === authorDid && authorKeyDeliveryPubKey)
793
+ ? authorKeyDeliveryPubKey
794
+ : undefined;
795
+
796
+ await this.writeContextKeyRecord({
797
+ tenantDid : request.target,
798
+ recipientDid : participantDid,
799
+ contextKeyData : contextKeyPayload,
800
+ sourceProtocol : writeParams.protocol,
801
+ sourceContextId : rootContextId,
802
+ recipientKeyDeliveryPublicKey : recipientKey,
803
+ });
804
+ } catch (keyDeliveryError: any) {
805
+ console.warn(
806
+ `AgentDwnApi: Key delivery to '${participantDid}' for context ` +
807
+ `'${rootContextId}' failed: ${keyDeliveryError.message}. ` +
808
+ `The participant may not be able to decrypt records in this context.`
809
+ );
810
+ }
742
811
  }
743
812
  }
813
+
814
+ // --- Post-connect delegate context key delivery (#824) ---
815
+ // Same-process: direct cache injection (fast, no network).
816
+ if (needsDelegateDelivery) {
817
+ this.deliverContextKeyToDelegates(
818
+ writeParams.protocol, rootContextId, contextKeyPayload,
819
+ );
820
+ }
821
+ }
822
+
823
+ // --- Cross-device delegate context key delivery (#826) ---
824
+ // Query grants to find ALL eligible delegates (including those on
825
+ // other agents) and write contextKey records to the DWN.
826
+ // This is separate from same-process delivery: it discovers delegates
827
+ // from the owner's DWN grants, not just in-memory caches. It must
828
+ // run even when no same-process delegates or participants exist.
829
+ if (isMultiParty && isRootRecord && !isExternallyAuthored) {
830
+ // Derive the context key if not already done above.
831
+ const { keyId: xdKeyId, keyUri: xdKeyUri } = await getEncryptionKeyInfoFn(this.agent, request.target);
832
+ const xdContextDerivationPath = [
833
+ KeyDerivationScheme.ProtocolContext,
834
+ rootContextId,
835
+ ];
836
+ const xdContextDerivedPrivateKeyBytes =
837
+ await this.agent.keyManager.derivePrivateKeyBytes({
838
+ keyUri : xdKeyUri,
839
+ derivationPath : xdContextDerivationPath,
840
+ });
841
+ const xdContextDerivedPrivateJwk =
842
+ await X25519.bytesToPrivateKey({ privateKeyBytes: xdContextDerivedPrivateKeyBytes });
843
+ const xdContextKeyPayload: DerivedPrivateJwk = {
844
+ rootKeyId : xdKeyId,
845
+ derivationScheme : KeyDerivationScheme.ProtocolContext,
846
+ derivationPath : xdContextDerivationPath,
847
+ derivedPrivateKey : xdContextDerivedPrivateJwk as PrivateKeyJwk,
848
+ };
849
+
850
+ await this.deliverContextKeyToDelegatesViaDwn(
851
+ request.target, writeParams.protocol, rootContextId, xdContextKeyPayload,
852
+ );
744
853
  }
745
854
  } catch (detectionError: any) {
746
855
  // Participant detection failure is non-fatal — the record is still stored.
@@ -1115,8 +1224,34 @@ export class AgentDwnApi {
1115
1224
  await this.getSigner(request.granteeDid) :
1116
1225
  await this.getSigner(request.author);
1117
1226
 
1227
+ // When signing as a delegate with a permissionGrantId, fetch the full
1228
+ // grant message and pass it as `delegatedGrant` so the DWN SDK correctly
1229
+ // sets `authorization.authorDelegatedGrant` and resolves the logical
1230
+ // author to the grantor (owner) rather than the signer (delegate).
1231
+ const params = { ...request.messageParams } as any;
1232
+ if (request.granteeDid && params.permissionGrantId && !params.delegatedGrant
1233
+ && isDwnRequest(request, DwnInterface.RecordsWrite)) {
1234
+ // Read as the grantee (delegate), not the owner. The delegate is
1235
+ // the grant's recipient so the permissions protocol authorizes the
1236
+ // read. The owner's signing key may not be available on the
1237
+ // delegate agent in real wallet-connect flows.
1238
+ const { reply: grantReply } = await this.processRequest({
1239
+ author : request.granteeDid,
1240
+ target : request.author,
1241
+ messageType : DwnInterface.RecordsRead,
1242
+ messageParams : { filter: { recordId: params.permissionGrantId } },
1243
+ });
1244
+ if (grantReply.status.code === 200 && grantReply.entry?.recordsWrite && grantReply.entry?.data) {
1245
+ const grantDataBytes = await DataStream.toBytes(grantReply.entry.data);
1246
+ params.delegatedGrant = {
1247
+ ...grantReply.entry.recordsWrite,
1248
+ encodedData: Convert.uint8Array(grantDataBytes).toBase64Url(),
1249
+ };
1250
+ }
1251
+ }
1252
+
1118
1253
  dwnMessage = await dwnMessageConstructor.create({
1119
- ...request.messageParams,
1254
+ ...params,
1120
1255
  signer
1121
1256
  });
1122
1257
 
@@ -1369,6 +1504,8 @@ export class AgentDwnApi {
1369
1504
  request, reply, this.agent,
1370
1505
  this._contextDerivedKeyCache,
1371
1506
  this.fetchContextKeyRecord.bind(this),
1507
+ this._delegateDecryptionKeyCache,
1508
+ this._delegateContextKeyCache,
1372
1509
  );
1373
1510
  }
1374
1511
 
@@ -1452,6 +1589,328 @@ export class AgentDwnApi {
1452
1589
  );
1453
1590
  }
1454
1591
 
1592
+ /**
1593
+ * Imports scope-aware decryption keys for delegate sessions.
1594
+ *
1595
+ * Called during the connect flow when the wallet delivers decryption keys
1596
+ * for encrypted protocols. Keys are derived only for read-like scopes
1597
+ * (Read/Query/Subscribe) — write-only delegates receive no keys.
1598
+ *
1599
+ * The keys are cached and used by `resolveKeyDecrypter()` to decrypt
1600
+ * records when the delegate does not possess the owner's root X25519
1601
+ * private key.
1602
+ *
1603
+ * @param delegateDid - The delegate DID for this session (unique per connect)
1604
+ * @param keys - Array of scope-aware decryption key entries
1605
+ */
1606
+
1607
+ /**
1608
+ * Sets a callback invoked whenever post-connect context keys are
1609
+ * delivered to a delegate. The auth layer uses this to persist
1610
+ * updated context keys so they survive restart.
1611
+ *
1612
+ * @param callback - Called with the delegateDid that received new keys.
1613
+ * Set to `undefined` to unregister.
1614
+ */
1615
+ public set onDelegateContextKeysChanged(
1616
+ callback: ((delegateDid: string) => void) | undefined,
1617
+ ) {
1618
+ this._onDelegateContextKeysChanged = callback;
1619
+ }
1620
+
1621
+ public importDelegateDecryptionKeys(
1622
+ delegateDid: string,
1623
+ keys: {
1624
+ protocol: string;
1625
+ scope: { kind: 'protocol' } | { kind: 'protocolPath'; protocolPath: string; match: 'exact' };
1626
+ derivedPrivateKey: DerivedPrivateJwk;
1627
+ }[],
1628
+ ): void {
1629
+ const cacheKey = `ddk~${delegateDid}`;
1630
+ this._delegateDecryptionKeyCache.set(cacheKey, keys);
1631
+ }
1632
+
1633
+ /**
1634
+ * Imports ProtocolContext decryption keys for multi-party encrypted protocols.
1635
+ * Each key is scoped to one rootContextId within one protocol.
1636
+ *
1637
+ * @param delegateDid - The delegate DID for this session
1638
+ * @param keys - Array of `{ protocol, contextId, derivedPrivateKey }` entries
1639
+ */
1640
+ public importDelegateContextKeys(
1641
+ delegateDid: string,
1642
+ keys: {
1643
+ protocol: string;
1644
+ contextId: string;
1645
+ derivedPrivateKey: DerivedPrivateJwk;
1646
+ }[],
1647
+ multiPartyProtocols?: string[],
1648
+ ): void {
1649
+ // Clear any previously indexed entries for this delegate first,
1650
+ // so a re-import (e.g. session restore) doesn't leave stale entries.
1651
+ const previousKeys = this._delegateContextKeyCacheIndex.get(delegateDid);
1652
+ if (previousKeys) {
1653
+ for (const ck of previousKeys) { this._delegateContextKeyCache.delete(ck); }
1654
+ }
1655
+
1656
+ const cacheKeys: string[] = [];
1657
+ for (const key of keys) {
1658
+ const ck = `dctx~${delegateDid}~${key.protocol}~${key.contextId}`;
1659
+ this._delegateContextKeyCache.set(ck, key.derivedPrivateKey);
1660
+ cacheKeys.push(ck);
1661
+ }
1662
+ this._delegateContextKeyCacheIndex.set(delegateDid, cacheKeys);
1663
+
1664
+ // Populate the explicit multi-party protocol registry.
1665
+ // Sources: explicit parameter (always wins) + protocols from delivered keys.
1666
+ const protocols = new Set<string>(multiPartyProtocols ?? []);
1667
+ for (const key of keys) { protocols.add(key.protocol); }
1668
+ if (protocols.size > 0) {
1669
+ this._delegateMultiPartyProtocols.set(delegateDid, protocols);
1670
+ } else {
1671
+ this._delegateMultiPartyProtocols.delete(delegateDid);
1672
+ }
1673
+ }
1674
+
1675
+ /**
1676
+ * Clears all delegate decryption keys (both ProtocolPath and ProtocolContext)
1677
+ * from the in-memory cache. Called on disconnect to prevent stale keys from
1678
+ * persisting across sessions.
1679
+ *
1680
+ * @param delegateDid - If provided, clears keys for that delegate session only.
1681
+ * If omitted, clears all delegate keys.
1682
+ */
1683
+ public clearDelegateDecryptionKeys(delegateDid?: string): void {
1684
+ if (delegateDid) {
1685
+ this._delegateDecryptionKeyCache.delete(`ddk~${delegateDid}`);
1686
+ // Delete only context keys belonging to this delegate.
1687
+ const cacheKeys = this._delegateContextKeyCacheIndex.get(delegateDid);
1688
+ if (cacheKeys) {
1689
+ for (const ck of cacheKeys) { this._delegateContextKeyCache.delete(ck); }
1690
+ this._delegateContextKeyCacheIndex.delete(delegateDid);
1691
+ }
1692
+ this._delegateMultiPartyProtocols.delete(delegateDid);
1693
+ } else {
1694
+ this._delegateDecryptionKeyCache.clear();
1695
+ this._delegateContextKeyCache.clear();
1696
+ this._delegateContextKeyCacheIndex.clear();
1697
+ this._delegateMultiPartyProtocols.clear();
1698
+ }
1699
+ }
1700
+
1701
+ /**
1702
+ * Exports the current set of delegate context keys for a specific delegate.
1703
+ * Returns an array of `{ protocol, contextId, derivedPrivateKey }` entries
1704
+ * suitable for serialization and persistence.
1705
+ *
1706
+ * Called by the auth layer to persist context keys (including keys delivered
1707
+ * post-connect) so they survive agent restarts.
1708
+ *
1709
+ * @param delegateDid - The delegate DID whose context keys to export
1710
+ * @returns Array of context key entries (may be empty)
1711
+ */
1712
+ public exportDelegateContextKeys(
1713
+ delegateDid: string,
1714
+ ): { protocol: string; contextId: string; derivedPrivateKey: DerivedPrivateJwk }[] {
1715
+ const cacheKeys = this._delegateContextKeyCacheIndex.get(delegateDid);
1716
+ if (!cacheKeys) { return []; }
1717
+
1718
+ const result: { protocol: string; contextId: string; derivedPrivateKey: DerivedPrivateJwk }[] = [];
1719
+ const prefix = `dctx~${delegateDid}~`;
1720
+
1721
+ for (const ck of cacheKeys) {
1722
+ const key = this._delegateContextKeyCache.get(ck);
1723
+ if (!key || !ck.startsWith(prefix)) { continue; }
1724
+
1725
+ // Parse protocol and contextId from cache key:
1726
+ // format is `dctx~<delegateDid>~<protocol>~<contextId>`
1727
+ // contextId is always the last segment; protocol is everything between.
1728
+ const rest = ck.slice(prefix.length);
1729
+ const lastTilde = rest.lastIndexOf('~');
1730
+ if (lastTilde === -1) { continue; }
1731
+
1732
+ result.push({
1733
+ protocol : rest.slice(0, lastTilde),
1734
+ contextId : rest.slice(lastTilde + 1),
1735
+ derivedPrivateKey : key,
1736
+ });
1737
+ }
1738
+
1739
+ return result;
1740
+ }
1741
+
1742
+ /**
1743
+ * Exports the registered multi-party protocol URIs for a delegate.
1744
+ * Used by the auth layer for persistence.
1745
+ */
1746
+ public exportDelegateMultiPartyProtocols(delegateDid: string): string[] {
1747
+ const protocols = this._delegateMultiPartyProtocols.get(delegateDid);
1748
+ return protocols ? [...protocols] : [];
1749
+ }
1750
+
1751
+ /**
1752
+ * Checks whether any active delegate session has context keys for the
1753
+ * given protocol. Used by `postWriteKeyDelivery()` to determine if
1754
+ * delegate delivery is needed.
1755
+ */
1756
+ private hasEligibleDelegatesForProtocol(protocol: string): boolean {
1757
+ for (const [, protocols] of this._delegateMultiPartyProtocols) {
1758
+ if (protocols.has(protocol)) {
1759
+ return true;
1760
+ }
1761
+ }
1762
+ return false;
1763
+ }
1764
+
1765
+ /**
1766
+ * Delivers a newly created multi-party context key to all active delegate
1767
+ * sessions that have existing context keys for the given protocol.
1768
+ *
1769
+ * This is same-process delivery: the context key is injected directly
1770
+ * into `_delegateContextKeyCache`. It works when the delegate cache is
1771
+ * on the same agent instance that creates the root record.
1772
+ *
1773
+ * Cross-device DWN-based delivery (where the owner's agent and the
1774
+ * delegate's agent are separate processes) is a documented follow-up.
1775
+ *
1776
+ * @param protocol - The protocol URI
1777
+ * @param rootContextId - The root context ID of the new context
1778
+ * @param contextKey - The derived context key (`DerivedPrivateJwk`)
1779
+ */
1780
+ private deliverContextKeyToDelegates(
1781
+ protocol: string,
1782
+ rootContextId: string,
1783
+ contextKey: DerivedPrivateJwk,
1784
+ ): void {
1785
+ for (const [delegateDid, protocols] of this._delegateMultiPartyProtocols) {
1786
+ if (!protocols.has(protocol)) { continue; }
1787
+
1788
+ // Skip if this delegate already has a key for this context (idempotent).
1789
+ const newCacheKey = `dctx~${delegateDid}~${protocol}~${rootContextId}`;
1790
+ if (this._delegateContextKeyCache.get(newCacheKey)) { continue; }
1791
+
1792
+ this._delegateContextKeyCache.set(newCacheKey, contextKey);
1793
+ const indexKeys = this._delegateContextKeyCacheIndex.get(delegateDid) ?? [];
1794
+ indexKeys.push(newCacheKey);
1795
+ this._delegateContextKeyCacheIndex.set(delegateDid, indexKeys);
1796
+
1797
+ // Notify the auth layer so it can persist the updated keys.
1798
+ this._onDelegateContextKeysChanged?.(delegateDid);
1799
+ }
1800
+ }
1801
+
1802
+ /**
1803
+ * Delivers a newly created multi-party context key to eligible delegates
1804
+ * by writing `contextKey` records to the owner's DWN via the key-delivery
1805
+ * protocol. This enables cross-device delivery: the delegate can later
1806
+ * fetch the record from the owner's DWN and decrypt it.
1807
+ *
1808
+ * Eligible delegates are discovered by querying the owner's DWN for
1809
+ * active permission grants with read-like scopes on the given protocol.
1810
+ *
1811
+ * The contextKey record is encrypted using the delegate's pre-derived
1812
+ * key-delivery leaf public key, which is stored in the grant's tags
1813
+ * during `submitConnectResponse()`.
1814
+ *
1815
+ * @param tenantDid - The owner's DID
1816
+ * @param protocol - The protocol URI
1817
+ * @param rootContextId - The root context ID of the new context
1818
+ * @param contextKey - The derived context key (`DerivedPrivateJwk`)
1819
+ */
1820
+ private async deliverContextKeyToDelegatesViaDwn(
1821
+ tenantDid: string,
1822
+ protocol: string,
1823
+ rootContextId: string,
1824
+ contextKey: DerivedPrivateJwk,
1825
+ ): Promise<void> {
1826
+ try {
1827
+ const permissionsApi = new AgentPermissionsApi({ agent: this.agent });
1828
+ const grants = await permissionsApi.fetchGrants({
1829
+ author : tenantDid,
1830
+ target : tenantDid,
1831
+ grantor : tenantDid,
1832
+ protocol,
1833
+ checkRevoked : true,
1834
+ });
1835
+
1836
+ const readMethods = new Set(['Read', 'Query', 'Subscribe']);
1837
+ const nowMs = Date.now();
1838
+
1839
+ // Deduplicate: one contextKey per delegate, not per grant.
1840
+ // Multiple grants (Read, Query, Subscribe) for the same delegate
1841
+ // should produce exactly one contextKey record.
1842
+ // IMPORTANT: dedup happens AFTER tag validation so that an older
1843
+ // untagged grant doesn't shadow a valid tagged grant for the same delegate.
1844
+ const deliveredDelegates = new Set<string>();
1845
+
1846
+ for (const grant of grants) {
1847
+ // Only delegated grants are eligible. Non-delegated grants (direct
1848
+ // access without a delegate session) should not trigger cross-device
1849
+ // context key delivery.
1850
+ if (!grant.grant.delegated) { continue; }
1851
+
1852
+ // Filter expired grants. fetchGrants checks revocation but does
1853
+ // NOT filter by dateExpires. Use numeric comparison for safety.
1854
+ if (new Date(grant.grant.dateExpires).getTime() <= nowMs) { continue; }
1855
+
1856
+ const scope = grant.grant.scope as any;
1857
+ if (scope.interface !== 'Records' || !readMethods.has(scope.method)) { continue; }
1858
+
1859
+ // Narrow scopes (protocolPath, contextId) are not supported for
1860
+ // multi-party delegate delivery — skip them silently.
1861
+ if (scope.protocolPath || scope.contextId) { continue; }
1862
+
1863
+ const delegateDid = grant.grant.grantee;
1864
+
1865
+ // Read the pre-derived key-delivery leaf public key from the
1866
+ // grant data payload. This was computed during submitConnectResponse()
1867
+ // and stored alongside the grant's standard fields.
1868
+ const keyDelivery = grant.grant.delegateKeyDelivery;
1869
+ if (!keyDelivery?.rootKeyId || !keyDelivery?.publicKeyJwk) {
1870
+ // Grant was created before key-delivery was supported, or
1871
+ // is not a read-like grant. Skip — do NOT dedup yet.
1872
+ continue;
1873
+ }
1874
+
1875
+ // Dedup check — skip if already delivered via an earlier grant.
1876
+ if (deliveredDelegates.has(delegateDid)) { continue; }
1877
+
1878
+ const leafPublicKeyJwk = keyDelivery.publicKeyJwk as PublicKeyJwk;
1879
+
1880
+ try {
1881
+ await this.writeContextKeyRecord({
1882
+ tenantDid,
1883
+ recipientDid : delegateDid,
1884
+ contextKeyData : contextKey,
1885
+ sourceProtocol : protocol,
1886
+ sourceContextId : rootContextId,
1887
+ recipientKeyDeliveryPublicKey : {
1888
+ rootKeyId : keyDelivery.rootKeyId,
1889
+ publicKeyJwk : leafPublicKeyJwk,
1890
+ },
1891
+ });
1892
+
1893
+ // Mark as delivered ONLY after the write succeeds. If the write
1894
+ // fails, a later valid grant for the same delegate can still try.
1895
+ deliveredDelegates.add(delegateDid);
1896
+ } catch (delegateError: any) {
1897
+ console.warn(
1898
+ `AgentDwnApi: Cross-device key delivery to delegate ` +
1899
+ `'${delegateDid}' for context '${rootContextId}' failed: ` +
1900
+ `${delegateError.message}. The delegate may need to reconnect.`
1901
+ );
1902
+ }
1903
+ }
1904
+ } catch (discoveryError: any) {
1905
+ // Grant discovery failure is non-fatal — same-process delivery may
1906
+ // still have succeeded, and sync will eventually deliver the record.
1907
+ console.warn(
1908
+ `AgentDwnApi: Delegate grant discovery for protocol ` +
1909
+ `'${protocol}' failed: ${discoveryError.message}`
1910
+ );
1911
+ }
1912
+ }
1913
+
1455
1914
  /**
1456
1915
  * Writes a `contextKey` record to the owner's DWN, delivering an encrypted
1457
1916
  * context key to a participant.
@@ -1507,9 +1966,6 @@ export class AgentDwnApi {
1507
1966
  return fetchContextKeyRecordFn(
1508
1967
  this.agent, params,
1509
1968
  this.processRequest.bind(this),
1510
- this.getSigner.bind(this),
1511
- this.sendDwnRpcRequest.bind(this),
1512
- this.getDwnEndpointUrlsForTarget.bind(this),
1513
1969
  );
1514
1970
  }
1515
1971
  }