@enbox/dwn-sdk-js 0.0.2 → 0.0.3

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 (601) hide show
  1. package/README.md +52 -301
  2. package/dist/bundles/dwn.js +19 -21
  3. package/dist/esm/generated/precompiled-validators.js +2764 -1773
  4. package/dist/esm/generated/precompiled-validators.js.map +1 -1
  5. package/dist/esm/src/core/dwn-error.js +27 -3
  6. package/dist/esm/src/core/dwn-error.js.map +1 -1
  7. package/dist/esm/src/core/message.js.map +1 -1
  8. package/dist/esm/src/core/messages-grant-authorization.js +17 -6
  9. package/dist/esm/src/core/messages-grant-authorization.js.map +1 -1
  10. package/dist/esm/src/core/protocol-authorization.js +245 -69
  11. package/dist/esm/src/core/protocol-authorization.js.map +1 -1
  12. package/dist/esm/src/core/resumable-task-manager.js +4 -4
  13. package/dist/esm/src/core/resumable-task-manager.js.map +1 -1
  14. package/dist/esm/src/dwn.js +10 -8
  15. package/dist/esm/src/dwn.js.map +1 -1
  16. package/dist/esm/src/enums/dwn-interface-method.js +4 -2
  17. package/dist/esm/src/enums/dwn-interface-method.js.map +1 -1
  18. package/dist/esm/src/event-stream/event-emitter-stream.js.map +1 -0
  19. package/dist/esm/src/handlers/messages-subscribe.js +1 -1
  20. package/dist/esm/src/handlers/messages-subscribe.js.map +1 -1
  21. package/dist/esm/src/handlers/messages-sync.js +116 -0
  22. package/dist/esm/src/handlers/messages-sync.js.map +1 -0
  23. package/dist/esm/src/handlers/protocols-configure.js +149 -16
  24. package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
  25. package/dist/esm/src/handlers/protocols-query.js +2 -2
  26. package/dist/esm/src/handlers/protocols-query.js.map +1 -1
  27. package/dist/esm/src/handlers/records-count.js +143 -0
  28. package/dist/esm/src/handlers/records-count.js.map +1 -0
  29. package/dist/esm/src/handlers/records-query.js +4 -0
  30. package/dist/esm/src/handlers/records-query.js.map +1 -1
  31. package/dist/esm/src/handlers/records-read.js +4 -6
  32. package/dist/esm/src/handlers/records-read.js.map +1 -1
  33. package/dist/esm/src/handlers/records-write.js +17 -18
  34. package/dist/esm/src/handlers/records-write.js.map +1 -1
  35. package/dist/esm/src/index.js +9 -5
  36. package/dist/esm/src/index.js.map +1 -1
  37. package/dist/esm/src/interfaces/messages-read.js +2 -7
  38. package/dist/esm/src/interfaces/messages-read.js.map +1 -1
  39. package/dist/esm/src/interfaces/messages-subscribe.js +1 -0
  40. package/dist/esm/src/interfaces/messages-subscribe.js.map +1 -1
  41. package/dist/esm/src/interfaces/{messages-query.js → messages-sync.js} +11 -12
  42. package/dist/esm/src/interfaces/messages-sync.js.map +1 -0
  43. package/dist/esm/src/interfaces/protocols-configure.js +153 -30
  44. package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
  45. package/dist/esm/src/interfaces/protocols-query.js +1 -0
  46. package/dist/esm/src/interfaces/protocols-query.js.map +1 -1
  47. package/dist/esm/src/interfaces/records-count.js +91 -0
  48. package/dist/esm/src/interfaces/records-count.js.map +1 -0
  49. package/dist/esm/src/interfaces/records-read.js +15 -1
  50. package/dist/esm/src/interfaces/records-read.js.map +1 -1
  51. package/dist/esm/src/interfaces/records-write.js +64 -15
  52. package/dist/esm/src/interfaces/records-write.js.map +1 -1
  53. package/dist/esm/src/jose/algorithms/signing/ed25519.js.map +1 -1
  54. package/dist/esm/src/jose/algorithms/signing/signature-algorithms.js.map +1 -1
  55. package/dist/esm/src/jose/jws/general/builder.js.map +1 -1
  56. package/dist/esm/src/jose/jws/general/verifier.js.map +1 -1
  57. package/dist/esm/src/protocols/permission-grant.js +30 -0
  58. package/dist/esm/src/protocols/permission-grant.js.map +1 -1
  59. package/dist/esm/src/protocols/permission-request.js +24 -0
  60. package/dist/esm/src/protocols/permission-request.js.map +1 -1
  61. package/dist/esm/src/protocols/permissions.js +1 -1
  62. package/dist/esm/src/protocols/permissions.js.map +1 -1
  63. package/dist/esm/src/schema-validator.js +0 -1
  64. package/dist/esm/src/schema-validator.js.map +1 -1
  65. package/dist/esm/src/smt/smt-store-level.js +125 -0
  66. package/dist/esm/src/smt/smt-store-level.js.map +1 -0
  67. package/dist/esm/src/smt/smt-store-memory.js +67 -0
  68. package/dist/esm/src/smt/smt-store-memory.js.map +1 -0
  69. package/dist/esm/src/smt/smt-utils.js +146 -0
  70. package/dist/esm/src/smt/smt-utils.js.map +1 -0
  71. package/dist/esm/src/smt/sparse-merkle-tree.js +622 -0
  72. package/dist/esm/src/smt/sparse-merkle-tree.js.map +1 -0
  73. package/dist/esm/src/state-index/state-index-level.js +228 -0
  74. package/dist/esm/src/state-index/state-index-level.js.map +1 -0
  75. package/dist/esm/src/store/data-store-level.js +6 -6
  76. package/dist/esm/src/store/data-store-level.js.map +1 -1
  77. package/dist/esm/src/store/index-level.js +375 -17
  78. package/dist/esm/src/store/index-level.js.map +1 -1
  79. package/dist/esm/src/store/message-store-level.js +56 -0
  80. package/dist/esm/src/store/message-store-level.js.map +1 -1
  81. package/dist/esm/src/store/storage-controller.js +19 -16
  82. package/dist/esm/src/store/storage-controller.js.map +1 -1
  83. package/dist/esm/src/types/encryption-types.js +2 -0
  84. package/dist/esm/src/types/encryption-types.js.map +1 -0
  85. package/dist/esm/src/types/message-types.js.map +1 -1
  86. package/dist/esm/src/types/protocols-types.js +0 -2
  87. package/dist/esm/src/types/protocols-types.js.map +1 -1
  88. package/dist/esm/src/types/records-types.js +2 -0
  89. package/dist/esm/src/types/records-types.js.map +1 -1
  90. package/dist/esm/src/types/smt-types.js +5 -0
  91. package/dist/esm/src/types/smt-types.js.map +1 -0
  92. package/dist/esm/src/types/state-index.js +2 -0
  93. package/dist/esm/src/types/state-index.js.map +1 -0
  94. package/dist/esm/src/utils/cid.js +2 -1
  95. package/dist/esm/src/utils/cid.js.map +1 -1
  96. package/dist/esm/src/utils/data-stream.js +84 -29
  97. package/dist/esm/src/utils/data-stream.js.map +1 -1
  98. package/dist/esm/src/utils/encryption.js +22 -31
  99. package/dist/esm/src/utils/encryption.js.map +1 -1
  100. package/dist/esm/src/utils/hd-key.js +3 -3
  101. package/dist/esm/src/utils/hd-key.js.map +1 -1
  102. package/dist/esm/src/utils/jws.js +4 -4
  103. package/dist/esm/src/utils/jws.js.map +1 -1
  104. package/dist/esm/src/utils/private-key-signer.js +4 -3
  105. package/dist/esm/src/utils/private-key-signer.js.map +1 -1
  106. package/dist/esm/src/utils/protocols.js +82 -9
  107. package/dist/esm/src/utils/protocols.js.map +1 -1
  108. package/dist/esm/src/utils/records.js +82 -26
  109. package/dist/esm/src/utils/records.js.map +1 -1
  110. package/dist/esm/src/utils/secp256k1.js +4 -3
  111. package/dist/esm/src/utils/secp256k1.js.map +1 -1
  112. package/dist/esm/src/utils/secp256r1.js +3 -2
  113. package/dist/esm/src/utils/secp256r1.js.map +1 -1
  114. package/dist/esm/src/utils/time.js +1 -1
  115. package/dist/esm/src/utils/url.js +1 -1
  116. package/dist/esm/src/utils/url.js.map +1 -1
  117. package/dist/esm/tests/core/auth.spec.js +2 -2
  118. package/dist/esm/tests/core/auth.spec.js.map +1 -1
  119. package/dist/esm/tests/core/message-reply.spec.js +3 -3
  120. package/dist/esm/tests/core/message-reply.spec.js.map +1 -1
  121. package/dist/esm/tests/core/message.spec.js +13 -13
  122. package/dist/esm/tests/core/message.spec.js.map +1 -1
  123. package/dist/esm/tests/core/protocol-authorization.spec.js +3 -3
  124. package/dist/esm/tests/core/protocol-authorization.spec.js.map +1 -1
  125. package/dist/esm/tests/dwn.spec.js +27 -37
  126. package/dist/esm/tests/dwn.spec.js.map +1 -1
  127. package/dist/esm/tests/{event-log → event-stream}/event-emitter-stream.spec.js +14 -15
  128. package/dist/esm/tests/event-stream/event-emitter-stream.spec.js.map +1 -0
  129. package/dist/esm/tests/{event-log → event-stream}/event-stream.spec.js +13 -15
  130. package/dist/esm/tests/event-stream/event-stream.spec.js.map +1 -0
  131. package/dist/esm/tests/features/author-delegated-grant.spec.js +281 -135
  132. package/dist/esm/tests/features/author-delegated-grant.spec.js.map +1 -1
  133. package/dist/esm/tests/features/owner-delegated-grant.spec.js +57 -59
  134. package/dist/esm/tests/features/owner-delegated-grant.spec.js.map +1 -1
  135. package/dist/esm/tests/features/owner-signature.spec.js +32 -34
  136. package/dist/esm/tests/features/owner-signature.spec.js.map +1 -1
  137. package/dist/esm/tests/features/permissions.spec.js +73 -95
  138. package/dist/esm/tests/features/permissions.spec.js.map +1 -1
  139. package/dist/esm/tests/features/protocol-composition.spec.js +1645 -0
  140. package/dist/esm/tests/features/protocol-composition.spec.js.map +1 -0
  141. package/dist/esm/tests/features/protocol-create-action.spec.js +25 -27
  142. package/dist/esm/tests/features/protocol-create-action.spec.js.map +1 -1
  143. package/dist/esm/tests/features/protocol-delete-action.spec.js +42 -44
  144. package/dist/esm/tests/features/protocol-delete-action.spec.js.map +1 -1
  145. package/dist/esm/tests/features/protocol-update-action.spec.js +53 -55
  146. package/dist/esm/tests/features/protocol-update-action.spec.js.map +1 -1
  147. package/dist/esm/tests/features/records-prune.spec.js +126 -100
  148. package/dist/esm/tests/features/records-prune.spec.js.map +1 -1
  149. package/dist/esm/tests/features/records-tags.spec.js +272 -272
  150. package/dist/esm/tests/features/records-tags.spec.js.map +1 -1
  151. package/dist/esm/tests/features/resumable-tasks.spec.js +35 -37
  152. package/dist/esm/tests/features/resumable-tasks.spec.js.map +1 -1
  153. package/dist/esm/tests/handlers/messages-read.spec.js +112 -112
  154. package/dist/esm/tests/handlers/messages-read.spec.js.map +1 -1
  155. package/dist/esm/tests/handlers/messages-subscribe.spec.js +78 -76
  156. package/dist/esm/tests/handlers/messages-subscribe.spec.js.map +1 -1
  157. package/dist/esm/tests/handlers/messages-sync.spec.js +528 -0
  158. package/dist/esm/tests/handlers/messages-sync.spec.js.map +1 -0
  159. package/dist/esm/tests/handlers/protocols-configure.spec.js +545 -152
  160. package/dist/esm/tests/handlers/protocols-configure.spec.js.map +1 -1
  161. package/dist/esm/tests/handlers/protocols-query.spec.js +70 -72
  162. package/dist/esm/tests/handlers/protocols-query.spec.js.map +1 -1
  163. package/dist/esm/tests/handlers/records-count.spec.js +313 -0
  164. package/dist/esm/tests/handlers/records-count.spec.js.map +1 -0
  165. package/dist/esm/tests/handlers/records-delete.spec.js +106 -109
  166. package/dist/esm/tests/handlers/records-delete.spec.js.map +1 -1
  167. package/dist/esm/tests/handlers/records-query.spec.js +863 -463
  168. package/dist/esm/tests/handlers/records-query.spec.js.map +1 -1
  169. package/dist/esm/tests/handlers/records-read.spec.js +439 -209
  170. package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
  171. package/dist/esm/tests/handlers/records-subscribe.spec.js +292 -97
  172. package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
  173. package/dist/esm/tests/handlers/records-write.spec.js +481 -483
  174. package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
  175. package/dist/esm/tests/interfaces/messages-get.spec.js +31 -11
  176. package/dist/esm/tests/interfaces/messages-get.spec.js.map +1 -1
  177. package/dist/esm/tests/interfaces/messages-subscribe.spec.js +5 -5
  178. package/dist/esm/tests/interfaces/messages-subscribe.spec.js.map +1 -1
  179. package/dist/esm/tests/interfaces/protocols-configure.spec.js +64 -134
  180. package/dist/esm/tests/interfaces/protocols-configure.spec.js.map +1 -1
  181. package/dist/esm/tests/interfaces/protocols-query.spec.js +4 -6
  182. package/dist/esm/tests/interfaces/protocols-query.spec.js.map +1 -1
  183. package/dist/esm/tests/interfaces/records-delete.spec.js +3 -5
  184. package/dist/esm/tests/interfaces/records-delete.spec.js.map +1 -1
  185. package/dist/esm/tests/interfaces/records-query.spec.js +9 -11
  186. package/dist/esm/tests/interfaces/records-query.spec.js.map +1 -1
  187. package/dist/esm/tests/interfaces/records-read.spec.js +76 -7
  188. package/dist/esm/tests/interfaces/records-read.spec.js.map +1 -1
  189. package/dist/esm/tests/interfaces/records-subscribe.spec.js +7 -9
  190. package/dist/esm/tests/interfaces/records-subscribe.spec.js.map +1 -1
  191. package/dist/esm/tests/interfaces/records-write.spec.js +244 -48
  192. package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
  193. package/dist/esm/tests/jose/jws/general.spec.js +15 -18
  194. package/dist/esm/tests/jose/jws/general.spec.js.map +1 -1
  195. package/dist/esm/tests/protocols/permission-grant.spec.js +114 -0
  196. package/dist/esm/tests/protocols/permission-grant.spec.js.map +1 -0
  197. package/dist/esm/tests/protocols/permission-request.spec.js +43 -7
  198. package/dist/esm/tests/protocols/permission-request.spec.js.map +1 -1
  199. package/dist/esm/tests/protocols/permissions.spec.js +9 -11
  200. package/dist/esm/tests/protocols/permissions.spec.js.map +1 -1
  201. package/dist/esm/tests/scenarios/aggregator.spec.js +90 -92
  202. package/dist/esm/tests/scenarios/aggregator.spec.js.map +1 -1
  203. package/dist/esm/tests/scenarios/deleted-record.spec.js +17 -19
  204. package/dist/esm/tests/scenarios/deleted-record.spec.js.map +1 -1
  205. package/dist/esm/tests/scenarios/end-to-end-tests.spec.js +27 -29
  206. package/dist/esm/tests/scenarios/end-to-end-tests.spec.js.map +1 -1
  207. package/dist/esm/tests/scenarios/nested-roles.spec.js +37 -39
  208. package/dist/esm/tests/scenarios/nested-roles.spec.js.map +1 -1
  209. package/dist/esm/tests/scenarios/subscriptions.spec.js +163 -163
  210. package/dist/esm/tests/scenarios/subscriptions.spec.js.map +1 -1
  211. package/dist/esm/tests/smt/smt-store-level.spec.js +143 -0
  212. package/dist/esm/tests/smt/smt-store-level.spec.js.map +1 -0
  213. package/dist/esm/tests/smt/sparse-merkle-tree.spec.js +741 -0
  214. package/dist/esm/tests/smt/sparse-merkle-tree.spec.js.map +1 -0
  215. package/dist/esm/tests/state-index/state-index-level.spec.js +254 -0
  216. package/dist/esm/tests/state-index/state-index-level.spec.js.map +1 -0
  217. package/dist/esm/tests/store/blockstore-level.spec.js +136 -0
  218. package/dist/esm/tests/store/blockstore-level.spec.js.map +1 -0
  219. package/dist/esm/tests/store/blockstore-mock.spec.js +29 -28
  220. package/dist/esm/tests/store/blockstore-mock.spec.js.map +1 -1
  221. package/dist/esm/tests/store/data-store-level.spec.js +23 -25
  222. package/dist/esm/tests/store/data-store-level.spec.js.map +1 -1
  223. package/dist/esm/tests/store/index-level.spec.js +544 -194
  224. package/dist/esm/tests/store/index-level.spec.js.map +1 -1
  225. package/dist/esm/tests/store/message-store-level.spec.js +4 -4
  226. package/dist/esm/tests/store/message-store-level.spec.js.map +1 -1
  227. package/dist/esm/tests/store/message-store.spec.js +147 -73
  228. package/dist/esm/tests/store/message-store.spec.js.map +1 -1
  229. package/dist/esm/tests/store-dependent-tests.spec.js +1 -0
  230. package/dist/esm/tests/store-dependent-tests.spec.js.map +1 -1
  231. package/dist/esm/tests/test-stores.js +5 -5
  232. package/dist/esm/tests/test-stores.js.map +1 -1
  233. package/dist/esm/tests/test-suite.js +9 -8
  234. package/dist/esm/tests/test-suite.js.map +1 -1
  235. package/dist/esm/tests/utils/cid.spec.js +8 -11
  236. package/dist/esm/tests/utils/cid.spec.js.map +1 -1
  237. package/dist/esm/tests/utils/data-stream.spec.js +167 -13
  238. package/dist/esm/tests/utils/data-stream.spec.js.map +1 -1
  239. package/dist/esm/tests/utils/encryption-callbacks.spec.js +233 -0
  240. package/dist/esm/tests/utils/encryption-callbacks.spec.js.map +1 -0
  241. package/dist/esm/tests/utils/encryption.spec.js +34 -85
  242. package/dist/esm/tests/utils/encryption.spec.js.map +1 -1
  243. package/dist/esm/tests/utils/filters.spec.js +67 -69
  244. package/dist/esm/tests/utils/filters.spec.js.map +1 -1
  245. package/dist/esm/tests/utils/hd-key.spec.js +3 -3
  246. package/dist/esm/tests/utils/hd-key.spec.js.map +1 -1
  247. package/dist/esm/tests/utils/jws.spec.js +54 -3
  248. package/dist/esm/tests/utils/jws.spec.js.map +1 -1
  249. package/dist/esm/tests/utils/memory-cache.spec.js +6 -9
  250. package/dist/esm/tests/utils/memory-cache.spec.js.map +1 -1
  251. package/dist/esm/tests/utils/messages.spec.js +63 -29
  252. package/dist/esm/tests/utils/messages.spec.js.map +1 -1
  253. package/dist/esm/tests/utils/object.spec.js +3 -3
  254. package/dist/esm/tests/utils/object.spec.js.map +1 -1
  255. package/dist/esm/tests/utils/poller.js +1 -1
  256. package/dist/esm/tests/utils/poller.js.map +1 -1
  257. package/dist/esm/tests/utils/private-key-signer.spec.js +6 -6
  258. package/dist/esm/tests/utils/private-key-signer.spec.js.map +1 -1
  259. package/dist/esm/tests/utils/records.spec.js +37 -5
  260. package/dist/esm/tests/utils/records.spec.js.map +1 -1
  261. package/dist/esm/tests/utils/secp256k1.spec.js +7 -7
  262. package/dist/esm/tests/utils/secp256k1.spec.js.map +1 -1
  263. package/dist/esm/tests/utils/secp256r1.spec.js +7 -7
  264. package/dist/esm/tests/utils/secp256r1.spec.js.map +1 -1
  265. package/dist/esm/tests/utils/test-data-generator.js +47 -28
  266. package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
  267. package/dist/esm/tests/utils/time.spec.js +7 -7
  268. package/dist/esm/tests/utils/time.spec.js.map +1 -1
  269. package/dist/esm/tests/utils/url.spec.js +25 -27
  270. package/dist/esm/tests/utils/url.spec.js.map +1 -1
  271. package/dist/esm/tests/validation/json-schemas/definitions.spec.js +4 -4
  272. package/dist/esm/tests/validation/json-schemas/definitions.spec.js.map +1 -1
  273. package/dist/esm/tests/validation/json-schemas/jwk/general-jwk.spec.js +15 -3
  274. package/dist/esm/tests/validation/json-schemas/jwk/general-jwk.spec.js.map +1 -1
  275. package/dist/esm/tests/validation/json-schemas/jwk/public-jwk.spec.js +8 -8
  276. package/dist/esm/tests/validation/json-schemas/jwk/public-jwk.spec.js.map +1 -1
  277. package/dist/esm/tests/validation/json-schemas/jwk-verification-method.spec.js +8 -18
  278. package/dist/esm/tests/validation/json-schemas/jwk-verification-method.spec.js.map +1 -1
  279. package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js +3 -3
  280. package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js.map +1 -1
  281. package/dist/esm/tests/validation/json-schemas/records/records-query.spec.js +9 -9
  282. package/dist/esm/tests/validation/json-schemas/records/records-query.spec.js.map +1 -1
  283. package/dist/esm/tests/validation/json-schemas/records/records-read.spec.js +106 -0
  284. package/dist/esm/tests/validation/json-schemas/records/records-read.spec.js.map +1 -0
  285. package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js +18 -18
  286. package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js.map +1 -1
  287. package/dist/esm/tests/vectors/protocol-definitions/email.json +1 -1
  288. package/dist/esm/tests/vectors/protocol-definitions/friend-role.json +2 -4
  289. package/dist/esm/tests/vectors/protocol-definitions/slack.json +2 -6
  290. package/dist/esm/tests/vectors/protocol-definitions/thread-role.json +2 -6
  291. package/dist/types/generated/precompiled-validators.d.ts +82 -64
  292. package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
  293. package/dist/types/src/core/dwn-error.d.ts +27 -3
  294. package/dist/types/src/core/dwn-error.d.ts.map +1 -1
  295. package/dist/types/src/core/message-reply.d.ts +1 -1
  296. package/dist/types/src/core/message.d.ts +3 -3
  297. package/dist/types/src/core/message.d.ts.map +1 -1
  298. package/dist/types/src/core/messages-grant-authorization.d.ts +4 -4
  299. package/dist/types/src/core/messages-grant-authorization.d.ts.map +1 -1
  300. package/dist/types/src/core/protocol-authorization.d.ts +43 -2
  301. package/dist/types/src/core/protocol-authorization.d.ts.map +1 -1
  302. package/dist/types/src/core/records-grant-authorization.d.ts +2 -2
  303. package/dist/types/src/core/records-grant-authorization.d.ts.map +1 -1
  304. package/dist/types/src/core/resumable-task-manager.d.ts +1 -0
  305. package/dist/types/src/core/resumable-task-manager.d.ts.map +1 -1
  306. package/dist/types/src/dwn.d.ts +8 -8
  307. package/dist/types/src/dwn.d.ts.map +1 -1
  308. package/dist/types/src/enums/dwn-interface-method.d.ts +5 -3
  309. package/dist/types/src/enums/dwn-interface-method.d.ts.map +1 -1
  310. package/dist/types/src/event-stream/event-emitter-stream.d.ts.map +1 -0
  311. package/dist/types/src/handlers/messages-sync.d.ts +21 -0
  312. package/dist/types/src/handlers/messages-sync.d.ts.map +1 -0
  313. package/dist/types/src/handlers/protocols-configure.d.ts +24 -4
  314. package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
  315. package/dist/types/src/handlers/protocols-query.d.ts.map +1 -1
  316. package/dist/types/src/handlers/records-count.d.ts +43 -0
  317. package/dist/types/src/handlers/records-count.d.ts.map +1 -0
  318. package/dist/types/src/handlers/records-query.d.ts.map +1 -1
  319. package/dist/types/src/handlers/records-read.d.ts.map +1 -1
  320. package/dist/types/src/handlers/records-write.d.ts +5 -5
  321. package/dist/types/src/handlers/records-write.d.ts.map +1 -1
  322. package/dist/types/src/index.d.ts +72 -37
  323. package/dist/types/src/index.d.ts.map +1 -1
  324. package/dist/types/src/interfaces/messages-read.d.ts +2 -2
  325. package/dist/types/src/interfaces/messages-read.d.ts.map +1 -1
  326. package/dist/types/src/interfaces/messages-subscribe.d.ts +2 -2
  327. package/dist/types/src/interfaces/messages-subscribe.d.ts.map +1 -1
  328. package/dist/types/src/interfaces/messages-sync.d.ts +16 -0
  329. package/dist/types/src/interfaces/messages-sync.d.ts.map +1 -0
  330. package/dist/types/src/interfaces/protocols-configure.d.ts +22 -2
  331. package/dist/types/src/interfaces/protocols-configure.d.ts.map +1 -1
  332. package/dist/types/src/interfaces/protocols-query.d.ts +2 -2
  333. package/dist/types/src/interfaces/protocols-query.d.ts.map +1 -1
  334. package/dist/types/src/interfaces/records-count.d.ts +27 -0
  335. package/dist/types/src/interfaces/records-count.d.ts.map +1 -0
  336. package/dist/types/src/interfaces/records-delete.d.ts +2 -2
  337. package/dist/types/src/interfaces/records-delete.d.ts.map +1 -1
  338. package/dist/types/src/interfaces/records-query.d.ts +2 -2
  339. package/dist/types/src/interfaces/records-query.d.ts.map +1 -1
  340. package/dist/types/src/interfaces/records-read.d.ts +4 -2
  341. package/dist/types/src/interfaces/records-read.d.ts.map +1 -1
  342. package/dist/types/src/interfaces/records-subscribe.d.ts +2 -2
  343. package/dist/types/src/interfaces/records-subscribe.d.ts.map +1 -1
  344. package/dist/types/src/interfaces/records-write.d.ts +37 -15
  345. package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
  346. package/dist/types/src/jose/algorithms/signing/ed25519.d.ts.map +1 -1
  347. package/dist/types/src/jose/algorithms/signing/signature-algorithms.d.ts +5 -1
  348. package/dist/types/src/jose/algorithms/signing/signature-algorithms.d.ts.map +1 -1
  349. package/dist/types/src/jose/jws/general/builder.d.ts +3 -3
  350. package/dist/types/src/jose/jws/general/builder.d.ts.map +1 -1
  351. package/dist/types/src/protocols/permission-grant.d.ts +11 -0
  352. package/dist/types/src/protocols/permission-grant.d.ts.map +1 -1
  353. package/dist/types/src/protocols/permission-request.d.ts +11 -0
  354. package/dist/types/src/protocols/permission-request.d.ts.map +1 -1
  355. package/dist/types/src/protocols/permissions.d.ts +4 -4
  356. package/dist/types/src/protocols/permissions.d.ts.map +1 -1
  357. package/dist/types/src/schema-validator.d.ts +1 -1
  358. package/dist/types/src/schema-validator.d.ts.map +1 -1
  359. package/dist/types/src/smt/smt-store-level.d.ts +32 -0
  360. package/dist/types/src/smt/smt-store-level.d.ts.map +1 -0
  361. package/dist/types/src/smt/smt-store-memory.d.ts +22 -0
  362. package/dist/types/src/smt/smt-store-memory.d.ts.map +1 -0
  363. package/dist/types/src/smt/smt-utils.d.ts +58 -0
  364. package/dist/types/src/smt/smt-utils.d.ts.map +1 -0
  365. package/dist/types/src/smt/sparse-merkle-tree.d.ts +124 -0
  366. package/dist/types/src/smt/sparse-merkle-tree.d.ts.map +1 -0
  367. package/dist/types/src/state-index/state-index-level.d.ts +83 -0
  368. package/dist/types/src/state-index/state-index-level.d.ts.map +1 -0
  369. package/dist/types/src/store/data-store-level.d.ts +1 -2
  370. package/dist/types/src/store/data-store-level.d.ts.map +1 -1
  371. package/dist/types/src/store/index-level.d.ts +98 -2
  372. package/dist/types/src/store/index-level.d.ts.map +1 -1
  373. package/dist/types/src/store/level-wrapper.d.ts.map +1 -1
  374. package/dist/types/src/store/message-store-level.d.ts +5 -0
  375. package/dist/types/src/store/message-store-level.d.ts.map +1 -1
  376. package/dist/types/src/store/storage-controller.d.ts +7 -7
  377. package/dist/types/src/store/storage-controller.d.ts.map +1 -1
  378. package/dist/types/src/types/data-store.d.ts +2 -3
  379. package/dist/types/src/types/data-store.d.ts.map +1 -1
  380. package/dist/types/src/types/encryption-types.d.ts +48 -0
  381. package/dist/types/src/types/encryption-types.d.ts.map +1 -0
  382. package/dist/types/src/types/jose-types.d.ts +9 -40
  383. package/dist/types/src/types/jose-types.d.ts.map +1 -1
  384. package/dist/types/src/types/message-store.d.ts +5 -0
  385. package/dist/types/src/types/message-store.d.ts.map +1 -1
  386. package/dist/types/src/types/message-types.d.ts +19 -0
  387. package/dist/types/src/types/message-types.d.ts.map +1 -1
  388. package/dist/types/src/types/messages-types.d.ts +16 -11
  389. package/dist/types/src/types/messages-types.d.ts.map +1 -1
  390. package/dist/types/src/types/method-handler.d.ts +1 -2
  391. package/dist/types/src/types/method-handler.d.ts.map +1 -1
  392. package/dist/types/src/types/permission-types.d.ts +2 -2
  393. package/dist/types/src/types/permission-types.d.ts.map +1 -1
  394. package/dist/types/src/types/protocols-types.d.ts +49 -5
  395. package/dist/types/src/types/protocols-types.d.ts.map +1 -1
  396. package/dist/types/src/types/records-types.d.ts +23 -7
  397. package/dist/types/src/types/records-types.d.ts.map +1 -1
  398. package/dist/types/src/types/signer.d.ts +1 -1
  399. package/dist/types/src/types/signer.d.ts.map +1 -1
  400. package/dist/types/src/types/smt-types.d.ts +81 -0
  401. package/dist/types/src/types/smt-types.d.ts.map +1 -0
  402. package/dist/types/src/types/state-index.d.ts +90 -0
  403. package/dist/types/src/types/state-index.d.ts.map +1 -0
  404. package/dist/types/src/utils/cid.d.ts +1 -2
  405. package/dist/types/src/utils/cid.d.ts.map +1 -1
  406. package/dist/types/src/utils/data-stream.d.ts +14 -7
  407. package/dist/types/src/utils/data-stream.d.ts.map +1 -1
  408. package/dist/types/src/utils/encryption.d.ts +2 -3
  409. package/dist/types/src/utils/encryption.d.ts.map +1 -1
  410. package/dist/types/src/utils/hd-key.d.ts +4 -4
  411. package/dist/types/src/utils/hd-key.d.ts.map +1 -1
  412. package/dist/types/src/utils/jws.d.ts +7 -7
  413. package/dist/types/src/utils/jws.d.ts.map +1 -1
  414. package/dist/types/src/utils/private-key-signer.d.ts +4 -4
  415. package/dist/types/src/utils/private-key-signer.d.ts.map +1 -1
  416. package/dist/types/src/utils/protocols.d.ts +46 -3
  417. package/dist/types/src/utils/protocols.d.ts.map +1 -1
  418. package/dist/types/src/utils/records.d.ts +33 -6
  419. package/dist/types/src/utils/records.d.ts.map +1 -1
  420. package/dist/types/src/utils/secp256k1.d.ts +11 -11
  421. package/dist/types/src/utils/secp256k1.d.ts.map +1 -1
  422. package/dist/types/src/utils/secp256r1.d.ts +8 -8
  423. package/dist/types/src/utils/secp256r1.d.ts.map +1 -1
  424. package/dist/types/src/utils/time.d.ts +1 -1
  425. package/dist/types/tests/dwn.spec.d.ts.map +1 -1
  426. package/dist/types/tests/event-stream/event-emitter-stream.spec.d.ts.map +1 -0
  427. package/dist/types/tests/event-stream/event-stream.spec.d.ts.map +1 -0
  428. package/dist/types/tests/features/author-delegated-grant.spec.d.ts.map +1 -1
  429. package/dist/types/tests/features/owner-delegated-grant.spec.d.ts.map +1 -1
  430. package/dist/types/tests/features/owner-signature.spec.d.ts.map +1 -1
  431. package/dist/types/tests/features/permissions.spec.d.ts.map +1 -1
  432. package/dist/types/tests/features/protocol-composition.spec.d.ts +5 -0
  433. package/dist/types/tests/features/protocol-composition.spec.d.ts.map +1 -0
  434. package/dist/types/tests/features/protocol-create-action.spec.d.ts.map +1 -1
  435. package/dist/types/tests/features/protocol-delete-action.spec.d.ts.map +1 -1
  436. package/dist/types/tests/features/protocol-update-action.spec.d.ts.map +1 -1
  437. package/dist/types/tests/features/records-prune.spec.d.ts.map +1 -1
  438. package/dist/types/tests/features/records-tags.spec.d.ts.map +1 -1
  439. package/dist/types/tests/features/resumable-tasks.spec.d.ts.map +1 -1
  440. package/dist/types/tests/handlers/messages-read.spec.d.ts.map +1 -1
  441. package/dist/types/tests/handlers/messages-subscribe.spec.d.ts.map +1 -1
  442. package/dist/types/tests/handlers/messages-sync.spec.d.ts +2 -0
  443. package/dist/types/tests/handlers/messages-sync.spec.d.ts.map +1 -0
  444. package/dist/types/tests/handlers/protocols-configure.spec.d.ts.map +1 -1
  445. package/dist/types/tests/handlers/protocols-query.spec.d.ts.map +1 -1
  446. package/dist/types/tests/handlers/records-count.spec.d.ts +2 -0
  447. package/dist/types/tests/handlers/records-count.spec.d.ts.map +1 -0
  448. package/dist/types/tests/handlers/records-delete.spec.d.ts.map +1 -1
  449. package/dist/types/tests/handlers/records-query.spec.d.ts.map +1 -1
  450. package/dist/types/tests/handlers/records-read.spec.d.ts.map +1 -1
  451. package/dist/types/tests/handlers/records-subscribe.spec.d.ts.map +1 -1
  452. package/dist/types/tests/handlers/records-write.spec.d.ts.map +1 -1
  453. package/dist/types/tests/protocols/permission-grant.spec.d.ts +2 -0
  454. package/dist/types/tests/protocols/permission-grant.spec.d.ts.map +1 -0
  455. package/dist/types/tests/scenarios/deleted-record.spec.d.ts.map +1 -1
  456. package/dist/types/tests/scenarios/end-to-end-tests.spec.d.ts.map +1 -1
  457. package/dist/types/tests/scenarios/nested-roles.spec.d.ts.map +1 -1
  458. package/dist/types/tests/smt/smt-store-level.spec.d.ts +2 -0
  459. package/dist/types/tests/smt/smt-store-level.spec.d.ts.map +1 -0
  460. package/dist/types/tests/smt/sparse-merkle-tree.spec.d.ts +2 -0
  461. package/dist/types/tests/smt/sparse-merkle-tree.spec.d.ts.map +1 -0
  462. package/dist/types/tests/state-index/state-index-level.spec.d.ts +2 -0
  463. package/dist/types/tests/state-index/state-index-level.spec.d.ts.map +1 -0
  464. package/dist/types/tests/store/blockstore-level.spec.d.ts +2 -0
  465. package/dist/types/tests/store/blockstore-level.spec.d.ts.map +1 -0
  466. package/dist/types/tests/store/message-store.spec.d.ts.map +1 -1
  467. package/dist/types/tests/test-stores.d.ts +4 -4
  468. package/dist/types/tests/test-stores.d.ts.map +1 -1
  469. package/dist/types/tests/test-suite.d.ts +2 -2
  470. package/dist/types/tests/test-suite.d.ts.map +1 -1
  471. package/dist/types/tests/utils/encryption-callbacks.spec.d.ts +2 -0
  472. package/dist/types/tests/utils/encryption-callbacks.spec.d.ts.map +1 -0
  473. package/dist/types/tests/utils/test-data-generator.d.ts +31 -28
  474. package/dist/types/tests/utils/test-data-generator.d.ts.map +1 -1
  475. package/dist/types/tests/validation/json-schemas/records/records-read.spec.d.ts +2 -0
  476. package/dist/types/tests/validation/json-schemas/records/records-read.spec.d.ts.map +1 -0
  477. package/package.json +27 -46
  478. package/src/core/dwn-error.ts +27 -3
  479. package/src/core/message-reply.ts +1 -1
  480. package/src/core/message.ts +5 -5
  481. package/src/core/messages-grant-authorization.ts +22 -8
  482. package/src/core/protocol-authorization.ts +345 -68
  483. package/src/core/records-grant-authorization.ts +2 -2
  484. package/src/core/resumable-task-manager.ts +4 -5
  485. package/src/dwn.ts +25 -20
  486. package/src/enums/dwn-interface-method.ts +5 -3
  487. package/src/handlers/messages-subscribe.ts +1 -1
  488. package/src/handlers/messages-sync.ts +129 -0
  489. package/src/handlers/protocols-configure.ts +195 -17
  490. package/src/handlers/protocols-query.ts +7 -5
  491. package/src/handlers/records-count.ts +184 -0
  492. package/src/handlers/records-query.ts +4 -0
  493. package/src/handlers/records-read.ts +4 -8
  494. package/src/handlers/records-write.ts +20 -21
  495. package/src/index.ts +74 -37
  496. package/src/interfaces/messages-read.ts +6 -5
  497. package/src/interfaces/messages-subscribe.ts +7 -6
  498. package/src/interfaces/messages-sync.ts +59 -0
  499. package/src/interfaces/protocols-configure.ts +211 -33
  500. package/src/interfaces/protocols-query.ts +7 -6
  501. package/src/interfaces/records-count.ts +106 -0
  502. package/src/interfaces/records-delete.ts +2 -2
  503. package/src/interfaces/records-query.ts +2 -2
  504. package/src/interfaces/records-read.ts +26 -3
  505. package/src/interfaces/records-subscribe.ts +2 -2
  506. package/src/interfaces/records-write.ts +115 -46
  507. package/src/jose/algorithms/signing/ed25519.ts +13 -12
  508. package/src/jose/algorithms/signing/signature-algorithms.ts +6 -1
  509. package/src/jose/jws/general/builder.ts +3 -3
  510. package/src/jose/jws/general/verifier.ts +3 -3
  511. package/src/protocols/permission-grant.ts +51 -0
  512. package/src/protocols/permission-request.ts +37 -0
  513. package/src/protocols/permissions.ts +5 -5
  514. package/src/schema-validator.ts +11 -3
  515. package/src/smt/smt-store-level.ts +143 -0
  516. package/src/smt/smt-store-memory.ts +53 -0
  517. package/src/smt/smt-utils.ts +149 -0
  518. package/src/smt/sparse-merkle-tree.ts +698 -0
  519. package/src/state-index/state-index-level.ts +241 -0
  520. package/src/store/data-store-level.ts +8 -7
  521. package/src/store/index-level.ts +415 -19
  522. package/src/store/level-wrapper.ts +1 -1
  523. package/src/store/message-store-level.ts +62 -0
  524. package/src/store/storage-controller.ts +21 -19
  525. package/src/types/data-store.ts +2 -4
  526. package/src/types/encryption-types.ts +52 -0
  527. package/src/types/jose-types.ts +10 -42
  528. package/src/types/message-store.ts +11 -0
  529. package/src/types/message-types.ts +21 -0
  530. package/src/types/messages-types.ts +21 -15
  531. package/src/types/method-handler.ts +1 -2
  532. package/src/types/permission-types.ts +2 -2
  533. package/src/types/protocols-types.ts +55 -6
  534. package/src/types/records-types.ts +26 -7
  535. package/src/types/signer.ts +1 -1
  536. package/src/types/smt-types.ts +95 -0
  537. package/src/types/state-index.ts +100 -0
  538. package/src/utils/cid.ts +3 -4
  539. package/src/utils/data-stream.ts +75 -38
  540. package/src/utils/encryption.ts +24 -39
  541. package/src/utils/hd-key.ts +6 -6
  542. package/src/utils/jws.ts +9 -9
  543. package/src/utils/private-key-signer.ts +9 -8
  544. package/src/utils/protocols.ts +132 -6
  545. package/src/utils/records.ts +118 -29
  546. package/src/utils/secp256k1.ts +23 -21
  547. package/src/utils/secp256r1.ts +17 -15
  548. package/src/utils/time.ts +1 -1
  549. package/src/utils/url.ts +1 -1
  550. package/dist/cjs/index.js +0 -36749
  551. package/dist/cjs/package.json +0 -1
  552. package/dist/esm/src/event-log/event-emitter-stream.js.map +0 -1
  553. package/dist/esm/src/event-log/event-log-level.js +0 -63
  554. package/dist/esm/src/event-log/event-log-level.js.map +0 -1
  555. package/dist/esm/src/handlers/messages-query.js +0 -71
  556. package/dist/esm/src/handlers/messages-query.js.map +0 -1
  557. package/dist/esm/src/interfaces/messages-query.js.map +0 -1
  558. package/dist/esm/src/types/event-log.js +0 -2
  559. package/dist/esm/src/types/event-log.js.map +0 -1
  560. package/dist/esm/tests/event-log/event-emitter-stream.spec.js.map +0 -1
  561. package/dist/esm/tests/event-log/event-log-level.spec.js +0 -44
  562. package/dist/esm/tests/event-log/event-log-level.spec.js.map +0 -1
  563. package/dist/esm/tests/event-log/event-log.spec.js +0 -236
  564. package/dist/esm/tests/event-log/event-log.spec.js.map +0 -1
  565. package/dist/esm/tests/event-log/event-stream.spec.js.map +0 -1
  566. package/dist/esm/tests/handlers/messages-query.spec.js +0 -349
  567. package/dist/esm/tests/handlers/messages-query.spec.js.map +0 -1
  568. package/dist/esm/tests/interfaces/messagess-query.spec.js +0 -127
  569. package/dist/esm/tests/interfaces/messagess-query.spec.js.map +0 -1
  570. package/dist/esm/tests/scenarios/messages-query.spec.js +0 -395
  571. package/dist/esm/tests/scenarios/messages-query.spec.js.map +0 -1
  572. package/dist/types/src/event-log/event-emitter-stream.d.ts.map +0 -1
  573. package/dist/types/src/event-log/event-log-level.d.ts +0 -35
  574. package/dist/types/src/event-log/event-log-level.d.ts.map +0 -1
  575. package/dist/types/src/handlers/messages-query.d.ts +0 -17
  576. package/dist/types/src/handlers/messages-query.d.ts.map +0 -1
  577. package/dist/types/src/interfaces/messages-query.d.ts +0 -16
  578. package/dist/types/src/interfaces/messages-query.d.ts.map +0 -1
  579. package/dist/types/src/types/event-log.d.ts +0 -52
  580. package/dist/types/src/types/event-log.d.ts.map +0 -1
  581. package/dist/types/tests/event-log/event-emitter-stream.spec.d.ts.map +0 -1
  582. package/dist/types/tests/event-log/event-log-level.spec.d.ts +0 -2
  583. package/dist/types/tests/event-log/event-log-level.spec.d.ts.map +0 -1
  584. package/dist/types/tests/event-log/event-log.spec.d.ts +0 -2
  585. package/dist/types/tests/event-log/event-log.spec.d.ts.map +0 -1
  586. package/dist/types/tests/event-log/event-stream.spec.d.ts.map +0 -1
  587. package/dist/types/tests/handlers/messages-query.spec.d.ts +0 -2
  588. package/dist/types/tests/handlers/messages-query.spec.d.ts.map +0 -1
  589. package/dist/types/tests/interfaces/messagess-query.spec.d.ts +0 -2
  590. package/dist/types/tests/interfaces/messagess-query.spec.d.ts.map +0 -1
  591. package/dist/types/tests/scenarios/messages-query.spec.d.ts +0 -2
  592. package/dist/types/tests/scenarios/messages-query.spec.d.ts.map +0 -1
  593. package/src/event-log/event-log-level.ts +0 -72
  594. package/src/handlers/messages-query.ts +0 -67
  595. package/src/interfaces/messages-query.ts +0 -60
  596. package/src/types/event-log.ts +0 -52
  597. /package/dist/esm/src/{event-log → event-stream}/event-emitter-stream.js +0 -0
  598. /package/dist/types/src/{event-log → event-stream}/event-emitter-stream.d.ts +0 -0
  599. /package/dist/types/tests/{event-log → event-stream}/event-emitter-stream.spec.d.ts +0 -0
  600. /package/dist/types/tests/{event-log → event-stream}/event-stream.spec.d.ts +0 -0
  601. /package/src/{event-log → event-stream}/event-emitter-stream.ts +0 -0
@@ -1,19 +1,24 @@
1
1
  import type { Filter } from '../types/query-types.js';
2
2
  import type { MessageStore } from '../types/message-store.js';
3
+ import type { RecordsCount } from '../interfaces/records-count.js';
3
4
  import type { RecordsDelete } from '../interfaces/records-delete.js';
4
5
  import type { RecordsQuery } from '../interfaces/records-query.js';
5
6
  import type { RecordsRead } from '../interfaces/records-read.js';
6
7
  import type { RecordsSubscribe } from '../interfaces/records-subscribe.js';
7
8
  import type { RecordsWriteMessage } from '../types/records-types.js';
8
- import type { ProtocolActionRule, ProtocolDefinition, ProtocolRuleSet, ProtocolsConfigureMessage, ProtocolType, ProtocolTypes } from '../types/protocols-types.js';
9
+ import type {
10
+ ProtocolActionRule, ProtocolDefinition, ProtocolRuleSet, ProtocolsConfigureMessage, ProtocolType, ProtocolTypes
11
+ } from '../types/protocols-types.js';
9
12
 
10
13
  import Ajv from 'ajv/dist/2020.js';
11
14
  import { FilterUtility } from '../utils/filter.js';
12
15
  import { PermissionsProtocol } from '../protocols/permissions.js';
13
16
  import { Records } from '../utils/records.js';
14
17
  import { RecordsWrite } from '../interfaces/records-write.js';
18
+ import { SortDirection } from '../types/query-types.js';
15
19
  import { DwnError, DwnErrorCode } from './dwn-error.js';
16
20
  import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
21
+ import { getRuleSetAtPath, isCrossProtocolRef, parseCrossProtocolRef } from '../utils/protocols.js';
17
22
  import { ProtocolAction, ProtocolActor } from '../types/protocols-types.js';
18
23
 
19
24
  export class ProtocolAuthorization {
@@ -27,17 +32,25 @@ export class ProtocolAuthorization {
27
32
  incomingMessage: RecordsWrite,
28
33
  messageStore: MessageStore,
29
34
  ): Promise<void> {
30
- // fetch the protocol definition
35
+ // Determine the governing timestamp for protocol definition lookup.
36
+ // For an initial write, this is the message's own timestamp.
37
+ // For an update, this is the initial write's timestamp (the protocol version is locked at creation time).
38
+ const governingTimestamp = await ProtocolAuthorization.getGoverningTimestamp(
39
+ tenant, incomingMessage, messageStore
40
+ );
41
+
42
+ // fetch the protocol definition that was active at the governing timestamp
31
43
  const protocolDefinition = await ProtocolAuthorization.fetchProtocolDefinition(
32
44
  tenant,
33
45
  incomingMessage.message.descriptor.protocol!,
34
46
  messageStore,
47
+ governingTimestamp,
35
48
  );
36
49
 
37
- // verify declared protocol type exists in protocol and that it conforms to type specification
38
- ProtocolAuthorization.verifyType(
39
- incomingMessage.message,
40
- protocolDefinition.types
50
+ // verify declared protocol type exists in protocol and that it conforms to type specification.
51
+ // For cross-protocol composition, the type may be defined in a referenced protocol.
52
+ await ProtocolAuthorization.verifyTypeWithComposition(
53
+ tenant, incomingMessage.message, protocolDefinition, messageStore, governingTimestamp
41
54
  );
42
55
 
43
56
  // validate `protocolPath`
@@ -45,6 +58,7 @@ export class ProtocolAuthorization {
45
58
  tenant,
46
59
  incomingMessage,
47
60
  messageStore,
61
+ governingTimestamp,
48
62
  );
49
63
 
50
64
  // get the rule set for the inbound message
@@ -89,11 +103,17 @@ export class ProtocolAuthorization {
89
103
  recordChain = await ProtocolAuthorization.constructRecordChain(tenant, incomingMessage.message.recordId, messageStore);
90
104
  }
91
105
 
92
- // fetch the protocol definition
106
+ // Determine the governing timestamp for protocol definition lookup.
107
+ const governingTimestamp = await ProtocolAuthorization.getGoverningTimestamp(
108
+ tenant, incomingMessage, messageStore
109
+ );
110
+
111
+ // fetch the protocol definition that was active at the governing timestamp
93
112
  const protocolDefinition = await ProtocolAuthorization.fetchProtocolDefinition(
94
113
  tenant,
95
114
  incomingMessage.message.descriptor.protocol!,
96
115
  messageStore,
116
+ governingTimestamp,
97
117
  );
98
118
 
99
119
  // get the rule set for the inbound message
@@ -110,6 +130,7 @@ export class ProtocolAuthorization {
110
130
  incomingMessage.message.contextId!,
111
131
  protocolDefinition,
112
132
  messageStore,
133
+ governingTimestamp,
113
134
  );
114
135
 
115
136
  // verify method invoked against the allowed actions in the rule set
@@ -119,6 +140,7 @@ export class ProtocolAuthorization {
119
140
  ruleSet,
120
141
  recordChain,
121
142
  messageStore,
143
+ protocolDefinition,
122
144
  );
123
145
  }
124
146
 
@@ -137,11 +159,21 @@ export class ProtocolAuthorization {
137
159
  const recordChain: RecordsWriteMessage[] =
138
160
  await ProtocolAuthorization.constructRecordChain(tenant, newestRecordsWrite.message.recordId, messageStore);
139
161
 
140
- // fetch the protocol definition
162
+ // Use the initial write's timestamp to determine the governing protocol definition.
163
+ // The protocol version is locked at the time the record was first created.
164
+ const initialWrite = await ProtocolAuthorization.fetchInitialWrite(
165
+ tenant, newestRecordsWrite.message.recordId, messageStore
166
+ );
167
+ const governingTimestamp = initialWrite !== undefined
168
+ ? initialWrite.descriptor.messageTimestamp
169
+ : newestRecordsWrite.message.descriptor.messageTimestamp;
170
+
171
+ // fetch the protocol definition that was active when the record was created
141
172
  const protocolDefinition = await ProtocolAuthorization.fetchProtocolDefinition(
142
173
  tenant,
143
174
  newestRecordsWrite.message.descriptor.protocol!,
144
175
  messageStore,
176
+ governingTimestamp,
145
177
  );
146
178
 
147
179
  // get the rule set for the inbound message
@@ -158,6 +190,7 @@ export class ProtocolAuthorization {
158
190
  newestRecordsWrite.message.contextId!,
159
191
  protocolDefinition,
160
192
  messageStore,
193
+ governingTimestamp,
161
194
  );
162
195
 
163
196
  // verify method invoked against the allowed actions in the rule set
@@ -167,12 +200,13 @@ export class ProtocolAuthorization {
167
200
  ruleSet,
168
201
  recordChain,
169
202
  messageStore,
203
+ protocolDefinition,
170
204
  );
171
205
  }
172
206
 
173
207
  public static async authorizeQueryOrSubscribe(
174
208
  tenant: string,
175
- incomingMessage: RecordsQuery | RecordsSubscribe,
209
+ incomingMessage: RecordsCount | RecordsQuery | RecordsSubscribe,
176
210
  messageStore: MessageStore,
177
211
  ): Promise<void> {
178
212
  const { protocol, protocolPath, contextId } = incomingMessage.message.descriptor.filter;
@@ -207,6 +241,7 @@ export class ProtocolAuthorization {
207
241
  ruleSet,
208
242
  [], // record chain is not relevant to queries or subscriptions
209
243
  messageStore,
244
+ protocolDefinition,
210
245
  );
211
246
  }
212
247
 
@@ -225,11 +260,20 @@ export class ProtocolAuthorization {
225
260
  const recordChain: RecordsWriteMessage[] =
226
261
  await ProtocolAuthorization.constructRecordChain(tenant, incomingMessage.message.descriptor.recordId, messageStore);
227
262
 
228
- // fetch the protocol definition
263
+ // Use the initial write's timestamp to determine the governing protocol definition.
264
+ const initialWrite = await ProtocolAuthorization.fetchInitialWrite(
265
+ tenant, incomingMessage.message.descriptor.recordId, messageStore
266
+ );
267
+ const governingTimestamp = initialWrite !== undefined
268
+ ? initialWrite.descriptor.messageTimestamp
269
+ : recordsWrite.message.descriptor.messageTimestamp;
270
+
271
+ // fetch the protocol definition that was active when the record was created
229
272
  const protocolDefinition = await ProtocolAuthorization.fetchProtocolDefinition(
230
273
  tenant,
231
274
  recordsWrite.message.descriptor.protocol!,
232
275
  messageStore,
276
+ governingTimestamp,
233
277
  );
234
278
 
235
279
  // get the rule set for the inbound message
@@ -246,6 +290,7 @@ export class ProtocolAuthorization {
246
290
  recordsWrite.message.contextId!,
247
291
  protocolDefinition,
248
292
  messageStore,
293
+ governingTimestamp,
249
294
  );
250
295
 
251
296
  // verify method invoked against the allowed actions in the rule set
@@ -255,16 +300,21 @@ export class ProtocolAuthorization {
255
300
  ruleSet,
256
301
  recordChain,
257
302
  messageStore,
303
+ protocolDefinition,
258
304
  );
259
305
  }
260
306
 
261
307
  /**
262
308
  * Fetches the protocol definition based on the protocol specified in the given message.
309
+ * When `messageTimestamp` is provided, returns the protocol definition that was active at that
310
+ * point in time — i.e. the ProtocolsConfigure with the greatest `messageTimestamp` that is <= the
311
+ * given timestamp. When not provided, returns the latest (current) protocol definition.
263
312
  */
264
313
  private static async fetchProtocolDefinition(
265
314
  tenant: string,
266
315
  protocolUri: string,
267
- messageStore: MessageStore
316
+ messageStore: MessageStore,
317
+ messageTimestamp?: string,
268
318
  ): Promise<ProtocolDefinition> {
269
319
  // if first-class protocol, return the definition from const object directly without going to data store
270
320
  if (protocolUri === PermissionsProtocol.uri) {
@@ -275,9 +325,23 @@ export class ProtocolAuthorization {
275
325
  const query: Filter = {
276
326
  interface : DwnInterfaceName.Protocols,
277
327
  method : DwnMethodName.Configure,
278
- protocol : protocolUri
328
+ protocol : protocolUri,
279
329
  };
280
- const { messages: protocols } = await messageStore.query(tenant, [query]);
330
+
331
+ if (messageTimestamp !== undefined) {
332
+ // temporal lookup: find the protocol definition active at the given timestamp
333
+ query.messageTimestamp = { lte: messageTimestamp };
334
+ } else {
335
+ // default: return only the latest protocol definition
336
+ query.isLatestBaseState = true;
337
+ }
338
+
339
+ const { messages: protocols } = await messageStore.query(
340
+ tenant,
341
+ [query],
342
+ { messageTimestamp: SortDirection.Descending },
343
+ { limit: 1 },
344
+ );
281
345
 
282
346
  if (protocols.length === 0) {
283
347
  throw new DwnError(DwnErrorCode.ProtocolAuthorizationProtocolNotFound, `unable to find protocol definition for ${protocolUri}`);
@@ -362,7 +426,7 @@ export class ProtocolAuthorization {
362
426
  protocolPath: string,
363
427
  protocolDefinition: ProtocolDefinition,
364
428
  ): ProtocolRuleSet {
365
- const ruleSet = ProtocolAuthorization.getRuleSetAtProtocolPath(protocolPath, protocolDefinition);
429
+ const ruleSet = getRuleSetAtPath(protocolPath, protocolDefinition.structure);
366
430
  if (ruleSet === undefined) {
367
431
  throw new DwnError(DwnErrorCode.ProtocolAuthorizationMissingRuleSet,
368
432
  `No rule set defined for protocolPath ${protocolPath}`);
@@ -372,12 +436,14 @@ export class ProtocolAuthorization {
372
436
 
373
437
  /**
374
438
  * Verifies the `protocolPath` declared in the given message (if it is a RecordsWrite) matches the path of actual record chain.
439
+ * For cross-protocol composition, the parent record may belong to a different protocol (resolved via `$ref` in the composing protocol).
375
440
  * @throws {DwnError} if fails verification.
376
441
  */
377
442
  private static async verifyProtocolPathAndContextId(
378
443
  tenant: string,
379
444
  inboundMessage: RecordsWrite,
380
- messageStore: MessageStore
445
+ messageStore: MessageStore,
446
+ governingTimestamp?: string,
381
447
  ): Promise<void> {
382
448
  const declaredProtocolPath = inboundMessage.message.descriptor.protocolPath!;
383
449
  const declaredTypeName = ProtocolAuthorization.getTypeName(declaredProtocolPath);
@@ -396,20 +462,42 @@ export class ProtocolAuthorization {
396
462
 
397
463
  // Else `parentId` is defined, so we need to verify both protocolPath and contextId
398
464
 
465
+ // Determine the protocol URI for the parent query.
466
+ // If the parent path segment has a `$ref` in the composing protocol, the parent lives in a different protocol.
467
+ const childProtocol = inboundMessage.message.descriptor.protocol!;
468
+ const parentProtocolUri = await ProtocolAuthorization.resolveParentProtocolUri(
469
+ tenant, childProtocol, declaredProtocolPath, messageStore, governingTimestamp
470
+ );
471
+
399
472
  // fetch the parent message
400
- const protocol = inboundMessage.message.descriptor.protocol!;
401
473
  const query: Filter = {
402
474
  isLatestBaseState : true, // NOTE: this filter is critical, to ensure are are not returning a deleted parent
403
475
  interface : DwnInterfaceName.Records,
404
476
  method : DwnMethodName.Write,
405
- protocol,
477
+ protocol : parentProtocolUri,
406
478
  recordId : parentId
407
479
  };
408
480
  const { messages: parentMessages } = await messageStore.query(tenant, [query]);
409
481
  const parentMessage = (parentMessages as RecordsWriteMessage[])[0];
410
482
 
483
+ if (parentMessage === undefined) {
484
+ // if this is a cross-protocol composition lookup, use a more descriptive error
485
+ if (parentProtocolUri !== childProtocol) {
486
+ throw new DwnError(
487
+ DwnErrorCode.ProtocolAuthorizationCrossProtocolParentNotFound,
488
+ `Could not find parent record '${parentId}' in protocol '${parentProtocolUri}' ` +
489
+ `for cross-protocol child at path '${declaredProtocolPath}'.`
490
+ );
491
+ }
492
+
493
+ throw new DwnError(
494
+ DwnErrorCode.ProtocolAuthorizationIncorrectProtocolPath,
495
+ `Could not find matching parent record to verify declared protocol path '${declaredProtocolPath}'.`
496
+ );
497
+ }
498
+
411
499
  // verifying protocolPath of incoming message is a child of the parent message's protocolPath
412
- const parentProtocolPath = parentMessage?.descriptor?.protocolPath;
500
+ const parentProtocolPath = parentMessage.descriptor.protocolPath;
413
501
  const expectedProtocolPath = `${parentProtocolPath}/${declaredTypeName}`;
414
502
  if (expectedProtocolPath !== declaredProtocolPath) {
415
503
  throw new DwnError(
@@ -430,6 +518,123 @@ export class ProtocolAuthorization {
430
518
 
431
519
  }
432
520
 
521
+ /**
522
+ * Resolves the protocol URI that should be used when querying for the parent record.
523
+ * For standard (non-composed) records, this is the same as the child's protocol.
524
+ * For cross-protocol composition, the parent may live in a different protocol
525
+ * (resolved via `$ref` in the composing protocol's definition).
526
+ *
527
+ * Logic: Given a child at protocolPath `a/b/c`, the parent is at `a/b`.
528
+ * Walk up the composing protocol's structure from root to `a/b`.
529
+ * If any segment along the way has a `$ref`, the parent (and its ancestors up to the `$ref` boundary)
530
+ * live in the referenced protocol. Specifically, the `$ref` at the topmost ancestor tells us
531
+ * the parent's protocol URI.
532
+ */
533
+ private static async resolveParentProtocolUri(
534
+ tenant: string,
535
+ childProtocolUri: string,
536
+ childProtocolPath: string,
537
+ messageStore: MessageStore,
538
+ governingTimestamp?: string,
539
+ ): Promise<string> {
540
+ const segments = childProtocolPath.split('/');
541
+
542
+ // A root-level record (no `/` in path) has no parent or uses the same protocol
543
+ if (segments.length <= 1) {
544
+ return childProtocolUri;
545
+ }
546
+
547
+ // Fetch the composing protocol's definition at the governing timestamp
548
+ const composingDefinition = await ProtocolAuthorization.fetchProtocolDefinition(
549
+ tenant, childProtocolUri, messageStore, governingTimestamp
550
+ );
551
+
552
+ // Walk the structure to find the parent's path segment
553
+ // The parent's position in the structure is at segments[0..n-2]
554
+ // We check if the first segment has a `$ref`, which means the parent is in a different protocol
555
+ const firstSegmentRuleSet = composingDefinition.structure[segments[0]];
556
+ if (firstSegmentRuleSet?.$ref !== undefined) {
557
+ const parsed = parseCrossProtocolRef(firstSegmentRuleSet.$ref);
558
+ if (parsed !== undefined && composingDefinition.uses !== undefined) {
559
+ const resolvedUri = composingDefinition.uses[parsed.alias];
560
+ if (resolvedUri !== undefined) {
561
+ // The parent path is within the `$ref` boundary — check if the parent IS the `$ref` node
562
+ // or is a descendant of it (which would still be in the composing protocol).
563
+ // If segments.length === 2, parent is at segments[0] which IS the $ref node → parent's protocol is the referenced one.
564
+ // If segments.length > 2, parent is at segments[0..n-2]. If segments[0] is $ref, the parent could be:
565
+ // - Still the $ref node itself (segments.length === 2) → referenced protocol
566
+ // - A child of the $ref node defined in the composing protocol (segments.length > 2) → composing protocol
567
+ if (segments.length === 2) {
568
+ // Parent is the $ref node itself (e.g., child is "thread/comment", parent is "thread")
569
+ return resolvedUri;
570
+ }
571
+ // else: parent is a deeper child defined in the composing protocol
572
+ return childProtocolUri;
573
+ }
574
+ }
575
+ }
576
+
577
+ return childProtocolUri;
578
+ }
579
+
580
+ /**
581
+ * Verifies the `dataFormat` and `schema` declared in the given message matches the type in the protocol.
582
+ * For cross-protocol composition, if the type is at a `$ref` position in the structure,
583
+ * the type definition is looked up in the referenced protocol's `types` map instead.
584
+ */
585
+ private static async verifyTypeWithComposition(
586
+ tenant: string,
587
+ inboundMessage: RecordsWriteMessage,
588
+ protocolDefinition: ProtocolDefinition,
589
+ messageStore: MessageStore,
590
+ governingTimestamp?: string,
591
+ ): Promise<void> {
592
+ const declaredProtocolPath = inboundMessage.descriptor.protocolPath!;
593
+ const declaredTypeName = ProtocolAuthorization.getTypeName(declaredProtocolPath);
594
+
595
+ // Resolve which protocol types map to use.
596
+ // If the first path segment has `$ref`, this record's type might be defined in a referenced protocol.
597
+ const protocolTypes = await ProtocolAuthorization.resolveProtocolTypesForPath(
598
+ tenant, declaredProtocolPath, protocolDefinition, messageStore, governingTimestamp
599
+ );
600
+
601
+ ProtocolAuthorization.verifyType(inboundMessage, protocolTypes, declaredTypeName);
602
+ }
603
+
604
+ /**
605
+ * Resolves the `ProtocolTypes` map that contains the type definition for the given protocol path.
606
+ * For non-composed records, this is the protocol definition's own `types` map.
607
+ * For records at a `$ref` position, this is the referenced protocol's `types` map.
608
+ */
609
+ private static async resolveProtocolTypesForPath(
610
+ tenant: string,
611
+ protocolPath: string,
612
+ protocolDefinition: ProtocolDefinition,
613
+ messageStore: MessageStore,
614
+ governingTimestamp?: string,
615
+ ): Promise<ProtocolTypes> {
616
+ const segments = protocolPath.split('/');
617
+
618
+ // Check if the first segment has a `$ref`
619
+ const firstSegmentRuleSet = protocolDefinition.structure[segments[0]];
620
+ if (firstSegmentRuleSet?.$ref !== undefined && segments.length === 1) {
621
+ // This record IS the $ref node itself — its type is defined in the referenced protocol
622
+ const parsed = parseCrossProtocolRef(firstSegmentRuleSet.$ref);
623
+ if (parsed !== undefined && protocolDefinition.uses !== undefined) {
624
+ const refProtocolUri = protocolDefinition.uses[parsed.alias];
625
+ if (refProtocolUri !== undefined) {
626
+ const refDefinition = await ProtocolAuthorization.fetchProtocolDefinition(
627
+ tenant, refProtocolUri, messageStore, governingTimestamp
628
+ );
629
+ return refDefinition.types;
630
+ }
631
+ }
632
+ }
633
+
634
+ // Default: use the composing protocol's own types
635
+ return protocolDefinition.types;
636
+ }
637
+
433
638
  /**
434
639
  * Verifies the `dataFormat` and `schema` declared in the given message (if it is a RecordsWrite) matches dataFormat
435
640
  * and schema of the type in the given protocol.
@@ -438,27 +643,24 @@ export class ProtocolAuthorization {
438
643
  private static verifyType(
439
644
  inboundMessage: RecordsWriteMessage,
440
645
  protocolTypes: ProtocolTypes,
646
+ typeName?: string,
441
647
  ): void {
442
-
648
+ const declaredTypeName = typeName ?? ProtocolAuthorization.getTypeName(inboundMessage.descriptor.protocolPath!);
443
649
  const typeNames = Object.keys(protocolTypes);
444
- const declaredProtocolPath = inboundMessage.descriptor.protocolPath!;
445
- const declaredTypeName = ProtocolAuthorization.getTypeName(declaredProtocolPath);
650
+
446
651
  if (!typeNames.includes(declaredTypeName)) {
447
652
  throw new DwnError(DwnErrorCode.ProtocolAuthorizationInvalidType,
448
653
  `record with type ${declaredTypeName} not allowed in protocol`);
449
654
  }
450
655
 
451
- const protocolPath = inboundMessage.descriptor.protocolPath!;
452
- // existence of `protocolType` has already been verified
453
- const typeName = ProtocolAuthorization.getTypeName(protocolPath);
454
- const protocolType: ProtocolType = protocolTypes[typeName];
656
+ const protocolType: ProtocolType = protocolTypes[declaredTypeName];
455
657
 
456
658
  // no `schema` specified in protocol definition means that any schema is allowed
457
659
  const { schema } = inboundMessage.descriptor;
458
660
  if (protocolType.schema !== undefined && protocolType.schema !== schema) {
459
661
  throw new DwnError(
460
662
  DwnErrorCode.ProtocolAuthorizationInvalidSchema,
461
- `type '${typeName}' must have schema '${protocolType.schema}', \
663
+ `type '${declaredTypeName}' must have schema '${protocolType.schema}', \
462
664
  instead has '${schema}'`
463
665
  );
464
666
  }
@@ -468,7 +670,7 @@ export class ProtocolAuthorization {
468
670
  if (protocolType.dataFormats !== undefined && !protocolType.dataFormats.includes(dataFormat)) {
469
671
  throw new DwnError(
470
672
  DwnErrorCode.ProtocolAuthorizationIncorrectDataFormat,
471
- `type '${typeName}' must have data format in (${protocolType.dataFormats}), \
673
+ `type '${declaredTypeName}' must have data format in (${protocolType.dataFormats}), \
472
674
  instead has '${dataFormat}'`
473
675
  );
474
676
  }
@@ -476,14 +678,17 @@ export class ProtocolAuthorization {
476
678
 
477
679
  /**
478
680
  * Check if the incoming message is invoking a role. If so, validate the invoked role.
681
+ * For cross-protocol role invocation, the role record may live in a different protocol
682
+ * (resolved via the composing protocol's `uses` map).
479
683
  */
480
684
  private static async verifyInvokedRole(
481
685
  tenant: string,
482
- incomingMessage: RecordsDelete | RecordsQuery | RecordsRead | RecordsSubscribe | RecordsWrite,
686
+ incomingMessage: RecordsCount | RecordsDelete | RecordsQuery | RecordsRead | RecordsSubscribe | RecordsWrite,
483
687
  protocolUri: string,
484
688
  contextId: string | undefined,
485
689
  protocolDefinition: ProtocolDefinition,
486
690
  messageStore: MessageStore,
691
+ governingTimestamp?: string,
487
692
  ): Promise<void> {
488
693
  const protocolRole = incomingMessage.signaturePayload?.protocolRole;
489
694
 
@@ -492,25 +697,63 @@ export class ProtocolAuthorization {
492
697
  return;
493
698
  }
494
699
 
495
- const roleRuleSet = ProtocolAuthorization.getRuleSetAtProtocolPath(protocolRole, protocolDefinition);
496
- if (roleRuleSet === undefined || !roleRuleSet.$role) {
497
- throw new DwnError(
498
- DwnErrorCode.ProtocolAuthorizationNotARole,
499
- `Protocol path ${protocolRole} does not match role record type.`
700
+ // Determine the protocol URI and protocol path for the role record.
701
+ // For cross-protocol roles (e.g., "threads:thread/participant"), resolve the alias.
702
+ let roleProtocolUri = protocolUri;
703
+ let roleProtocolPath = protocolRole;
704
+
705
+ if (isCrossProtocolRef(protocolRole)) {
706
+ const parsed = parseCrossProtocolRef(protocolRole);
707
+ if (parsed === undefined) {
708
+ throw new DwnError(
709
+ DwnErrorCode.ProtocolAuthorizationNotARole,
710
+ `Cross-protocol role '${protocolRole}' could not be parsed as a valid 'alias:path' format.`
711
+ );
712
+ }
713
+
714
+ if (protocolDefinition.uses === undefined || protocolDefinition.uses[parsed.alias] === undefined) {
715
+ throw new DwnError(
716
+ DwnErrorCode.ProtocolAuthorizationNotARole,
717
+ `Cross-protocol role alias '${parsed.alias}' in '${protocolRole}' does not exist in the protocol's 'uses' map.`
718
+ );
719
+ }
720
+
721
+ roleProtocolUri = protocolDefinition.uses[parsed.alias];
722
+ roleProtocolPath = parsed.protocolPath;
723
+
724
+ // Fetch the referenced protocol's definition to validate the role exists
725
+ const refDefinition = await ProtocolAuthorization.fetchProtocolDefinition(
726
+ tenant, roleProtocolUri, messageStore, governingTimestamp
500
727
  );
728
+ const roleRuleSet = getRuleSetAtPath(roleProtocolPath, refDefinition.structure);
729
+ if (roleRuleSet === undefined || !roleRuleSet.$role) {
730
+ throw new DwnError(
731
+ DwnErrorCode.ProtocolAuthorizationNotARole,
732
+ `Cross-protocol role path ${protocolRole} does not match role record type.`
733
+ );
734
+ }
735
+ } else {
736
+ // Local role: validate in the composing protocol's definition
737
+ const roleRuleSet = getRuleSetAtPath(protocolRole, protocolDefinition.structure);
738
+ if (roleRuleSet === undefined || !roleRuleSet.$role) {
739
+ throw new DwnError(
740
+ DwnErrorCode.ProtocolAuthorizationNotARole,
741
+ `Protocol path ${protocolRole} does not match role record type.`
742
+ );
743
+ }
501
744
  }
502
745
 
503
746
  // Construct a filter to fetch the invoked role record
504
747
  const roleRecordFilter: Filter = {
505
748
  interface : DwnInterfaceName.Records,
506
749
  method : DwnMethodName.Write,
507
- protocol : protocolUri,
508
- protocolPath : protocolRole,
750
+ protocol : roleProtocolUri,
751
+ protocolPath : roleProtocolPath,
509
752
  recipient : incomingMessage.author!,
510
753
  isLatestBaseState : true,
511
754
  };
512
755
 
513
- const ancestorSegmentCountOfRolePath = protocolRole.split('/').length - 1;
756
+ const ancestorSegmentCountOfRolePath = roleProtocolPath.split('/').length - 1;
514
757
  if (contextId === undefined && ancestorSegmentCountOfRolePath > 0) {
515
758
  throw new DwnError(
516
759
  DwnErrorCode.ProtocolAuthorizationMissingContextId,
@@ -536,7 +779,7 @@ export class ProtocolAuthorization {
536
779
  if (matchingMessages.length === 0) {
537
780
  throw new DwnError(
538
781
  DwnErrorCode.ProtocolAuthorizationMatchingRoleRecordNotFound,
539
- `No matching role record found for protocol path ${protocolRole}`
782
+ `No matching role record found for protocol path ${roleProtocolPath}`
540
783
  );
541
784
  }
542
785
  }
@@ -553,7 +796,7 @@ export class ProtocolAuthorization {
553
796
  */
554
797
  private static async getActionsSeekingARuleMatch(
555
798
  tenant: string,
556
- incomingMessage: RecordsDelete | RecordsQuery | RecordsRead | RecordsSubscribe | RecordsWrite,
799
+ incomingMessage: RecordsCount | RecordsDelete | RecordsQuery | RecordsRead | RecordsSubscribe | RecordsWrite,
557
800
  messageStore: MessageStore,
558
801
  ): Promise<ProtocolAction[]> {
559
802
 
@@ -590,14 +833,17 @@ export class ProtocolAuthorization {
590
833
 
591
834
  return actionsThatWouldAuthorizeDelete;
592
835
 
836
+ case DwnMethodName.Count:
837
+ return [ProtocolAction.Read];
838
+
593
839
  case DwnMethodName.Query:
594
- return [ProtocolAction.Query];
840
+ return [ProtocolAction.Read];
595
841
 
596
842
  case DwnMethodName.Read:
597
843
  return [ProtocolAction.Read];
598
844
 
599
845
  case DwnMethodName.Subscribe:
600
- return [ProtocolAction.Subscribe];
846
+ return [ProtocolAction.Read];
601
847
 
602
848
  case DwnMethodName.Write:
603
849
  const incomingRecordsWrite = incomingMessage as RecordsWrite;
@@ -632,14 +878,16 @@ export class ProtocolAuthorization {
632
878
 
633
879
  /**
634
880
  * Verifies the given message is authorized by one of the action rules in the given protocol rule set.
881
+ * @param protocolDefinition Optional protocol definition for resolving cross-protocol `of` and `role` references.
635
882
  * @throws {Error} if action not allowed.
636
883
  */
637
884
  private static async authorizeAgainstAllowedActions(
638
885
  tenant: string,
639
- incomingMessage: RecordsDelete | RecordsQuery | RecordsRead | RecordsSubscribe | RecordsWrite,
886
+ incomingMessage: RecordsCount | RecordsDelete | RecordsQuery | RecordsRead | RecordsSubscribe | RecordsWrite,
640
887
  ruleSet: ProtocolRuleSet,
641
888
  recordChain: RecordsWriteMessage[],
642
889
  messageStore: MessageStore,
890
+ protocolDefinition?: ProtocolDefinition,
643
891
  ): Promise<void> {
644
892
  const incomingMessageMethod = incomingMessage.message.descriptor.method;
645
893
  const actionsSeekingARuleMatch = await ProtocolAuthorization.getActionsSeekingARuleMatch(tenant, incomingMessage, messageStore);
@@ -716,7 +964,7 @@ export class ProtocolAuthorization {
716
964
  }
717
965
 
718
966
  // validate the actor is allowed by the current action rule
719
- const ancestorRuleSuccess: boolean = await ProtocolAuthorization.checkActor(author, actionRule, recordChain);
967
+ const ancestorRuleSuccess: boolean = await ProtocolAuthorization.checkActor(author, actionRule, recordChain, protocolDefinition);
720
968
  if (ancestorRuleSuccess) {
721
969
  return;
722
970
  }
@@ -847,43 +1095,48 @@ export class ProtocolAuthorization {
847
1095
  }
848
1096
  }
849
1097
 
850
- private static getRuleSetAtProtocolPath(protocolPath: string, protocolDefinition: ProtocolDefinition): ProtocolRuleSet | undefined {
851
- const protocolPathArray = protocolPath.split('/');
852
- let currentRuleSet: ProtocolRuleSet = protocolDefinition.structure;
853
- let i = 0;
854
- while (i < protocolPathArray.length) {
855
- const currentTypeName = protocolPathArray[i];
856
- const nextRuleSet: ProtocolRuleSet | undefined = currentRuleSet[currentTypeName];
857
-
858
- if (nextRuleSet === undefined) {
859
- return undefined;
860
- }
861
-
862
- currentRuleSet = nextRuleSet;
863
- i++;
864
- }
865
-
866
- return currentRuleSet;
867
- }
868
-
869
1098
  /**
870
1099
  * Checks if the `who: 'author' | 'recipient'` action rule has a matching record in the record chain.
1100
+ * For cross-protocol `of` references (e.g., `"threads:thread"`), matches against both the protocol URI
1101
+ * and the protocol path of the ancestor record.
871
1102
  * @returns `true` if the action rule is satisfied; `false` otherwise.
872
1103
  */
873
1104
  private static async checkActor(
874
1105
  author: string,
875
1106
  actionRule: ProtocolActionRule,
876
1107
  recordChain: RecordsWriteMessage[],
1108
+ composingDefinition?: ProtocolDefinition,
877
1109
  ): Promise<boolean> {
878
- // find a message with matching protocolPath
879
- const ancestorRecordsWrite = recordChain.find((recordsWriteMessage) =>
880
- recordsWriteMessage.descriptor.protocolPath === actionRule.of!
881
- );
1110
+ const ofValue = actionRule.of;
1111
+
1112
+ // `of` should always be defined when `checkActor` is called, but guard defensively
1113
+ if (ofValue === undefined) {
1114
+ return false;
1115
+ }
1116
+
1117
+ let ancestorRecordsWrite: RecordsWriteMessage | undefined;
1118
+
1119
+ if (isCrossProtocolRef(ofValue) && composingDefinition?.uses !== undefined) {
1120
+ // Cross-protocol `of`: resolve alias to protocol URI and match by both protocol + protocolPath
1121
+ const parsed = parseCrossProtocolRef(ofValue);
1122
+ if (parsed !== undefined) {
1123
+ const refProtocolUri = composingDefinition.uses[parsed.alias];
1124
+ if (refProtocolUri !== undefined) {
1125
+ ancestorRecordsWrite = recordChain.find((msg) =>
1126
+ msg.descriptor.protocol === refProtocolUri && msg.descriptor.protocolPath === parsed.protocolPath
1127
+ );
1128
+ }
1129
+ }
1130
+ } else {
1131
+ // Local `of`: match by protocolPath only (same protocol assumed)
1132
+ ancestorRecordsWrite = recordChain.find((msg) =>
1133
+ msg.descriptor.protocolPath === ofValue
1134
+ );
1135
+ }
882
1136
 
883
1137
  if (ancestorRecordsWrite === undefined) {
884
- // If this is reached, there is likely an issue with the protocol definition.
885
- // The protocolPath to the actionRule should start with actionRule.of
886
- // consider moving this check to ProtocolsConfigure message ingestion
1138
+ // No matching ancestor found in the record chain. Return false to allow the caller
1139
+ // to continue evaluating other action rules that might authorize the request.
887
1140
  return false;
888
1141
  }
889
1142
 
@@ -897,6 +1150,30 @@ export class ProtocolAuthorization {
897
1150
  }
898
1151
  }
899
1152
 
1153
+ /**
1154
+ * Determines the timestamp that governs which protocol definition version applies to the given RecordsWrite.
1155
+ * For an update, this is the initial write's `messageTimestamp` (the protocol version is locked at creation time).
1156
+ * For a new initial write, returns `undefined` — the latest protocol definition should be used because the
1157
+ * record is being created now and must conform to the current protocol rules.
1158
+ */
1159
+ private static async getGoverningTimestamp(
1160
+ tenant: string,
1161
+ incomingMessage: RecordsWrite,
1162
+ messageStore: MessageStore,
1163
+ ): Promise<string | undefined> {
1164
+ const existingInitialWrite = await ProtocolAuthorization.fetchInitialWrite(
1165
+ tenant, incomingMessage.message.recordId, messageStore
1166
+ );
1167
+
1168
+ if (existingInitialWrite !== undefined) {
1169
+ // update case: use the initial write's timestamp
1170
+ return existingInitialWrite.descriptor.messageTimestamp;
1171
+ }
1172
+
1173
+ // initial write case: validate against the latest protocol definition
1174
+ return undefined;
1175
+ }
1176
+
900
1177
  private static getTypeName(protocolPath: string): string {
901
1178
  return protocolPath.split('/').slice(-1)[0];
902
1179
  }