@enbox/dwn-sdk-js 0.4.5 → 0.4.7

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 (369) hide show
  1. package/README.md +3 -1
  2. package/dist/browser.mjs +19 -78
  3. package/dist/browser.mjs.map +4 -4
  4. package/dist/esm/generated/precompiled-validators.js +4465 -3861
  5. package/dist/esm/generated/precompiled-validators.js.map +1 -1
  6. package/dist/esm/src/core/constants.js +50 -0
  7. package/dist/esm/src/core/constants.js.map +1 -1
  8. package/dist/esm/src/core/dwn-error.js +28 -11
  9. package/dist/esm/src/core/dwn-error.js.map +1 -1
  10. package/dist/esm/src/core/encryption-control.js +785 -0
  11. package/dist/esm/src/core/encryption-control.js.map +1 -0
  12. package/dist/esm/src/core/message.js +6 -0
  13. package/dist/esm/src/core/message.js.map +1 -1
  14. package/dist/esm/src/core/messages-grant-authorization.js +36 -5
  15. package/dist/esm/src/core/messages-grant-authorization.js.map +1 -1
  16. package/dist/esm/src/core/protocol-authorization-action.js +3 -12
  17. package/dist/esm/src/core/protocol-authorization-action.js.map +1 -1
  18. package/dist/esm/src/core/protocol-authorization-validation.js +31 -30
  19. package/dist/esm/src/core/protocol-authorization-validation.js.map +1 -1
  20. package/dist/esm/src/core/protocol-authorization.js +6 -0
  21. package/dist/esm/src/core/protocol-authorization.js.map +1 -1
  22. package/dist/esm/src/core/recording-validation-state-reader.js +3 -3
  23. package/dist/esm/src/core/recording-validation-state-reader.js.map +1 -1
  24. package/dist/esm/src/core/replication-apply.js +62 -108
  25. package/dist/esm/src/core/replication-apply.js.map +1 -1
  26. package/dist/esm/src/core/validation-state-reader.js +5 -6
  27. package/dist/esm/src/core/validation-state-reader.js.map +1 -1
  28. package/dist/esm/src/dwn.js +1 -2
  29. package/dist/esm/src/dwn.js.map +1 -1
  30. package/dist/esm/src/event-stream/event-emitter-wake-publisher.js +11 -11
  31. package/dist/esm/src/event-stream/event-emitter-wake-publisher.js.map +1 -1
  32. package/dist/esm/src/handlers/messages-query.js +6 -16
  33. package/dist/esm/src/handlers/messages-query.js.map +1 -1
  34. package/dist/esm/src/handlers/messages-read.js +4 -3
  35. package/dist/esm/src/handlers/messages-read.js.map +1 -1
  36. package/dist/esm/src/handlers/messages-subscribe.js +26 -30
  37. package/dist/esm/src/handlers/messages-subscribe.js.map +1 -1
  38. package/dist/esm/src/handlers/protocols-configure.js +6 -4
  39. package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
  40. package/dist/esm/src/handlers/records-count.js +85 -10
  41. package/dist/esm/src/handlers/records-count.js.map +1 -1
  42. package/dist/esm/src/handlers/records-delete.js +11 -0
  43. package/dist/esm/src/handlers/records-delete.js.map +1 -1
  44. package/dist/esm/src/handlers/records-query.js +140 -18
  45. package/dist/esm/src/handlers/records-query.js.map +1 -1
  46. package/dist/esm/src/handlers/records-read.js +20 -4
  47. package/dist/esm/src/handlers/records-read.js.map +1 -1
  48. package/dist/esm/src/handlers/records-subscribe.js +127 -11
  49. package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
  50. package/dist/esm/src/handlers/records-write.js +15 -0
  51. package/dist/esm/src/handlers/records-write.js.map +1 -1
  52. package/dist/esm/src/index.js +7 -10
  53. package/dist/esm/src/index.js.map +1 -1
  54. package/dist/esm/src/interfaces/protocols-configure.js +66 -9
  55. package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
  56. package/dist/esm/src/interfaces/records-write.js +43 -36
  57. package/dist/esm/src/interfaces/records-write.js.map +1 -1
  58. package/dist/esm/src/jose/algorithms/signing/ed25519.js +5 -5
  59. package/dist/esm/src/jose/algorithms/signing/ed25519.js.map +1 -1
  60. package/dist/esm/src/jose/jws/general/verifier.js +1 -1
  61. package/dist/esm/src/jose/jws/general/verifier.js.map +1 -1
  62. package/dist/esm/src/protocols/encryption.js +32 -274
  63. package/dist/esm/src/protocols/encryption.js.map +1 -1
  64. package/dist/esm/src/store/blockstore-level.js +14 -23
  65. package/dist/esm/src/store/blockstore-level.js.map +1 -1
  66. package/dist/esm/src/store/blockstore-mock.js +10 -27
  67. package/dist/esm/src/store/blockstore-mock.js.map +1 -1
  68. package/dist/esm/src/store/blockstore-utils.js +45 -0
  69. package/dist/esm/src/store/blockstore-utils.js.map +1 -0
  70. package/dist/esm/src/store/blockstore.js +2 -0
  71. package/dist/esm/src/store/blockstore.js.map +1 -0
  72. package/dist/esm/src/store/data-store-level.js +4 -12
  73. package/dist/esm/src/store/data-store-level.js.map +1 -1
  74. package/dist/esm/src/store/level.js +7 -0
  75. package/dist/esm/src/store/level.js.map +1 -0
  76. package/dist/esm/src/types/encryption-types.js +4 -1
  77. package/dist/esm/src/types/encryption-types.js.map +1 -1
  78. package/dist/esm/src/utils/data-stream.js +25 -0
  79. package/dist/esm/src/utils/data-stream.js.map +1 -1
  80. package/dist/esm/src/utils/encryption.js +142 -34
  81. package/dist/esm/src/utils/encryption.js.map +1 -1
  82. package/dist/esm/src/utils/grant-key-coverage.js +180 -0
  83. package/dist/esm/src/utils/grant-key-coverage.js.map +1 -0
  84. package/dist/esm/src/utils/hd-key.js +1 -2
  85. package/dist/esm/src/utils/hd-key.js.map +1 -1
  86. package/dist/esm/src/utils/jws.js +7 -1
  87. package/dist/esm/src/utils/jws.js.map +1 -1
  88. package/dist/esm/src/utils/memory-cache.js +29 -8
  89. package/dist/esm/src/utils/memory-cache.js.map +1 -1
  90. package/dist/esm/src/utils/protocols.js +27 -0
  91. package/dist/esm/src/utils/protocols.js.map +1 -1
  92. package/dist/esm/src/utils/record-limit-occupancy.js +23 -3
  93. package/dist/esm/src/utils/record-limit-occupancy.js.map +1 -1
  94. package/dist/esm/src/utils/records.js +29 -0
  95. package/dist/esm/src/utils/records.js.map +1 -1
  96. package/dist/esm/src/utils/secp256k1.js +12 -11
  97. package/dist/esm/src/utils/secp256k1.js.map +1 -1
  98. package/dist/esm/src/utils/secp256r1.js +12 -20
  99. package/dist/esm/src/utils/secp256r1.js.map +1 -1
  100. package/dist/esm/src/utils/time.js +103 -25
  101. package/dist/esm/src/utils/time.js.map +1 -1
  102. package/dist/esm/tests/core/constants.spec.js +35 -0
  103. package/dist/esm/tests/core/constants.spec.js.map +1 -0
  104. package/dist/esm/tests/core/encryption-control.spec.js +100 -0
  105. package/dist/esm/tests/core/encryption-control.spec.js.map +1 -0
  106. package/dist/esm/tests/core/message.spec.js +35 -0
  107. package/dist/esm/tests/core/message.spec.js.map +1 -1
  108. package/dist/esm/tests/core/protocol-authorization.spec.js +1 -1
  109. package/dist/esm/tests/core/protocol-authorization.spec.js.map +1 -1
  110. package/dist/esm/tests/core/replication-apply.spec.js +157 -74
  111. package/dist/esm/tests/core/replication-apply.spec.js.map +1 -1
  112. package/dist/esm/tests/core/replication-replay-property.spec.js +2 -1
  113. package/dist/esm/tests/core/replication-replay-property.spec.js.map +1 -1
  114. package/dist/esm/tests/core/validation-read-closure.spec.js +14 -28
  115. package/dist/esm/tests/core/validation-read-closure.spec.js.map +1 -1
  116. package/dist/esm/tests/core/validation-state-reader.spec.js +19 -23
  117. package/dist/esm/tests/core/validation-state-reader.spec.js.map +1 -1
  118. package/dist/esm/tests/dwn.spec.js +2 -1
  119. package/dist/esm/tests/dwn.spec.js.map +1 -1
  120. package/dist/esm/tests/event-emitter-wake-publisher.spec.js +51 -0
  121. package/dist/esm/tests/event-emitter-wake-publisher.spec.js.map +1 -0
  122. package/dist/esm/tests/features/protocol-composition.spec.js +1 -1
  123. package/dist/esm/tests/features/protocol-composition.spec.js.map +1 -1
  124. package/dist/esm/tests/features/records-record-limit.spec.js +1 -1
  125. package/dist/esm/tests/features/records-record-limit.spec.js.map +1 -1
  126. package/dist/esm/tests/fuzz/encryption.fuzz.spec.js +9 -1
  127. package/dist/esm/tests/fuzz/encryption.fuzz.spec.js.map +1 -1
  128. package/dist/esm/tests/fuzz/process-message.fuzz.spec.js +1 -1
  129. package/dist/esm/tests/fuzz/process-message.fuzz.spec.js.map +1 -1
  130. package/dist/esm/tests/fuzz/protocols-utils.fuzz.spec.js +29 -1
  131. package/dist/esm/tests/fuzz/protocols-utils.fuzz.spec.js.map +1 -1
  132. package/dist/esm/tests/fuzz/secp256k1.fuzz.spec.js +2 -2
  133. package/dist/esm/tests/fuzz/secp256k1.fuzz.spec.js.map +1 -1
  134. package/dist/esm/tests/fuzz/time.fuzz.spec.js +7 -1
  135. package/dist/esm/tests/fuzz/time.fuzz.spec.js.map +1 -1
  136. package/dist/esm/tests/handlers/messages-query.spec.js +123 -11
  137. package/dist/esm/tests/handlers/messages-query.spec.js.map +1 -1
  138. package/dist/esm/tests/handlers/messages-read.spec.js +95 -0
  139. package/dist/esm/tests/handlers/messages-read.spec.js.map +1 -1
  140. package/dist/esm/tests/handlers/messages-subscribe.spec.js +90 -0
  141. package/dist/esm/tests/handlers/messages-subscribe.spec.js.map +1 -1
  142. package/dist/esm/tests/handlers/protocols-configure.spec.js +66 -0
  143. package/dist/esm/tests/handlers/protocols-configure.spec.js.map +1 -1
  144. package/dist/esm/tests/handlers/records-count.spec.js +370 -0
  145. package/dist/esm/tests/handlers/records-count.spec.js.map +1 -1
  146. package/dist/esm/tests/handlers/records-delete.spec.js +70 -1
  147. package/dist/esm/tests/handlers/records-delete.spec.js.map +1 -1
  148. package/dist/esm/tests/handlers/records-query.spec.js +562 -1
  149. package/dist/esm/tests/handlers/records-query.spec.js.map +1 -1
  150. package/dist/esm/tests/handlers/records-read.spec.js +140 -2
  151. package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
  152. package/dist/esm/tests/handlers/records-subscribe.spec.js +241 -1
  153. package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
  154. package/dist/esm/tests/handlers/records-write.spec.js +1187 -29
  155. package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
  156. package/dist/esm/tests/interfaces/protocols-configure.spec.js +290 -2
  157. package/dist/esm/tests/interfaces/protocols-configure.spec.js.map +1 -1
  158. package/dist/esm/tests/interfaces/records-write.spec.js +47 -5
  159. package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
  160. package/dist/esm/tests/protocols/encryption.spec.js +116 -472
  161. package/dist/esm/tests/protocols/encryption.spec.js.map +1 -1
  162. package/dist/esm/tests/scenarios/end-to-end-tests.spec.js +13 -27
  163. package/dist/esm/tests/scenarios/end-to-end-tests.spec.js.map +1 -1
  164. package/dist/esm/tests/store/blockstore-level.spec.js +33 -10
  165. package/dist/esm/tests/store/blockstore-level.spec.js.map +1 -1
  166. package/dist/esm/tests/store/blockstore-mock.spec.js +31 -7
  167. package/dist/esm/tests/store/blockstore-mock.spec.js.map +1 -1
  168. package/dist/esm/tests/store/blockstore-utils.spec.js +115 -0
  169. package/dist/esm/tests/store/blockstore-utils.spec.js.map +1 -0
  170. package/dist/esm/tests/store/index-level.spec.js +3 -3
  171. package/dist/esm/tests/store/index-level.spec.js.map +1 -1
  172. package/dist/esm/tests/test-stores.js +2 -1
  173. package/dist/esm/tests/test-stores.js.map +1 -1
  174. package/dist/esm/tests/utils/cid.spec.js +15 -0
  175. package/dist/esm/tests/utils/cid.spec.js.map +1 -1
  176. package/dist/esm/tests/utils/data-stream.spec.js +30 -0
  177. package/dist/esm/tests/utils/data-stream.spec.js.map +1 -1
  178. package/dist/esm/tests/utils/encryption-control-test-utils.js +111 -0
  179. package/dist/esm/tests/utils/encryption-control-test-utils.js.map +1 -0
  180. package/dist/esm/tests/utils/encryption.spec.js +240 -67
  181. package/dist/esm/tests/utils/encryption.spec.js.map +1 -1
  182. package/dist/esm/tests/utils/grant-key-coverage.spec.js +262 -0
  183. package/dist/esm/tests/utils/grant-key-coverage.spec.js.map +1 -0
  184. package/dist/esm/tests/utils/memory-cache.spec.js +12 -0
  185. package/dist/esm/tests/utils/memory-cache.spec.js.map +1 -1
  186. package/dist/esm/tests/utils/secp256r1.spec.js +2 -2
  187. package/dist/esm/tests/utils/secp256r1.spec.js.map +1 -1
  188. package/dist/esm/tests/utils/test-data-generator.js +2 -1
  189. package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
  190. package/dist/esm/tests/utils/test-validation-state-reader.js +1 -1
  191. package/dist/esm/tests/utils/test-validation-state-reader.js.map +1 -1
  192. package/dist/esm/tests/utils/time.spec.js +26 -0
  193. package/dist/esm/tests/utils/time.spec.js.map +1 -1
  194. package/dist/esm/tests/validation/json-schemas/encryption/audience.spec.js +45 -0
  195. package/dist/esm/tests/validation/json-schemas/encryption/audience.spec.js.map +1 -0
  196. package/dist/esm/tests/validation/json-schemas/encryption/delivery.spec.js +47 -0
  197. package/dist/esm/tests/validation/json-schemas/encryption/delivery.spec.js.map +1 -0
  198. package/dist/esm/tests/validation/json-schemas/encryption/grant-key.spec.js +25 -16
  199. package/dist/esm/tests/validation/json-schemas/encryption/grant-key.spec.js.map +1 -1
  200. package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js +152 -0
  201. package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js.map +1 -1
  202. package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js +46 -1
  203. package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js.map +1 -1
  204. package/dist/types/generated/precompiled-validators.d.ts +4 -4
  205. package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
  206. package/dist/types/src/core/constants.d.ts +39 -0
  207. package/dist/types/src/core/constants.d.ts.map +1 -1
  208. package/dist/types/src/core/dwn-error.d.ts +28 -11
  209. package/dist/types/src/core/dwn-error.d.ts.map +1 -1
  210. package/dist/types/src/core/encryption-control.d.ts +128 -0
  211. package/dist/types/src/core/encryption-control.d.ts.map +1 -0
  212. package/dist/types/src/core/message.d.ts +4 -0
  213. package/dist/types/src/core/message.d.ts.map +1 -1
  214. package/dist/types/src/core/messages-grant-authorization.d.ts +11 -0
  215. package/dist/types/src/core/messages-grant-authorization.d.ts.map +1 -1
  216. package/dist/types/src/core/protocol-authorization-action.d.ts.map +1 -1
  217. package/dist/types/src/core/protocol-authorization-validation.d.ts.map +1 -1
  218. package/dist/types/src/core/protocol-authorization.d.ts.map +1 -1
  219. package/dist/types/src/core/recording-validation-state-reader.d.ts +2 -3
  220. package/dist/types/src/core/recording-validation-state-reader.d.ts.map +1 -1
  221. package/dist/types/src/core/replication-apply.d.ts +10 -1
  222. package/dist/types/src/core/replication-apply.d.ts.map +1 -1
  223. package/dist/types/src/core/validation-state-reader.d.ts +2 -3
  224. package/dist/types/src/core/validation-state-reader.d.ts.map +1 -1
  225. package/dist/types/src/dwn.d.ts.map +1 -1
  226. package/dist/types/src/event-stream/event-emitter-wake-publisher.d.ts +1 -1
  227. package/dist/types/src/event-stream/event-emitter-wake-publisher.d.ts.map +1 -1
  228. package/dist/types/src/handlers/messages-query.d.ts.map +1 -1
  229. package/dist/types/src/handlers/messages-read.d.ts.map +1 -1
  230. package/dist/types/src/handlers/messages-subscribe.d.ts.map +1 -1
  231. package/dist/types/src/handlers/protocols-configure.d.ts +1 -0
  232. package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
  233. package/dist/types/src/handlers/records-count.d.ts +2 -0
  234. package/dist/types/src/handlers/records-count.d.ts.map +1 -1
  235. package/dist/types/src/handlers/records-delete.d.ts.map +1 -1
  236. package/dist/types/src/handlers/records-query.d.ts +3 -0
  237. package/dist/types/src/handlers/records-query.d.ts.map +1 -1
  238. package/dist/types/src/handlers/records-read.d.ts.map +1 -1
  239. package/dist/types/src/handlers/records-subscribe.d.ts +2 -0
  240. package/dist/types/src/handlers/records-subscribe.d.ts.map +1 -1
  241. package/dist/types/src/handlers/records-write.d.ts.map +1 -1
  242. package/dist/types/src/index.d.ts +10 -17
  243. package/dist/types/src/index.d.ts.map +1 -1
  244. package/dist/types/src/interfaces/protocols-configure.d.ts +13 -1
  245. package/dist/types/src/interfaces/protocols-configure.d.ts.map +1 -1
  246. package/dist/types/src/interfaces/records-write.d.ts +5 -1
  247. package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
  248. package/dist/types/src/jose/algorithms/signing/ed25519.d.ts.map +1 -1
  249. package/dist/types/src/protocols/encryption.d.ts +2 -19
  250. package/dist/types/src/protocols/encryption.d.ts.map +1 -1
  251. package/dist/types/src/store/blockstore-level.d.ts +11 -11
  252. package/dist/types/src/store/blockstore-level.d.ts.map +1 -1
  253. package/dist/types/src/store/blockstore-mock.d.ts +12 -12
  254. package/dist/types/src/store/blockstore-mock.d.ts.map +1 -1
  255. package/dist/types/src/store/blockstore-utils.d.ts +23 -0
  256. package/dist/types/src/store/blockstore-utils.d.ts.map +1 -0
  257. package/dist/types/src/store/blockstore.d.ts +3 -0
  258. package/dist/types/src/store/blockstore.d.ts.map +1 -0
  259. package/dist/types/src/store/data-store-level.d.ts.map +1 -1
  260. package/dist/types/src/store/level.d.ts +13 -0
  261. package/dist/types/src/store/level.d.ts.map +1 -0
  262. package/dist/types/src/types/cache.d.ts +2 -2
  263. package/dist/types/src/types/cache.d.ts.map +1 -1
  264. package/dist/types/src/types/encryption-types.d.ts +31 -2
  265. package/dist/types/src/types/encryption-types.d.ts.map +1 -1
  266. package/dist/types/src/types/validation-state-reader.d.ts +3 -5
  267. package/dist/types/src/types/validation-state-reader.d.ts.map +1 -1
  268. package/dist/types/src/utils/data-stream.d.ts +5 -0
  269. package/dist/types/src/utils/data-stream.d.ts.map +1 -1
  270. package/dist/types/src/utils/encryption.d.ts +58 -22
  271. package/dist/types/src/utils/encryption.d.ts.map +1 -1
  272. package/dist/types/src/utils/grant-key-coverage.d.ts +36 -0
  273. package/dist/types/src/utils/grant-key-coverage.d.ts.map +1 -0
  274. package/dist/types/src/utils/hd-key.d.ts.map +1 -1
  275. package/dist/types/src/utils/jws.d.ts.map +1 -1
  276. package/dist/types/src/utils/memory-cache.d.ts +4 -2
  277. package/dist/types/src/utils/memory-cache.d.ts.map +1 -1
  278. package/dist/types/src/utils/protocols.d.ts +11 -0
  279. package/dist/types/src/utils/protocols.d.ts.map +1 -1
  280. package/dist/types/src/utils/record-limit-occupancy.d.ts +7 -0
  281. package/dist/types/src/utils/record-limit-occupancy.d.ts.map +1 -1
  282. package/dist/types/src/utils/records.d.ts +2 -0
  283. package/dist/types/src/utils/records.d.ts.map +1 -1
  284. package/dist/types/src/utils/secp256k1.d.ts.map +1 -1
  285. package/dist/types/src/utils/secp256r1.d.ts.map +1 -1
  286. package/dist/types/src/utils/time.d.ts +21 -13
  287. package/dist/types/src/utils/time.d.ts.map +1 -1
  288. package/dist/types/tests/core/constants.spec.d.ts +2 -0
  289. package/dist/types/tests/core/constants.spec.d.ts.map +1 -0
  290. package/dist/types/tests/core/encryption-control.spec.d.ts +2 -0
  291. package/dist/types/tests/core/encryption-control.spec.d.ts.map +1 -0
  292. package/dist/types/tests/dwn.spec.d.ts.map +1 -1
  293. package/dist/types/tests/event-emitter-wake-publisher.spec.d.ts +2 -0
  294. package/dist/types/tests/event-emitter-wake-publisher.spec.d.ts.map +1 -0
  295. package/dist/types/tests/handlers/messages-query.spec.d.ts.map +1 -1
  296. package/dist/types/tests/handlers/messages-read.spec.d.ts.map +1 -1
  297. package/dist/types/tests/handlers/messages-subscribe.spec.d.ts.map +1 -1
  298. package/dist/types/tests/handlers/protocols-configure.spec.d.ts.map +1 -1
  299. package/dist/types/tests/handlers/records-count.spec.d.ts.map +1 -1
  300. package/dist/types/tests/handlers/records-delete.spec.d.ts.map +1 -1
  301. package/dist/types/tests/handlers/records-query.spec.d.ts.map +1 -1
  302. package/dist/types/tests/handlers/records-read.spec.d.ts.map +1 -1
  303. package/dist/types/tests/handlers/records-subscribe.spec.d.ts.map +1 -1
  304. package/dist/types/tests/handlers/records-write.spec.d.ts.map +1 -1
  305. package/dist/types/tests/scenarios/end-to-end-tests.spec.d.ts.map +1 -1
  306. package/dist/types/tests/store/blockstore-utils.spec.d.ts +2 -0
  307. package/dist/types/tests/store/blockstore-utils.spec.d.ts.map +1 -0
  308. package/dist/types/tests/test-stores.d.ts.map +1 -1
  309. package/dist/types/tests/utils/encryption-control-test-utils.d.ts +46 -0
  310. package/dist/types/tests/utils/encryption-control-test-utils.d.ts.map +1 -0
  311. package/dist/types/tests/utils/grant-key-coverage.spec.d.ts +2 -0
  312. package/dist/types/tests/utils/grant-key-coverage.spec.d.ts.map +1 -0
  313. package/dist/types/tests/utils/test-data-generator.d.ts.map +1 -1
  314. package/dist/types/tests/validation/json-schemas/encryption/audience.spec.d.ts +2 -0
  315. package/dist/types/tests/validation/json-schemas/encryption/audience.spec.d.ts.map +1 -0
  316. package/dist/types/tests/validation/json-schemas/encryption/delivery.spec.d.ts +2 -0
  317. package/dist/types/tests/validation/json-schemas/encryption/delivery.spec.d.ts.map +1 -0
  318. package/package.json +47 -28
  319. package/src/core/constants.ts +61 -0
  320. package/src/core/dwn-error.ts +28 -11
  321. package/src/core/encryption-control.ts +1249 -0
  322. package/src/core/message.ts +7 -0
  323. package/src/core/messages-grant-authorization.ts +60 -9
  324. package/src/core/protocol-authorization-action.ts +3 -13
  325. package/src/core/protocol-authorization-validation.ts +66 -46
  326. package/src/core/protocol-authorization.ts +7 -0
  327. package/src/core/recording-validation-state-reader.ts +4 -5
  328. package/src/core/replication-apply.ts +77 -133
  329. package/src/core/validation-state-reader.ts +6 -8
  330. package/src/dwn.ts +1 -2
  331. package/src/event-stream/event-emitter-wake-publisher.ts +10 -14
  332. package/src/handlers/messages-query.ts +6 -22
  333. package/src/handlers/messages-read.ts +4 -3
  334. package/src/handlers/messages-subscribe.ts +34 -30
  335. package/src/handlers/protocols-configure.ts +7 -4
  336. package/src/handlers/records-count.ts +111 -10
  337. package/src/handlers/records-delete.ts +15 -0
  338. package/src/handlers/records-query.ts +176 -20
  339. package/src/handlers/records-read.ts +19 -6
  340. package/src/handlers/records-subscribe.ts +158 -8
  341. package/src/handlers/records-write.ts +19 -0
  342. package/src/index.ts +48 -21
  343. package/src/interfaces/protocols-configure.ts +102 -11
  344. package/src/interfaces/records-write.ts +49 -43
  345. package/src/jose/algorithms/signing/ed25519.ts +7 -6
  346. package/src/jose/jws/general/verifier.ts +3 -3
  347. package/src/protocols/encryption.ts +50 -420
  348. package/src/store/blockstore-level.ts +33 -37
  349. package/src/store/blockstore-mock.ts +24 -38
  350. package/src/store/blockstore-utils.ts +85 -0
  351. package/src/store/blockstore.ts +8 -0
  352. package/src/store/data-store-level.ts +5 -12
  353. package/src/store/level.ts +19 -0
  354. package/src/types/cache.ts +3 -3
  355. package/src/types/encryption-types.ts +39 -2
  356. package/src/types/validation-state-reader.ts +3 -5
  357. package/src/utils/data-stream.ts +29 -1
  358. package/src/utils/encryption.ts +247 -69
  359. package/src/utils/grant-key-coverage.ts +303 -0
  360. package/src/utils/hd-key.ts +1 -2
  361. package/src/utils/jws.ts +8 -2
  362. package/src/utils/memory-cache.ts +42 -11
  363. package/src/utils/protocols.ts +32 -0
  364. package/src/utils/record-limit-occupancy.ts +34 -5
  365. package/src/utils/records.ts +36 -2
  366. package/src/utils/secp256k1.ts +12 -12
  367. package/src/utils/secp256r1.ts +12 -22
  368. package/src/utils/time.ts +145 -27
  369. package/src/types/mitt.d.ts +0 -28
@@ -6,6 +6,7 @@ import type { RecordsQueryReplyEntry, RecordsSubscribeMessage, RecordsSubscribeR
6
6
 
7
7
  import { authenticate } from '../core/auth.js';
8
8
  import { DateSort } from '../types/records-types.js';
9
+ import { EncryptionControl } from '../core/encryption-control.js';
9
10
  import { Message } from '../core/message.js';
10
11
  import { messageReplyFromError } from '../core/message-reply.js';
11
12
  import { ProtocolAuthorization } from '../core/protocol-authorization.js';
@@ -52,6 +53,7 @@ export class RecordsSubscribeHandler implements MethodHandler {
52
53
 
53
54
  let eventFilters: Filter[] = [];
54
55
  let queryFilters: Filter[] = [];
56
+ const requester = Message.getRequester(recordsSubscribe.message);
55
57
 
56
58
  // if this is an anonymous subscribe and the filter supports published records, subscribe to only published records
57
59
  if (Records.filterIncludesPublishedRecords(recordsSubscribe.message.descriptor.filter) && recordsSubscribe.author === undefined) {
@@ -82,6 +84,7 @@ export class RecordsSubscribeHandler implements MethodHandler {
82
84
  const { cursor: eventLogCursor } = recordsSubscribe.message.descriptor;
83
85
  const projectedSubscriptionHandler = RecordsSubscribeHandler.createRecordLimitOccupancyGuard({
84
86
  deps: this.deps,
87
+ eventFilters,
85
88
  recordsSubscribe,
86
89
  subscriptionHandler,
87
90
  tenant,
@@ -130,15 +133,14 @@ export class RecordsSubscribeHandler implements MethodHandler {
130
133
  try {
131
134
  const { dateSort, pagination } = recordsSubscribe.message.descriptor;
132
135
  const messageSort = RecordsSubscribeHandler.convertDateSort(dateSort);
133
- const queryResult = await queryRecordsWithRecordLimitOccupancy({
134
- messageStore : this.deps.messageStore,
135
- validationStateReader : this.deps.validationStateReader,
136
+ const queryResult = await this.queryRecordsWithVisibleControlFiltering(
136
137
  tenant,
137
- filters : queryFilters,
138
+ recordsSubscribe,
139
+ requester,
140
+ queryFilters,
138
141
  messageSort,
139
142
  pagination,
140
- messageTimestamp : recordsSubscribe.message.descriptor.messageTimestamp,
141
- });
143
+ );
142
144
  entries = queryResult.messages;
143
145
  paginationCursor = queryResult.cursor;
144
146
 
@@ -194,11 +196,13 @@ export class RecordsSubscribeHandler implements MethodHandler {
194
196
 
195
197
  private static createRecordLimitOccupancyGuard(input: {
196
198
  deps: HandlerDependencies;
199
+ eventFilters: Filter[];
197
200
  recordsSubscribe: RecordsSubscribe;
198
201
  subscriptionHandler: SubscriptionListener;
199
202
  tenant: string;
200
203
  }): ProjectedRecordsSubscriptionHandler {
201
- const { deps, recordsSubscribe, subscriptionHandler, tenant } = input;
204
+ const { deps, eventFilters, recordsSubscribe, subscriptionHandler, tenant } = input;
205
+ const requester = Message.getRequester(recordsSubscribe.message);
202
206
  let subscription: EventSubscription | undefined;
203
207
  let closeRequested = false;
204
208
  let terminalErrorEmitted = false;
@@ -230,6 +234,27 @@ export class RecordsSubscribeHandler implements MethodHandler {
230
234
  const deliverProjectedEvent = async (subscriptionEvent: SubscriptionEvent): Promise<void> => {
231
235
  const { message } = subscriptionEvent.event;
232
236
  if (Records.isRecordsWrite(message)) {
237
+ const visibleMessages = await EncryptionControl.filterVisibleControlRecords({
238
+ tenant,
239
+ incomingMessage : recordsSubscribe.message,
240
+ requester,
241
+ recordsWriteMessages : [message],
242
+ validationStateReader : deps.validationStateReader,
243
+ });
244
+ if (visibleMessages.length === 0) {
245
+ return;
246
+ }
247
+
248
+ const projectedMessages = await EncryptionControl.projectCurrentAudienceRecords({
249
+ messageStore : deps.messageStore,
250
+ tenant,
251
+ recordsWriteMessages : [message],
252
+ bypassFilters : eventFilters,
253
+ });
254
+ if (projectedMessages.length === 0) {
255
+ return;
256
+ }
257
+
233
258
  let isOccupant: boolean;
234
259
  try {
235
260
  isOccupant = await isRecordLimitOccupant({
@@ -315,6 +340,15 @@ export class RecordsSubscribeHandler implements MethodHandler {
315
340
  }
316
341
 
317
342
  if (Records.filterIncludesUnpublishedRecords(filter)) {
343
+ if (EncryptionControl.isExactAudienceFilter(filter)) {
344
+ filters.push({
345
+ ...Records.convertFilter(filter),
346
+ interface : DwnInterfaceName.Records,
347
+ method : [DwnMethodName.Write, DwnMethodName.Delete],
348
+ published : false,
349
+ });
350
+ }
351
+
318
352
  if (Records.shouldBuildUnpublishedAuthorFilter(filter, recordsSubscribe.author!)) {
319
353
  filters.push({
320
354
  ...Records.convertFilter(filter),
@@ -397,6 +431,10 @@ export class RecordsSubscribeHandler implements MethodHandler {
397
431
  }
398
432
 
399
433
  if (Records.filterIncludesUnpublishedRecords(filter)) {
434
+ if (EncryptionControl.isExactAudienceFilter(filter)) {
435
+ filters.push(Records.buildUnpublishedControlRecordsFilter(filter, dateSort));
436
+ }
437
+
400
438
  if (Records.shouldBuildUnpublishedAuthorFilter(filter, recordsSubscribe.author!)) {
401
439
  filters.push({
402
440
  ...Records.convertFilter(filter, dateSort),
@@ -465,8 +503,16 @@ export class RecordsSubscribeHandler implements MethodHandler {
465
503
  deps: HandlerDependencies,
466
504
  ): Promise<void> {
467
505
 
468
- if (Message.isSignedByAuthorDelegate(recordsSubscribe.message)) {
506
+ if (Message.isSignedByAuthorDelegate(recordsSubscribe.message) &&
507
+ !EncryptionControl.filterTargetsOnlyControlRecords(recordsSubscribe.message.descriptor.filter)) {
469
508
  await recordsSubscribe.authorizeDelegate(deps.validationStateReader);
509
+ } else if (EncryptionControl.filterTargetsOnlyControlRecords(recordsSubscribe.message.descriptor.filter)) {
510
+ await EncryptionControl.authorizeControlReadRequest({
511
+ tenant,
512
+ incomingMessage : recordsSubscribe.message,
513
+ requester : Message.getRequester(recordsSubscribe.message),
514
+ validationStateReader : deps.validationStateReader,
515
+ });
470
516
  }
471
517
 
472
518
  const permissionGrantId = Message.getPermissionGrantId(recordsSubscribe.signaturePayload!);
@@ -489,4 +535,108 @@ export class RecordsSubscribeHandler implements MethodHandler {
489
535
  await ProtocolAuthorization.authorizeQueryOrSubscribe(tenant, recordsSubscribe, deps.validationStateReader);
490
536
  }
491
537
  }
538
+
539
+ private async filterControlRecordsForNonOwner(
540
+ tenant: string,
541
+ recordsSubscribe: RecordsSubscribe,
542
+ requester: string | undefined,
543
+ recordsWrites: RecordsQueryReplyEntry[],
544
+ ): Promise<RecordsQueryReplyEntry[]> {
545
+ return EncryptionControl.filterVisibleControlRecords({
546
+ tenant,
547
+ incomingMessage : recordsSubscribe.message,
548
+ requester,
549
+ recordsWriteMessages : recordsWrites,
550
+ validationStateReader : this.deps.validationStateReader,
551
+ });
552
+ }
553
+
554
+ private async queryRecordsWithVisibleControlFiltering(
555
+ tenant: string,
556
+ recordsSubscribe: RecordsSubscribe,
557
+ requester: string | undefined,
558
+ filters: Filter[],
559
+ messageSort: MessageSort,
560
+ pagination: { cursor?: PaginationCursor; limit?: number } | undefined,
561
+ ): Promise<{ messages: RecordsQueryReplyEntry[], cursor?: PaginationCursor }> {
562
+ const controlFilters = Records.buildControlRecordsFilters(filters);
563
+ const currentAudienceRecordIdCache = new Map<string, string | undefined>();
564
+ if (controlFilters.length === 0) {
565
+ const result = await queryRecordsWithRecordLimitOccupancy({
566
+ messageStore : this.deps.messageStore,
567
+ validationStateReader : this.deps.validationStateReader,
568
+ tenant,
569
+ filters,
570
+ messageSort,
571
+ pagination,
572
+ messageTimestamp : recordsSubscribe.message.descriptor.messageTimestamp,
573
+ });
574
+ return EncryptionControl.projectCurrentAudienceRecordPage({
575
+ messageStore: this.deps.messageStore,
576
+ tenant,
577
+ filters,
578
+ currentAudienceRecordIdCache,
579
+ result,
580
+ });
581
+ }
582
+
583
+ if (pagination?.limit === undefined || pagination.limit <= 0) {
584
+ const result = await queryRecordsWithRecordLimitOccupancy({
585
+ messageStore : this.deps.messageStore,
586
+ validationStateReader : this.deps.validationStateReader,
587
+ tenant,
588
+ filters,
589
+ messageSort,
590
+ pagination,
591
+ messageTimestamp : recordsSubscribe.message.descriptor.messageTimestamp,
592
+ });
593
+ const projectedResult = await EncryptionControl.projectCurrentAudienceRecordPage({
594
+ messageStore: this.deps.messageStore,
595
+ tenant,
596
+ filters,
597
+ currentAudienceRecordIdCache,
598
+ result,
599
+ });
600
+ return {
601
+ messages : await this.filterControlRecordsForNonOwner(tenant, recordsSubscribe, requester, projectedResult.messages),
602
+ cursor : projectedResult.cursor,
603
+ };
604
+ }
605
+
606
+ const visibleMessages: RecordsQueryReplyEntry[] = [];
607
+ let cursor = pagination.cursor;
608
+ let nextCursor: PaginationCursor | undefined;
609
+ // Keeps visible-page pagination stable until #1100 moves control visibility into indexed store filters.
610
+ do {
611
+ const remainingLimit = pagination.limit - visibleMessages.length;
612
+ const result = await queryRecordsWithRecordLimitOccupancy({
613
+ messageStore : this.deps.messageStore,
614
+ validationStateReader : this.deps.validationStateReader,
615
+ tenant,
616
+ filters,
617
+ messageSort,
618
+ pagination : { ...pagination, cursor, limit: remainingLimit },
619
+ messageTimestamp : recordsSubscribe.message.descriptor.messageTimestamp,
620
+ });
621
+ const projectedResult = await EncryptionControl.projectCurrentAudienceRecordPage({
622
+ messageStore: this.deps.messageStore,
623
+ tenant,
624
+ filters,
625
+ currentAudienceRecordIdCache,
626
+ result,
627
+ });
628
+ const filteredMessages = await this.filterControlRecordsForNonOwner(
629
+ tenant,
630
+ recordsSubscribe,
631
+ requester,
632
+ projectedResult.messages,
633
+ );
634
+ visibleMessages.push(...filteredMessages);
635
+ nextCursor = projectedResult.cursor;
636
+ cursor = projectedResult.cursor;
637
+ } while (visibleMessages.length < pagination.limit && cursor !== undefined);
638
+
639
+ return { messages: visibleMessages, cursor: nextCursor };
640
+ }
641
+
492
642
  }
@@ -8,6 +8,7 @@ import { Cid } from '../utils/cid.js';
8
8
  import { DataStream } from '../utils/data-stream.js';
9
9
  import { DwnConstant } from '../core/dwn-constant.js';
10
10
  import { Encoder } from '../utils/encoder.js';
11
+ import { EncryptionControl } from '../core/encryption-control.js';
11
12
  import { Message } from '../core/message.js';
12
13
  import { messageReplyFromError } from '../core/message-reply.js';
13
14
  import { ProtocolAuthorization } from '../core/protocol-authorization.js';
@@ -135,6 +136,15 @@ export class RecordsWriteHandler implements MethodHandler {
135
136
  if (coreProtocol?.preProcessWrite !== undefined) {
136
137
  await coreProtocol.preProcessWrite(tenant, message, this.deps.validationStateReader);
137
138
  }
139
+ if (EncryptionControl.isControlMessage(message)) {
140
+ await EncryptionControl.preProcessWrite(tenant, message, this.deps.validationStateReader);
141
+ if (dataStream === undefined) {
142
+ throw new DwnError(
143
+ DwnErrorCode.EncryptionControlValidateUnexpectedRecord,
144
+ 'encryption control records require data.'
145
+ );
146
+ }
147
+ }
138
148
 
139
149
  // NOTE: We allow isLatestBaseState to be true ONLY if the incoming message comes with data, or if the incoming message is NOT an initial write
140
150
  // This would allow an initial write to be written to the DB without data, but having it not queryable,
@@ -170,6 +180,7 @@ export class RecordsWriteHandler implements MethodHandler {
170
180
  error.code === DwnErrorCode.RecordsWriteDataCidMismatch ||
171
181
  error.code === DwnErrorCode.RecordsWriteDataSizeMismatch ||
172
182
  error.code.startsWith('SchemaValidator') ||
183
+ EncryptionControl.mapErrorToStatusCode(error.code) !== undefined ||
173
184
  this.deps.coreProtocols?.mapErrorToStatusCode(error.code) !== undefined) {
174
185
  return messageReplyFromError(error, 400);
175
186
  }
@@ -246,6 +257,9 @@ export class RecordsWriteHandler implements MethodHandler {
246
257
  if (coreProtocol?.validateRecord !== undefined) {
247
258
  await coreProtocol.validateRecord(message, dataBytes);
248
259
  }
260
+ if (EncryptionControl.isControlMessage(message)) {
261
+ await EncryptionControl.validateRecord({ tenant, message, dataBytes, validationStateReader: this.deps.validationStateReader });
262
+ }
249
263
 
250
264
  messageWithOptionalEncodedData = await this.cloneAndAddEncodedData(message, dataBytes);
251
265
  } else {
@@ -414,6 +428,11 @@ export class RecordsWriteHandler implements MethodHandler {
414
428
  );
415
429
  }
416
430
 
431
+ if (EncryptionControl.isControlMessage(recordsWrite.message)) {
432
+ await EncryptionControl.authorizeWrite(tenant, recordsWrite, this.deps.validationStateReader);
433
+ return;
434
+ }
435
+
417
436
  if (recordsWrite.isSignedByAuthorDelegate) {
418
437
  await recordsWrite.authorizeAuthorDelegate(this.deps.validationStateReader);
419
438
  }
package/src/index.ts CHANGED
@@ -16,7 +16,20 @@ export type { DataEncodedRecordsWriteMessage, RecordsCountDescriptor, RecordsCou
16
16
  export type { GeneralJws, SignatureEntry } from './types/jws-types.js';
17
17
  export { authenticate } from './core/auth.js';
18
18
  export { CoreProtocolRegistry } from './core/core-protocol.js';
19
- export { PERMISSIONS_REVOCATION_PATH } from './core/constants.js';
19
+ export { EncryptionControl } from './core/encryption-control.js';
20
+ export {
21
+ ENCRYPTION_CONTROL_AUDIENCE_PATH,
22
+ ENCRYPTION_CONTROL_AUDIENCE_SCHEMA_URI,
23
+ ENCRYPTION_CONTROL_DELIVERY_PATH,
24
+ ENCRYPTION_CONTROL_DELIVERY_SCHEMA_URI,
25
+ ENCRYPTION_CONTROL_PATHS,
26
+ ENCRYPTION_CONTROL_ROOT_PATH,
27
+ ENCRYPTION_PROTOCOL_URI,
28
+ EncryptionControlRecordType,
29
+ PERMISSIONS_REVOCATION_PATH,
30
+ isEncryptionControlPath,
31
+ } from './core/constants.js';
32
+ export type { EncryptionControlPath } from './core/constants.js';
20
33
  export type { CoreProtocol, CoreProtocolStores } from './core/core-protocol.js';
21
34
  export { AllowAllTenantGate } from './core/tenant-gate.js';
22
35
  export type { ActiveTenantCheckResult, TenantGate } from './core/tenant-gate.js';
@@ -28,6 +41,8 @@ export type { RecordsQueryOptions } from './interfaces/records-query.js';
28
41
  export type { DataStore, DataStorePutResult, DataStoreGetResult } from './types/data-store.js';
29
42
  export type { ResumableTaskStore, ManagedResumableTask } from './types/resumable-task-store.js';
30
43
  export { DataStream } from './utils/data-stream.js';
44
+ export { getGrantKeyDeliveryScopes, grantKeyScopeCoversDeliveredScope, isGrantKeyEligibleRecordsScope, isGrantKeyRecordsScope } from './utils/grant-key-coverage.js';
45
+ export type { GrantKeyEligibleRecordsScope, GrantKeyProtocolPathScope, GrantKeyReadRecordsScope, GrantKeyRecordsScope, GrantKeyWriteRecordsScope } from './utils/grant-key-coverage.js';
31
46
  export { HdKey, KeyDerivationScheme } from './utils/hd-key.js';
32
47
  export type { DerivedPrivateJwk } from './utils/hd-key.js';
33
48
  export { Dwn } from './dwn.js';
@@ -38,16 +53,21 @@ export { DwnInterfaceName, DwnMethodName } from './enums/dwn-interface-method.js
38
53
  export { Encoder } from './utils/encoder.js';
39
54
  export { MessagesSubscribe } from './interfaces/messages-subscribe.js';
40
55
  export type { MessagesSubscribeOptions } from './interfaces/messages-subscribe.js';
41
- export { Encryption, ContentEncryptionAlgorithm, KeyAgreementAlgorithm, ROLE_AUDIENCE_DERIVATION_SCHEME } from './utils/encryption.js';
56
+ export { Encryption, ContentEncryptionAlgorithm, KeyAgreementAlgorithm, ROLE_AUDIENCE_DERIVATION_SCHEME, SEAL_DERIVATION_SCHEME } from './utils/encryption.js';
42
57
  export type {
43
58
  DwnEncryption,
44
- KeyEncryption,
45
- KeyEncryptionInput,
46
59
  KeyUnwrapPayload,
47
60
  ProtocolPathKeyEncryption,
48
61
  ProtocolPathKeyEncryptionInput,
49
- RoleAudienceKeyEncryption,
50
- RoleAudienceKeyEncryptionInput,
62
+ SealKeyWrap,
63
+ SealKeyWrapInput,
64
+ SealUnwrapInput,
65
+ SealWrapInput,
66
+ SourceRoleAudienceKeyEncryption,
67
+ SourceRoleAudienceKeyEncryptionInput,
68
+ X25519KeyEncryption,
69
+ X25519KeyEncryptionInput,
70
+ X25519KeyWrapInput,
51
71
  } from './utils/encryption.js';
52
72
  export { RecordsWrite } from './interfaces/records-write.js';
53
73
  export type { EncryptionInput, RecordsWriteOptions, CreateFromOptions } from './interfaces/records-write.js';
@@ -72,7 +92,14 @@ export { PermissionScopeMatcher } from './utils/permission-scope.js';
72
92
  export type { ProtocolScope } from './utils/permission-scope.js';
73
93
  export { PrivateKeySigner } from './utils/private-key-signer.js';
74
94
  export type { PrivateKeySignerOptions } from './utils/private-key-signer.js';
75
- export { Protocols, parseCrossProtocolRef, isCrossProtocolRef, getRuleSetAtPath } from './utils/protocols.js';
95
+ export {
96
+ Protocols,
97
+ getRoleAudienceContextId,
98
+ getRoleContextPrefix,
99
+ getRuleSetAtPath,
100
+ isCrossProtocolRef,
101
+ parseCrossProtocolRef,
102
+ } from './utils/protocols.js';
76
103
  export type { CrossProtocolRef } from './utils/protocols.js';
77
104
  export { ProtocolsConfigure } from './interfaces/protocols-configure.js';
78
105
  export type { ProtocolsConfigureOptions } from './interfaces/protocols-configure.js';
@@ -90,24 +117,24 @@ export { Secp256r1 } from './utils/secp256r1.js';
90
117
  export type { SupportedCurve } from './jose/algorithms/signing/signature-algorithms.js';
91
118
  export type { MessageSigner } from './types/signer.js';
92
119
  export { SortDirection } from './types/query-types.js';
93
- export type { EncryptionKeyDeriver, KeyDecrypter, KeyDecrypterDerivationScheme } from './types/encryption-types.js';
120
+ export type {
121
+ EncryptionControlAudiencePayload,
122
+ EncryptionControlDeliveryPayload,
123
+ EncryptionControlDeliveryTags,
124
+ EncryptionControlSeal,
125
+ EncryptionKeyDeriver,
126
+ KeyDecrypter,
127
+ KeyDecrypterDerivationScheme,
128
+ RoleAudienceKeyId,
129
+ RoleAudienceKeyMaterial,
130
+ RoleAudienceTuple,
131
+ } from './types/encryption-types.js';
132
+ export { EncryptionControlDeliveryRecipientAuthority } from './types/encryption-types.js';
94
133
  export { Time } from './utils/time.js';
95
134
  export * from './types/permission-types.js';
96
135
  export * from './types/records-types.js';
97
136
 
98
- // concrete implementations of stores and event log
99
- export { BlockstoreLevel } from './store/blockstore-level.js';
100
- export type { BlockstoreLevelConfig } from './store/blockstore-level.js';
101
- export { DataStoreLevel } from './store/data-store-level.js';
102
- export type { DataStoreLevelConfig } from './store/data-store-level.js';
103
- export { IndexLevel } from './store/index-level.js';
104
- export type { CompoundIndexDefinition, IndexLevelConfig, IndexedItem, IndexLevelOptions } from './store/index-level.js';
105
- export { createLevelDatabase, LevelWrapper } from './store/level-wrapper.js';
106
- export type { CreateLevelDatabaseOptions, LevelDatabase, LevelWrapperConfig, LevelWrapperBatchOperation, LevelWrapperOptions, LevelWrapperIteratorOptions } from './store/level-wrapper.js';
107
- export { MessageStoreLevel } from './store/message-store-level.js';
108
- export type { MessageStoreLevelConfig } from './store/message-store-level.js';
109
- export { ResumableTaskStoreLevel } from './store/resumable-task-store-level.js';
110
- export type { ResumableTaskStoreLevelConfig } from './store/resumable-task-store-level.js';
137
+ // concrete event log implementations
111
138
  export { EventEmitterWakePublisher } from './event-stream/event-emitter-wake-publisher.js';
112
139
  export { DurableEventLog } from './event-stream/durable-event-log.js';
113
140
  export type { DurableEventLogConfig, DurableEventLogStore } from './event-stream/durable-event-log.js';
@@ -1,3 +1,4 @@
1
+ import type { CrossProtocolRef } from '../utils/protocols.js';
1
2
  import type { DataEncodedRecordsWriteMessage } from '../types/records-types.js';
2
3
  import type { MessageSigner } from '../types/signer.js';
3
4
  import type { ValidationStateReader } from '../types/validation-state-reader.js';
@@ -15,7 +16,7 @@ import { Time } from '../utils/time.js';
15
16
  import { validateProtocolTagSchemaDefinition } from '../utils/protocol-tags.js';
16
17
  import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
17
18
  import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
18
- import { getRuleSetAtPath, isCrossProtocolRef, parseCrossProtocolRef } from '../utils/protocols.js';
19
+ import { getRoleAudienceContextId, getRuleSetAtPath, isCrossProtocolRef, parseCrossProtocolRef } from '../utils/protocols.js';
19
20
  import { normalizeProtocolUrl, normalizeSchemaUrl, validateProtocolUrlNormalized, validateSchemaUrlNormalized } from '../utils/url.js';
20
21
  import { ProtocolAction, ProtocolActor, ProtocolRecordLimitStrategy } from '../types/protocols-types.js';
21
22
 
@@ -31,7 +32,10 @@ export type ProtocolsConfigureOptions = {
31
32
  };
32
33
 
33
34
  export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessage> {
35
+ private static readonly maxRecordNestingDepth = 10;
36
+
34
37
  public static async parse(message: ProtocolsConfigureMessage): Promise<ProtocolsConfigure> {
38
+ ProtocolsConfigure.validateReservedEncryptionControlPath(message.descriptor?.definition);
35
39
  Message.validateJsonSchema(message);
36
40
  ProtocolsConfigure.validateProtocolDefinition(message.descriptor.definition);
37
41
  await Message.validateSignatureStructure(message.authorization.signature, message.descriptor);
@@ -53,6 +57,8 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
53
57
  ...permissionGrantInvocation,
54
58
  };
55
59
 
60
+ ProtocolsConfigure.validateReservedEncryptionControlPath(descriptor.definition);
61
+
56
62
  const authorization = await Message.createAuthorization({
57
63
  descriptor,
58
64
  signer : options.signer,
@@ -109,6 +115,59 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
109
115
  ProtocolsConfigure.validateStructure(definition);
110
116
  }
111
117
 
118
+ /**
119
+ * Validates the reserved encryption-control namespace before JSON Schema validation.
120
+ */
121
+ private static validateReservedEncryptionControlPath(definition: unknown): void {
122
+ if (!ProtocolsConfigure.isRecord(definition)) {
123
+ return;
124
+ }
125
+
126
+ if (ProtocolsConfigure.isRecord(definition.types) && Object.hasOwn(definition.types, '$encryption')) {
127
+ throw new DwnError(
128
+ DwnErrorCode.ProtocolsConfigureReservedEncryptionControlPath,
129
+ `protocol type '$encryption' is reserved for DWN encryption control records.`
130
+ );
131
+ }
132
+
133
+ ProtocolsConfigure.validateReservedEncryptionControlStructure(definition.structure, '', 0);
134
+ }
135
+
136
+ private static validateReservedEncryptionControlStructure(ruleSet: unknown, protocolPath: string, depth: number): void {
137
+ if (!ProtocolsConfigure.isRecord(ruleSet)) {
138
+ return;
139
+ }
140
+
141
+ for (const recordType in ruleSet) {
142
+ const childDepth = depth + 1;
143
+ const childPath = protocolPath === '' ? recordType : `${protocolPath}/${recordType}`;
144
+
145
+ if (recordType === '$encryption') {
146
+ throw new DwnError(
147
+ DwnErrorCode.ProtocolsConfigureReservedEncryptionControlPath,
148
+ `protocol structure path '${childPath}' is reserved for DWN encryption control records.`
149
+ );
150
+ }
151
+
152
+ if (recordType.startsWith('$')) {
153
+ continue;
154
+ }
155
+
156
+ if (childDepth > ProtocolsConfigure.maxRecordNestingDepth) {
157
+ throw new DwnError(
158
+ DwnErrorCode.ProtocolsConfigureRecordNestingDepthExceeded,
159
+ `record nesting depth exceeded ${ProtocolsConfigure.maxRecordNestingDepth} levels.`
160
+ );
161
+ }
162
+
163
+ ProtocolsConfigure.validateReservedEncryptionControlStructure(ruleSet[recordType], childPath, childDepth);
164
+ }
165
+ }
166
+
167
+ private static isRecord(value: unknown): value is Record<string, unknown> {
168
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
169
+ }
170
+
112
171
  /**
113
172
  * Validates the `uses` map: alias names must match `^[a-zA-Z][a-zA-Z0-9_-]*$`,
114
173
  * values must be normalized protocol URLs, and no alias may reference the protocol itself.
@@ -175,15 +234,8 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
175
234
 
176
235
  /**
177
236
  * Parses the given rule set hierarchy to get all the role protocol paths.
178
- * @throws DwnError if the hierarchy depth goes beyond 10 levels.
179
237
  */
180
238
  private static fetchAllRolePathsRecursively(ruleSetProtocolPath: string, ruleSet: ProtocolRuleSet, roles: string[]): string[] {
181
- // Limit the depth of the record hierarchy to 10 levels
182
- // There is opportunity to optimize here to avoid repeated string splitting
183
- if (ruleSetProtocolPath.split('/').length > 10) {
184
- throw new DwnError(DwnErrorCode.ProtocolsConfigureRecordNestingDepthExceeded, 'Record nesting depth exceeded 10 levels.');
185
- }
186
-
187
239
  for (const recordType in ruleSet) {
188
240
  // ignore non-nested-record properties
189
241
  if (recordType.startsWith('$')) {
@@ -300,7 +352,8 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
300
352
  if (actionRule.role !== undefined) {
301
353
  if (isCrossProtocolRef(actionRule.role)) {
302
354
  // Cross-protocol role reference: validate alias exists in `uses`
303
- ProtocolsConfigure.validateCrossProtocolAlias(actionRule.role, uses, ruleSetProtocolPath, 'role');
355
+ const parsedRole = ProtocolsConfigure.validateCrossProtocolAlias(actionRule.role, uses, ruleSetProtocolPath, 'role');
356
+ ProtocolsConfigure.validateRoleParentContextDepth(parsedRole.protocolPath, ruleSetProtocolPath, actionRule);
304
357
  } else {
305
358
  // Local role: make sure the role contains a valid protocol path to a role record
306
359
  if (!roles.includes(actionRule.role)) {
@@ -309,6 +362,8 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
309
362
  `Role in action ${JSON.stringify(actionRule)} for rule set ${ruleSetProtocolPath} does not exist.`
310
363
  );
311
364
  }
365
+
366
+ ProtocolsConfigure.validateRoleParentContextDepth(actionRule.role, ruleSetProtocolPath, actionRule);
312
367
  }
313
368
  }
314
369
 
@@ -443,10 +498,17 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
443
498
  }
444
499
 
445
500
  for (const actionRule of actionRules) {
446
- if (actionRule.role === undefined || !actionRule.can.includes(ProtocolAction.Read) || isCrossProtocolRef(actionRule.role)) {
501
+ if (actionRule.role === undefined || !actionRule.can.includes(ProtocolAction.Read)) {
447
502
  continue;
448
503
  }
449
504
 
505
+ if (isCrossProtocolRef(actionRule.role)) {
506
+ throw new DwnError(
507
+ DwnErrorCode.ProtocolsConfigureInvalidEncryptedCrossProtocolRole,
508
+ `Encrypted protocol path '${ruleSetProtocolPath}' references cross-protocol read role '${actionRule.role}'.`
509
+ );
510
+ }
511
+
450
512
  const roleRuleSet = getRuleSetAtPath(actionRule.role, rootStructure);
451
513
  if (roleRuleSet?.$keyAgreement === undefined) {
452
514
  throw new DwnError(
@@ -558,6 +620,33 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
558
620
  }
559
621
  }
560
622
 
623
+ /**
624
+ * Validates that a role rule only references a role whose parent context can be found
625
+ * from records at the rule set's protocol path.
626
+ */
627
+ private static validateRoleParentContextDepth(rolePath: string, ruleSetProtocolPath: string, actionRule: ProtocolActionRule): void {
628
+ const syntheticContextId = ProtocolsConfigure.getSyntheticContextIdForProtocolPath(ruleSetProtocolPath);
629
+
630
+ if (getRoleAudienceContextId(rolePath, syntheticContextId) === undefined) {
631
+ throw new DwnError(
632
+ DwnErrorCode.ProtocolsConfigureRoleParentContextDepthExceeded,
633
+ `role '${rolePath}' in action ${JSON.stringify(actionRule)} at protocol path '${ruleSetProtocolPath}' ` +
634
+ `requires a context that records at the rule path cannot provide.`
635
+ );
636
+ }
637
+ }
638
+
639
+ private static getSyntheticContextIdForProtocolPath(protocolPath: string): string | undefined {
640
+ if (protocolPath === '') {
641
+ return undefined;
642
+ }
643
+
644
+ return protocolPath
645
+ .split('/')
646
+ .map((_segment, index): string => `context-${index}`)
647
+ .join('/');
648
+ }
649
+
561
650
  /**
562
651
  * Validates that a cross-protocol reference (in `alias:path` format) has a valid alias
563
652
  * that exists in the `uses` map.
@@ -568,7 +657,7 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
568
657
  */
569
658
  private static validateCrossProtocolAlias(
570
659
  ref: string, uses: ProtocolUses | undefined, ruleSetProtocolPath: string, fieldName: string
571
- ): void {
660
+ ): CrossProtocolRef {
572
661
  const parsed = parseCrossProtocolRef(ref);
573
662
 
574
663
  if (parsed === undefined) {
@@ -595,6 +684,8 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
595
684
  `does not exist in the 'uses' map.`
596
685
  );
597
686
  }
687
+
688
+ return parsed;
598
689
  }
599
690
 
600
691
  private static normalizeDefinition(definition: ProtocolDefinition): ProtocolDefinition {