@enbox/dwn-sdk-js 0.3.7 → 0.3.8

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 (230) hide show
  1. package/dist/browser.mjs +8 -8
  2. package/dist/browser.mjs.map +4 -4
  3. package/dist/esm/generated/precompiled-validators.js +2591 -1435
  4. package/dist/esm/generated/precompiled-validators.js.map +1 -1
  5. package/dist/esm/src/core/constants.js +20 -0
  6. package/dist/esm/src/core/constants.js.map +1 -1
  7. package/dist/esm/src/core/dwn-error.js +24 -1
  8. package/dist/esm/src/core/dwn-error.js.map +1 -1
  9. package/dist/esm/src/core/grant-authorization.js +4 -4
  10. package/dist/esm/src/core/grant-authorization.js.map +1 -1
  11. package/dist/esm/src/core/message.js +89 -4
  12. package/dist/esm/src/core/message.js.map +1 -1
  13. package/dist/esm/src/core/messages-grant-authorization.js +147 -55
  14. package/dist/esm/src/core/messages-grant-authorization.js.map +1 -1
  15. package/dist/esm/src/core/protocol-authorization.js +76 -0
  16. package/dist/esm/src/core/protocol-authorization.js.map +1 -1
  17. package/dist/esm/src/core/records-grant-authorization.js +40 -15
  18. package/dist/esm/src/core/records-grant-authorization.js.map +1 -1
  19. package/dist/esm/src/handlers/messages-read.js +5 -5
  20. package/dist/esm/src/handlers/messages-read.js.map +1 -1
  21. package/dist/esm/src/handlers/messages-subscribe.js +109 -7
  22. package/dist/esm/src/handlers/messages-subscribe.js.map +1 -1
  23. package/dist/esm/src/handlers/messages-sync.js +341 -96
  24. package/dist/esm/src/handlers/messages-sync.js.map +1 -1
  25. package/dist/esm/src/handlers/protocols-configure.js +81 -2
  26. package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
  27. package/dist/esm/src/handlers/records-count.js +30 -0
  28. package/dist/esm/src/handlers/records-count.js.map +1 -1
  29. package/dist/esm/src/handlers/records-delete.js +3 -2
  30. package/dist/esm/src/handlers/records-delete.js.map +1 -1
  31. package/dist/esm/src/handlers/records-query.js +30 -0
  32. package/dist/esm/src/handlers/records-query.js.map +1 -1
  33. package/dist/esm/src/handlers/records-read.js +3 -2
  34. package/dist/esm/src/handlers/records-read.js.map +1 -1
  35. package/dist/esm/src/handlers/records-subscribe.js +31 -0
  36. package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
  37. package/dist/esm/src/handlers/records-write.js +3 -2
  38. package/dist/esm/src/handlers/records-write.js.map +1 -1
  39. package/dist/esm/src/index.js +2 -0
  40. package/dist/esm/src/index.js.map +1 -1
  41. package/dist/esm/src/interfaces/messages-read.js +6 -3
  42. package/dist/esm/src/interfaces/messages-read.js.map +1 -1
  43. package/dist/esm/src/interfaces/messages-subscribe.js +6 -3
  44. package/dist/esm/src/interfaces/messages-subscribe.js.map +1 -1
  45. package/dist/esm/src/interfaces/messages-sync.js +17 -3
  46. package/dist/esm/src/interfaces/messages-sync.js.map +1 -1
  47. package/dist/esm/src/interfaces/protocols-configure.js +5 -2
  48. package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
  49. package/dist/esm/src/interfaces/protocols-query.js +8 -4
  50. package/dist/esm/src/interfaces/protocols-query.js.map +1 -1
  51. package/dist/esm/src/interfaces/records-count.js +5 -0
  52. package/dist/esm/src/interfaces/records-count.js.map +1 -1
  53. package/dist/esm/src/interfaces/records-delete.js +6 -2
  54. package/dist/esm/src/interfaces/records-delete.js.map +1 -1
  55. package/dist/esm/src/interfaces/records-query.js +5 -0
  56. package/dist/esm/src/interfaces/records-query.js.map +1 -1
  57. package/dist/esm/src/interfaces/records-read.js +6 -3
  58. package/dist/esm/src/interfaces/records-read.js.map +1 -1
  59. package/dist/esm/src/interfaces/records-subscribe.js +5 -0
  60. package/dist/esm/src/interfaces/records-subscribe.js.map +1 -1
  61. package/dist/esm/src/interfaces/records-write.js +6 -3
  62. package/dist/esm/src/interfaces/records-write.js.map +1 -1
  63. package/dist/esm/src/protocols/permissions.js +28 -7
  64. package/dist/esm/src/protocols/permissions.js.map +1 -1
  65. package/dist/esm/src/sync/records-projection.js +228 -0
  66. package/dist/esm/src/sync/records-projection.js.map +1 -0
  67. package/dist/esm/src/types/message-types.js.map +1 -1
  68. package/dist/esm/src/types/permission-types.js.map +1 -1
  69. package/dist/esm/src/utils/permission-scope.js +37 -0
  70. package/dist/esm/src/utils/permission-scope.js.map +1 -0
  71. package/dist/esm/tests/core/grant-authorization.spec.js +26 -3
  72. package/dist/esm/tests/core/grant-authorization.spec.js.map +1 -1
  73. package/dist/esm/tests/core/records-grant-authorization.spec.js +117 -0
  74. package/dist/esm/tests/core/records-grant-authorization.spec.js.map +1 -0
  75. package/dist/esm/tests/features/permissions.spec.js +126 -0
  76. package/dist/esm/tests/features/permissions.spec.js.map +1 -1
  77. package/dist/esm/tests/handlers/messages-read.spec.js +345 -12
  78. package/dist/esm/tests/handlers/messages-read.spec.js.map +1 -1
  79. package/dist/esm/tests/handlers/messages-subscribe.spec.js +326 -9
  80. package/dist/esm/tests/handlers/messages-subscribe.spec.js.map +1 -1
  81. package/dist/esm/tests/handlers/messages-sync.spec.js +1053 -7
  82. package/dist/esm/tests/handlers/messages-sync.spec.js.map +1 -1
  83. package/dist/esm/tests/handlers/protocols-configure.spec.js +361 -0
  84. package/dist/esm/tests/handlers/protocols-configure.spec.js.map +1 -1
  85. package/dist/esm/tests/handlers/records-count.spec.js +75 -2
  86. package/dist/esm/tests/handlers/records-count.spec.js.map +1 -1
  87. package/dist/esm/tests/handlers/records-query.spec.js +73 -0
  88. package/dist/esm/tests/handlers/records-query.spec.js.map +1 -1
  89. package/dist/esm/tests/handlers/records-subscribe.spec.js +75 -1
  90. package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
  91. package/dist/esm/tests/interfaces/messages-get.spec.js +107 -5
  92. package/dist/esm/tests/interfaces/messages-get.spec.js.map +1 -1
  93. package/dist/esm/tests/interfaces/protocols-configure.spec.js +13 -0
  94. package/dist/esm/tests/interfaces/protocols-configure.spec.js.map +1 -1
  95. package/dist/esm/tests/interfaces/records-delete.spec.js +12 -0
  96. package/dist/esm/tests/interfaces/records-delete.spec.js.map +1 -1
  97. package/dist/esm/tests/interfaces/records-query.spec.js +10 -0
  98. package/dist/esm/tests/interfaces/records-query.spec.js.map +1 -1
  99. package/dist/esm/tests/interfaces/records-subscribe.spec.js +10 -0
  100. package/dist/esm/tests/interfaces/records-subscribe.spec.js.map +1 -1
  101. package/dist/esm/tests/interfaces/records-write.spec.js +33 -0
  102. package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
  103. package/dist/esm/tests/sync/records-projection.spec.js +245 -0
  104. package/dist/esm/tests/sync/records-projection.spec.js.map +1 -0
  105. package/dist/esm/tests/test-suite.js +2 -0
  106. package/dist/esm/tests/test-suite.js.map +1 -1
  107. package/dist/esm/tests/utils/permission-scope.spec.js +66 -0
  108. package/dist/esm/tests/utils/permission-scope.spec.js.map +1 -0
  109. package/dist/esm/tests/utils/test-data-generator.js +5 -2
  110. package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
  111. package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
  112. package/dist/types/src/core/constants.d.ts +13 -0
  113. package/dist/types/src/core/constants.d.ts.map +1 -1
  114. package/dist/types/src/core/dwn-error.d.ts +24 -1
  115. package/dist/types/src/core/dwn-error.d.ts.map +1 -1
  116. package/dist/types/src/core/grant-authorization.d.ts +1 -2
  117. package/dist/types/src/core/grant-authorization.d.ts.map +1 -1
  118. package/dist/types/src/core/message.d.ts +41 -1
  119. package/dist/types/src/core/message.d.ts.map +1 -1
  120. package/dist/types/src/core/messages-grant-authorization.d.ts +36 -4
  121. package/dist/types/src/core/messages-grant-authorization.d.ts.map +1 -1
  122. package/dist/types/src/core/protocol-authorization.d.ts +12 -0
  123. package/dist/types/src/core/protocol-authorization.d.ts.map +1 -1
  124. package/dist/types/src/core/records-grant-authorization.d.ts +6 -0
  125. package/dist/types/src/core/records-grant-authorization.d.ts.map +1 -1
  126. package/dist/types/src/handlers/messages-read.d.ts.map +1 -1
  127. package/dist/types/src/handlers/messages-subscribe.d.ts +2 -1
  128. package/dist/types/src/handlers/messages-subscribe.d.ts.map +1 -1
  129. package/dist/types/src/handlers/messages-sync.d.ts +31 -0
  130. package/dist/types/src/handlers/messages-sync.d.ts.map +1 -1
  131. package/dist/types/src/handlers/protocols-configure.d.ts +3 -0
  132. package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
  133. package/dist/types/src/handlers/records-count.d.ts +4 -0
  134. package/dist/types/src/handlers/records-count.d.ts.map +1 -1
  135. package/dist/types/src/handlers/records-delete.d.ts.map +1 -1
  136. package/dist/types/src/handlers/records-query.d.ts +4 -0
  137. package/dist/types/src/handlers/records-query.d.ts.map +1 -1
  138. package/dist/types/src/handlers/records-read.d.ts.map +1 -1
  139. package/dist/types/src/handlers/records-subscribe.d.ts.map +1 -1
  140. package/dist/types/src/handlers/records-write.d.ts.map +1 -1
  141. package/dist/types/src/index.d.ts +6 -2
  142. package/dist/types/src/index.d.ts.map +1 -1
  143. package/dist/types/src/interfaces/messages-read.d.ts +1 -1
  144. package/dist/types/src/interfaces/messages-read.d.ts.map +1 -1
  145. package/dist/types/src/interfaces/messages-subscribe.d.ts +1 -1
  146. package/dist/types/src/interfaces/messages-subscribe.d.ts.map +1 -1
  147. package/dist/types/src/interfaces/messages-sync.d.ts +4 -1
  148. package/dist/types/src/interfaces/messages-sync.d.ts.map +1 -1
  149. package/dist/types/src/interfaces/protocols-configure.d.ts.map +1 -1
  150. package/dist/types/src/interfaces/protocols-query.d.ts.map +1 -1
  151. package/dist/types/src/interfaces/records-count.d.ts +1 -0
  152. package/dist/types/src/interfaces/records-count.d.ts.map +1 -1
  153. package/dist/types/src/interfaces/records-delete.d.ts.map +1 -1
  154. package/dist/types/src/interfaces/records-query.d.ts +1 -0
  155. package/dist/types/src/interfaces/records-query.d.ts.map +1 -1
  156. package/dist/types/src/interfaces/records-read.d.ts.map +1 -1
  157. package/dist/types/src/interfaces/records-subscribe.d.ts +1 -0
  158. package/dist/types/src/interfaces/records-subscribe.d.ts.map +1 -1
  159. package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
  160. package/dist/types/src/protocols/permissions.d.ts +2 -0
  161. package/dist/types/src/protocols/permissions.d.ts.map +1 -1
  162. package/dist/types/src/sync/records-projection.d.ts +98 -0
  163. package/dist/types/src/sync/records-projection.d.ts.map +1 -0
  164. package/dist/types/src/types/message-types.d.ts +1 -0
  165. package/dist/types/src/types/message-types.d.ts.map +1 -1
  166. package/dist/types/src/types/messages-types.d.ts +21 -3
  167. package/dist/types/src/types/messages-types.d.ts.map +1 -1
  168. package/dist/types/src/types/permission-types.d.ts +4 -0
  169. package/dist/types/src/types/permission-types.d.ts.map +1 -1
  170. package/dist/types/src/types/records-types.d.ts +4 -0
  171. package/dist/types/src/types/records-types.d.ts.map +1 -1
  172. package/dist/types/src/types/subscriptions.d.ts +18 -3
  173. package/dist/types/src/types/subscriptions.d.ts.map +1 -1
  174. package/dist/types/src/utils/permission-scope.d.ts +29 -0
  175. package/dist/types/src/utils/permission-scope.d.ts.map +1 -0
  176. package/dist/types/tests/core/records-grant-authorization.spec.d.ts +2 -0
  177. package/dist/types/tests/core/records-grant-authorization.spec.d.ts.map +1 -0
  178. package/dist/types/tests/features/permissions.spec.d.ts.map +1 -1
  179. package/dist/types/tests/handlers/messages-read.spec.d.ts.map +1 -1
  180. package/dist/types/tests/handlers/messages-subscribe.spec.d.ts.map +1 -1
  181. package/dist/types/tests/handlers/messages-sync.spec.d.ts.map +1 -1
  182. package/dist/types/tests/handlers/protocols-configure.spec.d.ts.map +1 -1
  183. package/dist/types/tests/handlers/records-count.spec.d.ts.map +1 -1
  184. package/dist/types/tests/handlers/records-query.spec.d.ts.map +1 -1
  185. package/dist/types/tests/handlers/records-subscribe.spec.d.ts.map +1 -1
  186. package/dist/types/tests/sync/records-projection.spec.d.ts +2 -0
  187. package/dist/types/tests/sync/records-projection.spec.d.ts.map +1 -0
  188. package/dist/types/tests/test-suite.d.ts.map +1 -1
  189. package/dist/types/tests/utils/permission-scope.spec.d.ts +2 -0
  190. package/dist/types/tests/utils/permission-scope.spec.d.ts.map +1 -0
  191. package/dist/types/tests/utils/test-data-generator.d.ts +5 -2
  192. package/dist/types/tests/utils/test-data-generator.d.ts.map +1 -1
  193. package/package.json +1 -1
  194. package/src/core/constants.ts +24 -0
  195. package/src/core/dwn-error.ts +24 -1
  196. package/src/core/grant-authorization.ts +7 -5
  197. package/src/core/message.ts +153 -6
  198. package/src/core/messages-grant-authorization.ts +282 -70
  199. package/src/core/protocol-authorization.ts +130 -0
  200. package/src/core/records-grant-authorization.ts +64 -21
  201. package/src/handlers/messages-read.ts +7 -5
  202. package/src/handlers/messages-subscribe.ts +149 -9
  203. package/src/handlers/messages-sync.ts +593 -102
  204. package/src/handlers/protocols-configure.ts +103 -2
  205. package/src/handlers/records-count.ts +33 -0
  206. package/src/handlers/records-delete.ts +3 -2
  207. package/src/handlers/records-query.ts +33 -0
  208. package/src/handlers/records-read.ts +3 -2
  209. package/src/handlers/records-subscribe.ts +34 -0
  210. package/src/handlers/records-write.ts +3 -2
  211. package/src/index.ts +7 -3
  212. package/src/interfaces/messages-read.ts +8 -5
  213. package/src/interfaces/messages-subscribe.ts +12 -9
  214. package/src/interfaces/messages-sync.ts +33 -12
  215. package/src/interfaces/protocols-configure.ts +8 -4
  216. package/src/interfaces/protocols-query.ts +13 -9
  217. package/src/interfaces/records-count.ts +7 -0
  218. package/src/interfaces/records-delete.ts +9 -5
  219. package/src/interfaces/records-query.ts +7 -0
  220. package/src/interfaces/records-read.ts +6 -3
  221. package/src/interfaces/records-subscribe.ts +7 -0
  222. package/src/interfaces/records-write.ts +25 -17
  223. package/src/protocols/permissions.ts +47 -9
  224. package/src/sync/records-projection.ts +328 -0
  225. package/src/types/message-types.ts +1 -0
  226. package/src/types/messages-types.ts +23 -3
  227. package/src/types/permission-types.ts +5 -1
  228. package/src/types/records-types.ts +5 -1
  229. package/src/types/subscriptions.ts +19 -3
  230. package/src/utils/permission-scope.ts +55 -0
@@ -1,3 +1,4 @@
1
+ import freeForAll from '../vectors/protocol-definitions/free-for-all.json' with { type: 'json' };
1
2
  import { GeneralJwsVerifier } from '../../src/jose/jws/general/verifier.js';
2
3
  import { Message } from '../../src/core/message.js';
3
4
  import minimalProtocolDefinition from '../vectors/protocol-definitions/minimal.json' with { type: 'json' };
@@ -305,7 +306,7 @@ export function testMessagesReadHandler() {
305
306
  const messagesRead = await TestDataGenerator.generateMessagesRead({
306
307
  author: bob,
307
308
  messageCid: await Message.getCid(recordsWrite.message),
308
- permissionGrantId: permissionGrant.recordsWrite.message.recordId,
309
+ permissionGrantIds: [permissionGrant.recordsWrite.message.recordId],
309
310
  });
310
311
  const messagesReadReply = await dwn.processMessage(alice.did, messagesRead.message);
311
312
  expect(messagesReadReply.status.code).toBe(401);
@@ -340,7 +341,7 @@ export function testMessagesReadHandler() {
340
341
  // Bob invokes that grant to read a record from Alice's DWN
341
342
  const messagesRead = await TestDataGenerator.generateMessagesRead({
342
343
  author: bob,
343
- permissionGrantId: permissionGrant.recordsWrite.message.recordId,
344
+ permissionGrantIds: [permissionGrant.recordsWrite.message.recordId],
344
345
  messageCid,
345
346
  });
346
347
  const readReply = await dwn.processMessage(alice.did, messagesRead.message);
@@ -348,6 +349,96 @@ export function testMessagesReadHandler() {
348
349
  expect(readReply.entry).toBeDefined();
349
350
  expect(readReply.entry.messageCid).toBe(messageCid);
350
351
  });
352
+ it('allows reads when one grant in a plural grant set covers the message', async () => {
353
+ const alice = await TestDataGenerator.generateDidKeyPersona();
354
+ const bob = await TestDataGenerator.generateDidKeyPersona();
355
+ const protocol1 = { ...minimalProtocolDefinition, protocol: 'http://plural-grant-read-1' };
356
+ const protocol2 = { ...minimalProtocolDefinition, protocol: 'http://plural-grant-read-2' };
357
+ for (const protocolDefinition of [protocol1, protocol2]) {
358
+ const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
359
+ author: alice,
360
+ protocolDefinition,
361
+ });
362
+ const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
363
+ expect(protocolsConfigureReply.status.code).toBe(202);
364
+ }
365
+ const { recordsWrite, dataStream } = await TestDataGenerator.generateRecordsWrite({
366
+ author: alice,
367
+ protocol: protocol2.protocol,
368
+ protocolPath: 'foo',
369
+ });
370
+ const recordsWriteReply = await dwn.processMessage(alice.did, recordsWrite.message, { dataStream });
371
+ expect(recordsWriteReply.status.code).toBe(202);
372
+ const permissionGrantIds = [];
373
+ for (const protocolDefinition of [protocol1, protocol2]) {
374
+ const permissionGrant = await PermissionsProtocol.createGrant({
375
+ signer: Jws.createSigner(alice),
376
+ grantedTo: bob.did,
377
+ dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }),
378
+ scope: {
379
+ interface: DwnInterfaceName.Messages,
380
+ method: DwnMethodName.Read,
381
+ protocol: protocolDefinition.protocol,
382
+ }
383
+ });
384
+ const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
385
+ const grantReply = await dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
386
+ expect(grantReply.status.code).toBe(202);
387
+ permissionGrantIds.push(permissionGrant.recordsWrite.message.recordId);
388
+ }
389
+ const messageCid = await Message.getCid(recordsWrite.message);
390
+ const messagesRead = await TestDataGenerator.generateMessagesRead({
391
+ author: bob,
392
+ messageCid,
393
+ permissionGrantIds: permissionGrantIds.reverse(),
394
+ });
395
+ const readReply = await dwn.processMessage(alice.did, messagesRead.message);
396
+ expect(readReply.status.code).toBe(200);
397
+ expect(readReply.entry?.messageCid).toBe(messageCid);
398
+ expect(messagesRead.message.descriptor.permissionGrantIds).toEqual([...permissionGrantIds].sort());
399
+ });
400
+ it('rejects reads if any grant in a plural grant set cannot be resolved', async () => {
401
+ const alice = await TestDataGenerator.generateDidKeyPersona();
402
+ const bob = await TestDataGenerator.generateDidKeyPersona();
403
+ const protocolDefinition = { ...minimalProtocolDefinition, protocol: 'http://plural-grant-read-unresolved' };
404
+ const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
405
+ author: alice,
406
+ protocolDefinition,
407
+ });
408
+ const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
409
+ expect(protocolsConfigureReply.status.code).toBe(202);
410
+ const { recordsWrite, dataStream } = await TestDataGenerator.generateRecordsWrite({
411
+ author: alice,
412
+ protocol: protocolDefinition.protocol,
413
+ protocolPath: 'foo',
414
+ });
415
+ const recordsWriteReply = await dwn.processMessage(alice.did, recordsWrite.message, { dataStream });
416
+ expect(recordsWriteReply.status.code).toBe(202);
417
+ const permissionGrant = await PermissionsProtocol.createGrant({
418
+ signer: Jws.createSigner(alice),
419
+ grantedTo: bob.did,
420
+ dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }),
421
+ scope: {
422
+ interface: DwnInterfaceName.Messages,
423
+ method: DwnMethodName.Read,
424
+ protocol: protocolDefinition.protocol,
425
+ }
426
+ });
427
+ const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
428
+ const grantReply = await dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
429
+ expect(grantReply.status.code).toBe(202);
430
+ const messagesRead = await TestDataGenerator.generateMessagesRead({
431
+ author: bob,
432
+ messageCid: await Message.getCid(recordsWrite.message),
433
+ permissionGrantIds: [
434
+ permissionGrant.recordsWrite.message.recordId,
435
+ await TestDataGenerator.randomCborSha256Cid(),
436
+ ],
437
+ });
438
+ const readReply = await dwn.processMessage(alice.did, messagesRead.message);
439
+ expect(readReply.status.code).toBe(401);
440
+ expect(readReply.entry).toBeUndefined();
441
+ });
351
442
  describe('protocol scoped messages', () => {
352
443
  it('allows reads of protocol messages with a protocol restricted grant scope', async () => {
353
444
  // This test will verify that a grant scoped to a specific protocol will allow a user to read messages associated with that protocol.
@@ -468,7 +559,7 @@ export function testMessagesReadHandler() {
468
559
  const messagesReadProtocolConfigure = await TestDataGenerator.generateMessagesRead({
469
560
  author: bob,
470
561
  messageCid: protocolConfigureMessageCid,
471
- permissionGrantId: permissionGrant.recordsWrite.message.recordId,
562
+ permissionGrantIds: [permissionGrant.recordsWrite.message.recordId],
472
563
  });
473
564
  const messagesReadProtocolConfigureReply = await dwn.processMessage(alice.did, messagesReadProtocolConfigure.message);
474
565
  expect(messagesReadProtocolConfigureReply.status.code).toBe(200);
@@ -478,7 +569,7 @@ export function testMessagesReadHandler() {
478
569
  const messagesReadWithGrant = await TestDataGenerator.generateMessagesRead({
479
570
  author: bob,
480
571
  messageCid: aliceRecordMessageCid,
481
- permissionGrantId: permissionGrant.recordsWrite.message.recordId,
572
+ permissionGrantIds: [permissionGrant.recordsWrite.message.recordId],
482
573
  });
483
574
  const messagesReadWithGrantReply = await dwn.processMessage(alice.did, messagesReadWithGrant.message);
484
575
  expect(messagesReadWithGrantReply.status.code).toBe(200);
@@ -488,7 +579,7 @@ export function testMessagesReadHandler() {
488
579
  const messagesReadDelete = await TestDataGenerator.generateMessagesRead({
489
580
  author: bob,
490
581
  messageCid: await Message.getCid(recordsDelete.message),
491
- permissionGrantId: permissionGrant.recordsWrite.message.recordId,
582
+ permissionGrantIds: [permissionGrant.recordsWrite.message.recordId],
492
583
  });
493
584
  const messagesReadDeleteReply = await dwn.processMessage(alice.did, messagesReadDelete.message);
494
585
  expect(messagesReadDeleteReply.status.code).toBe(200);
@@ -498,7 +589,7 @@ export function testMessagesReadHandler() {
498
589
  const messagesReadCarolRequest = await TestDataGenerator.generateMessagesRead({
499
590
  author: bob,
500
591
  messageCid: await Message.getCid(permissionRequestCarol.recordsWrite.message),
501
- permissionGrantId: permissionGrant.recordsWrite.message.recordId,
592
+ permissionGrantIds: [permissionGrant.recordsWrite.message.recordId],
502
593
  });
503
594
  const messagesReadCarolRequestReply = await dwn.processMessage(alice.did, messagesReadCarolRequest.message);
504
595
  expect(messagesReadCarolRequestReply.status.code).toBe(200);
@@ -508,7 +599,7 @@ export function testMessagesReadHandler() {
508
599
  const messagesReadCarolGrant = await TestDataGenerator.generateMessagesRead({
509
600
  author: bob,
510
601
  messageCid: carolGrantMessageCiD,
511
- permissionGrantId: permissionGrant.recordsWrite.message.recordId,
602
+ permissionGrantIds: [permissionGrant.recordsWrite.message.recordId],
512
603
  });
513
604
  const messagesReadCarolGrantReply = await dwn.processMessage(alice.did, messagesReadCarolGrant.message);
514
605
  expect(messagesReadCarolGrantReply.status.code).toBe(200);
@@ -518,7 +609,7 @@ export function testMessagesReadHandler() {
518
609
  const messagesReadCarolRecord = await TestDataGenerator.generateMessagesRead({
519
610
  author: bob,
520
611
  messageCid: carolRecordMessageCid,
521
- permissionGrantId: permissionGrant.recordsWrite.message.recordId,
612
+ permissionGrantIds: [permissionGrant.recordsWrite.message.recordId],
522
613
  });
523
614
  const messagesReadCarolRecordReply = await dwn.processMessage(alice.did, messagesReadCarolRecord.message);
524
615
  expect(messagesReadCarolRecordReply.status.code).toBe(200);
@@ -528,7 +619,7 @@ export function testMessagesReadHandler() {
528
619
  const messagesReadCarolGrantRevocation = await TestDataGenerator.generateMessagesRead({
529
620
  author: bob,
530
621
  messageCid: await Message.getCid(permissionRevocationCarol.recordsWrite.message),
531
- permissionGrantId: permissionGrant.recordsWrite.message.recordId,
622
+ permissionGrantIds: [permissionGrant.recordsWrite.message.recordId],
532
623
  });
533
624
  const messagesReadCarolGrantRevocationReply = await dwn.processMessage(alice.did, messagesReadCarolGrantRevocation.message);
534
625
  expect(messagesReadCarolGrantRevocationReply.status.code).toBe(200);
@@ -545,7 +636,7 @@ export function testMessagesReadHandler() {
545
636
  const messagesReadControl = await TestDataGenerator.generateMessagesRead({
546
637
  author: bob,
547
638
  messageCid: await Message.getCid(recordsWriteControl.message),
548
- permissionGrantId: permissionGrant.recordsWrite.message.recordId,
639
+ permissionGrantIds: [permissionGrant.recordsWrite.message.recordId],
549
640
  });
550
641
  const messagesReadControlReply = await dwn.processMessage(alice.did, messagesReadControl.message);
551
642
  expect(messagesReadControlReply.status.code).toBe(401);
@@ -589,12 +680,254 @@ export function testMessagesReadHandler() {
589
680
  const messagesReadWithoutGrant = await TestDataGenerator.generateMessagesRead({
590
681
  author: bob,
591
682
  messageCid: await Message.getCid(recordsWrite.message),
592
- permissionGrantId: permissionGrant.recordsWrite.message.recordId,
683
+ permissionGrantIds: [permissionGrant.recordsWrite.message.recordId],
593
684
  });
594
685
  const messagesReadWithoutGrantReply = await dwn.processMessage(alice.did, messagesReadWithoutGrant.message);
595
686
  expect(messagesReadWithoutGrantReply.status.code).toBe(401);
596
687
  expect(messagesReadWithoutGrantReply.status.detail).toContain(DwnErrorCode.MessagesReadVerifyScopeFailed);
597
688
  });
689
+ it('rejects reading arbitrary permission records with a grant scoped to the Permissions protocol', async () => {
690
+ const alice = await TestDataGenerator.generateDidKeyPersona();
691
+ const bob = await TestDataGenerator.generateDidKeyPersona();
692
+ const appProtocolGrant = await PermissionsProtocol.createGrant({
693
+ signer: Jws.createSigner(alice),
694
+ grantedTo: bob.did,
695
+ dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }),
696
+ scope: {
697
+ interface: DwnInterfaceName.Messages,
698
+ method: DwnMethodName.Read,
699
+ protocol: minimalProtocolDefinition.protocol,
700
+ }
701
+ });
702
+ expect((await dwn.processMessage(alice.did, appProtocolGrant.recordsWrite.message, { dataStream: DataStream.fromBytes(appProtocolGrant.permissionGrantBytes) })).status.code).toBe(202);
703
+ const permissionsProtocolGrant = await PermissionsProtocol.createGrant({
704
+ signer: Jws.createSigner(alice),
705
+ grantedTo: bob.did,
706
+ dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }),
707
+ scope: {
708
+ interface: DwnInterfaceName.Messages,
709
+ method: DwnMethodName.Read,
710
+ protocol: PermissionsProtocol.uri,
711
+ }
712
+ });
713
+ expect((await dwn.processMessage(alice.did, permissionsProtocolGrant.recordsWrite.message, { dataStream: DataStream.fromBytes(permissionsProtocolGrant.permissionGrantBytes) })).status.code).toBe(202);
714
+ const messagesRead = await TestDataGenerator.generateMessagesRead({
715
+ author: bob,
716
+ messageCid: await Message.getCid(appProtocolGrant.recordsWrite.message),
717
+ permissionGrantIds: [permissionsProtocolGrant.recordsWrite.message.recordId],
718
+ });
719
+ const messagesReadReply = await dwn.processMessage(alice.did, messagesRead.message);
720
+ expect(messagesReadReply.status.code).toBe(401);
721
+ expect(messagesReadReply.status.detail).toContain(DwnErrorCode.MessagesReadVerifyScopeFailed);
722
+ });
723
+ it('authorizes Records messages with exact protocolPath Messages.Read grants', async () => {
724
+ const alice = await TestDataGenerator.generateDidKeyPersona();
725
+ const bob = await TestDataGenerator.generateDidKeyPersona();
726
+ const protocolDefinition = { ...freeForAll, protocol: 'http://messages-read-path-scope' };
727
+ const otherProtocolDefinition = { ...freeForAll, protocol: 'http://messages-read-path-scope-other' };
728
+ const { message: protocolMessage } = await TestDataGenerator.generateProtocolsConfigure({
729
+ author: alice,
730
+ protocolDefinition
731
+ });
732
+ expect((await dwn.processMessage(alice.did, protocolMessage)).status.code).toBe(202);
733
+ const { message: otherProtocolMessage } = await TestDataGenerator.generateProtocolsConfigure({
734
+ author: alice,
735
+ protocolDefinition: otherProtocolDefinition
736
+ });
737
+ expect((await dwn.processMessage(alice.did, otherProtocolMessage)).status.code).toBe(202);
738
+ const { recordsWrite: post, dataStream: postData } = await TestDataGenerator.generateRecordsWrite({
739
+ author: alice,
740
+ protocol: protocolDefinition.protocol,
741
+ protocolPath: 'post',
742
+ schema: protocolDefinition.types.post.schema,
743
+ });
744
+ expect((await dwn.processMessage(alice.did, post.message, { dataStream: postData })).status.code).toBe(202);
745
+ const postContextId = post.message.contextId ?? post.message.recordId;
746
+ const { recordsWrite: attachment, dataStream: attachmentData } = await TestDataGenerator.generateRecordsWrite({
747
+ author: alice,
748
+ protocol: protocolDefinition.protocol,
749
+ protocolPath: 'post/attachment',
750
+ parentContextId: postContextId,
751
+ });
752
+ expect((await dwn.processMessage(alice.did, attachment.message, { dataStream: attachmentData })).status.code).toBe(202);
753
+ const { recordsWrite: otherProtocolPost, dataStream: otherProtocolPostData } = await TestDataGenerator.generateRecordsWrite({
754
+ author: alice,
755
+ protocol: otherProtocolDefinition.protocol,
756
+ protocolPath: 'post',
757
+ schema: otherProtocolDefinition.types.post.schema,
758
+ });
759
+ expect((await dwn.processMessage(alice.did, otherProtocolPost.message, { dataStream: otherProtocolPostData })).status.code).toBe(202);
760
+ const { recordsDelete } = await TestDataGenerator.generateRecordsDelete({
761
+ author: alice,
762
+ recordId: post.message.recordId,
763
+ });
764
+ expect((await dwn.processMessage(alice.did, recordsDelete.message)).status.code).toBe(202);
765
+ const permissionGrant = await PermissionsProtocol.createGrant({
766
+ signer: Jws.createSigner(alice),
767
+ grantedTo: bob.did,
768
+ dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }),
769
+ scope: {
770
+ interface: DwnInterfaceName.Messages,
771
+ method: DwnMethodName.Read,
772
+ protocol: protocolDefinition.protocol,
773
+ protocolPath: 'post',
774
+ }
775
+ });
776
+ expect((await dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: DataStream.fromBytes(permissionGrant.permissionGrantBytes) })).status.code).toBe(202);
777
+ const grantId = permissionGrant.recordsWrite.message.recordId;
778
+ const postRead = await TestDataGenerator.generateMessagesRead({
779
+ author: bob,
780
+ messageCid: await Message.getCid(post.message),
781
+ permissionGrantIds: [grantId],
782
+ });
783
+ expect((await dwn.processMessage(alice.did, postRead.message)).status.code).toBe(200);
784
+ const deleteRead = await TestDataGenerator.generateMessagesRead({
785
+ author: bob,
786
+ messageCid: await Message.getCid(recordsDelete.message),
787
+ permissionGrantIds: [grantId],
788
+ });
789
+ expect((await dwn.processMessage(alice.did, deleteRead.message)).status.code).toBe(200);
790
+ const attachmentRead = await TestDataGenerator.generateMessagesRead({
791
+ author: bob,
792
+ messageCid: await Message.getCid(attachment.message),
793
+ permissionGrantIds: [grantId],
794
+ });
795
+ expect((await dwn.processMessage(alice.did, attachmentRead.message)).status.code).toBe(401);
796
+ const otherProtocolRead = await TestDataGenerator.generateMessagesRead({
797
+ author: bob,
798
+ messageCid: await Message.getCid(otherProtocolPost.message),
799
+ permissionGrantIds: [grantId],
800
+ });
801
+ const otherProtocolReadReply = await dwn.processMessage(alice.did, otherProtocolRead.message);
802
+ expect(otherProtocolReadReply.status.code).toBe(401);
803
+ expect(otherProtocolReadReply.status.detail).toContain(DwnErrorCode.MessagesReadVerifyScopeFailed);
804
+ const protocolRead = await TestDataGenerator.generateMessagesRead({
805
+ author: bob,
806
+ messageCid: await Message.getCid(protocolMessage),
807
+ permissionGrantIds: [grantId],
808
+ });
809
+ const protocolReadReply = await dwn.processMessage(alice.did, protocolRead.message);
810
+ expect(protocolReadReply.status.code).toBe(200);
811
+ expect(protocolReadReply.entry.message).toEqual(protocolMessage);
812
+ const otherProtocolConfigRead = await TestDataGenerator.generateMessagesRead({
813
+ author: bob,
814
+ messageCid: await Message.getCid(otherProtocolMessage),
815
+ permissionGrantIds: [grantId],
816
+ });
817
+ const otherProtocolConfigReadReply = await dwn.processMessage(alice.did, otherProtocolConfigRead.message);
818
+ expect(otherProtocolConfigReadReply.status.code).toBe(401);
819
+ expect(otherProtocolConfigReadReply.status.detail).toContain(DwnErrorCode.MessagesReadVerifyScopeFailed);
820
+ const grantRecordRead = await TestDataGenerator.generateMessagesRead({
821
+ author: bob,
822
+ messageCid: await Message.getCid(permissionGrant.recordsWrite.message),
823
+ permissionGrantIds: [grantId],
824
+ });
825
+ const grantRecordReadReply = await dwn.processMessage(alice.did, grantRecordRead.message);
826
+ expect(grantRecordReadReply.status.code).toBe(401);
827
+ expect(grantRecordReadReply.status.detail).toContain(DwnErrorCode.MessagesReadVerifyScopeFailed);
828
+ const expectPermissionsSubtreeGrantReadRejected = async (scope) => {
829
+ const grant = await PermissionsProtocol.createGrant({
830
+ signer: Jws.createSigner(alice),
831
+ grantedTo: bob.did,
832
+ dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }),
833
+ scope: {
834
+ interface: DwnInterfaceName.Messages,
835
+ method: DwnMethodName.Read,
836
+ protocol: PermissionsProtocol.uri,
837
+ ...scope,
838
+ }
839
+ });
840
+ expect((await dwn.processMessage(alice.did, grant.recordsWrite.message, { dataStream: DataStream.fromBytes(grant.permissionGrantBytes) })).status.code).toBe(202);
841
+ const messagesRead = await TestDataGenerator.generateMessagesRead({
842
+ author: bob,
843
+ messageCid: await Message.getCid(permissionGrant.recordsWrite.message),
844
+ permissionGrantIds: [grant.recordsWrite.message.recordId],
845
+ });
846
+ const messagesReadReply = await dwn.processMessage(alice.did, messagesRead.message);
847
+ expect(messagesReadReply.status.code).toBe(401);
848
+ expect(messagesReadReply.status.detail).toContain(DwnErrorCode.MessagesReadVerifyScopeFailed);
849
+ };
850
+ const permissionGrantContextId = permissionGrant.recordsWrite.message.contextId ?? permissionGrant.recordsWrite.message.recordId;
851
+ await expectPermissionsSubtreeGrantReadRejected({ protocolPath: PermissionsProtocol.grantPath });
852
+ await expectPermissionsSubtreeGrantReadRejected({ contextId: permissionGrantContextId });
853
+ });
854
+ it('authorizes Records messages with context subtree Messages.Read grants', async () => {
855
+ const alice = await TestDataGenerator.generateDidKeyPersona();
856
+ const bob = await TestDataGenerator.generateDidKeyPersona();
857
+ const protocolDefinition = { ...freeForAll, protocol: 'http://messages-read-context-scope' };
858
+ const { message: protocolMessage } = await TestDataGenerator.generateProtocolsConfigure({
859
+ author: alice,
860
+ protocolDefinition
861
+ });
862
+ expect((await dwn.processMessage(alice.did, protocolMessage)).status.code).toBe(202);
863
+ const { recordsWrite: post, dataStream: postData } = await TestDataGenerator.generateRecordsWrite({
864
+ author: alice,
865
+ protocol: protocolDefinition.protocol,
866
+ protocolPath: 'post',
867
+ schema: protocolDefinition.types.post.schema,
868
+ });
869
+ expect((await dwn.processMessage(alice.did, post.message, { dataStream: postData })).status.code).toBe(202);
870
+ const postContextId = post.message.contextId ?? post.message.recordId;
871
+ const { recordsWrite: attachment, dataStream: attachmentData } = await TestDataGenerator.generateRecordsWrite({
872
+ author: alice,
873
+ protocol: protocolDefinition.protocol,
874
+ protocolPath: 'post/attachment',
875
+ parentContextId: postContextId,
876
+ });
877
+ expect((await dwn.processMessage(alice.did, attachment.message, { dataStream: attachmentData })).status.code).toBe(202);
878
+ const { recordsWrite: siblingPost, dataStream: siblingData } = await TestDataGenerator.generateRecordsWrite({
879
+ author: alice,
880
+ protocol: protocolDefinition.protocol,
881
+ protocolPath: 'post',
882
+ schema: protocolDefinition.types.post.schema,
883
+ });
884
+ expect((await dwn.processMessage(alice.did, siblingPost.message, { dataStream: siblingData })).status.code).toBe(202);
885
+ const permissionGrant = await PermissionsProtocol.createGrant({
886
+ signer: Jws.createSigner(alice),
887
+ grantedTo: bob.did,
888
+ dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }),
889
+ scope: {
890
+ interface: DwnInterfaceName.Messages,
891
+ method: DwnMethodName.Read,
892
+ protocol: protocolDefinition.protocol,
893
+ contextId: postContextId,
894
+ }
895
+ });
896
+ expect((await dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: DataStream.fromBytes(permissionGrant.permissionGrantBytes) })).status.code).toBe(202);
897
+ const grantId = permissionGrant.recordsWrite.message.recordId;
898
+ for (const message of [post.message, attachment.message]) {
899
+ const messagesRead = await TestDataGenerator.generateMessagesRead({
900
+ author: bob,
901
+ messageCid: await Message.getCid(message),
902
+ permissionGrantIds: [grantId],
903
+ });
904
+ expect((await dwn.processMessage(alice.did, messagesRead.message)).status.code).toBe(200);
905
+ }
906
+ const siblingRead = await TestDataGenerator.generateMessagesRead({
907
+ author: bob,
908
+ messageCid: await Message.getCid(siblingPost.message),
909
+ permissionGrantIds: [grantId],
910
+ });
911
+ const siblingReadReply = await dwn.processMessage(alice.did, siblingRead.message);
912
+ expect(siblingReadReply.status.code).toBe(401);
913
+ expect(siblingReadReply.status.detail).toContain(DwnErrorCode.MessagesReadVerifyScopeFailed);
914
+ const protocolRead = await TestDataGenerator.generateMessagesRead({
915
+ author: bob,
916
+ messageCid: await Message.getCid(protocolMessage),
917
+ permissionGrantIds: [grantId],
918
+ });
919
+ const protocolReadReply = await dwn.processMessage(alice.did, protocolRead.message);
920
+ expect(protocolReadReply.status.code).toBe(200);
921
+ expect(protocolReadReply.entry.message).toEqual(protocolMessage);
922
+ const grantRecordRead = await TestDataGenerator.generateMessagesRead({
923
+ author: bob,
924
+ messageCid: await Message.getCid(permissionGrant.recordsWrite.message),
925
+ permissionGrantIds: [grantId],
926
+ });
927
+ const grantRecordReadReply = await dwn.processMessage(alice.did, grantRecordRead.message);
928
+ expect(grantRecordReadReply.status.code).toBe(401);
929
+ expect(grantRecordReadReply.status.detail).toContain(DwnErrorCode.MessagesReadVerifyScopeFailed);
930
+ });
598
931
  it('rejects message if the RecordsWrite message is not found for a RecordsDelete being retrieved', async () => {
599
932
  // NOTE: This is a corner case that is unlikely to happen in practice, but is tested for completeness
600
933
  const alice = await TestDataGenerator.generateDidKeyPersona();
@@ -639,7 +972,7 @@ export function testMessagesReadHandler() {
639
972
  const messagesRead = await TestDataGenerator.generateMessagesRead({
640
973
  author: bob,
641
974
  messageCid: recordsDeleteCid,
642
- permissionGrantId: permissionGrant.recordsWrite.message.recordId,
975
+ permissionGrantIds: [permissionGrant.recordsWrite.message.recordId],
643
976
  });
644
977
  const messagesReadReply = await dwn.processMessage(alice.did, messagesRead.message);
645
978
  expect(messagesReadReply.status.code).toBe(401);