@abaxxtech/id 0.0.0

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