@enbox/dwn-sdk-js 0.3.3 → 0.3.5

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 (202) hide show
  1. package/dist/browser.mjs +8 -8
  2. package/dist/browser.mjs.map +3 -3
  3. package/dist/esm/generated/precompiled-validators.js +766 -1224
  4. package/dist/esm/generated/precompiled-validators.js.map +1 -1
  5. package/dist/esm/src/core/abstract-message.js +3 -3
  6. package/dist/esm/src/core/abstract-message.js.map +1 -1
  7. package/dist/esm/src/core/grant-authorization.js +6 -2
  8. package/dist/esm/src/core/grant-authorization.js.map +1 -1
  9. package/dist/esm/src/core/message.js +3 -3
  10. package/dist/esm/src/core/message.js.map +1 -1
  11. package/dist/esm/src/core/protocol-authorization-action.js +3 -3
  12. package/dist/esm/src/core/protocol-authorization-action.js.map +1 -1
  13. package/dist/esm/src/core/protocol-authorization-validation.js +1 -1
  14. package/dist/esm/src/core/protocol-authorization-validation.js.map +1 -1
  15. package/dist/esm/src/core/protocol-authorization.js +11 -11
  16. package/dist/esm/src/core/protocol-authorization.js.map +1 -1
  17. package/dist/esm/src/core/records-grant-authorization.js +1 -1
  18. package/dist/esm/src/core/records-grant-authorization.js.map +1 -1
  19. package/dist/esm/src/core/resumable-task-manager.js.map +1 -1
  20. package/dist/esm/src/dwn.js.map +1 -1
  21. package/dist/esm/src/event-stream/event-emitter-event-log.js +12 -12
  22. package/dist/esm/src/event-stream/event-emitter-event-log.js.map +1 -1
  23. package/dist/esm/src/handlers/messages-read.js +7 -7
  24. package/dist/esm/src/handlers/messages-read.js.map +1 -1
  25. package/dist/esm/src/handlers/messages-subscribe.js +1 -1
  26. package/dist/esm/src/handlers/messages-subscribe.js.map +1 -1
  27. package/dist/esm/src/handlers/messages-sync.js +18 -18
  28. package/dist/esm/src/handlers/messages-sync.js.map +1 -1
  29. package/dist/esm/src/handlers/protocols-configure.js +1 -1
  30. package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
  31. package/dist/esm/src/handlers/protocols-query.js.map +1 -1
  32. package/dist/esm/src/handlers/records-count.js.map +1 -1
  33. package/dist/esm/src/handlers/records-delete.js.map +1 -1
  34. package/dist/esm/src/handlers/records-query.js.map +1 -1
  35. package/dist/esm/src/handlers/records-read.js +6 -6
  36. package/dist/esm/src/handlers/records-read.js.map +1 -1
  37. package/dist/esm/src/handlers/records-subscribe.js +1 -1
  38. package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
  39. package/dist/esm/src/handlers/records-write.js +16 -16
  40. package/dist/esm/src/handlers/records-write.js.map +1 -1
  41. package/dist/esm/src/index.js +2 -2
  42. package/dist/esm/src/index.js.map +1 -1
  43. package/dist/esm/src/interfaces/protocols-configure.js +9 -9
  44. package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
  45. package/dist/esm/src/interfaces/records-delete.js.map +1 -1
  46. package/dist/esm/src/interfaces/records-write.js +8 -8
  47. package/dist/esm/src/interfaces/records-write.js.map +1 -1
  48. package/dist/esm/src/jose/jws/general/builder.js.map +1 -1
  49. package/dist/esm/src/jose/jws/general/verifier.js +30 -2
  50. package/dist/esm/src/jose/jws/general/verifier.js.map +1 -1
  51. package/dist/esm/src/protocols/permissions.js +1 -1
  52. package/dist/esm/src/protocols/permissions.js.map +1 -1
  53. package/dist/esm/src/smt/smt-store-level.js.map +1 -1
  54. package/dist/esm/src/smt/smt-store-memory.js.map +1 -1
  55. package/dist/esm/src/smt/sparse-merkle-tree.js +2 -2
  56. package/dist/esm/src/smt/sparse-merkle-tree.js.map +1 -1
  57. package/dist/esm/src/state-index/state-index-level.js.map +1 -1
  58. package/dist/esm/src/store/index-level-compound.js +10 -10
  59. package/dist/esm/src/store/index-level-compound.js.map +1 -1
  60. package/dist/esm/src/store/index-level.js +2 -2
  61. package/dist/esm/src/store/index-level.js.map +1 -1
  62. package/dist/esm/src/store/level-wrapper.js +1 -1
  63. package/dist/esm/src/store/level-wrapper.js.map +1 -1
  64. package/dist/esm/src/store/storage-controller.js +23 -10
  65. package/dist/esm/src/store/storage-controller.js.map +1 -1
  66. package/dist/esm/src/types/permission-types.js.map +1 -1
  67. package/dist/esm/src/utils/memory-cache.js.map +1 -1
  68. package/dist/esm/src/utils/messages.js +1 -1
  69. package/dist/esm/src/utils/messages.js.map +1 -1
  70. package/dist/esm/src/utils/object.js +1 -4
  71. package/dist/esm/src/utils/object.js.map +1 -1
  72. package/dist/esm/src/utils/private-key-signer.js.map +1 -1
  73. package/dist/esm/src/utils/records.js.map +1 -1
  74. package/dist/esm/tests/core/grant-authorization.spec.js +38 -0
  75. package/dist/esm/tests/core/grant-authorization.spec.js.map +1 -0
  76. package/dist/esm/tests/features/permissions.spec.js +1 -1
  77. package/dist/esm/tests/features/permissions.spec.js.map +1 -1
  78. package/dist/esm/tests/features/records-prune-cross-protocol.spec.js +422 -0
  79. package/dist/esm/tests/features/records-prune-cross-protocol.spec.js.map +1 -0
  80. package/dist/esm/tests/handlers/messages-subscribe.spec.js +3 -26
  81. package/dist/esm/tests/handlers/messages-subscribe.spec.js.map +1 -1
  82. package/dist/esm/tests/handlers/messages-sync.spec.js +3 -26
  83. package/dist/esm/tests/handlers/messages-sync.spec.js.map +1 -1
  84. package/dist/esm/tests/handlers/protocols-query.spec.js +4 -3
  85. package/dist/esm/tests/handlers/protocols-query.spec.js.map +1 -1
  86. package/dist/esm/tests/jose/jws/general.spec.js +115 -0
  87. package/dist/esm/tests/jose/jws/general.spec.js.map +1 -1
  88. package/dist/esm/tests/store/message-store.spec.js +15 -0
  89. package/dist/esm/tests/store/message-store.spec.js.map +1 -1
  90. package/dist/esm/tests/test-suite.js +2 -0
  91. package/dist/esm/tests/test-suite.js.map +1 -1
  92. package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
  93. package/dist/types/src/core/abstract-message.d.ts +4 -4
  94. package/dist/types/src/core/abstract-message.d.ts.map +1 -1
  95. package/dist/types/src/core/grant-authorization.d.ts.map +1 -1
  96. package/dist/types/src/core/resumable-task-manager.d.ts +2 -2
  97. package/dist/types/src/core/resumable-task-manager.d.ts.map +1 -1
  98. package/dist/types/src/dwn.d.ts +12 -12
  99. package/dist/types/src/dwn.d.ts.map +1 -1
  100. package/dist/types/src/event-stream/event-emitter-event-log.d.ts +5 -5
  101. package/dist/types/src/event-stream/event-emitter-event-log.d.ts.map +1 -1
  102. package/dist/types/src/handlers/messages-read.d.ts +1 -1
  103. package/dist/types/src/handlers/messages-read.d.ts.map +1 -1
  104. package/dist/types/src/handlers/messages-subscribe.d.ts +1 -1
  105. package/dist/types/src/handlers/messages-subscribe.d.ts.map +1 -1
  106. package/dist/types/src/handlers/messages-sync.d.ts +1 -1
  107. package/dist/types/src/handlers/messages-sync.d.ts.map +1 -1
  108. package/dist/types/src/handlers/protocols-configure.d.ts +1 -1
  109. package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
  110. package/dist/types/src/handlers/protocols-query.d.ts +1 -1
  111. package/dist/types/src/handlers/protocols-query.d.ts.map +1 -1
  112. package/dist/types/src/handlers/records-count.d.ts +1 -1
  113. package/dist/types/src/handlers/records-count.d.ts.map +1 -1
  114. package/dist/types/src/handlers/records-delete.d.ts +1 -1
  115. package/dist/types/src/handlers/records-delete.d.ts.map +1 -1
  116. package/dist/types/src/handlers/records-query.d.ts +1 -1
  117. package/dist/types/src/handlers/records-query.d.ts.map +1 -1
  118. package/dist/types/src/handlers/records-read.d.ts +1 -1
  119. package/dist/types/src/handlers/records-read.d.ts.map +1 -1
  120. package/dist/types/src/handlers/records-subscribe.d.ts +1 -1
  121. package/dist/types/src/handlers/records-subscribe.d.ts.map +1 -1
  122. package/dist/types/src/handlers/records-write.d.ts +1 -1
  123. package/dist/types/src/handlers/records-write.d.ts.map +1 -1
  124. package/dist/types/src/index.d.ts +5 -5
  125. package/dist/types/src/index.d.ts.map +1 -1
  126. package/dist/types/src/interfaces/records-write.d.ts +2 -2
  127. package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
  128. package/dist/types/src/jose/jws/general/builder.d.ts +1 -1
  129. package/dist/types/src/jose/jws/general/builder.d.ts.map +1 -1
  130. package/dist/types/src/jose/jws/general/verifier.d.ts +13 -0
  131. package/dist/types/src/jose/jws/general/verifier.d.ts.map +1 -1
  132. package/dist/types/src/smt/smt-store-level.d.ts +1 -1
  133. package/dist/types/src/smt/smt-store-level.d.ts.map +1 -1
  134. package/dist/types/src/smt/smt-store-memory.d.ts +1 -1
  135. package/dist/types/src/smt/smt-store-memory.d.ts.map +1 -1
  136. package/dist/types/src/smt/sparse-merkle-tree.d.ts +1 -1
  137. package/dist/types/src/smt/sparse-merkle-tree.d.ts.map +1 -1
  138. package/dist/types/src/state-index/state-index-level.d.ts +3 -3
  139. package/dist/types/src/state-index/state-index-level.d.ts.map +1 -1
  140. package/dist/types/src/store/index-level.d.ts +2 -2
  141. package/dist/types/src/store/index-level.d.ts.map +1 -1
  142. package/dist/types/src/store/storage-controller.d.ts +19 -5
  143. package/dist/types/src/store/storage-controller.d.ts.map +1 -1
  144. package/dist/types/src/types/permission-types.d.ts +3 -4
  145. package/dist/types/src/types/permission-types.d.ts.map +1 -1
  146. package/dist/types/src/utils/memory-cache.d.ts +2 -2
  147. package/dist/types/src/utils/memory-cache.d.ts.map +1 -1
  148. package/dist/types/src/utils/object.d.ts.map +1 -1
  149. package/dist/types/src/utils/private-key-signer.d.ts +2 -2
  150. package/dist/types/src/utils/private-key-signer.d.ts.map +1 -1
  151. package/dist/types/tests/core/grant-authorization.spec.d.ts +2 -0
  152. package/dist/types/tests/core/grant-authorization.spec.d.ts.map +1 -0
  153. package/dist/types/tests/features/records-prune-cross-protocol.spec.d.ts +29 -0
  154. package/dist/types/tests/features/records-prune-cross-protocol.spec.d.ts.map +1 -0
  155. package/dist/types/tests/handlers/messages-subscribe.spec.d.ts.map +1 -1
  156. package/dist/types/tests/handlers/messages-sync.spec.d.ts.map +1 -1
  157. package/dist/types/tests/handlers/protocols-query.spec.d.ts.map +1 -1
  158. package/dist/types/tests/store/message-store.spec.d.ts.map +1 -1
  159. package/dist/types/tests/test-suite.d.ts.map +1 -1
  160. package/package.json +1 -1
  161. package/src/core/abstract-message.ts +8 -8
  162. package/src/core/grant-authorization.ts +9 -2
  163. package/src/core/message.ts +3 -3
  164. package/src/core/protocol-authorization-action.ts +3 -3
  165. package/src/core/protocol-authorization-validation.ts +9 -9
  166. package/src/core/protocol-authorization.ts +24 -24
  167. package/src/core/records-grant-authorization.ts +1 -1
  168. package/src/core/resumable-task-manager.ts +2 -2
  169. package/src/dwn.ts +13 -13
  170. package/src/event-stream/event-emitter-event-log.ts +15 -15
  171. package/src/handlers/messages-read.ts +7 -7
  172. package/src/handlers/messages-subscribe.ts +2 -2
  173. package/src/handlers/messages-sync.ts +19 -19
  174. package/src/handlers/protocols-configure.ts +2 -2
  175. package/src/handlers/protocols-query.ts +1 -1
  176. package/src/handlers/records-count.ts +1 -1
  177. package/src/handlers/records-delete.ts +1 -1
  178. package/src/handlers/records-query.ts +1 -1
  179. package/src/handlers/records-read.ts +6 -6
  180. package/src/handlers/records-subscribe.ts +2 -2
  181. package/src/handlers/records-write.ts +18 -18
  182. package/src/index.ts +5 -5
  183. package/src/interfaces/protocols-configure.ts +12 -12
  184. package/src/interfaces/records-delete.ts +1 -1
  185. package/src/interfaces/records-write.ts +11 -11
  186. package/src/jose/jws/general/builder.ts +1 -1
  187. package/src/jose/jws/general/verifier.ts +44 -3
  188. package/src/protocols/permissions.ts +1 -1
  189. package/src/smt/smt-store-level.ts +1 -1
  190. package/src/smt/smt-store-memory.ts +1 -1
  191. package/src/smt/sparse-merkle-tree.ts +10 -10
  192. package/src/state-index/state-index-level.ts +3 -3
  193. package/src/store/index-level-compound.ts +11 -11
  194. package/src/store/index-level.ts +4 -4
  195. package/src/store/level-wrapper.ts +1 -1
  196. package/src/store/storage-controller.ts +31 -16
  197. package/src/types/permission-types.ts +3 -4
  198. package/src/utils/memory-cache.ts +2 -2
  199. package/src/utils/messages.ts +2 -2
  200. package/src/utils/object.ts +1 -5
  201. package/src/utils/private-key-signer.ts +2 -2
  202. package/src/utils/records.ts +1 -1
@@ -19,7 +19,7 @@ import type { Hash, SMTDiffResult, SMTInternalNode, SMTLeafNode, SMTNodeStore, S
19
19
  import { getBit, hashChildren, hashEquals, hashKey, hashLeaf, initDefaultHashes, SMT_DEPTH } from './smt-utils.js';
20
20
 
21
21
  export class SparseMerkleTree {
22
- private store: SMTNodeStore;
22
+ private readonly store: SMTNodeStore;
23
23
  private defaultHashes!: Hash[];
24
24
 
25
25
  constructor(store: SMTNodeStore) {
@@ -142,13 +142,13 @@ export class SparseMerkleTree {
142
142
  // subtree hash would be if this leaf were pushed down to the prefix depth.
143
143
  // For simplicity, if we've hit a leaf, the subtree at this prefix
144
144
  // either contains this leaf or is empty.
145
- if (node !== undefined && node.type === 'leaf') {
145
+ if (node?.type === 'leaf') {
146
146
  return this.computeSubtreeHashForLeaf(node, i, prefix);
147
147
  }
148
148
  return this.defaultHashes[prefix.length];
149
149
  }
150
150
 
151
- const internalNode = node as SMTInternalNode;
151
+ const internalNode = node;
152
152
  if (prefix[i]) {
153
153
  currentHash = internalNode.rightHash;
154
154
  } else {
@@ -186,7 +186,7 @@ export class SparseMerkleTree {
186
186
  return [];
187
187
  }
188
188
 
189
- const internalNode = node as SMTInternalNode;
189
+ const internalNode = node;
190
190
  if (prefix[i]) {
191
191
  currentHash = internalNode.rightHash;
192
192
  } else {
@@ -266,7 +266,7 @@ export class SparseMerkleTree {
266
266
  }
267
267
 
268
268
  // Internal node — recurse into the appropriate child
269
- const internalNode = node as SMTInternalNode;
269
+ const internalNode = node;
270
270
  const goRight = getBit(keyHash, depth);
271
271
 
272
272
  let newLeftHash: Hash;
@@ -405,7 +405,7 @@ export class SparseMerkleTree {
405
405
  }
406
406
 
407
407
  // Internal node — recurse into the appropriate child
408
- const internalNode = node as SMTInternalNode;
408
+ const internalNode = node;
409
409
  const goRight = getBit(keyHash, depth);
410
410
 
411
411
  let newLeftHash: Hash;
@@ -433,7 +433,7 @@ export class SparseMerkleTree {
433
433
  if (leftIsDefault || rightIsDefault) {
434
434
  const survivingHash = leftIsDefault ? newRightHash : newLeftHash;
435
435
  const survivingNode = await this.store.getNode(survivingHash);
436
- if (survivingNode !== undefined && survivingNode.type === 'leaf') {
436
+ if (survivingNode?.type === 'leaf') {
437
437
  // Collapse: remove the internal node, return the leaf hash directly
438
438
  await this.store.deleteNode(currentHash);
439
439
  return survivingHash;
@@ -477,7 +477,7 @@ export class SparseMerkleTree {
477
477
  return hashEquals(node.keyHash, keyHash);
478
478
  }
479
479
 
480
- const internalNode = node as SMTInternalNode;
480
+ const internalNode = node;
481
481
  const goRight = getBit(keyHash, depth);
482
482
 
483
483
  if (goRight) {
@@ -508,7 +508,7 @@ export class SparseMerkleTree {
508
508
  return { siblings: [], leafNode: node, depth };
509
509
  }
510
510
 
511
- const internalNode = node as SMTInternalNode;
511
+ const internalNode = node;
512
512
  const goRight = getBit(keyHash, depth);
513
513
 
514
514
  let childHash: Hash;
@@ -578,7 +578,7 @@ export class SparseMerkleTree {
578
578
  return [node.valueCid];
579
579
  }
580
580
 
581
- const internalNode = node as SMTInternalNode;
581
+ const internalNode = node;
582
582
  const leftLeaves = await this.collectLeaves(internalNode.leftHash, depth + 1);
583
583
  const rightLeaves = await this.collectLeaves(internalNode.rightHash, depth + 1);
584
584
 
@@ -28,7 +28,7 @@ export type StateIndexLevelConfig = {
28
28
  };
29
29
 
30
30
  export class StateIndexLevel implements StateIndex {
31
- private config: StateIndexLevelConfig;
31
+ private readonly config: StateIndexLevelConfig;
32
32
  private db!: LevelWrapper<string>;
33
33
 
34
34
  /**
@@ -36,13 +36,13 @@ export class StateIndexLevel implements StateIndex {
36
36
  * Stores promises to avoid race conditions when multiple concurrent operations
37
37
  * trigger lazy initialization of the same tenant's SMT.
38
38
  */
39
- private globalTrees: Map<string, Promise<SparseMerkleTree>> = new Map();
39
+ private readonly globalTrees: Map<string, Promise<SparseMerkleTree>> = new Map();
40
40
 
41
41
  /**
42
42
  * Cache of per-tenant, per-protocol SMTs. Key format: `{tenant}\x00{protocol}`
43
43
  * Stores promises to avoid race conditions (same reason as globalTrees).
44
44
  */
45
- private protocolTrees: Map<string, Promise<SparseMerkleTree>> = new Map();
45
+ private readonly protocolTrees: Map<string, Promise<SparseMerkleTree>> = new Map();
46
46
 
47
47
  constructor(config?: StateIndexLevelConfig) {
48
48
  this.config = {
@@ -203,28 +203,28 @@ export async function queryWithCompoundIndex(
203
203
  // determine the iterator bounds from the prefix
204
204
  const iteratorOptions: LevelWrapperIteratorOptions<string> = {};
205
205
 
206
- if (cursor !== undefined) {
207
- // build the full compound key for the cursor position
208
- const cursorSortEncoded = encodeValue(cursor.value);
209
- const cursorKey = prefix + cursorSortEncoded + delimiter + cursor.messageCid;
210
-
206
+ if (cursor === undefined) {
211
207
  if (sortDirection === SortDirection.Ascending) {
212
- iteratorOptions.gt = cursorKey;
213
- // upper bound: everything with this prefix (prefix + \xff is past all valid compound keys with this prefix)
208
+ iteratorOptions.gt = prefix;
214
209
  iteratorOptions.lt = prefix + '\xff';
215
210
  } else {
216
- iteratorOptions.lt = cursorKey;
211
+ // for descending without cursor, start from the end of the prefix range
217
212
  iteratorOptions.gt = prefix;
213
+ iteratorOptions.lt = prefix + '\xff';
218
214
  iteratorOptions.reverse = true;
219
215
  }
220
216
  } else {
217
+ // build the full compound key for the cursor position
218
+ const cursorSortEncoded = encodeValue(cursor.value);
219
+ const cursorKey = prefix + cursorSortEncoded + delimiter + cursor.messageCid;
220
+
221
221
  if (sortDirection === SortDirection.Ascending) {
222
- iteratorOptions.gt = prefix;
222
+ iteratorOptions.gt = cursorKey;
223
+ // upper bound: everything with this prefix (prefix + \xff is past all valid compound keys with this prefix)
223
224
  iteratorOptions.lt = prefix + '\xff';
224
225
  } else {
225
- // for descending without cursor, start from the end of the prefix range
226
+ iteratorOptions.lt = cursorKey;
226
227
  iteratorOptions.gt = prefix;
227
- iteratorOptions.lt = prefix + '\xff';
228
228
  iteratorOptions.reverse = true;
229
229
  }
230
230
  }
@@ -53,7 +53,7 @@ export interface IndexLevelOptions {
53
53
  export class IndexLevel {
54
54
  db: LevelWrapper<string>;
55
55
  config: IndexLevelConfig;
56
- private _compoundIndexes: CompoundIndexDefinition[];
56
+ private readonly _compoundIndexes: CompoundIndexDefinition[];
57
57
 
58
58
  constructor(config: IndexLevelConfig) {
59
59
  this.config = {
@@ -498,13 +498,13 @@ export class IndexLevel {
498
498
 
499
499
  const sortedValues = [...matches.values()].sort((a,b) => this.sortItems(a,b, sortProperty, sortDirection));
500
500
 
501
- const start = cursorStartingKey !== undefined ? this.findCursorStartingIndex(sortedValues, sortDirection, sortProperty, cursorStartingKey) : 0;
501
+ const start = cursorStartingKey === undefined ? 0 : this.findCursorStartingIndex(sortedValues, sortDirection, sortProperty, cursorStartingKey);
502
502
  if (start < 0) {
503
503
  // if the provided cursor does not come before any of the results, we return no results
504
504
  return [];
505
505
  }
506
506
 
507
- const end = limit !== undefined ? start + limit: undefined;
507
+ const end = limit === undefined ? undefined : start + limit;
508
508
  return sortedValues.slice(start, end);
509
509
  }
510
510
 
@@ -735,7 +735,7 @@ export class IndexLevel {
735
735
  /**
736
736
  * Joins the given values using the `\x00` (\u0000) character.
737
737
  */
738
- private static delimiter = `\x00`;
738
+ private static readonly delimiter = `\x00`;
739
739
  private static keySegmentJoin(...values: string[]): string {
740
740
  return values.join(IndexLevel.delimiter);
741
741
  }
@@ -183,7 +183,7 @@ export class LevelWrapper<V> {
183
183
  }
184
184
 
185
185
  async isEmpty(options?: LevelWrapperOptions): Promise<boolean> {
186
- for await (const _key of this.keys(options)) {
186
+ for await (const _key of this.keys(options)) { // NOSONAR — intentional single-iteration check
187
187
  return false;
188
188
  }
189
189
  return true;
@@ -30,10 +30,10 @@ export type ResumableRecordsSquashData = {
30
30
  */
31
31
  export class StorageController {
32
32
 
33
- private messageStore: MessageStore;
34
- private dataStore: DataStore;
35
- private stateIndex: StateIndex;
36
- private eventLog?: EventLog;
33
+ private readonly messageStore: MessageStore;
34
+ private readonly dataStore: DataStore;
35
+ private readonly stateIndex: StateIndex;
36
+ private readonly eventLog?: EventLog;
37
37
 
38
38
  public constructor({ messageStore, dataStore, stateIndex, eventLog }: {
39
39
  messageStore : MessageStore,
@@ -79,8 +79,13 @@ export class StorageController {
79
79
  }
80
80
 
81
81
  if (message.descriptor.prune) {
82
- // purge/hard-delete all descendent records
83
- await StorageController.purgeRecordDescendants(tenant, message.descriptor.recordId, this.messageStore, this.dataStore, this.stateIndex);
82
+ // purge/hard-delete all descendant records. Cascade is intentionally protocol-agnostic:
83
+ // `parentContextId` is a structural link, and a prune removes the whole subtree regardless
84
+ // of which protocol a descendant lives in. Cross-protocol composing children (linked via
85
+ // `$ref`/`uses`) participate in the cascade. See issue #298 for the design discussion.
86
+ await StorageController.purgeRecordDescendants(
87
+ tenant, message.descriptor.recordId, this.messageStore, this.dataStore, this.stateIndex
88
+ );
84
89
  }
85
90
 
86
91
  // delete all existing messages that are not newest, except for the initial write
@@ -131,10 +136,10 @@ export class StorageController {
131
136
  }
132
137
 
133
138
  const existing = recordIdToMessages.get(recordId);
134
- if (existing !== undefined) {
135
- existing.push(msg);
136
- } else {
139
+ if (existing === undefined) {
137
140
  recordIdToMessages.set(recordId, [msg]);
141
+ } else {
142
+ existing.push(msg);
138
143
  }
139
144
  }
140
145
 
@@ -191,7 +196,21 @@ export class StorageController {
191
196
  }
192
197
 
193
198
  /**
194
- * Purges (permanent hard-delete) all descendant's data of the given `recordId`.
199
+ * Purges (permanent hard-delete) all descendants of the given `recordId`, recursively.
200
+ *
201
+ * The cascade is intentionally protocol-agnostic: `parentContextId` is a structural link,
202
+ * so pruning a parent removes every record hanging off it regardless of which protocol a
203
+ * descendant lives in. Cross-protocol composing children (records in a different protocol
204
+ * that reference the parent via `$ref` / `uses`) are included in the cascade.
205
+ *
206
+ * Rationale (closes #298 as working-as-intended):
207
+ * - A DWN is tenant-owned storage. The tenant's prune authority extends across the whole
208
+ * subtree they rooted, regardless of which protocol a descendant declares itself under.
209
+ * - Preserving cross-protocol orphans creates a half-alive state (readable but not
210
+ * updatable, since `validateReferentialIntegrity` requires the pruned parent) that is
211
+ * worse for callers than simply cascading.
212
+ * - Same-protocol cascade is already protocol-agnostic at every hop via `parentId`,
213
+ * so treating cross-protocol boundaries differently was inconsistent.
195
214
  */
196
215
  public static async purgeRecordDescendants(
197
216
  tenant: string,
@@ -200,16 +219,15 @@ export class StorageController {
200
219
  dataStore: DataStore,
201
220
  stateIndex: StateIndex
202
221
  ): Promise<void> {
203
- const filter = {
222
+ const filter: Filter = {
204
223
  interface : DwnInterfaceName.Records,
205
- parentId : recordId
224
+ parentId : recordId,
206
225
  };
207
226
  const { messages: childMessages } = await messageStore.query(tenant, [filter]);
208
227
 
209
228
  // group the child messages by `recordId`
210
229
  const recordIdToMessagesMap = new Map<string, GenericMessage[]>();
211
230
  for (const message of childMessages) {
212
- // get the recordId
213
231
  let recordId;
214
232
  if (Records.isRecordsWrite(message)) {
215
233
  recordId = message.recordId;
@@ -225,13 +243,10 @@ export class StorageController {
225
243
  }
226
244
  }
227
245
 
228
- // purge all child's descendants first
229
246
  for (const childRecordId of recordIdToMessagesMap.keys()) {
230
- // purge the child's descendent messages first
231
247
  await StorageController.purgeRecordDescendants(tenant, childRecordId, messageStore, dataStore, stateIndex);
232
248
  }
233
249
 
234
- // then purge the child messages themselves
235
250
  for (const childRecordId of recordIdToMessagesMap.keys()) {
236
251
  await StorageController.purgeRecordMessages(tenant, recordIdToMessagesMap.get(childRecordId)!, messageStore, dataStore, stateIndex);
237
252
  }
@@ -89,13 +89,12 @@ export type ProtocolPermissionScope = {
89
89
  /**
90
90
  * Permission scope for the Messages interface.
91
91
  *
92
- * A `Read` scope is a unified scope that authorizes `MessagesRead`, `MessagesSubscribe`, and `MessagesSync` operations.
93
- * The `Subscribe` and `Sync` method values are retained for backward compatibility with existing grants but are
94
- * functionally equivalent to `Read` — new grants SHOULD use `Read` exclusively.
92
+ * `Read` is the only valid method and acts as a unified scope that authorizes
93
+ * `MessagesRead`, `MessagesSubscribe`, and `MessagesSync` operations.
95
94
  */
96
95
  export type MessagesPermissionScope = {
97
96
  interface: DwnInterfaceName.Messages;
98
- method: DwnMethodName.Read | DwnMethodName.Subscribe | DwnMethodName.Sync;
97
+ method: DwnMethodName.Read;
99
98
  protocol?: string;
100
99
  };
101
100
 
@@ -5,12 +5,12 @@ import { LRUCache } from 'lru-cache';
5
5
  * A cache using local memory.
6
6
  */
7
7
  export class MemoryCache implements Cache {
8
- private cache: LRUCache<string, any>;
8
+ private readonly cache: LRUCache<string, any>;
9
9
 
10
10
  /**
11
11
  * @param timeToLiveInSeconds time-to-live for every key-value pair set in the cache
12
12
  */
13
- public constructor (private timeToLiveInSeconds: number) {
13
+ public constructor (private readonly timeToLiveInSeconds: number) {
14
14
  this.cache = new LRUCache({
15
15
  max : 100_000,
16
16
  ttl : timeToLiveInSeconds * 1000
@@ -21,7 +21,7 @@ export class Messages {
21
21
  // normalize each filter, and only add non-empty filters to the returned array
22
22
  for (const filter of filters) {
23
23
  // normalize the protocol URL if it exists
24
- const protocol = filter.protocol !== undefined ? normalizeProtocolUrl(filter.protocol) : undefined;
24
+ const protocol = filter.protocol === undefined ? undefined : normalizeProtocolUrl(filter.protocol);
25
25
 
26
26
  const messagesFilter = {
27
27
  ...filter,
@@ -130,6 +130,6 @@ export class Messages {
130
130
  };
131
131
  }
132
132
 
133
- return filterCopy as Filter;
133
+ return filterCopy;
134
134
  }
135
135
  }
@@ -6,11 +6,7 @@ export function isEmptyObject(obj: unknown): boolean {
6
6
  return false;
7
7
  }
8
8
 
9
- for (const _ in obj) {
10
- return false;
11
- }
12
-
13
- return true;
9
+ return Object.keys(obj as object).length === 0;
14
10
  }
15
11
 
16
12
  /**
@@ -30,8 +30,8 @@ export type PrivateKeySignerOptions = {
30
30
  export class PrivateKeySigner implements MessageSigner {
31
31
  public keyId;
32
32
  public algorithm;
33
- private privateJwk: PrivateKeyJwk;
34
- private signatureAlgorithm;
33
+ private readonly privateJwk: PrivateKeyJwk;
34
+ private readonly signatureAlgorithm;
35
35
 
36
36
  public constructor(options: PrivateKeySignerOptions) {
37
37
  if (options.keyId === undefined && options.privateJwk.kid === undefined) {
@@ -375,7 +375,7 @@ export class Records {
375
375
  delete filterCopy.recipient;
376
376
  }
377
377
 
378
- return filterCopy as Filter;
378
+ return filterCopy;
379
379
  }
380
380
 
381
381
  /**