@enbox/dwn-sdk-js 0.0.1

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 (810) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +352 -0
  3. package/dist/bundles/dwn.js +153 -0
  4. package/dist/cjs/index.js +36749 -0
  5. package/dist/cjs/package.json +1 -0
  6. package/dist/esm/generated/precompiled-validators.js +11973 -0
  7. package/dist/esm/generated/precompiled-validators.js.map +1 -0
  8. package/dist/esm/json-schemas/definitions.json +23 -0
  9. package/dist/esm/src/core/abstract-message.js +47 -0
  10. package/dist/esm/src/core/abstract-message.js.map +1 -0
  11. package/dist/esm/src/core/auth.js +39 -0
  12. package/dist/esm/src/core/auth.js.map +1 -0
  13. package/dist/esm/src/core/dwn-constant.js +10 -0
  14. package/dist/esm/src/core/dwn-constant.js.map +1 -0
  15. package/dist/esm/src/core/dwn-error.js +169 -0
  16. package/dist/esm/src/core/dwn-error.js.map +1 -0
  17. package/dist/esm/src/core/grant-authorization.js +97 -0
  18. package/dist/esm/src/core/grant-authorization.js.map +1 -0
  19. package/dist/esm/src/core/message-reply.js +5 -0
  20. package/dist/esm/src/core/message-reply.js.map +1 -0
  21. package/dist/esm/src/core/message.js +233 -0
  22. package/dist/esm/src/core/message.js.map +1 -0
  23. package/dist/esm/src/core/messages-grant-authorization.js +101 -0
  24. package/dist/esm/src/core/messages-grant-authorization.js.map +1 -0
  25. package/dist/esm/src/core/protocol-authorization.js +608 -0
  26. package/dist/esm/src/core/protocol-authorization.js.map +1 -0
  27. package/dist/esm/src/core/protocols-grant-authorization.js +66 -0
  28. package/dist/esm/src/core/protocols-grant-authorization.js.map +1 -0
  29. package/dist/esm/src/core/records-grant-authorization.js +132 -0
  30. package/dist/esm/src/core/records-grant-authorization.js.map +1 -0
  31. package/dist/esm/src/core/resumable-task-manager.js +109 -0
  32. package/dist/esm/src/core/resumable-task-manager.js.map +1 -0
  33. package/dist/esm/src/core/tenant-gate.js +20 -0
  34. package/dist/esm/src/core/tenant-gate.js.map +1 -0
  35. package/dist/esm/src/dwn.js +164 -0
  36. package/dist/esm/src/dwn.js.map +1 -0
  37. package/dist/esm/src/enums/dwn-interface-method.js +16 -0
  38. package/dist/esm/src/enums/dwn-interface-method.js.map +1 -0
  39. package/dist/esm/src/event-log/event-emitter-stream.js +60 -0
  40. package/dist/esm/src/event-log/event-emitter-stream.js.map +1 -0
  41. package/dist/esm/src/event-log/event-log-level.js +63 -0
  42. package/dist/esm/src/event-log/event-log-level.js.map +1 -0
  43. package/dist/esm/src/handlers/messages-query.js +71 -0
  44. package/dist/esm/src/handlers/messages-query.js.map +1 -0
  45. package/dist/esm/src/handlers/messages-read.js +102 -0
  46. package/dist/esm/src/handlers/messages-read.js.map +1 -0
  47. package/dist/esm/src/handlers/messages-subscribe.js +81 -0
  48. package/dist/esm/src/handlers/messages-subscribe.js.map +1 -0
  49. package/dist/esm/src/handlers/protocols-configure.js +133 -0
  50. package/dist/esm/src/handlers/protocols-configure.js.map +1 -0
  51. package/dist/esm/src/handlers/protocols-query.js +73 -0
  52. package/dist/esm/src/handlers/protocols-query.js.map +1 -0
  53. package/dist/esm/src/handlers/records-delete.js +107 -0
  54. package/dist/esm/src/handlers/records-delete.js.map +1 -0
  55. package/dist/esm/src/handlers/records-query.js +210 -0
  56. package/dist/esm/src/handlers/records-query.js.map +1 -0
  57. package/dist/esm/src/handlers/records-read.js +169 -0
  58. package/dist/esm/src/handlers/records-read.js.map +1 -0
  59. package/dist/esm/src/handlers/records-subscribe.js +172 -0
  60. package/dist/esm/src/handlers/records-subscribe.js.map +1 -0
  61. package/dist/esm/src/handlers/records-write.js +344 -0
  62. package/dist/esm/src/handlers/records-write.js.map +1 -0
  63. package/dist/esm/src/index.js +49 -0
  64. package/dist/esm/src/index.js.map +1 -0
  65. package/dist/esm/src/interfaces/messages-query.js +53 -0
  66. package/dist/esm/src/interfaces/messages-query.js.map +1 -0
  67. package/dist/esm/src/interfaces/messages-read.js +61 -0
  68. package/dist/esm/src/interfaces/messages-read.js.map +1 -0
  69. package/dist/esm/src/interfaces/messages-subscribe.js +58 -0
  70. package/dist/esm/src/interfaces/messages-subscribe.js.map +1 -0
  71. package/dist/esm/src/interfaces/protocols-configure.js +271 -0
  72. package/dist/esm/src/interfaces/protocols-configure.js.map +1 -0
  73. package/dist/esm/src/interfaces/protocols-query.js +84 -0
  74. package/dist/esm/src/interfaces/protocols-query.js.map +1 -0
  75. package/dist/esm/src/interfaces/records-delete.js +89 -0
  76. package/dist/esm/src/interfaces/records-delete.js.map +1 -0
  77. package/dist/esm/src/interfaces/records-query.js +104 -0
  78. package/dist/esm/src/interfaces/records-query.js.map +1 -0
  79. package/dist/esm/src/interfaces/records-read.js +84 -0
  80. package/dist/esm/src/interfaces/records-read.js.map +1 -0
  81. package/dist/esm/src/interfaces/records-subscribe.js +91 -0
  82. package/dist/esm/src/interfaces/records-subscribe.js.map +1 -0
  83. package/dist/esm/src/interfaces/records-write.js +795 -0
  84. package/dist/esm/src/interfaces/records-write.js.map +1 -0
  85. package/dist/esm/src/jose/algorithms/signing/ed25519.js +51 -0
  86. package/dist/esm/src/jose/algorithms/signing/ed25519.js.map +1 -0
  87. package/dist/esm/src/jose/algorithms/signing/signature-algorithms.js +20 -0
  88. package/dist/esm/src/jose/algorithms/signing/signature-algorithms.js.map +1 -0
  89. package/dist/esm/src/jose/jws/general/builder.js +47 -0
  90. package/dist/esm/src/jose/jws/general/builder.js.map +1 -0
  91. package/dist/esm/src/jose/jws/general/verifier.js +97 -0
  92. package/dist/esm/src/jose/jws/general/verifier.js.map +1 -0
  93. package/dist/esm/src/protocols/permission-grant.js +39 -0
  94. package/dist/esm/src/protocols/permission-grant.js.map +1 -0
  95. package/dist/esm/src/protocols/permission-request.js +35 -0
  96. package/dist/esm/src/protocols/permission-request.js.map +1 -0
  97. package/dist/esm/src/protocols/permissions.js +357 -0
  98. package/dist/esm/src/protocols/permissions.js.map +1 -0
  99. package/dist/esm/src/schema-validator.js +37 -0
  100. package/dist/esm/src/schema-validator.js.map +1 -0
  101. package/dist/esm/src/store/blockstore-level.js +187 -0
  102. package/dist/esm/src/store/blockstore-level.js.map +1 -0
  103. package/dist/esm/src/store/blockstore-mock.js +168 -0
  104. package/dist/esm/src/store/blockstore-mock.js.map +1 -0
  105. package/dist/esm/src/store/data-store-level.js +136 -0
  106. package/dist/esm/src/store/data-store-level.js.map +1 -0
  107. package/dist/esm/src/store/index-level.js +660 -0
  108. package/dist/esm/src/store/index-level.js.map +1 -0
  109. package/dist/esm/src/store/level-wrapper.js +305 -0
  110. package/dist/esm/src/store/level-wrapper.js.map +1 -0
  111. package/dist/esm/src/store/message-store-level.js +159 -0
  112. package/dist/esm/src/store/message-store-level.js.map +1 -0
  113. package/dist/esm/src/store/resumable-task-store-level.js +131 -0
  114. package/dist/esm/src/store/resumable-task-store-level.js.map +1 -0
  115. package/dist/esm/src/store/storage-controller.js +184 -0
  116. package/dist/esm/src/store/storage-controller.js.map +1 -0
  117. package/dist/esm/src/types/cache.js +2 -0
  118. package/dist/esm/src/types/cache.js.map +1 -0
  119. package/dist/esm/src/types/data-store.js +2 -0
  120. package/dist/esm/src/types/data-store.js.map +1 -0
  121. package/dist/esm/src/types/event-log.js +2 -0
  122. package/dist/esm/src/types/event-log.js.map +1 -0
  123. package/dist/esm/src/types/jose-types.js +2 -0
  124. package/dist/esm/src/types/jose-types.js.map +1 -0
  125. package/dist/esm/src/types/jws-types.js +2 -0
  126. package/dist/esm/src/types/jws-types.js.map +1 -0
  127. package/dist/esm/src/types/message-interface.js +2 -0
  128. package/dist/esm/src/types/message-interface.js.map +1 -0
  129. package/dist/esm/src/types/message-store.js +2 -0
  130. package/dist/esm/src/types/message-store.js.map +1 -0
  131. package/dist/esm/src/types/message-types.js +3 -0
  132. package/dist/esm/src/types/message-types.js.map +1 -0
  133. package/dist/esm/src/types/messages-types.js +2 -0
  134. package/dist/esm/src/types/messages-types.js.map +1 -0
  135. package/dist/esm/src/types/method-handler.js +2 -0
  136. package/dist/esm/src/types/method-handler.js.map +1 -0
  137. package/dist/esm/src/types/permission-types.js +6 -0
  138. package/dist/esm/src/types/permission-types.js.map +1 -0
  139. package/dist/esm/src/types/protocols-types.js +20 -0
  140. package/dist/esm/src/types/protocols-types.js.map +1 -0
  141. package/dist/esm/src/types/query-types.js +6 -0
  142. package/dist/esm/src/types/query-types.js.map +1 -0
  143. package/dist/esm/src/types/records-types.js +8 -0
  144. package/dist/esm/src/types/records-types.js.map +1 -0
  145. package/dist/esm/src/types/resumable-task-store.js +2 -0
  146. package/dist/esm/src/types/resumable-task-store.js.map +1 -0
  147. package/dist/esm/src/types/signer.js +2 -0
  148. package/dist/esm/src/types/signer.js.map +1 -0
  149. package/dist/esm/src/types/subscriptions.js +2 -0
  150. package/dist/esm/src/types/subscriptions.js.map +1 -0
  151. package/dist/esm/src/utils/abort.js +40 -0
  152. package/dist/esm/src/utils/abort.js.map +1 -0
  153. package/dist/esm/src/utils/array.js +72 -0
  154. package/dist/esm/src/utils/array.js.map +1 -0
  155. package/dist/esm/src/utils/cid.js +130 -0
  156. package/dist/esm/src/utils/cid.js.map +1 -0
  157. package/dist/esm/src/utils/data-stream.js +100 -0
  158. package/dist/esm/src/utils/data-stream.js.map +1 -0
  159. package/dist/esm/src/utils/encoder.js +45 -0
  160. package/dist/esm/src/utils/encoder.js.map +1 -0
  161. package/dist/esm/src/utils/encryption.js +128 -0
  162. package/dist/esm/src/utils/encryption.js.map +1 -0
  163. package/dist/esm/src/utils/filter.js +229 -0
  164. package/dist/esm/src/utils/filter.js.map +1 -0
  165. package/dist/esm/src/utils/hd-key.js +114 -0
  166. package/dist/esm/src/utils/hd-key.js.map +1 -0
  167. package/dist/esm/src/utils/jws.js +89 -0
  168. package/dist/esm/src/utils/jws.js.map +1 -0
  169. package/dist/esm/src/utils/memory-cache.js +41 -0
  170. package/dist/esm/src/utils/memory-cache.js.map +1 -0
  171. package/dist/esm/src/utils/messages.js +84 -0
  172. package/dist/esm/src/utils/messages.js.map +1 -0
  173. package/dist/esm/src/utils/object.js +40 -0
  174. package/dist/esm/src/utils/object.js.map +1 -0
  175. package/dist/esm/src/utils/private-key-signer.js +43 -0
  176. package/dist/esm/src/utils/private-key-signer.js.map +1 -0
  177. package/dist/esm/src/utils/protocols.js +51 -0
  178. package/dist/esm/src/utils/protocols.js.map +1 -0
  179. package/dist/esm/src/utils/records.js +454 -0
  180. package/dist/esm/src/utils/records.js.map +1 -0
  181. package/dist/esm/src/utils/secp256k1.js +166 -0
  182. package/dist/esm/src/utils/secp256k1.js.map +1 -0
  183. package/dist/esm/src/utils/secp256r1.js +120 -0
  184. package/dist/esm/src/utils/secp256r1.js.map +1 -0
  185. package/dist/esm/src/utils/string.js +16 -0
  186. package/dist/esm/src/utils/string.js.map +1 -0
  187. package/dist/esm/src/utils/time.js +85 -0
  188. package/dist/esm/src/utils/time.js.map +1 -0
  189. package/dist/esm/src/utils/url.js +62 -0
  190. package/dist/esm/src/utils/url.js.map +1 -0
  191. package/dist/esm/tests/core/auth.spec.js +22 -0
  192. package/dist/esm/tests/core/auth.spec.js.map +1 -0
  193. package/dist/esm/tests/core/message-reply.spec.js +16 -0
  194. package/dist/esm/tests/core/message-reply.spec.js.map +1 -0
  195. package/dist/esm/tests/core/message.spec.js +146 -0
  196. package/dist/esm/tests/core/message.spec.js.map +1 -0
  197. package/dist/esm/tests/core/protocol-authorization.spec.js +48 -0
  198. package/dist/esm/tests/core/protocol-authorization.spec.js.map +1 -0
  199. package/dist/esm/tests/dwn.spec.js +166 -0
  200. package/dist/esm/tests/dwn.spec.js.map +1 -0
  201. package/dist/esm/tests/event-log/event-emitter-stream.spec.js +78 -0
  202. package/dist/esm/tests/event-log/event-emitter-stream.spec.js.map +1 -0
  203. package/dist/esm/tests/event-log/event-log-level.spec.js +44 -0
  204. package/dist/esm/tests/event-log/event-log-level.spec.js.map +1 -0
  205. package/dist/esm/tests/event-log/event-log.spec.js +236 -0
  206. package/dist/esm/tests/event-log/event-log.spec.js.map +1 -0
  207. package/dist/esm/tests/event-log/event-stream.spec.js +125 -0
  208. package/dist/esm/tests/event-log/event-stream.spec.js.map +1 -0
  209. package/dist/esm/tests/features/author-delegated-grant.spec.js +1273 -0
  210. package/dist/esm/tests/features/author-delegated-grant.spec.js.map +1 -0
  211. package/dist/esm/tests/features/owner-delegated-grant.spec.js +584 -0
  212. package/dist/esm/tests/features/owner-delegated-grant.spec.js.map +1 -0
  213. package/dist/esm/tests/features/owner-signature.spec.js +192 -0
  214. package/dist/esm/tests/features/owner-signature.spec.js.map +1 -0
  215. package/dist/esm/tests/features/permissions.spec.js +815 -0
  216. package/dist/esm/tests/features/permissions.spec.js.map +1 -0
  217. package/dist/esm/tests/features/protocol-create-action.spec.js +248 -0
  218. package/dist/esm/tests/features/protocol-create-action.spec.js.map +1 -0
  219. package/dist/esm/tests/features/protocol-delete-action.spec.js +492 -0
  220. package/dist/esm/tests/features/protocol-delete-action.spec.js.map +1 -0
  221. package/dist/esm/tests/features/protocol-update-action.spec.js +572 -0
  222. package/dist/esm/tests/features/protocol-update-action.spec.js.map +1 -0
  223. package/dist/esm/tests/features/records-prune.spec.js +812 -0
  224. package/dist/esm/tests/features/records-prune.spec.js.map +1 -0
  225. package/dist/esm/tests/features/records-tags.spec.js +2516 -0
  226. package/dist/esm/tests/features/records-tags.spec.js.map +1 -0
  227. package/dist/esm/tests/features/resumable-tasks.spec.js +349 -0
  228. package/dist/esm/tests/features/resumable-tasks.spec.js.map +1 -0
  229. package/dist/esm/tests/handlers/messages-query.spec.js +349 -0
  230. package/dist/esm/tests/handlers/messages-query.spec.js.map +1 -0
  231. package/dist/esm/tests/handlers/messages-read.spec.js +647 -0
  232. package/dist/esm/tests/handlers/messages-read.spec.js.map +1 -0
  233. package/dist/esm/tests/handlers/messages-subscribe.spec.js +432 -0
  234. package/dist/esm/tests/handlers/messages-subscribe.spec.js.map +1 -0
  235. package/dist/esm/tests/handlers/protocols-configure.spec.js +608 -0
  236. package/dist/esm/tests/handlers/protocols-configure.spec.js.map +1 -0
  237. package/dist/esm/tests/handlers/protocols-query.spec.js +454 -0
  238. package/dist/esm/tests/handlers/protocols-query.spec.js.map +1 -0
  239. package/dist/esm/tests/handlers/records-delete.spec.js +662 -0
  240. package/dist/esm/tests/handlers/records-delete.spec.js.map +1 -0
  241. package/dist/esm/tests/handlers/records-query.spec.js +2695 -0
  242. package/dist/esm/tests/handlers/records-query.spec.js.map +1 -0
  243. package/dist/esm/tests/handlers/records-read.spec.js +1724 -0
  244. package/dist/esm/tests/handlers/records-read.spec.js.map +1 -0
  245. package/dist/esm/tests/handlers/records-subscribe.spec.js +684 -0
  246. package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -0
  247. package/dist/esm/tests/handlers/records-write.spec.js +3637 -0
  248. package/dist/esm/tests/handlers/records-write.spec.js.map +1 -0
  249. package/dist/esm/tests/interfaces/messages-get.spec.js +78 -0
  250. package/dist/esm/tests/interfaces/messages-get.spec.js.map +1 -0
  251. package/dist/esm/tests/interfaces/messages-subscribe.spec.js +30 -0
  252. package/dist/esm/tests/interfaces/messages-subscribe.spec.js.map +1 -0
  253. package/dist/esm/tests/interfaces/messagess-query.spec.js +127 -0
  254. package/dist/esm/tests/interfaces/messagess-query.spec.js.map +1 -0
  255. package/dist/esm/tests/interfaces/protocols-configure.spec.js +489 -0
  256. package/dist/esm/tests/interfaces/protocols-configure.spec.js.map +1 -0
  257. package/dist/esm/tests/interfaces/protocols-query.spec.js +46 -0
  258. package/dist/esm/tests/interfaces/protocols-query.spec.js.map +1 -0
  259. package/dist/esm/tests/interfaces/records-delete.spec.js +39 -0
  260. package/dist/esm/tests/interfaces/records-delete.spec.js.map +1 -0
  261. package/dist/esm/tests/interfaces/records-query.spec.js +85 -0
  262. package/dist/esm/tests/interfaces/records-query.spec.js.map +1 -0
  263. package/dist/esm/tests/interfaces/records-read.spec.js +62 -0
  264. package/dist/esm/tests/interfaces/records-read.spec.js.map +1 -0
  265. package/dist/esm/tests/interfaces/records-subscribe.spec.js +72 -0
  266. package/dist/esm/tests/interfaces/records-subscribe.spec.js.map +1 -0
  267. package/dist/esm/tests/interfaces/records-write.spec.js +423 -0
  268. package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -0
  269. package/dist/esm/tests/jose/jws/general.spec.js +243 -0
  270. package/dist/esm/tests/jose/jws/general.spec.js.map +1 -0
  271. package/dist/esm/tests/protocols/permission-request.spec.js +40 -0
  272. package/dist/esm/tests/protocols/permission-request.spec.js.map +1 -0
  273. package/dist/esm/tests/protocols/permissions.spec.js +123 -0
  274. package/dist/esm/tests/protocols/permissions.spec.js.map +1 -0
  275. package/dist/esm/tests/scenarios/aggregator.spec.js +670 -0
  276. package/dist/esm/tests/scenarios/aggregator.spec.js.map +1 -0
  277. package/dist/esm/tests/scenarios/deleted-record.spec.js +102 -0
  278. package/dist/esm/tests/scenarios/deleted-record.spec.js.map +1 -0
  279. package/dist/esm/tests/scenarios/end-to-end-tests.spec.js +220 -0
  280. package/dist/esm/tests/scenarios/end-to-end-tests.spec.js.map +1 -0
  281. package/dist/esm/tests/scenarios/messages-query.spec.js +395 -0
  282. package/dist/esm/tests/scenarios/messages-query.spec.js.map +1 -0
  283. package/dist/esm/tests/scenarios/nested-roles.spec.js +300 -0
  284. package/dist/esm/tests/scenarios/nested-roles.spec.js.map +1 -0
  285. package/dist/esm/tests/scenarios/subscriptions.spec.js +886 -0
  286. package/dist/esm/tests/scenarios/subscriptions.spec.js.map +1 -0
  287. package/dist/esm/tests/store/blockstore-mock.spec.js +192 -0
  288. package/dist/esm/tests/store/blockstore-mock.spec.js.map +1 -0
  289. package/dist/esm/tests/store/data-store-level.spec.js +146 -0
  290. package/dist/esm/tests/store/data-store-level.spec.js.map +1 -0
  291. package/dist/esm/tests/store/index-level.spec.js +1208 -0
  292. package/dist/esm/tests/store/index-level.spec.js.map +1 -0
  293. package/dist/esm/tests/store/message-store-level.spec.js +48 -0
  294. package/dist/esm/tests/store/message-store-level.spec.js.map +1 -0
  295. package/dist/esm/tests/store/message-store.spec.js +404 -0
  296. package/dist/esm/tests/store/message-store.spec.js.map +1 -0
  297. package/dist/esm/tests/store-dependent-tests.spec.js +5 -0
  298. package/dist/esm/tests/store-dependent-tests.spec.js.map +1 -0
  299. package/dist/esm/tests/test-event-stream.js +25 -0
  300. package/dist/esm/tests/test-event-stream.js.map +1 -0
  301. package/dist/esm/tests/test-stores.js +45 -0
  302. package/dist/esm/tests/test-stores.js.map +1 -0
  303. package/dist/esm/tests/test-suite.js +88 -0
  304. package/dist/esm/tests/test-suite.js.map +1 -0
  305. package/dist/esm/tests/utils/cid.spec.js +80 -0
  306. package/dist/esm/tests/utils/cid.spec.js.map +1 -0
  307. package/dist/esm/tests/utils/data-stream.spec.js +27 -0
  308. package/dist/esm/tests/utils/data-stream.spec.js.map +1 -0
  309. package/dist/esm/tests/utils/encryption.spec.js +148 -0
  310. package/dist/esm/tests/utils/encryption.spec.js.map +1 -0
  311. package/dist/esm/tests/utils/filters.spec.js +295 -0
  312. package/dist/esm/tests/utils/filters.spec.js.map +1 -0
  313. package/dist/esm/tests/utils/hd-key.spec.js +35 -0
  314. package/dist/esm/tests/utils/hd-key.spec.js.map +1 -0
  315. package/dist/esm/tests/utils/jws.spec.js +8 -0
  316. package/dist/esm/tests/utils/jws.spec.js.map +1 -0
  317. package/dist/esm/tests/utils/memory-cache.spec.js +35 -0
  318. package/dist/esm/tests/utils/memory-cache.spec.js.map +1 -0
  319. package/dist/esm/tests/utils/messages.spec.js +101 -0
  320. package/dist/esm/tests/utils/messages.spec.js.map +1 -0
  321. package/dist/esm/tests/utils/object.spec.js +36 -0
  322. package/dist/esm/tests/utils/object.spec.js.map +1 -0
  323. package/dist/esm/tests/utils/poller.js +49 -0
  324. package/dist/esm/tests/utils/poller.js.map +1 -0
  325. package/dist/esm/tests/utils/private-key-signer.spec.js +44 -0
  326. package/dist/esm/tests/utils/private-key-signer.spec.js.map +1 -0
  327. package/dist/esm/tests/utils/records.spec.js +53 -0
  328. package/dist/esm/tests/utils/records.spec.js.map +1 -0
  329. package/dist/esm/tests/utils/secp256k1.spec.js +50 -0
  330. package/dist/esm/tests/utils/secp256k1.spec.js.map +1 -0
  331. package/dist/esm/tests/utils/secp256r1.spec.js +56 -0
  332. package/dist/esm/tests/utils/secp256r1.spec.js.map +1 -0
  333. package/dist/esm/tests/utils/test-data-generator.js +643 -0
  334. package/dist/esm/tests/utils/test-data-generator.js.map +1 -0
  335. package/dist/esm/tests/utils/test-stub-generator.js +39 -0
  336. package/dist/esm/tests/utils/test-stub-generator.js.map +1 -0
  337. package/dist/esm/tests/utils/time.spec.js +64 -0
  338. package/dist/esm/tests/utils/time.spec.js.map +1 -0
  339. package/dist/esm/tests/utils/url.spec.js +43 -0
  340. package/dist/esm/tests/utils/url.spec.js.map +1 -0
  341. package/dist/esm/tests/validation/json-schemas/definitions.spec.js +33 -0
  342. package/dist/esm/tests/validation/json-schemas/definitions.spec.js.map +1 -0
  343. package/dist/esm/tests/validation/json-schemas/jwk/general-jwk.spec.js +50 -0
  344. package/dist/esm/tests/validation/json-schemas/jwk/general-jwk.spec.js.map +1 -0
  345. package/dist/esm/tests/validation/json-schemas/jwk/public-jwk.spec.js +36 -0
  346. package/dist/esm/tests/validation/json-schemas/jwk/public-jwk.spec.js.map +1 -0
  347. package/dist/esm/tests/validation/json-schemas/jwk-verification-method.spec.js +82 -0
  348. package/dist/esm/tests/validation/json-schemas/jwk-verification-method.spec.js.map +1 -0
  349. package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js +75 -0
  350. package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js.map +1 -0
  351. package/dist/esm/tests/validation/json-schemas/records/records-query.spec.js +148 -0
  352. package/dist/esm/tests/validation/json-schemas/records/records-query.spec.js.map +1 -0
  353. package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js +421 -0
  354. package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js.map +1 -0
  355. package/dist/esm/tests/vectors/protocol-definitions/anyone-collaborate.json +21 -0
  356. package/dist/esm/tests/vectors/protocol-definitions/author-can.json +33 -0
  357. package/dist/esm/tests/vectors/protocol-definitions/chat.json +70 -0
  358. package/dist/esm/tests/vectors/protocol-definitions/credential-issuance.json +41 -0
  359. package/dist/esm/tests/vectors/protocol-definitions/dex.json +58 -0
  360. package/dist/esm/tests/vectors/protocol-definitions/email.json +62 -0
  361. package/dist/esm/tests/vectors/protocol-definitions/free-for-all.json +45 -0
  362. package/dist/esm/tests/vectors/protocol-definitions/friend-role.json +48 -0
  363. package/dist/esm/tests/vectors/protocol-definitions/message.json +37 -0
  364. package/dist/esm/tests/vectors/protocol-definitions/minimal.json +10 -0
  365. package/dist/esm/tests/vectors/protocol-definitions/nested.json +31 -0
  366. package/dist/esm/tests/vectors/protocol-definitions/private-protocol.json +15 -0
  367. package/dist/esm/tests/vectors/protocol-definitions/recipient-can.json +33 -0
  368. package/dist/esm/tests/vectors/protocol-definitions/slack.json +242 -0
  369. package/dist/esm/tests/vectors/protocol-definitions/social-media.json +106 -0
  370. package/dist/esm/tests/vectors/protocol-definitions/thread-role.json +70 -0
  371. package/dist/types/generated/precompiled-validators.d.ts +597 -0
  372. package/dist/types/generated/precompiled-validators.d.ts.map +1 -0
  373. package/dist/types/src/core/abstract-message.d.ts +25 -0
  374. package/dist/types/src/core/abstract-message.d.ts.map +1 -0
  375. package/dist/types/src/core/auth.d.ts +9 -0
  376. package/dist/types/src/core/auth.d.ts.map +1 -0
  377. package/dist/types/src/core/dwn-constant.d.ts +10 -0
  378. package/dist/types/src/core/dwn-constant.d.ts.map +1 -0
  379. package/dist/types/src/core/dwn-error.d.ts +164 -0
  380. package/dist/types/src/core/dwn-error.d.ts.map +1 -0
  381. package/dist/types/src/core/grant-authorization.d.ts +43 -0
  382. package/dist/types/src/core/grant-authorization.d.ts.map +1 -0
  383. package/dist/types/src/core/message-reply.d.ts +32 -0
  384. package/dist/types/src/core/message-reply.d.ts.map +1 -0
  385. package/dist/types/src/core/message.d.ts +94 -0
  386. package/dist/types/src/core/message.d.ts.map +1 -0
  387. package/dist/types/src/core/messages-grant-authorization.d.ts +34 -0
  388. package/dist/types/src/core/messages-grant-authorization.d.ts.map +1 -0
  389. package/dist/types/src/core/protocol-authorization.d.ts +103 -0
  390. package/dist/types/src/core/protocol-authorization.d.ts.map +1 -0
  391. package/dist/types/src/core/protocols-grant-authorization.d.ts +31 -0
  392. package/dist/types/src/core/protocols-grant-authorization.d.ts.map +1 -0
  393. package/dist/types/src/core/records-grant-authorization.d.ts +60 -0
  394. package/dist/types/src/core/records-grant-authorization.d.ts.map +1 -0
  395. package/dist/types/src/core/resumable-task-manager.d.ts +43 -0
  396. package/dist/types/src/core/resumable-task-manager.d.ts.map +1 -0
  397. package/dist/types/src/core/tenant-gate.d.ts +29 -0
  398. package/dist/types/src/core/tenant-gate.d.ts.map +1 -0
  399. package/dist/types/src/dwn.d.ts +85 -0
  400. package/dist/types/src/dwn.d.ts.map +1 -0
  401. package/dist/types/src/enums/dwn-interface-method.d.ts +14 -0
  402. package/dist/types/src/enums/dwn-interface-method.d.ts.map +1 -0
  403. package/dist/types/src/event-log/event-emitter-stream.d.ts +23 -0
  404. package/dist/types/src/event-log/event-emitter-stream.d.ts.map +1 -0
  405. package/dist/types/src/event-log/event-log-level.d.ts +35 -0
  406. package/dist/types/src/event-log/event-log-level.d.ts.map +1 -0
  407. package/dist/types/src/handlers/messages-query.d.ts +17 -0
  408. package/dist/types/src/handlers/messages-query.d.ts.map +1 -0
  409. package/dist/types/src/handlers/messages-read.d.ts +22 -0
  410. package/dist/types/src/handlers/messages-read.d.ts.map +1 -0
  411. package/dist/types/src/handlers/messages-subscribe.d.ts +18 -0
  412. package/dist/types/src/handlers/messages-subscribe.d.ts.map +1 -0
  413. package/dist/types/src/handlers/protocols-configure.d.ts +24 -0
  414. package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -0
  415. package/dist/types/src/handlers/protocols-query.d.ts +20 -0
  416. package/dist/types/src/handlers/protocols-query.d.ts.map +1 -0
  417. package/dist/types/src/handlers/records-delete.d.ts +23 -0
  418. package/dist/types/src/handlers/records-delete.d.ts.map +1 -0
  419. package/dist/types/src/handlers/records-query.d.ts +70 -0
  420. package/dist/types/src/handlers/records-query.d.ts.map +1 -0
  421. package/dist/types/src/handlers/records-read.d.ts +20 -0
  422. package/dist/types/src/handlers/records-read.d.ts.map +1 -0
  423. package/dist/types/src/handlers/records-subscribe.d.ts +62 -0
  424. package/dist/types/src/handlers/records-subscribe.d.ts.map +1 -0
  425. package/dist/types/src/handlers/records-write.d.ts +51 -0
  426. package/dist/types/src/handlers/records-write.d.ts.map +1 -0
  427. package/dist/types/src/index.d.ts +63 -0
  428. package/dist/types/src/index.d.ts.map +1 -0
  429. package/dist/types/src/interfaces/messages-query.d.ts +16 -0
  430. package/dist/types/src/interfaces/messages-query.d.ts.map +1 -0
  431. package/dist/types/src/interfaces/messages-read.d.ts +20 -0
  432. package/dist/types/src/interfaces/messages-read.d.ts.map +1 -0
  433. package/dist/types/src/interfaces/messages-subscribe.d.ts +20 -0
  434. package/dist/types/src/interfaces/messages-subscribe.d.ts.map +1 -0
  435. package/dist/types/src/interfaces/protocols-configure.d.ts +40 -0
  436. package/dist/types/src/interfaces/protocols-configure.d.ts.map +1 -0
  437. package/dist/types/src/interfaces/protocols-query.d.ts +17 -0
  438. package/dist/types/src/interfaces/protocols-query.d.ts.map +1 -0
  439. package/dist/types/src/interfaces/records-delete.d.ts +34 -0
  440. package/dist/types/src/interfaces/records-delete.d.ts.map +1 -0
  441. package/dist/types/src/interfaces/records-query.d.ts +31 -0
  442. package/dist/types/src/interfaces/records-query.d.ts.map +1 -0
  443. package/dist/types/src/interfaces/records-read.d.ts +36 -0
  444. package/dist/types/src/interfaces/records-read.d.ts.map +1 -0
  445. package/dist/types/src/interfaces/records-subscribe.d.ts +27 -0
  446. package/dist/types/src/interfaces/records-subscribe.d.ts.map +1 -0
  447. package/dist/types/src/interfaces/records-write.d.ts +309 -0
  448. package/dist/types/src/interfaces/records-write.d.ts.map +1 -0
  449. package/dist/types/src/jose/algorithms/signing/ed25519.d.ts +3 -0
  450. package/dist/types/src/jose/algorithms/signing/ed25519.d.ts.map +1 -0
  451. package/dist/types/src/jose/algorithms/signing/signature-algorithms.d.ts +3 -0
  452. package/dist/types/src/jose/algorithms/signing/signature-algorithms.d.ts.map +1 -0
  453. package/dist/types/src/jose/jws/general/builder.d.ts +10 -0
  454. package/dist/types/src/jose/jws/general/builder.d.ts.map +1 -0
  455. package/dist/types/src/jose/jws/general/verifier.d.ts +32 -0
  456. package/dist/types/src/jose/jws/general/verifier.d.ts.map +1 -0
  457. package/dist/types/src/protocols/permission-grant.d.ts +50 -0
  458. package/dist/types/src/protocols/permission-grant.d.ts.map +1 -0
  459. package/dist/types/src/protocols/permission-request.d.ts +35 -0
  460. package/dist/types/src/protocols/permission-request.d.ts.map +1 -0
  461. package/dist/types/src/protocols/permissions.d.ts +150 -0
  462. package/dist/types/src/protocols/permissions.d.ts.map +1 -0
  463. package/dist/types/src/schema-validator.d.ts +8 -0
  464. package/dist/types/src/schema-validator.d.ts.map +1 -0
  465. package/dist/types/src/store/blockstore-level.d.ts +34 -0
  466. package/dist/types/src/store/blockstore-level.d.ts.map +1 -0
  467. package/dist/types/src/store/blockstore-mock.d.ts +27 -0
  468. package/dist/types/src/store/blockstore-mock.d.ts.map +1 -0
  469. package/dist/types/src/store/data-store-level.d.ts +34 -0
  470. package/dist/types/src/store/data-store-level.d.ts.map +1 -0
  471. package/dist/types/src/store/index-level.d.ts +171 -0
  472. package/dist/types/src/store/index-level.d.ts.map +1 -0
  473. package/dist/types/src/store/level-wrapper.d.ts +48 -0
  474. package/dist/types/src/store/level-wrapper.d.ts.map +1 -0
  475. package/dist/types/src/store/message-store-level.d.ts +46 -0
  476. package/dist/types/src/store/message-store-level.d.ts.map +1 -0
  477. package/dist/types/src/store/resumable-task-store-level.d.ts +28 -0
  478. package/dist/types/src/store/resumable-task-store-level.d.ts.map +1 -0
  479. package/dist/types/src/store/storage-controller.d.ts +46 -0
  480. package/dist/types/src/store/storage-controller.d.ts.map +1 -0
  481. package/dist/types/src/types/cache.d.ts +16 -0
  482. package/dist/types/src/types/cache.d.ts.map +1 -0
  483. package/dist/types/src/types/data-store.d.ts +57 -0
  484. package/dist/types/src/types/data-store.d.ts.map +1 -0
  485. package/dist/types/src/types/event-log.d.ts +52 -0
  486. package/dist/types/src/types/event-log.d.ts.map +1 -0
  487. package/dist/types/src/types/jose-types.d.ts +75 -0
  488. package/dist/types/src/types/jose-types.d.ts.map +1 -0
  489. package/dist/types/src/types/jws-types.d.ts +27 -0
  490. package/dist/types/src/types/jws-types.d.ts.map +1 -0
  491. package/dist/types/src/types/message-interface.d.ts +27 -0
  492. package/dist/types/src/types/message-interface.d.ts.map +1 -0
  493. package/dist/types/src/types/message-store.d.ts +42 -0
  494. package/dist/types/src/types/message-store.d.ts.map +1 -0
  495. package/dist/types/src/types/message-types.d.ts +116 -0
  496. package/dist/types/src/types/message-types.d.ts.map +1 -0
  497. package/dist/types/src/types/messages-types.d.ts +65 -0
  498. package/dist/types/src/types/messages-types.d.ts.map +1 -0
  499. package/dist/types/src/types/method-handler.d.ts +19 -0
  500. package/dist/types/src/types/method-handler.d.ts.map +1 -0
  501. package/dist/types/src/types/permission-types.d.ts +93 -0
  502. package/dist/types/src/types/permission-types.d.ts.map +1 -0
  503. package/dist/types/src/types/protocols-types.d.ts +154 -0
  504. package/dist/types/src/types/protocols-types.d.ts.map +1 -0
  505. package/dist/types/src/types/query-types.d.ts +66 -0
  506. package/dist/types/src/types/query-types.d.ts.map +1 -0
  507. package/dist/types/src/types/records-types.d.ts +230 -0
  508. package/dist/types/src/types/records-types.d.ts.map +1 -0
  509. package/dist/types/src/types/resumable-task-store.d.ts +89 -0
  510. package/dist/types/src/types/resumable-task-store.d.ts.map +1 -0
  511. package/dist/types/src/types/signer.d.ts +26 -0
  512. package/dist/types/src/types/signer.d.ts.map +1 -0
  513. package/dist/types/src/types/subscriptions.d.ts +30 -0
  514. package/dist/types/src/types/subscriptions.d.ts.map +1 -0
  515. package/dist/types/src/utils/abort.d.ts +5 -0
  516. package/dist/types/src/utils/abort.d.ts.map +1 -0
  517. package/dist/types/src/utils/array.d.ts +18 -0
  518. package/dist/types/src/utils/array.d.ts.map +1 -0
  519. package/dist/types/src/utils/cid.d.ts +30 -0
  520. package/dist/types/src/utils/cid.d.ts.map +1 -0
  521. package/dist/types/src/utils/data-stream.d.ts +31 -0
  522. package/dist/types/src/utils/data-stream.d.ts.map +1 -0
  523. package/dist/types/src/utils/encoder.d.ts +14 -0
  524. package/dist/types/src/utils/encoder.d.ts.map +1 -0
  525. package/dist/types/src/utils/encryption.d.ts +44 -0
  526. package/dist/types/src/utils/encryption.d.ts.map +1 -0
  527. package/dist/types/src/utils/filter.d.ts +60 -0
  528. package/dist/types/src/utils/filter.d.ts.map +1 -0
  529. package/dist/types/src/utils/hd-key.d.ts +54 -0
  530. package/dist/types/src/utils/hd-key.d.ts.map +1 -0
  531. package/dist/types/src/utils/jws.d.ts +39 -0
  532. package/dist/types/src/utils/jws.d.ts.map +1 -0
  533. package/dist/types/src/utils/memory-cache.d.ts +15 -0
  534. package/dist/types/src/utils/memory-cache.d.ts.map +1 -0
  535. package/dist/types/src/utils/messages.d.ts +27 -0
  536. package/dist/types/src/utils/messages.d.ts.map +1 -0
  537. package/dist/types/src/utils/object.d.ts +13 -0
  538. package/dist/types/src/utils/object.d.ts.map +1 -0
  539. package/dist/types/src/utils/private-key-signer.d.ts +34 -0
  540. package/dist/types/src/utils/private-key-signer.d.ts.map +1 -0
  541. package/dist/types/src/utils/protocols.d.ts +14 -0
  542. package/dist/types/src/utils/protocols.d.ts.map +1 -0
  543. package/dist/types/src/utils/records.d.ts +122 -0
  544. package/dist/types/src/utils/records.d.ts.map +1 -0
  545. package/dist/types/src/utils/secp256k1.d.ts +59 -0
  546. package/dist/types/src/utils/secp256k1.d.ts.map +1 -0
  547. package/dist/types/src/utils/secp256r1.d.ts +39 -0
  548. package/dist/types/src/utils/secp256r1.d.ts.map +1 -0
  549. package/dist/types/src/utils/string.d.ts +6 -0
  550. package/dist/types/src/utils/string.d.ts.map +1 -0
  551. package/dist/types/src/utils/time.d.ts +50 -0
  552. package/dist/types/src/utils/time.d.ts.map +1 -0
  553. package/dist/types/src/utils/url.d.ts +5 -0
  554. package/dist/types/src/utils/url.d.ts.map +1 -0
  555. package/dist/types/tests/core/auth.spec.d.ts +2 -0
  556. package/dist/types/tests/core/auth.spec.d.ts.map +1 -0
  557. package/dist/types/tests/core/message-reply.spec.d.ts +2 -0
  558. package/dist/types/tests/core/message-reply.spec.d.ts.map +1 -0
  559. package/dist/types/tests/core/message.spec.d.ts +2 -0
  560. package/dist/types/tests/core/message.spec.d.ts.map +1 -0
  561. package/dist/types/tests/core/protocol-authorization.spec.d.ts +2 -0
  562. package/dist/types/tests/core/protocol-authorization.spec.d.ts.map +1 -0
  563. package/dist/types/tests/dwn.spec.d.ts +2 -0
  564. package/dist/types/tests/dwn.spec.d.ts.map +1 -0
  565. package/dist/types/tests/event-log/event-emitter-stream.spec.d.ts +2 -0
  566. package/dist/types/tests/event-log/event-emitter-stream.spec.d.ts.map +1 -0
  567. package/dist/types/tests/event-log/event-log-level.spec.d.ts +2 -0
  568. package/dist/types/tests/event-log/event-log-level.spec.d.ts.map +1 -0
  569. package/dist/types/tests/event-log/event-log.spec.d.ts +2 -0
  570. package/dist/types/tests/event-log/event-log.spec.d.ts.map +1 -0
  571. package/dist/types/tests/event-log/event-stream.spec.d.ts +2 -0
  572. package/dist/types/tests/event-log/event-stream.spec.d.ts.map +1 -0
  573. package/dist/types/tests/features/author-delegated-grant.spec.d.ts +2 -0
  574. package/dist/types/tests/features/author-delegated-grant.spec.d.ts.map +1 -0
  575. package/dist/types/tests/features/owner-delegated-grant.spec.d.ts +2 -0
  576. package/dist/types/tests/features/owner-delegated-grant.spec.d.ts.map +1 -0
  577. package/dist/types/tests/features/owner-signature.spec.d.ts +2 -0
  578. package/dist/types/tests/features/owner-signature.spec.d.ts.map +1 -0
  579. package/dist/types/tests/features/permissions.spec.d.ts +2 -0
  580. package/dist/types/tests/features/permissions.spec.d.ts.map +1 -0
  581. package/dist/types/tests/features/protocol-create-action.spec.d.ts +2 -0
  582. package/dist/types/tests/features/protocol-create-action.spec.d.ts.map +1 -0
  583. package/dist/types/tests/features/protocol-delete-action.spec.d.ts +2 -0
  584. package/dist/types/tests/features/protocol-delete-action.spec.d.ts.map +1 -0
  585. package/dist/types/tests/features/protocol-update-action.spec.d.ts +2 -0
  586. package/dist/types/tests/features/protocol-update-action.spec.d.ts.map +1 -0
  587. package/dist/types/tests/features/records-prune.spec.d.ts +2 -0
  588. package/dist/types/tests/features/records-prune.spec.d.ts.map +1 -0
  589. package/dist/types/tests/features/records-tags.spec.d.ts +2 -0
  590. package/dist/types/tests/features/records-tags.spec.d.ts.map +1 -0
  591. package/dist/types/tests/features/resumable-tasks.spec.d.ts +2 -0
  592. package/dist/types/tests/features/resumable-tasks.spec.d.ts.map +1 -0
  593. package/dist/types/tests/handlers/messages-query.spec.d.ts +2 -0
  594. package/dist/types/tests/handlers/messages-query.spec.d.ts.map +1 -0
  595. package/dist/types/tests/handlers/messages-read.spec.d.ts +2 -0
  596. package/dist/types/tests/handlers/messages-read.spec.d.ts.map +1 -0
  597. package/dist/types/tests/handlers/messages-subscribe.spec.d.ts +2 -0
  598. package/dist/types/tests/handlers/messages-subscribe.spec.d.ts.map +1 -0
  599. package/dist/types/tests/handlers/protocols-configure.spec.d.ts +2 -0
  600. package/dist/types/tests/handlers/protocols-configure.spec.d.ts.map +1 -0
  601. package/dist/types/tests/handlers/protocols-query.spec.d.ts +2 -0
  602. package/dist/types/tests/handlers/protocols-query.spec.d.ts.map +1 -0
  603. package/dist/types/tests/handlers/records-delete.spec.d.ts +2 -0
  604. package/dist/types/tests/handlers/records-delete.spec.d.ts.map +1 -0
  605. package/dist/types/tests/handlers/records-query.spec.d.ts +2 -0
  606. package/dist/types/tests/handlers/records-query.spec.d.ts.map +1 -0
  607. package/dist/types/tests/handlers/records-read.spec.d.ts +2 -0
  608. package/dist/types/tests/handlers/records-read.spec.d.ts.map +1 -0
  609. package/dist/types/tests/handlers/records-subscribe.spec.d.ts +2 -0
  610. package/dist/types/tests/handlers/records-subscribe.spec.d.ts.map +1 -0
  611. package/dist/types/tests/handlers/records-write.spec.d.ts +2 -0
  612. package/dist/types/tests/handlers/records-write.spec.d.ts.map +1 -0
  613. package/dist/types/tests/interfaces/messages-get.spec.d.ts +2 -0
  614. package/dist/types/tests/interfaces/messages-get.spec.d.ts.map +1 -0
  615. package/dist/types/tests/interfaces/messages-subscribe.spec.d.ts +2 -0
  616. package/dist/types/tests/interfaces/messages-subscribe.spec.d.ts.map +1 -0
  617. package/dist/types/tests/interfaces/messagess-query.spec.d.ts +2 -0
  618. package/dist/types/tests/interfaces/messagess-query.spec.d.ts.map +1 -0
  619. package/dist/types/tests/interfaces/protocols-configure.spec.d.ts +2 -0
  620. package/dist/types/tests/interfaces/protocols-configure.spec.d.ts.map +1 -0
  621. package/dist/types/tests/interfaces/protocols-query.spec.d.ts +2 -0
  622. package/dist/types/tests/interfaces/protocols-query.spec.d.ts.map +1 -0
  623. package/dist/types/tests/interfaces/records-delete.spec.d.ts +2 -0
  624. package/dist/types/tests/interfaces/records-delete.spec.d.ts.map +1 -0
  625. package/dist/types/tests/interfaces/records-query.spec.d.ts +2 -0
  626. package/dist/types/tests/interfaces/records-query.spec.d.ts.map +1 -0
  627. package/dist/types/tests/interfaces/records-read.spec.d.ts +2 -0
  628. package/dist/types/tests/interfaces/records-read.spec.d.ts.map +1 -0
  629. package/dist/types/tests/interfaces/records-subscribe.spec.d.ts +2 -0
  630. package/dist/types/tests/interfaces/records-subscribe.spec.d.ts.map +1 -0
  631. package/dist/types/tests/interfaces/records-write.spec.d.ts +2 -0
  632. package/dist/types/tests/interfaces/records-write.spec.d.ts.map +1 -0
  633. package/dist/types/tests/jose/jws/general.spec.d.ts +2 -0
  634. package/dist/types/tests/jose/jws/general.spec.d.ts.map +1 -0
  635. package/dist/types/tests/protocols/permission-request.spec.d.ts +2 -0
  636. package/dist/types/tests/protocols/permission-request.spec.d.ts.map +1 -0
  637. package/dist/types/tests/protocols/permissions.spec.d.ts +2 -0
  638. package/dist/types/tests/protocols/permissions.spec.d.ts.map +1 -0
  639. package/dist/types/tests/scenarios/aggregator.spec.d.ts +2 -0
  640. package/dist/types/tests/scenarios/aggregator.spec.d.ts.map +1 -0
  641. package/dist/types/tests/scenarios/deleted-record.spec.d.ts +2 -0
  642. package/dist/types/tests/scenarios/deleted-record.spec.d.ts.map +1 -0
  643. package/dist/types/tests/scenarios/end-to-end-tests.spec.d.ts +2 -0
  644. package/dist/types/tests/scenarios/end-to-end-tests.spec.d.ts.map +1 -0
  645. package/dist/types/tests/scenarios/messages-query.spec.d.ts +2 -0
  646. package/dist/types/tests/scenarios/messages-query.spec.d.ts.map +1 -0
  647. package/dist/types/tests/scenarios/nested-roles.spec.d.ts +2 -0
  648. package/dist/types/tests/scenarios/nested-roles.spec.d.ts.map +1 -0
  649. package/dist/types/tests/scenarios/subscriptions.spec.d.ts +2 -0
  650. package/dist/types/tests/scenarios/subscriptions.spec.d.ts.map +1 -0
  651. package/dist/types/tests/store/blockstore-mock.spec.d.ts +2 -0
  652. package/dist/types/tests/store/blockstore-mock.spec.d.ts.map +1 -0
  653. package/dist/types/tests/store/data-store-level.spec.d.ts +2 -0
  654. package/dist/types/tests/store/data-store-level.spec.d.ts.map +1 -0
  655. package/dist/types/tests/store/index-level.spec.d.ts +2 -0
  656. package/dist/types/tests/store/index-level.spec.d.ts.map +1 -0
  657. package/dist/types/tests/store/message-store-level.spec.d.ts +2 -0
  658. package/dist/types/tests/store/message-store-level.spec.d.ts.map +1 -0
  659. package/dist/types/tests/store/message-store.spec.d.ts +2 -0
  660. package/dist/types/tests/store/message-store.spec.d.ts.map +1 -0
  661. package/dist/types/tests/store-dependent-tests.spec.d.ts +2 -0
  662. package/dist/types/tests/store-dependent-tests.spec.d.ts.map +1 -0
  663. package/dist/types/tests/test-event-stream.d.ts +22 -0
  664. package/dist/types/tests/test-event-stream.d.ts.map +1 -0
  665. package/dist/types/tests/test-stores.d.ts +33 -0
  666. package/dist/types/tests/test-stores.d.ts.map +1 -0
  667. package/dist/types/tests/test-suite.d.ts +18 -0
  668. package/dist/types/tests/test-suite.d.ts.map +1 -0
  669. package/dist/types/tests/utils/cid.spec.d.ts +2 -0
  670. package/dist/types/tests/utils/cid.spec.d.ts.map +1 -0
  671. package/dist/types/tests/utils/data-stream.spec.d.ts +2 -0
  672. package/dist/types/tests/utils/data-stream.spec.d.ts.map +1 -0
  673. package/dist/types/tests/utils/encryption.spec.d.ts +2 -0
  674. package/dist/types/tests/utils/encryption.spec.d.ts.map +1 -0
  675. package/dist/types/tests/utils/filters.spec.d.ts +2 -0
  676. package/dist/types/tests/utils/filters.spec.d.ts.map +1 -0
  677. package/dist/types/tests/utils/hd-key.spec.d.ts +2 -0
  678. package/dist/types/tests/utils/hd-key.spec.d.ts.map +1 -0
  679. package/dist/types/tests/utils/jws.spec.d.ts +2 -0
  680. package/dist/types/tests/utils/jws.spec.d.ts.map +1 -0
  681. package/dist/types/tests/utils/memory-cache.spec.d.ts +2 -0
  682. package/dist/types/tests/utils/memory-cache.spec.d.ts.map +1 -0
  683. package/dist/types/tests/utils/messages.spec.d.ts +2 -0
  684. package/dist/types/tests/utils/messages.spec.d.ts.map +1 -0
  685. package/dist/types/tests/utils/object.spec.d.ts +2 -0
  686. package/dist/types/tests/utils/object.spec.d.ts.map +1 -0
  687. package/dist/types/tests/utils/poller.d.ts +21 -0
  688. package/dist/types/tests/utils/poller.d.ts.map +1 -0
  689. package/dist/types/tests/utils/private-key-signer.spec.d.ts +2 -0
  690. package/dist/types/tests/utils/private-key-signer.spec.d.ts.map +1 -0
  691. package/dist/types/tests/utils/records.spec.d.ts +2 -0
  692. package/dist/types/tests/utils/records.spec.d.ts.map +1 -0
  693. package/dist/types/tests/utils/secp256k1.spec.d.ts +2 -0
  694. package/dist/types/tests/utils/secp256k1.spec.d.ts.map +1 -0
  695. package/dist/types/tests/utils/secp256r1.spec.d.ts +2 -0
  696. package/dist/types/tests/utils/secp256r1.spec.d.ts.map +1 -0
  697. package/dist/types/tests/utils/test-data-generator.d.ts +342 -0
  698. package/dist/types/tests/utils/test-data-generator.d.ts.map +1 -0
  699. package/dist/types/tests/utils/test-stub-generator.d.ts +16 -0
  700. package/dist/types/tests/utils/test-stub-generator.d.ts.map +1 -0
  701. package/dist/types/tests/utils/time.spec.d.ts +2 -0
  702. package/dist/types/tests/utils/time.spec.d.ts.map +1 -0
  703. package/dist/types/tests/utils/url.spec.d.ts +2 -0
  704. package/dist/types/tests/utils/url.spec.d.ts.map +1 -0
  705. package/dist/types/tests/validation/json-schemas/definitions.spec.d.ts +2 -0
  706. package/dist/types/tests/validation/json-schemas/definitions.spec.d.ts.map +1 -0
  707. package/dist/types/tests/validation/json-schemas/jwk/general-jwk.spec.d.ts +2 -0
  708. package/dist/types/tests/validation/json-schemas/jwk/general-jwk.spec.d.ts.map +1 -0
  709. package/dist/types/tests/validation/json-schemas/jwk/public-jwk.spec.d.ts +2 -0
  710. package/dist/types/tests/validation/json-schemas/jwk/public-jwk.spec.d.ts.map +1 -0
  711. package/dist/types/tests/validation/json-schemas/jwk-verification-method.spec.d.ts +2 -0
  712. package/dist/types/tests/validation/json-schemas/jwk-verification-method.spec.d.ts.map +1 -0
  713. package/dist/types/tests/validation/json-schemas/protocols/protocols-configure.spec.d.ts +2 -0
  714. package/dist/types/tests/validation/json-schemas/protocols/protocols-configure.spec.d.ts.map +1 -0
  715. package/dist/types/tests/validation/json-schemas/records/records-query.spec.d.ts +2 -0
  716. package/dist/types/tests/validation/json-schemas/records/records-query.spec.d.ts.map +1 -0
  717. package/dist/types/tests/validation/json-schemas/records/records-write.spec.d.ts +2 -0
  718. package/dist/types/tests/validation/json-schemas/records/records-write.spec.d.ts.map +1 -0
  719. package/package.json +167 -0
  720. package/src/core/abstract-message.ts +62 -0
  721. package/src/core/auth.ts +36 -0
  722. package/src/core/dwn-constant.ts +9 -0
  723. package/src/core/dwn-error.ts +167 -0
  724. package/src/core/grant-authorization.ts +148 -0
  725. package/src/core/message-reply.ts +41 -0
  726. package/src/core/message.ts +259 -0
  727. package/src/core/messages-grant-authorization.ts +134 -0
  728. package/src/core/protocol-authorization.ts +903 -0
  729. package/src/core/protocols-grant-authorization.ts +88 -0
  730. package/src/core/records-grant-authorization.ts +197 -0
  731. package/src/core/resumable-task-manager.ts +114 -0
  732. package/src/core/tenant-gate.ts +33 -0
  733. package/src/dwn.ts +264 -0
  734. package/src/enums/dwn-interface-method.ts +14 -0
  735. package/src/event-log/event-emitter-stream.ts +69 -0
  736. package/src/event-log/event-log-level.ts +72 -0
  737. package/src/handlers/messages-query.ts +67 -0
  738. package/src/handlers/messages-read.ts +103 -0
  739. package/src/handlers/messages-subscribe.ts +89 -0
  740. package/src/handlers/protocols-configure.ts +137 -0
  741. package/src/handlers/protocols-query.ts +82 -0
  742. package/src/handlers/records-delete.ts +124 -0
  743. package/src/handlers/records-query.ts +262 -0
  744. package/src/handlers/records-read.ts +187 -0
  745. package/src/handlers/records-subscribe.ts +218 -0
  746. package/src/handlers/records-write.ts +404 -0
  747. package/src/index.ts +67 -0
  748. package/src/interfaces/messages-query.ts +60 -0
  749. package/src/interfaces/messages-read.ts +63 -0
  750. package/src/interfaces/messages-subscribe.ts +64 -0
  751. package/src/interfaces/protocols-configure.ts +340 -0
  752. package/src/interfaces/protocols-query.ts +96 -0
  753. package/src/interfaces/records-delete.ts +117 -0
  754. package/src/interfaces/records-query.ts +131 -0
  755. package/src/interfaces/records-read.ts +100 -0
  756. package/src/interfaces/records-subscribe.ts +104 -0
  757. package/src/interfaces/records-write.ts +1072 -0
  758. package/src/jose/algorithms/signing/ed25519.ts +58 -0
  759. package/src/jose/algorithms/signing/signature-algorithms.ts +22 -0
  760. package/src/jose/jws/general/builder.ts +48 -0
  761. package/src/jose/jws/general/verifier.ts +112 -0
  762. package/src/protocols/permission-grant.ts +86 -0
  763. package/src/protocols/permission-request.ts +63 -0
  764. package/src/protocols/permissions.ts +508 -0
  765. package/src/schema-validator.ts +46 -0
  766. package/src/store/blockstore-level.ts +113 -0
  767. package/src/store/blockstore-mock.ts +80 -0
  768. package/src/store/data-store-level.ts +120 -0
  769. package/src/store/index-level.ts +691 -0
  770. package/src/store/level-wrapper.ts +272 -0
  771. package/src/store/message-store-level.ts +195 -0
  772. package/src/store/resumable-task-store-level.ts +120 -0
  773. package/src/store/storage-controller.ts +240 -0
  774. package/src/types/cache.ts +16 -0
  775. package/src/types/data-store.ts +64 -0
  776. package/src/types/event-log.ts +52 -0
  777. package/src/types/jose-types.ts +76 -0
  778. package/src/types/jws-types.ts +28 -0
  779. package/src/types/message-interface.ts +30 -0
  780. package/src/types/message-store.ts +57 -0
  781. package/src/types/message-types.ts +132 -0
  782. package/src/types/messages-types.ts +77 -0
  783. package/src/types/method-handler.ts +19 -0
  784. package/src/types/permission-types.ts +110 -0
  785. package/src/types/protocols-types.ts +177 -0
  786. package/src/types/query-types.ts +61 -0
  787. package/src/types/records-types.ts +263 -0
  788. package/src/types/resumable-task-store.ts +96 -0
  789. package/src/types/signer.ts +27 -0
  790. package/src/types/subscriptions.ts +34 -0
  791. package/src/utils/abort.ts +31 -0
  792. package/src/utils/array.ts +39 -0
  793. package/src/utils/cid.ts +101 -0
  794. package/src/utils/data-stream.ts +99 -0
  795. package/src/utils/encoder.ts +54 -0
  796. package/src/utils/encryption.ts +145 -0
  797. package/src/utils/filter.ts +245 -0
  798. package/src/utils/hd-key.ts +126 -0
  799. package/src/utils/jws.ts +95 -0
  800. package/src/utils/memory-cache.ts +31 -0
  801. package/src/utils/messages.ts +109 -0
  802. package/src/utils/object.ts +43 -0
  803. package/src/utils/private-key-signer.ts +72 -0
  804. package/src/utils/protocols.ts +50 -0
  805. package/src/utils/records.ts +559 -0
  806. package/src/utils/secp256k1.ts +157 -0
  807. package/src/utils/secp256r1.ts +142 -0
  808. package/src/utils/string.ts +13 -0
  809. package/src/utils/time.ts +78 -0
  810. package/src/utils/url.ts +65 -0
@@ -0,0 +1,3637 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import anyoneCollaborateProtocolDefinition from '../vectors/protocol-definitions/anyone-collaborate.json' assert { type: 'json' };
11
+ import authorCanProtocolDefinition from '../vectors/protocol-definitions/author-can.json' assert { type: 'json' };
12
+ import chaiAsPromised from 'chai-as-promised';
13
+ import credentialIssuanceProtocolDefinition from '../vectors/protocol-definitions/credential-issuance.json' assert { type: 'json' };
14
+ import dexProtocolDefinition from '../vectors/protocol-definitions/dex.json' assert { type: 'json' };
15
+ import emailProtocolDefinition from '../vectors/protocol-definitions/email.json' assert { type: 'json' };
16
+ import friendRoleProtocolDefinition from '../vectors/protocol-definitions/friend-role.json' assert { type: 'json' };
17
+ import messageProtocolDefinition from '../vectors/protocol-definitions/message.json' assert { type: 'json' };
18
+ import minimalProtocolDefinition from '../vectors/protocol-definitions/minimal.json' assert { type: 'json' };
19
+ import nestedProtocol from '../vectors/protocol-definitions/nested.json' assert { type: 'json' };
20
+ import privateProtocol from '../vectors/protocol-definitions/private-protocol.json' assert { type: 'json' };
21
+ import recipientCanProtocol from '../vectors/protocol-definitions/recipient-can.json' assert { type: 'json' };
22
+ import sinon from 'sinon';
23
+ import socialMediaProtocolDefinition from '../vectors/protocol-definitions/social-media.json' assert { type: 'json' };
24
+ import threadRoleProtocolDefinition from '../vectors/protocol-definitions/thread-role.json' assert { type: 'json' };
25
+ import chai, { expect } from 'chai';
26
+ import { ArrayUtility } from '../../src/utils/array.js';
27
+ import { base64url } from 'multiformats/bases/base64';
28
+ import { Cid } from '../../src/utils/cid.js';
29
+ import { DataStream } from '../../src/utils/data-stream.js';
30
+ import { Dwn } from '../../src/dwn.js';
31
+ import { Encoder } from '../../src/utils/encoder.js';
32
+ import { GeneralJwsBuilder } from '../../src/jose/jws/general/builder.js';
33
+ import { Jws } from '../../src/utils/jws.js';
34
+ import { Message } from '../../src/core/message.js';
35
+ import { PermissionConditionPublication } from '../../src/types/permission-types.js';
36
+ import { RecordsRead } from '../../src/interfaces/records-read.js';
37
+ import { RecordsWrite } from '../../src/interfaces/records-write.js';
38
+ import { RecordsWriteHandler } from '../../src/handlers/records-write.js';
39
+ import { TestDataGenerator } from '../utils/test-data-generator.js';
40
+ import { TestEventStream } from '../test-event-stream.js';
41
+ import { TestStores } from '../test-stores.js';
42
+ import { TestStubGenerator } from '../utils/test-stub-generator.js';
43
+ import { Time } from '../../src/utils/time.js';
44
+ import { DwnError, DwnErrorCode } from '../../src/core/dwn-error.js';
45
+ import { DataStoreLevel, DwnConstant, DwnInterfaceName, DwnMethodName, KeyDerivationScheme, MessageStoreLevel, PermissionsProtocol, RecordsDelete, RecordsQuery } from '../../src/index.js';
46
+ import { DidKey, UniversalResolver } from '@enbox/dids';
47
+ import { Encryption, EncryptionAlgorithm } from '../../src/utils/encryption.js';
48
+ chai.use(chaiAsPromised);
49
+ export function testRecordsWriteHandler() {
50
+ describe('RecordsWriteHandler.handle()', () => __awaiter(this, void 0, void 0, function* () {
51
+ let didResolver;
52
+ let messageStore;
53
+ let dataStore;
54
+ let resumableTaskStore;
55
+ let eventLog;
56
+ let eventStream;
57
+ let dwn;
58
+ beforeEach(() => {
59
+ sinon.restore();
60
+ });
61
+ describe('functional tests', () => {
62
+ // important to follow the `before` and `after` pattern to initialize and clean the stores in tests
63
+ // so that different test suites can reuse the same backend store for testing
64
+ before(() => __awaiter(this, void 0, void 0, function* () {
65
+ didResolver = new UniversalResolver({ didResolvers: [DidKey] });
66
+ const stores = TestStores.get();
67
+ messageStore = stores.messageStore;
68
+ dataStore = stores.dataStore;
69
+ resumableTaskStore = stores.resumableTaskStore;
70
+ eventLog = stores.eventLog;
71
+ eventStream = TestEventStream.get();
72
+ dwn = yield Dwn.create({ didResolver, messageStore, dataStore, eventLog, eventStream, resumableTaskStore });
73
+ }));
74
+ beforeEach(() => __awaiter(this, void 0, void 0, function* () {
75
+ // clean up before each test rather than after so that a test does not depend on other tests to do the clean up
76
+ yield messageStore.clear();
77
+ yield dataStore.clear();
78
+ yield resumableTaskStore.clear();
79
+ yield eventLog.clear();
80
+ }));
81
+ after(() => __awaiter(this, void 0, void 0, function* () {
82
+ yield dwn.close();
83
+ }));
84
+ it('should call preProcessingForCoreRecordsWrite after authorization and before storage', () => __awaiter(this, void 0, void 0, function* () {
85
+ // We create spy or stub for authorization, preProcessingForCoreRecordsWrite and processMessageWithDataStream methods
86
+ // When we trigger a failure for `preProcessingForCoreRecordsWrite`, we expect the `processMessageWithDataStream` method to not be called
87
+ const authorizationSpy = sinon.spy(RecordsWriteHandler, 'authorizeRecordsWrite');
88
+ const processDataStreamSpy = sinon.spy(RecordsWriteHandler.prototype, 'processMessageWithDataStream');
89
+ const preProcessingForCoreRecordsWriteSpy = sinon.stub(RecordsWriteHandler.prototype, 'preProcessingForCoreRecordsWrite')
90
+ .throws(new DwnError(DwnErrorCode.PermissionsProtocolValidateScopeProtocolMismatch, 'Some Error'));
91
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
92
+ const { message, dataStream } = yield TestDataGenerator.generateRecordsWrite({ author: alice });
93
+ const reply = yield dwn.processMessage(alice.did, message, { dataStream });
94
+ expect(reply.status.code).to.equal(400);
95
+ // expect that authorization and preProcessingForCoreRecordsWrite are both called once
96
+ expect(authorizationSpy.calledOnce).to.be.true;
97
+ expect(preProcessingForCoreRecordsWriteSpy.calledOnce).to.be.true;
98
+ // expect that processMessageWithDataStream is NOT called since preProcessingForCoreRecordsWrite failed before reaching it
99
+ expect(processDataStreamSpy.called).to.be.false;
100
+ }));
101
+ it('should only be able to overwrite existing record if new record has a later `messageTimestamp` value', () => __awaiter(this, void 0, void 0, function* () {
102
+ var _a, _b, _c;
103
+ // write a message into DB
104
+ const author = yield TestDataGenerator.generateDidKeyPersona();
105
+ const data1 = new TextEncoder().encode('data1');
106
+ const recordsWriteMessageData = yield TestDataGenerator.generateRecordsWrite({ author, data: data1 });
107
+ const tenant = author.did;
108
+ const recordsWriteReply = yield dwn.processMessage(tenant, recordsWriteMessageData.message, { dataStream: recordsWriteMessageData.dataStream });
109
+ expect(recordsWriteReply.status.code).to.equal(202);
110
+ const recordId = recordsWriteMessageData.message.recordId;
111
+ const recordsQueryMessageData = yield TestDataGenerator.generateRecordsQuery({
112
+ author,
113
+ filter: { recordId }
114
+ });
115
+ // verify the message written can be queried
116
+ const recordsQueryReply = yield dwn.processMessage(tenant, recordsQueryMessageData.message);
117
+ expect(recordsQueryReply.status.code).to.equal(200);
118
+ expect((_a = recordsQueryReply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(1);
119
+ expect(recordsQueryReply.entries[0].encodedData).to.equal(base64url.baseEncode(data1));
120
+ // generate and write a new RecordsWrite to overwrite the existing record
121
+ // a new RecordsWrite by default will have a later `messageTimestamp`
122
+ const newDataBytes = Encoder.stringToBytes('new data');
123
+ const newDataEncoded = Encoder.bytesToBase64Url(newDataBytes);
124
+ const newRecordsWrite = yield TestDataGenerator.generateFromRecordsWrite({
125
+ author,
126
+ existingWrite: recordsWriteMessageData.recordsWrite,
127
+ data: newDataBytes
128
+ });
129
+ // sanity check that old data and new data are different
130
+ expect(newDataEncoded).to.not.equal(Encoder.bytesToBase64Url(recordsWriteMessageData.dataBytes));
131
+ const newRecordsWriteReply = yield dwn.processMessage(tenant, newRecordsWrite.message, { dataStream: newRecordsWrite.dataStream });
132
+ expect(newRecordsWriteReply.status.code).to.equal(202);
133
+ // verify new record has overwritten the existing record
134
+ const newRecordsQueryReply = yield dwn.processMessage(tenant, recordsQueryMessageData.message);
135
+ expect(newRecordsQueryReply.status.code).to.equal(200);
136
+ expect((_b = newRecordsQueryReply.entries) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
137
+ expect(newRecordsQueryReply.entries[0].encodedData).to.equal(newDataEncoded);
138
+ // try to write the older message to store again and verify that it is not accepted
139
+ const thirdRecordsWriteReply = yield dwn.processMessage(tenant, recordsWriteMessageData.message, { dataStream: recordsWriteMessageData.dataStream });
140
+ expect(thirdRecordsWriteReply.status.code).to.equal(409); // expecting to fail
141
+ // expecting unchanged
142
+ const thirdRecordsQueryReply = yield dwn.processMessage(tenant, recordsQueryMessageData.message);
143
+ expect(thirdRecordsQueryReply.status.code).to.equal(200);
144
+ expect((_c = thirdRecordsQueryReply.entries) === null || _c === void 0 ? void 0 : _c.length).to.equal(1);
145
+ expect(thirdRecordsQueryReply.entries[0].encodedData).to.equal(newDataEncoded);
146
+ }));
147
+ it('should only be able to overwrite existing record if new message CID is larger when `messageTimestamp` value is the same', () => __awaiter(this, void 0, void 0, function* () {
148
+ var _a, _b, _c;
149
+ // start by writing an originating message
150
+ const author = yield TestDataGenerator.generatePersona();
151
+ const tenant = author.did;
152
+ const originatingMessageData = yield TestDataGenerator.generateRecordsWrite({
153
+ author,
154
+ data: Encoder.stringToBytes('unused')
155
+ });
156
+ // setting up a stub DID resolver
157
+ TestStubGenerator.stubDidResolver(didResolver, [author]);
158
+ const originatingMessageWriteReply = yield dwn.processMessage(tenant, originatingMessageData.message, { dataStream: originatingMessageData.dataStream });
159
+ expect(originatingMessageWriteReply.status.code).to.equal(202);
160
+ // generate two new RecordsWrite messages with the same `messageTimestamp` value
161
+ const dateModified = Time.getCurrentTimestamp();
162
+ const recordsWrite1 = yield TestDataGenerator.generateFromRecordsWrite({
163
+ author,
164
+ existingWrite: originatingMessageData.recordsWrite,
165
+ messageTimestamp: dateModified
166
+ });
167
+ const recordsWrite2 = yield TestDataGenerator.generateFromRecordsWrite({
168
+ author,
169
+ existingWrite: originatingMessageData.recordsWrite,
170
+ messageTimestamp: dateModified
171
+ });
172
+ // determine the lexicographical order of the two messages
173
+ const message1Cid = yield Message.getCid(recordsWrite1.message);
174
+ const message2Cid = yield Message.getCid(recordsWrite2.message);
175
+ let newerWrite;
176
+ let olderWrite;
177
+ if (message1Cid > message2Cid) {
178
+ newerWrite = recordsWrite1;
179
+ olderWrite = recordsWrite2;
180
+ }
181
+ else {
182
+ newerWrite = recordsWrite2;
183
+ olderWrite = recordsWrite1;
184
+ }
185
+ // write the message with the smaller lexicographical message CID first
186
+ const recordsWriteReply = yield dwn.processMessage(tenant, olderWrite.message, { dataStream: olderWrite.dataStream });
187
+ expect(recordsWriteReply.status.code).to.equal(202);
188
+ // query to fetch the record
189
+ const recordsQueryMessageData = yield TestDataGenerator.generateRecordsQuery({
190
+ author,
191
+ filter: { recordId: originatingMessageData.message.recordId }
192
+ });
193
+ // verify the data is written
194
+ const recordsQueryReply = yield dwn.processMessage(tenant, recordsQueryMessageData.message);
195
+ expect(recordsQueryReply.status.code).to.equal(200);
196
+ expect((_a = recordsQueryReply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(1);
197
+ expect(recordsQueryReply.entries[0].descriptor.dataCid)
198
+ .to.equal(olderWrite.message.descriptor.dataCid);
199
+ // attempt to write the message with larger lexicographical message CID
200
+ const newRecordsWriteReply = yield dwn.processMessage(tenant, newerWrite.message, { dataStream: newerWrite.dataStream });
201
+ expect(newRecordsWriteReply.status.code).to.equal(202);
202
+ // verify new record has overwritten the existing record
203
+ const newRecordsQueryReply = yield dwn.processMessage(tenant, recordsQueryMessageData.message);
204
+ expect(newRecordsQueryReply.status.code).to.equal(200);
205
+ expect((_b = newRecordsQueryReply.entries) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
206
+ expect(newRecordsQueryReply.entries[0].descriptor.dataCid)
207
+ .to.equal(newerWrite.message.descriptor.dataCid);
208
+ // try to write the message with smaller lexicographical message CID again
209
+ const thirdRecordsWriteReply = yield dwn.processMessage(tenant, olderWrite.message, { dataStream: DataStream.fromBytes(olderWrite.dataBytes) } // need to create data stream again since it's already used above
210
+ );
211
+ expect(thirdRecordsWriteReply.status.code).to.equal(409); // expecting to fail
212
+ // verify the message in store is still the one with larger lexicographical message CID
213
+ const thirdRecordsQueryReply = yield dwn.processMessage(tenant, recordsQueryMessageData.message);
214
+ expect(thirdRecordsQueryReply.status.code).to.equal(200);
215
+ expect((_c = thirdRecordsQueryReply.entries) === null || _c === void 0 ? void 0 : _c.length).to.equal(1);
216
+ expect(thirdRecordsQueryReply.entries[0].descriptor.dataCid)
217
+ .to.equal(newerWrite.message.descriptor.dataCid); // expecting unchanged
218
+ }));
219
+ it('#690 - should allow data format of a flat-space record to be updated to any value', () => __awaiter(this, void 0, void 0, function* () {
220
+ var _a;
221
+ const initialWriteData = yield TestDataGenerator.generateRecordsWrite();
222
+ const tenant = initialWriteData.author.did;
223
+ TestStubGenerator.stubDidResolver(didResolver, [initialWriteData.author]);
224
+ const initialWriteReply = yield dwn.processMessage(tenant, initialWriteData.message, { dataStream: initialWriteData.dataStream });
225
+ expect(initialWriteReply.status.code).to.equal(202);
226
+ const newDataFormat = 'any-new-data-format';
227
+ const newDataBytes = TestDataGenerator.randomBytes(100);
228
+ const updateWrite = yield RecordsWrite.createFrom({
229
+ recordsWriteMessage: initialWriteData.message,
230
+ dataFormat: newDataFormat,
231
+ signer: Jws.createSigner(initialWriteData.author),
232
+ data: newDataBytes
233
+ });
234
+ const newDataStream = DataStream.fromBytes(newDataBytes);
235
+ const updateReply = yield dwn.processMessage(tenant, updateWrite.message, { dataStream: newDataStream });
236
+ expect(updateReply.status.code).to.equal(202);
237
+ // verify the data format of the record is updated
238
+ const recordsRead = yield RecordsRead.create({
239
+ filter: { recordId: initialWriteData.message.recordId },
240
+ signer: Jws.createSigner(initialWriteData.author),
241
+ });
242
+ const recordsReadReply = yield dwn.processMessage(tenant, recordsRead.message);
243
+ expect(recordsReadReply.status.code).to.equal(200);
244
+ expect((_a = recordsReadReply.entry.recordsWrite) === null || _a === void 0 ? void 0 : _a.descriptor.dataFormat).to.equal(newDataFormat);
245
+ }));
246
+ it('should not allow changes to immutable properties', () => __awaiter(this, void 0, void 0, function* () {
247
+ const initialWriteData = yield TestDataGenerator.generateRecordsWrite();
248
+ const tenant = initialWriteData.author.did;
249
+ TestStubGenerator.stubDidResolver(didResolver, [initialWriteData.author]);
250
+ const initialWriteReply = yield dwn.processMessage(tenant, initialWriteData.message, { dataStream: initialWriteData.dataStream });
251
+ expect(initialWriteReply.status.code).to.equal(202);
252
+ const recordId = initialWriteData.message.recordId;
253
+ const dateCreated = initialWriteData.message.descriptor.dateCreated;
254
+ const schema = initialWriteData.message.descriptor.schema;
255
+ // dateCreated test
256
+ let childMessageData = yield TestDataGenerator.generateRecordsWrite({
257
+ author: initialWriteData.author,
258
+ recordId,
259
+ schema,
260
+ dateCreated: Time.getCurrentTimestamp(), // should not be allowed to be modified
261
+ dataFormat: initialWriteData.message.descriptor.dataFormat
262
+ });
263
+ let reply = yield dwn.processMessage(tenant, childMessageData.message, { dataStream: childMessageData.dataStream });
264
+ expect(reply.status.code).to.equal(400);
265
+ expect(reply.status.detail).to.contain('dateCreated is an immutable property');
266
+ // schema test
267
+ childMessageData = yield TestDataGenerator.generateRecordsWrite({
268
+ author: initialWriteData.author,
269
+ recordId,
270
+ schema: 'should-not-allowed-to-be-modified',
271
+ dateCreated,
272
+ dataFormat: initialWriteData.message.descriptor.dataFormat
273
+ });
274
+ reply = yield dwn.processMessage(tenant, childMessageData.message, { dataStream: childMessageData.dataStream });
275
+ expect(reply.status.code).to.equal(400);
276
+ expect(reply.status.detail).to.contain('schema is an immutable property');
277
+ }));
278
+ it('should inherit data from previous RecordsWrite given a matching dataCid and dataSize and no dataStream', () => __awaiter(this, void 0, void 0, function* () {
279
+ const { message, author, dataStream, dataBytes } = yield TestDataGenerator.generateRecordsWrite({
280
+ published: false
281
+ });
282
+ const tenant = author.did;
283
+ TestStubGenerator.stubDidResolver(didResolver, [author]);
284
+ const initialWriteReply = yield dwn.processMessage(tenant, message, { dataStream });
285
+ expect(initialWriteReply.status.code).to.equal(202);
286
+ const write2 = yield RecordsWrite.createFrom({
287
+ recordsWriteMessage: message,
288
+ published: true,
289
+ signer: Jws.createSigner(author),
290
+ });
291
+ const writeUpdateReply = yield dwn.processMessage(tenant, write2.message);
292
+ expect(writeUpdateReply.status.code).to.equal(202);
293
+ const readMessage = yield RecordsRead.create({
294
+ filter: {
295
+ recordId: message.recordId,
296
+ }
297
+ });
298
+ const readMessageReply = yield dwn.processMessage(tenant, readMessage.message);
299
+ expect(readMessageReply.status.code).to.equal(200);
300
+ expect(readMessageReply.entry.recordsWrite).to.exist;
301
+ const data = yield DataStream.toBytes(readMessageReply.entry.data);
302
+ expect(data).to.eql(dataBytes);
303
+ }));
304
+ it('should allow an initial `RecordsWrite` to be written without supplying data', () => __awaiter(this, void 0, void 0, function* () {
305
+ //scenario: you have an initial write without the data and a subsequent write with data to be able to write.
306
+ // the DWN should accept an initial write without data, however prevent the user from querying for it until it's updated.
307
+ var _a, _b;
308
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
309
+ const { recordsWrite } = yield TestDataGenerator.generateRecordsWrite({ author: alice });
310
+ // simulate synchronize of pruned initial `RecordsWrite`
311
+ const reply = yield dwn.processMessage(alice.did, recordsWrite.message);
312
+ expect(reply.status.code).to.equal(204);
313
+ // verify `RecordsWrite` inserted is not returned with a query
314
+ const recordsQueryMessageData = yield TestDataGenerator.generateRecordsQuery({
315
+ author: alice,
316
+ filter: { recordId: recordsWrite.message.recordId }
317
+ });
318
+ const recordsQueryReply = yield dwn.processMessage(alice.did, recordsQueryMessageData.message);
319
+ expect(recordsQueryReply.status.code).to.equal(200);
320
+ expect((_a = recordsQueryReply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(0);
321
+ // generate and write a new `RecordsWrite` to overwrite the existing record
322
+ const newDataBytes = Encoder.stringToBytes('new data');
323
+ const newDataEncoded = Encoder.bytesToBase64Url(newDataBytes);
324
+ const newRecordsWrite = yield TestDataGenerator.generateFromRecordsWrite({
325
+ author: alice,
326
+ existingWrite: recordsWrite,
327
+ data: newDataBytes
328
+ });
329
+ const newRecordsWriteReply = yield dwn.processMessage(alice.did, newRecordsWrite.message, { dataStream: newRecordsWrite.dataStream });
330
+ expect(newRecordsWriteReply.status.code).to.equal(202);
331
+ // verify new `RecordsWrite` has overwritten the existing record with new data
332
+ const newRecordsQueryReply = yield dwn.processMessage(alice.did, recordsQueryMessageData.message);
333
+ expect(newRecordsQueryReply.status.code).to.equal(200);
334
+ expect((_b = newRecordsQueryReply.entries) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
335
+ expect(newRecordsQueryReply.entries[0].encodedData).to.equal(newDataEncoded);
336
+ }));
337
+ it('should not allow non-initial writes to be written without supplying data', () => __awaiter(this, void 0, void 0, function* () {
338
+ //scenario: you have an initial write without the data and a subsequent write with data to be able to write.
339
+ // the DWN should accept an initial write without data, however prevent the user from querying for it until it's updated.
340
+ var _a, _b;
341
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
342
+ // write a record into the dwn
343
+ const { recordsWrite, dataStream, dataBytes } = yield TestDataGenerator.generateRecordsWrite({ author: alice });
344
+ const reply = yield dwn.processMessage(alice.did, recordsWrite.message, { dataStream });
345
+ expect(reply.status.code).to.equal(202);
346
+ // verify `RecordsWrite` inserted can be queried
347
+ const recordsQueryMessageData = yield TestDataGenerator.generateRecordsQuery({
348
+ author: alice,
349
+ filter: { recordId: recordsWrite.message.recordId }
350
+ });
351
+ const recordsQueryReply = yield dwn.processMessage(alice.did, recordsQueryMessageData.message);
352
+ expect(recordsQueryReply.status.code).to.equal(200);
353
+ expect((_a = recordsQueryReply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(1);
354
+ // generate and write a new `RecordsWrite` to overwrite the existing record
355
+ const newDataBytes = Encoder.stringToBytes('new data');
356
+ const newRecordsWrite = yield TestDataGenerator.generateFromRecordsWrite({
357
+ author: alice,
358
+ existingWrite: recordsWrite,
359
+ data: newDataBytes
360
+ });
361
+ // records write should be rejected.
362
+ const newRecordsWriteReply = yield dwn.processMessage(alice.did, newRecordsWrite.message);
363
+ expect(newRecordsWriteReply.status.code).to.equal(400);
364
+ expect(newRecordsWriteReply.status.detail).to.contain(DwnErrorCode.RecordsWriteDataCidMismatch);
365
+ // verify the original `RecordsWrite` and data are still available
366
+ const newRecordsQueryReply = yield dwn.processMessage(alice.did, recordsQueryMessageData.message);
367
+ expect(newRecordsQueryReply.status.code).to.equal(200);
368
+ expect((_b = newRecordsQueryReply.entries) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
369
+ const originalEncodedData = Encoder.bytesToBase64Url(dataBytes);
370
+ expect(newRecordsQueryReply.entries[0].encodedData).to.equal(originalEncodedData);
371
+ }));
372
+ describe('should inherit data from previous RecordsWrite given a matching dataCid and dataSize and no dataStream', () => {
373
+ it('with data above the threshold for encodedData', () => __awaiter(this, void 0, void 0, function* () {
374
+ const { message, author, dataStream, dataBytes } = yield TestDataGenerator.generateRecordsWrite({
375
+ data: TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1),
376
+ published: false
377
+ });
378
+ const tenant = author.did;
379
+ TestStubGenerator.stubDidResolver(didResolver, [author]);
380
+ const initialWriteReply = yield dwn.processMessage(tenant, message, { dataStream });
381
+ expect(initialWriteReply.status.code).to.equal(202);
382
+ const write2 = yield RecordsWrite.createFrom({
383
+ recordsWriteMessage: message,
384
+ published: true,
385
+ signer: Jws.createSigner(author),
386
+ });
387
+ const writeUpdateReply = yield dwn.processMessage(tenant, write2.message);
388
+ expect(writeUpdateReply.status.code).to.equal(202);
389
+ const readMessage = yield RecordsRead.create({
390
+ filter: {
391
+ recordId: message.recordId,
392
+ }
393
+ });
394
+ const readMessageReply = yield dwn.processMessage(tenant, readMessage.message);
395
+ expect(readMessageReply.status.code).to.equal(200);
396
+ expect(readMessageReply.entry.recordsWrite).to.exist;
397
+ const data = yield DataStream.toBytes(readMessageReply.entry.data);
398
+ expect(data).to.eql(dataBytes);
399
+ }));
400
+ it('with data equal to or below the threshold for encodedData', () => __awaiter(this, void 0, void 0, function* () {
401
+ const { message, author, dataStream, dataBytes } = yield TestDataGenerator.generateRecordsWrite({
402
+ data: TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded),
403
+ published: false
404
+ });
405
+ const tenant = author.did;
406
+ TestStubGenerator.stubDidResolver(didResolver, [author]);
407
+ const initialWriteReply = yield dwn.processMessage(tenant, message, { dataStream });
408
+ expect(initialWriteReply.status.code).to.equal(202);
409
+ const write2 = yield RecordsWrite.createFrom({
410
+ recordsWriteMessage: message,
411
+ published: true,
412
+ signer: Jws.createSigner(author),
413
+ });
414
+ const writeUpdateReply = yield dwn.processMessage(tenant, write2.message);
415
+ expect(writeUpdateReply.status.code).to.equal(202);
416
+ const readMessage = yield RecordsRead.create({
417
+ filter: {
418
+ recordId: message.recordId,
419
+ }
420
+ });
421
+ const readMessageReply = yield dwn.processMessage(tenant, readMessage.message);
422
+ expect(readMessageReply.status.code).to.equal(200);
423
+ expect(readMessageReply.entry.recordsWrite).to.exist;
424
+ const data = yield DataStream.toBytes(readMessageReply.entry.data);
425
+ expect(data).to.eql(dataBytes);
426
+ }));
427
+ });
428
+ describe('should return 400 if actual data size mismatches with `dataSize` in descriptor', () => {
429
+ it('with dataStream and `dataSize` larger than encodedData threshold', () => __awaiter(this, void 0, void 0, function* () {
430
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
431
+ const { message, dataStream } = yield TestDataGenerator.generateRecordsWrite({
432
+ author: alice,
433
+ data: TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1)
434
+ });
435
+ // replace the dataSize to simulate mismatch, will need to generate `recordId` and `authorization` property again
436
+ message.descriptor.dataSize = DwnConstant.maxDataSizeAllowedToBeEncoded + 100;
437
+ const descriptorCid = yield Cid.computeCid(message.descriptor);
438
+ const recordId = yield RecordsWrite.getEntryId(alice.did, message.descriptor);
439
+ const signer = Jws.createSigner(alice);
440
+ const signature = yield RecordsWrite.createSignerSignature({
441
+ recordId,
442
+ contextId: message.contextId,
443
+ descriptorCid,
444
+ attestation: message.attestation,
445
+ encryption: message.encryption,
446
+ signer
447
+ });
448
+ message.recordId = recordId;
449
+ message.authorization = { signature };
450
+ const reply = yield dwn.processMessage(alice.did, message, { dataStream });
451
+ expect(reply.status.code).to.equal(400);
452
+ expect(reply.status.detail).to.contain(DwnErrorCode.RecordsWriteDataSizeMismatch);
453
+ }));
454
+ it('with only `dataSize` larger than encodedData threshold', () => __awaiter(this, void 0, void 0, function* () {
455
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
456
+ const { message, dataStream } = yield TestDataGenerator.generateRecordsWrite({
457
+ author: alice,
458
+ data: TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded)
459
+ });
460
+ // replace the dataSize to simulate mismatch, will need to generate `recordId` and `authorization` property again
461
+ message.descriptor.dataSize = DwnConstant.maxDataSizeAllowedToBeEncoded + 100;
462
+ const descriptorCid = yield Cid.computeCid(message.descriptor);
463
+ const recordId = yield RecordsWrite.getEntryId(alice.did, message.descriptor);
464
+ const signer = Jws.createSigner(alice);
465
+ const signature = yield RecordsWrite.createSignerSignature({
466
+ recordId,
467
+ contextId: message.contextId,
468
+ descriptorCid,
469
+ attestation: message.attestation,
470
+ encryption: message.encryption,
471
+ signer
472
+ });
473
+ message.recordId = recordId;
474
+ message.authorization = { signature };
475
+ const reply = yield dwn.processMessage(alice.did, message, { dataStream });
476
+ expect(reply.status.code).to.equal(400);
477
+ expect(reply.status.detail).to.contain(DwnErrorCode.RecordsWriteDataSizeMismatch);
478
+ }));
479
+ it('with only dataStream larger than encodedData threshold', () => __awaiter(this, void 0, void 0, function* () {
480
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
481
+ const { message, dataStream } = yield TestDataGenerator.generateRecordsWrite({
482
+ author: alice,
483
+ data: TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1)
484
+ });
485
+ // replace the dataSize to simulate mismatch, will need to generate `recordId` and `authorization` property again
486
+ message.descriptor.dataSize = 1;
487
+ const descriptorCid = yield Cid.computeCid(message.descriptor);
488
+ const recordId = yield RecordsWrite.getEntryId(alice.did, message.descriptor);
489
+ const signer = Jws.createSigner(alice);
490
+ const signature = yield RecordsWrite.createSignerSignature({
491
+ recordId,
492
+ contextId: message.contextId,
493
+ descriptorCid,
494
+ attestation: message.attestation,
495
+ encryption: message.encryption,
496
+ signer
497
+ });
498
+ message.recordId = recordId;
499
+ message.authorization = { signature };
500
+ const reply = yield dwn.processMessage(alice.did, message, { dataStream });
501
+ expect(reply.status.code).to.equal(400);
502
+ expect(reply.status.detail).to.contain(DwnErrorCode.RecordsWriteDataSizeMismatch);
503
+ }));
504
+ it('with both `dataSize` and dataStream below than encodedData threshold', () => __awaiter(this, void 0, void 0, function* () {
505
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
506
+ const { message, dataStream } = yield TestDataGenerator.generateRecordsWrite({
507
+ author: alice
508
+ });
509
+ // replace the dataSize to simulate mismatch, will need to generate `recordId` and `authorization` property again
510
+ message.descriptor.dataSize = 1;
511
+ const descriptorCid = yield Cid.computeCid(message.descriptor);
512
+ const recordId = yield RecordsWrite.getEntryId(alice.did, message.descriptor);
513
+ const signer = Jws.createSigner(alice);
514
+ const signature = yield RecordsWrite.createSignerSignature({
515
+ recordId,
516
+ contextId: message.contextId,
517
+ descriptorCid,
518
+ attestation: message.attestation,
519
+ encryption: message.encryption,
520
+ signer
521
+ });
522
+ message.recordId = recordId;
523
+ message.authorization = { signature };
524
+ const reply = yield dwn.processMessage(alice.did, message, { dataStream });
525
+ expect(reply.status.code).to.equal(400);
526
+ expect(reply.status.detail).to.contain(DwnErrorCode.RecordsWriteDataSizeMismatch);
527
+ }));
528
+ });
529
+ it('should return 400 for data CID mismatch with both dataStream and `dataSize` larger than encodedData threshold', () => __awaiter(this, void 0, void 0, function* () {
530
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
531
+ const { message } = yield TestDataGenerator.generateRecordsWrite({
532
+ author: alice,
533
+ data: TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1)
534
+ });
535
+ const dataStream = DataStream.fromBytes(TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1)); // mismatch data stream
536
+ const reply = yield dwn.processMessage(alice.did, message, { dataStream });
537
+ expect(reply.status.code).to.equal(400);
538
+ expect(reply.status.detail).to.contain(DwnErrorCode.RecordsWriteDataCidMismatch);
539
+ }));
540
+ it('should return 400 for data CID mismatch with `dataSize` larger than encodedData threshold', () => __awaiter(this, void 0, void 0, function* () {
541
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
542
+ const { message } = yield TestDataGenerator.generateRecordsWrite({
543
+ author: alice,
544
+ data: TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1)
545
+ });
546
+ const dataStream = DataStream.fromBytes(TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded)); // mismatch data stream
547
+ const reply = yield dwn.processMessage(alice.did, message, { dataStream });
548
+ expect(reply.status.code).to.equal(400);
549
+ expect(reply.status.detail).to.contain(DwnErrorCode.RecordsWriteDataCidMismatch);
550
+ }));
551
+ it('should return 400 for data CID mismatch with dataStream larger than encodedData threshold', () => __awaiter(this, void 0, void 0, function* () {
552
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
553
+ const { message } = yield TestDataGenerator.generateRecordsWrite({
554
+ author: alice,
555
+ data: TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded)
556
+ });
557
+ const dataStream = DataStream.fromBytes(TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1)); // mismatch data stream
558
+ const reply = yield dwn.processMessage(alice.did, message, { dataStream });
559
+ expect(reply.status.code).to.equal(400);
560
+ expect(reply.status.detail).to.contain(DwnErrorCode.RecordsWriteDataCidMismatch);
561
+ }));
562
+ it('should return 400 for data CID mismatch with both dataStream and `dataSize` below than encodedData threshold', () => __awaiter(this, void 0, void 0, function* () {
563
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
564
+ const { message } = yield TestDataGenerator.generateRecordsWrite({
565
+ author: alice,
566
+ data: TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded)
567
+ });
568
+ const dataStream = DataStream.fromBytes(TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded)); // mismatch data stream
569
+ const reply = yield dwn.processMessage(alice.did, message, { dataStream });
570
+ expect(reply.status.code).to.equal(400);
571
+ expect(reply.status.detail).to.contain(DwnErrorCode.RecordsWriteDataCidMismatch);
572
+ }));
573
+ it('#359 - should not allow access of data by referencing a different`dataCid` in "modify" `RecordsWrite` with large data', () => __awaiter(this, void 0, void 0, function* () {
574
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
575
+ // alice writes a record
576
+ const dataString = TestDataGenerator.randomString(DwnConstant.maxDataSizeAllowedToBeEncoded + 1);
577
+ const dataSize = dataString.length;
578
+ const data = Encoder.stringToBytes(dataString);
579
+ const dataCid = yield Cid.computeDagPbCidFromBytes(data);
580
+ const write1 = yield TestDataGenerator.generateRecordsWrite({
581
+ author: alice,
582
+ data,
583
+ });
584
+ const write1Reply = yield dwn.processMessage(alice.did, write1.message, { dataStream: write1.dataStream });
585
+ expect(write1Reply.status.code).to.equal(202);
586
+ // alice writes another record (which will be modified later)
587
+ const write2 = yield TestDataGenerator.generateRecordsWrite({ author: alice });
588
+ const write2Reply = yield dwn.processMessage(alice.did, write2.message, { dataStream: write2.dataStream });
589
+ expect(write2Reply.status.code).to.equal(202);
590
+ // modify write2 by referencing the `dataCid` in write1 (which should not be allowed)
591
+ const write2Change = yield TestDataGenerator.generateRecordsWrite({
592
+ author: alice,
593
+ recipient: write2.message.descriptor.recipient,
594
+ recordId: write2.message.recordId,
595
+ dateCreated: write2.message.descriptor.dateCreated,
596
+ protocolPath: write2.message.descriptor.protocolPath,
597
+ schema: write2.message.descriptor.schema,
598
+ dataFormat: write2.message.descriptor.dataFormat,
599
+ // unauthorized reference to data in write1
600
+ dataCid,
601
+ dataSize
602
+ });
603
+ const write2ChangeReply = yield dwn.processMessage(alice.did, write2Change.message);
604
+ expect(write2ChangeReply.status.code).to.equal(400); // should be disallowed
605
+ expect(write2ChangeReply.status.detail).to.contain(DwnErrorCode.RecordsWriteDataCidMismatch);
606
+ // further sanity test to make sure the change is not written, ie. write2 still has the original data
607
+ const read = yield RecordsRead.create({
608
+ filter: {
609
+ recordId: write2.message.recordId,
610
+ },
611
+ signer: Jws.createSigner(alice)
612
+ });
613
+ const readReply = yield dwn.processMessage(alice.did, read.message);
614
+ expect(readReply.status.code).to.equal(200);
615
+ const readDataBytes = yield DataStream.toBytes(readReply.entry.data);
616
+ expect(ArrayUtility.byteArraysEqual(readDataBytes, write2.dataBytes)).to.be.true;
617
+ }));
618
+ it('#359 - should not allow access of data by referencing a different`dataCid` in "modify" `RecordsWrite`', () => __awaiter(this, void 0, void 0, function* () {
619
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
620
+ // alice writes a record
621
+ const dataString = TestDataGenerator.randomString(DwnConstant.maxDataSizeAllowedToBeEncoded);
622
+ const dataSize = dataString.length;
623
+ const data = Encoder.stringToBytes(dataString);
624
+ const dataCid = yield Cid.computeDagPbCidFromBytes(data);
625
+ const write1 = yield TestDataGenerator.generateRecordsWrite({
626
+ author: alice,
627
+ data,
628
+ });
629
+ const write1Reply = yield dwn.processMessage(alice.did, write1.message, { dataStream: write1.dataStream });
630
+ expect(write1Reply.status.code).to.equal(202);
631
+ // alice writes another record (which will be modified later)
632
+ const write2 = yield TestDataGenerator.generateRecordsWrite({ author: alice });
633
+ const write2Reply = yield dwn.processMessage(alice.did, write2.message, { dataStream: write2.dataStream });
634
+ expect(write2Reply.status.code).to.equal(202);
635
+ // modify write2 by referencing the `dataCid` in write1 (which should not be allowed)
636
+ const write2Change = yield TestDataGenerator.generateRecordsWrite({
637
+ author: alice,
638
+ recipient: write2.message.descriptor.recipient,
639
+ recordId: write2.message.recordId,
640
+ dateCreated: write2.message.descriptor.dateCreated,
641
+ protocolPath: write2.message.descriptor.protocolPath,
642
+ schema: write2.message.descriptor.schema,
643
+ dataFormat: write2.message.descriptor.dataFormat,
644
+ // unauthorized reference to data in write1
645
+ dataCid,
646
+ dataSize
647
+ });
648
+ const write2ChangeReply = yield dwn.processMessage(alice.did, write2Change.message);
649
+ expect(write2ChangeReply.status.code).to.equal(400); // should be disallowed
650
+ expect(write2ChangeReply.status.detail).to.contain(DwnErrorCode.RecordsWriteDataCidMismatch);
651
+ // further sanity test to make sure the change is not written, ie. write2 still has the original data
652
+ const read = yield RecordsRead.create({
653
+ filter: {
654
+ recordId: write2.message.recordId,
655
+ },
656
+ signer: Jws.createSigner(alice)
657
+ });
658
+ const readReply = yield dwn.processMessage(alice.did, read.message);
659
+ expect(readReply.status.code).to.equal(200);
660
+ const readDataBytes = yield DataStream.toBytes(readReply.entry.data);
661
+ expect(ArrayUtility.byteArraysEqual(readDataBytes, write2.dataBytes)).to.be.true;
662
+ }));
663
+ describe('initial write & subsequent write tests', () => {
664
+ describe('createFrom()', () => {
665
+ it('should accept a published RecordsWrite using createFrom() without specifying `data` or `datePublished`', () => __awaiter(this, void 0, void 0, function* () {
666
+ var _a;
667
+ const data = Encoder.stringToBytes('test');
668
+ const encodedData = Encoder.bytesToBase64Url(data);
669
+ // new record
670
+ const { message, author, recordsWrite, dataStream } = yield TestDataGenerator.generateRecordsWrite({
671
+ published: false,
672
+ data,
673
+ });
674
+ const tenant = author.did;
675
+ // setting up a stub DID resolver
676
+ TestStubGenerator.stubDidResolver(didResolver, [author]);
677
+ const reply = yield dwn.processMessage(tenant, message, { dataStream });
678
+ expect(reply.status.code).to.equal(202);
679
+ // changing the `published` property
680
+ const newWrite = yield RecordsWrite.createFrom({
681
+ recordsWriteMessage: recordsWrite.message,
682
+ published: true,
683
+ signer: Jws.createSigner(author)
684
+ });
685
+ const newWriteReply = yield dwn.processMessage(tenant, newWrite.message);
686
+ expect(newWriteReply.status.code).to.equal(202);
687
+ // verify the new record state can be queried
688
+ const recordsQueryMessageData = yield TestDataGenerator.generateRecordsQuery({
689
+ author,
690
+ filter: { recordId: message.recordId }
691
+ });
692
+ const recordsQueryReply = yield dwn.processMessage(tenant, recordsQueryMessageData.message);
693
+ expect(recordsQueryReply.status.code).to.equal(200);
694
+ expect((_a = recordsQueryReply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(1);
695
+ expect(recordsQueryReply.entries[0].descriptor.published).to.equal(true);
696
+ // very importantly verify the original data is still returned
697
+ expect(recordsQueryReply.entries[0].encodedData).to.equal(encodedData);
698
+ }));
699
+ it('should inherit parent published state when using createFrom() to create RecordsWrite', () => __awaiter(this, void 0, void 0, function* () {
700
+ var _a;
701
+ const { message, author, recordsWrite, dataStream } = yield TestDataGenerator.generateRecordsWrite({
702
+ published: true
703
+ });
704
+ const tenant = author.did;
705
+ // setting up a stub DID resolver
706
+ TestStubGenerator.stubDidResolver(didResolver, [author]);
707
+ const reply = yield dwn.processMessage(tenant, message, { dataStream });
708
+ expect(reply.status.code).to.equal(202);
709
+ const newData = Encoder.stringToBytes('new data');
710
+ const newWrite = yield RecordsWrite.createFrom({
711
+ recordsWriteMessage: recordsWrite.message,
712
+ data: newData,
713
+ signer: Jws.createSigner(author)
714
+ });
715
+ const newWriteReply = yield dwn.processMessage(tenant, newWrite.message, { dataStream: DataStream.fromBytes(newData) });
716
+ expect(newWriteReply.status.code).to.equal(202);
717
+ // verify the new record state can be queried
718
+ const recordsQueryMessageData = yield TestDataGenerator.generateRecordsQuery({
719
+ author,
720
+ filter: { recordId: message.recordId }
721
+ });
722
+ const recordsQueryReply = yield dwn.processMessage(tenant, recordsQueryMessageData.message);
723
+ expect(recordsQueryReply.status.code).to.equal(200);
724
+ expect((_a = recordsQueryReply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(1);
725
+ const recordsWriteReturned = recordsQueryReply.entries[0];
726
+ expect(recordsWriteReturned.encodedData).to.equal(Encoder.bytesToBase64Url(newData));
727
+ expect(recordsWriteReturned.descriptor.published).to.equal(true);
728
+ expect(recordsWriteReturned.descriptor.datePublished).to.equal(message.descriptor.datePublished);
729
+ }));
730
+ });
731
+ it('should fail with 400 if modifying a record but its initial write cannot be found in DB', () => __awaiter(this, void 0, void 0, function* () {
732
+ const recordId = yield TestDataGenerator.randomCborSha256Cid();
733
+ const { message, author, dataStream } = yield TestDataGenerator.generateRecordsWrite({
734
+ recordId,
735
+ data: Encoder.stringToBytes('anything') // simulating modification of a message
736
+ });
737
+ const tenant = author.did;
738
+ TestStubGenerator.stubDidResolver(didResolver, [author]);
739
+ const reply = yield dwn.processMessage(tenant, message, { dataStream });
740
+ expect(reply.status.code).to.equal(400);
741
+ expect(reply.status.detail).to.contain(DwnErrorCode.RecordsWriteGetInitialWriteNotFound);
742
+ }));
743
+ it('should return 400 if `dateCreated` and `messageTimestamp` are not the same in an initial write', () => __awaiter(this, void 0, void 0, function* () {
744
+ const { author, message, dataStream } = yield TestDataGenerator.generateRecordsWrite({
745
+ dateCreated: '2023-01-10T10:20:30.405060Z',
746
+ messageTimestamp: Time.getCurrentTimestamp() // this always generate a different timestamp
747
+ });
748
+ const tenant = author.did;
749
+ TestStubGenerator.stubDidResolver(didResolver, [author]);
750
+ const reply = yield dwn.processMessage(tenant, message, { dataStream });
751
+ expect(reply.status.code).to.equal(400);
752
+ expect(reply.status.detail).to.contain('must match dateCreated');
753
+ }));
754
+ it('should return 400 if `contextId` in an initial protocol-base write mismatches with the expected deterministic `contextId`', () => __awaiter(this, void 0, void 0, function* () {
755
+ // generate a message with protocol so that computed contextId is also computed and included in message
756
+ const { message, dataStream, author } = yield TestDataGenerator.generateRecordsWrite({ protocol: 'http://any.value', protocolPath: 'any/value' });
757
+ message.contextId = yield TestDataGenerator.randomCborSha256Cid(); // make contextId mismatch from computed value
758
+ TestStubGenerator.stubDidResolver(didResolver, [author]);
759
+ const reply = yield dwn.processMessage('unused-tenant-DID', message, { dataStream });
760
+ expect(reply.status.code).to.equal(400);
761
+ expect(reply.status.detail).to.contain('does not match deterministic contextId');
762
+ }));
763
+ describe('event log', () => {
764
+ it('should add an event to the event log on initial write', () => __awaiter(this, void 0, void 0, function* () {
765
+ const { message, author, dataStream } = yield TestDataGenerator.generateRecordsWrite();
766
+ TestStubGenerator.stubDidResolver(didResolver, [author]);
767
+ const reply = yield dwn.processMessage(author.did, message, { dataStream });
768
+ expect(reply.status.code).to.equal(202);
769
+ const { events } = yield eventLog.getEvents(author.did);
770
+ expect(events.length).to.equal(1);
771
+ const messageCid = yield Message.getCid(message);
772
+ expect(events[0]).to.equal(messageCid);
773
+ }));
774
+ it('should only keep first write and latest write when subsequent writes happen', () => __awaiter(this, void 0, void 0, function* () {
775
+ const { message, author, dataStream, recordsWrite } = yield TestDataGenerator.generateRecordsWrite();
776
+ TestStubGenerator.stubDidResolver(didResolver, [author]);
777
+ const reply = yield dwn.processMessage(author.did, message, { dataStream });
778
+ expect(reply.status.code).to.equal(202);
779
+ const newWrite = yield RecordsWrite.createFrom({
780
+ recordsWriteMessage: recordsWrite.message,
781
+ published: true,
782
+ signer: Jws.createSigner(author)
783
+ });
784
+ const newWriteReply = yield dwn.processMessage(author.did, newWrite.message);
785
+ expect(newWriteReply.status.code).to.equal(202);
786
+ const newestWrite = yield RecordsWrite.createFrom({
787
+ recordsWriteMessage: recordsWrite.message,
788
+ published: true,
789
+ signer: Jws.createSigner(author)
790
+ });
791
+ const newestWriteReply = yield dwn.processMessage(author.did, newestWrite.message);
792
+ expect(newestWriteReply.status.code).to.equal(202);
793
+ const { events } = yield eventLog.getEvents(author.did);
794
+ expect(events.length).to.equal(2);
795
+ const deletedMessageCid = yield Message.getCid(newWrite.message);
796
+ for (const messageCid of events) {
797
+ if (messageCid === deletedMessageCid) {
798
+ expect.fail(`${messageCid} should not exist`);
799
+ }
800
+ }
801
+ }));
802
+ });
803
+ });
804
+ describe('protocol based writes', () => {
805
+ it('should allow write with allow-anyone rule', () => __awaiter(this, void 0, void 0, function* () {
806
+ // scenario: Bob writes into Alice's DWN given Alice's "email" protocol allow-anyone rule
807
+ var _a;
808
+ // write a protocol definition with an allow-anyone rule
809
+ const protocolDefinition = emailProtocolDefinition;
810
+ const alice = yield TestDataGenerator.generatePersona();
811
+ const bob = yield TestDataGenerator.generatePersona();
812
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
813
+ author: alice,
814
+ protocolDefinition
815
+ });
816
+ // setting up a stub DID resolver
817
+ TestStubGenerator.stubDidResolver(didResolver, [alice, bob]);
818
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
819
+ expect(protocolsConfigureReply.status.code).to.equal(202);
820
+ // generate a `RecordsWrite` message from bob
821
+ const bobData = Encoder.stringToBytes('data from bob');
822
+ const emailFromBob = yield TestDataGenerator.generateRecordsWrite({
823
+ author: bob,
824
+ protocol: protocolDefinition.protocol,
825
+ protocolPath: 'email',
826
+ schema: protocolDefinition.types.email.schema,
827
+ dataFormat: protocolDefinition.types.email.dataFormats[0],
828
+ data: bobData
829
+ });
830
+ const bobWriteReply = yield dwn.processMessage(alice.did, emailFromBob.message, { dataStream: emailFromBob.dataStream });
831
+ expect(bobWriteReply.status.code).to.equal(202);
832
+ // verify bob's message got written to the DB
833
+ const messageDataForQueryingBobsWrite = yield TestDataGenerator.generateRecordsQuery({
834
+ author: alice,
835
+ filter: { recordId: emailFromBob.message.recordId }
836
+ });
837
+ const bobRecordsQueryReply = yield dwn.processMessage(alice.did, messageDataForQueryingBobsWrite.message);
838
+ expect(bobRecordsQueryReply.status.code).to.equal(200);
839
+ expect((_a = bobRecordsQueryReply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(1);
840
+ expect(bobRecordsQueryReply.entries[0].encodedData).to.equal(Encoder.bytesToBase64Url(bobData));
841
+ }));
842
+ it('should allow co-update with allow-anyone rule', () => __awaiter(this, void 0, void 0, function* () {
843
+ // scenario: Alice creates a record on her DWN, and Bob (anyone) is able to update it. Bob is not able to
844
+ // create a record.
845
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
846
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
847
+ const protocolDefinition = anyoneCollaborateProtocolDefinition;
848
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
849
+ author: alice,
850
+ protocolDefinition
851
+ });
852
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
853
+ expect(protocolsConfigureReply.status.code).to.equal(202);
854
+ // Alice creates a doc
855
+ const docRecord = yield TestDataGenerator.generateRecordsWrite({
856
+ author: alice,
857
+ recipient: alice.did,
858
+ protocol: protocolDefinition.protocol,
859
+ protocolPath: 'doc'
860
+ });
861
+ const docRecordsReply = yield dwn.processMessage(alice.did, docRecord.message, { dataStream: docRecord.dataStream });
862
+ expect(docRecordsReply.status.code).to.equal(202);
863
+ // Bob updates Alice's doc
864
+ const bobsData = yield TestDataGenerator.randomBytes(10);
865
+ const docUpdateRecord = yield TestDataGenerator.generateFromRecordsWrite({
866
+ author: bob,
867
+ existingWrite: docRecord.recordsWrite,
868
+ data: bobsData
869
+ });
870
+ const docUpdateRecordsReply = yield dwn.processMessage(alice.did, docUpdateRecord.message, { dataStream: docUpdateRecord.dataStream });
871
+ expect(docUpdateRecordsReply.status.code).to.equal(202);
872
+ // Bob tries and fails to create a new record
873
+ const bobDocRecord = yield TestDataGenerator.generateRecordsWrite({
874
+ author: bob,
875
+ recipient: bob.did,
876
+ protocol: protocolDefinition.protocol,
877
+ protocolPath: 'doc'
878
+ });
879
+ const bobDocRecordsReply = yield dwn.processMessage(alice.did, bobDocRecord.message, { dataStream: bobDocRecord.dataStream });
880
+ expect(bobDocRecordsReply.status.code).to.equal(401);
881
+ expect(bobDocRecordsReply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationActionNotAllowed);
882
+ }));
883
+ describe('recipient rules', () => {
884
+ it('should allow write with ancestor recipient rule', () => __awaiter(this, void 0, void 0, function* () {
885
+ // scenario: VC issuer writes into Alice's DWN an asynchronous credential response upon receiving Alice's credential application
886
+ // Carol tries to write a credential response but is rejected
887
+ var _a;
888
+ const protocolDefinition = credentialIssuanceProtocolDefinition;
889
+ const credentialApplicationSchema = protocolDefinition.types.credentialApplication.schema;
890
+ const credentialResponseSchema = protocolDefinition.types.credentialResponse.schema;
891
+ const alice = yield TestDataGenerator.generatePersona();
892
+ const vcIssuer = yield TestDataGenerator.generatePersona();
893
+ const carol = yield TestDataGenerator.generatePersona();
894
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
895
+ author: alice,
896
+ protocolDefinition
897
+ });
898
+ // setting up a stub DID resolver
899
+ TestStubGenerator.stubDidResolver(didResolver, [alice, vcIssuer, carol]);
900
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
901
+ expect(protocolsConfigureReply.status.code).to.equal(202);
902
+ // write a credential application to Alice's DWN to simulate that she has sent a credential application to a VC issuer
903
+ const encodedCredentialApplication = new TextEncoder().encode('credential application data');
904
+ const credentialApplication = yield TestDataGenerator.generateRecordsWrite({
905
+ author: alice,
906
+ recipient: vcIssuer.did,
907
+ protocol: protocolDefinition.protocol,
908
+ protocolPath: 'credentialApplication', // this comes from `types` in protocol definition
909
+ schema: credentialApplicationSchema,
910
+ dataFormat: protocolDefinition.types.credentialApplication.dataFormats[0],
911
+ data: encodedCredentialApplication
912
+ });
913
+ const credentialApplicationReply = yield dwn.processMessage(alice.did, credentialApplication.message, { dataStream: credentialApplication.dataStream });
914
+ expect(credentialApplicationReply.status.code).to.equal(202);
915
+ // generate a credential application response message from VC issuer
916
+ const encodedCredentialResponse = new TextEncoder().encode('credential response data');
917
+ const credentialResponse = yield TestDataGenerator.generateRecordsWrite({
918
+ author: vcIssuer,
919
+ recipient: alice.did,
920
+ protocol: protocolDefinition.protocol,
921
+ protocolPath: 'credentialApplication/credentialResponse', // this comes from `types` in protocol definition
922
+ parentContextId: credentialApplication.message.contextId,
923
+ schema: credentialResponseSchema,
924
+ dataFormat: protocolDefinition.types.credentialResponse.dataFormats[0],
925
+ data: encodedCredentialResponse
926
+ });
927
+ const credentialResponseReply = yield dwn.processMessage(alice.did, credentialResponse.message, { dataStream: credentialResponse.dataStream });
928
+ expect(credentialResponseReply.status.code).to.equal(202);
929
+ // verify VC issuer's message got written to the DB
930
+ const messageDataForQueryingCredentialResponse = yield TestDataGenerator.generateRecordsQuery({
931
+ author: alice,
932
+ filter: { recordId: credentialResponse.message.recordId }
933
+ });
934
+ const applicationResponseQueryReply = yield dwn.processMessage(alice.did, messageDataForQueryingCredentialResponse.message);
935
+ expect(applicationResponseQueryReply.status.code).to.equal(200);
936
+ expect((_a = applicationResponseQueryReply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(1);
937
+ expect(applicationResponseQueryReply.entries[0].encodedData)
938
+ .to.equal(base64url.baseEncode(encodedCredentialResponse));
939
+ }));
940
+ it('should allow co-update with ancestor recipient rule', () => __awaiter(this, void 0, void 0, function* () {
941
+ // scenario: Alice creates a post with Bob as recipient. Alice adds a `post/tag` to the post. Bob is able to update
942
+ // the `post/tag` because he is recipient of the post. Bob is not able to create a new `post/tag`.
943
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
944
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
945
+ const protocolDefinition = recipientCanProtocol;
946
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
947
+ author: alice,
948
+ protocolDefinition
949
+ });
950
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
951
+ expect(protocolsConfigureReply.status.code).to.equal(202);
952
+ // Alice creates a post with Bob as recipient
953
+ const docRecord = yield TestDataGenerator.generateRecordsWrite({
954
+ author: alice,
955
+ recipient: bob.did,
956
+ protocol: protocolDefinition.protocol,
957
+ protocolPath: 'post'
958
+ });
959
+ const docRecordsReply = yield dwn.processMessage(alice.did, docRecord.message, { dataStream: docRecord.dataStream });
960
+ expect(docRecordsReply.status.code).to.equal(202);
961
+ // Alice creates a post/tag
962
+ const tagRecord = yield TestDataGenerator.generateRecordsWrite({
963
+ author: alice,
964
+ recipient: alice.did,
965
+ protocol: protocolDefinition.protocol,
966
+ protocolPath: 'post/tag',
967
+ parentContextId: docRecord.message.contextId,
968
+ });
969
+ const tagRecordsReply = yield dwn.processMessage(alice.did, tagRecord.message, { dataStream: tagRecord.dataStream });
970
+ expect(tagRecordsReply.status.code).to.equal(202);
971
+ // Bob updates Alice's post
972
+ const bobsData = yield TestDataGenerator.randomBytes(10);
973
+ const tagUpdateRecord = yield TestDataGenerator.generateFromRecordsWrite({
974
+ author: bob,
975
+ existingWrite: tagRecord.recordsWrite,
976
+ data: bobsData
977
+ });
978
+ const tagUpdateRecordsReply = yield dwn.processMessage(alice.did, tagUpdateRecord.message, { dataStream: tagUpdateRecord.dataStream });
979
+ expect(tagUpdateRecordsReply.status.code).to.equal(202);
980
+ // Bob tries and fails to create a new record
981
+ const bobTagRecord = yield TestDataGenerator.generateRecordsWrite({
982
+ author: bob,
983
+ recipient: bob.did,
984
+ protocol: protocolDefinition.protocol,
985
+ protocolPath: 'post/tag',
986
+ parentContextId: docRecord.message.contextId,
987
+ });
988
+ const bobTagRecordsReply = yield dwn.processMessage(alice.did, bobTagRecord.message, { dataStream: bobTagRecord.dataStream });
989
+ expect(bobTagRecordsReply.status.code).to.equal(401);
990
+ expect(bobTagRecordsReply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationActionNotAllowed);
991
+ }));
992
+ it('should allow co-update with direct recipient rule', () => __awaiter(this, void 0, void 0, function* () {
993
+ // scenario:
994
+ // Alice creates a 'post' with Bob as recipient.
995
+ // Bob is able to update the 'post' because he was recipient of it.
996
+ // Carol is not able to update it.
997
+ const protocolDefinition = recipientCanProtocol;
998
+ const alice = yield TestDataGenerator.generatePersona();
999
+ const bob = yield TestDataGenerator.generatePersona();
1000
+ const carol = yield TestDataGenerator.generatePersona();
1001
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1002
+ author: alice,
1003
+ protocolDefinition
1004
+ });
1005
+ // setting up a stub DID resolver
1006
+ TestStubGenerator.stubDidResolver(didResolver, [alice, bob, carol]);
1007
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1008
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1009
+ // Alice creates a 'post' with Bob as recipient
1010
+ const recordsWrite = yield TestDataGenerator.generateRecordsWrite({
1011
+ author: alice,
1012
+ recipient: bob.did,
1013
+ protocol: protocolDefinition.protocol,
1014
+ protocolPath: 'post',
1015
+ });
1016
+ const recordsWriteReply = yield dwn.processMessage(alice.did, recordsWrite.message, { dataStream: recordsWrite.dataStream });
1017
+ expect(recordsWriteReply.status.code).to.eq(202);
1018
+ // Carol is unable to update the 'post'
1019
+ const carolRecordsWrite = yield TestDataGenerator.generateFromRecordsWrite({
1020
+ author: carol,
1021
+ existingWrite: recordsWrite.recordsWrite
1022
+ });
1023
+ const carolRecordsWriteReply = yield dwn.processMessage(alice.did, carolRecordsWrite.message);
1024
+ expect(carolRecordsWriteReply.status.code).to.eq(401);
1025
+ expect(carolRecordsWriteReply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationActionNotAllowed);
1026
+ // Bob is able to update the post
1027
+ const bobRecordsWrite = yield TestDataGenerator.generateFromRecordsWrite({
1028
+ author: bob,
1029
+ existingWrite: recordsWrite.recordsWrite,
1030
+ });
1031
+ const bobRecordsWriteReply = yield dwn.processMessage(alice.did, bobRecordsWrite.message, { dataStream: bobRecordsWrite.dataStream });
1032
+ expect(bobRecordsWriteReply.status.code).to.eq(202);
1033
+ }));
1034
+ });
1035
+ describe('author action rules', () => {
1036
+ it('allow author to write with ancestor author rule and block non-authors', () => __awaiter(this, void 0, void 0, function* () {
1037
+ var _a;
1038
+ // scenario: Alice posts an image on the social media protocol to Bob's, then she adds a caption
1039
+ // AliceImposter attempts to post add a caption to Alice's image, but is blocked
1040
+ const protocolDefinition = socialMediaProtocolDefinition;
1041
+ const alice = yield TestDataGenerator.generatePersona();
1042
+ const aliceImposter = yield TestDataGenerator.generatePersona();
1043
+ const bob = yield TestDataGenerator.generatePersona();
1044
+ // setting up a stub DID resolver
1045
+ TestStubGenerator.stubDidResolver(didResolver, [alice, aliceImposter, bob]);
1046
+ // Install social-media protocol
1047
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1048
+ author: bob,
1049
+ protocolDefinition
1050
+ });
1051
+ const protocolsConfigureReply = yield dwn.processMessage(bob.did, protocolsConfig.message);
1052
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1053
+ // Alice writes image to bob's DWN
1054
+ const encodedImage = new TextEncoder().encode('cafe-aesthetic.jpg');
1055
+ const imageRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
1056
+ author: alice,
1057
+ protocol: protocolDefinition.protocol,
1058
+ protocolPath: 'image', // this comes from `types` in protocol definition
1059
+ schema: protocolDefinition.types.image.schema,
1060
+ dataFormat: protocolDefinition.types.image.dataFormats[0],
1061
+ data: encodedImage
1062
+ });
1063
+ const imageReply = yield dwn.processMessage(bob.did, imageRecordsWrite.message, { dataStream: imageRecordsWrite.dataStream });
1064
+ expect(imageReply.status.code).to.equal(202);
1065
+ // AliceImposter attempts and fails to caption Alice's image
1066
+ const encodedCaptionImposter = new TextEncoder().encode('bad vibes! >:(');
1067
+ const captionImposter = yield TestDataGenerator.generateRecordsWrite({
1068
+ author: aliceImposter,
1069
+ protocol: protocolDefinition.protocol,
1070
+ protocolPath: 'image/caption', // this comes from `types` in protocol definition
1071
+ schema: protocolDefinition.types.caption.schema,
1072
+ dataFormat: protocolDefinition.types.caption.dataFormats[0],
1073
+ parentContextId: imageRecordsWrite.recordsWrite.message.contextId,
1074
+ data: encodedCaptionImposter
1075
+ });
1076
+ const captionReply = yield dwn.processMessage(bob.did, captionImposter.message, { dataStream: captionImposter.dataStream });
1077
+ expect(captionReply.status.code).to.equal(401);
1078
+ expect(captionReply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationActionNotAllowed);
1079
+ // Alice is able to add a caption to her image
1080
+ const encodedCaption = new TextEncoder().encode('coffee and work vibes!');
1081
+ const captionRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
1082
+ author: alice,
1083
+ protocol: protocolDefinition.protocol,
1084
+ protocolPath: 'image/caption',
1085
+ schema: protocolDefinition.types.caption.schema,
1086
+ dataFormat: protocolDefinition.types.caption.dataFormats[0],
1087
+ parentContextId: imageRecordsWrite.recordsWrite.message.contextId,
1088
+ data: encodedCaption
1089
+ });
1090
+ const captionResponse = yield dwn.processMessage(bob.did, captionRecordsWrite.message, { dataStream: captionRecordsWrite.dataStream });
1091
+ expect(captionResponse.status.code).to.equal(202);
1092
+ // Verify Alice's caption got written to the DB
1093
+ const messageDataForQueryingCaptionResponse = yield TestDataGenerator.generateRecordsQuery({
1094
+ author: alice,
1095
+ filter: { recordId: captionRecordsWrite.message.recordId }
1096
+ });
1097
+ const applicationResponseQueryReply = yield dwn.processMessage(bob.did, messageDataForQueryingCaptionResponse.message);
1098
+ expect(applicationResponseQueryReply.status.code).to.equal(200);
1099
+ expect((_a = applicationResponseQueryReply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(1);
1100
+ expect(applicationResponseQueryReply.entries[0].encodedData)
1101
+ .to.equal(base64url.baseEncode(encodedCaption));
1102
+ }));
1103
+ it('should allow co-update with ancestor author rule', () => __awaiter(this, void 0, void 0, function* () {
1104
+ // scenario: Bob authors a post on Alice's DWN. Alice adds a comment to the post. Bob is able to update the comment,
1105
+ // since he authored the post.
1106
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1107
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
1108
+ const protocolDefinition = authorCanProtocolDefinition;
1109
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1110
+ author: alice,
1111
+ protocolDefinition
1112
+ });
1113
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1114
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1115
+ // Bob creates a post
1116
+ const postRecord = yield TestDataGenerator.generateRecordsWrite({
1117
+ author: bob,
1118
+ recipient: bob.did,
1119
+ protocol: protocolDefinition.protocol,
1120
+ protocolPath: 'post'
1121
+ });
1122
+ const postRecordsReply = yield dwn.processMessage(alice.did, postRecord.message, { dataStream: postRecord.dataStream });
1123
+ expect(postRecordsReply.status.code).to.equal(202);
1124
+ // Alice creates a post/comment
1125
+ const commentRecord = yield TestDataGenerator.generateRecordsWrite({
1126
+ author: alice,
1127
+ recipient: alice.did,
1128
+ protocol: protocolDefinition.protocol,
1129
+ protocolPath: 'post/comment',
1130
+ parentContextId: postRecord.message.contextId,
1131
+ });
1132
+ const commentRecordsReply = yield dwn.processMessage(alice.did, commentRecord.message, { dataStream: commentRecord.dataStream });
1133
+ expect(commentRecordsReply.status.code).to.equal(202);
1134
+ // Bob updates Alice's comment
1135
+ const bobsData = yield TestDataGenerator.randomBytes(10);
1136
+ const postUpdateRecord = yield TestDataGenerator.generateFromRecordsWrite({
1137
+ author: alice,
1138
+ existingWrite: commentRecord.recordsWrite,
1139
+ data: bobsData
1140
+ });
1141
+ const commentUpdateRecordsReply = yield dwn.processMessage(alice.did, postUpdateRecord.message, { dataStream: postUpdateRecord.dataStream });
1142
+ expect(commentUpdateRecordsReply.status.code).to.equal(202);
1143
+ // Bob tries and fails to create a new comment
1144
+ const bobPostRecord = yield TestDataGenerator.generateRecordsWrite({
1145
+ author: bob,
1146
+ recipient: bob.did,
1147
+ protocol: protocolDefinition.protocol,
1148
+ protocolPath: 'post/comment',
1149
+ parentContextId: postRecord.message.contextId,
1150
+ });
1151
+ const bobPostRecordsReply = yield dwn.processMessage(alice.did, bobPostRecord.message, { dataStream: bobPostRecord.dataStream });
1152
+ expect(bobPostRecordsReply.status.code).to.equal(401);
1153
+ expect(bobPostRecordsReply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationActionNotAllowed);
1154
+ }));
1155
+ });
1156
+ describe('role rules', () => {
1157
+ describe('write root-level role records', () => {
1158
+ it('allows a root-level role record with unique recipient to be created and updated', () => __awaiter(this, void 0, void 0, function* () {
1159
+ // scenario: Alice adds Bob to the 'friend' role. Then she updates the 'friend' record.
1160
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1161
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
1162
+ const protocolDefinition = friendRoleProtocolDefinition;
1163
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1164
+ author: alice,
1165
+ protocolDefinition
1166
+ });
1167
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1168
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1169
+ // Alice writes a 'friend' root-level role record with Bob as recipient
1170
+ const friendRoleRecord = yield TestDataGenerator.generateRecordsWrite({
1171
+ author: alice,
1172
+ recipient: bob.did,
1173
+ protocol: protocolDefinition.protocol,
1174
+ protocolPath: 'friend',
1175
+ data: new TextEncoder().encode('Bob is my friend'),
1176
+ });
1177
+ const friendRoleReply = yield dwn.processMessage(alice.did, friendRoleRecord.message, { dataStream: friendRoleRecord.dataStream });
1178
+ expect(friendRoleReply.status.code).to.equal(202);
1179
+ // Alice updates Bob's 'friend' record
1180
+ const updateFriendRecord = yield TestDataGenerator.generateFromRecordsWrite({
1181
+ author: alice,
1182
+ existingWrite: friendRoleRecord.recordsWrite,
1183
+ });
1184
+ const updateFriendReply = yield dwn.processMessage(alice.did, updateFriendRecord.message, { dataStream: updateFriendRecord.dataStream });
1185
+ expect(updateFriendReply.status.code).to.equal(202);
1186
+ }));
1187
+ it('should reject role RecordsWrite if recipient is undefined', () => __awaiter(this, void 0, void 0, function* () {
1188
+ // scenario: Alice writes a root-level role record with no recipient and it is rejected
1189
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1190
+ const protocolDefinition = friendRoleProtocolDefinition;
1191
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1192
+ author: alice,
1193
+ protocolDefinition
1194
+ });
1195
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1196
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1197
+ // Alice writes a 'friend' root-level role record with no recipient
1198
+ const friendRoleRecord = yield TestDataGenerator.generateRecordsWrite({
1199
+ author: alice,
1200
+ protocol: protocolDefinition.protocol,
1201
+ protocolPath: 'friend',
1202
+ data: new TextEncoder().encode('Bob is my friend'),
1203
+ });
1204
+ const friendRoleReply = yield dwn.processMessage(alice.did, friendRoleRecord.message, { dataStream: friendRoleRecord.dataStream });
1205
+ expect(friendRoleReply.status.code).to.equal(400);
1206
+ expect(friendRoleReply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationRoleMissingRecipient);
1207
+ }));
1208
+ it('should allow a new root-level role record to be created for the same recipient if their old one was deleted', () => __awaiter(this, void 0, void 0, function* () {
1209
+ // scenario: Alice adds Bob to the 'friend' role, then deletes the role. Alice writes a new record adding Bob as a 'friend' again.
1210
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1211
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
1212
+ const protocolDefinition = friendRoleProtocolDefinition;
1213
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1214
+ author: alice,
1215
+ protocolDefinition
1216
+ });
1217
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1218
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1219
+ // Alice writes a 'friend' root-level role record with Bob as recipient
1220
+ const friendRoleRecord = yield TestDataGenerator.generateRecordsWrite({
1221
+ author: alice,
1222
+ recipient: bob.did,
1223
+ protocol: protocolDefinition.protocol,
1224
+ protocolPath: 'friend',
1225
+ data: new TextEncoder().encode('Bob is my friend'),
1226
+ });
1227
+ const friendRoleReply = yield dwn.processMessage(alice.did, friendRoleRecord.message, { dataStream: friendRoleRecord.dataStream });
1228
+ expect(friendRoleReply.status.code).to.equal(202);
1229
+ // Alice deletes Bob's 'friend' role record
1230
+ const deleteFriend = yield TestDataGenerator.generateRecordsDelete({
1231
+ author: alice,
1232
+ recordId: friendRoleRecord.message.recordId,
1233
+ });
1234
+ const deleteFriendReply = yield dwn.processMessage(alice.did, deleteFriend.message);
1235
+ expect(deleteFriendReply.status.code).to.equal(202);
1236
+ // Alice writes a new record adding Bob as a 'friend' again
1237
+ const duplicateFriendRecord = yield TestDataGenerator.generateRecordsWrite({
1238
+ author: alice,
1239
+ recipient: bob.did,
1240
+ protocol: protocolDefinition.protocol,
1241
+ protocolPath: 'friend',
1242
+ data: new TextEncoder().encode('Bob is still my friend'),
1243
+ });
1244
+ const duplicateFriendReply = yield dwn.processMessage(alice.did, duplicateFriendRecord.message, { dataStream: duplicateFriendRecord.dataStream });
1245
+ expect(duplicateFriendReply.status.code).to.equal(202);
1246
+ }));
1247
+ });
1248
+ describe('write context role records', () => {
1249
+ it('can authorized a create or update RecordsWrite using the invoked a context role', () => __awaiter(this, void 0, void 0, function* () {
1250
+ // scenario: Alice creates a thread and adds Bob to the 'thread/participant' role. Then she updates Bob's role record.
1251
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1252
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
1253
+ const protocolDefinition = threadRoleProtocolDefinition;
1254
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1255
+ author: alice,
1256
+ protocolDefinition
1257
+ });
1258
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1259
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1260
+ // Alice creates a thread
1261
+ const threadRecord = yield TestDataGenerator.generateRecordsWrite({
1262
+ author: alice,
1263
+ recipient: bob.did,
1264
+ protocol: protocolDefinition.protocol,
1265
+ protocolPath: 'thread'
1266
+ });
1267
+ const threadRecordReply = yield dwn.processMessage(alice.did, threadRecord.message, { dataStream: threadRecord.dataStream });
1268
+ expect(threadRecordReply.status.code).to.equal(202);
1269
+ // Alice adds Bob as a 'thread/participant' in that thread
1270
+ const participantRecord = yield TestDataGenerator.generateRecordsWrite({
1271
+ author: alice,
1272
+ recipient: bob.did,
1273
+ protocol: protocolDefinition.protocol,
1274
+ protocolPath: 'thread/participant',
1275
+ parentContextId: threadRecord.message.contextId,
1276
+ });
1277
+ const participantRecordReply = yield dwn.processMessage(alice.did, participantRecord.message, { dataStream: participantRecord.dataStream });
1278
+ expect(participantRecordReply.status.code).to.equal(202);
1279
+ // Alice updates Bob's role record
1280
+ const participantUpdateRecord = yield TestDataGenerator.generateFromRecordsWrite({
1281
+ author: alice,
1282
+ existingWrite: participantRecord.recordsWrite,
1283
+ });
1284
+ const participantUpdateRecordReply = yield dwn.processMessage(alice.did, participantUpdateRecord.message, { dataStream: participantUpdateRecord.dataStream });
1285
+ expect(participantUpdateRecordReply.status.code).to.equal(202);
1286
+ }));
1287
+ it('can create the same role under different contexts', () => __awaiter(this, void 0, void 0, function* () {
1288
+ // scenario: Alice creates a thread and adds Bob to the 'thread/participant' role. Alice repeats the steps with a new thread.
1289
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1290
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
1291
+ const protocolDefinition = threadRoleProtocolDefinition;
1292
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1293
+ author: alice,
1294
+ protocolDefinition
1295
+ });
1296
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1297
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1298
+ // Alice creates the first thread
1299
+ const threadRecord1 = yield TestDataGenerator.generateRecordsWrite({
1300
+ author: alice,
1301
+ recipient: bob.did,
1302
+ protocol: protocolDefinition.protocol,
1303
+ protocolPath: 'thread'
1304
+ });
1305
+ const threadRecordReply1 = yield dwn.processMessage(alice.did, threadRecord1.message, { dataStream: threadRecord1.dataStream });
1306
+ expect(threadRecordReply1.status.code).to.equal(202);
1307
+ // Alice adds Bob as a 'thread/participant' to the first thread
1308
+ const participantRecord1 = yield TestDataGenerator.generateRecordsWrite({
1309
+ author: alice,
1310
+ recipient: bob.did,
1311
+ protocol: protocolDefinition.protocol,
1312
+ protocolPath: 'thread/participant',
1313
+ parentContextId: threadRecord1.message.contextId,
1314
+ });
1315
+ const participantRecordReply1 = yield dwn.processMessage(alice.did, participantRecord1.message, { dataStream: participantRecord1.dataStream });
1316
+ expect(participantRecordReply1.status.code).to.equal(202);
1317
+ // Alice creates a second thread
1318
+ const threadRecord2 = yield TestDataGenerator.generateRecordsWrite({
1319
+ author: alice,
1320
+ recipient: bob.did,
1321
+ protocol: protocolDefinition.protocol,
1322
+ protocolPath: 'thread'
1323
+ });
1324
+ const threadRecordReply2 = yield dwn.processMessage(alice.did, threadRecord2.message, { dataStream: threadRecord2.dataStream });
1325
+ expect(threadRecordReply2.status.code).to.equal(202);
1326
+ // Alice adds Bob as a 'thread/participant' to the second thread
1327
+ const participantRecord2 = yield TestDataGenerator.generateRecordsWrite({
1328
+ author: alice,
1329
+ recipient: bob.did,
1330
+ protocol: protocolDefinition.protocol,
1331
+ protocolPath: 'thread/participant',
1332
+ parentContextId: threadRecord2.message.contextId,
1333
+ });
1334
+ const participantRecordReply2 = yield dwn.processMessage(alice.did, participantRecord2.message, { dataStream: participantRecord2.dataStream });
1335
+ expect(participantRecordReply2.status.code).to.equal(202);
1336
+ }));
1337
+ it('rejects writes to a $role record if there already exists one in the same context', () => __awaiter(this, void 0, void 0, function* () {
1338
+ // scenario: Alice creates a thread and adds Bob to the 'thread/participant' role. She adds Bob to the role second time and fails
1339
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1340
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
1341
+ const protocolDefinition = threadRoleProtocolDefinition;
1342
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1343
+ author: alice,
1344
+ protocolDefinition
1345
+ });
1346
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1347
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1348
+ // Alice creates the first thread
1349
+ const threadRecord = yield TestDataGenerator.generateRecordsWrite({
1350
+ author: alice,
1351
+ recipient: bob.did,
1352
+ protocol: protocolDefinition.protocol,
1353
+ protocolPath: 'thread'
1354
+ });
1355
+ const threadRecordReply = yield dwn.processMessage(alice.did, threadRecord.message, { dataStream: threadRecord.dataStream });
1356
+ expect(threadRecordReply.status.code).to.equal(202);
1357
+ // Alice adds Bob as a 'thread/participant' to the thread
1358
+ const participantRecord1 = yield TestDataGenerator.generateRecordsWrite({
1359
+ author: alice,
1360
+ recipient: bob.did,
1361
+ protocol: protocolDefinition.protocol,
1362
+ protocolPath: 'thread/participant',
1363
+ parentContextId: threadRecord.message.contextId,
1364
+ });
1365
+ const participantRecordReply1 = yield dwn.processMessage(alice.did, participantRecord1.message, { dataStream: participantRecord1.dataStream });
1366
+ expect(participantRecordReply1.status.code).to.equal(202);
1367
+ // Alice adds Bob as a 'thread/participant' again to the same thread
1368
+ const participantRecord2 = yield TestDataGenerator.generateRecordsWrite({
1369
+ author: alice,
1370
+ recipient: bob.did,
1371
+ protocol: protocolDefinition.protocol,
1372
+ protocolPath: 'thread/participant',
1373
+ parentContextId: threadRecord.message.contextId,
1374
+ });
1375
+ const participantRecordReply2 = yield dwn.processMessage(alice.did, participantRecord2.message, { dataStream: participantRecord2.dataStream });
1376
+ expect(participantRecordReply2.status.code).to.equal(400);
1377
+ expect(participantRecordReply2.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationDuplicateRoleRecipient);
1378
+ }));
1379
+ it('allows a new context role record to be created for the same recipient in the same context if their old one was deleted', () => __awaiter(this, void 0, void 0, function* () {
1380
+ // scenario: Alice creates a thread and adds Bob to the 'thread/participant' role. She deletes the role and then adds a new one.
1381
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1382
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
1383
+ const protocolDefinition = threadRoleProtocolDefinition;
1384
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1385
+ author: alice,
1386
+ protocolDefinition
1387
+ });
1388
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1389
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1390
+ // Alice creates the first thread
1391
+ const threadRecord = yield TestDataGenerator.generateRecordsWrite({
1392
+ author: alice,
1393
+ recipient: bob.did,
1394
+ protocol: protocolDefinition.protocol,
1395
+ protocolPath: 'thread'
1396
+ });
1397
+ const threadRecordReply = yield dwn.processMessage(alice.did, threadRecord.message, { dataStream: threadRecord.dataStream });
1398
+ expect(threadRecordReply.status.code).to.equal(202);
1399
+ // Alice adds Bob as a 'thread/participant' to the thread
1400
+ const participantRecord1 = yield TestDataGenerator.generateRecordsWrite({
1401
+ author: alice,
1402
+ recipient: bob.did,
1403
+ protocol: protocolDefinition.protocol,
1404
+ protocolPath: 'thread/participant',
1405
+ parentContextId: threadRecord.message.contextId,
1406
+ });
1407
+ const participantRecordReply1 = yield dwn.processMessage(alice.did, participantRecord1.message, { dataStream: participantRecord1.dataStream });
1408
+ expect(participantRecordReply1.status.code).to.equal(202);
1409
+ // Alice deletes the participant record
1410
+ const participantDelete = yield TestDataGenerator.generateRecordsDelete({
1411
+ author: alice,
1412
+ recordId: participantRecord1.message.recordId,
1413
+ });
1414
+ const participantDeleteReply = yield dwn.processMessage(alice.did, participantDelete.message);
1415
+ expect(participantDeleteReply.status.code).to.equal(202);
1416
+ // Alice creates a new 'thread/participant' record
1417
+ const participantRecord2 = yield TestDataGenerator.generateRecordsWrite({
1418
+ author: alice,
1419
+ recipient: bob.did,
1420
+ protocol: protocolDefinition.protocol,
1421
+ protocolPath: 'thread/participant',
1422
+ parentContextId: threadRecord.message.contextId,
1423
+ });
1424
+ const participantRecordReply2 = yield dwn.processMessage(alice.did, participantRecord2.message, { dataStream: participantRecord2.dataStream });
1425
+ expect(participantRecordReply2.status.code).to.equal(202);
1426
+ }));
1427
+ });
1428
+ describe('role based writes', () => {
1429
+ it('uses a root-level role to authorize a write', () => __awaiter(this, void 0, void 0, function* () {
1430
+ // scenario: Alice gives Bob a friend role. Bob invokes his
1431
+ // friend role in order to write a chat message
1432
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1433
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
1434
+ const protocolDefinition = friendRoleProtocolDefinition;
1435
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1436
+ author: alice,
1437
+ protocolDefinition
1438
+ });
1439
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1440
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1441
+ // Alice writes a 'friend' $root-level role record with Bob as recipient
1442
+ const friendRoleRecord = yield TestDataGenerator.generateRecordsWrite({
1443
+ author: alice,
1444
+ recipient: bob.did,
1445
+ protocol: protocolDefinition.protocol,
1446
+ protocolPath: 'friend',
1447
+ data: new TextEncoder().encode('Bob is my friend'),
1448
+ });
1449
+ const friendRoleReply = yield dwn.processMessage(alice.did, friendRoleRecord.message, { dataStream: friendRoleRecord.dataStream });
1450
+ expect(friendRoleReply.status.code).to.equal(202);
1451
+ // Bob writes a 'chat' record
1452
+ const chatRecord = yield TestDataGenerator.generateRecordsWrite({
1453
+ author: bob,
1454
+ recipient: alice.did,
1455
+ protocol: protocolDefinition.protocol,
1456
+ protocolPath: 'chat',
1457
+ data: new TextEncoder().encode('Bob can write this cuz he is Alices friend'),
1458
+ protocolRole: 'friend'
1459
+ });
1460
+ const chatReply = yield dwn.processMessage(alice.did, chatRecord.message, { dataStream: chatRecord.dataStream });
1461
+ expect(chatReply.status.code).to.equal(202);
1462
+ }));
1463
+ it('uses a root-level role to authorize a co-update', () => __awaiter(this, void 0, void 0, function* () {
1464
+ // scenario: Alice gives Bob a admin role. Bob invokes his
1465
+ // admin role in order to update a chat message that Alice wrote
1466
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1467
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
1468
+ const protocolDefinition = friendRoleProtocolDefinition;
1469
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1470
+ author: alice,
1471
+ protocolDefinition
1472
+ });
1473
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1474
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1475
+ // Alice writes a 'admin' root-level role record with Bob as recipient
1476
+ const friendRoleRecord = yield TestDataGenerator.generateRecordsWrite({
1477
+ author: alice,
1478
+ recipient: bob.did,
1479
+ protocol: protocolDefinition.protocol,
1480
+ protocolPath: 'admin',
1481
+ data: new TextEncoder().encode('Bob is my friend'),
1482
+ });
1483
+ const friendRoleReply = yield dwn.processMessage(alice.did, friendRoleRecord.message, { dataStream: friendRoleRecord.dataStream });
1484
+ expect(friendRoleReply.status.code).to.equal(202);
1485
+ // Alice creates a 'chat' record
1486
+ const chatRecord = yield TestDataGenerator.generateRecordsWrite({
1487
+ author: alice,
1488
+ recipient: alice.did,
1489
+ protocol: protocolDefinition.protocol,
1490
+ protocolPath: 'chat',
1491
+ data: new TextEncoder().encode('Bob can write this cuz he is Alices friend'),
1492
+ });
1493
+ const chatReply = yield dwn.processMessage(alice.did, chatRecord.message, { dataStream: chatRecord.dataStream });
1494
+ expect(chatReply.status.code).to.equal(202);
1495
+ // Bob invokes his admin role to update the 'chat' record
1496
+ const chatUpdateRecord = yield TestDataGenerator.generateFromRecordsWrite({
1497
+ author: bob,
1498
+ existingWrite: chatRecord.recordsWrite,
1499
+ protocolRole: 'admin',
1500
+ });
1501
+ const chatUpdateReply = yield dwn.processMessage(alice.did, chatUpdateRecord.message, { dataStream: chatUpdateRecord.dataStream });
1502
+ expect(chatUpdateReply.status.code).to.equal(202);
1503
+ }));
1504
+ it('rejects root-level role authorized writes if the protocolRole is not a valid protocol path to an active role record', () => __awaiter(this, void 0, void 0, function* () {
1505
+ // scenario: Bob tries to invoke the 'chat' role to write to Alice's DWN, but 'chat' is not a role.
1506
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1507
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
1508
+ const protocolDefinition = friendRoleProtocolDefinition;
1509
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1510
+ author: alice,
1511
+ protocolDefinition
1512
+ });
1513
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1514
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1515
+ // Alice writes a 'chat' record with Bob as recipient
1516
+ const chatRecord = yield TestDataGenerator.generateRecordsWrite({
1517
+ author: alice,
1518
+ recipient: bob.did,
1519
+ protocol: protocolDefinition.protocol,
1520
+ protocolPath: 'chat',
1521
+ data: new TextEncoder().encode('Blah blah blah'),
1522
+ });
1523
+ const chatReply = yield dwn.processMessage(alice.did, chatRecord.message, { dataStream: chatRecord.dataStream });
1524
+ expect(chatReply.status.code).to.equal(202);
1525
+ // Bob tries to invoke a 'chat' role but 'chat' is not a role
1526
+ const writeChatRecord = yield TestDataGenerator.generateRecordsWrite({
1527
+ author: bob,
1528
+ recipient: bob.did,
1529
+ protocol: protocolDefinition.protocol,
1530
+ protocolPath: 'chat',
1531
+ data: new TextEncoder().encode('Blah blah blah'),
1532
+ protocolRole: 'chat',
1533
+ });
1534
+ const chatReadReply = yield dwn.processMessage(alice.did, writeChatRecord.message, { dataStream: writeChatRecord.dataStream });
1535
+ expect(chatReadReply.status.code).to.equal(401);
1536
+ expect(chatReadReply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationNotARole);
1537
+ }));
1538
+ it('rejects root-level role authorized writes if there is no active role for the recipient', () => __awaiter(this, void 0, void 0, function* () {
1539
+ // scenario: Bob tries to invoke a role to write, but he has not been given one.
1540
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1541
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
1542
+ const protocolDefinition = friendRoleProtocolDefinition;
1543
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1544
+ author: alice,
1545
+ protocolDefinition
1546
+ });
1547
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1548
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1549
+ // Bob writes a 'chat' record invoking a friend role that he does not have
1550
+ const chatRecord = yield TestDataGenerator.generateRecordsWrite({
1551
+ author: bob,
1552
+ recipient: bob.did,
1553
+ protocol: protocolDefinition.protocol,
1554
+ protocolPath: 'chat',
1555
+ data: new TextEncoder().encode('Blah blah blah'),
1556
+ protocolRole: 'friend'
1557
+ });
1558
+ const chatReply = yield dwn.processMessage(alice.did, chatRecord.message, { dataStream: chatRecord.dataStream });
1559
+ expect(chatReply.status.code).to.equal(401);
1560
+ expect(chatReply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationMatchingRoleRecordNotFound);
1561
+ }));
1562
+ it('uses a context role to authorize a write', () => __awaiter(this, void 0, void 0, function* () {
1563
+ // scenario: Alice creates a thread and adds Bob to the 'thread/participant' role. Bob invokes the record to write in the thread
1564
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1565
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
1566
+ const protocolDefinition = threadRoleProtocolDefinition;
1567
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1568
+ author: alice,
1569
+ protocolDefinition
1570
+ });
1571
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1572
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1573
+ // Alice creates a thread
1574
+ const threadRecord = yield TestDataGenerator.generateRecordsWrite({
1575
+ author: alice,
1576
+ recipient: bob.did,
1577
+ protocol: protocolDefinition.protocol,
1578
+ protocolPath: 'thread'
1579
+ });
1580
+ const threadRecordReply = yield dwn.processMessage(alice.did, threadRecord.message, { dataStream: threadRecord.dataStream });
1581
+ expect(threadRecordReply.status.code).to.equal(202);
1582
+ // Alice adds Bob as a 'thread/participant' in that thread
1583
+ const participantRecord = yield TestDataGenerator.generateRecordsWrite({
1584
+ author: alice,
1585
+ recipient: bob.did,
1586
+ protocol: protocolDefinition.protocol,
1587
+ protocolPath: 'thread/participant',
1588
+ parentContextId: threadRecord.message.contextId,
1589
+ });
1590
+ const participantRecordReply = yield dwn.processMessage(alice.did, participantRecord.message, { dataStream: participantRecord.dataStream });
1591
+ expect(participantRecordReply.status.code).to.equal(202);
1592
+ // Bob invokes the role to write to the thread
1593
+ const chatRecord = yield TestDataGenerator.generateRecordsWrite({
1594
+ author: bob,
1595
+ protocol: protocolDefinition.protocol,
1596
+ protocolPath: 'thread/chat',
1597
+ parentContextId: threadRecord.message.contextId,
1598
+ protocolRole: 'thread/participant'
1599
+ });
1600
+ const chatRecordReply = yield dwn.processMessage(alice.did, chatRecord.message, { dataStream: chatRecord.dataStream });
1601
+ expect(chatRecordReply.status.code).to.equal(202);
1602
+ }));
1603
+ it('uses a context role to authorize a co-update', () => __awaiter(this, void 0, void 0, function* () {
1604
+ // scenario: Alice creates a thread and adds Bob to the 'thread/admin' role.
1605
+ // Bob invokes the record to write in the thread
1606
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1607
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
1608
+ const protocolDefinition = threadRoleProtocolDefinition;
1609
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1610
+ author: alice,
1611
+ protocolDefinition
1612
+ });
1613
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1614
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1615
+ // Alice creates a thread
1616
+ const threadRecord = yield TestDataGenerator.generateRecordsWrite({
1617
+ author: alice,
1618
+ recipient: bob.did,
1619
+ protocol: protocolDefinition.protocol,
1620
+ protocolPath: 'thread'
1621
+ });
1622
+ const threadRecordReply = yield dwn.processMessage(alice.did, threadRecord.message, { dataStream: threadRecord.dataStream });
1623
+ expect(threadRecordReply.status.code).to.equal(202);
1624
+ // Alice adds Bob as a 'thread/participant' in that thread
1625
+ const participantRecord = yield TestDataGenerator.generateRecordsWrite({
1626
+ author: alice,
1627
+ recipient: bob.did,
1628
+ protocol: protocolDefinition.protocol,
1629
+ protocolPath: 'thread/admin',
1630
+ parentContextId: threadRecord.message.contextId,
1631
+ });
1632
+ const participantRecordReply = yield dwn.processMessage(alice.did, participantRecord.message, { dataStream: participantRecord.dataStream });
1633
+ expect(participantRecordReply.status.code).to.equal(202);
1634
+ // Alice writes a chat message in the thread
1635
+ const chatRecord = yield TestDataGenerator.generateRecordsWrite({
1636
+ author: alice,
1637
+ protocol: protocolDefinition.protocol,
1638
+ protocolPath: 'thread/chat',
1639
+ parentContextId: threadRecord.message.contextId,
1640
+ });
1641
+ const chatRecordReply = yield dwn.processMessage(alice.did, chatRecord.message, { dataStream: chatRecord.dataStream });
1642
+ expect(chatRecordReply.status.code).to.equal(202);
1643
+ // Bob invokes his admin role to co-update the chat message
1644
+ const chatCoUpdateRecord = yield TestDataGenerator.generateFromRecordsWrite({
1645
+ author: bob,
1646
+ existingWrite: chatRecord.recordsWrite,
1647
+ protocolRole: 'thread/admin',
1648
+ });
1649
+ const chatUpdateRecordReply = yield dwn.processMessage(alice.did, chatCoUpdateRecord.message, { dataStream: chatCoUpdateRecord.dataStream });
1650
+ expect(chatUpdateRecordReply.status.code).to.equal(202);
1651
+ }));
1652
+ it('rejects context role authorized writes if the protocolRole is not a valid protocol path to an active role record', () => __awaiter(this, void 0, void 0, function* () {
1653
+ // scenario: Alice creates a thread and adds Bob as a participant. ALice creates another thread. Bob tries and fails to invoke his
1654
+ // contextRole to write a chat in the second thread
1655
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1656
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
1657
+ const protocolDefinition = threadRoleProtocolDefinition;
1658
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1659
+ author: alice,
1660
+ protocolDefinition
1661
+ });
1662
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1663
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1664
+ // Alice creates a thread
1665
+ const threadRecord1 = yield TestDataGenerator.generateRecordsWrite({
1666
+ author: alice,
1667
+ recipient: bob.did,
1668
+ protocol: protocolDefinition.protocol,
1669
+ protocolPath: 'thread'
1670
+ });
1671
+ const threadRecordReply1 = yield dwn.processMessage(alice.did, threadRecord1.message, { dataStream: threadRecord1.dataStream });
1672
+ expect(threadRecordReply1.status.code).to.equal(202);
1673
+ // Alice adds Bob as a 'thread/participant' in that thread
1674
+ const participantRecord = yield TestDataGenerator.generateRecordsWrite({
1675
+ author: alice,
1676
+ recipient: bob.did,
1677
+ protocol: protocolDefinition.protocol,
1678
+ protocolPath: 'thread/participant',
1679
+ parentContextId: threadRecord1.message.contextId,
1680
+ });
1681
+ const participantRecordReply = yield dwn.processMessage(alice.did, participantRecord.message, { dataStream: participantRecord.dataStream });
1682
+ expect(participantRecordReply.status.code).to.equal(202);
1683
+ // Alice creates a second thread
1684
+ const threadRecord2 = yield TestDataGenerator.generateRecordsWrite({
1685
+ author: alice,
1686
+ recipient: bob.did,
1687
+ protocol: protocolDefinition.protocol,
1688
+ protocolPath: 'thread'
1689
+ });
1690
+ const threadRecordReply2 = yield dwn.processMessage(alice.did, threadRecord2.message, { dataStream: threadRecord2.dataStream });
1691
+ expect(threadRecordReply2.status.code).to.equal(202);
1692
+ // Bob invokes his role to try to write to the second thread
1693
+ const chatRecord = yield TestDataGenerator.generateRecordsWrite({
1694
+ author: bob,
1695
+ protocol: protocolDefinition.protocol,
1696
+ protocolPath: 'thread/chat',
1697
+ parentContextId: threadRecord2.message.contextId,
1698
+ protocolRole: 'thread/participant'
1699
+ });
1700
+ const chatRecordReply = yield dwn.processMessage(alice.did, chatRecord.message, { dataStream: chatRecord.dataStream });
1701
+ expect(chatRecordReply.status.code).to.equal(401);
1702
+ expect(chatRecordReply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationMatchingRoleRecordNotFound);
1703
+ }));
1704
+ it('rejects attempts to invoke an invalid path as a protocolRole', () => __awaiter(this, void 0, void 0, function* () {
1705
+ // scenario: Bob tries to invoke 'notARealPath' as a protocolRole and fails
1706
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1707
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
1708
+ const protocolDefinition = threadRoleProtocolDefinition;
1709
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1710
+ author: alice,
1711
+ protocolDefinition
1712
+ });
1713
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1714
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1715
+ // Bob invokes a fake protocolRole to write
1716
+ const fakeRoleInvocation = yield TestDataGenerator.generateRecordsWrite({
1717
+ author: bob,
1718
+ recipient: alice.did,
1719
+ protocol: protocolDefinition.protocol,
1720
+ protocolPath: 'thread',
1721
+ protocolRole: 'notARealPath',
1722
+ });
1723
+ const fakeRoleInvocationReply = yield dwn.processMessage(alice.did, fakeRoleInvocation.message, { dataStream: fakeRoleInvocation.dataStream });
1724
+ expect(fakeRoleInvocationReply.status.code).to.equal(401);
1725
+ expect(fakeRoleInvocationReply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationNotARole);
1726
+ }));
1727
+ });
1728
+ });
1729
+ it('should allow updating records by the initial author', () => __awaiter(this, void 0, void 0, function* () {
1730
+ // scenario: Bob writes into Alice's DWN given Alice's "message" protocol allow-anyone rule, then modifies the message
1731
+ var _a, _b;
1732
+ // write a protocol definition with an allow-anyone rule
1733
+ const protocolDefinition = messageProtocolDefinition;
1734
+ const protocol = protocolDefinition.protocol;
1735
+ const alice = yield TestDataGenerator.generatePersona();
1736
+ const bob = yield TestDataGenerator.generatePersona();
1737
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1738
+ author: alice,
1739
+ protocolDefinition
1740
+ });
1741
+ // setting up a stub DID resolver
1742
+ TestStubGenerator.stubDidResolver(didResolver, [alice, bob]);
1743
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1744
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1745
+ // generate a `RecordsWrite` message from bob
1746
+ const bobData = new TextEncoder().encode('message from bob');
1747
+ const messageFromBob = yield TestDataGenerator.generateRecordsWrite({
1748
+ author: bob,
1749
+ protocol,
1750
+ protocolPath: 'message', // this comes from `types` in protocol definition
1751
+ schema: protocolDefinition.types.message.schema,
1752
+ dataFormat: protocolDefinition.types.message.dataFormats[0],
1753
+ data: bobData
1754
+ });
1755
+ const bobWriteReply = yield dwn.processMessage(alice.did, messageFromBob.message, { dataStream: messageFromBob.dataStream });
1756
+ expect(bobWriteReply.status.code).to.equal(202);
1757
+ // verify bob's message got written to the DB
1758
+ const messageDataForQueryingBobsWrite = yield TestDataGenerator.generateRecordsQuery({
1759
+ author: alice,
1760
+ filter: { recordId: messageFromBob.message.recordId }
1761
+ });
1762
+ const bobRecordsQueryReply = yield dwn.processMessage(alice.did, messageDataForQueryingBobsWrite.message);
1763
+ expect(bobRecordsQueryReply.status.code).to.equal(200);
1764
+ expect((_a = bobRecordsQueryReply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(1);
1765
+ expect(bobRecordsQueryReply.entries[0].encodedData).to.equal(base64url.baseEncode(bobData));
1766
+ // generate a new message from bob updating the existing message
1767
+ const updatedMessageBytes = Encoder.stringToBytes('updated message from bob');
1768
+ const updatedMessageFromBob = yield TestDataGenerator.generateFromRecordsWrite({
1769
+ author: bob,
1770
+ existingWrite: messageFromBob.recordsWrite,
1771
+ data: updatedMessageBytes
1772
+ });
1773
+ const newWriteReply = yield dwn.processMessage(alice.did, updatedMessageFromBob.message, { dataStream: updatedMessageFromBob.dataStream });
1774
+ expect(newWriteReply.status.code).to.equal(202);
1775
+ // verify bob's message got written to the DB
1776
+ const newRecordQueryReply = yield dwn.processMessage(alice.did, messageDataForQueryingBobsWrite.message);
1777
+ expect(newRecordQueryReply.status.code).to.equal(200);
1778
+ expect((_b = newRecordQueryReply.entries) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
1779
+ expect(newRecordQueryReply.entries[0].encodedData).to.equal(Encoder.bytesToBase64Url(updatedMessageBytes));
1780
+ }));
1781
+ it('should disallow overwriting existing records by a different author if author is not authorized to `co-update`', () => __awaiter(this, void 0, void 0, function* () {
1782
+ // scenario: Bob writes into Alice's DWN given Alice's "message" protocol, Carol then attempts to modify the existing message
1783
+ var _a;
1784
+ // write a protocol definition with an allow-anyone rule
1785
+ const protocolDefinition = messageProtocolDefinition;
1786
+ const protocol = protocolDefinition.protocol;
1787
+ const alice = yield TestDataGenerator.generatePersona();
1788
+ const bob = yield TestDataGenerator.generatePersona();
1789
+ const carol = yield TestDataGenerator.generatePersona();
1790
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1791
+ author: alice,
1792
+ protocolDefinition
1793
+ });
1794
+ // setting up a stub DID resolver
1795
+ TestStubGenerator.stubDidResolver(didResolver, [alice, bob, carol]);
1796
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1797
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1798
+ // generate a `RecordsWrite` message from bob
1799
+ const bobData = new TextEncoder().encode('data from bob');
1800
+ const messageFromBob = yield TestDataGenerator.generateRecordsWrite({
1801
+ author: bob,
1802
+ protocol,
1803
+ protocolPath: 'message', // this comes from `types` in protocol definition
1804
+ schema: protocolDefinition.types.message.schema,
1805
+ dataFormat: protocolDefinition.types.message.dataFormats[0],
1806
+ data: bobData
1807
+ });
1808
+ const bobWriteReply = yield dwn.processMessage(alice.did, messageFromBob.message, { dataStream: messageFromBob.dataStream });
1809
+ expect(bobWriteReply.status.code).to.equal(202);
1810
+ // verify bob's message got written to the DB
1811
+ const messageDataForQueryingBobsWrite = yield TestDataGenerator.generateRecordsQuery({
1812
+ author: alice,
1813
+ filter: { recordId: messageFromBob.message.recordId }
1814
+ });
1815
+ const bobRecordsQueryReply = yield dwn.processMessage(alice.did, messageDataForQueryingBobsWrite.message);
1816
+ expect(bobRecordsQueryReply.status.code).to.equal(200);
1817
+ expect((_a = bobRecordsQueryReply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(1);
1818
+ expect(bobRecordsQueryReply.entries[0].encodedData).to.equal(base64url.baseEncode(bobData));
1819
+ // generate a new message from carol updating the existing message, which should not be allowed/accepted
1820
+ const modifiedMessageData = new TextEncoder().encode('modified message by carol');
1821
+ const modifiedMessageFromCarol = yield TestDataGenerator.generateRecordsWrite({
1822
+ author: carol,
1823
+ protocol,
1824
+ protocolPath: 'message', // this comes from `types` in protocol definition
1825
+ schema: protocolDefinition.types.message.schema,
1826
+ dataFormat: protocolDefinition.types.message.dataFormats[0],
1827
+ data: modifiedMessageData,
1828
+ recordId: messageFromBob.message.recordId,
1829
+ });
1830
+ const carolWriteReply = yield dwn.processMessage(alice.did, modifiedMessageFromCarol.message, { dataStream: modifiedMessageFromCarol.dataStream });
1831
+ expect(carolWriteReply.status.code).to.equal(401);
1832
+ expect(carolWriteReply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationActionNotAllowed);
1833
+ }));
1834
+ it('should not allow to change immutable recipient', () => __awaiter(this, void 0, void 0, function* () {
1835
+ // scenario: Bob writes into Alice's DWN given Alice's "message" protocol allow-anyone rule, then tries to modify immutable recipient
1836
+ var _a;
1837
+ // NOTE: no need to test the same for parent, protocol, and contextId
1838
+ // because changing them will result in other error conditions
1839
+ // write a protocol definition with an allow-anyone rule
1840
+ const protocolDefinition = messageProtocolDefinition;
1841
+ const protocol = protocolDefinition.protocol;
1842
+ const alice = yield TestDataGenerator.generatePersona();
1843
+ const bob = yield TestDataGenerator.generatePersona();
1844
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1845
+ author: alice,
1846
+ protocolDefinition
1847
+ });
1848
+ // setting up a stub DID resolver
1849
+ TestStubGenerator.stubDidResolver(didResolver, [alice, bob]);
1850
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1851
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1852
+ // generate a `RecordsWrite` message from bob
1853
+ const bobData = new TextEncoder().encode('message from bob');
1854
+ const messageFromBob = yield TestDataGenerator.generateRecordsWrite({
1855
+ author: bob,
1856
+ protocol,
1857
+ protocolPath: 'message', // this comes from `types` in protocol definition
1858
+ schema: protocolDefinition.types.message.schema,
1859
+ dataFormat: protocolDefinition.types.message.dataFormats[0],
1860
+ data: bobData
1861
+ });
1862
+ const bobWriteReply = yield dwn.processMessage(alice.did, messageFromBob.message, { dataStream: messageFromBob.dataStream });
1863
+ expect(bobWriteReply.status.code).to.equal(202);
1864
+ // verify bob's message got written to the DB
1865
+ const messageDataForQueryingBobsWrite = yield TestDataGenerator.generateRecordsQuery({
1866
+ author: alice,
1867
+ filter: { recordId: messageFromBob.message.recordId }
1868
+ });
1869
+ const bobRecordsQueryReply = yield dwn.processMessage(alice.did, messageDataForQueryingBobsWrite.message);
1870
+ expect(bobRecordsQueryReply.status.code).to.equal(200);
1871
+ expect((_a = bobRecordsQueryReply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(1);
1872
+ expect(bobRecordsQueryReply.entries[0].encodedData).to.equal(base64url.baseEncode(bobData));
1873
+ // generate a new message from bob changing immutable recipient
1874
+ const updatedMessageFromBob = yield TestDataGenerator.generateRecordsWrite({
1875
+ author: bob,
1876
+ dateCreated: messageFromBob.message.descriptor.dateCreated,
1877
+ protocol,
1878
+ protocolPath: 'message', // this comes from `types` in protocol definition
1879
+ schema: protocolDefinition.types.message.schema,
1880
+ dataFormat: protocolDefinition.types.message.dataFormats[0],
1881
+ data: bobData,
1882
+ recordId: messageFromBob.message.recordId,
1883
+ recipient: bob.did // this immutable property was Alice's DID initially
1884
+ });
1885
+ const newWriteReply = yield dwn.processMessage(alice.did, updatedMessageFromBob.message, { dataStream: updatedMessageFromBob.dataStream });
1886
+ expect(newWriteReply.status.code).to.equal(400);
1887
+ expect(newWriteReply.status.detail).to.contain('recipient is an immutable property');
1888
+ }));
1889
+ it('should block unauthorized write with recipient rule', () => __awaiter(this, void 0, void 0, function* () {
1890
+ // scenario: fake VC issuer attempts write into Alice's DWN a credential response
1891
+ // upon learning the ID of Alice's credential application to actual issuer
1892
+ const protocolDefinition = credentialIssuanceProtocolDefinition;
1893
+ const protocol = protocolDefinition.protocol;
1894
+ const credentialApplicationSchema = protocolDefinition.types.credentialApplication.schema;
1895
+ const credentialResponseSchema = protocolDefinition.types.credentialResponse.schema;
1896
+ const alice = yield TestDataGenerator.generatePersona();
1897
+ const fakeVcIssuer = yield TestDataGenerator.generatePersona();
1898
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
1899
+ author: alice,
1900
+ protocolDefinition
1901
+ });
1902
+ // setting up a stub DID resolver
1903
+ TestStubGenerator.stubDidResolver(didResolver, [alice, fakeVcIssuer]);
1904
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
1905
+ expect(protocolsConfigureReply.status.code).to.equal(202);
1906
+ // write a credential application to Alice's DWN to simulate that she has sent a credential application to a VC issuer
1907
+ const vcIssuer = yield TestDataGenerator.generatePersona();
1908
+ const encodedCredentialApplication = new TextEncoder().encode('credential application data');
1909
+ const credentialApplication = yield TestDataGenerator.generateRecordsWrite({
1910
+ author: alice,
1911
+ recipient: vcIssuer.did,
1912
+ protocol,
1913
+ protocolPath: 'credentialApplication', // this comes from `types` in protocol definition
1914
+ schema: credentialApplicationSchema,
1915
+ dataFormat: protocolDefinition.types.credentialApplication.dataFormats[0],
1916
+ data: encodedCredentialApplication
1917
+ });
1918
+ const credentialApplicationContextId = yield credentialApplication.recordsWrite.getEntryId();
1919
+ const credentialApplicationReply = yield dwn.processMessage(alice.did, credentialApplication.message, { dataStream: credentialApplication.dataStream });
1920
+ expect(credentialApplicationReply.status.code).to.equal(202);
1921
+ // generate a credential application response message from a fake VC issuer
1922
+ const encodedCredentialResponse = new TextEncoder().encode('credential response data');
1923
+ const credentialResponse = yield TestDataGenerator.generateRecordsWrite({
1924
+ author: fakeVcIssuer,
1925
+ recipient: alice.did,
1926
+ protocol,
1927
+ protocolPath: 'credentialApplication/credentialResponse', // this comes from `types` in protocol definition
1928
+ parentContextId: credentialApplicationContextId,
1929
+ schema: credentialResponseSchema,
1930
+ dataFormat: protocolDefinition.types.credentialResponse.dataFormats[0],
1931
+ data: encodedCredentialResponse
1932
+ });
1933
+ const credentialResponseReply = yield dwn.processMessage(alice.did, credentialResponse.message, { dataStream: credentialResponse.dataStream });
1934
+ expect(credentialResponseReply.status.code).to.equal(401);
1935
+ expect(credentialResponseReply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationActionNotAllowed);
1936
+ }));
1937
+ it('should fail authorization if protocol definition cannot be found for a protocol-based RecordsWrite', () => __awaiter(this, void 0, void 0, function* () {
1938
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1939
+ const protocol = 'nonExistentProtocol';
1940
+ const data = Encoder.stringToBytes('any data');
1941
+ const credentialApplication = yield TestDataGenerator.generateRecordsWrite({
1942
+ author: alice,
1943
+ recipient: alice.did,
1944
+ protocol,
1945
+ protocolPath: 'credentialApplication/credentialResponse', // this comes from `types` in protocol definition
1946
+ data
1947
+ });
1948
+ const reply = yield dwn.processMessage(alice.did, credentialApplication.message, { dataStream: credentialApplication.dataStream });
1949
+ expect(reply.status.code).to.equal(400);
1950
+ expect(reply.status.detail).to.contain('unable to find protocol definition');
1951
+ }));
1952
+ it('should fail authorization if record schema is incorrect for a protocol-based RecordsWrite', () => __awaiter(this, void 0, void 0, function* () {
1953
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1954
+ const protocolDefinition = credentialIssuanceProtocolDefinition;
1955
+ const protocol = protocolDefinition.protocol;
1956
+ const protocolConfig = yield TestDataGenerator.generateProtocolsConfigure({
1957
+ author: alice,
1958
+ protocolDefinition
1959
+ });
1960
+ const protocolConfigureReply = yield dwn.processMessage(alice.did, protocolConfig.message);
1961
+ expect(protocolConfigureReply.status.code).to.equal(202);
1962
+ const data = Encoder.stringToBytes('any data');
1963
+ const credentialApplication = yield TestDataGenerator.generateRecordsWrite({
1964
+ author: alice,
1965
+ recipient: alice.did,
1966
+ protocol,
1967
+ protocolPath: 'credentialApplication', // this comes from `types` in protocol definition
1968
+ schema: 'unexpectedSchema',
1969
+ data
1970
+ });
1971
+ const reply = yield dwn.processMessage(alice.did, credentialApplication.message, { dataStream: credentialApplication.dataStream });
1972
+ expect(reply.status.code).to.equal(400);
1973
+ expect(reply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationInvalidSchema);
1974
+ }));
1975
+ it('should fail authorization if given `protocolPath` contains an invalid record type', () => __awaiter(this, void 0, void 0, function* () {
1976
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1977
+ const protocolDefinition = credentialIssuanceProtocolDefinition;
1978
+ const protocol = protocolDefinition.protocol;
1979
+ const protocolConfig = yield TestDataGenerator.generateProtocolsConfigure({
1980
+ author: alice,
1981
+ protocolDefinition
1982
+ });
1983
+ const protocolConfigureReply = yield dwn.processMessage(alice.did, protocolConfig.message);
1984
+ expect(protocolConfigureReply.status.code).to.equal(202);
1985
+ const data = Encoder.stringToBytes('any data');
1986
+ const credentialApplication = yield TestDataGenerator.generateRecordsWrite({
1987
+ author: alice,
1988
+ recipient: alice.did,
1989
+ protocol,
1990
+ protocolPath: 'invalidType',
1991
+ data
1992
+ });
1993
+ const reply = yield dwn.processMessage(alice.did, credentialApplication.message, { dataStream: credentialApplication.dataStream });
1994
+ expect(reply.status.code).to.equal(400);
1995
+ expect(reply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationInvalidType);
1996
+ }));
1997
+ it('should fail authorization if given `protocolPath` is mismatching with actual path', () => __awaiter(this, void 0, void 0, function* () {
1998
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
1999
+ const protocolDefinition = credentialIssuanceProtocolDefinition;
2000
+ const protocol = protocolDefinition.protocol;
2001
+ const protocolConfig = yield TestDataGenerator.generateProtocolsConfigure({
2002
+ author: alice,
2003
+ protocolDefinition,
2004
+ });
2005
+ const protocolConfigureReply = yield dwn.processMessage(alice.did, protocolConfig.message);
2006
+ expect(protocolConfigureReply.status.code).to.equal(202);
2007
+ const data = Encoder.stringToBytes('any data');
2008
+ const credentialApplication = yield TestDataGenerator.generateRecordsWrite({
2009
+ author: alice,
2010
+ recipient: alice.did,
2011
+ protocol,
2012
+ protocolPath: 'credentialApplication/credentialResponse', // incorrect path. correct path is `credentialResponse` because this record has no parent
2013
+ schema: protocolDefinition.types.credentialResponse.schema,
2014
+ data
2015
+ });
2016
+ const reply = yield dwn.processMessage(alice.did, credentialApplication.message, { dataStream: credentialApplication.dataStream });
2017
+ expect(reply.status.code).to.equal(400);
2018
+ expect(reply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationParentlessIncorrectProtocolPath);
2019
+ expect(reply.status.detail).to.contain('is not valid for records with no parent');
2020
+ }));
2021
+ it('#690 - should only allow data format of a protocol-space record to be updated to any value allowed by the protocol configuration', () => __awaiter(this, void 0, void 0, function* () {
2022
+ var _a;
2023
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
2024
+ const protocolDefinition = socialMediaProtocolDefinition;
2025
+ const protocol = protocolDefinition.protocol;
2026
+ const protocolConfig = yield TestDataGenerator.generateProtocolsConfigure({
2027
+ author: alice,
2028
+ protocolDefinition: protocolDefinition,
2029
+ });
2030
+ const protocolConfigureReply = yield dwn.processMessage(alice.did, protocolConfig.message);
2031
+ expect(protocolConfigureReply.status.code).to.equal(202);
2032
+ // write image record
2033
+ const data = TestDataGenerator.randomBytes(100);
2034
+ const imageRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
2035
+ author: alice,
2036
+ recipient: alice.did,
2037
+ protocol,
2038
+ protocolPath: 'image',
2039
+ schema: protocolDefinition.types.image.schema,
2040
+ dataFormat: protocolDefinition.types.image.dataFormats[0],
2041
+ data
2042
+ });
2043
+ const writeReply = yield dwn.processMessage(alice.did, imageRecordsWrite.message, { dataStream: imageRecordsWrite.dataStream });
2044
+ expect(writeReply.status.code).to.equal(202);
2045
+ // update the image to a not-allowed data format
2046
+ const newDataBytes = TestDataGenerator.randomBytes(100);
2047
+ const notAllowedUpdateWrite = yield RecordsWrite.createFrom({
2048
+ recordsWriteMessage: imageRecordsWrite.message,
2049
+ dataFormat: `not-allowed-data-format`,
2050
+ signer: Jws.createSigner(alice),
2051
+ data: newDataBytes
2052
+ });
2053
+ const newDataStream = DataStream.fromBytes(newDataBytes);
2054
+ const notAllowedUpdateWriteReply = yield dwn.processMessage(alice.did, notAllowedUpdateWrite.message, { dataStream: newDataStream });
2055
+ expect(notAllowedUpdateWriteReply.status.code).to.equal(400);
2056
+ expect(notAllowedUpdateWriteReply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationIncorrectDataFormat);
2057
+ // update the image to a different allowed dataFormat
2058
+ const updateWrite = yield RecordsWrite.createFrom({
2059
+ recordsWriteMessage: imageRecordsWrite.message,
2060
+ dataFormat: protocolDefinition.types.image.dataFormats[1],
2061
+ signer: Jws.createSigner(alice),
2062
+ data: newDataBytes
2063
+ });
2064
+ const updateReply = yield dwn.processMessage(alice.did, updateWrite.message, { dataStream: newDataStream });
2065
+ expect(updateReply.status.code).to.equal(202);
2066
+ // verify the data format of the record is updated
2067
+ const recordsRead = yield RecordsRead.create({
2068
+ filter: { recordId: imageRecordsWrite.message.recordId },
2069
+ signer: Jws.createSigner(alice),
2070
+ });
2071
+ const recordsReadReply = yield dwn.processMessage(alice.did, recordsRead.message);
2072
+ expect(recordsReadReply.status.code).to.equal(200);
2073
+ expect((_a = recordsReadReply.entry.recordsWrite) === null || _a === void 0 ? void 0 : _a.descriptor.dataFormat).to.equal(protocolDefinition.types.image.dataFormats[1]);
2074
+ }));
2075
+ it('#690 - should allow any data format for a record if protocol definition does not explicitly specify the list of allowed data formats', () => __awaiter(this, void 0, void 0, function* () {
2076
+ var _a;
2077
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
2078
+ const protocolDefinition = minimalProtocolDefinition;
2079
+ const protocol = protocolDefinition.protocol;
2080
+ const protocolConfig = yield TestDataGenerator.generateProtocolsConfigure({
2081
+ author: alice,
2082
+ protocolDefinition: protocolDefinition,
2083
+ });
2084
+ const protocolConfigureReply = yield dwn.processMessage(alice.did, protocolConfig.message);
2085
+ expect(protocolConfigureReply.status.code).to.equal(202);
2086
+ // write image record
2087
+ const data = TestDataGenerator.randomBytes(100);
2088
+ const imageRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
2089
+ author: alice,
2090
+ recipient: alice.did,
2091
+ protocol,
2092
+ protocolPath: 'foo',
2093
+ schema: 'any-schema',
2094
+ dataFormat: 'any-data-format',
2095
+ data
2096
+ });
2097
+ const writeReply = yield dwn.processMessage(alice.did, imageRecordsWrite.message, { dataStream: imageRecordsWrite.dataStream });
2098
+ expect(writeReply.status.code).to.equal(202);
2099
+ // update the image to a different data format
2100
+ const newDataFormat = 'any-new-data-format';
2101
+ const newDataBytes = TestDataGenerator.randomBytes(100);
2102
+ const updateWrite = yield RecordsWrite.createFrom({
2103
+ recordsWriteMessage: imageRecordsWrite.message,
2104
+ dataFormat: newDataFormat,
2105
+ signer: Jws.createSigner(alice),
2106
+ data: newDataBytes
2107
+ });
2108
+ const newDataStream = DataStream.fromBytes(newDataBytes);
2109
+ const updateReply = yield dwn.processMessage(alice.did, updateWrite.message, { dataStream: newDataStream });
2110
+ expect(updateReply.status.code).to.equal(202);
2111
+ // verify the data format of the record is updated
2112
+ const recordsRead = yield RecordsRead.create({
2113
+ filter: { recordId: imageRecordsWrite.message.recordId },
2114
+ signer: Jws.createSigner(alice),
2115
+ });
2116
+ const recordsReadReply = yield dwn.processMessage(alice.did, recordsRead.message);
2117
+ expect(recordsReadReply.status.code).to.equal(200);
2118
+ expect((_a = recordsReadReply.entry.recordsWrite) === null || _a === void 0 ? void 0 : _a.descriptor.dataFormat).to.equal(newDataFormat);
2119
+ }));
2120
+ it('should fail authorization if record schema is not allowed at the hierarchical level attempted for the RecordsWrite', () => __awaiter(this, void 0, void 0, function* () {
2121
+ // scenario: Attempt writing of records at 3 levels in the hierarchy to cover all possible cases of missing rule sets
2122
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
2123
+ const protocolDefinition = credentialIssuanceProtocolDefinition;
2124
+ const protocol = protocolDefinition.protocol;
2125
+ const protocolConfig = yield TestDataGenerator.generateProtocolsConfigure({
2126
+ author: alice,
2127
+ protocolDefinition
2128
+ });
2129
+ const credentialApplicationSchema = protocolDefinition.types.credentialApplication.schema;
2130
+ const credentialResponseSchema = protocolDefinition.types.credentialResponse.schema;
2131
+ const protocolConfigureReply = yield dwn.processMessage(alice.did, protocolConfig.message);
2132
+ expect(protocolConfigureReply.status.code).to.equal(202);
2133
+ // Try and fail to write a 'credentialResponse', which is not allowed at the top level of the record hierarchy
2134
+ const data = Encoder.stringToBytes('any data');
2135
+ const failedCredentialResponse = yield TestDataGenerator.generateRecordsWrite({
2136
+ author: alice,
2137
+ recipient: alice.did,
2138
+ protocol,
2139
+ protocolPath: 'credentialResponse',
2140
+ schema: credentialResponseSchema, // this is a known schema type, but not allowed for a protocol root record
2141
+ data
2142
+ });
2143
+ const failedCredentialResponseReply = yield dwn.processMessage(alice.did, failedCredentialResponse.message, { dataStream: failedCredentialResponse.dataStream });
2144
+ expect(failedCredentialResponseReply.status.code).to.equal(400);
2145
+ expect(failedCredentialResponseReply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationMissingRuleSet);
2146
+ // Successfully write a 'credentialApplication' at the top level of the of the record hierarchy
2147
+ const credentialApplication = yield TestDataGenerator.generateRecordsWrite({
2148
+ author: alice,
2149
+ recipient: alice.did,
2150
+ protocol,
2151
+ protocolPath: 'credentialApplication', // allowed at root level
2152
+ schema: credentialApplicationSchema,
2153
+ data
2154
+ });
2155
+ const credentialApplicationReply = yield dwn.processMessage(alice.did, credentialApplication.message, { dataStream: credentialApplication.dataStream });
2156
+ expect(credentialApplicationReply.status.code).to.equal(202);
2157
+ // Try and fail to write another 'credentialApplication' below the first 'credentialApplication'
2158
+ const failedCredentialApplication = yield TestDataGenerator.generateRecordsWrite({
2159
+ author: alice,
2160
+ recipient: alice.did,
2161
+ protocol,
2162
+ protocolPath: 'credentialApplication/credentialApplication', // credentialApplications may not be nested below another credentialApplication
2163
+ schema: credentialApplicationSchema,
2164
+ parentContextId: credentialApplication.message.contextId,
2165
+ data
2166
+ });
2167
+ const failedCredentialApplicationReply2 = yield dwn.processMessage(alice.did, failedCredentialApplication.message, { dataStream: failedCredentialApplication.dataStream });
2168
+ expect(failedCredentialApplicationReply2.status.code).to.equal(400);
2169
+ expect(failedCredentialApplicationReply2.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationMissingRuleSet);
2170
+ // Successfully write a 'credentialResponse' below the 'credentialApplication'
2171
+ const credentialResponse = yield TestDataGenerator.generateRecordsWrite({
2172
+ author: alice,
2173
+ recipient: alice.did,
2174
+ protocol,
2175
+ protocolPath: 'credentialApplication/credentialResponse',
2176
+ schema: credentialResponseSchema,
2177
+ parentContextId: credentialApplication.message.contextId,
2178
+ data
2179
+ });
2180
+ const credentialResponseReply = yield dwn.processMessage(alice.did, credentialResponse.message, { dataStream: credentialResponse.dataStream });
2181
+ expect(credentialResponseReply.status.code).to.equal(202);
2182
+ // Try and fail to write a 'credentialApplication' below 'credentialApplication/credentialResponse'
2183
+ // Testing case where there is no rule set for any record type at the given level in the hierarchy
2184
+ const nestedCredentialApplication = yield TestDataGenerator.generateRecordsWrite({
2185
+ author: alice,
2186
+ recipient: alice.did,
2187
+ protocol,
2188
+ protocolPath: 'credentialApplication/credentialResponse/credentialApplication',
2189
+ schema: credentialApplicationSchema,
2190
+ parentContextId: credentialResponse.message.contextId,
2191
+ data
2192
+ });
2193
+ const nestedCredentialApplicationReply = yield dwn.processMessage(alice.did, nestedCredentialApplication.message, { dataStream: nestedCredentialApplication.dataStream });
2194
+ expect(nestedCredentialApplicationReply.status.code).to.equal(400);
2195
+ expect(nestedCredentialApplicationReply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationMissingRuleSet);
2196
+ }));
2197
+ it('should only allow DWN owner to write if record does not have an action rule defined', () => __awaiter(this, void 0, void 0, function* () {
2198
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
2199
+ // write a protocol definition without an explicit action rule
2200
+ const protocolDefinition = privateProtocol;
2201
+ const protocol = protocolDefinition.protocol;
2202
+ const protocolConfig = yield TestDataGenerator.generateProtocolsConfigure({
2203
+ author: alice,
2204
+ protocolDefinition
2205
+ });
2206
+ const protocolConfigureReply = yield dwn.processMessage(alice.did, protocolConfig.message);
2207
+ expect(protocolConfigureReply.status.code).to.equal(202);
2208
+ // test that Alice is allowed to write to her own DWN
2209
+ const data = Encoder.stringToBytes('any data');
2210
+ const aliceWriteMessageData = yield TestDataGenerator.generateRecordsWrite({
2211
+ author: alice,
2212
+ recipient: alice.did,
2213
+ protocol,
2214
+ protocolPath: 'privateNote', // this comes from `types`
2215
+ schema: protocolDefinition.types.privateNote.schema,
2216
+ dataFormat: protocolDefinition.types.privateNote.dataFormats[0],
2217
+ data
2218
+ });
2219
+ let reply = yield dwn.processMessage(alice.did, aliceWriteMessageData.message, { dataStream: aliceWriteMessageData.dataStream });
2220
+ expect(reply.status.code).to.equal(202);
2221
+ // test that Bob is not allowed to write to Alice's DWN
2222
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
2223
+ const bobWriteMessageData = yield TestDataGenerator.generateRecordsWrite({
2224
+ author: bob,
2225
+ recipient: alice.did,
2226
+ protocol,
2227
+ protocolPath: 'privateNote', // this comes from `types`
2228
+ schema: 'private-note',
2229
+ dataFormat: protocolDefinition.types.privateNote.dataFormats[0],
2230
+ data
2231
+ });
2232
+ reply = yield dwn.processMessage(alice.did, bobWriteMessageData.message, { dataStream: bobWriteMessageData.dataStream });
2233
+ expect(reply.status.code).to.equal(401);
2234
+ expect(reply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationActionRulesNotFound);
2235
+ }));
2236
+ it('should look up recipient path with ancestor depth of 2+ (excluding self) in action rule correctly', () => __awaiter(this, void 0, void 0, function* () {
2237
+ // simulate a DEX protocol with at least 3 layers of message exchange: ask -> offer -> fulfillment
2238
+ // make sure recipient of offer can send fulfillment
2239
+ var _a;
2240
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
2241
+ const pfi = yield TestDataGenerator.generateDidKeyPersona();
2242
+ // write a DEX protocol definition
2243
+ const protocolDefinition = dexProtocolDefinition;
2244
+ const protocol = protocolDefinition.protocol;
2245
+ // write the DEX protocol in the PFI
2246
+ const protocolConfig = yield TestDataGenerator.generateProtocolsConfigure({
2247
+ author: pfi,
2248
+ protocolDefinition: protocolDefinition
2249
+ });
2250
+ const protocolConfigureReply = yield dwn.processMessage(pfi.did, protocolConfig.message);
2251
+ expect(protocolConfigureReply.status.code).to.equal(202);
2252
+ // simulate Alice's ask and PFI's offer already occurred
2253
+ const data = Encoder.stringToBytes('irrelevant');
2254
+ const askMessageData = yield TestDataGenerator.generateRecordsWrite({
2255
+ author: alice,
2256
+ recipient: pfi.did,
2257
+ schema: protocolDefinition.types.ask.schema,
2258
+ protocol,
2259
+ protocolPath: 'ask',
2260
+ data
2261
+ });
2262
+ let reply = yield dwn.processMessage(pfi.did, askMessageData.message, { dataStream: askMessageData.dataStream });
2263
+ expect(reply.status.code).to.equal(202);
2264
+ const offerMessageData = yield TestDataGenerator.generateRecordsWrite({
2265
+ author: pfi,
2266
+ recipient: alice.did,
2267
+ schema: protocolDefinition.types.offer.schema,
2268
+ parentContextId: askMessageData.message.contextId,
2269
+ protocol,
2270
+ protocolPath: 'ask/offer',
2271
+ data
2272
+ });
2273
+ reply = yield dwn.processMessage(pfi.did, offerMessageData.message, { dataStream: offerMessageData.dataStream });
2274
+ expect(reply.status.code).to.equal(202);
2275
+ // the actual test: making sure fulfillment message is accepted
2276
+ const fulfillmentMessageData = yield TestDataGenerator.generateRecordsWrite({
2277
+ author: alice,
2278
+ recipient: pfi.did,
2279
+ schema: protocolDefinition.types.fulfillment.schema,
2280
+ parentContextId: offerMessageData.message.contextId,
2281
+ protocol,
2282
+ protocolPath: 'ask/offer/fulfillment',
2283
+ data
2284
+ });
2285
+ reply = yield dwn.processMessage(pfi.did, fulfillmentMessageData.message, { dataStream: fulfillmentMessageData.dataStream });
2286
+ expect(reply.status.code).to.equal(202);
2287
+ // verify the fulfillment message is stored
2288
+ const recordsQueryMessageData = yield TestDataGenerator.generateRecordsQuery({
2289
+ author: pfi,
2290
+ filter: { recordId: fulfillmentMessageData.message.recordId }
2291
+ });
2292
+ // verify the data is written
2293
+ const recordsQueryReply = yield dwn.processMessage(pfi.did, recordsQueryMessageData.message);
2294
+ expect(recordsQueryReply.status.code).to.equal(200);
2295
+ expect((_a = recordsQueryReply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(1);
2296
+ expect(recordsQueryReply.entries[0].descriptor.dataCid).to.equal(fulfillmentMessageData.message.descriptor.dataCid);
2297
+ }));
2298
+ it('should fail authorization if incoming message contains `parentId` that leads to no record', () => __awaiter(this, void 0, void 0, function* () {
2299
+ // 1. DEX protocol with at least 3 layers of message exchange: ask -> offer -> fulfillment
2300
+ // 2. Alice sends an ask to a PFI
2301
+ // 3. Alice sends a fulfillment to an non-existent offer to the PFI
2302
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
2303
+ const pfi = yield TestDataGenerator.generateDidKeyPersona();
2304
+ // write a DEX protocol definition
2305
+ const protocolDefinition = dexProtocolDefinition;
2306
+ const protocol = protocolDefinition.protocol;
2307
+ // write the DEX protocol in the PFI
2308
+ const protocolConfig = yield TestDataGenerator.generateProtocolsConfigure({
2309
+ author: pfi,
2310
+ protocolDefinition: protocolDefinition
2311
+ });
2312
+ const protocolConfigureReply = yield dwn.processMessage(pfi.did, protocolConfig.message);
2313
+ expect(protocolConfigureReply.status.code).to.equal(202);
2314
+ // simulate Alice's ask
2315
+ const data = Encoder.stringToBytes('irrelevant');
2316
+ const askMessageData = yield TestDataGenerator.generateRecordsWrite({
2317
+ author: alice,
2318
+ recipient: pfi.did,
2319
+ schema: protocolDefinition.types.ask.schema,
2320
+ protocol,
2321
+ protocolPath: 'ask',
2322
+ data
2323
+ });
2324
+ let reply = yield dwn.processMessage(pfi.did, askMessageData.message, { dataStream: askMessageData.dataStream });
2325
+ expect(reply.status.code).to.equal(202);
2326
+ // the actual test: making sure fulfillment message fails
2327
+ const fulfillmentMessageData = yield TestDataGenerator.generateRecordsWrite({
2328
+ author: alice,
2329
+ recipient: pfi.did,
2330
+ schema: protocolDefinition.types.fulfillment.schema,
2331
+ parentContextId: 'nonExistentId', // NOTE: this will point to a non-existent parent
2332
+ protocolPath: 'ask/offer/fulfillment',
2333
+ protocol,
2334
+ data
2335
+ });
2336
+ reply = yield dwn.processMessage(pfi.did, fulfillmentMessageData.message, { dataStream: fulfillmentMessageData.dataStream });
2337
+ expect(reply.status.code).to.equal(400);
2338
+ expect(reply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationIncorrectProtocolPath);
2339
+ }));
2340
+ it('should 400 if expected CID of `encryption` mismatches the `encryptionCid` in `authorization`', () => __awaiter(this, void 0, void 0, function* () {
2341
+ const alice = yield TestDataGenerator.generatePersona();
2342
+ TestStubGenerator.stubDidResolver(didResolver, [alice]);
2343
+ // configure protocol
2344
+ const protocolDefinition = emailProtocolDefinition;
2345
+ const protocol = protocolDefinition.protocol;
2346
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
2347
+ author: alice,
2348
+ protocolDefinition
2349
+ });
2350
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
2351
+ expect(protocolsConfigureReply.status.code).to.equal(202);
2352
+ const bobMessageBytes = Encoder.stringToBytes('message from bob');
2353
+ const bobMessageStream = DataStream.fromBytes(bobMessageBytes);
2354
+ const dataEncryptionInitializationVector = TestDataGenerator.randomBytes(16);
2355
+ const dataEncryptionKey = TestDataGenerator.randomBytes(32);
2356
+ const bobMessageEncryptedStream = yield Encryption.aes256CtrEncrypt(dataEncryptionKey, dataEncryptionInitializationVector, bobMessageStream);
2357
+ const bobMessageEncryptedBytes = yield DataStream.toBytes(bobMessageEncryptedStream);
2358
+ const encryptionInput = {
2359
+ algorithm: EncryptionAlgorithm.Aes256Ctr,
2360
+ initializationVector: dataEncryptionInitializationVector,
2361
+ key: dataEncryptionKey,
2362
+ keyEncryptionInputs: [{
2363
+ publicKeyId: alice.keyId, // reusing signing key for encryption purely as a convenience
2364
+ publicKey: alice.keyPair.publicJwk,
2365
+ algorithm: EncryptionAlgorithm.EciesSecp256k1,
2366
+ derivationScheme: KeyDerivationScheme.ProtocolPath
2367
+ }]
2368
+ };
2369
+ const { message, dataStream } = yield TestDataGenerator.generateRecordsWrite({
2370
+ author: alice,
2371
+ protocol,
2372
+ protocolPath: 'email',
2373
+ schema: 'email',
2374
+ data: bobMessageEncryptedBytes,
2375
+ encryptionInput
2376
+ });
2377
+ // replace valid `encryption` property with a mismatching one
2378
+ message.encryption.initializationVector = Encoder.stringToBase64Url('any value which will result in a different CID');
2379
+ const recordsWriteHandler = new RecordsWriteHandler(didResolver, messageStore, dataStore, eventLog, eventStream);
2380
+ const writeReply = yield recordsWriteHandler.handle({ tenant: alice.did, message, dataStream: dataStream });
2381
+ expect(writeReply.status.code).to.equal(400);
2382
+ expect(writeReply.status.detail).to.contain(DwnErrorCode.RecordsWriteValidateIntegrityEncryptionCidMismatch);
2383
+ }));
2384
+ it('should return 400 if protocol is not normalized', () => __awaiter(this, void 0, void 0, function* () {
2385
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
2386
+ const protocolDefinition = emailProtocolDefinition;
2387
+ // write a message into DB
2388
+ const recordsWrite = yield TestDataGenerator.generateRecordsWrite({
2389
+ author: alice,
2390
+ data: new TextEncoder().encode('data1'),
2391
+ protocol: 'example.com/',
2392
+ protocolPath: 'email', // from email protocol
2393
+ schema: protocolDefinition.types.email.schema
2394
+ });
2395
+ // overwrite protocol because #create auto-normalizes protocol
2396
+ recordsWrite.message.descriptor.protocol = 'example.com/';
2397
+ // Re-create auth because we altered the descriptor after signing
2398
+ const descriptorCid = yield Cid.computeCid(recordsWrite.message.descriptor);
2399
+ const attestation = yield RecordsWrite.createAttestation(descriptorCid);
2400
+ const signature = yield RecordsWrite.createSignerSignature({
2401
+ recordId: recordsWrite.message.recordId,
2402
+ contextId: recordsWrite.message.contextId,
2403
+ descriptorCid,
2404
+ attestation,
2405
+ encryption: recordsWrite.message.encryption,
2406
+ signer: Jws.createSigner(alice)
2407
+ });
2408
+ recordsWrite.message = Object.assign(Object.assign({}, recordsWrite.message), { attestation, authorization: { signature } });
2409
+ // Send records write message
2410
+ const reply = yield dwn.processMessage(alice.did, recordsWrite.message, { dataStream: recordsWrite.dataStream });
2411
+ expect(reply.status.code).to.equal(400);
2412
+ expect(reply.status.detail).to.contain(DwnErrorCode.UrlProtocolNotNormalized);
2413
+ }));
2414
+ it('#359 - should not allow access of data by referencing `dataCid` in protocol authorized `RecordsWrite`', () => __awaiter(this, void 0, void 0, function* () {
2415
+ var _a, _b, _c;
2416
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
2417
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
2418
+ // alice writes a private record
2419
+ const dataString = TestDataGenerator.randomString(DwnConstant.maxDataSizeAllowedToBeEncoded);
2420
+ const dataSize = dataString.length;
2421
+ const data = Encoder.stringToBytes(dataString);
2422
+ const dataCid = yield Cid.computeDagPbCidFromBytes(data);
2423
+ const { message, dataStream } = yield TestDataGenerator.generateRecordsWrite({
2424
+ author: alice,
2425
+ data,
2426
+ });
2427
+ const reply = yield dwn.processMessage(alice.did, message, { dataStream });
2428
+ expect(reply.status.code).to.equal(202);
2429
+ const protocolDefinition = socialMediaProtocolDefinition;
2430
+ const protocol = protocolDefinition.protocol;
2431
+ // alice has a social media protocol that allows anyone to write and read images
2432
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
2433
+ author: alice,
2434
+ protocolDefinition
2435
+ });
2436
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
2437
+ expect(protocolsConfigureReply.status.code).to.equal(202);
2438
+ // bob learns of metadata (ie. dataCid) of alice's secret data,
2439
+ // attempts to gain unauthorized access by writing to alice's DWN through open protocol referencing the dataCid without supplying the data
2440
+ // which he is allowed to do, the DWN will treat the operation as an initial-write or a record that has a later and different state.
2441
+ const imageRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
2442
+ author: bob,
2443
+ protocol,
2444
+ protocolPath: 'image',
2445
+ schema: protocolDefinition.types.image.schema,
2446
+ dataFormat: 'image/jpeg',
2447
+ dataCid, // bob learns of, and references alice's secrete data's CID
2448
+ dataSize,
2449
+ recipient: alice.did
2450
+ });
2451
+ const imageReply = yield dwn.processMessage(alice.did, imageRecordsWrite.message);
2452
+ expect(imageReply.status.code).to.equal(204); // allows write but is not readable or queryable
2453
+ // verify the record is not able to be read
2454
+ const bobRecordsReadData = yield RecordsRead.create({
2455
+ filter: {
2456
+ recordId: imageRecordsWrite.message.recordId,
2457
+ },
2458
+ signer: Jws.createSigner(bob)
2459
+ });
2460
+ const bobRecordsReadReply = yield dwn.processMessage(alice.did, bobRecordsReadData.message);
2461
+ expect(bobRecordsReadReply.status.code).to.equal(404);
2462
+ // verify the record is not part of a query
2463
+ const bobRecordsQuery = yield RecordsQuery.create({
2464
+ filter: {
2465
+ schema: protocolDefinition.types.image.schema,
2466
+ },
2467
+ signer: Jws.createSigner(bob)
2468
+ });
2469
+ const bobRecordsQueryReply = yield dwn.processMessage(alice.did, bobRecordsQuery.message);
2470
+ expect(bobRecordsQueryReply.status.code).to.equal(200);
2471
+ expect((_a = bobRecordsQueryReply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(0);
2472
+ //further sanity query for specific recordId
2473
+ const bobRecordsQueryRecordId = yield RecordsQuery.create({
2474
+ filter: {
2475
+ recordId: imageRecordsWrite.message.recordId,
2476
+ },
2477
+ signer: Jws.createSigner(bob)
2478
+ });
2479
+ const bobRecordsQueryRecordIdReply = yield dwn.processMessage(alice.did, bobRecordsQueryRecordId.message);
2480
+ expect(bobRecordsQueryRecordIdReply.status.code).to.equal(200);
2481
+ expect((_b = bobRecordsQueryRecordIdReply.entries) === null || _b === void 0 ? void 0 : _b.length).to.equal(0);
2482
+ // attempt update recordsWrite without data, this will reject
2483
+ const updateRecord = yield RecordsWrite.createFrom({
2484
+ recordsWriteMessage: imageRecordsWrite.message,
2485
+ signer: Jws.createSigner(bob),
2486
+ published: true,
2487
+ });
2488
+ const updateRecordReply = yield dwn.processMessage(alice.did, updateRecord.message);
2489
+ expect(updateRecordReply.status.code).to.equal(400);
2490
+ expect(updateRecordReply.status.detail).to.include(DwnErrorCode.RecordsWriteMissingEncodedDataInPrevious);
2491
+ // sanity still can't query
2492
+ const bobRecordsQueryReply2 = yield dwn.processMessage(alice.did, bobRecordsQuery.message);
2493
+ expect(bobRecordsQueryReply2.status.code).to.equal(200);
2494
+ expect((_c = bobRecordsQueryReply2.entries) === null || _c === void 0 ? void 0 : _c.length).to.equal(0);
2495
+ }));
2496
+ it('#359 - should not allow access of data by referencing `dataCid` in protocol authorized `RecordsWrite` with large data', () => __awaiter(this, void 0, void 0, function* () {
2497
+ var _a, _b, _c;
2498
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
2499
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
2500
+ // alice writes a private record
2501
+ const dataString = TestDataGenerator.randomString(DwnConstant.maxDataSizeAllowedToBeEncoded + 1);
2502
+ const dataSize = dataString.length;
2503
+ const data = Encoder.stringToBytes(dataString);
2504
+ const dataCid = yield Cid.computeDagPbCidFromBytes(data);
2505
+ const { message, dataStream } = yield TestDataGenerator.generateRecordsWrite({
2506
+ author: alice,
2507
+ data,
2508
+ });
2509
+ const reply = yield dwn.processMessage(alice.did, message, { dataStream });
2510
+ expect(reply.status.code).to.equal(202);
2511
+ const protocolDefinition = socialMediaProtocolDefinition;
2512
+ const protocol = protocolDefinition.protocol;
2513
+ // alice has a social media protocol that allows anyone to write and read images
2514
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
2515
+ author: alice,
2516
+ protocolDefinition
2517
+ });
2518
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
2519
+ expect(protocolsConfigureReply.status.code).to.equal(202);
2520
+ // bob learns of metadata (ie. dataCid) of alice's secret data,
2521
+ // attempts to gain unauthorized access by writing to alice's DWN through open protocol referencing the dataCid without supplying the data
2522
+ // which he is allowed to do, the DWN will treat the operation as an initial-write or a record that has a later and different state.
2523
+ const imageRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
2524
+ author: bob,
2525
+ protocol,
2526
+ protocolPath: 'image',
2527
+ schema: protocolDefinition.types.image.schema,
2528
+ dataFormat: 'image/jpeg',
2529
+ dataCid, // bob learns of, and references alice's secrete data's CID
2530
+ dataSize,
2531
+ recipient: alice.did
2532
+ });
2533
+ const imageReply = yield dwn.processMessage(alice.did, imageRecordsWrite.message);
2534
+ expect(imageReply.status.code).to.equal(204); // allows write but is not readable or queryable
2535
+ // verify the record is not able to be read
2536
+ const bobRecordsReadData = yield RecordsRead.create({
2537
+ filter: {
2538
+ recordId: imageRecordsWrite.message.recordId,
2539
+ },
2540
+ signer: Jws.createSigner(bob)
2541
+ });
2542
+ const bobRecordsReadReply = yield dwn.processMessage(alice.did, bobRecordsReadData.message);
2543
+ expect(bobRecordsReadReply.status.code).to.equal(404);
2544
+ // verify the record is not part of a query
2545
+ const bobRecordsQuery = yield RecordsQuery.create({
2546
+ filter: {
2547
+ schema: protocolDefinition.types.image.schema,
2548
+ },
2549
+ signer: Jws.createSigner(bob)
2550
+ });
2551
+ const bobRecordsQueryReply = yield dwn.processMessage(alice.did, bobRecordsQuery.message);
2552
+ expect(bobRecordsQueryReply.status.code).to.equal(200);
2553
+ expect((_a = bobRecordsQueryReply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(0);
2554
+ //further sanity query for specific recordId
2555
+ const bobRecordsQueryRecordId = yield RecordsQuery.create({
2556
+ filter: {
2557
+ recordId: imageRecordsWrite.message.recordId,
2558
+ },
2559
+ signer: Jws.createSigner(bob)
2560
+ });
2561
+ const bobRecordsQueryRecordIdReply = yield dwn.processMessage(alice.did, bobRecordsQueryRecordId.message);
2562
+ expect(bobRecordsQueryRecordIdReply.status.code).to.equal(200);
2563
+ expect((_b = bobRecordsQueryRecordIdReply.entries) === null || _b === void 0 ? void 0 : _b.length).to.equal(0);
2564
+ // attempt update recordsWrite without data, this will reject
2565
+ const updateRecord = yield RecordsWrite.createFrom({
2566
+ recordsWriteMessage: imageRecordsWrite.message,
2567
+ signer: Jws.createSigner(bob),
2568
+ published: true,
2569
+ });
2570
+ const updateRecordReply = yield dwn.processMessage(alice.did, updateRecord.message);
2571
+ expect(updateRecordReply.status.code).to.equal(400);
2572
+ expect(updateRecordReply.status.detail).to.include(DwnErrorCode.RecordsWriteMissingDataInPrevious);
2573
+ // sanity still can't query
2574
+ const bobRecordsQueryReply2 = yield dwn.processMessage(alice.did, bobRecordsQuery.message);
2575
+ expect(bobRecordsQueryReply2.status.code).to.equal(200);
2576
+ expect((_c = bobRecordsQueryReply2.entries) === null || _c === void 0 ? void 0 : _c.length).to.equal(0);
2577
+ }));
2578
+ it('should allow record with or without schema if protocol does not require schema for a record type', () => __awaiter(this, void 0, void 0, function* () {
2579
+ // scenario: Alice's DWN has a protocol that allows anyone to write a record without schema
2580
+ var _a;
2581
+ // write a protocol definition that has a record type without schema
2582
+ const protocolDefinition = anyoneCollaborateProtocolDefinition;
2583
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
2584
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
2585
+ author: alice,
2586
+ protocolDefinition
2587
+ });
2588
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
2589
+ expect(protocolsConfigureReply.status.code).to.equal(202);
2590
+ // write a `RecordsWrite` message without schema
2591
+ const data = TestDataGenerator.randomBytes(100);
2592
+ const dataStream = DataStream.fromBytes(data);
2593
+ const docWrite = yield RecordsWrite.create({
2594
+ protocol: protocolDefinition.protocol,
2595
+ protocolPath: 'doc',
2596
+ dataFormat: 'application/octet-stream',
2597
+ data,
2598
+ signer: Jws.createSigner(alice)
2599
+ });
2600
+ const writeReply = yield dwn.processMessage(alice.did, docWrite.message, { dataStream });
2601
+ expect(writeReply.status.code).to.equal(202);
2602
+ // write a `RecordsWrite` message with schema
2603
+ const data2 = TestDataGenerator.randomBytes(100);
2604
+ const data2Stream = DataStream.fromBytes(data2);
2605
+ const doc2Write = yield RecordsWrite.create({
2606
+ protocol: protocolDefinition.protocol,
2607
+ protocolPath: 'doc',
2608
+ schema: TestDataGenerator.randomString(10),
2609
+ dataFormat: 'application/octet-stream',
2610
+ data: data2,
2611
+ signer: Jws.createSigner(alice)
2612
+ });
2613
+ const write2Reply = yield dwn.processMessage(alice.did, doc2Write.message, { dataStream: data2Stream });
2614
+ expect(write2Reply.status.code).to.equal(202);
2615
+ // verify messages got written to the DB
2616
+ const recordsQuery = yield RecordsQuery.create({
2617
+ filter: { protocolPath: 'doc' },
2618
+ signer: Jws.createSigner(alice)
2619
+ });
2620
+ const recordsReadReply = yield dwn.processMessage(alice.did, recordsQuery.message);
2621
+ expect(recordsReadReply.status.code).to.equal(200);
2622
+ expect((_a = recordsReadReply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(2);
2623
+ }));
2624
+ it('should allow authorization if protocol message size is within min and max size', () => __awaiter(this, void 0, void 0, function* () {
2625
+ const alice = yield TestDataGenerator.generatePersona();
2626
+ TestStubGenerator.stubDidResolver(didResolver, [alice]);
2627
+ const protocolDefinition = {
2628
+ protocol: 'http://blob-size.xyz',
2629
+ published: true,
2630
+ types: {
2631
+ blob: {}
2632
+ },
2633
+ structure: {
2634
+ blob: {
2635
+ $size: {
2636
+ min: 1,
2637
+ max: 1000
2638
+ }
2639
+ }
2640
+ }
2641
+ };
2642
+ const protocol = protocolDefinition.protocol;
2643
+ const protocolConfig = yield TestDataGenerator.generateProtocolsConfigure({
2644
+ author: alice,
2645
+ protocolDefinition,
2646
+ });
2647
+ const protocolConfigureReply = yield dwn.processMessage(alice.did, protocolConfig.message);
2648
+ expect(protocolConfigureReply.status.code).to.equal(202);
2649
+ // test min record size
2650
+ const data = TestDataGenerator.randomBytes(1);
2651
+ const testRecord = yield TestDataGenerator.generateRecordsWrite({
2652
+ author: alice,
2653
+ recipient: alice.did,
2654
+ protocol,
2655
+ protocolPath: 'blob',
2656
+ data
2657
+ });
2658
+ const reply = yield dwn.processMessage(alice.did, testRecord.message, { dataStream: testRecord.dataStream });
2659
+ expect(reply.status.code).to.equal(202);
2660
+ // test max record size
2661
+ const data2 = TestDataGenerator.randomBytes(1000);
2662
+ const testRecord2 = yield TestDataGenerator.generateRecordsWrite({
2663
+ author: alice,
2664
+ recipient: alice.did,
2665
+ protocol,
2666
+ protocolPath: 'blob',
2667
+ data: data2
2668
+ });
2669
+ const reply2 = yield dwn.processMessage(alice.did, testRecord2.message, { dataStream: testRecord2.dataStream });
2670
+ expect(reply2.status.code).to.equal(202);
2671
+ // test beyond max size
2672
+ const data3 = TestDataGenerator.randomBytes(1001);
2673
+ const testRecord3 = yield TestDataGenerator.generateRecordsWrite({
2674
+ author: alice,
2675
+ recipient: alice.did,
2676
+ protocol,
2677
+ protocolPath: 'blob',
2678
+ data: data3
2679
+ });
2680
+ const reply3 = yield dwn.processMessage(alice.did, testRecord3.message, { dataStream: testRecord3.dataStream });
2681
+ expect(reply3.status.code).to.equal(400);
2682
+ expect(reply3.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationMaxSizeInvalid);
2683
+ }));
2684
+ it('should fail authorization if protocol message size is less than specified minimum size', () => __awaiter(this, void 0, void 0, function* () {
2685
+ const alice = yield TestDataGenerator.generatePersona();
2686
+ TestStubGenerator.stubDidResolver(didResolver, [alice]);
2687
+ const protocolDefinition = {
2688
+ protocol: 'http://blob-size.xyz',
2689
+ published: true,
2690
+ types: {
2691
+ blob: {}
2692
+ },
2693
+ structure: {
2694
+ blob: {
2695
+ $size: {
2696
+ min: 1000
2697
+ }
2698
+ }
2699
+ }
2700
+ };
2701
+ const protocol = protocolDefinition.protocol;
2702
+ const protocolConfig = yield TestDataGenerator.generateProtocolsConfigure({
2703
+ author: alice,
2704
+ protocolDefinition,
2705
+ });
2706
+ const protocolConfigureReply = yield dwn.processMessage(alice.did, protocolConfig.message);
2707
+ expect(protocolConfigureReply.status.code).to.equal(202);
2708
+ const data = TestDataGenerator.randomBytes(999);
2709
+ const testRecord = yield TestDataGenerator.generateRecordsWrite({
2710
+ author: alice,
2711
+ recipient: alice.did,
2712
+ protocol,
2713
+ protocolPath: 'blob',
2714
+ data
2715
+ });
2716
+ const reply = yield dwn.processMessage(alice.did, testRecord.message, { dataStream: testRecord.dataStream });
2717
+ expect(reply.status.code).to.equal(400);
2718
+ expect(reply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationMinSizeInvalid);
2719
+ // test valid min record size
2720
+ const data2 = TestDataGenerator.randomBytes(1000);
2721
+ const testRecord2 = yield TestDataGenerator.generateRecordsWrite({
2722
+ author: alice,
2723
+ recipient: alice.did,
2724
+ protocol,
2725
+ protocolPath: 'blob',
2726
+ data: data2
2727
+ });
2728
+ const reply2 = yield dwn.processMessage(alice.did, testRecord2.message, { dataStream: testRecord2.dataStream });
2729
+ expect(reply2.status.code).to.equal(202);
2730
+ }));
2731
+ it('should fail authorization if protocol message size is more than specified maximum size', () => __awaiter(this, void 0, void 0, function* () {
2732
+ const alice = yield TestDataGenerator.generatePersona();
2733
+ TestStubGenerator.stubDidResolver(didResolver, [alice]);
2734
+ const protocolDefinition = {
2735
+ protocol: 'http://blob-size.xyz',
2736
+ published: true,
2737
+ types: {
2738
+ blob: {}
2739
+ },
2740
+ structure: {
2741
+ blob: {
2742
+ $size: {
2743
+ max: 1000
2744
+ }
2745
+ }
2746
+ }
2747
+ };
2748
+ const protocol = protocolDefinition.protocol;
2749
+ const protocolConfig = yield TestDataGenerator.generateProtocolsConfigure({
2750
+ author: alice,
2751
+ protocolDefinition,
2752
+ });
2753
+ const protocolConfigureReply = yield dwn.processMessage(alice.did, protocolConfig.message);
2754
+ expect(protocolConfigureReply.status.code).to.equal(202);
2755
+ const data = TestDataGenerator.randomBytes(1001);
2756
+ const testRecord = yield TestDataGenerator.generateRecordsWrite({
2757
+ author: alice,
2758
+ recipient: alice.did,
2759
+ protocol,
2760
+ protocolPath: 'blob',
2761
+ data
2762
+ });
2763
+ const reply = yield dwn.processMessage(alice.did, testRecord.message, { dataStream: testRecord.dataStream });
2764
+ expect(reply.status.code).to.equal(400);
2765
+ expect(reply.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationMaxSizeInvalid);
2766
+ // test valid max record size
2767
+ const data2 = TestDataGenerator.randomBytes(1000);
2768
+ const testRecord2 = yield TestDataGenerator.generateRecordsWrite({
2769
+ author: alice,
2770
+ recipient: alice.did,
2771
+ protocol,
2772
+ protocolPath: 'blob',
2773
+ data: data2
2774
+ });
2775
+ const reply2 = yield dwn.processMessage(alice.did, testRecord2.message, { dataStream: testRecord2.dataStream });
2776
+ expect(reply2.status.code).to.equal(202);
2777
+ }));
2778
+ it('should fail if a write references a parent that has been deleted', () => __awaiter(this, void 0, void 0, function* () {
2779
+ // scenario:
2780
+ // 0. Alice installs a nested protocol foo -> bar -> baz
2781
+ // 1. Alice writes foo1
2782
+ // 2. Alice deletes foo1
2783
+ // 3. Alice tries to write a bar1 referencing the deleted foo and should fail
2784
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
2785
+ const protocolDefinition = nestedProtocol;
2786
+ // 0. Alice installs a nested protocol foo -> bar -> baz
2787
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
2788
+ author: alice,
2789
+ protocolDefinition
2790
+ });
2791
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
2792
+ expect(protocolsConfigureReply.status.code).to.equal(202);
2793
+ // 1. Alice writes foo1
2794
+ const fooOptions = {
2795
+ author: alice,
2796
+ protocol: nestedProtocol.protocol,
2797
+ protocolPath: 'foo',
2798
+ schema: nestedProtocol.types.foo.schema,
2799
+ dataFormat: nestedProtocol.types.foo.dataFormats[0],
2800
+ };
2801
+ const foo1 = yield TestDataGenerator.generateRecordsWrite(fooOptions);
2802
+ const foo1WriteResponse = yield dwn.processMessage(alice.did, foo1.message, { dataStream: foo1.dataStream });
2803
+ expect(foo1WriteResponse.status.code).equals(202);
2804
+ // 2. Alice deletes foo1
2805
+ const deleteFoo = yield TestDataGenerator.generateRecordsDelete({
2806
+ author: alice,
2807
+ recordId: foo1.message.recordId
2808
+ });
2809
+ const deleteFooReply = yield dwn.processMessage(alice.did, deleteFoo.message);
2810
+ expect(deleteFooReply.status.code).equals(202);
2811
+ // 3. Alice tries to write a bar1 referencing the deleted foo and should fail
2812
+ const barOptions = {
2813
+ author: alice,
2814
+ protocol: nestedProtocol.protocol,
2815
+ protocolPath: 'foo/bar',
2816
+ schema: nestedProtocol.types.bar.schema,
2817
+ dataFormat: nestedProtocol.types.bar.dataFormats[0],
2818
+ parentContextId: foo1.message.contextId
2819
+ };
2820
+ const bar1 = yield TestDataGenerator.generateRecordsWrite(barOptions);
2821
+ const bar1WriteResponse = yield dwn.processMessage(alice.did, bar1.message, { dataStream: bar1.dataStream });
2822
+ expect(bar1WriteResponse.status.code).equals(400);
2823
+ expect(bar1WriteResponse.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationIncorrectProtocolPath);
2824
+ }));
2825
+ it('should fail if a write references a mismatching parent that compared to the parent in the `contextId` ', () => __awaiter(this, void 0, void 0, function* () {
2826
+ // scenario:
2827
+ // 0. Alice installs a nested protocol foo -> bar -> baz
2828
+ // 1. Alice writes foo1
2829
+ // 2. Alice tries to write a bar1 referencing the foo1 in parentId, but contextId does not reference the same parent
2830
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
2831
+ const protocolDefinition = nestedProtocol;
2832
+ // 0. Alice installs a nested protocol foo -> bar -> baz
2833
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
2834
+ author: alice,
2835
+ protocolDefinition
2836
+ });
2837
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
2838
+ expect(protocolsConfigureReply.status.code).to.equal(202);
2839
+ // 1. Alice writes foo1
2840
+ const fooOptions = {
2841
+ author: alice,
2842
+ protocol: nestedProtocol.protocol,
2843
+ protocolPath: 'foo',
2844
+ schema: nestedProtocol.types.foo.schema,
2845
+ dataFormat: nestedProtocol.types.foo.dataFormats[0],
2846
+ };
2847
+ const foo1 = yield TestDataGenerator.generateRecordsWrite(fooOptions);
2848
+ const foo1WriteResponse = yield dwn.processMessage(alice.did, foo1.message, { dataStream: foo1.dataStream });
2849
+ expect(foo1WriteResponse.status.code).equals(202);
2850
+ // 2. Alice tries to write a bar1 referencing the foo1 in parentId, but contextId does not reference the same parent
2851
+ const barOptions = {
2852
+ author: alice,
2853
+ protocol: nestedProtocol.protocol,
2854
+ protocolPath: 'foo/bar',
2855
+ schema: nestedProtocol.types.bar.schema,
2856
+ dataFormat: nestedProtocol.types.bar.dataFormats[0],
2857
+ parentContextId: foo1.message.contextId
2858
+ };
2859
+ const bar1 = yield TestDataGenerator.generateRecordsWrite(barOptions);
2860
+ // replace the contextId with a different parent
2861
+ const contextIdSegments = bar1.message.contextId.split(`/`);
2862
+ contextIdSegments[1] = 'differentParent';
2863
+ bar1.message.contextId = contextIdSegments.join(`/`);
2864
+ // resign the message
2865
+ const recordId = yield RecordsWrite.getEntryId(alice.did, bar1.message.descriptor);
2866
+ const descriptorCid = yield Cid.computeCid(bar1.message.descriptor);
2867
+ const signature = yield RecordsWrite.createSignerSignature({
2868
+ recordId,
2869
+ contextId: bar1.message.contextId,
2870
+ descriptorCid,
2871
+ encryption: undefined,
2872
+ attestation: undefined,
2873
+ signer: Jws.createSigner(alice)
2874
+ });
2875
+ bar1.message.recordId = recordId;
2876
+ bar1.message.authorization = { signature };
2877
+ const bar1WriteResponse = yield dwn.processMessage(alice.did, bar1.message);
2878
+ expect(bar1WriteResponse.status.code).equals(400);
2879
+ expect(bar1WriteResponse.status.detail).to.contain(DwnErrorCode.ProtocolAuthorizationIncorrectContextId);
2880
+ }));
2881
+ });
2882
+ describe('grant based writes', () => {
2883
+ describe('protocol records', () => {
2884
+ it('allows writes of protocol records with matching protocol grant scopes', () => __awaiter(this, void 0, void 0, function* () {
2885
+ // scenario: Alice gives Bob a grant to read all records in the protocol
2886
+ // Bob invokes that grant to write a protocol record.
2887
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
2888
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
2889
+ const protocolDefinition = minimalProtocolDefinition;
2890
+ // Alice installs the protocol
2891
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
2892
+ author: alice,
2893
+ protocolDefinition
2894
+ });
2895
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
2896
+ expect(protocolsConfigureReply.status.code).to.equal(202);
2897
+ // Alice gives Bob a permission grant
2898
+ const permissionGrant = yield PermissionsProtocol.createGrant({
2899
+ signer: Jws.createSigner(alice),
2900
+ grantedTo: bob.did,
2901
+ dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }), // 24 hours
2902
+ scope: {
2903
+ interface: DwnInterfaceName.Records,
2904
+ method: DwnMethodName.Write,
2905
+ protocol: protocolDefinition.protocol,
2906
+ }
2907
+ });
2908
+ const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
2909
+ const permissionGrantWriteReply = yield dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
2910
+ expect(permissionGrantWriteReply.status.code).to.equal(202);
2911
+ // Bob invokes the grant in order to write a record to the protocol
2912
+ const { recordsWrite, dataStream } = yield TestDataGenerator.generateRecordsWrite({
2913
+ author: bob,
2914
+ protocol: protocolDefinition.protocol,
2915
+ protocolPath: 'foo',
2916
+ permissionGrantId: permissionGrant.recordsWrite.message.recordId,
2917
+ });
2918
+ const recordsWriteReply = yield dwn.processMessage(alice.did, recordsWrite.message, { dataStream });
2919
+ expect(recordsWriteReply.status.code).to.equal(202);
2920
+ }));
2921
+ it('rejects writes of protocol records with mismatching protocol grant scopes', () => __awaiter(this, void 0, void 0, function* () {
2922
+ // scenario: Alice gives Bob a grant to write to a protocol. Bob tries and fails to
2923
+ // invoke the grant to write to another protocol.
2924
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
2925
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
2926
+ const protocolDefinition = minimalProtocolDefinition;
2927
+ // Alice installs the protocol
2928
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
2929
+ author: alice,
2930
+ protocolDefinition
2931
+ });
2932
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
2933
+ expect(protocolsConfigureReply.status.code).to.equal(202);
2934
+ // Alice gives Bob a permission grant with a different protocol than what Bob will try to write to
2935
+ const permissionGrant = yield PermissionsProtocol.createGrant({
2936
+ signer: Jws.createSigner(alice),
2937
+ grantedTo: bob.did,
2938
+ dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }), // 24 hours
2939
+ scope: {
2940
+ interface: DwnInterfaceName.Records,
2941
+ method: DwnMethodName.Write,
2942
+ protocol: 'some-other-protocol',
2943
+ }
2944
+ });
2945
+ const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
2946
+ const permissionGrantWriteReply = yield dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
2947
+ expect(permissionGrantWriteReply.status.code).to.equal(202);
2948
+ // Bob invokes the grant, failing to write to a different protocol than the grant allows
2949
+ const { recordsWrite, dataStream } = yield TestDataGenerator.generateRecordsWrite({
2950
+ author: bob,
2951
+ protocol: protocolDefinition.protocol,
2952
+ protocolPath: 'foo',
2953
+ permissionGrantId: permissionGrant.recordsWrite.message.recordId,
2954
+ });
2955
+ const recordsWriteReply = yield dwn.processMessage(alice.did, recordsWrite.message, { dataStream });
2956
+ expect(recordsWriteReply.status.code).to.equal(401);
2957
+ expect(recordsWriteReply.status.detail).to.contain(DwnErrorCode.RecordsGrantAuthorizationScopeProtocolMismatch);
2958
+ }));
2959
+ it('allows writes of protocol records with matching contextId grant scopes', () => __awaiter(this, void 0, void 0, function* () {
2960
+ // scenario: Alice gives Bob a grant to write to a specific contextId.
2961
+ // Bob invokes that grant to write a record in the allowed contextId.
2962
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
2963
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
2964
+ const protocolDefinition = emailProtocolDefinition;
2965
+ // Alice installs the protocol
2966
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
2967
+ author: alice,
2968
+ protocolDefinition
2969
+ });
2970
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
2971
+ expect(protocolsConfigureReply.status.code).to.equal(202);
2972
+ // Alice creates the context that she will give Bob access to
2973
+ const alicesRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
2974
+ author: alice,
2975
+ data: new TextEncoder().encode('data1'),
2976
+ protocol: protocolDefinition.protocol,
2977
+ protocolPath: 'email',
2978
+ schema: protocolDefinition.types.email.schema,
2979
+ dataFormat: protocolDefinition.types.email.dataFormats[0],
2980
+ });
2981
+ const alicesRecordsWriteReply = yield dwn.processMessage(alice.did, alicesRecordsWrite.message, { dataStream: alicesRecordsWrite.dataStream });
2982
+ expect(alicesRecordsWriteReply.status.code).to.equal(202);
2983
+ // Alice gives Bob a permission grant
2984
+ const permissionGrant = yield PermissionsProtocol.createGrant({
2985
+ signer: Jws.createSigner(alice),
2986
+ grantedTo: bob.did,
2987
+ dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }), // 24 hours
2988
+ scope: {
2989
+ interface: DwnInterfaceName.Records,
2990
+ method: DwnMethodName.Write,
2991
+ protocol: protocolDefinition.protocol,
2992
+ contextId: alicesRecordsWrite.message.contextId,
2993
+ }
2994
+ });
2995
+ const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
2996
+ const permissionGrantWriteReply = yield dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
2997
+ expect(permissionGrantWriteReply.status.code).to.equal(202);
2998
+ // Bob invokes the grant in order to write a record to the protocol
2999
+ const bobsRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
3000
+ author: bob,
3001
+ protocol: protocolDefinition.protocol,
3002
+ protocolPath: 'email/email',
3003
+ schema: protocolDefinition.types.email.schema,
3004
+ dataFormat: protocolDefinition.types.email.dataFormats[0],
3005
+ parentContextId: alicesRecordsWrite.message.contextId,
3006
+ permissionGrantId: permissionGrant.recordsWrite.message.recordId,
3007
+ });
3008
+ const bobsRecordsWriteReply = yield dwn.processMessage(alice.did, bobsRecordsWrite.message, { dataStream: bobsRecordsWrite.dataStream });
3009
+ expect(bobsRecordsWriteReply.status.code).to.equal(202);
3010
+ }));
3011
+ it('rejects writes of protocol records with mismatching contextId grant scopes', () => __awaiter(this, void 0, void 0, function* () {
3012
+ // scenario: Alice gives Bob a grant to write to a specific contextId. Bob tries and fails to
3013
+ // invoke the grant to write to another contextId.
3014
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
3015
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
3016
+ const protocolDefinition = emailProtocolDefinition;
3017
+ // Alice installs the protocol
3018
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
3019
+ author: alice,
3020
+ protocolDefinition
3021
+ });
3022
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
3023
+ expect(protocolsConfigureReply.status.code).to.equal(202);
3024
+ // Alice creates the context that she will give Bob access to
3025
+ const alicesRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
3026
+ author: alice,
3027
+ data: new TextEncoder().encode('data1'),
3028
+ protocol: protocolDefinition.protocol,
3029
+ protocolPath: 'email',
3030
+ schema: protocolDefinition.types.email.schema,
3031
+ dataFormat: protocolDefinition.types.email.dataFormats[0],
3032
+ });
3033
+ const alicesRecordsWriteReply = yield dwn.processMessage(alice.did, alicesRecordsWrite.message, { dataStream: alicesRecordsWrite.dataStream });
3034
+ expect(alicesRecordsWriteReply.status.code).to.equal(202);
3035
+ // Alice gives Bob a permission grant
3036
+ const permissionGrant = yield PermissionsProtocol.createGrant({
3037
+ signer: Jws.createSigner(alice),
3038
+ grantedTo: bob.did,
3039
+ dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }), // 24 hours
3040
+ scope: {
3041
+ interface: DwnInterfaceName.Records,
3042
+ method: DwnMethodName.Write,
3043
+ protocol: protocolDefinition.protocol,
3044
+ contextId: yield TestDataGenerator.randomCborSha256Cid(), // different contextId than what Bob will try to write to
3045
+ }
3046
+ });
3047
+ const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
3048
+ const permissionGrantWriteReply = yield dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
3049
+ expect(permissionGrantWriteReply.status.code).to.equal(202);
3050
+ // Bob invokes the grant in order to write a record to the protocol
3051
+ const bobsRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
3052
+ author: bob,
3053
+ protocol: protocolDefinition.protocol,
3054
+ protocolPath: 'email/email',
3055
+ schema: protocolDefinition.types.email.schema,
3056
+ dataFormat: protocolDefinition.types.email.dataFormats[0],
3057
+ parentContextId: alicesRecordsWrite.message.contextId,
3058
+ permissionGrantId: permissionGrant.recordsWrite.message.recordId,
3059
+ });
3060
+ const bobsRecordsWriteReply = yield dwn.processMessage(alice.did, bobsRecordsWrite.message, { dataStream: bobsRecordsWrite.dataStream });
3061
+ expect(bobsRecordsWriteReply.status.code).to.equal(401);
3062
+ expect(bobsRecordsWriteReply.status.detail).to.contain(DwnErrorCode.RecordsGrantAuthorizationScopeContextIdMismatch);
3063
+ }));
3064
+ it('allows writes of protocol records with matching protocolPath grant scopes', () => __awaiter(this, void 0, void 0, function* () {
3065
+ // scenario: Alice gives Bob a grant to write to a specific protocolPath.
3066
+ // Bob invokes that grant to write a record in the allowed protocolPath.
3067
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
3068
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
3069
+ const protocolDefinition = minimalProtocolDefinition;
3070
+ // Alice installs the protocol
3071
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
3072
+ author: alice,
3073
+ protocolDefinition
3074
+ });
3075
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
3076
+ expect(protocolsConfigureReply.status.code).to.equal(202);
3077
+ // Alice gives Bob a permission grant
3078
+ const permissionGrant = yield PermissionsProtocol.createGrant({
3079
+ signer: Jws.createSigner(alice),
3080
+ grantedTo: bob.did,
3081
+ dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }), // 24 hours
3082
+ scope: {
3083
+ interface: DwnInterfaceName.Records,
3084
+ method: DwnMethodName.Write,
3085
+ protocol: protocolDefinition.protocol,
3086
+ protocolPath: 'foo',
3087
+ }
3088
+ });
3089
+ const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
3090
+ const permissionGrantWriteReply = yield dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
3091
+ expect(permissionGrantWriteReply.status.code).to.equal(202);
3092
+ // Bob invokes the grant in order to write a record to the protocol
3093
+ const bobsRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
3094
+ author: bob,
3095
+ protocol: protocolDefinition.protocol,
3096
+ protocolPath: 'foo',
3097
+ permissionGrantId: permissionGrant.recordsWrite.message.recordId,
3098
+ });
3099
+ const bobsRecordsWriteReply = yield dwn.processMessage(alice.did, bobsRecordsWrite.message, { dataStream: bobsRecordsWrite.dataStream });
3100
+ expect(bobsRecordsWriteReply.status.code).to.equal(202);
3101
+ }));
3102
+ it('rejects writes of protocol records with mismatching protocolPath grant scopes', () => __awaiter(this, void 0, void 0, function* () {
3103
+ // scenario: Alice gives Bob a grant to write to a specific protocolPath. Bob tries and fails to
3104
+ // invoke the grant to write to another protocolPath.
3105
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
3106
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
3107
+ const protocolDefinition = minimalProtocolDefinition;
3108
+ // Alice installs the protocol
3109
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
3110
+ author: alice,
3111
+ protocolDefinition
3112
+ });
3113
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
3114
+ expect(protocolsConfigureReply.status.code).to.equal(202);
3115
+ // Alice gives Bob a permission grant
3116
+ const permissionGrant = yield PermissionsProtocol.createGrant({
3117
+ signer: Jws.createSigner(alice),
3118
+ grantedTo: bob.did,
3119
+ dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }), // 24 hours
3120
+ scope: {
3121
+ interface: DwnInterfaceName.Records,
3122
+ method: DwnMethodName.Write,
3123
+ protocol: protocolDefinition.protocol,
3124
+ protocolPath: 'some-other-protocol-path',
3125
+ }
3126
+ });
3127
+ const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
3128
+ const permissionGrantWriteReply = yield dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
3129
+ expect(permissionGrantWriteReply.status.code).to.equal(202);
3130
+ // Bob invokes the grant in order to write a record to the protocol
3131
+ const bobsRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
3132
+ author: bob,
3133
+ protocol: protocolDefinition.protocol,
3134
+ protocolPath: 'foo',
3135
+ permissionGrantId: permissionGrant.recordsWrite.message.recordId,
3136
+ });
3137
+ const bobsRecordsWriteReply = yield dwn.processMessage(alice.did, bobsRecordsWrite.message, { dataStream: bobsRecordsWrite.dataStream });
3138
+ expect(bobsRecordsWriteReply.status.code).to.equal(401);
3139
+ expect(bobsRecordsWriteReply.status.detail).to.contain(DwnErrorCode.RecordsGrantAuthorizationScopeProtocolPathMismatch);
3140
+ }));
3141
+ });
3142
+ describe('grant condition published', () => {
3143
+ it('Rejects unpublished records if grant condition `published` === required', () => __awaiter(this, void 0, void 0, function* () {
3144
+ // scenario: Alice gives Bob a grant with condition `published` === required.
3145
+ // Bob is able to write a public record but not able to write an unpublished record.
3146
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
3147
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
3148
+ // Alice installs a protocol
3149
+ const protocolDefinition = minimalProtocolDefinition;
3150
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
3151
+ author: alice,
3152
+ protocolDefinition,
3153
+ });
3154
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
3155
+ expect(protocolsConfigureReply.status.code).to.equal(202);
3156
+ // Alice creates a grant for Bob with `published` === required
3157
+ const permissionGrant = yield PermissionsProtocol.createGrant({
3158
+ signer: Jws.createSigner(alice),
3159
+ grantedTo: bob.did,
3160
+ dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }), // 24 hours
3161
+ scope: {
3162
+ interface: DwnInterfaceName.Records,
3163
+ method: DwnMethodName.Write,
3164
+ protocol: protocolDefinition.protocol,
3165
+ },
3166
+ conditions: {
3167
+ publication: PermissionConditionPublication.Required,
3168
+ }
3169
+ });
3170
+ const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
3171
+ const permissionGrantWriteReply = yield dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
3172
+ expect(permissionGrantWriteReply.status.code).to.equal(202);
3173
+ const permissionGrantId = permissionGrant.recordsWrite.message.recordId;
3174
+ // Bob is able to write a published record
3175
+ const publishedRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
3176
+ author: bob,
3177
+ protocol: protocolDefinition.protocol,
3178
+ protocolPath: 'foo',
3179
+ published: true,
3180
+ permissionGrantId
3181
+ });
3182
+ const publishedRecordsWriteReply = yield dwn.processMessage(alice.did, publishedRecordsWrite.message, { dataStream: publishedRecordsWrite.dataStream });
3183
+ expect(publishedRecordsWriteReply.status.code).to.equal(202);
3184
+ // Bob is not able to write an unpublished record
3185
+ const unpublishedRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
3186
+ author: bob,
3187
+ protocol: protocolDefinition.protocol,
3188
+ protocolPath: 'foo',
3189
+ published: false,
3190
+ permissionGrantId
3191
+ });
3192
+ const unpublishedRecordsWriteReply = yield dwn.processMessage(alice.did, unpublishedRecordsWrite.message, { dataStream: unpublishedRecordsWrite.dataStream });
3193
+ expect(unpublishedRecordsWriteReply.status.code).to.equal(401);
3194
+ expect(unpublishedRecordsWriteReply.status.detail).to.contain(DwnErrorCode.RecordsGrantAuthorizationConditionPublicationRequired);
3195
+ }));
3196
+ it('Rejects published records if grant condition `published` === prohibited', () => __awaiter(this, void 0, void 0, function* () {
3197
+ // scenario: Alice gives Bob a grant with condition `published` === prohibited.
3198
+ // Bob is able to write a unpublished record but not able to write a public record.
3199
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
3200
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
3201
+ // Alice installs a protocol
3202
+ const protocolDefinition = minimalProtocolDefinition;
3203
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
3204
+ author: alice,
3205
+ protocolDefinition,
3206
+ });
3207
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
3208
+ expect(protocolsConfigureReply.status.code).to.equal(202);
3209
+ // Alice creates a grant for Bob with `published` === prohibited
3210
+ const permissionGrant = yield PermissionsProtocol.createGrant({
3211
+ signer: Jws.createSigner(alice),
3212
+ grantedTo: bob.did,
3213
+ dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }), // 24 hours
3214
+ scope: {
3215
+ interface: DwnInterfaceName.Records,
3216
+ method: DwnMethodName.Write,
3217
+ protocol: protocolDefinition.protocol,
3218
+ },
3219
+ conditions: {
3220
+ publication: PermissionConditionPublication.Prohibited
3221
+ }
3222
+ });
3223
+ const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
3224
+ const permissionGrantWriteReply = yield dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
3225
+ expect(permissionGrantWriteReply.status.code).to.equal(202);
3226
+ const permissionGrantId = permissionGrant.recordsWrite.message.recordId;
3227
+ // Bob not is able to write a published record
3228
+ const publishedRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
3229
+ author: bob,
3230
+ protocol: protocolDefinition.protocol,
3231
+ protocolPath: 'foo',
3232
+ published: true,
3233
+ permissionGrantId
3234
+ });
3235
+ const publishedRecordsWriteReply = yield dwn.processMessage(alice.did, publishedRecordsWrite.message, { dataStream: publishedRecordsWrite.dataStream });
3236
+ expect(publishedRecordsWriteReply.status.code).to.equal(401);
3237
+ expect(publishedRecordsWriteReply.status.detail).to.contain(DwnErrorCode.RecordsGrantAuthorizationConditionPublicationProhibited);
3238
+ // Bob is able to write an unpublished record
3239
+ const unpublishedRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
3240
+ author: bob,
3241
+ protocol: protocolDefinition.protocol,
3242
+ protocolPath: 'foo',
3243
+ published: false,
3244
+ permissionGrantId
3245
+ });
3246
+ const unpublishedRecordsWriteReply = yield dwn.processMessage(alice.did, unpublishedRecordsWrite.message, { dataStream: unpublishedRecordsWrite.dataStream });
3247
+ expect(unpublishedRecordsWriteReply.status.code).to.equal(202);
3248
+ }));
3249
+ it('Allows both published and unpublished records if grant condition `published` is undefined', () => __awaiter(this, void 0, void 0, function* () {
3250
+ // scenario: Alice gives Bob a grant without condition `published`.
3251
+ // Bob is able to write both an unpublished record and a published record.
3252
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
3253
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
3254
+ // Alice installs a protocol
3255
+ const protocolDefinition = minimalProtocolDefinition;
3256
+ const protocolsConfig = yield TestDataGenerator.generateProtocolsConfigure({
3257
+ author: alice,
3258
+ protocolDefinition,
3259
+ });
3260
+ const protocolsConfigureReply = yield dwn.processMessage(alice.did, protocolsConfig.message);
3261
+ expect(protocolsConfigureReply.status.code).to.equal(202);
3262
+ // Alice creates a grant for Bob with `published` === prohibited
3263
+ const permissionGrant = yield PermissionsProtocol.createGrant({
3264
+ signer: Jws.createSigner(alice),
3265
+ grantedTo: bob.did,
3266
+ dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }), // 24 hours
3267
+ scope: {
3268
+ interface: DwnInterfaceName.Records,
3269
+ method: DwnMethodName.Write,
3270
+ protocol: protocolDefinition.protocol,
3271
+ },
3272
+ conditions: {
3273
+ // publication: '', // intentionally undefined
3274
+ }
3275
+ });
3276
+ const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
3277
+ const permissionGrantWriteReply = yield dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
3278
+ expect(permissionGrantWriteReply.status.code).to.equal(202);
3279
+ const permissionGrantId = permissionGrant.recordsWrite.message.recordId;
3280
+ // Bob is able to write a published record
3281
+ const publishedRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
3282
+ author: bob,
3283
+ protocol: protocolDefinition.protocol,
3284
+ protocolPath: 'foo',
3285
+ published: true,
3286
+ permissionGrantId
3287
+ });
3288
+ const publishedRecordsWriteReply = yield dwn.processMessage(alice.did, publishedRecordsWrite.message, { dataStream: publishedRecordsWrite.dataStream });
3289
+ expect(publishedRecordsWriteReply.status.code).to.equal(202);
3290
+ // Bob is able to write an unpublished record
3291
+ const unpublishedRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
3292
+ author: bob,
3293
+ protocol: protocolDefinition.protocol,
3294
+ protocolPath: 'foo',
3295
+ published: false,
3296
+ permissionGrantId
3297
+ });
3298
+ const unpublishedRecordsWriteReply = yield dwn.processMessage(alice.did, unpublishedRecordsWrite.message, { dataStream: unpublishedRecordsWrite.dataStream });
3299
+ expect(unpublishedRecordsWriteReply.status.code).to.equal(202);
3300
+ }));
3301
+ });
3302
+ });
3303
+ it('should return 400 if dataStream is not provided and dataStore does not contain dataCid', () => __awaiter(this, void 0, void 0, function* () {
3304
+ // scenario: A sync writes a pruned initial RecordsWrite, without a `dataStream`. Alice does another regular
3305
+ // RecordsWrite for the same record, referencing the same `dataCid` but omitting the `dataStream`.
3306
+ // Pruned RecordsWrite
3307
+ // Data large enough to use the DataStore
3308
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
3309
+ const data = TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1);
3310
+ const prunedRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
3311
+ author: alice,
3312
+ published: false,
3313
+ data,
3314
+ });
3315
+ const prunedRecordsWriteReply = yield dwn.processMessage(alice.did, prunedRecordsWrite.message);
3316
+ expect(prunedRecordsWriteReply.status.code).to.equal(204);
3317
+ // Update record to published, omitting dataStream
3318
+ const recordsWrite = yield TestDataGenerator.generateFromRecordsWrite({
3319
+ author: alice,
3320
+ existingWrite: prunedRecordsWrite.recordsWrite,
3321
+ published: true,
3322
+ data,
3323
+ });
3324
+ const recordsWriteReply = yield dwn.processMessage(alice.did, recordsWrite.message);
3325
+ expect(recordsWriteReply.status.code).to.equal(400);
3326
+ expect(recordsWriteReply.status.detail).to.contain(DwnErrorCode.RecordsWriteMissingDataInPrevious);
3327
+ }));
3328
+ it('should return 400 if dataStream is not provided and previous message does not contain encodedData', () => __awaiter(this, void 0, void 0, function* () {
3329
+ // scenario: A sync writes a pruned initial RecordsWrite, without a `dataStream`. Alice does another regular
3330
+ // RecordsWrite for the same record, referencing the same `dataCid` but omitting the `dataStream`.
3331
+ // Pruned RecordsWrite
3332
+ // Data that would be encoded within the message
3333
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
3334
+ const data = TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded);
3335
+ const prunedRecordsWrite = yield TestDataGenerator.generateRecordsWrite({
3336
+ author: alice,
3337
+ published: false,
3338
+ data,
3339
+ });
3340
+ const prunedRecordsWriteReply = yield dwn.processMessage(alice.did, prunedRecordsWrite.message);
3341
+ expect(prunedRecordsWriteReply.status.code).to.equal(204);
3342
+ // Update record to published, omitting dataStream
3343
+ const recordsWrite = yield TestDataGenerator.generateFromRecordsWrite({
3344
+ author: alice,
3345
+ existingWrite: prunedRecordsWrite.recordsWrite,
3346
+ published: true,
3347
+ data,
3348
+ });
3349
+ const recordsWriteReply = yield dwn.processMessage(alice.did, recordsWrite.message);
3350
+ expect(recordsWriteReply.status.code).to.equal(400);
3351
+ expect(recordsWriteReply.status.detail).to.contain(DwnErrorCode.RecordsWriteMissingEncodedDataInPrevious);
3352
+ }));
3353
+ it('should return 400 if attempting a write after a delete', () => __awaiter(this, void 0, void 0, function* () {
3354
+ const { message, author, dataStream } = yield TestDataGenerator.generateRecordsWrite({
3355
+ data: TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded),
3356
+ published: false
3357
+ });
3358
+ const tenant = author.did;
3359
+ TestStubGenerator.stubDidResolver(didResolver, [author]);
3360
+ const initialWriteReply = yield dwn.processMessage(tenant, message, { dataStream });
3361
+ expect(initialWriteReply.status.code).to.equal(202);
3362
+ const recordsDelete = yield RecordsDelete.create({
3363
+ recordId: message.recordId,
3364
+ signer: Jws.createSigner(author),
3365
+ });
3366
+ const deleteReply = yield dwn.processMessage(tenant, recordsDelete.message);
3367
+ expect(deleteReply.status.code).to.equal(202);
3368
+ const newDataBytes = TestDataGenerator.randomBytes(100);
3369
+ const newInvalidWrite = yield RecordsWrite.createFrom({
3370
+ recordsWriteMessage: message,
3371
+ signer: Jws.createSigner(author),
3372
+ data: newDataBytes
3373
+ });
3374
+ const newInvalidWriteReply = yield dwn.processMessage(tenant, newInvalidWrite.message, { dataStream: DataStream.fromBytes(newDataBytes) });
3375
+ expect(newInvalidWriteReply.status.code).to.equal(400);
3376
+ expect(newInvalidWriteReply.status.detail).to.contain(DwnErrorCode.RecordsWriteNotAllowedAfterDelete);
3377
+ }));
3378
+ it('should not allow referencing data across tenants', () => __awaiter(this, void 0, void 0, function* () {
3379
+ var _a, _b, _c;
3380
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
3381
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
3382
+ const data = Encoder.stringToBytes('test');
3383
+ const dataCid = yield Cid.computeDagPbCidFromBytes(data);
3384
+ const encodedData = Encoder.bytesToBase64Url(data);
3385
+ // alice writes data to her DWN
3386
+ const aliceWriteData = yield TestDataGenerator.generateRecordsWrite({
3387
+ author: alice,
3388
+ data
3389
+ });
3390
+ const aliceWriteReply = yield dwn.processMessage(alice.did, aliceWriteData.message, { dataStream: aliceWriteData.dataStream });
3391
+ expect(aliceWriteReply.status.code).to.equal(202);
3392
+ const aliceQueryWriteAfterAliceWriteData = yield TestDataGenerator.generateRecordsQuery({
3393
+ author: alice,
3394
+ filter: { recordId: aliceWriteData.message.recordId }
3395
+ });
3396
+ const aliceQueryWriteAfterAliceWriteReply = yield dwn.processMessage(alice.did, aliceQueryWriteAfterAliceWriteData.message);
3397
+ expect(aliceQueryWriteAfterAliceWriteReply.status.code).to.equal(200);
3398
+ expect((_a = aliceQueryWriteAfterAliceWriteReply.entries) === null || _a === void 0 ? void 0 : _a.length).to.equal(1);
3399
+ expect(aliceQueryWriteAfterAliceWriteReply.entries[0].encodedData).to.equal(encodedData);
3400
+ // bob learns of the CID of data of alice and tries to gain unauthorized access by referencing it in his own DWN
3401
+ const bobWriteData = yield TestDataGenerator.generateRecordsWrite({
3402
+ author: bob,
3403
+ dataCid,
3404
+ dataSize: 4
3405
+ });
3406
+ const bobWriteReply = yield dwn.processMessage(bob.did, bobWriteData.message); // intentionally missing data stream
3407
+ expect(bobWriteReply.status.code).to.equal(204); // NOTE: allows write here but does not allow read or query later
3408
+ const aliceQueryWriteAfterBobWriteData = yield TestDataGenerator.generateRecordsQuery({
3409
+ author: alice,
3410
+ filter: { recordId: aliceWriteData.message.recordId }
3411
+ });
3412
+ const aliceQueryWriteAfterBobWriteReply = yield dwn.processMessage(alice.did, aliceQueryWriteAfterBobWriteData.message);
3413
+ expect(aliceQueryWriteAfterBobWriteReply.status.code).to.equal(200);
3414
+ expect((_b = aliceQueryWriteAfterBobWriteReply.entries) === null || _b === void 0 ? void 0 : _b.length).to.equal(1);
3415
+ expect(aliceQueryWriteAfterBobWriteReply.entries[0].encodedData).to.equal(encodedData);
3416
+ // verify that bob has not gained access to alice's data
3417
+ const bobQueryAfterBobWriteData = yield TestDataGenerator.generateRecordsQuery({
3418
+ author: bob,
3419
+ filter: { recordId: bobWriteData.message.recordId }
3420
+ });
3421
+ const bobQueryAfterBobWriteReply = yield dwn.processMessage(bob.did, bobQueryAfterBobWriteData.message);
3422
+ expect(bobQueryAfterBobWriteReply.status.code).to.equal(200);
3423
+ expect((_c = bobQueryAfterBobWriteReply.entries) === null || _c === void 0 ? void 0 : _c.length).to.equal(0);
3424
+ }));
3425
+ describe('encodedData threshold', () => __awaiter(this, void 0, void 0, function* () {
3426
+ it('should call cloneAndAddEncodedData if dataSize is less than or equal to the threshold', () => __awaiter(this, void 0, void 0, function* () {
3427
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
3428
+ const dataBytes = TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded);
3429
+ const { message, dataStream } = yield TestDataGenerator.generateRecordsWrite({ author: alice, data: dataBytes });
3430
+ const processEncoded = sinon.spy(RecordsWriteHandler.prototype, 'cloneAndAddEncodedData');
3431
+ const writeMessage = yield dwn.processMessage(alice.did, message, { dataStream });
3432
+ expect(writeMessage.status.code).to.equal(202);
3433
+ sinon.assert.calledOnce(processEncoded);
3434
+ }));
3435
+ it('should not call cloneAndAddEncodedData if dataSize is greater than the threshold', () => __awaiter(this, void 0, void 0, function* () {
3436
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
3437
+ const dataBytes = TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1);
3438
+ const { message, dataStream } = yield TestDataGenerator.generateRecordsWrite({ author: alice, data: dataBytes });
3439
+ const processEncoded = sinon.spy(RecordsWriteHandler.prototype, 'cloneAndAddEncodedData');
3440
+ const writeMessage = yield dwn.processMessage(alice.did, message, { dataStream });
3441
+ expect(writeMessage.status.code).to.equal(202);
3442
+ sinon.assert.notCalled(processEncoded);
3443
+ }));
3444
+ it('should have encodedData field if dataSize is less than or equal to the threshold', () => __awaiter(this, void 0, void 0, function* () {
3445
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
3446
+ const dataBytes = TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded);
3447
+ const { message, dataStream } = yield TestDataGenerator.generateRecordsWrite({ author: alice, data: dataBytes });
3448
+ const writeMessage = yield dwn.processMessage(alice.did, message, { dataStream });
3449
+ expect(writeMessage.status.code).to.equal(202);
3450
+ const messageCid = yield Message.getCid(message);
3451
+ const storedMessage = yield messageStore.get(alice.did, messageCid);
3452
+ expect(storedMessage.encodedData).to.exist.and.not.be.undefined;
3453
+ }));
3454
+ it('should not have encodedData field if dataSize greater than threshold', () => __awaiter(this, void 0, void 0, function* () {
3455
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
3456
+ const dataBytes = TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded + 1);
3457
+ const { message, dataStream } = yield TestDataGenerator.generateRecordsWrite({ author: alice, data: dataBytes });
3458
+ const writeMessage = yield dwn.processMessage(alice.did, message, { dataStream });
3459
+ expect(writeMessage.status.code).to.equal(202);
3460
+ const messageCid = yield Message.getCid(message);
3461
+ const storedMessage = yield messageStore.get(alice.did, messageCid);
3462
+ expect(storedMessage.encodedData).to.not.exist;
3463
+ }));
3464
+ it('should retain original RecordsWrite message but without the encodedData if data is under threshold', () => __awaiter(this, void 0, void 0, function* () {
3465
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
3466
+ const dataBytes = TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded);
3467
+ const { message, dataStream } = yield TestDataGenerator.generateRecordsWrite({ author: alice, data: dataBytes });
3468
+ const writeMessage = yield dwn.processMessage(alice.did, message, { dataStream });
3469
+ expect(writeMessage.status.code).to.equal(202);
3470
+ const messageCid = yield Message.getCid(message);
3471
+ const storedMessage = yield messageStore.get(alice.did, messageCid);
3472
+ expect(storedMessage.encodedData).to.exist.and.not.be.undefined;
3473
+ const updatedDataBytes = TestDataGenerator.randomBytes(DwnConstant.maxDataSizeAllowedToBeEncoded);
3474
+ const newWrite = yield RecordsWrite.createFrom({
3475
+ recordsWriteMessage: message,
3476
+ published: true,
3477
+ signer: Jws.createSigner(alice),
3478
+ data: updatedDataBytes,
3479
+ });
3480
+ const updateDataStream = DataStream.fromBytes(updatedDataBytes);
3481
+ const writeMessage2 = yield dwn.processMessage(alice.did, newWrite.message, { dataStream: updateDataStream });
3482
+ expect(writeMessage2.status.code).to.equal(202);
3483
+ const originalWrite = yield messageStore.get(alice.did, messageCid);
3484
+ expect(originalWrite.encodedData).to.not.exist;
3485
+ const newestWrite = yield messageStore.get(alice.did, yield Message.getCid(newWrite.message));
3486
+ expect(newestWrite.encodedData).to.exist.and.not.be.undefined;
3487
+ }));
3488
+ }));
3489
+ });
3490
+ describe('authorization validation tests', () => {
3491
+ it('should return 400 if `recordId` in payload of the message signature mismatches with `recordId` in the message', () => __awaiter(this, void 0, void 0, function* () {
3492
+ const { author, message, recordsWrite, dataStream } = yield TestDataGenerator.generateRecordsWrite();
3493
+ // replace signature with mismatching `recordId`, even though signature is still valid
3494
+ const signaturePayload = Object.assign({}, recordsWrite.signaturePayload);
3495
+ signaturePayload.recordId = yield TestDataGenerator.randomCborSha256Cid(); // make recordId mismatch in authorization payload
3496
+ const signaturePayloadBytes = Encoder.objectToBytes(signaturePayload);
3497
+ const signer = Jws.createSigner(author);
3498
+ const jwsBuilder = yield GeneralJwsBuilder.create(signaturePayloadBytes, [signer]);
3499
+ message.authorization = { signature: jwsBuilder.getJws() };
3500
+ const tenant = author.did;
3501
+ const didResolver = TestStubGenerator.createDidResolverStub(author);
3502
+ const messageStoreStub = sinon.createStubInstance(MessageStoreLevel);
3503
+ const dataStoreStub = sinon.createStubInstance(DataStoreLevel);
3504
+ const recordsWriteHandler = new RecordsWriteHandler(didResolver, messageStoreStub, dataStoreStub, eventLog, eventStream);
3505
+ const reply = yield recordsWriteHandler.handle({ tenant, message, dataStream: dataStream });
3506
+ expect(reply.status.code).to.equal(400);
3507
+ expect(reply.status.detail).to.contain('does not match recordId in authorization');
3508
+ }));
3509
+ it('should return 400 if `contextId` in payload of message signature mismatches with `contextId` in the message', () => __awaiter(this, void 0, void 0, function* () {
3510
+ // generate a message with protocol so that computed contextId is also computed and included in message
3511
+ const { author, message, recordsWrite, dataStream } = yield TestDataGenerator.generateRecordsWrite({ protocol: 'http://any.value', protocolPath: 'any/value' });
3512
+ // replace `authorization` with mismatching `contextId`, even though signature is still valid
3513
+ const signaturePayload = Object.assign({}, recordsWrite.signaturePayload);
3514
+ signaturePayload.contextId = yield TestDataGenerator.randomCborSha256Cid(); // make contextId mismatch in authorization payload
3515
+ const signaturePayloadBytes = Encoder.objectToBytes(signaturePayload);
3516
+ const signer = Jws.createSigner(author);
3517
+ const jwsBuilder = yield GeneralJwsBuilder.create(signaturePayloadBytes, [signer]);
3518
+ message.authorization = { signature: jwsBuilder.getJws() };
3519
+ const tenant = author.did;
3520
+ const didResolver = sinon.createStubInstance(UniversalResolver);
3521
+ const messageStoreStub = sinon.createStubInstance(MessageStoreLevel);
3522
+ const dataStoreStub = sinon.createStubInstance(DataStoreLevel);
3523
+ const recordsWriteHandler = new RecordsWriteHandler(didResolver, messageStoreStub, dataStoreStub, eventLog, eventStream);
3524
+ const reply = yield recordsWriteHandler.handle({ tenant, message, dataStream: dataStream });
3525
+ expect(reply.status.code).to.equal(400);
3526
+ expect(reply.status.detail).to.contain('does not match contextId in authorization');
3527
+ }));
3528
+ it('should return 401 if `authorization` signature check fails', () => __awaiter(this, void 0, void 0, function* () {
3529
+ const { author, message, dataStream } = yield TestDataGenerator.generateRecordsWrite();
3530
+ const tenant = author.did;
3531
+ // setting up a stub DID resolver & message store
3532
+ // intentionally not supplying the public key so a different public key is generated to simulate invalid signature
3533
+ const mismatchingPersona = yield TestDataGenerator.generatePersona({ did: author.did, keyId: author.keyId });
3534
+ const didResolver = TestStubGenerator.createDidResolverStub(mismatchingPersona);
3535
+ const messageStoreStub = sinon.createStubInstance(MessageStoreLevel);
3536
+ const dataStoreStub = sinon.createStubInstance(DataStoreLevel);
3537
+ const recordsWriteHandler = new RecordsWriteHandler(didResolver, messageStoreStub, dataStoreStub, eventLog, eventStream);
3538
+ const reply = yield recordsWriteHandler.handle({ tenant, message, dataStream: dataStream });
3539
+ expect(reply.status.code).to.equal(401);
3540
+ }));
3541
+ it('should return 401 if an unauthorized author is attempting write', () => __awaiter(this, void 0, void 0, function* () {
3542
+ const author = yield TestDataGenerator.generatePersona();
3543
+ const { message, dataStream } = yield TestDataGenerator.generateRecordsWrite({ author });
3544
+ // setting up a stub DID resolver & message store
3545
+ const didResolver = TestStubGenerator.createDidResolverStub(author);
3546
+ const messageStoreStub = sinon.createStubInstance(MessageStoreLevel);
3547
+ const dataStoreStub = sinon.createStubInstance(DataStoreLevel);
3548
+ const recordsWriteHandler = new RecordsWriteHandler(didResolver, messageStoreStub, dataStoreStub, eventLog, eventStream);
3549
+ const tenant = yield (yield TestDataGenerator.generatePersona()).did; // unauthorized tenant
3550
+ const reply = yield recordsWriteHandler.handle({ tenant, message, dataStream: dataStream });
3551
+ expect(reply.status.code).to.equal(401);
3552
+ }));
3553
+ });
3554
+ describe('attestation validation tests', () => {
3555
+ it('should fail with 400 if `attestation` payload contains properties other than `descriptorCid`', () => __awaiter(this, void 0, void 0, function* () {
3556
+ const { author, message, recordsWrite, dataStream } = yield TestDataGenerator.generateRecordsWrite();
3557
+ const tenant = author.did;
3558
+ const signer = Jws.createSigner(author);
3559
+ // replace `attestation` with one that has an additional property, but go the extra mile of making sure signature is valid
3560
+ const descriptorCid = recordsWrite.signaturePayload.descriptorCid;
3561
+ const attestationPayload = { descriptorCid, someAdditionalProperty: 'anyValue' }; // additional property is not allowed
3562
+ const attestationPayloadBytes = Encoder.objectToBytes(attestationPayload);
3563
+ const attestationBuilder = yield GeneralJwsBuilder.create(attestationPayloadBytes, [signer]);
3564
+ message.attestation = attestationBuilder.getJws();
3565
+ // recreate the `authorization` based on the new` attestationCid`
3566
+ const signaturePayload = Object.assign({}, recordsWrite.signaturePayload);
3567
+ signaturePayload.attestationCid = yield Cid.computeCid(attestationPayload);
3568
+ const signaturePayloadBytes = Encoder.objectToBytes(signaturePayload);
3569
+ const authorizationBuilder = yield GeneralJwsBuilder.create(signaturePayloadBytes, [signer]);
3570
+ message.authorization = { signature: authorizationBuilder.getJws() };
3571
+ const didResolver = TestStubGenerator.createDidResolverStub(author);
3572
+ const messageStoreStub = sinon.createStubInstance(MessageStoreLevel);
3573
+ const dataStoreStub = sinon.createStubInstance(DataStoreLevel);
3574
+ const recordsWriteHandler = new RecordsWriteHandler(didResolver, messageStoreStub, dataStoreStub, eventLog, eventStream);
3575
+ const reply = yield recordsWriteHandler.handle({ tenant, message, dataStream: dataStream });
3576
+ expect(reply.status.code).to.equal(400);
3577
+ expect(reply.status.detail).to.contain(`Only 'descriptorCid' is allowed in attestation payload`);
3578
+ }));
3579
+ it('should fail validation with 400 if more than 1 attester is given ', () => __awaiter(this, void 0, void 0, function* () {
3580
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
3581
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
3582
+ const { message, dataStream } = yield TestDataGenerator.generateRecordsWrite({ author: alice, attesters: [alice, bob] });
3583
+ const recordsWriteHandler = new RecordsWriteHandler(didResolver, messageStore, dataStore, eventLog, eventStream);
3584
+ const writeReply = yield recordsWriteHandler.handle({ tenant: alice.did, message, dataStream: dataStream });
3585
+ expect(writeReply.status.code).to.equal(400);
3586
+ expect(writeReply.status.detail).to.contain('implementation only supports 1 attester');
3587
+ }));
3588
+ it('should fail validation with 400 if the `attestation` does not include the correct `descriptorCid`', () => __awaiter(this, void 0, void 0, function* () {
3589
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
3590
+ const { message, dataStream } = yield TestDataGenerator.generateRecordsWrite({ author: alice, attesters: [alice] });
3591
+ // create another write and use its `attestation` value instead, that `attestation` will point to an entirely different `descriptorCid`
3592
+ const anotherWrite = yield TestDataGenerator.generateRecordsWrite({ attesters: [alice] });
3593
+ message.attestation = anotherWrite.message.attestation;
3594
+ const recordsWriteHandler = new RecordsWriteHandler(didResolver, messageStore, dataStore, eventLog, eventStream);
3595
+ const writeReply = yield recordsWriteHandler.handle({ tenant: alice.did, message, dataStream: dataStream });
3596
+ expect(writeReply.status.code).to.equal(400);
3597
+ expect(writeReply.status.detail).to.contain('does not match expected descriptorCid');
3598
+ }));
3599
+ it('should fail validation with 400 if expected CID of `attestation` mismatches the `attestationCid` in `authorization`', () => __awaiter(this, void 0, void 0, function* () {
3600
+ const alice = yield TestDataGenerator.generateDidKeyPersona();
3601
+ const { message, dataStream } = yield TestDataGenerator.generateRecordsWrite({ author: alice, attesters: [alice] });
3602
+ // replace valid attestation (the one signed by `authorization` with another attestation to the same message (descriptorCid)
3603
+ const bob = yield TestDataGenerator.generateDidKeyPersona();
3604
+ const descriptorCid = yield Cid.computeCid(message.descriptor);
3605
+ const attestationNotReferencedByAuthorization = yield RecordsWrite['createAttestation'](descriptorCid, Jws.createSigners([bob]));
3606
+ message.attestation = attestationNotReferencedByAuthorization;
3607
+ const recordsWriteHandler = new RecordsWriteHandler(didResolver, messageStore, dataStore, eventLog, eventStream);
3608
+ const writeReply = yield recordsWriteHandler.handle({ tenant: alice.did, message, dataStream: dataStream });
3609
+ expect(writeReply.status.code).to.equal(400);
3610
+ expect(writeReply.status.detail).to.contain('does not match attestationCid');
3611
+ }));
3612
+ });
3613
+ describe('unknown error', () => {
3614
+ it('should throw if `recordsWriteHandler.processMessageWithoutDataStream()` throws unknown error', () => __awaiter(this, void 0, void 0, function* () {
3615
+ // simulate an initial write to test non-data path, as initial writes without data are always accepted (bot not readable)
3616
+ // https://github.com/TBD54566975/dwn-sdk-js/issues/628
3617
+ const { author, message: initialWriteMessage, recordsWrite: initialWrite } = yield TestDataGenerator.generateRecordsWrite();
3618
+ yield Time.minimalSleep();
3619
+ const { message, dataStream } = yield TestDataGenerator.generateFromRecordsWrite({ author, existingWrite: initialWrite });
3620
+ const tenant = author.did;
3621
+ const didResolverStub = TestStubGenerator.createDidResolverStub(author);
3622
+ const messageStoreStub = sinon.createStubInstance(MessageStoreLevel);
3623
+ messageStoreStub.query.resolves({ messages: [initialWriteMessage] });
3624
+ const dataStoreStub = sinon.createStubInstance(DataStoreLevel);
3625
+ const recordsWriteHandler = new RecordsWriteHandler(didResolverStub, messageStoreStub, dataStoreStub, eventLog, eventStream);
3626
+ // simulate throwing unexpected error
3627
+ sinon.stub(recordsWriteHandler, 'processMessageWithoutDataStream').throws(new Error('an unknown error in recordsWriteHandler.processMessageWithoutDataStream()'));
3628
+ sinon.stub(recordsWriteHandler, 'processMessageWithDataStream').throws(new Error('an unknown error in recordsWriteHandler.processMessageWithDataStream()'));
3629
+ let handlerPromise = recordsWriteHandler.handle({ tenant, message, dataStream: dataStream }); // with data stream
3630
+ yield expect(handlerPromise).to.be.rejectedWith('an unknown error in recordsWriteHandler.processMessageWithDataStream()');
3631
+ handlerPromise = recordsWriteHandler.handle({ tenant, message }); // without data stream
3632
+ yield expect(handlerPromise).to.be.rejectedWith('an unknown error in recordsWriteHandler.processMessageWithoutDataStream()');
3633
+ }));
3634
+ });
3635
+ }));
3636
+ }
3637
+ //# sourceMappingURL=records-write.spec.js.map