@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,127 @@
1
+ import type { GenericMessage } from './message-types.js';
2
+ import type { PermissionGrant } from '../protocols/permission-grant.js';
3
+ import type { ProtocolDefinition } from './protocols-types.js';
4
+ import type { RecordsWrite } from '../interfaces/records-write.js';
5
+ import type { RecordsWriteMessage } from './records-types.js';
6
+
7
+ /**
8
+ * The single narrow surface through which validation logic reads state.
9
+ *
10
+ * Every validation-time state read performed during message admission routes through this
11
+ * interface, so the replay basis (initial writes ∪ latest states ∪ tombstones ∪ protocol-config
12
+ * history ∪ permission records) provably stays closed under admission's read set. Validation
13
+ * modules (`core/protocol-authorization*`, `protocols/permissions*`) are lint-banned from
14
+ * importing `MessageStore` directly; a new protocol-engine feature that needs new state must add
15
+ * a reader method here.
16
+ */
17
+ export interface ValidationStateReader {
18
+ /**
19
+ * Fetches a record's initial `RecordsWrite` by entry ID, parsed.
20
+ * @returns the initial write, or `undefined` when no message carries the entry ID.
21
+ */
22
+ fetchInitialRecordsWrite(tenant: string, recordId: string): Promise<RecordsWrite | undefined>;
23
+
24
+ /**
25
+ * Fetches a record's initial write from among all of the record's writes.
26
+ * @returns the initial write message, or `undefined` when the record has no messages at all.
27
+ * @throws {DwnError} with `RecordsWriteGetInitialWriteNotFound` when writes exist for the
28
+ * record but none of them is the initial write.
29
+ */
30
+ fetchInitialWrite(tenant: string, recordId: string): Promise<RecordsWriteMessage | undefined>;
31
+
32
+ /**
33
+ * Constructs the chain of existing records from the root to the given
34
+ * descendant, each represented by its initial `RecordsWrite`.
35
+ * @returns the chain root-first; an empty array when `descendantRecordId` is `undefined`.
36
+ * @throws {DwnError} with `ProtocolAuthorizationParentNotFoundConstructingRecordChain` when any
37
+ * link in the chain is missing.
38
+ */
39
+ constructRecordChain(tenant: string, descendantRecordId: string | undefined): Promise<RecordsWriteMessage[]>;
40
+
41
+ /**
42
+ * Fetches the immediate parent record for protocolPath/contextId verification.
43
+ *
44
+ * Queries the latest-state write first — the fast path that excludes deleted parents. If no
45
+ * latest write exists, a retained initial write is sufficient for immutable parent facts
46
+ * (protocolPath/contextId) provided no local tombstone exists for that record.
47
+ * @returns the parent write, or `undefined` when the parent is absent (or deleted).
48
+ */
49
+ fetchParentRecord(input: {
50
+ tenant: string;
51
+ parentProtocolUri: string;
52
+ parentId: string;
53
+ }): Promise<RecordsWriteMessage | undefined>;
54
+
55
+ /**
56
+ * Checks whether a role record matching the invoked-role selector exists.
57
+ * Filter-only — role validation never reads record data. The latest-state match is the fast
58
+ * path. If no latest match exists, a retained initial role write is sufficient for immutable
59
+ * role facts (recipient/path/context) provided no local tombstone exists for that role record.
60
+ */
61
+ hasMatchingRoleRecord(input: {
62
+ tenant: string;
63
+ protocol: string;
64
+ protocolPath: string;
65
+ recipient: string;
66
+ contextIdPrefix?: string;
67
+ }): Promise<boolean>;
68
+
69
+ /**
70
+ * Queries the latest-state role records matching the given
71
+ * selector, used to reject duplicate role assignments to the same recipient. Filter-only.
72
+ */
73
+ queryLatestRoleRecords(input: {
74
+ tenant: string;
75
+ protocol: string;
76
+ protocolPath: string;
77
+ recipient: string;
78
+ contextIdPrefix?: string;
79
+ }): Promise<RecordsWriteMessage[]>;
80
+
81
+ /**
82
+ * Fetches the permission grant with the given record ID, with its scope parsed from grant data.
83
+ * @throws {DwnError} with `GrantAuthorizationGrantMissing` when the grant does not exist.
84
+ */
85
+ fetchGrant(tenant: string, permissionGrantId: string): Promise<PermissionGrant>;
86
+
87
+ /**
88
+ * Fetches the oldest latest-state revocation record for the given permission grant, if any.
89
+ * Grant activity checks compare the oldest revocation timestamp to the incoming message timestamp.
90
+ */
91
+ fetchOldestGrantRevocation(tenant: string, permissionGrantId: string): Promise<GenericMessage | undefined>;
92
+
93
+ /**
94
+ * Fetches the newest `RecordsWrite` associated with a record, used to authorize `Messages.Read`
95
+ * access to `RecordsDelete` messages by projecting the delete back to the deleted record's
96
+ * protocol scope.
97
+ * @throws {DwnError} with `RecordsWriteGetNewestWriteRecordNotFound` when no write exists.
98
+ */
99
+ fetchNewestRecordsWrite(tenant: string, recordId: string): Promise<RecordsWriteMessage>;
100
+
101
+ /**
102
+ * Fetches the protocol definition for the given protocol URI.
103
+ * When `messageTimestamp` is provided, returns the definition active at that point in time —
104
+ * the `ProtocolsConfigure` with the greatest `messageTimestamp` that is <= the given timestamp,
105
+ * read from retained config history. When not provided, returns the latest definition.
106
+ * Core protocol definitions are returned from the registry without a store read.
107
+ * @throws {DwnError} with `ProtocolAuthorizationProtocolNotFound` when no definition exists.
108
+ */
109
+ fetchProtocolDefinition(tenant: string, protocolUri: string, messageTimestamp?: string): Promise<ProtocolDefinition>;
110
+
111
+ /**
112
+ * Fetches the latest `$squash: true` record at a protocol path within the parent context.
113
+ * This is the temporal floor used by the squash backstop.
114
+ */
115
+ fetchLatestSquashRecordAtScope(input: {
116
+ tenant: string;
117
+ protocol: string;
118
+ protocolPath: string;
119
+ contextIdPrefix?: string;
120
+ }): Promise<RecordsWriteMessage | undefined>;
121
+
122
+ /**
123
+ * Checks whether the data with the given CID is present in the `DataStore` for the given record.
124
+ * This is the prior-data integrity check for dataless non-initial writes.
125
+ */
126
+ hasStoredData(tenant: string, recordId: string, dataCid: string): Promise<boolean>;
127
+ }
@@ -1,11 +1,15 @@
1
1
  import type { CoreProtocolRegistry } from '../core/core-protocol.js';
2
2
  import type { Filter } from '../types/query-types.js';
3
+ import type { GenericMessage } from '../types/message-types.js';
3
4
  import type { MessagesFilter } from '../types/messages-types.js';
4
5
 
5
6
  import { FilterUtility } from './filter.js';
6
7
  import { normalizeProtocolUrl } from './url.js';
8
+ import { Records } from './records.js';
7
9
  import { isEmptyObject, removeUndefinedProperties } from '@enbox/common';
8
10
 
11
+ type StoredMessageWithEncodedData = GenericMessage & { encodedData?: string };
12
+
9
13
 
10
14
  /**
11
15
  * Class containing Messages related utility methods.
@@ -95,6 +99,22 @@ export class Messages {
95
99
  return messagesQueryFilters;
96
100
  }
97
101
 
102
+ /**
103
+ * Returns a copy of a RecordsWrite message without inline encodedData, and the
104
+ * detached encodedData value for wire surfaces that carry data beside the message.
105
+ */
106
+ public static detachEncodedData(message: GenericMessage): { message: GenericMessage; encodedData?: string } {
107
+ if (!Records.isRecordsWrite(message) || !Messages.hasEncodedData(message)) {
108
+ return { message };
109
+ }
110
+
111
+ const messageWithoutEncodedData: StoredMessageWithEncodedData = { ...message };
112
+ const { encodedData } = messageWithoutEncodedData;
113
+ delete messageWithoutEncodedData.encodedData;
114
+
115
+ return { message: messageWithoutEncodedData, encodedData };
116
+ }
117
+
98
118
  /**
99
119
  * Converts an external-facing filter model into an internal-facing filer model used by data store.
100
120
  */
@@ -132,4 +152,8 @@ export class Messages {
132
152
 
133
153
  return filterCopy;
134
154
  }
135
- }
155
+
156
+ private static hasEncodedData(message: GenericMessage): message is StoredMessageWithEncodedData {
157
+ return 'encodedData' in message && typeof message.encodedData === 'string';
158
+ }
159
+ }
@@ -0,0 +1,366 @@
1
+ import type { ProtocolTagSchema, ProtocolTagsDefinition } from '../types/protocols-types.js';
2
+
3
+ type TagSchema = ProtocolTagSchema | Record<string, unknown>;
4
+
5
+ type TagValidationError = {
6
+ instancePath: string;
7
+ message: string;
8
+ };
9
+
10
+ const allowedTagTypes = new Set(['string', 'number', 'integer', 'boolean', 'array']);
11
+ const allowedArrayItemTypes = new Set(['string', 'number', 'integer']);
12
+ const numericConstraintKeywords = [ 'minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum' ];
13
+ const stringConstraintKeywords = [ 'minLength', 'maxLength' ];
14
+ const arrayConstraintKeywords = [ 'minItems', 'maxItems', 'minContains', 'maxContains' ];
15
+
16
+ function isRecord(value: unknown): value is Record<string, unknown> {
17
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
18
+ }
19
+
20
+ function pathSegment(segment: string | number): string {
21
+ return String(segment).replaceAll('~', '~0').replaceAll('/', '~1');
22
+ }
23
+
24
+ function appendPath(path: string, segment: string | number): string {
25
+ return `${path}/${pathSegment(segment)}`;
26
+ }
27
+
28
+ function hasOwnProperty(value: Record<string, unknown>, property: string): boolean {
29
+ return Object.hasOwn(value, property);
30
+ }
31
+
32
+ function addError(errors: TagValidationError[], instancePath: string, message: string): void {
33
+ errors.push({ instancePath, message });
34
+ }
35
+
36
+ function isNumber(value: unknown): value is number {
37
+ return typeof value === 'number' && Number.isFinite(value);
38
+ }
39
+
40
+ function valuesEqual(left: unknown, right: unknown): boolean {
41
+ if (Object.is(left, right)) {
42
+ return true;
43
+ }
44
+
45
+ if (Array.isArray(left) && Array.isArray(right)) {
46
+ return left.length === right.length && left.every((value, index) => valuesEqual(value, right[index]));
47
+ }
48
+
49
+ if (isRecord(left) && isRecord(right)) {
50
+ const leftKeys = Object.keys(left);
51
+ const rightKeys = Object.keys(right);
52
+
53
+ return leftKeys.length === rightKeys.length
54
+ && leftKeys.every(key => Object.hasOwn(right, key) && valuesEqual(left[key], right[key]));
55
+ }
56
+
57
+ return false;
58
+ }
59
+
60
+ function getTagSchemas(tagsDefinition: ProtocolTagsDefinition): Record<string, TagSchema> {
61
+ const schemas: Record<string, TagSchema> = {};
62
+
63
+ for (const [ tag, schema ] of Object.entries(tagsDefinition)) {
64
+ if (tag === '$requiredTags' || tag === '$allowUndefinedTags') {
65
+ continue;
66
+ }
67
+
68
+ schemas[tag] = schema as TagSchema;
69
+ }
70
+
71
+ return schemas;
72
+ }
73
+
74
+ function validateSchemaConstraintTypes(
75
+ schema: Record<string, unknown>,
76
+ dataPath: string,
77
+ errors: TagValidationError[],
78
+ ): void {
79
+ if (schema.enum !== undefined) {
80
+ if (!Array.isArray(schema.enum) || schema.enum.length === 0) {
81
+ addError(errors, appendPath(dataPath, 'enum'), 'must be non-empty array');
82
+ }
83
+ }
84
+
85
+ for (const keyword of numericConstraintKeywords) {
86
+ if (schema[keyword] !== undefined && !isNumber(schema[keyword])) {
87
+ addError(errors, appendPath(dataPath, keyword), 'must be number');
88
+ }
89
+ }
90
+
91
+ for (const keyword of [ ...stringConstraintKeywords, ...arrayConstraintKeywords ]) {
92
+ if (schema[keyword] !== undefined && (!Number.isInteger(schema[keyword]) || (schema[keyword] as number) < 0)) {
93
+ addError(errors, appendPath(dataPath, keyword), 'must be integer');
94
+ }
95
+ }
96
+
97
+ if (schema.uniqueItems !== undefined && typeof schema.uniqueItems !== 'boolean') {
98
+ addError(errors, appendPath(dataPath, 'uniqueItems'), 'must be boolean');
99
+ }
100
+ }
101
+
102
+ function validateTagSubschemaDefinition(
103
+ schema: unknown,
104
+ dataPath: string,
105
+ allowedTypes: Set<string>,
106
+ errors: TagValidationError[],
107
+ ): void {
108
+ if (!isRecord(schema)) {
109
+ addError(errors, dataPath, 'must be object');
110
+ return;
111
+ }
112
+
113
+ if (schema.type !== undefined && (typeof schema.type !== 'string' || !allowedTypes.has(schema.type))) {
114
+ addError(errors, appendPath(dataPath, 'type'), 'must be equal to one of the allowed values');
115
+ }
116
+
117
+ validateSchemaConstraintTypes(schema, dataPath, errors);
118
+ }
119
+
120
+ /**
121
+ * Validates DWN protocol tag schema definitions without invoking Ajv's runtime compiler.
122
+ *
123
+ * The broader protocol message shape is already checked by the precompiled
124
+ * ProtocolRuleSet validator. This function covers the tag-schema constraints
125
+ * that are deliberately modeled as a small DWN subset rather than arbitrary
126
+ * JSON Schema.
127
+ */
128
+ export function validateProtocolTagSchemaDefinition(
129
+ schema: unknown,
130
+ dataVar: string,
131
+ ): string | undefined {
132
+ const errors: TagValidationError[] = [];
133
+
134
+ validateTagSubschemaDefinition(schema, '', allowedTagTypes, errors);
135
+
136
+ if (isRecord(schema)) {
137
+ if (schema.items !== undefined) {
138
+ validateTagSubschemaDefinition(schema.items, '/items', allowedArrayItemTypes, errors);
139
+ }
140
+
141
+ if (schema.contains !== undefined) {
142
+ validateTagSubschemaDefinition(schema.contains, '/contains', allowedArrayItemTypes, errors);
143
+ }
144
+ }
145
+
146
+ return formatTagValidationErrors(errors, dataVar);
147
+ }
148
+
149
+ function validateType(type: unknown, value: unknown, dataPath: string, errors: TagValidationError[]): boolean {
150
+ switch (type) {
151
+ case undefined:
152
+ return true;
153
+ case 'string':
154
+ if (typeof value === 'string') {
155
+ return true;
156
+ }
157
+ addError(errors, dataPath, 'must be string');
158
+ return false;
159
+ case 'number':
160
+ if (isNumber(value)) {
161
+ return true;
162
+ }
163
+ addError(errors, dataPath, 'must be number');
164
+ return false;
165
+ case 'integer':
166
+ if (isNumber(value) && Number.isInteger(value)) {
167
+ return true;
168
+ }
169
+ addError(errors, dataPath, 'must be integer');
170
+ return false;
171
+ case 'boolean':
172
+ if (typeof value === 'boolean') {
173
+ return true;
174
+ }
175
+ addError(errors, dataPath, 'must be boolean');
176
+ return false;
177
+ case 'array':
178
+ if (Array.isArray(value)) {
179
+ return true;
180
+ }
181
+ addError(errors, dataPath, 'must be array');
182
+ return false;
183
+ default:
184
+ addError(errors, dataPath, 'must match a supported tag schema type');
185
+ return false;
186
+ }
187
+ }
188
+
189
+ function validateEnum(schema: Record<string, unknown>, value: unknown, dataPath: string, errors: TagValidationError[]): void {
190
+ if (Array.isArray(schema.enum) && !schema.enum.some(allowed => valuesEqual(allowed, value))) {
191
+ addError(errors, dataPath, 'must be equal to one of the allowed values');
192
+ }
193
+ }
194
+
195
+ function validateNumberConstraints(
196
+ schema: Record<string, unknown>,
197
+ value: unknown,
198
+ dataPath: string,
199
+ errors: TagValidationError[],
200
+ ): void {
201
+ if (!isNumber(value)) {
202
+ return;
203
+ }
204
+
205
+ if (isNumber(schema.minimum) && value < schema.minimum) {
206
+ addError(errors, dataPath, `must be >= ${schema.minimum}`);
207
+ }
208
+
209
+ if (isNumber(schema.maximum) && value > schema.maximum) {
210
+ addError(errors, dataPath, `must be <= ${schema.maximum}`);
211
+ }
212
+
213
+ if (isNumber(schema.exclusiveMinimum) && value <= schema.exclusiveMinimum) {
214
+ addError(errors, dataPath, `must be > ${schema.exclusiveMinimum}`);
215
+ }
216
+
217
+ if (isNumber(schema.exclusiveMaximum) && value >= schema.exclusiveMaximum) {
218
+ addError(errors, dataPath, `must be < ${schema.exclusiveMaximum}`);
219
+ }
220
+ }
221
+
222
+ function validateStringConstraints(
223
+ schema: Record<string, unknown>,
224
+ value: unknown,
225
+ dataPath: string,
226
+ errors: TagValidationError[],
227
+ ): void {
228
+ if (typeof value !== 'string') {
229
+ return;
230
+ }
231
+
232
+ if (Number.isInteger(schema.minLength) && value.length < (schema.minLength as number)) {
233
+ addError(errors, dataPath, `must NOT have fewer than ${schema.minLength} characters`);
234
+ }
235
+
236
+ if (Number.isInteger(schema.maxLength) && value.length > (schema.maxLength as number)) {
237
+ addError(errors, dataPath, `must NOT have more than ${schema.maxLength} characters`);
238
+ }
239
+ }
240
+
241
+ function validateArrayConstraints(
242
+ schema: Record<string, unknown>,
243
+ value: unknown,
244
+ dataPath: string,
245
+ errors: TagValidationError[],
246
+ ): void {
247
+ if (!Array.isArray(value)) {
248
+ return;
249
+ }
250
+
251
+ if (Number.isInteger(schema.minItems) && value.length < (schema.minItems as number)) {
252
+ addError(errors, dataPath, `must NOT have fewer than ${schema.minItems} items`);
253
+ }
254
+
255
+ if (Number.isInteger(schema.maxItems) && value.length > (schema.maxItems as number)) {
256
+ addError(errors, dataPath, `must NOT have more than ${schema.maxItems} items`);
257
+ }
258
+
259
+ if (schema.uniqueItems === true) {
260
+ for (let i = 0; i < value.length; i++) {
261
+ for (let j = i + 1; j < value.length; j++) {
262
+ if (valuesEqual(value[i], value[j])) {
263
+ addError(errors, dataPath, 'must NOT have duplicate items');
264
+ return;
265
+ }
266
+ }
267
+ }
268
+ }
269
+ }
270
+
271
+ function validateTagValue(
272
+ schema: unknown,
273
+ value: unknown,
274
+ dataPath: string,
275
+ errors: TagValidationError[],
276
+ ): void {
277
+ if (!isRecord(schema)) {
278
+ addError(errors, dataPath, 'must match a supported tag schema');
279
+ return;
280
+ }
281
+
282
+ const validType = validateType(schema.type, value, dataPath, errors);
283
+ if (!validType) {
284
+ return;
285
+ }
286
+
287
+ validateEnum(schema, value, dataPath, errors);
288
+ validateNumberConstraints(schema, value, dataPath, errors);
289
+ validateStringConstraints(schema, value, dataPath, errors);
290
+ validateArrayConstraints(schema, value, dataPath, errors);
291
+
292
+ if (Array.isArray(value) && isRecord(schema.items)) {
293
+ value.forEach((item, index) => validateTagValue(schema.items, item, appendPath(dataPath, index), errors));
294
+ }
295
+
296
+ if (Array.isArray(value) && isRecord(schema.contains)) {
297
+ validateContains(schema, value, dataPath, errors);
298
+ }
299
+ }
300
+
301
+ function validateContains(
302
+ schema: Record<string, unknown>,
303
+ value: unknown[],
304
+ dataPath: string,
305
+ errors: TagValidationError[],
306
+ ): void {
307
+ const minimumCount = Number.isInteger(schema.minContains) ? schema.minContains as number : 1;
308
+ const maximumCount = Number.isInteger(schema.maxContains) ? schema.maxContains as number : undefined;
309
+ const validItemCount = value.filter(item => {
310
+ const itemErrors: TagValidationError[] = [];
311
+ validateTagValue(schema.contains, item, dataPath, itemErrors);
312
+ return itemErrors.length === 0;
313
+ }).length;
314
+
315
+ if (validItemCount < minimumCount || (maximumCount !== undefined && validItemCount > maximumCount)) {
316
+ const message = maximumCount === undefined
317
+ ? `must contain at least ${minimumCount} valid item(s)`
318
+ : `must contain at least ${minimumCount} and no more than ${maximumCount} valid item(s)`;
319
+ addError(errors, dataPath, message);
320
+ }
321
+ }
322
+
323
+ /**
324
+ * Validates a record's `descriptor.tags` against a protocol rule set `$tags` definition.
325
+ */
326
+ export function validateProtocolTags(
327
+ tagsDefinition: ProtocolTagsDefinition,
328
+ tags: Record<string, unknown>,
329
+ dataVar: string,
330
+ ): string | undefined {
331
+ const errors: TagValidationError[] = [];
332
+ const tagSchemas = getTagSchemas(tagsDefinition);
333
+ const requiredTags = Array.isArray(tagsDefinition.$requiredTags) ? tagsDefinition.$requiredTags : [];
334
+
335
+ for (const requiredTag of requiredTags) {
336
+ if (!hasOwnProperty(tags, requiredTag)) {
337
+ addError(errors, '', `must have required property '${requiredTag}'`);
338
+ }
339
+ }
340
+
341
+ if (tagsDefinition.$allowUndefinedTags !== true) {
342
+ for (const tag of Object.keys(tags)) {
343
+ if (tagSchemas[tag] === undefined) {
344
+ addError(errors, '', 'must NOT have additional properties');
345
+ }
346
+ }
347
+ }
348
+
349
+ for (const [ tag, schema ] of Object.entries(tagSchemas)) {
350
+ if (hasOwnProperty(tags, tag)) {
351
+ validateTagValue(schema, tags[tag], appendPath('', tag), errors);
352
+ }
353
+ }
354
+
355
+ return formatTagValidationErrors(errors, dataVar);
356
+ }
357
+
358
+ function formatTagValidationErrors(errors: TagValidationError[], dataVar: string): string | undefined {
359
+ if (errors.length === 0) {
360
+ return undefined;
361
+ }
362
+
363
+ return errors
364
+ .map(error => `${dataVar}${error.instancePath} ${error.message}`)
365
+ .join(', ');
366
+ }