@enbox/dwn-sdk-js 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (522) hide show
  1. package/README.md +4 -4
  2. package/dist/browser.mjs +3 -10
  3. package/dist/browser.mjs.map +4 -4
  4. package/dist/esm/generated/precompiled-validators.js +799 -885
  5. package/dist/esm/generated/precompiled-validators.js.map +1 -1
  6. package/dist/esm/src/core/dwn-constant.js +5 -0
  7. package/dist/esm/src/core/dwn-constant.js.map +1 -1
  8. package/dist/esm/src/core/dwn-error.js +12 -4
  9. package/dist/esm/src/core/dwn-error.js.map +1 -1
  10. package/dist/esm/src/core/grant-authorization.js +9 -18
  11. package/dist/esm/src/core/grant-authorization.js.map +1 -1
  12. package/dist/esm/src/core/message-reply.js.map +1 -1
  13. package/dist/esm/src/core/messages-grant-authorization.js +28 -45
  14. package/dist/esm/src/core/messages-grant-authorization.js.map +1 -1
  15. package/dist/esm/src/core/protocol-authorization-action.js +25 -27
  16. package/dist/esm/src/core/protocol-authorization-action.js.map +1 -1
  17. package/dist/esm/src/core/protocol-authorization-validation.js +34 -89
  18. package/dist/esm/src/core/protocol-authorization-validation.js.map +1 -1
  19. package/dist/esm/src/core/protocol-authorization.js +44 -118
  20. package/dist/esm/src/core/protocol-authorization.js.map +1 -1
  21. package/dist/esm/src/core/protocols-grant-authorization.js +5 -5
  22. package/dist/esm/src/core/protocols-grant-authorization.js.map +1 -1
  23. package/dist/esm/src/core/recording-validation-state-reader.js +84 -0
  24. package/dist/esm/src/core/recording-validation-state-reader.js.map +1 -0
  25. package/dist/esm/src/core/records-grant-authorization.js +11 -11
  26. package/dist/esm/src/core/records-grant-authorization.js.map +1 -1
  27. package/dist/esm/src/core/replication-apply.js +123 -28
  28. package/dist/esm/src/core/replication-apply.js.map +1 -1
  29. package/dist/esm/src/core/resumable-task-manager.js +5 -4
  30. package/dist/esm/src/core/resumable-task-manager.js.map +1 -1
  31. package/dist/esm/src/core/validation-state-reader.js +237 -0
  32. package/dist/esm/src/core/validation-state-reader.js.map +1 -0
  33. package/dist/esm/src/dwn.js +165 -132
  34. package/dist/esm/src/dwn.js.map +1 -1
  35. package/dist/esm/src/enums/dwn-interface-method.js +0 -1
  36. package/dist/esm/src/enums/dwn-interface-method.js.map +1 -1
  37. package/dist/esm/src/event-stream/durable-event-log.js +365 -0
  38. package/dist/esm/src/event-stream/durable-event-log.js.map +1 -0
  39. package/dist/esm/src/event-stream/event-emitter-wake-publisher.js +25 -0
  40. package/dist/esm/src/event-stream/event-emitter-wake-publisher.js.map +1 -0
  41. package/dist/esm/src/handlers/messages-query.js +159 -0
  42. package/dist/esm/src/handlers/messages-query.js.map +1 -0
  43. package/dist/esm/src/handlers/messages-read.js +5 -5
  44. package/dist/esm/src/handlers/messages-read.js.map +1 -1
  45. package/dist/esm/src/handlers/messages-subscribe.js +8 -8
  46. package/dist/esm/src/handlers/messages-subscribe.js.map +1 -1
  47. package/dist/esm/src/handlers/protocols-configure.js +30 -49
  48. package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
  49. package/dist/esm/src/handlers/protocols-query.js +1 -1
  50. package/dist/esm/src/handlers/protocols-query.js.map +1 -1
  51. package/dist/esm/src/handlers/records-count.js +20 -11
  52. package/dist/esm/src/handlers/records-count.js.map +1 -1
  53. package/dist/esm/src/handlers/records-delete.js +20 -16
  54. package/dist/esm/src/handlers/records-delete.js.map +1 -1
  55. package/dist/esm/src/handlers/records-query.js +35 -11
  56. package/dist/esm/src/handlers/records-query.js.map +1 -1
  57. package/dist/esm/src/handlers/records-read.js +52 -42
  58. package/dist/esm/src/handlers/records-read.js.map +1 -1
  59. package/dist/esm/src/handlers/records-subscribe.js +107 -11
  60. package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
  61. package/dist/esm/src/handlers/records-write.js +62 -116
  62. package/dist/esm/src/handlers/records-write.js.map +1 -1
  63. package/dist/esm/src/index.js +6 -7
  64. package/dist/esm/src/index.js.map +1 -1
  65. package/dist/esm/src/interfaces/{messages-sync.js → messages-query.js} +21 -15
  66. package/dist/esm/src/interfaces/messages-query.js.map +1 -0
  67. package/dist/esm/src/interfaces/protocols-configure.js +12 -9
  68. package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
  69. package/dist/esm/src/interfaces/protocols-query.js +3 -4
  70. package/dist/esm/src/interfaces/protocols-query.js.map +1 -1
  71. package/dist/esm/src/interfaces/records-count.js +4 -3
  72. package/dist/esm/src/interfaces/records-count.js.map +1 -1
  73. package/dist/esm/src/interfaces/records-delete.js +21 -4
  74. package/dist/esm/src/interfaces/records-delete.js.map +1 -1
  75. package/dist/esm/src/interfaces/records-query.js +4 -3
  76. package/dist/esm/src/interfaces/records-query.js.map +1 -1
  77. package/dist/esm/src/interfaces/records-read.js +3 -3
  78. package/dist/esm/src/interfaces/records-read.js.map +1 -1
  79. package/dist/esm/src/interfaces/records-subscribe.js +4 -3
  80. package/dist/esm/src/interfaces/records-subscribe.js.map +1 -1
  81. package/dist/esm/src/interfaces/records-write.js +27 -13
  82. package/dist/esm/src/interfaces/records-write.js.map +1 -1
  83. package/dist/esm/src/protocols/permissions.js +27 -34
  84. package/dist/esm/src/protocols/permissions.js.map +1 -1
  85. package/dist/esm/src/store/index-level.js +24 -9
  86. package/dist/esm/src/store/index-level.js.map +1 -1
  87. package/dist/esm/src/store/level-wrapper.js +7 -0
  88. package/dist/esm/src/store/level-wrapper.js.map +1 -1
  89. package/dist/esm/src/store/message-store-level.js +536 -42
  90. package/dist/esm/src/store/message-store-level.js.map +1 -1
  91. package/dist/esm/src/store/storage-controller.js +58 -49
  92. package/dist/esm/src/store/storage-controller.js.map +1 -1
  93. package/dist/esm/src/types/message-types.js.map +1 -1
  94. package/dist/esm/src/types/validation-state-reader.js +2 -0
  95. package/dist/esm/src/types/validation-state-reader.js.map +1 -0
  96. package/dist/esm/src/utils/messages.js +17 -0
  97. package/dist/esm/src/utils/messages.js.map +1 -1
  98. package/dist/esm/src/utils/protocol-tags.js +262 -0
  99. package/dist/esm/src/utils/protocol-tags.js.map +1 -0
  100. package/dist/esm/src/utils/record-limit-occupancy.js +244 -0
  101. package/dist/esm/src/utils/record-limit-occupancy.js.map +1 -0
  102. package/dist/esm/src/utils/records.js +50 -14
  103. package/dist/esm/src/utils/records.js.map +1 -1
  104. package/dist/esm/src/utils/replication.js +85 -0
  105. package/dist/esm/src/utils/replication.js.map +1 -0
  106. package/dist/esm/tests/core/grant-authorization.spec.js +4 -4
  107. package/dist/esm/tests/core/grant-authorization.spec.js.map +1 -1
  108. package/dist/esm/tests/core/process-message-parity.spec.js +222 -0
  109. package/dist/esm/tests/core/process-message-parity.spec.js.map +1 -0
  110. package/dist/esm/tests/core/protocol-authorization.spec.js +5 -2
  111. package/dist/esm/tests/core/protocol-authorization.spec.js.map +1 -1
  112. package/dist/esm/tests/core/records-grant-authorization.spec.js +5 -5
  113. package/dist/esm/tests/core/records-grant-authorization.spec.js.map +1 -1
  114. package/dist/esm/tests/core/replication-apply.spec.js +55 -1
  115. package/dist/esm/tests/core/replication-apply.spec.js.map +1 -1
  116. package/dist/esm/tests/core/replication-replay-property.spec.js +350 -0
  117. package/dist/esm/tests/core/replication-replay-property.spec.js.map +1 -0
  118. package/dist/esm/tests/core/validation-read-closure.spec.js +469 -0
  119. package/dist/esm/tests/core/validation-read-closure.spec.js.map +1 -0
  120. package/dist/esm/tests/core/validation-state-reader.spec.js +716 -0
  121. package/dist/esm/tests/core/validation-state-reader.spec.js.map +1 -0
  122. package/dist/esm/tests/durable-event-log.spec.js +373 -0
  123. package/dist/esm/tests/durable-event-log.spec.js.map +1 -0
  124. package/dist/esm/tests/dwn.spec.js +504 -35
  125. package/dist/esm/tests/dwn.spec.js.map +1 -1
  126. package/dist/esm/tests/features/author-delegated-grant.spec.js +9 -6
  127. package/dist/esm/tests/features/author-delegated-grant.spec.js.map +1 -1
  128. package/dist/esm/tests/features/owner-delegated-grant.spec.js +1 -4
  129. package/dist/esm/tests/features/owner-delegated-grant.spec.js.map +1 -1
  130. package/dist/esm/tests/features/owner-signature.spec.js +1 -4
  131. package/dist/esm/tests/features/owner-signature.spec.js.map +1 -1
  132. package/dist/esm/tests/features/permissions.spec.js +165 -4
  133. package/dist/esm/tests/features/permissions.spec.js.map +1 -1
  134. package/dist/esm/tests/features/protocol-composition.spec.js +8 -11
  135. package/dist/esm/tests/features/protocol-composition.spec.js.map +1 -1
  136. package/dist/esm/tests/features/protocol-create-action.spec.js +1 -4
  137. package/dist/esm/tests/features/protocol-create-action.spec.js.map +1 -1
  138. package/dist/esm/tests/features/protocol-delete-action.spec.js +3 -5
  139. package/dist/esm/tests/features/protocol-delete-action.spec.js.map +1 -1
  140. package/dist/esm/tests/features/protocol-update-action.spec.js +3 -6
  141. package/dist/esm/tests/features/protocol-update-action.spec.js.map +1 -1
  142. package/dist/esm/tests/features/records-delivery.spec.js +1 -4
  143. package/dist/esm/tests/features/records-delivery.spec.js.map +1 -1
  144. package/dist/esm/tests/features/records-immutable.spec.js +1 -4
  145. package/dist/esm/tests/features/records-immutable.spec.js.map +1 -1
  146. package/dist/esm/tests/features/records-nested-query-scope.spec.js +281 -0
  147. package/dist/esm/tests/features/records-nested-query-scope.spec.js.map +1 -0
  148. package/dist/esm/tests/features/records-prune-cross-protocol.spec.js +3 -7
  149. package/dist/esm/tests/features/records-prune-cross-protocol.spec.js.map +1 -1
  150. package/dist/esm/tests/features/records-prune.spec.js +11 -22
  151. package/dist/esm/tests/features/records-prune.spec.js.map +1 -1
  152. package/dist/esm/tests/features/records-record-limit.spec.js +441 -231
  153. package/dist/esm/tests/features/records-record-limit.spec.js.map +1 -1
  154. package/dist/esm/tests/features/records-squash.spec.js +6 -4
  155. package/dist/esm/tests/features/records-squash.spec.js.map +1 -1
  156. package/dist/esm/tests/features/records-tags.spec.js +1 -4
  157. package/dist/esm/tests/features/records-tags.spec.js.map +1 -1
  158. package/dist/esm/tests/features/resumable-tasks.spec.js +3 -5
  159. package/dist/esm/tests/features/resumable-tasks.spec.js.map +1 -1
  160. package/dist/esm/tests/fuzz/message-store.fuzz.spec.js +1 -2
  161. package/dist/esm/tests/fuzz/message-store.fuzz.spec.js.map +1 -1
  162. package/dist/esm/tests/fuzz/process-message.fuzz.spec.js +2 -4
  163. package/dist/esm/tests/fuzz/process-message.fuzz.spec.js.map +1 -1
  164. package/dist/esm/tests/fuzz/schema-validation.fuzz.spec.js +1 -1
  165. package/dist/esm/tests/fuzz/schema-validation.fuzz.spec.js.map +1 -1
  166. package/dist/esm/tests/handlers/messages-query.spec.js +246 -0
  167. package/dist/esm/tests/handlers/messages-query.spec.js.map +1 -0
  168. package/dist/esm/tests/handlers/messages-read.spec.js +2 -5
  169. package/dist/esm/tests/handlers/messages-read.spec.js.map +1 -1
  170. package/dist/esm/tests/handlers/messages-subscribe.spec.js +3 -14
  171. package/dist/esm/tests/handlers/messages-subscribe.spec.js.map +1 -1
  172. package/dist/esm/tests/handlers/protocols-configure.spec.js +27 -26
  173. package/dist/esm/tests/handlers/protocols-configure.spec.js.map +1 -1
  174. package/dist/esm/tests/handlers/protocols-query.spec.js +1 -4
  175. package/dist/esm/tests/handlers/protocols-query.spec.js.map +1 -1
  176. package/dist/esm/tests/handlers/records-count.spec.js +1 -4
  177. package/dist/esm/tests/handlers/records-count.spec.js.map +1 -1
  178. package/dist/esm/tests/handlers/records-delete.spec.js +312 -30
  179. package/dist/esm/tests/handlers/records-delete.spec.js.map +1 -1
  180. package/dist/esm/tests/handlers/records-query.spec.js +32 -9
  181. package/dist/esm/tests/handlers/records-query.spec.js.map +1 -1
  182. package/dist/esm/tests/handlers/records-read.spec.js +4 -4
  183. package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
  184. package/dist/esm/tests/handlers/records-subscribe.spec.js +33 -14
  185. package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
  186. package/dist/esm/tests/handlers/records-write.spec.js +82 -36
  187. package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
  188. package/dist/esm/tests/interfaces/records-delete.spec.js +69 -2
  189. package/dist/esm/tests/interfaces/records-delete.spec.js.map +1 -1
  190. package/dist/esm/tests/interfaces/records-write.spec.js +4 -3
  191. package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
  192. package/dist/esm/tests/protocols/permissions.spec.js +55 -6
  193. package/dist/esm/tests/protocols/permissions.spec.js.map +1 -1
  194. package/dist/esm/tests/scenarios/aggregator.spec.js +1 -4
  195. package/dist/esm/tests/scenarios/aggregator.spec.js.map +1 -1
  196. package/dist/esm/tests/scenarios/deleted-record.spec.js +1 -4
  197. package/dist/esm/tests/scenarios/deleted-record.spec.js.map +1 -1
  198. package/dist/esm/tests/scenarios/end-to-end-tests.spec.js +1 -4
  199. package/dist/esm/tests/scenarios/end-to-end-tests.spec.js.map +1 -1
  200. package/dist/esm/tests/scenarios/nested-roles.spec.js +1 -4
  201. package/dist/esm/tests/scenarios/nested-roles.spec.js.map +1 -1
  202. package/dist/esm/tests/scenarios/subscriptions.spec.js +1 -4
  203. package/dist/esm/tests/scenarios/subscriptions.spec.js.map +1 -1
  204. package/dist/esm/tests/store/message-store-level.spec.js +361 -5
  205. package/dist/esm/tests/store/message-store-level.spec.js.map +1 -1
  206. package/dist/esm/tests/store/message-store.spec.js +60 -0
  207. package/dist/esm/tests/store/message-store.spec.js.map +1 -1
  208. package/dist/esm/tests/test-event-stream.js +7 -3
  209. package/dist/esm/tests/test-event-stream.js.map +1 -1
  210. package/dist/esm/tests/test-stores.js +19 -9
  211. package/dist/esm/tests/test-stores.js.map +1 -1
  212. package/dist/esm/tests/test-suite.js +4 -2
  213. package/dist/esm/tests/test-suite.js.map +1 -1
  214. package/dist/esm/tests/utils/protocol-tags.spec.js +96 -0
  215. package/dist/esm/tests/utils/protocol-tags.spec.js.map +1 -0
  216. package/dist/esm/tests/utils/test-data-generator.js +25 -0
  217. package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
  218. package/dist/esm/tests/utils/test-stub-generator.js.map +1 -1
  219. package/dist/esm/tests/utils/test-validation-state-reader.js +16 -0
  220. package/dist/esm/tests/utils/test-validation-state-reader.js.map +1 -0
  221. package/dist/types/generated/precompiled-validators.d.ts +6 -6
  222. package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
  223. package/dist/types/src/core/core-protocol.d.ts +3 -3
  224. package/dist/types/src/core/core-protocol.d.ts.map +1 -1
  225. package/dist/types/src/core/dwn-constant.d.ts +5 -0
  226. package/dist/types/src/core/dwn-constant.d.ts.map +1 -1
  227. package/dist/types/src/core/dwn-error.d.ts +12 -4
  228. package/dist/types/src/core/dwn-error.d.ts.map +1 -1
  229. package/dist/types/src/core/grant-authorization.d.ts +5 -5
  230. package/dist/types/src/core/grant-authorization.d.ts.map +1 -1
  231. package/dist/types/src/core/message-reply.d.ts +5 -4
  232. package/dist/types/src/core/message-reply.d.ts.map +1 -1
  233. package/dist/types/src/core/messages-grant-authorization.d.ts +12 -14
  234. package/dist/types/src/core/messages-grant-authorization.d.ts.map +1 -1
  235. package/dist/types/src/core/protocol-authorization-action.d.ts +4 -5
  236. package/dist/types/src/core/protocol-authorization-action.d.ts.map +1 -1
  237. package/dist/types/src/core/protocol-authorization-validation.d.ts +14 -17
  238. package/dist/types/src/core/protocol-authorization-validation.d.ts.map +1 -1
  239. package/dist/types/src/core/protocol-authorization.d.ts +8 -33
  240. package/dist/types/src/core/protocol-authorization.d.ts.map +1 -1
  241. package/dist/types/src/core/protocols-grant-authorization.d.ts +4 -4
  242. package/dist/types/src/core/protocols-grant-authorization.d.ts.map +1 -1
  243. package/dist/types/src/core/recording-validation-state-reader.d.ts +75 -0
  244. package/dist/types/src/core/recording-validation-state-reader.d.ts.map +1 -0
  245. package/dist/types/src/core/records-grant-authorization.d.ts +8 -8
  246. package/dist/types/src/core/records-grant-authorization.d.ts.map +1 -1
  247. package/dist/types/src/core/replication-apply.d.ts +36 -0
  248. package/dist/types/src/core/replication-apply.d.ts.map +1 -1
  249. package/dist/types/src/core/resumable-task-manager.d.ts +1 -1
  250. package/dist/types/src/core/resumable-task-manager.d.ts.map +1 -1
  251. package/dist/types/src/core/validation-state-reader.d.ts +79 -0
  252. package/dist/types/src/core/validation-state-reader.d.ts.map +1 -0
  253. package/dist/types/src/dwn.d.ts +33 -20
  254. package/dist/types/src/dwn.d.ts.map +1 -1
  255. package/dist/types/src/enums/dwn-interface-method.d.ts +0 -1
  256. package/dist/types/src/enums/dwn-interface-method.d.ts.map +1 -1
  257. package/dist/types/src/event-stream/durable-event-log.d.ts +69 -0
  258. package/dist/types/src/event-stream/durable-event-log.d.ts.map +1 -0
  259. package/dist/types/src/event-stream/event-emitter-wake-publisher.d.ts +13 -0
  260. package/dist/types/src/event-stream/event-emitter-wake-publisher.d.ts.map +1 -0
  261. package/dist/types/src/handlers/messages-query.d.ts +20 -0
  262. package/dist/types/src/handlers/messages-query.d.ts.map +1 -0
  263. package/dist/types/src/handlers/messages-read.d.ts +1 -1
  264. package/dist/types/src/handlers/messages-read.d.ts.map +1 -1
  265. package/dist/types/src/handlers/messages-subscribe.d.ts.map +1 -1
  266. package/dist/types/src/handlers/protocols-configure.d.ts +0 -5
  267. package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
  268. package/dist/types/src/handlers/records-count.d.ts +2 -1
  269. package/dist/types/src/handlers/records-count.d.ts.map +1 -1
  270. package/dist/types/src/handlers/records-delete.d.ts +2 -2
  271. package/dist/types/src/handlers/records-delete.d.ts.map +1 -1
  272. package/dist/types/src/handlers/records-query.d.ts +1 -1
  273. package/dist/types/src/handlers/records-query.d.ts.map +1 -1
  274. package/dist/types/src/handlers/records-read.d.ts +2 -1
  275. package/dist/types/src/handlers/records-read.d.ts.map +1 -1
  276. package/dist/types/src/handlers/records-subscribe.d.ts +4 -5
  277. package/dist/types/src/handlers/records-subscribe.d.ts.map +1 -1
  278. package/dist/types/src/handlers/records-write.d.ts +3 -11
  279. package/dist/types/src/handlers/records-write.d.ts.map +1 -1
  280. package/dist/types/src/index.d.ts +14 -16
  281. package/dist/types/src/index.d.ts.map +1 -1
  282. package/dist/types/src/interfaces/messages-query.d.ts +23 -0
  283. package/dist/types/src/interfaces/messages-query.d.ts.map +1 -0
  284. package/dist/types/src/interfaces/protocols-configure.d.ts +3 -3
  285. package/dist/types/src/interfaces/protocols-configure.d.ts.map +1 -1
  286. package/dist/types/src/interfaces/protocols-query.d.ts +2 -2
  287. package/dist/types/src/interfaces/protocols-query.d.ts.map +1 -1
  288. package/dist/types/src/interfaces/records-count.d.ts +3 -3
  289. package/dist/types/src/interfaces/records-count.d.ts.map +1 -1
  290. package/dist/types/src/interfaces/records-delete.d.ts +11 -3
  291. package/dist/types/src/interfaces/records-delete.d.ts.map +1 -1
  292. package/dist/types/src/interfaces/records-query.d.ts +3 -3
  293. package/dist/types/src/interfaces/records-query.d.ts.map +1 -1
  294. package/dist/types/src/interfaces/records-read.d.ts +3 -3
  295. package/dist/types/src/interfaces/records-read.d.ts.map +1 -1
  296. package/dist/types/src/interfaces/records-subscribe.d.ts +3 -3
  297. package/dist/types/src/interfaces/records-subscribe.d.ts.map +1 -1
  298. package/dist/types/src/interfaces/records-write.d.ts +15 -7
  299. package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
  300. package/dist/types/src/protocols/permissions.d.ts +9 -12
  301. package/dist/types/src/protocols/permissions.d.ts.map +1 -1
  302. package/dist/types/src/store/index-level.d.ts +10 -1
  303. package/dist/types/src/store/index-level.d.ts.map +1 -1
  304. package/dist/types/src/store/level-wrapper.d.ts +5 -0
  305. package/dist/types/src/store/level-wrapper.d.ts.map +1 -1
  306. package/dist/types/src/store/message-store-level.d.ts +94 -14
  307. package/dist/types/src/store/message-store-level.d.ts.map +1 -1
  308. package/dist/types/src/store/storage-controller.d.ts +17 -14
  309. package/dist/types/src/store/storage-controller.d.ts.map +1 -1
  310. package/dist/types/src/types/message-store.d.ts +29 -1
  311. package/dist/types/src/types/message-store.d.ts.map +1 -1
  312. package/dist/types/src/types/message-types.d.ts +2 -0
  313. package/dist/types/src/types/message-types.d.ts.map +1 -1
  314. package/dist/types/src/types/messages-types.d.ts +21 -37
  315. package/dist/types/src/types/messages-types.d.ts.map +1 -1
  316. package/dist/types/src/types/method-handler.d.ts +2 -2
  317. package/dist/types/src/types/method-handler.d.ts.map +1 -1
  318. package/dist/types/src/types/permission-types.d.ts +1 -1
  319. package/dist/types/src/types/subscriptions.d.ts +50 -39
  320. package/dist/types/src/types/subscriptions.d.ts.map +1 -1
  321. package/dist/types/src/types/validation-state-reader.d.ts +116 -0
  322. package/dist/types/src/types/validation-state-reader.d.ts.map +1 -0
  323. package/dist/types/src/utils/messages.d.ts +10 -0
  324. package/dist/types/src/utils/messages.d.ts.map +1 -1
  325. package/dist/types/src/utils/protocol-tags.d.ts +15 -0
  326. package/dist/types/src/utils/protocol-tags.d.ts.map +1 -0
  327. package/dist/types/src/utils/record-limit-occupancy.d.ts +40 -0
  328. package/dist/types/src/utils/record-limit-occupancy.d.ts.map +1 -0
  329. package/dist/types/src/utils/records.d.ts +25 -3
  330. package/dist/types/src/utils/records.d.ts.map +1 -1
  331. package/dist/types/src/utils/replication.d.ts +22 -0
  332. package/dist/types/src/utils/replication.d.ts.map +1 -0
  333. package/dist/types/tests/core/process-message-parity.spec.d.ts +2 -0
  334. package/dist/types/tests/core/process-message-parity.spec.d.ts.map +1 -0
  335. package/dist/types/tests/core/replication-replay-property.spec.d.ts +2 -0
  336. package/dist/types/tests/core/replication-replay-property.spec.d.ts.map +1 -0
  337. package/dist/types/tests/core/validation-read-closure.spec.d.ts +2 -0
  338. package/dist/types/tests/core/validation-read-closure.spec.d.ts.map +1 -0
  339. package/dist/types/tests/core/validation-state-reader.spec.d.ts +2 -0
  340. package/dist/types/tests/core/validation-state-reader.spec.d.ts.map +1 -0
  341. package/dist/types/tests/durable-event-log.spec.d.ts +2 -0
  342. package/dist/types/tests/durable-event-log.spec.d.ts.map +1 -0
  343. package/dist/types/tests/dwn.spec.d.ts.map +1 -1
  344. package/dist/types/tests/features/author-delegated-grant.spec.d.ts.map +1 -1
  345. package/dist/types/tests/features/owner-delegated-grant.spec.d.ts.map +1 -1
  346. package/dist/types/tests/features/owner-signature.spec.d.ts.map +1 -1
  347. package/dist/types/tests/features/permissions.spec.d.ts.map +1 -1
  348. package/dist/types/tests/features/protocol-composition.spec.d.ts.map +1 -1
  349. package/dist/types/tests/features/protocol-create-action.spec.d.ts.map +1 -1
  350. package/dist/types/tests/features/protocol-delete-action.spec.d.ts.map +1 -1
  351. package/dist/types/tests/features/protocol-update-action.spec.d.ts.map +1 -1
  352. package/dist/types/tests/features/records-delivery.spec.d.ts.map +1 -1
  353. package/dist/types/tests/features/records-immutable.spec.d.ts.map +1 -1
  354. package/dist/types/tests/features/records-nested-query-scope.spec.d.ts +2 -0
  355. package/dist/types/tests/features/records-nested-query-scope.spec.d.ts.map +1 -0
  356. package/dist/types/tests/features/records-prune-cross-protocol.spec.d.ts.map +1 -1
  357. package/dist/types/tests/features/records-prune.spec.d.ts.map +1 -1
  358. package/dist/types/tests/features/records-record-limit.spec.d.ts.map +1 -1
  359. package/dist/types/tests/features/records-squash.spec.d.ts.map +1 -1
  360. package/dist/types/tests/features/records-tags.spec.d.ts.map +1 -1
  361. package/dist/types/tests/features/resumable-tasks.spec.d.ts.map +1 -1
  362. package/dist/types/tests/handlers/messages-query.spec.d.ts +2 -0
  363. package/dist/types/tests/handlers/messages-query.spec.d.ts.map +1 -0
  364. package/dist/types/tests/handlers/messages-read.spec.d.ts.map +1 -1
  365. package/dist/types/tests/handlers/messages-subscribe.spec.d.ts.map +1 -1
  366. package/dist/types/tests/handlers/protocols-configure.spec.d.ts.map +1 -1
  367. package/dist/types/tests/handlers/protocols-query.spec.d.ts.map +1 -1
  368. package/dist/types/tests/handlers/records-count.spec.d.ts.map +1 -1
  369. package/dist/types/tests/handlers/records-delete.spec.d.ts.map +1 -1
  370. package/dist/types/tests/handlers/records-query.spec.d.ts.map +1 -1
  371. package/dist/types/tests/handlers/records-read.spec.d.ts.map +1 -1
  372. package/dist/types/tests/handlers/records-subscribe.spec.d.ts.map +1 -1
  373. package/dist/types/tests/handlers/records-write.spec.d.ts.map +1 -1
  374. package/dist/types/tests/scenarios/deleted-record.spec.d.ts.map +1 -1
  375. package/dist/types/tests/scenarios/end-to-end-tests.spec.d.ts.map +1 -1
  376. package/dist/types/tests/scenarios/nested-roles.spec.d.ts.map +1 -1
  377. package/dist/types/tests/scenarios/subscriptions.spec.d.ts.map +1 -1
  378. package/dist/types/tests/store/message-store.spec.d.ts.map +1 -1
  379. package/dist/types/tests/test-event-stream.d.ts +1 -1
  380. package/dist/types/tests/test-event-stream.d.ts.map +1 -1
  381. package/dist/types/tests/test-stores.d.ts +5 -4
  382. package/dist/types/tests/test-stores.d.ts.map +1 -1
  383. package/dist/types/tests/test-suite.d.ts +1 -2
  384. package/dist/types/tests/test-suite.d.ts.map +1 -1
  385. package/dist/types/tests/utils/protocol-tags.spec.d.ts +2 -0
  386. package/dist/types/tests/utils/protocol-tags.spec.d.ts.map +1 -0
  387. package/dist/types/tests/utils/test-data-generator.d.ts +20 -1
  388. package/dist/types/tests/utils/test-data-generator.d.ts.map +1 -1
  389. package/dist/types/tests/utils/test-validation-state-reader.d.ts +15 -0
  390. package/dist/types/tests/utils/test-validation-state-reader.d.ts.map +1 -0
  391. package/package.json +2 -2
  392. package/src/core/core-protocol.ts +3 -3
  393. package/src/core/dwn-constant.ts +7 -1
  394. package/src/core/dwn-error.ts +12 -4
  395. package/src/core/grant-authorization.ts +11 -20
  396. package/src/core/message-reply.ts +6 -5
  397. package/src/core/messages-grant-authorization.ts +37 -70
  398. package/src/core/protocol-authorization-action.ts +29 -38
  399. package/src/core/protocol-authorization-validation.ts +47 -121
  400. package/src/core/protocol-authorization.ts +56 -202
  401. package/src/core/protocols-grant-authorization.ts +9 -9
  402. package/src/core/recording-validation-state-reader.ts +130 -0
  403. package/src/core/records-grant-authorization.ts +16 -16
  404. package/src/core/replication-apply.ts +172 -32
  405. package/src/core/resumable-task-manager.ts +10 -8
  406. package/src/core/validation-state-reader.ts +350 -0
  407. package/src/dwn.ts +285 -192
  408. package/src/enums/dwn-interface-method.ts +0 -1
  409. package/src/event-stream/durable-event-log.ts +509 -0
  410. package/src/event-stream/event-emitter-wake-publisher.ts +34 -0
  411. package/src/handlers/messages-query.ts +203 -0
  412. package/src/handlers/messages-read.ts +9 -10
  413. package/src/handlers/messages-subscribe.ts +12 -13
  414. package/src/handlers/protocols-configure.ts +37 -58
  415. package/src/handlers/protocols-query.ts +1 -1
  416. package/src/handlers/records-count.ts +24 -17
  417. package/src/handlers/records-delete.ts +29 -27
  418. package/src/handlers/records-query.ts +38 -17
  419. package/src/handlers/records-read.ts +63 -50
  420. package/src/handlers/records-subscribe.ts +132 -19
  421. package/src/handlers/records-write.ts +77 -168
  422. package/src/index.ts +14 -17
  423. package/src/interfaces/messages-query.ts +70 -0
  424. package/src/interfaces/protocols-configure.ts +20 -10
  425. package/src/interfaces/protocols-query.ts +4 -5
  426. package/src/interfaces/records-count.ts +9 -4
  427. package/src/interfaces/records-delete.ts +25 -5
  428. package/src/interfaces/records-query.ts +9 -4
  429. package/src/interfaces/records-read.ts +4 -4
  430. package/src/interfaces/records-subscribe.ts +9 -4
  431. package/src/interfaces/records-write.ts +41 -13
  432. package/src/protocols/permissions.ts +32 -52
  433. package/src/store/index-level.ts +30 -9
  434. package/src/store/level-wrapper.ts +9 -1
  435. package/src/store/message-store-level.ts +757 -47
  436. package/src/store/storage-controller.ts +74 -63
  437. package/src/types/message-store.ts +45 -2
  438. package/src/types/message-types.ts +3 -1
  439. package/src/types/messages-types.ts +26 -45
  440. package/src/types/method-handler.ts +3 -3
  441. package/src/types/permission-types.ts +1 -1
  442. package/src/types/subscriptions.ts +53 -42
  443. package/src/types/validation-state-reader.ts +127 -0
  444. package/src/utils/messages.ts +25 -1
  445. package/src/utils/protocol-tags.ts +366 -0
  446. package/src/utils/record-limit-occupancy.ts +377 -0
  447. package/src/utils/records.ts +69 -13
  448. package/src/utils/replication.ts +122 -0
  449. package/dist/esm/src/core/record-chain.js +0 -64
  450. package/dist/esm/src/core/record-chain.js.map +0 -1
  451. package/dist/esm/src/event-stream/event-emitter-event-log.js +0 -334
  452. package/dist/esm/src/event-stream/event-emitter-event-log.js.map +0 -1
  453. package/dist/esm/src/handlers/messages-sync.js +0 -278
  454. package/dist/esm/src/handlers/messages-sync.js.map +0 -1
  455. package/dist/esm/src/interfaces/messages-sync.js.map +0 -1
  456. package/dist/esm/src/smt/smt-store-level.js +0 -103
  457. package/dist/esm/src/smt/smt-store-level.js.map +0 -1
  458. package/dist/esm/src/smt/smt-store-memory.js +0 -41
  459. package/dist/esm/src/smt/smt-store-memory.js.map +0 -1
  460. package/dist/esm/src/smt/smt-utils.js +0 -129
  461. package/dist/esm/src/smt/smt-utils.js.map +0 -1
  462. package/dist/esm/src/smt/sparse-merkle-tree.js +0 -577
  463. package/dist/esm/src/smt/sparse-merkle-tree.js.map +0 -1
  464. package/dist/esm/src/state-index/state-index-level.js +0 -191
  465. package/dist/esm/src/state-index/state-index-level.js.map +0 -1
  466. package/dist/esm/src/types/smt-types.js +0 -5
  467. package/dist/esm/src/types/smt-types.js.map +0 -1
  468. package/dist/esm/src/types/state-index.js +0 -2
  469. package/dist/esm/src/types/state-index.js.map +0 -1
  470. package/dist/esm/tests/event-emitter-event-log.spec.js +0 -499
  471. package/dist/esm/tests/event-emitter-event-log.spec.js.map +0 -1
  472. package/dist/esm/tests/handlers/messages-sync.spec.js +0 -1088
  473. package/dist/esm/tests/handlers/messages-sync.spec.js.map +0 -1
  474. package/dist/esm/tests/smt/smt-store-level.spec.js +0 -132
  475. package/dist/esm/tests/smt/smt-store-level.spec.js.map +0 -1
  476. package/dist/esm/tests/smt/sparse-merkle-tree.spec.js +0 -732
  477. package/dist/esm/tests/smt/sparse-merkle-tree.spec.js.map +0 -1
  478. package/dist/esm/tests/state-index/state-index-level.spec.js +0 -245
  479. package/dist/esm/tests/state-index/state-index-level.spec.js.map +0 -1
  480. package/dist/types/src/core/record-chain.d.ts +0 -24
  481. package/dist/types/src/core/record-chain.d.ts.map +0 -1
  482. package/dist/types/src/event-stream/event-emitter-event-log.d.ts +0 -80
  483. package/dist/types/src/event-stream/event-emitter-event-log.d.ts.map +0 -1
  484. package/dist/types/src/handlers/messages-sync.d.ts +0 -39
  485. package/dist/types/src/handlers/messages-sync.d.ts.map +0 -1
  486. package/dist/types/src/interfaces/messages-sync.d.ts +0 -20
  487. package/dist/types/src/interfaces/messages-sync.d.ts.map +0 -1
  488. package/dist/types/src/smt/smt-store-level.d.ts +0 -32
  489. package/dist/types/src/smt/smt-store-level.d.ts.map +0 -1
  490. package/dist/types/src/smt/smt-store-memory.d.ts +0 -22
  491. package/dist/types/src/smt/smt-store-memory.d.ts.map +0 -1
  492. package/dist/types/src/smt/smt-utils.d.ts +0 -58
  493. package/dist/types/src/smt/smt-utils.d.ts.map +0 -1
  494. package/dist/types/src/smt/sparse-merkle-tree.d.ts +0 -124
  495. package/dist/types/src/smt/sparse-merkle-tree.d.ts.map +0 -1
  496. package/dist/types/src/state-index/state-index-level.d.ts +0 -83
  497. package/dist/types/src/state-index/state-index-level.d.ts.map +0 -1
  498. package/dist/types/src/types/smt-types.d.ts +0 -81
  499. package/dist/types/src/types/smt-types.d.ts.map +0 -1
  500. package/dist/types/src/types/state-index.d.ts +0 -90
  501. package/dist/types/src/types/state-index.d.ts.map +0 -1
  502. package/dist/types/tests/event-emitter-event-log.spec.d.ts +0 -2
  503. package/dist/types/tests/event-emitter-event-log.spec.d.ts.map +0 -1
  504. package/dist/types/tests/handlers/messages-sync.spec.d.ts +0 -2
  505. package/dist/types/tests/handlers/messages-sync.spec.d.ts.map +0 -1
  506. package/dist/types/tests/smt/smt-store-level.spec.d.ts +0 -2
  507. package/dist/types/tests/smt/smt-store-level.spec.d.ts.map +0 -1
  508. package/dist/types/tests/smt/sparse-merkle-tree.spec.d.ts +0 -2
  509. package/dist/types/tests/smt/sparse-merkle-tree.spec.d.ts.map +0 -1
  510. package/dist/types/tests/state-index/state-index-level.spec.d.ts +0 -2
  511. package/dist/types/tests/state-index/state-index-level.spec.d.ts.map +0 -1
  512. package/src/core/record-chain.ts +0 -99
  513. package/src/event-stream/event-emitter-event-log.ts +0 -430
  514. package/src/handlers/messages-sync.ts +0 -403
  515. package/src/interfaces/messages-sync.ts +0 -69
  516. package/src/smt/smt-store-level.ts +0 -143
  517. package/src/smt/smt-store-memory.ts +0 -53
  518. package/src/smt/smt-utils.ts +0 -149
  519. package/src/smt/sparse-merkle-tree.ts +0 -698
  520. package/src/state-index/state-index-level.ts +0 -239
  521. package/src/types/smt-types.ts +0 -95
  522. package/src/types/state-index.ts +0 -100
@@ -10,6 +10,7 @@ import { ArrayUtility } from '../../src/utils/array.js';
10
10
  import { DwnErrorCode } from '../../src/core/dwn-error.js';
11
11
  import { Message } from '../../src/core/message.js';
12
12
  import { normalizeSchemaUrl } from '../../src/utils/url.js';
13
+ import { Poller } from '../utils/poller.js';
13
14
  import { RecordsDeleteHandler } from '../../src/handlers/records-delete.js';
14
15
  import { TestDataGenerator } from '../utils/test-data-generator.js';
15
16
  import { TestEventLog } from '../test-event-stream.js';
@@ -19,13 +20,13 @@ import { Time } from '../../src/utils/time.js';
19
20
  import { DataStream, Dwn, Encoder, Jws, MessageStoreLevel, PermissionsProtocol, RecordsDelete, RecordsRead, RecordsWrite } from '../../src/index.js';
20
21
  import { DidKey, UniversalResolver } from '@enbox/dids';
21
22
  import { DwnInterfaceName, DwnMethodName } from '../../src/enums/dwn-interface-method.js';
23
+ import { createTestValidationStateReader } from '../utils/test-validation-state-reader.js';
22
24
  export function testRecordsDeleteHandler() {
23
25
  describe('RecordsDeleteHandler.handle()', () => {
24
26
  let didResolver;
25
27
  let messageStore;
26
28
  let dataStore;
27
29
  let resumableTaskStore;
28
- let stateIndex;
29
30
  let eventLog;
30
31
  let dwn;
31
32
  beforeEach(() => {
@@ -43,21 +44,19 @@ export function testRecordsDeleteHandler() {
43
44
  messageStore = stores.messageStore;
44
45
  dataStore = stores.dataStore;
45
46
  resumableTaskStore = stores.resumableTaskStore;
46
- stateIndex = stores.stateIndex;
47
47
  eventLog = TestEventLog.get();
48
- dwn = await Dwn.create({ didResolver, messageStore, dataStore, stateIndex, eventLog, resumableTaskStore });
48
+ dwn = await Dwn.create({ didResolver, messageStore, dataStore, eventLog, resumableTaskStore });
49
49
  });
50
50
  beforeEach(async () => {
51
51
  // clean up before each test rather than after so that a test does not depend on other tests to do the clean up
52
52
  await messageStore.clear();
53
53
  await dataStore.clear();
54
54
  await resumableTaskStore.clear();
55
- await stateIndex.clear();
56
55
  });
57
56
  afterAll(async () => {
58
57
  await dwn.close();
59
58
  });
60
- it('should handle RecordsDelete successfully and return 404 if deleting a deleted record', async () => {
59
+ it('should handle RecordsDelete successfully and accept a newer tombstone over a deleted record', async () => {
61
60
  const alice = await TestDataGenerator.generateDidKeyPersona();
62
61
  await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
63
62
  // insert data
@@ -83,13 +82,13 @@ export function testRecordsDeleteHandler() {
83
82
  const reply2 = await dwn.processMessage(alice.did, queryData.message);
84
83
  expect(reply2.status.code).toBe(200);
85
84
  expect(reply2.entries?.length).toBe(0);
86
- // testing deleting a deleted record
85
+ // a newer tombstone displaces the older one — one canonical winner per record
87
86
  const recordsDelete2 = await RecordsDelete.create({
88
87
  recordId: message.recordId,
89
88
  signer: Jws.createSigner(alice)
90
89
  });
91
90
  const recordsDelete2Reply = await dwn.processMessage(alice.did, recordsDelete2.message);
92
- expect(recordsDelete2Reply.status.code).toBe(404);
91
+ expect(recordsDelete2Reply.status.code).toBe(202);
93
92
  });
94
93
  it('should not affect other records or tenants with the same data', async () => {
95
94
  const alice = await TestDataGenerator.generateDidKeyPersona();
@@ -163,7 +162,7 @@ export function testRecordsDeleteHandler() {
163
162
  const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
164
163
  expect(deleteReply.status.code).toBe(404);
165
164
  });
166
- it('should be disallowed if there is a newer RecordsWrite already in the DWN ', async () => {
165
+ it('should apply a tombstone over a newer RecordsWrite (delete-wins)', async () => {
167
166
  const alice = await TestDataGenerator.generateDidKeyPersona();
168
167
  await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
169
168
  // initial write
@@ -184,19 +183,63 @@ export function testRecordsDeleteHandler() {
184
183
  // subsequent write
185
184
  const subsequentWriteReply = await dwn.processMessage(alice.did, subsequentWriteData.message, { dataStream: subsequentWriteData.dataStream });
186
185
  expect(subsequentWriteReply.status.code).toBe(202);
187
- // test that a delete with an earlier `messageTimestamp` results in a 409
186
+ // the tombstone displaces the newer write regardless of timestamp (delete-wins) so
187
+ // that replicas converge on the same terminal state no matter the arrival order
188
188
  const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
189
- expect(deleteReply.status.code).toBe(409);
190
- // ensure data still exists
189
+ expect(deleteReply.status.code).toBe(202);
190
+ // the record reads as deleted and the displaced write is gone
191
191
  const queryData = await TestDataGenerator.generateRecordsQuery({
192
192
  author: alice,
193
193
  filter: { recordId: initialWriteData.message.recordId }
194
194
  });
195
- const expectedEncodedData = Encoder.bytesToBase64Url(subsequentWriteData.dataBytes);
196
195
  const reply = await dwn.processMessage(alice.did, queryData.message);
197
196
  expect(reply.status.code).toBe(200);
198
- expect(reply.entries?.length).toBe(1);
199
- expect(reply.entries[0].encodedData).toBe(expectedEncodedData);
197
+ expect(reply.entries?.length).toBe(0);
198
+ });
199
+ it('should apply a stale prune over the record\'s newest plain tombstone (prune dominates)', async () => {
200
+ const alice = await TestDataGenerator.generateDidKeyPersona();
201
+ await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
202
+ const initialWriteData = await TestDataGenerator.generateRecordsWrite({ author: alice });
203
+ const initialWriteReply = await dwn.processMessage(alice.did, initialWriteData.message, { dataStream: initialWriteData.dataStream });
204
+ expect(initialWriteReply.status.code).toBe(202);
205
+ // generate the prune first so its timestamp is older than the tombstone admitted below
206
+ const stalePrune = await RecordsDelete.create({
207
+ recordId: initialWriteData.message.recordId,
208
+ prune: true,
209
+ signer: Jws.createSigner(alice)
210
+ });
211
+ await Time.minimalSleep();
212
+ const recordsDelete = await RecordsDelete.create({
213
+ recordId: initialWriteData.message.recordId,
214
+ signer: Jws.createSigner(alice)
215
+ });
216
+ const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
217
+ expect(deleteReply.status.code).toBe(202);
218
+ // prune dominates plain regardless of timestamp — the cascade must run on every replica
219
+ const stalePruneReply = await dwn.processMessage(alice.did, stalePrune.message);
220
+ expect(stalePruneReply.status.code).toBe(202);
221
+ });
222
+ it('should return 409 for a plain delete beaten by the record\'s newest tombstone', async () => {
223
+ const alice = await TestDataGenerator.generateDidKeyPersona();
224
+ await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
225
+ const initialWriteData = await TestDataGenerator.generateRecordsWrite({ author: alice });
226
+ const initialWriteReply = await dwn.processMessage(alice.did, initialWriteData.message, { dataStream: initialWriteData.dataStream });
227
+ expect(initialWriteReply.status.code).toBe(202);
228
+ // generate the losing delete first so its timestamp is older than the winner's
229
+ const staleDelete = await RecordsDelete.create({
230
+ recordId: initialWriteData.message.recordId,
231
+ signer: Jws.createSigner(alice)
232
+ });
233
+ await Time.minimalSleep();
234
+ const recordsDelete = await RecordsDelete.create({
235
+ recordId: initialWriteData.message.recordId,
236
+ signer: Jws.createSigner(alice)
237
+ });
238
+ const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
239
+ expect(deleteReply.status.code).toBe(202);
240
+ // same class, older timestamp: Conflict no-op, the canonical winner stands
241
+ const staleDeleteReply = await dwn.processMessage(alice.did, staleDelete.message);
242
+ expect(staleDeleteReply.status.code).toBe(409);
200
243
  });
201
244
  it('should be able to delete then rewrite the same data', async () => {
202
245
  const alice = await TestDataGenerator.generateDidKeyPersona();
@@ -670,9 +713,250 @@ export function testRecordsDeleteHandler() {
670
713
  const { messages } = await messageStore.query(alice.did, [{ schema: normalizeSchemaUrl('testSchema'), method: DwnMethodName.Delete }]);
671
714
  expect(messages.length).toBe(1);
672
715
  expect(await Message.getCid(messages[0])).toBe(deleteMessageCid);
673
- // state index
674
- const events = await stateIndex.getLeaves(alice.did, []);
675
- expect(events).toContain(deleteMessageCid);
716
+ });
717
+ describe('tombstone visibility facts', () => {
718
+ it('should construct a tombstone matching the permission shadow filter when a tagged permission record is deleted', async () => {
719
+ const alice = await TestDataGenerator.generateDidKeyPersona();
720
+ const bob = await TestDataGenerator.generateDidKeyPersona();
721
+ await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
722
+ // alice creates a permission grant scoped to a protocol — the grant record carries `tags: { protocol }`
723
+ const scopedProtocol = 'https://example.com/protocol/shadow-filter-test';
724
+ const permissionGrant = await PermissionsProtocol.createGrant({
725
+ signer: Jws.createSigner(alice),
726
+ grantedTo: bob.did,
727
+ dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }),
728
+ scope: {
729
+ interface: DwnInterfaceName.Records,
730
+ method: DwnMethodName.Write,
731
+ protocol: scopedProtocol,
732
+ }
733
+ });
734
+ const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
735
+ const grantWriteReply = await dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
736
+ expect(grantWriteReply.status.code).toBe(202);
737
+ // the permission shadow filter shape matches the live grant record
738
+ const shadowFilter = { 'protocol': PermissionsProtocol.uri, 'tag.protocol': scopedProtocol };
739
+ const { messages: liveMatches } = await messageStore.query(alice.did, [shadowFilter]);
740
+ expect(liveMatches.length).toBe(1);
741
+ // alice deletes the grant record
742
+ const recordsDelete = await RecordsDelete.create({
743
+ recordId: permissionGrant.recordsWrite.message.recordId,
744
+ signer: Jws.createSigner(alice)
745
+ });
746
+ const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
747
+ expect(deleteReply.status.code).toBe(202);
748
+ // the tombstone is now the only message matching the shadow filter:
749
+ // the retained initial write no longer indexes tags once displaced from the latest base state
750
+ const { messages: matchesAfterDelete } = await messageStore.query(alice.did, [shadowFilter]);
751
+ expect(matchesAfterDelete.length).toBe(1);
752
+ expect(await Message.getCid(matchesAfterDelete[0])).toBe(await Message.getCid(recordsDelete.message));
753
+ expect(matchesAfterDelete[0].descriptor.method).toBe(DwnMethodName.Delete);
754
+ });
755
+ it('should carry `published` and `datePublished` onto the tombstone so it matches published queries and subscriptions', async () => {
756
+ const alice = await TestDataGenerator.generateDidKeyPersona();
757
+ const datePublished = '2025-01-01T00:00:00.000000Z';
758
+ await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
759
+ // subscribe to date-published records of the test schema before any writes
760
+ const receivedEvents = [];
761
+ const subscriptionHandler = (message) => {
762
+ if (message.type === 'event') {
763
+ receivedEvents.push(message.event);
764
+ }
765
+ };
766
+ const recordsSubscribe = await TestDataGenerator.generateRecordsSubscribe({
767
+ author: alice,
768
+ filter: { schema: 'http://published-tombstone', datePublished: { from: datePublished } },
769
+ });
770
+ const subscribeReply = await dwn.processMessage(alice.did, recordsSubscribe.message, { subscriptionHandler });
771
+ expect(subscribeReply.status.code).toBe(200);
772
+ // a published and an unpublished record
773
+ const publishedWrite = await TestDataGenerator.generateRecordsWrite({
774
+ author: alice,
775
+ schema: 'http://published-tombstone',
776
+ published: true,
777
+ datePublished,
778
+ });
779
+ const publishedWriteReply = await dwn.processMessage(alice.did, publishedWrite.message, { dataStream: publishedWrite.dataStream });
780
+ expect(publishedWriteReply.status.code).toBe(202);
781
+ const unpublishedWrite = await TestDataGenerator.generateRecordsWrite({
782
+ author: alice,
783
+ schema: 'http://published-tombstone',
784
+ });
785
+ const unpublishedWriteReply = await dwn.processMessage(alice.did, unpublishedWrite.message, { dataStream: unpublishedWrite.dataStream });
786
+ expect(unpublishedWriteReply.status.code).toBe(202);
787
+ // delete both records
788
+ const publishedDelete = await RecordsDelete.create({
789
+ recordId: publishedWrite.message.recordId,
790
+ signer: Jws.createSigner(alice)
791
+ });
792
+ const publishedDeleteReply = await dwn.processMessage(alice.did, publishedDelete.message);
793
+ expect(publishedDeleteReply.status.code).toBe(202);
794
+ const unpublishedDelete = await RecordsDelete.create({
795
+ recordId: unpublishedWrite.message.recordId,
796
+ signer: Jws.createSigner(alice)
797
+ });
798
+ const unpublishedDeleteReply = await dwn.processMessage(alice.did, unpublishedDelete.message);
799
+ expect(unpublishedDeleteReply.status.code).toBe(202);
800
+ // the published record's tombstone matches a `published: true` message store filter; the unpublished one's does not
801
+ const publishedTombstoneFilter = {
802
+ method: DwnMethodName.Delete,
803
+ published: true,
804
+ datePublished,
805
+ schema: normalizeSchemaUrl('http://published-tombstone'),
806
+ };
807
+ const { messages: publishedTombstones } = await messageStore.query(alice.did, [publishedTombstoneFilter]);
808
+ expect(publishedTombstones.length).toBe(1);
809
+ expect(await Message.getCid(publishedTombstones[0])).toBe(await Message.getCid(publishedDelete.message));
810
+ // the subscription receives the published record's write and delete events only
811
+ await Poller.pollUntilSuccessOrTimeout(async () => {
812
+ expect(receivedEvents.length).toBe(2);
813
+ });
814
+ const writeEvents = receivedEvents.filter((event) => event.message.descriptor.method === DwnMethodName.Write);
815
+ const deleteEvents = receivedEvents.filter((event) => event.message.descriptor.method === DwnMethodName.Delete);
816
+ expect(writeEvents.length).toBe(1);
817
+ expect(writeEvents[0].message.recordId).toBe(publishedWrite.message.recordId);
818
+ expect(deleteEvents.length).toBe(1);
819
+ expect(deleteEvents[0].message.descriptor.recordId).toBe(publishedWrite.message.recordId);
820
+ await subscribeReply.subscription.close();
821
+ });
822
+ it('should take mutable visibility facts from the latest pre-delete write and immutable facts from the initial write', async () => {
823
+ const alice = await TestDataGenerator.generateDidKeyPersona();
824
+ const datePublished = '2025-01-02T00:00:00.000000Z';
825
+ await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
826
+ // initial write: unpublished, tagged red
827
+ const initialWriteData = await TestDataGenerator.generateRecordsWrite({
828
+ author: alice,
829
+ schema: 'http://visibility-facts',
830
+ tags: { team: 'red' },
831
+ });
832
+ const initialWriteReply = await dwn.processMessage(alice.did, initialWriteData.message, { dataStream: initialWriteData.dataStream });
833
+ expect(initialWriteReply.status.code).toBe(202);
834
+ // update: published, tagged blue
835
+ const updateWrite = await RecordsWrite.createFrom({
836
+ recordsWriteMessage: initialWriteData.message,
837
+ published: true,
838
+ datePublished,
839
+ tags: { team: 'blue' },
840
+ signer: Jws.createSigner(alice),
841
+ });
842
+ const updateReply = await dwn.processMessage(alice.did, updateWrite.message);
843
+ expect(updateReply.status.code).toBe(202);
844
+ const recordsDelete = await RecordsDelete.create({
845
+ recordId: initialWriteData.message.recordId,
846
+ signer: Jws.createSigner(alice)
847
+ });
848
+ const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
849
+ expect(deleteReply.status.code).toBe(202);
850
+ const deleteMessageCid = await Message.getCid(recordsDelete.message);
851
+ // mutable facts come from the update that was the latest write immediately before deletion
852
+ const { messages: blueMatches } = await messageStore.query(alice.did, [{ 'method': DwnMethodName.Delete, 'tag.team': 'blue' }]);
853
+ expect(blueMatches.length).toBe(1);
854
+ expect(await Message.getCid(blueMatches[0])).toBe(deleteMessageCid);
855
+ const { messages: redMatches } = await messageStore.query(alice.did, [{ 'method': DwnMethodName.Delete, 'tag.team': 'red' }]);
856
+ expect(redMatches.length).toBe(0);
857
+ // immutable facts still come from the initial write
858
+ const { messages: immutableMatches } = await messageStore.query(alice.did, [{
859
+ method: DwnMethodName.Delete,
860
+ schema: normalizeSchemaUrl('http://visibility-facts'),
861
+ dateCreated: initialWriteData.message.descriptor.dateCreated,
862
+ published: true,
863
+ datePublished,
864
+ }]);
865
+ expect(immutableMatches.length).toBe(1);
866
+ expect(await Message.getCid(immutableMatches[0])).toBe(deleteMessageCid);
867
+ });
868
+ it('should carry the existing tombstone visibility facts forward when pruning an already-deleted record', async () => {
869
+ const alice = await TestDataGenerator.generateDidKeyPersona();
870
+ const datePublished = '2025-01-03T00:00:00.000000Z';
871
+ await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
872
+ // initial write: unpublished, tagged red
873
+ const initialWriteData = await TestDataGenerator.generateRecordsWrite({
874
+ author: alice,
875
+ tags: { team: 'red' },
876
+ });
877
+ const initialWriteReply = await dwn.processMessage(alice.did, initialWriteData.message, { dataStream: initialWriteData.dataStream });
878
+ expect(initialWriteReply.status.code).toBe(202);
879
+ // update: published, tagged blue
880
+ const updateWrite = await RecordsWrite.createFrom({
881
+ recordsWriteMessage: initialWriteData.message,
882
+ published: true,
883
+ datePublished,
884
+ tags: { team: 'blue' },
885
+ signer: Jws.createSigner(alice),
886
+ });
887
+ const updateReply = await dwn.processMessage(alice.did, updateWrite.message);
888
+ expect(updateReply.status.code).toBe(202);
889
+ // plain delete: the tombstone carries the record's visibility facts
890
+ const plainDelete = await RecordsDelete.create({
891
+ recordId: initialWriteData.message.recordId,
892
+ signer: Jws.createSigner(alice)
893
+ });
894
+ const plainDeleteReply = await dwn.processMessage(alice.did, plainDelete.message);
895
+ expect(plainDeleteReply.status.code).toBe(202);
896
+ await Time.minimalSleep();
897
+ // prune of the already-deleted record: displaces the plain tombstone (prune beats plain)
898
+ const pruneDelete = await RecordsDelete.create({
899
+ recordId: initialWriteData.message.recordId,
900
+ prune: true,
901
+ signer: Jws.createSigner(alice)
902
+ });
903
+ const pruneDeleteReply = await dwn.processMessage(alice.did, pruneDelete.message);
904
+ expect(pruneDeleteReply.status.code).toBe(202);
905
+ // exactly one tombstone matches the visibility facts and it is the prune
906
+ const { messages: tombstones } = await messageStore.query(alice.did, [{
907
+ 'method': DwnMethodName.Delete,
908
+ 'tag.team': 'blue',
909
+ 'published': true,
910
+ 'datePublished': datePublished
911
+ }]);
912
+ expect(tombstones.length).toBe(1);
913
+ expect(await Message.getCid(tombstones[0])).toBe(await Message.getCid(pruneDelete.message));
914
+ expect(tombstones[0].descriptor.prune).toBe(true);
915
+ const { messages: redMatches } = await messageStore.query(alice.did, [{ 'method': DwnMethodName.Delete, 'tag.team': 'red' }]);
916
+ expect(redMatches.length).toBe(0);
917
+ });
918
+ it('should carry the displaced newer write tags and published state when a tombstone applies over it (delete-wins)', async () => {
919
+ const alice = await TestDataGenerator.generateDidKeyPersona();
920
+ const datePublished = '2025-01-04T00:00:00.000000Z';
921
+ await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
922
+ // initial write: unpublished, tagged red
923
+ const initialWriteData = await TestDataGenerator.generateRecordsWrite({
924
+ author: alice,
925
+ tags: { team: 'red' },
926
+ });
927
+ const initialWriteReply = await dwn.processMessage(alice.did, initialWriteData.message, { dataStream: initialWriteData.dataStream });
928
+ expect(initialWriteReply.status.code).toBe(202);
929
+ // create the tombstone BEFORE the update so its `messageTimestamp` is older than the update's
930
+ const recordsDelete = await RecordsDelete.create({
931
+ recordId: initialWriteData.message.recordId,
932
+ signer: Jws.createSigner(alice)
933
+ });
934
+ await Time.minimalSleep();
935
+ // newer update: published, tagged blue
936
+ const updateWrite = await RecordsWrite.createFrom({
937
+ recordsWriteMessage: initialWriteData.message,
938
+ published: true,
939
+ datePublished,
940
+ tags: { team: 'blue' },
941
+ signer: Jws.createSigner(alice),
942
+ });
943
+ const updateReply = await dwn.processMessage(alice.did, updateWrite.message);
944
+ expect(updateReply.status.code).toBe(202);
945
+ // the older tombstone still applies over the newer write (delete-wins)
946
+ const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
947
+ expect(deleteReply.status.code).toBe(202);
948
+ // tombstone visibility facts reflect the displaced newer write
949
+ const { messages: blueMatches } = await messageStore.query(alice.did, [{
950
+ 'method': DwnMethodName.Delete,
951
+ 'tag.team': 'blue',
952
+ 'published': true,
953
+ 'datePublished': datePublished
954
+ }]);
955
+ expect(blueMatches.length).toBe(1);
956
+ expect(await Message.getCid(blueMatches[0])).toBe(await Message.getCid(recordsDelete.message));
957
+ const { messages: redMatches } = await messageStore.query(alice.did, [{ 'method': DwnMethodName.Delete, 'tag.team': 'red' }]);
958
+ expect(redMatches.length).toBe(0);
959
+ });
676
960
  });
677
961
  describe('state index', () => {
678
962
  it('should include RecordsDelete event and keep initial RecordsWrite event', async () => {
@@ -687,18 +971,17 @@ export function testRecordsDeleteHandler() {
687
971
  });
688
972
  const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
689
973
  expect(deleteReply.status.code).toBe(202);
690
- // NOTE: getLeaves returns ALL messageCids (including ProtocolsConfigure), so count is 3 not 2
691
- const events = await stateIndex.getLeaves(alice.did, []);
692
- expect(events.length).toBe(3);
693
974
  const writeMessageCid = await Message.getCid(message);
694
975
  const deleteMessageCid = await Message.getCid(recordsDelete.message);
695
976
  const expectedMessageCids = new Set([writeMessageCid, deleteMessageCid]);
696
- for (const messageCid of events) {
977
+ const { messages } = await messageStore.query(alice.did, [{ recordId: message.recordId }]);
978
+ for (const storedMessage of messages) {
979
+ const messageCid = await Message.getCid(storedMessage);
697
980
  expectedMessageCids.delete(messageCid);
698
981
  }
699
982
  expect(expectedMessageCids.size).toBe(0);
700
983
  });
701
- it('should only keep first write and delete when subsequent writes happen', async () => {
984
+ it('should keep first write, latest pre-delete write, and delete when subsequent writes happen', async () => {
702
985
  const author = await TestDataGenerator.generatePersona();
703
986
  TestStubGenerator.stubDidResolver(didResolver, [author]);
704
987
  await TestDataGenerator.installDefaultTestProtocol(dwn, author);
@@ -718,14 +1001,11 @@ export function testRecordsDeleteHandler() {
718
1001
  });
719
1002
  const deleteReply = await dwn.processMessage(author.did, recordsDelete.message);
720
1003
  expect(deleteReply.status.code).toBe(202);
721
- const events = await stateIndex.getLeaves(author.did, []);
722
- expect(events.length).toBe(3);
723
- const deletedMessageCid = await Message.getCid(newWrite.message);
724
- for (const messageCid of events) {
725
- if (messageCid === deletedMessageCid) {
726
- throw new Error(`${messageCid} should not exist`);
727
- }
728
- }
1004
+ const { messages } = await messageStore.query(author.did, [{ recordId: message.recordId }]);
1005
+ expect(messages.length).toBe(3); // first write + latest pre-delete write + delete
1006
+ const retainedWriteCid = await Message.getCid(newWrite.message);
1007
+ const retainedCids = await Promise.all(messages.map((storedMessage) => Message.getCid(storedMessage)));
1008
+ expect(retainedCids).toContain(retainedWriteCid);
729
1009
  });
730
1010
  });
731
1011
  });
@@ -741,6 +1021,7 @@ export function testRecordsDeleteHandler() {
741
1021
  const resumableTaskManagerStub = sinon.createStubInstance(ResumableTaskManager);
742
1022
  const recordsDeleteHandler = new RecordsDeleteHandler({
743
1023
  didResolver, messageStore: messageStoreStub, resumableTaskManager: resumableTaskManagerStub,
1024
+ validationStateReader: createTestValidationStateReader({ messageStore: messageStoreStub }),
744
1025
  });
745
1026
  const reply = await recordsDeleteHandler.handle({ tenant, message });
746
1027
  expect(reply.status.code).toBe(401);
@@ -753,6 +1034,7 @@ export function testRecordsDeleteHandler() {
753
1034
  const resumableTaskManagerStub = sinon.createStubInstance(ResumableTaskManager);
754
1035
  const recordsDeleteHandler = new RecordsDeleteHandler({
755
1036
  didResolver, messageStore: messageStoreStub, resumableTaskManager: resumableTaskManagerStub,
1037
+ validationStateReader: createTestValidationStateReader({ messageStore: messageStoreStub }),
756
1038
  });
757
1039
  // stub the `parse()` function to throw an error
758
1040
  sinon.stub(RecordsDelete, 'parse').throws('anyError');