@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
@@ -0,0 +1,377 @@
1
+ import type { MessageStore } from '../types/message-store.js';
2
+ import type { ProtocolRecordLimitDefinition } from '../types/protocols-types.js';
3
+ import type { RecordsWriteMessage } from '../types/records-types.js';
4
+ import type { ValidationStateReader } from '../types/validation-state-reader.js';
5
+ import type { Filter, PaginationCursor } from '../types/query-types.js';
6
+ import type { MessageSort, Pagination } from '../types/message-types.js';
7
+
8
+ import { FilterUtility } from './filter.js';
9
+ import { getRuleSetAtPath } from './protocols.js';
10
+ import { lexicographicalCompare } from './string.js';
11
+ import { ProtocolRecordLimitStrategy } from '../types/protocols-types.js';
12
+ import { Records } from './records.js';
13
+ import { SortDirection } from '../types/query-types.js';
14
+ import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
15
+ import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
16
+
17
+ type RecordLimitOccupancyDependencies = {
18
+ messageStore: MessageStore;
19
+ validationStateReader: ValidationStateReader;
20
+ };
21
+
22
+ type RecordLimitOccupancyQueryInput = RecordLimitOccupancyDependencies & {
23
+ tenant: string;
24
+ filters: Filter[];
25
+ messageTimestamp: string;
26
+ messageSort?: MessageSort;
27
+ pagination?: Pagination;
28
+ };
29
+
30
+ type RecordLimitScope = {
31
+ protocol: string;
32
+ protocolPath: string;
33
+ parentContextId: string;
34
+ };
35
+
36
+ type RecordLimitFilterResolution = {
37
+ projectedFilters: Filter[];
38
+ };
39
+
40
+ /**
41
+ * Queries records with bounded `$recordLimit` occupancy projection when every limited filter targets one concrete scope.
42
+ *
43
+ * Broad filters keep the store's native query path. Projecting those without a store-level grouping primitive would require
44
+ * scanning the full matching set, which is worse than leaving them unprojected until a bounded broad-query strategy exists.
45
+ */
46
+ export async function queryRecordsWithRecordLimitOccupancy(
47
+ input: RecordLimitOccupancyQueryInput
48
+ ): Promise<{ messages: RecordsWriteMessage[]; cursor?: PaginationCursor }> {
49
+ const filterResolution = await resolveRecordLimitFilters(input);
50
+ if (filterResolution === undefined) {
51
+ const { messages, cursor } = await input.messageStore.query(input.tenant, input.filters, input.messageSort, input.pagination);
52
+ return { messages: messages.filter(Records.isRecordsWrite), cursor };
53
+ }
54
+
55
+ if (filterResolution.projectedFilters.length === 0) {
56
+ return { messages: [] };
57
+ }
58
+
59
+ const { messages, cursor } = await input.messageStore.query(
60
+ input.tenant,
61
+ filterResolution.projectedFilters,
62
+ input.messageSort,
63
+ input.pagination
64
+ );
65
+
66
+ return { messages: messages.filter(Records.isRecordsWrite), cursor };
67
+ }
68
+
69
+ /**
70
+ * Counts records with bounded `$recordLimit` occupancy projection when every limited filter targets one concrete scope.
71
+ */
72
+ export async function countRecordsWithRecordLimitOccupancy(input: Omit<RecordLimitOccupancyQueryInput, 'pagination'>): Promise<number> {
73
+ const filterResolution = await resolveRecordLimitFilters(input);
74
+ if (filterResolution === undefined) {
75
+ return input.messageStore.count(input.tenant, input.filters, input.messageSort);
76
+ }
77
+
78
+ if (filterResolution.projectedFilters.length === 0) {
79
+ return 0;
80
+ }
81
+
82
+ return input.messageStore.count(input.tenant, filterResolution.projectedFilters, input.messageSort);
83
+ }
84
+
85
+ /**
86
+ * Returns true when the latest RecordsWrite is visible under the `$recordLimit` projection.
87
+ */
88
+ export async function isRecordLimitOccupant(input: RecordLimitOccupancyDependencies & {
89
+ tenant: string;
90
+ message: RecordsWriteMessage;
91
+ messageTimestamp: string;
92
+ }): Promise<boolean> {
93
+ const recordLimit = await getRecordLimitForMessage({
94
+ messageStore : input.messageStore,
95
+ validationStateReader : input.validationStateReader,
96
+ tenant : input.tenant,
97
+ message : input.message,
98
+ messageTimestamp : input.messageTimestamp,
99
+ recordLimitDefinitions : new Map(),
100
+ });
101
+
102
+ if (recordLimit === undefined) {
103
+ return true;
104
+ }
105
+
106
+ const occupantRecordIds = await findOccupantRecordIds({
107
+ messageStore : input.messageStore,
108
+ tenant : input.tenant,
109
+ scope : getRecordLimitScope(input.message),
110
+ recordLimit,
111
+ });
112
+
113
+ return occupantRecordIds.has(input.message.recordId);
114
+ }
115
+
116
+ async function resolveRecordLimitFilters(
117
+ input: Omit<RecordLimitOccupancyQueryInput, 'pagination'>
118
+ ): Promise<RecordLimitFilterResolution | undefined> {
119
+ const recordLimitDefinitions = new Map<string, ProtocolRecordLimitDefinition | undefined>();
120
+ const projectedFilters: Filter[] = [];
121
+ let projectionApplied = false;
122
+
123
+ for (const filter of input.filters) {
124
+ const recordLimit = await getRecordLimitForFilter({
125
+ messageStore : input.messageStore,
126
+ validationStateReader : input.validationStateReader,
127
+ tenant : input.tenant,
128
+ filter,
129
+ messageTimestamp : input.messageTimestamp,
130
+ recordLimitDefinitions,
131
+ });
132
+
133
+ if (recordLimit === undefined) {
134
+ projectedFilters.push(filter);
135
+ continue;
136
+ }
137
+
138
+ const scope = getRecordLimitScopeFromFilter(filter);
139
+ if (scope === undefined) {
140
+ return undefined;
141
+ }
142
+
143
+ const occupantRecordIds = await findOccupantRecordIds({
144
+ messageStore : input.messageStore,
145
+ tenant : input.tenant,
146
+ scope,
147
+ recordLimit,
148
+ });
149
+
150
+ const projectedFilter = buildProjectedFilter(filter, occupantRecordIds);
151
+ if (projectedFilter !== undefined) {
152
+ projectedFilters.push(projectedFilter);
153
+ }
154
+ projectionApplied = true;
155
+ }
156
+
157
+ return projectionApplied ? { projectedFilters } : undefined;
158
+ }
159
+
160
+ async function getRecordLimitForMessage(input: RecordLimitOccupancyDependencies & {
161
+ tenant: string;
162
+ message: RecordsWriteMessage;
163
+ messageTimestamp: string;
164
+ recordLimitDefinitions: Map<string, ProtocolRecordLimitDefinition | undefined>;
165
+ }): Promise<ProtocolRecordLimitDefinition | undefined> {
166
+ const { protocol, protocolPath } = input.message.descriptor;
167
+ if (protocol === undefined || protocolPath === undefined) {
168
+ return undefined;
169
+ }
170
+
171
+ return getRecordLimit({
172
+ validationStateReader : input.validationStateReader,
173
+ tenant : input.tenant,
174
+ protocol,
175
+ protocolPath,
176
+ messageTimestamp : input.messageTimestamp,
177
+ recordLimitDefinitions : input.recordLimitDefinitions,
178
+ });
179
+ }
180
+
181
+ async function getRecordLimitForFilter(input: RecordLimitOccupancyDependencies & {
182
+ tenant: string;
183
+ filter: Filter;
184
+ messageTimestamp: string;
185
+ recordLimitDefinitions: Map<string, ProtocolRecordLimitDefinition | undefined>;
186
+ }): Promise<ProtocolRecordLimitDefinition | undefined> {
187
+ if (input.filter.interface !== DwnInterfaceName.Records ||
188
+ input.filter.method !== DwnMethodName.Write ||
189
+ input.filter.isLatestBaseState !== true
190
+ ) {
191
+ return undefined;
192
+ }
193
+
194
+ const { protocol, protocolPath } = input.filter;
195
+ if (typeof protocol !== 'string' || typeof protocolPath !== 'string') {
196
+ return undefined;
197
+ }
198
+
199
+ return getRecordLimit({
200
+ validationStateReader : input.validationStateReader,
201
+ tenant : input.tenant,
202
+ protocol,
203
+ protocolPath,
204
+ messageTimestamp : input.messageTimestamp,
205
+ recordLimitDefinitions : input.recordLimitDefinitions,
206
+ });
207
+ }
208
+
209
+ async function getRecordLimit(input: {
210
+ validationStateReader: ValidationStateReader;
211
+ tenant: string;
212
+ protocol: string;
213
+ protocolPath: string;
214
+ messageTimestamp: string;
215
+ recordLimitDefinitions: Map<string, ProtocolRecordLimitDefinition | undefined>;
216
+ }): Promise<ProtocolRecordLimitDefinition | undefined> {
217
+ const key = `${input.protocol}\u0000${input.protocolPath}`;
218
+ if (!input.recordLimitDefinitions.has(key)) {
219
+ let protocolDefinition;
220
+ try {
221
+ protocolDefinition = await input.validationStateReader.fetchProtocolDefinition(
222
+ input.tenant,
223
+ input.protocol,
224
+ input.messageTimestamp,
225
+ );
226
+ } catch (error) {
227
+ if (error instanceof DwnError && error.code === DwnErrorCode.ProtocolAuthorizationProtocolNotFound) {
228
+ input.recordLimitDefinitions.set(key, undefined);
229
+ return undefined;
230
+ }
231
+ throw error;
232
+ }
233
+
234
+ const ruleSet = getRuleSetAtPath(input.protocolPath, protocolDefinition.structure);
235
+ const recordLimit = ruleSet?.$recordLimit;
236
+ input.recordLimitDefinitions.set(
237
+ key,
238
+ recordLimit?.strategy === ProtocolRecordLimitStrategy.Reject ? recordLimit : undefined
239
+ );
240
+ }
241
+
242
+ return input.recordLimitDefinitions.get(key);
243
+ }
244
+
245
+ async function findOccupantRecordIds(input: {
246
+ messageStore: MessageStore;
247
+ tenant: string;
248
+ scope: RecordLimitScope;
249
+ recordLimit: ProtocolRecordLimitDefinition;
250
+ }): Promise<Set<string>> {
251
+ const scopeFilter = buildRecordLimitScopeFilter(input.scope);
252
+ const messageSort = { dateCreated: SortDirection.Ascending };
253
+ const { messages: firstPage } = await input.messageStore.query(
254
+ input.tenant,
255
+ [scopeFilter],
256
+ messageSort,
257
+ { limit: input.recordLimit.max }
258
+ );
259
+ const firstPageCandidates = firstPage.filter(Records.isRecordsWrite);
260
+ if (firstPageCandidates.length === 0) {
261
+ return new Set();
262
+ }
263
+
264
+ const boundaryDateCreated = firstPageCandidates.at(-1)!.descriptor.dateCreated;
265
+ const beforeBoundary = firstPageCandidates.filter(
266
+ (message): boolean => message.descriptor.dateCreated < boundaryDateCreated
267
+ );
268
+ let boundaryCandidates = firstPageCandidates.filter(
269
+ (message): boolean => message.descriptor.dateCreated === boundaryDateCreated
270
+ );
271
+
272
+ if (firstPageCandidates.length === input.recordLimit.max) {
273
+ const { messages } = await input.messageStore.query(
274
+ input.tenant,
275
+ [{ ...scopeFilter, dateCreated: boundaryDateCreated }],
276
+ messageSort
277
+ );
278
+ boundaryCandidates = messages.filter(Records.isRecordsWrite);
279
+ }
280
+
281
+ boundaryCandidates.sort(compareRecordLimitCandidates);
282
+
283
+ const rankedCandidates = [
284
+ ...beforeBoundary,
285
+ ...boundaryCandidates,
286
+ ];
287
+
288
+ return new Set(
289
+ rankedCandidates
290
+ .slice(0, input.recordLimit.max)
291
+ .map((message): string => message.recordId)
292
+ );
293
+ }
294
+
295
+ function buildRecordLimitScopeFilter(scope: RecordLimitScope): Filter {
296
+ const filter: Filter = {
297
+ interface : DwnInterfaceName.Records,
298
+ method : DwnMethodName.Write,
299
+ isLatestBaseState : true,
300
+ protocol : scope.protocol,
301
+ protocolPath : scope.protocolPath,
302
+ };
303
+
304
+ if (scope.parentContextId !== '') {
305
+ filter.contextId = FilterUtility.constructPrefixFilterAsRangeFilter(scope.parentContextId);
306
+ }
307
+
308
+ return filter;
309
+ }
310
+
311
+ function getRecordLimitScopeFromFilter(filter: Filter): RecordLimitScope | undefined {
312
+ const { protocol, protocolPath } = filter;
313
+ if (typeof protocol !== 'string' || typeof protocolPath !== 'string') {
314
+ return undefined;
315
+ }
316
+
317
+ if (!protocolPath.includes('/')) {
318
+ return { protocol, protocolPath, parentContextId: '' };
319
+ }
320
+
321
+ const parentContextId = getExactParentContextIdFromFilter(filter);
322
+ if (parentContextId === undefined) {
323
+ return undefined;
324
+ }
325
+
326
+ return { protocol, protocolPath, parentContextId };
327
+ }
328
+
329
+ function getRecordLimitScope(message: RecordsWriteMessage): RecordLimitScope {
330
+ return {
331
+ protocol : message.descriptor.protocol,
332
+ protocolPath : message.descriptor.protocolPath,
333
+ parentContextId : Records.getParentContextFromOfContextId(message.contextId) ?? '',
334
+ };
335
+ }
336
+
337
+ function getExactParentContextIdFromFilter(filter: Filter): string | undefined {
338
+ const { contextId } = filter;
339
+ if (contextId === undefined || !FilterUtility.isRangeFilter(contextId)) {
340
+ return undefined;
341
+ }
342
+
343
+ if (typeof contextId.gte !== 'string' || contextId.lt !== `${contextId.gte}\uffff`) {
344
+ return undefined;
345
+ }
346
+
347
+ return contextId.gte;
348
+ }
349
+
350
+ function buildProjectedFilter(filter: Filter, occupantRecordIds: Set<string>): Filter | undefined {
351
+ let projectedRecordIds = Array.from(occupantRecordIds);
352
+ const existingRecordIdFilter = filter.recordId;
353
+ if (typeof existingRecordIdFilter === 'string') {
354
+ projectedRecordIds = occupantRecordIds.has(existingRecordIdFilter) ? [existingRecordIdFilter] : [];
355
+ } else if (Array.isArray(existingRecordIdFilter)) {
356
+ projectedRecordIds = existingRecordIdFilter
357
+ .filter((recordId): recordId is string => typeof recordId === 'string' && occupantRecordIds.has(recordId));
358
+ }
359
+
360
+ if (projectedRecordIds.length === 0) {
361
+ return undefined;
362
+ }
363
+
364
+ return {
365
+ ...filter,
366
+ recordId: projectedRecordIds,
367
+ };
368
+ }
369
+
370
+ function compareRecordLimitCandidates(left: RecordsWriteMessage, right: RecordsWriteMessage): number {
371
+ const dateComparison = lexicographicalCompare(left.descriptor.dateCreated, right.descriptor.dateCreated);
372
+ if (dateComparison !== 0) {
373
+ return dateComparison;
374
+ }
375
+
376
+ return lexicographicalCompare(left.recordId, right.recordId);
377
+ }
@@ -36,6 +36,26 @@ export class Records {
36
36
  return isRecordsWrite;
37
37
  }
38
38
 
39
+ /**
40
+ * Gets the newest `RecordsWrite` from the given message set.
41
+ */
42
+ public static async getNewestRecordsWrite(messages: GenericMessage[]): Promise<RecordsWriteMessage | undefined> {
43
+ const recordsWriteMessages = messages.filter(Records.isRecordsWrite);
44
+ const newestRecordsWrite = await Message.getNewestMessage(recordsWriteMessages);
45
+ return newestRecordsWrite as RecordsWriteMessage | undefined;
46
+ }
47
+
48
+ /**
49
+ * Gets the newest `RecordsDelete` from the given message set.
50
+ */
51
+ public static async getNewestRecordsDelete(messages: GenericMessage[]): Promise<RecordsDeleteMessage | undefined> {
52
+ const recordsDeleteMessages = messages.filter((message): message is RecordsDeleteMessage =>
53
+ message.descriptor.interface === DwnInterfaceName.Records && message.descriptor.method === DwnMethodName.Delete
54
+ );
55
+ const newestRecordsDelete = await Message.getNewestMessage(recordsDeleteMessages);
56
+ return newestRecordsDelete as RecordsDeleteMessage | undefined;
57
+ }
58
+
39
59
  /**
40
60
  * Decrypts the encrypted data in a message reply.
41
61
  *
@@ -285,6 +305,35 @@ export class Records {
285
305
  return filterCopy;
286
306
  }
287
307
 
308
+ /**
309
+ * Nested protocol-path queries must pin one parent context. Otherwise the same
310
+ * protocol type is read across every parent instance.
311
+ */
312
+ public static validateNestedProtocolPathQueryScope(
313
+ filter: RecordsFilter,
314
+ errorCode: DwnErrorCode,
315
+ operationName: string,
316
+ ): void {
317
+ const { contextId, protocolPath } = filter;
318
+ if (!protocolPath?.includes('/')) {
319
+ return;
320
+ }
321
+
322
+ const expectedParentDepth = protocolPath.split('/').length - 1;
323
+ const contextIdSegments = contextId?.split('/');
324
+ if (
325
+ contextIdSegments?.length === expectedParentDepth &&
326
+ contextIdSegments.every(segment => segment.length > 0)
327
+ ) {
328
+ return;
329
+ }
330
+
331
+ throw new DwnError(
332
+ errorCode,
333
+ `${operationName} for nested protocol path '${protocolPath}' must include the direct parent contextId in the filter`
334
+ );
335
+ }
336
+
288
337
 
289
338
  public static isStartsWithFilter(filter: RecordsWriteTagsFilter): filter is StartsWithFilter {
290
339
  return typeof filter === 'object' && ('startsWith' in filter && typeof filter.startsWith === 'string');
@@ -530,25 +579,32 @@ export class Records {
530
579
  }
531
580
 
532
581
  /**
533
- * Checks if the given RecordsDelete message can be performed against a record with the given newest existing state.
582
+ * Checks whether the given `RecordsDelete` is beaten by an existing tombstone for the record,
583
+ * per the tombstone lattice. A tombstone displaces any `RecordsWrite` regardless of timestamp
584
+ * (delete-wins). Among competing tombstones one canonical winner stands on every replica:
585
+ * a prune beats a plain delete regardless of timestamp — the cascade is a side effect, and a
586
+ * plain-newer winner would leave replicas that ran the cascade diverged from those that never
587
+ * would — and within the same class the newest tombstone wins, with `Message.isNewer`'s
588
+ * (messageTimestamp, CID) total order picking the same winner everywhere. Admission and
589
+ * resumable-task replay must share this predicate: state can advance between acceptance and
590
+ * replay, and replay must never admit a delete that admission would now reject.
534
591
  */
535
- public static canPerformDeleteAgainstRecord(deleteToBePerformed: RecordsDeleteMessage, newestExistingMessage: GenericMessage | undefined): boolean {
536
- if (newestExistingMessage === undefined) {
592
+ public static async isDeleteBeatenByExistingTombstone(
593
+ deleteToBePerformed: RecordsDeleteMessage,
594
+ newestExistingMessage: GenericMessage
595
+ ): Promise<boolean> {
596
+ if (newestExistingMessage.descriptor.method !== DwnMethodName.Delete) {
537
597
  return false;
538
598
  }
539
599
 
540
- // can't perform delete if:
541
- // attempting to delete on an already deleted record; or
542
- // attempting to prune on an already pruned record;
543
- if (newestExistingMessage.descriptor.method === DwnMethodName.Delete) {
544
- if (deleteToBePerformed.descriptor.prune !== true) {
545
- return false;
546
- } else if ((newestExistingMessage as RecordsDeleteMessage).descriptor.prune === true) {
547
- return false;
548
- }
600
+ const incomingIsPrune = deleteToBePerformed.descriptor.prune === true;
601
+ const existingIsPrune = (newestExistingMessage as RecordsDeleteMessage).descriptor.prune === true;
602
+ if (incomingIsPrune !== existingIsPrune) {
603
+ return existingIsPrune;
549
604
  }
550
605
 
551
- return true;
606
+ const incomingDeleteIsNewest = await Message.isNewer(deleteToBePerformed, newestExistingMessage);
607
+ return !incomingDeleteIsNewest;
552
608
  }
553
609
 
554
610
  /**
@@ -0,0 +1,122 @@
1
+ import type { GenericMessage } from '../types/message-types.js';
2
+ import type { KeyValues } from '../types/query-types.js';
3
+
4
+ import { PermissionsProtocol } from '../protocols/permissions.js';
5
+ import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
6
+
7
+ const POSITION_PAD_WIDTH = 20;
8
+
9
+ type ReplicationMessageDescriptor = GenericMessage['descriptor'] & {
10
+ tags?: Record<string, unknown>;
11
+ };
12
+
13
+ /**
14
+ * Shared helpers for the replication log substrate.
15
+ */
16
+ export class Replication {
17
+ public static readonly globalDomain = '';
18
+
19
+ public static protocolDomain(protocolUri: string): string {
20
+ return `protocol:${protocolUri}`;
21
+ }
22
+
23
+ public static permissionDomain(protocolUri: string): string {
24
+ return `perm:${protocolUri}`;
25
+ }
26
+
27
+ public static async deriveStreamId(tenant: string): Promise<string> {
28
+ const bytes = new TextEncoder().encode(tenant);
29
+ const hashBuffer = await crypto.subtle.digest('SHA-256', bytes);
30
+ const hashArray = new Uint8Array(hashBuffer);
31
+ return Array.from(hashArray.slice(0, 8), (b: number) => b.toString(16).padStart(2, '0')).join('');
32
+ }
33
+
34
+ public static computeFingerprintScopes(message: GenericMessage, indexes: KeyValues): string[] {
35
+ const scopes = [Replication.globalDomain];
36
+
37
+ const descriptor: ReplicationMessageDescriptor = message.descriptor;
38
+ const protocol = indexes.protocol;
39
+ if (typeof protocol === 'string') {
40
+ scopes.push(Replication.protocolDomain(protocol));
41
+
42
+ if (protocol === PermissionsProtocol.uri) {
43
+ const indexedTaggedProtocol = indexes['tag.protocol'];
44
+ const taggedProtocol = indexedTaggedProtocol ?? descriptor.tags?.protocol;
45
+ if (typeof taggedProtocol === 'string') {
46
+ scopes.push(Replication.permissionDomain(taggedProtocol));
47
+ }
48
+ }
49
+ }
50
+
51
+ return scopes;
52
+ }
53
+
54
+ public static assertFingerprintScopesUntouched(
55
+ persistedScopes: string[],
56
+ message: GenericMessage,
57
+ messageCid: string,
58
+ newIndexes: KeyValues,
59
+ ): void {
60
+ const expectedScopes = Replication.computeFingerprintScopes(message, newIndexes);
61
+ if (!Replication.scopeSetsMatch(persistedScopes, expectedScopes)) {
62
+ Replication.throwFingerprintScopeMutation(messageCid);
63
+ }
64
+ }
65
+
66
+ private static scopeSetsMatch(left: string[], right: string[]): boolean {
67
+ if (left.length !== right.length) {
68
+ return false;
69
+ }
70
+
71
+ return right.every((scope) => left.includes(scope));
72
+ }
73
+
74
+ private static throwFingerprintScopeMutation(messageCid: string): never {
75
+ throw new DwnError(
76
+ DwnErrorCode.MessageStoreFingerprintScopeMutation,
77
+ `index replacement for message ${messageCid} would change its persisted fingerprint scopes`
78
+ );
79
+ }
80
+
81
+ public static async hashMessageCid(messageCid: string): Promise<Uint8Array> {
82
+ const bytes = new TextEncoder().encode(messageCid);
83
+ const hashBuffer = await crypto.subtle.digest('SHA-256', bytes);
84
+ return new Uint8Array(hashBuffer);
85
+ }
86
+
87
+ public static emptyFingerprint(): Uint8Array {
88
+ return new Uint8Array(32);
89
+ }
90
+
91
+ public static xorFingerprint(fingerprint: Uint8Array, contribution: Uint8Array): Uint8Array {
92
+ const result = new Uint8Array(32);
93
+ for (let i = 0; i < 32; i++) {
94
+ result[i] = fingerprint[i] ^ contribution[i];
95
+ }
96
+ return result;
97
+ }
98
+
99
+ public static fingerprintToHex(fingerprint: Uint8Array): string {
100
+ return Array.from(fingerprint, (b: number) => b.toString(16).padStart(2, '0')).join('');
101
+ }
102
+
103
+ public static hexToFingerprint(hex: string): Uint8Array {
104
+ const bytes = new Uint8Array(32);
105
+ for (let i = 0; i < 32; i++) {
106
+ bytes[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
107
+ }
108
+ return bytes;
109
+ }
110
+
111
+ public static encodePositionKey(position: bigint): string {
112
+ const decimal = position.toString();
113
+ if (position < 0n || decimal.length > POSITION_PAD_WIDTH) {
114
+ throw new DwnError(
115
+ DwnErrorCode.MessageStoreReplicationPositionOverflow,
116
+ `log position ${decimal} cannot be encoded within ${POSITION_PAD_WIDTH} digits`
117
+ );
118
+ }
119
+
120
+ return decimal.padStart(POSITION_PAD_WIDTH, '0');
121
+ }
122
+ }
@@ -1,64 +0,0 @@
1
- import { RecordsWrite } from '../interfaces/records-write.js';
2
- import { DwnError, DwnErrorCode } from './dwn-error.js';
3
- import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
4
- /**
5
- * Fetches the initial RecordsWrite message associated with the given (tenant + recordId).
6
- */
7
- export async function fetchInitialWrite(tenant, recordId, messageStore) {
8
- const query = {
9
- interface: DwnInterfaceName.Records,
10
- method: DwnMethodName.Write,
11
- recordId: recordId
12
- };
13
- const { messages } = await messageStore.query(tenant, [query]);
14
- if (messages.length === 0) {
15
- return undefined;
16
- }
17
- const initialWrite = await RecordsWrite.getInitialWrite(messages);
18
- return initialWrite;
19
- }
20
- /**
21
- * Constructs the chain of EXISTING records in the datastore where the first record is the root initial `RecordsWrite` of the record chain
22
- * and last record is the initial `RecordsWrite` of the descendant record specified.
23
- * @param descendantRecordId The ID of the descendent record to start constructing the record chain from by repeatedly looking up the parent.
24
- * @returns the record chain where each record is represented by its initial `RecordsWrite`;
25
- * returns empty array if `descendantRecordId` is `undefined`.
26
- * @throws {DwnError} if `descendantRecordId` is defined but any initial `RecordsWrite` is not found in the chain of records.
27
- */
28
- export async function constructRecordChain(tenant, descendantRecordId, messageStore) {
29
- if (descendantRecordId === undefined) {
30
- return [];
31
- }
32
- const recordChain = [];
33
- // keep walking up the chain from the inbound message's parent, until there is no more parent
34
- let currentRecordId = descendantRecordId;
35
- while (currentRecordId !== undefined) {
36
- const initialWrite = await fetchInitialWrite(tenant, currentRecordId, messageStore);
37
- // RecordsWrite needed should be available since we perform necessary checks at the time of writes,
38
- // eg. check the immediate parent in `verifyProtocolPathAndContextId` at the time of writing,
39
- // so if this condition is triggered, it means there is an unexpected bug that caused an incomplete chain.
40
- // We add additional defensive check here because returning an unexpected/incorrect record chain could lead to security vulnerabilities.
41
- if (initialWrite === undefined) {
42
- throw new DwnError(DwnErrorCode.ProtocolAuthorizationParentNotFoundConstructingRecordChain, `Unexpected error that should never trigger: no parent found with ID ${currentRecordId} when constructing record chain.`);
43
- }
44
- recordChain.push(initialWrite);
45
- currentRecordId = initialWrite.descriptor.parentId;
46
- }
47
- return recordChain.reverse(); // root record first
48
- }
49
- /**
50
- * Determines the timestamp that governs which protocol definition version applies to the given RecordsWrite.
51
- * For an update, this is the initial write's `messageTimestamp` (the protocol version is locked at creation time).
52
- * For a new initial write, returns `undefined` — the latest protocol definition should be used because the
53
- * record is being created now and must conform to the current protocol rules.
54
- */
55
- export async function getGoverningTimestamp(tenant, incomingMessage, messageStore) {
56
- const existingInitialWrite = await fetchInitialWrite(tenant, incomingMessage.message.recordId, messageStore);
57
- if (existingInitialWrite !== undefined) {
58
- // update case: use the initial write's timestamp
59
- return existingInitialWrite.descriptor.messageTimestamp;
60
- }
61
- // initial write case: validate against the latest protocol definition
62
- return undefined;
63
- }
64
- //# sourceMappingURL=record-chain.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"record-chain.js","sourceRoot":"","sources":["../../../../src/core/record-chain.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAEnF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAc,EACd,QAAgB,EAChB,YAA0B;IAG1B,MAAM,KAAK,GAAW;QACpB,SAAS,EAAG,gBAAgB,CAAC,OAAO;QACpC,MAAM,EAAM,aAAa,CAAC,KAAK;QAC/B,QAAQ,EAAI,QAAQ;KACrB,CAAC;IACF,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAE/D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,YAAY,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IAClE,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAc,EACd,kBAAsC,EACtC,YAA0B;IAG1B,IAAI,kBAAkB,KAAK,SAAS,EAAE,CAAC;QACrC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,WAAW,GAA0B,EAAE,CAAC;IAE9C,6FAA6F;IAC7F,IAAI,eAAe,GAAuB,kBAAkB,CAAC;IAC7D,OAAO,eAAe,KAAK,SAAS,EAAE,CAAC;QAErC,MAAM,YAAY,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC;QAEpF,mGAAmG;QACnG,6FAA6F;QAC7F,0GAA0G;QAC1G,wIAAwI;QACxI,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,MAAM,IAAI,QAAQ,CAChB,YAAY,CAAC,0DAA0D,EACvE,uEAAuE,eAAe,kCAAkC,CACzH,CAAC;QACJ,CAAC;QAED,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC/B,eAAe,GAAG,YAAY,CAAC,UAAU,CAAC,QAAQ,CAAC;IACrD,CAAC;IAED,OAAO,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,oBAAoB;AACpD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAc,EACd,eAA6B,EAC7B,YAA0B;IAE1B,MAAM,oBAAoB,GAAG,MAAM,iBAAiB,CAClD,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,QAAQ,EAAE,YAAY,CACvD,CAAC;IAEF,IAAI,oBAAoB,KAAK,SAAS,EAAE,CAAC;QACvC,iDAAiD;QACjD,OAAO,oBAAoB,CAAC,UAAU,CAAC,gBAAgB,CAAC;IAC1D,CAAC;IAED,sEAAsE;IACtE,OAAO,SAAS,CAAC;AACnB,CAAC"}