@enbox/dwn-sdk-js 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.mjs +8 -8
- package/dist/browser.mjs.map +4 -4
- package/dist/esm/generated/precompiled-validators.js +1 -2
- package/dist/esm/generated/precompiled-validators.js.map +1 -1
- package/dist/esm/src/core/abstract-message.js +4 -0
- package/dist/esm/src/core/abstract-message.js.map +1 -1
- package/dist/esm/src/core/auth.js +22 -33
- package/dist/esm/src/core/auth.js.map +1 -1
- package/dist/esm/src/core/dwn-constant.js +7 -7
- package/dist/esm/src/core/dwn-constant.js.map +1 -1
- package/dist/esm/src/core/dwn-error.js +1 -0
- package/dist/esm/src/core/dwn-error.js.map +1 -1
- package/dist/esm/src/core/grant-authorization.js +37 -52
- package/dist/esm/src/core/grant-authorization.js.map +1 -1
- package/dist/esm/src/core/message.js +85 -116
- package/dist/esm/src/core/message.js.map +1 -1
- package/dist/esm/src/core/messages-grant-authorization.js +63 -78
- package/dist/esm/src/core/messages-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization-action.js +266 -0
- package/dist/esm/src/core/protocol-authorization-action.js.map +1 -0
- package/dist/esm/src/core/protocol-authorization-validation.js +254 -0
- package/dist/esm/src/core/protocol-authorization-validation.js.map +1 -0
- package/dist/esm/src/core/protocol-authorization.js +122 -740
- package/dist/esm/src/core/protocol-authorization.js.map +1 -1
- package/dist/esm/src/core/protocols-grant-authorization.js +24 -38
- package/dist/esm/src/core/protocols-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/record-chain.js +64 -0
- package/dist/esm/src/core/record-chain.js.map +1 -0
- package/dist/esm/src/core/records-grant-authorization.js +55 -72
- package/dist/esm/src/core/records-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/resumable-task-manager.js +50 -65
- package/dist/esm/src/core/resumable-task-manager.js.map +1 -1
- package/dist/esm/src/core/tenant-gate.js +2 -13
- package/dist/esm/src/core/tenant-gate.js.map +1 -1
- package/dist/esm/src/dwn.js +69 -86
- package/dist/esm/src/dwn.js.map +1 -1
- package/dist/esm/src/event-stream/event-emitter-stream.js +17 -31
- package/dist/esm/src/event-stream/event-emitter-stream.js.map +1 -1
- package/dist/esm/src/handlers/messages-read.js +67 -77
- package/dist/esm/src/handlers/messages-read.js.map +1 -1
- package/dist/esm/src/handlers/messages-subscribe.js +51 -61
- package/dist/esm/src/handlers/messages-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/messages-sync.js +75 -85
- package/dist/esm/src/handlers/messages-sync.js.map +1 -1
- package/dist/esm/src/handlers/protocols-configure.js +135 -155
- package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
- package/dist/esm/src/handlers/protocols-query.js +52 -51
- package/dist/esm/src/handlers/protocols-query.js.map +1 -1
- package/dist/esm/src/handlers/records-count.js +96 -82
- package/dist/esm/src/handlers/records-count.js.map +1 -1
- package/dist/esm/src/handlers/records-delete.js +78 -88
- package/dist/esm/src/handlers/records-delete.js.map +1 -1
- package/dist/esm/src/handlers/records-query.js +116 -101
- package/dist/esm/src/handlers/records-query.js.map +1 -1
- package/dist/esm/src/handlers/records-read.js +124 -131
- package/dist/esm/src/handlers/records-read.js.map +1 -1
- package/dist/esm/src/handlers/records-subscribe.js +150 -103
- package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/records-write.js +250 -259
- package/dist/esm/src/handlers/records-write.js.map +1 -1
- package/dist/esm/src/interfaces/messages-read.js +24 -32
- package/dist/esm/src/interfaces/messages-read.js.map +1 -1
- package/dist/esm/src/interfaces/messages-subscribe.js +27 -41
- package/dist/esm/src/interfaces/messages-subscribe.js.map +1 -1
- package/dist/esm/src/interfaces/messages-sync.js +26 -40
- package/dist/esm/src/interfaces/messages-sync.js.map +1 -1
- package/dist/esm/src/interfaces/protocols-configure.js +63 -63
- package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
- package/dist/esm/src/interfaces/protocols-query.js +55 -68
- package/dist/esm/src/interfaces/protocols-query.js.map +1 -1
- package/dist/esm/src/interfaces/records-count.js +50 -66
- package/dist/esm/src/interfaces/records-count.js.map +1 -1
- package/dist/esm/src/interfaces/records-delete.js +45 -55
- package/dist/esm/src/interfaces/records-delete.js.map +1 -1
- package/dist/esm/src/interfaces/records-query.js +60 -76
- package/dist/esm/src/interfaces/records-query.js.map +1 -1
- package/dist/esm/src/interfaces/records-read.js +51 -67
- package/dist/esm/src/interfaces/records-read.js.map +1 -1
- package/dist/esm/src/interfaces/records-subscribe.js +52 -68
- package/dist/esm/src/interfaces/records-subscribe.js.map +1 -1
- package/dist/esm/src/interfaces/records-write-query.js +102 -0
- package/dist/esm/src/interfaces/records-write-query.js.map +1 -0
- package/dist/esm/src/interfaces/records-write-signing.js +92 -0
- package/dist/esm/src/interfaces/records-write-signing.js.map +1 -0
- package/dist/esm/src/interfaces/records-write.js +407 -602
- package/dist/esm/src/interfaces/records-write.js.map +1 -1
- package/dist/esm/src/jose/algorithms/signing/ed25519.js +10 -19
- package/dist/esm/src/jose/algorithms/signing/ed25519.js.map +1 -1
- package/dist/esm/src/jose/jws/general/builder.js +23 -35
- package/dist/esm/src/jose/jws/general/builder.js.map +1 -1
- package/dist/esm/src/jose/jws/general/verifier.js +56 -69
- package/dist/esm/src/jose/jws/general/verifier.js.map +1 -1
- package/dist/esm/src/protocols/permission-grant.js +44 -15
- package/dist/esm/src/protocols/permission-grant.js.map +1 -1
- package/dist/esm/src/protocols/permission-request.js +29 -15
- package/dist/esm/src/protocols/permission-request.js.map +1 -1
- package/dist/esm/src/protocols/permissions.js +216 -226
- package/dist/esm/src/protocols/permissions.js.map +1 -1
- package/dist/esm/src/smt/smt-store-level.js +42 -64
- package/dist/esm/src/smt/smt-store-level.js.map +1 -1
- package/dist/esm/src/smt/smt-store-memory.js +19 -45
- package/dist/esm/src/smt/smt-store-memory.js.map +1 -1
- package/dist/esm/src/smt/smt-utils.js +28 -45
- package/dist/esm/src/smt/smt-utils.js.map +1 -1
- package/dist/esm/src/smt/sparse-merkle-tree.js +426 -471
- package/dist/esm/src/smt/sparse-merkle-tree.js.map +1 -1
- package/dist/esm/src/state-index/state-index-level.js +115 -150
- package/dist/esm/src/state-index/state-index-level.js.map +1 -1
- package/dist/esm/src/store/blockstore-level.js +54 -156
- package/dist/esm/src/store/blockstore-level.js.map +1 -1
- package/dist/esm/src/store/blockstore-mock.js +48 -153
- package/dist/esm/src/store/blockstore-mock.js.map +1 -1
- package/dist/esm/src/store/data-store-level.js +59 -99
- package/dist/esm/src/store/data-store-level.js.map +1 -1
- package/dist/esm/src/store/index-level-compound.js +246 -0
- package/dist/esm/src/store/index-level-compound.js.map +1 -0
- package/dist/esm/src/store/index-level.js +295 -713
- package/dist/esm/src/store/index-level.js.map +1 -1
- package/dist/esm/src/store/level-wrapper.js +143 -244
- package/dist/esm/src/store/level-wrapper.js.map +1 -1
- package/dist/esm/src/store/message-store-level.js +71 -94
- package/dist/esm/src/store/message-store-level.js.map +1 -1
- package/dist/esm/src/store/resumable-task-store-level.js +62 -101
- package/dist/esm/src/store/resumable-task-store-level.js.map +1 -1
- package/dist/esm/src/store/storage-controller.js +129 -144
- package/dist/esm/src/store/storage-controller.js.map +1 -1
- package/dist/esm/src/utils/abort.js +8 -19
- package/dist/esm/src/utils/abort.js.map +1 -1
- package/dist/esm/src/utils/array.js +15 -49
- package/dist/esm/src/utils/array.js.map +1 -1
- package/dist/esm/src/utils/cid.js +29 -77
- package/dist/esm/src/utils/cid.js.map +1 -1
- package/dist/esm/src/utils/data-stream.js +37 -65
- package/dist/esm/src/utils/data-stream.js.map +1 -1
- package/dist/esm/src/utils/encryption.js +136 -162
- package/dist/esm/src/utils/encryption.js.map +1 -1
- package/dist/esm/src/utils/filter.js +1 -12
- package/dist/esm/src/utils/filter.js.map +1 -1
- package/dist/esm/src/utils/hd-key.js +45 -63
- package/dist/esm/src/utils/hd-key.js.map +1 -1
- package/dist/esm/src/utils/jws.js +9 -20
- package/dist/esm/src/utils/jws.js.map +1 -1
- package/dist/esm/src/utils/memory-cache.js +12 -23
- package/dist/esm/src/utils/memory-cache.js.map +1 -1
- package/dist/esm/src/utils/messages.js +9 -3
- package/dist/esm/src/utils/messages.js.map +1 -1
- package/dist/esm/src/utils/private-key-signer.js +9 -17
- package/dist/esm/src/utils/private-key-signer.js.map +1 -1
- package/dist/esm/src/utils/protocols.js +62 -70
- package/dist/esm/src/utils/protocols.js.map +1 -1
- package/dist/esm/src/utils/records.js +108 -140
- package/dist/esm/src/utils/records.js.map +1 -1
- package/dist/esm/src/utils/secp256k1.js +60 -96
- package/dist/esm/src/utils/secp256k1.js.map +1 -1
- package/dist/esm/src/utils/secp256r1.js +54 -71
- package/dist/esm/src/utils/secp256r1.js.map +1 -1
- package/dist/esm/src/utils/time.js +5 -18
- package/dist/esm/src/utils/time.js.map +1 -1
- package/dist/esm/src/utils/url.js +3 -3
- package/dist/esm/src/utils/url.js.map +1 -1
- package/dist/esm/tests/core/auth.spec.js +3 -12
- package/dist/esm/tests/core/auth.spec.js.map +1 -1
- package/dist/esm/tests/core/message.spec.js +50 -59
- package/dist/esm/tests/core/message.spec.js.map +1 -1
- package/dist/esm/tests/core/protocol-authorization.spec.js +9 -18
- package/dist/esm/tests/core/protocol-authorization.spec.js.map +1 -1
- package/dist/esm/tests/dwn.spec.js +45 -58
- package/dist/esm/tests/dwn.spec.js.map +1 -1
- package/dist/esm/tests/event-stream/event-emitter-stream.spec.js +24 -33
- package/dist/esm/tests/event-stream/event-emitter-stream.spec.js.map +1 -1
- package/dist/esm/tests/event-stream/event-stream.spec.js +46 -55
- package/dist/esm/tests/event-stream/event-stream.spec.js.map +1 -1
- package/dist/esm/tests/features/author-delegated-grant.spec.js +326 -343
- package/dist/esm/tests/features/author-delegated-grant.spec.js.map +1 -1
- package/dist/esm/tests/features/owner-delegated-grant.spec.js +153 -169
- package/dist/esm/tests/features/owner-delegated-grant.spec.js.map +1 -1
- package/dist/esm/tests/features/owner-signature.spec.js +67 -78
- package/dist/esm/tests/features/owner-signature.spec.js.map +1 -1
- package/dist/esm/tests/features/permissions.spec.js +446 -181
- package/dist/esm/tests/features/permissions.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-composition.spec.js +346 -356
- package/dist/esm/tests/features/protocol-composition.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-create-action.spec.js +42 -51
- package/dist/esm/tests/features/protocol-create-action.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-delete-action.spec.js +94 -103
- package/dist/esm/tests/features/protocol-delete-action.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-update-action.spec.js +105 -114
- package/dist/esm/tests/features/protocol-update-action.spec.js.map +1 -1
- package/dist/esm/tests/features/records-prune.spec.js +175 -191
- package/dist/esm/tests/features/records-prune.spec.js.map +1 -1
- package/dist/esm/tests/features/records-tags.spec.js +441 -460
- package/dist/esm/tests/features/records-tags.spec.js.map +1 -1
- package/dist/esm/tests/features/resumable-tasks.spec.js +82 -91
- package/dist/esm/tests/features/resumable-tasks.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-read.spec.js +206 -207
- package/dist/esm/tests/handlers/messages-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-subscribe.spec.js +145 -154
- package/dist/esm/tests/handlers/messages-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-sync.spec.js +174 -183
- package/dist/esm/tests/handlers/messages-sync.spec.js.map +1 -1
- package/dist/esm/tests/handlers/protocols-configure.spec.js +244 -238
- package/dist/esm/tests/handlers/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/handlers/protocols-query.spec.js +156 -169
- package/dist/esm/tests/handlers/protocols-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-count.spec.js +93 -102
- package/dist/esm/tests/handlers/records-count.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-delete.spec.js +252 -264
- package/dist/esm/tests/handlers/records-delete.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-query.spec.js +917 -988
- package/dist/esm/tests/handlers/records-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-read.spec.js +553 -568
- package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js +269 -278
- package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-write.spec.js +1057 -1082
- package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/messages-get.spec.js +39 -48
- package/dist/esm/tests/interfaces/messages-get.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/messages-subscribe.spec.js +4 -13
- package/dist/esm/tests/interfaces/messages-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/protocols-configure.spec.js +212 -88
- package/dist/esm/tests/interfaces/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/protocols-query.spec.js +8 -17
- package/dist/esm/tests/interfaces/protocols-query.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-delete.spec.js +8 -17
- package/dist/esm/tests/interfaces/records-delete.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-query.spec.js +20 -29
- package/dist/esm/tests/interfaces/records-query.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-read.spec.js +42 -51
- package/dist/esm/tests/interfaces/records-read.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-subscribe.spec.js +16 -25
- package/dist/esm/tests/interfaces/records-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-write.spec.js +152 -165
- package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
- package/dist/esm/tests/jose/jws/general.spec.js +36 -45
- package/dist/esm/tests/jose/jws/general.spec.js.map +1 -1
- package/dist/esm/tests/protocols/permission-grant.spec.js +44 -50
- package/dist/esm/tests/protocols/permission-grant.spec.js.map +1 -1
- package/dist/esm/tests/protocols/permission-request.spec.js +23 -32
- package/dist/esm/tests/protocols/permission-request.spec.js.map +1 -1
- package/dist/esm/tests/protocols/permissions.spec.js +49 -55
- package/dist/esm/tests/protocols/permissions.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/aggregator.spec.js +124 -135
- package/dist/esm/tests/scenarios/aggregator.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/deleted-record.spec.js +23 -32
- package/dist/esm/tests/scenarios/deleted-record.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js +52 -61
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/nested-roles.spec.js +63 -73
- package/dist/esm/tests/scenarios/nested-roles.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/subscriptions.spec.js +377 -333
- package/dist/esm/tests/scenarios/subscriptions.spec.js.map +1 -1
- package/dist/esm/tests/smt/smt-store-level.spec.js +76 -87
- package/dist/esm/tests/smt/smt-store-level.spec.js.map +1 -1
- package/dist/esm/tests/smt/sparse-merkle-tree.spec.js +344 -353
- package/dist/esm/tests/smt/sparse-merkle-tree.spec.js.map +1 -1
- package/dist/esm/tests/state-index/state-index-level.spec.js +117 -126
- package/dist/esm/tests/state-index/state-index-level.spec.js.map +1 -1
- package/dist/esm/tests/store/blockstore-level.spec.js +44 -99
- package/dist/esm/tests/store/blockstore-level.spec.js.map +1 -1
- package/dist/esm/tests/store/blockstore-mock.spec.js +40 -120
- package/dist/esm/tests/store/blockstore-mock.spec.js.map +1 -1
- package/dist/esm/tests/store/data-store-level.spec.js +86 -95
- package/dist/esm/tests/store/data-store-level.spec.js.map +1 -1
- package/dist/esm/tests/store/index-level.spec.js +404 -414
- package/dist/esm/tests/store/index-level.spec.js.map +1 -1
- package/dist/esm/tests/store/message-store-level.spec.js +13 -22
- package/dist/esm/tests/store/message-store-level.spec.js.map +1 -1
- package/dist/esm/tests/store/message-store.spec.js +229 -238
- package/dist/esm/tests/store/message-store.spec.js.map +1 -1
- package/dist/esm/tests/test-event-stream.js +3 -3
- package/dist/esm/tests/test-event-stream.js.map +1 -1
- package/dist/esm/tests/test-stores.js +16 -13
- package/dist/esm/tests/test-stores.js.map +1 -1
- package/dist/esm/tests/test-suite.js +2 -11
- package/dist/esm/tests/test-suite.js.map +1 -1
- package/dist/esm/tests/utils/cid.spec.js +24 -33
- package/dist/esm/tests/utils/cid.spec.js.map +1 -1
- package/dist/esm/tests/utils/data-stream.spec.js +48 -57
- package/dist/esm/tests/utils/data-stream.spec.js.map +1 -1
- package/dist/esm/tests/utils/encryption-callbacks.spec.js +45 -54
- package/dist/esm/tests/utils/encryption-callbacks.spec.js.map +1 -1
- package/dist/esm/tests/utils/encryption.spec.js +291 -44
- package/dist/esm/tests/utils/encryption.spec.js.map +1 -1
- package/dist/esm/tests/utils/filters.spec.js +46 -55
- package/dist/esm/tests/utils/filters.spec.js.map +1 -1
- package/dist/esm/tests/utils/hd-key.spec.js +10 -19
- package/dist/esm/tests/utils/hd-key.spec.js.map +1 -1
- package/dist/esm/tests/utils/jws.spec.js +3 -12
- package/dist/esm/tests/utils/jws.spec.js.map +1 -1
- package/dist/esm/tests/utils/memory-cache.spec.js +9 -18
- package/dist/esm/tests/utils/memory-cache.spec.js.map +1 -1
- package/dist/esm/tests/utils/messages.spec.js +6 -15
- package/dist/esm/tests/utils/messages.spec.js.map +1 -1
- package/dist/esm/tests/utils/poller.js +22 -33
- package/dist/esm/tests/utils/poller.js.map +1 -1
- package/dist/esm/tests/utils/private-key-signer.spec.js +15 -24
- package/dist/esm/tests/utils/private-key-signer.spec.js.map +1 -1
- package/dist/esm/tests/utils/records.spec.js +10 -19
- package/dist/esm/tests/utils/records.spec.js.map +1 -1
- package/dist/esm/tests/utils/secp256k1.spec.js +16 -25
- package/dist/esm/tests/utils/secp256k1.spec.js.map +1 -1
- package/dist/esm/tests/utils/secp256r1.spec.js +18 -27
- package/dist/esm/tests/utils/secp256r1.spec.js.map +1 -1
- package/dist/esm/tests/utils/test-data-generator.js +414 -468
- package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/definitions.spec.js +2 -11
- package/dist/esm/tests/validation/json-schemas/definitions.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/jwk/general-jwk.spec.js +4 -13
- package/dist/esm/tests/validation/json-schemas/jwk/general-jwk.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/jwk/public-jwk.spec.js +8 -17
- package/dist/esm/tests/validation/json-schemas/jwk/public-jwk.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/jwk-verification-method.spec.js +3 -12
- package/dist/esm/tests/validation/json-schemas/jwk-verification-method.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js +4 -13
- package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/records/records-query.spec.js +2 -11
- package/dist/esm/tests/validation/json-schemas/records/records-query.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/records/records-read.spec.js +2 -11
- package/dist/esm/tests/validation/json-schemas/records/records-read.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js +7 -16
- package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js.map +1 -1
- package/dist/types/src/core/protocol-authorization-action.d.ts +42 -0
- package/dist/types/src/core/protocol-authorization-action.d.ts.map +1 -0
- package/dist/types/src/core/protocol-authorization-validation.d.ts +60 -0
- package/dist/types/src/core/protocol-authorization-validation.d.ts.map +1 -0
- package/dist/types/src/core/protocol-authorization.d.ts +10 -100
- package/dist/types/src/core/protocol-authorization.d.ts.map +1 -1
- package/dist/types/src/core/record-chain.d.ts +24 -0
- package/dist/types/src/core/record-chain.d.ts.map +1 -0
- package/dist/types/src/handlers/records-write.d.ts +2 -1
- package/dist/types/src/handlers/records-write.d.ts.map +1 -1
- package/dist/types/src/interfaces/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-write-query.d.ts +33 -0
- package/dist/types/src/interfaces/records-write-query.d.ts.map +1 -0
- package/dist/types/src/interfaces/records-write-signing.d.ts +35 -0
- package/dist/types/src/interfaces/records-write-signing.d.ts.map +1 -0
- package/dist/types/src/interfaces/records-write.d.ts +10 -44
- package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
- package/dist/types/src/store/index-level-compound.d.ts +70 -0
- package/dist/types/src/store/index-level-compound.d.ts.map +1 -0
- package/dist/types/src/store/index-level.d.ts +0 -58
- package/dist/types/src/store/index-level.d.ts.map +1 -1
- package/dist/types/src/utils/protocols.d.ts +5 -0
- package/dist/types/src/utils/protocols.d.ts.map +1 -1
- package/dist/types/src/utils/records.d.ts +3 -1
- package/dist/types/src/utils/records.d.ts.map +1 -1
- package/dist/types/tests/features/permissions.spec.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/core/protocol-authorization-action.ts +377 -0
- package/src/core/protocol-authorization-validation.ts +391 -0
- package/src/core/protocol-authorization.ts +60 -849
- package/src/core/record-chain.ts +99 -0
- package/src/handlers/records-read.ts +1 -1
- package/src/handlers/records-write.ts +37 -21
- package/src/interfaces/protocols-configure.ts +33 -5
- package/src/interfaces/records-write-query.ts +139 -0
- package/src/interfaces/records-write-signing.ts +143 -0
- package/src/interfaces/records-write.ts +49 -221
- package/src/store/index-level-compound.ts +324 -0
- package/src/store/index-level.ts +24 -306
- package/src/utils/protocols.ts +8 -0
- package/src/utils/records.ts +9 -15
|
@@ -1,12 +1,3 @@
|
|
|
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
1
|
import sinon from 'sinon';
|
|
11
2
|
import { DataStream } from '../../src/utils/data-stream.js';
|
|
12
3
|
import { Dwn } from '../../src/dwn.js';
|
|
@@ -35,7 +26,7 @@ export function testProtocolComposition() {
|
|
|
35
26
|
let stateIndex;
|
|
36
27
|
let eventStream;
|
|
37
28
|
let dwn;
|
|
38
|
-
beforeAll(() =>
|
|
29
|
+
beforeAll(async () => {
|
|
39
30
|
didResolver = new UniversalResolver({ didResolvers: [DidKey] });
|
|
40
31
|
const stores = TestStores.get();
|
|
41
32
|
messageStore = stores.messageStore;
|
|
@@ -43,18 +34,18 @@ export function testProtocolComposition() {
|
|
|
43
34
|
resumableTaskStore = stores.resumableTaskStore;
|
|
44
35
|
stateIndex = stores.stateIndex;
|
|
45
36
|
eventStream = TestEventStream.get();
|
|
46
|
-
dwn =
|
|
47
|
-
})
|
|
48
|
-
beforeEach(() =>
|
|
37
|
+
dwn = await Dwn.create({ didResolver, messageStore, dataStore, stateIndex, eventStream, resumableTaskStore });
|
|
38
|
+
});
|
|
39
|
+
beforeEach(async () => {
|
|
49
40
|
sinon.restore();
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
})
|
|
55
|
-
afterAll(() =>
|
|
56
|
-
|
|
57
|
-
})
|
|
41
|
+
await messageStore.clear();
|
|
42
|
+
await dataStore.clear();
|
|
43
|
+
await resumableTaskStore.clear();
|
|
44
|
+
await stateIndex.clear();
|
|
45
|
+
});
|
|
46
|
+
afterAll(async () => {
|
|
47
|
+
await dwn.close();
|
|
48
|
+
});
|
|
58
49
|
// =========================================================================
|
|
59
50
|
// Protocol definitions for tests
|
|
60
51
|
// =========================================================================
|
|
@@ -117,18 +108,18 @@ export function testProtocolComposition() {
|
|
|
117
108
|
// Validation tests (ProtocolsConfigure)
|
|
118
109
|
// =========================================================================
|
|
119
110
|
describe('ProtocolsConfigure validation', () => {
|
|
120
|
-
it('should accept a valid protocol definition with `uses` and `$ref`', () =>
|
|
121
|
-
const alice =
|
|
122
|
-
const protocolsConfigure =
|
|
111
|
+
it('should accept a valid protocol definition with `uses` and `$ref`', async () => {
|
|
112
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
113
|
+
const protocolsConfigure = await ProtocolsConfigure.create({
|
|
123
114
|
definition: commentsProtocol,
|
|
124
115
|
signer: Jws.createSigner(alice),
|
|
125
116
|
});
|
|
126
117
|
expect(protocolsConfigure.message.descriptor.definition.uses).toEqual({
|
|
127
118
|
threads: 'https://threads.example.com',
|
|
128
119
|
});
|
|
129
|
-
})
|
|
130
|
-
it('should reject `uses` alias that does not match naming pattern (bypassing JSON schema)', () =>
|
|
131
|
-
const alice =
|
|
120
|
+
});
|
|
121
|
+
it('should reject `uses` alias that does not match naming pattern (bypassing JSON schema)', async () => {
|
|
122
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
132
123
|
// The JSON schema enforces alias naming via `patternProperties` + `additionalProperties: false`,
|
|
133
124
|
// which means invalid aliases like '123invalid' are caught by JSON schema before the code-level
|
|
134
125
|
// `validateUses()` check. To exercise the code-level `ProtocolsConfigureInvalidUsesAlias` error,
|
|
@@ -142,7 +133,7 @@ export function testProtocolComposition() {
|
|
|
142
133
|
structure: {},
|
|
143
134
|
};
|
|
144
135
|
try {
|
|
145
|
-
|
|
136
|
+
await ProtocolsConfigure.create({
|
|
146
137
|
definition: badDefinition,
|
|
147
138
|
signer: Jws.createSigner(alice),
|
|
148
139
|
});
|
|
@@ -151,9 +142,9 @@ export function testProtocolComposition() {
|
|
|
151
142
|
catch (error) {
|
|
152
143
|
expect(error.message).toContain(DwnErrorCode.ProtocolsConfigureInvalidUsesAlias);
|
|
153
144
|
}
|
|
154
|
-
})
|
|
155
|
-
it('should reject `$ref` with alias not in `uses`', () =>
|
|
156
|
-
const alice =
|
|
145
|
+
});
|
|
146
|
+
it('should reject `$ref` with alias not in `uses`', async () => {
|
|
147
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
157
148
|
const badDefinition = {
|
|
158
149
|
protocol: 'https://bad.example.com',
|
|
159
150
|
published: true,
|
|
@@ -171,7 +162,7 @@ export function testProtocolComposition() {
|
|
|
171
162
|
},
|
|
172
163
|
};
|
|
173
164
|
try {
|
|
174
|
-
|
|
165
|
+
await ProtocolsConfigure.create({
|
|
175
166
|
definition: badDefinition,
|
|
176
167
|
signer: Jws.createSigner(alice),
|
|
177
168
|
});
|
|
@@ -180,9 +171,9 @@ export function testProtocolComposition() {
|
|
|
180
171
|
catch (error) {
|
|
181
172
|
expect(error.message).toContain(DwnErrorCode.ProtocolsConfigureInvalidRefAlias);
|
|
182
173
|
}
|
|
183
|
-
})
|
|
184
|
-
it('should reject `$ref` node with `$actions`', () =>
|
|
185
|
-
const alice =
|
|
174
|
+
});
|
|
175
|
+
it('should reject `$ref` node with `$actions`', async () => {
|
|
176
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
186
177
|
const badDefinition = {
|
|
187
178
|
protocol: 'https://bad.example.com',
|
|
188
179
|
published: true,
|
|
@@ -199,7 +190,7 @@ export function testProtocolComposition() {
|
|
|
199
190
|
},
|
|
200
191
|
};
|
|
201
192
|
try {
|
|
202
|
-
|
|
193
|
+
await ProtocolsConfigure.create({
|
|
203
194
|
definition: badDefinition,
|
|
204
195
|
signer: Jws.createSigner(alice),
|
|
205
196
|
});
|
|
@@ -208,9 +199,9 @@ export function testProtocolComposition() {
|
|
|
208
199
|
catch (error) {
|
|
209
200
|
expect(error.message).toContain(DwnErrorCode.ProtocolsConfigureInvalidRefNodeHasDirectives);
|
|
210
201
|
}
|
|
211
|
-
})
|
|
212
|
-
it('should reject `$ref` node with `$role`', () =>
|
|
213
|
-
const alice =
|
|
202
|
+
});
|
|
203
|
+
it('should reject `$ref` node with `$role`', async () => {
|
|
204
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
214
205
|
const badDefinition = {
|
|
215
206
|
protocol: 'https://bad.example.com',
|
|
216
207
|
published: true,
|
|
@@ -224,7 +215,7 @@ export function testProtocolComposition() {
|
|
|
224
215
|
},
|
|
225
216
|
};
|
|
226
217
|
try {
|
|
227
|
-
|
|
218
|
+
await ProtocolsConfigure.create({
|
|
228
219
|
definition: badDefinition,
|
|
229
220
|
signer: Jws.createSigner(alice),
|
|
230
221
|
});
|
|
@@ -233,9 +224,9 @@ export function testProtocolComposition() {
|
|
|
233
224
|
catch (error) {
|
|
234
225
|
expect(error.message).toContain(DwnErrorCode.ProtocolsConfigureInvalidRefNodeHasDirectives);
|
|
235
226
|
}
|
|
236
|
-
})
|
|
237
|
-
it('should reject cross-protocol `role` with alias not in `uses`', () =>
|
|
238
|
-
const alice =
|
|
227
|
+
});
|
|
228
|
+
it('should reject cross-protocol `role` with alias not in `uses`', async () => {
|
|
229
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
239
230
|
const badDefinition = {
|
|
240
231
|
protocol: 'https://bad.example.com',
|
|
241
232
|
published: true,
|
|
@@ -253,7 +244,7 @@ export function testProtocolComposition() {
|
|
|
253
244
|
},
|
|
254
245
|
};
|
|
255
246
|
try {
|
|
256
|
-
|
|
247
|
+
await ProtocolsConfigure.create({
|
|
257
248
|
definition: badDefinition,
|
|
258
249
|
signer: Jws.createSigner(alice),
|
|
259
250
|
});
|
|
@@ -262,9 +253,9 @@ export function testProtocolComposition() {
|
|
|
262
253
|
catch (error) {
|
|
263
254
|
expect(error.message).toContain(DwnErrorCode.ProtocolsConfigureInvalidCrossProtocolRole);
|
|
264
255
|
}
|
|
265
|
-
})
|
|
266
|
-
it('should reject `uses` with invalid protocol URL', () =>
|
|
267
|
-
const alice =
|
|
256
|
+
});
|
|
257
|
+
it('should reject `uses` with invalid protocol URL', async () => {
|
|
258
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
268
259
|
const badDefinition = {
|
|
269
260
|
protocol: 'https://bad.example.com',
|
|
270
261
|
published: true,
|
|
@@ -273,7 +264,7 @@ export function testProtocolComposition() {
|
|
|
273
264
|
structure: {},
|
|
274
265
|
};
|
|
275
266
|
try {
|
|
276
|
-
|
|
267
|
+
await ProtocolsConfigure.create({
|
|
277
268
|
definition: badDefinition,
|
|
278
269
|
signer: Jws.createSigner(alice),
|
|
279
270
|
});
|
|
@@ -282,9 +273,9 @@ export function testProtocolComposition() {
|
|
|
282
273
|
catch (error) {
|
|
283
274
|
expect(error.message).toContain(DwnErrorCode.ProtocolsConfigureInvalidUsesProtocolUrl);
|
|
284
275
|
}
|
|
285
|
-
})
|
|
286
|
-
it('should accept `$ref` referencing a multi-segment path in the referenced protocol', () =>
|
|
287
|
-
const alice =
|
|
276
|
+
});
|
|
277
|
+
it('should accept `$ref` referencing a multi-segment path in the referenced protocol', async () => {
|
|
278
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
288
279
|
// The root-only constraint means `$ref` must appear at the root of the composing structure,
|
|
289
280
|
// but the REFERENCED path can be multi-segment (e.g., 'thread/participant').
|
|
290
281
|
const definition = {
|
|
@@ -304,22 +295,22 @@ export function testProtocolComposition() {
|
|
|
304
295
|
},
|
|
305
296
|
};
|
|
306
297
|
// ProtocolsConfigure.create() should succeed — the $ref is at root level
|
|
307
|
-
const protocolsConfigure =
|
|
298
|
+
const protocolsConfigure = await ProtocolsConfigure.create({
|
|
308
299
|
definition,
|
|
309
300
|
signer: Jws.createSigner(alice),
|
|
310
301
|
});
|
|
311
302
|
expect(protocolsConfigure.message.descriptor.definition.uses).toBeDefined();
|
|
312
303
|
// Install-time validation should also succeed when the referenced protocol is installed
|
|
313
|
-
const threadsConfigure =
|
|
304
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
314
305
|
definition: threadsProtocol,
|
|
315
306
|
signer: Jws.createSigner(alice),
|
|
316
307
|
});
|
|
317
|
-
|
|
318
|
-
const installReply =
|
|
308
|
+
await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
309
|
+
const installReply = await dwn.processMessage(alice.did, protocolsConfigure.message);
|
|
319
310
|
expect(installReply.status.code).toBe(202);
|
|
320
|
-
})
|
|
321
|
-
it('should not require `$ref` types in local types map', () =>
|
|
322
|
-
const alice =
|
|
311
|
+
});
|
|
312
|
+
it('should not require `$ref` types in local types map', async () => {
|
|
313
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
323
314
|
// 'thread' is NOT in the local `types` — it comes from the $ref
|
|
324
315
|
const definition = {
|
|
325
316
|
protocol: 'https://comments.example.com',
|
|
@@ -336,53 +327,53 @@ export function testProtocolComposition() {
|
|
|
336
327
|
},
|
|
337
328
|
};
|
|
338
329
|
// should succeed without error
|
|
339
|
-
const protocolsConfigure =
|
|
330
|
+
const protocolsConfigure = await ProtocolsConfigure.create({
|
|
340
331
|
definition,
|
|
341
332
|
signer: Jws.createSigner(alice),
|
|
342
333
|
});
|
|
343
334
|
expect(protocolsConfigure.message.descriptor.definition.uses).toBeDefined();
|
|
344
|
-
})
|
|
335
|
+
});
|
|
345
336
|
});
|
|
346
337
|
// =========================================================================
|
|
347
338
|
// Install-time validation tests (handler)
|
|
348
339
|
// =========================================================================
|
|
349
340
|
describe('install-time composition dependency validation', () => {
|
|
350
|
-
it('should reject composing protocol if `uses` protocol is not installed', () =>
|
|
351
|
-
const alice =
|
|
341
|
+
it('should reject composing protocol if `uses` protocol is not installed', async () => {
|
|
342
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
352
343
|
// Try to install comments protocol WITHOUT installing threads first
|
|
353
|
-
const commentsConfigure =
|
|
344
|
+
const commentsConfigure = await ProtocolsConfigure.create({
|
|
354
345
|
definition: commentsProtocol,
|
|
355
346
|
signer: Jws.createSigner(alice),
|
|
356
347
|
});
|
|
357
|
-
const reply =
|
|
348
|
+
const reply = await dwn.processMessage(alice.did, commentsConfigure.message);
|
|
358
349
|
expect(reply.status.code).toBe(400);
|
|
359
350
|
expect(reply.status.detail).toContain(DwnErrorCode.ProtocolsConfigureComposedProtocolNotInstalled);
|
|
360
|
-
})
|
|
361
|
-
it('should accept composing protocol when `uses` protocol is already installed', () =>
|
|
362
|
-
const alice =
|
|
351
|
+
});
|
|
352
|
+
it('should accept composing protocol when `uses` protocol is already installed', async () => {
|
|
353
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
363
354
|
// Install threads protocol first
|
|
364
|
-
const threadsConfigure =
|
|
355
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
365
356
|
definition: threadsProtocol,
|
|
366
357
|
signer: Jws.createSigner(alice),
|
|
367
358
|
});
|
|
368
|
-
const threadsReply =
|
|
359
|
+
const threadsReply = await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
369
360
|
expect(threadsReply.status.code).toBe(202);
|
|
370
361
|
// Now install comments protocol — should succeed
|
|
371
|
-
const commentsConfigure =
|
|
362
|
+
const commentsConfigure = await ProtocolsConfigure.create({
|
|
372
363
|
definition: commentsProtocol,
|
|
373
364
|
signer: Jws.createSigner(alice),
|
|
374
365
|
});
|
|
375
|
-
const commentsReply =
|
|
366
|
+
const commentsReply = await dwn.processMessage(alice.did, commentsConfigure.message);
|
|
376
367
|
expect(commentsReply.status.code).toBe(202);
|
|
377
|
-
})
|
|
378
|
-
it('should reject composing protocol if `$ref` path does not exist in referenced protocol', () =>
|
|
379
|
-
const alice =
|
|
368
|
+
});
|
|
369
|
+
it('should reject composing protocol if `$ref` path does not exist in referenced protocol', async () => {
|
|
370
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
380
371
|
// Install threads protocol first
|
|
381
|
-
const threadsConfigure =
|
|
372
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
382
373
|
definition: threadsProtocol,
|
|
383
374
|
signer: Jws.createSigner(alice),
|
|
384
375
|
});
|
|
385
|
-
|
|
376
|
+
await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
386
377
|
// Install a composing protocol that references a non-existent type path
|
|
387
378
|
const badDefinition = {
|
|
388
379
|
protocol: 'https://bad.example.com',
|
|
@@ -398,22 +389,22 @@ export function testProtocolComposition() {
|
|
|
398
389
|
},
|
|
399
390
|
},
|
|
400
391
|
};
|
|
401
|
-
const badConfigure =
|
|
392
|
+
const badConfigure = await ProtocolsConfigure.create({
|
|
402
393
|
definition: badDefinition,
|
|
403
394
|
signer: Jws.createSigner(alice),
|
|
404
395
|
});
|
|
405
|
-
const reply =
|
|
396
|
+
const reply = await dwn.processMessage(alice.did, badConfigure.message);
|
|
406
397
|
expect(reply.status.code).toBe(400);
|
|
407
398
|
expect(reply.status.detail).toContain(DwnErrorCode.ProtocolsConfigureInvalidRefProtocolPath);
|
|
408
|
-
})
|
|
409
|
-
it('should reject composing protocol if cross-protocol `of` path does not exist in referenced protocol', () =>
|
|
410
|
-
const alice =
|
|
399
|
+
});
|
|
400
|
+
it('should reject composing protocol if cross-protocol `of` path does not exist in referenced protocol', async () => {
|
|
401
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
411
402
|
// Install threads protocol first
|
|
412
|
-
const threadsConfigure =
|
|
403
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
413
404
|
definition: threadsProtocol,
|
|
414
405
|
signer: Jws.createSigner(alice),
|
|
415
406
|
});
|
|
416
|
-
|
|
407
|
+
await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
417
408
|
// Install a composing protocol with an `of` reference to a non-existent path
|
|
418
409
|
const badDefinition = {
|
|
419
410
|
protocol: 'https://bad.example.com',
|
|
@@ -431,22 +422,22 @@ export function testProtocolComposition() {
|
|
|
431
422
|
},
|
|
432
423
|
},
|
|
433
424
|
};
|
|
434
|
-
const badConfigure =
|
|
425
|
+
const badConfigure = await ProtocolsConfigure.create({
|
|
435
426
|
definition: badDefinition,
|
|
436
427
|
signer: Jws.createSigner(alice),
|
|
437
428
|
});
|
|
438
|
-
const reply =
|
|
429
|
+
const reply = await dwn.processMessage(alice.did, badConfigure.message);
|
|
439
430
|
expect(reply.status.code).toBe(400);
|
|
440
431
|
expect(reply.status.detail).toContain(DwnErrorCode.ProtocolsConfigureInvalidCrossProtocolOf);
|
|
441
|
-
})
|
|
442
|
-
it('should reject composing protocol if cross-protocol role does not exist in referenced protocol', () =>
|
|
443
|
-
const alice =
|
|
432
|
+
});
|
|
433
|
+
it('should reject composing protocol if cross-protocol role does not exist in referenced protocol', async () => {
|
|
434
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
444
435
|
// Install threads protocol first
|
|
445
|
-
const threadsConfigure =
|
|
436
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
446
437
|
definition: threadsProtocol,
|
|
447
438
|
signer: Jws.createSigner(alice),
|
|
448
439
|
});
|
|
449
|
-
|
|
440
|
+
await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
450
441
|
// Install a composing protocol with invalid cross-protocol role
|
|
451
442
|
const badDefinition = {
|
|
452
443
|
protocol: 'https://bad.example.com',
|
|
@@ -465,45 +456,45 @@ export function testProtocolComposition() {
|
|
|
465
456
|
},
|
|
466
457
|
},
|
|
467
458
|
};
|
|
468
|
-
const badConfigure =
|
|
459
|
+
const badConfigure = await ProtocolsConfigure.create({
|
|
469
460
|
definition: badDefinition,
|
|
470
461
|
signer: Jws.createSigner(alice),
|
|
471
462
|
});
|
|
472
|
-
const reply =
|
|
463
|
+
const reply = await dwn.processMessage(alice.did, badConfigure.message);
|
|
473
464
|
expect(reply.status.code).toBe(400);
|
|
474
465
|
expect(reply.status.detail).toContain(DwnErrorCode.ProtocolsConfigureInvalidCrossProtocolRole);
|
|
475
|
-
})
|
|
466
|
+
});
|
|
476
467
|
});
|
|
477
468
|
// =========================================================================
|
|
478
469
|
// Runtime cross-protocol record creation tests
|
|
479
470
|
// =========================================================================
|
|
480
471
|
describe('cross-protocol record creation', () => {
|
|
481
|
-
it('should allow creating a child record in a composing protocol under a parent from a different protocol', () =>
|
|
482
|
-
const alice =
|
|
472
|
+
it('should allow creating a child record in a composing protocol under a parent from a different protocol', async () => {
|
|
473
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
483
474
|
// Install both protocols
|
|
484
|
-
const threadsConfigure =
|
|
475
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
485
476
|
definition: threadsProtocol,
|
|
486
477
|
signer: Jws.createSigner(alice),
|
|
487
478
|
});
|
|
488
|
-
|
|
489
|
-
const commentsConfigure =
|
|
479
|
+
await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
480
|
+
const commentsConfigure = await ProtocolsConfigure.create({
|
|
490
481
|
definition: commentsProtocol,
|
|
491
482
|
signer: Jws.createSigner(alice),
|
|
492
483
|
});
|
|
493
|
-
|
|
484
|
+
await dwn.processMessage(alice.did, commentsConfigure.message);
|
|
494
485
|
// Create a thread record in the threads protocol
|
|
495
|
-
const threadWrite =
|
|
486
|
+
const threadWrite = await TestDataGenerator.generateRecordsWrite({
|
|
496
487
|
author: alice,
|
|
497
488
|
protocol: threadsProtocol.protocol,
|
|
498
489
|
protocolPath: 'thread',
|
|
499
490
|
schema: 'https://threads.example.com/schemas/thread',
|
|
500
491
|
dataFormat: 'application/json',
|
|
501
492
|
});
|
|
502
|
-
const threadReply =
|
|
493
|
+
const threadReply = await dwn.processMessage(alice.did, threadWrite.message, { dataStream: threadWrite.dataStream });
|
|
503
494
|
expect(threadReply.status.code).toBe(202);
|
|
504
495
|
const threadContextId = threadWrite.message.contextId;
|
|
505
496
|
// Create a comment record in the comments protocol, parented under the thread
|
|
506
|
-
const commentWrite =
|
|
497
|
+
const commentWrite = await TestDataGenerator.generateRecordsWrite({
|
|
507
498
|
author: alice,
|
|
508
499
|
protocol: commentsProtocol.protocol,
|
|
509
500
|
protocolPath: 'thread/comment',
|
|
@@ -511,35 +502,35 @@ export function testProtocolComposition() {
|
|
|
511
502
|
dataFormat: 'application/json',
|
|
512
503
|
parentContextId: threadContextId,
|
|
513
504
|
});
|
|
514
|
-
const commentReply =
|
|
505
|
+
const commentReply = await dwn.processMessage(alice.did, commentWrite.message, { dataStream: commentWrite.dataStream });
|
|
515
506
|
expect(commentReply.status.code).toBe(202);
|
|
516
507
|
// The comment's contextId should chain from the thread's contextId
|
|
517
508
|
expect(commentWrite.message.contextId).toBe(`${threadContextId}/${commentWrite.message.recordId}`);
|
|
518
|
-
})
|
|
519
|
-
it('should allow creating a grandchild in the composing protocol under a cross-protocol child', () =>
|
|
520
|
-
const alice =
|
|
509
|
+
});
|
|
510
|
+
it('should allow creating a grandchild in the composing protocol under a cross-protocol child', async () => {
|
|
511
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
521
512
|
// Install both protocols
|
|
522
|
-
const threadsConfigure =
|
|
513
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
523
514
|
definition: threadsProtocol,
|
|
524
515
|
signer: Jws.createSigner(alice),
|
|
525
516
|
});
|
|
526
|
-
|
|
527
|
-
const commentsConfigure =
|
|
517
|
+
await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
518
|
+
const commentsConfigure = await ProtocolsConfigure.create({
|
|
528
519
|
definition: commentsProtocol,
|
|
529
520
|
signer: Jws.createSigner(alice),
|
|
530
521
|
});
|
|
531
|
-
|
|
522
|
+
await dwn.processMessage(alice.did, commentsConfigure.message);
|
|
532
523
|
// Create thread -> comment -> reaction chain
|
|
533
|
-
const threadWrite =
|
|
524
|
+
const threadWrite = await TestDataGenerator.generateRecordsWrite({
|
|
534
525
|
author: alice,
|
|
535
526
|
protocol: threadsProtocol.protocol,
|
|
536
527
|
protocolPath: 'thread',
|
|
537
528
|
schema: 'https://threads.example.com/schemas/thread',
|
|
538
529
|
dataFormat: 'application/json',
|
|
539
530
|
});
|
|
540
|
-
|
|
531
|
+
await dwn.processMessage(alice.did, threadWrite.message, { dataStream: threadWrite.dataStream });
|
|
541
532
|
const threadContextId = threadWrite.message.contextId;
|
|
542
|
-
const commentWrite =
|
|
533
|
+
const commentWrite = await TestDataGenerator.generateRecordsWrite({
|
|
543
534
|
author: alice,
|
|
544
535
|
protocol: commentsProtocol.protocol,
|
|
545
536
|
protocolPath: 'thread/comment',
|
|
@@ -547,10 +538,10 @@ export function testProtocolComposition() {
|
|
|
547
538
|
dataFormat: 'application/json',
|
|
548
539
|
parentContextId: threadContextId,
|
|
549
540
|
});
|
|
550
|
-
|
|
541
|
+
await dwn.processMessage(alice.did, commentWrite.message, { dataStream: commentWrite.dataStream });
|
|
551
542
|
const commentContextId = commentWrite.message.contextId;
|
|
552
543
|
// Create a reaction under the comment (grandchild, same composing protocol)
|
|
553
|
-
const reactionWrite =
|
|
544
|
+
const reactionWrite = await TestDataGenerator.generateRecordsWrite({
|
|
554
545
|
author: alice,
|
|
555
546
|
protocol: commentsProtocol.protocol,
|
|
556
547
|
protocolPath: 'thread/comment/reaction',
|
|
@@ -558,104 +549,104 @@ export function testProtocolComposition() {
|
|
|
558
549
|
dataFormat: 'application/json',
|
|
559
550
|
parentContextId: commentContextId,
|
|
560
551
|
});
|
|
561
|
-
const reactionReply =
|
|
552
|
+
const reactionReply = await dwn.processMessage(alice.did, reactionWrite.message, { dataStream: reactionWrite.dataStream });
|
|
562
553
|
expect(reactionReply.status.code).toBe(202);
|
|
563
|
-
})
|
|
554
|
+
});
|
|
564
555
|
});
|
|
565
556
|
// =========================================================================
|
|
566
557
|
// Writing at the $ref position
|
|
567
558
|
// =========================================================================
|
|
568
559
|
describe('writing at the $ref position', () => {
|
|
569
|
-
it('should reject a non-tenant writing at the `$ref` position because `$ref` nodes have no `$actions`', () =>
|
|
570
|
-
const alice =
|
|
571
|
-
const bob =
|
|
560
|
+
it('should reject a non-tenant writing at the `$ref` position because `$ref` nodes have no `$actions`', async () => {
|
|
561
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
562
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
572
563
|
// Install both protocols on Alice's DWN
|
|
573
|
-
const threadsConfigure =
|
|
564
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
574
565
|
definition: threadsProtocol,
|
|
575
566
|
signer: Jws.createSigner(alice),
|
|
576
567
|
});
|
|
577
|
-
|
|
578
|
-
const commentsConfigure =
|
|
568
|
+
await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
569
|
+
const commentsConfigure = await ProtocolsConfigure.create({
|
|
579
570
|
definition: commentsProtocol,
|
|
580
571
|
signer: Jws.createSigner(alice),
|
|
581
572
|
});
|
|
582
|
-
|
|
573
|
+
await dwn.processMessage(alice.did, commentsConfigure.message);
|
|
583
574
|
// Bob tries to write a record at the `$ref` position (protocolPath: 'thread')
|
|
584
575
|
// through the composing protocol. The `$ref` node has no `$actions`, so this should
|
|
585
576
|
// be rejected for any non-tenant author.
|
|
586
|
-
const threadWriteAtRef =
|
|
577
|
+
const threadWriteAtRef = await TestDataGenerator.generateRecordsWrite({
|
|
587
578
|
author: bob,
|
|
588
579
|
protocol: commentsProtocol.protocol,
|
|
589
580
|
protocolPath: 'thread',
|
|
590
581
|
schema: 'https://threads.example.com/schemas/thread',
|
|
591
582
|
dataFormat: 'application/json',
|
|
592
583
|
});
|
|
593
|
-
const reply =
|
|
584
|
+
const reply = await dwn.processMessage(alice.did, threadWriteAtRef.message, { dataStream: threadWriteAtRef.dataStream });
|
|
594
585
|
expect(reply.status.code).toBe(401);
|
|
595
586
|
expect(reply.status.detail).toContain(DwnErrorCode.ProtocolAuthorizationActionRulesNotFound);
|
|
596
|
-
})
|
|
597
|
-
it('should resolve type from the referenced protocol for records at the `$ref` position', () =>
|
|
598
|
-
const alice =
|
|
587
|
+
});
|
|
588
|
+
it('should resolve type from the referenced protocol for records at the `$ref` position', async () => {
|
|
589
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
599
590
|
// Install both protocols on Alice's DWN
|
|
600
|
-
const threadsConfigure =
|
|
591
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
601
592
|
definition: threadsProtocol,
|
|
602
593
|
signer: Jws.createSigner(alice),
|
|
603
594
|
});
|
|
604
|
-
|
|
605
|
-
const commentsConfigure =
|
|
595
|
+
await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
596
|
+
const commentsConfigure = await ProtocolsConfigure.create({
|
|
606
597
|
definition: commentsProtocol,
|
|
607
598
|
signer: Jws.createSigner(alice),
|
|
608
599
|
});
|
|
609
|
-
|
|
600
|
+
await dwn.processMessage(alice.did, commentsConfigure.message);
|
|
610
601
|
// Alice (tenant) writes at the `$ref` position using the WRONG schema.
|
|
611
602
|
// The type at position 'thread' should resolve from the threads protocol, which expects
|
|
612
603
|
// schema 'https://threads.example.com/schemas/thread'. Using a different schema should fail.
|
|
613
|
-
const wrongSchemaWrite =
|
|
604
|
+
const wrongSchemaWrite = await TestDataGenerator.generateRecordsWrite({
|
|
614
605
|
author: alice,
|
|
615
606
|
protocol: commentsProtocol.protocol,
|
|
616
607
|
protocolPath: 'thread',
|
|
617
608
|
schema: 'https://comments.example.com/schemas/comment', // wrong schema
|
|
618
609
|
dataFormat: 'application/json',
|
|
619
610
|
});
|
|
620
|
-
const reply =
|
|
611
|
+
const reply = await dwn.processMessage(alice.did, wrongSchemaWrite.message, { dataStream: wrongSchemaWrite.dataStream });
|
|
621
612
|
expect(reply.status.code).toBe(400);
|
|
622
613
|
// Type verification should fail because the schema doesn't match the referenced protocol's type
|
|
623
|
-
})
|
|
614
|
+
});
|
|
624
615
|
});
|
|
625
616
|
// =========================================================================
|
|
626
617
|
// Cross-protocol role invocation tests
|
|
627
618
|
// =========================================================================
|
|
628
619
|
describe('cross-protocol role invocation', () => {
|
|
629
|
-
it('should allow a cross-protocol role holder to perform actions in the composing protocol', () =>
|
|
630
|
-
const alice =
|
|
631
|
-
const bob =
|
|
620
|
+
it('should allow a cross-protocol role holder to perform actions in the composing protocol', async () => {
|
|
621
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
622
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
632
623
|
// Install threads protocol on Alice's DWN
|
|
633
|
-
const threadsConfigure =
|
|
624
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
634
625
|
definition: threadsProtocol,
|
|
635
626
|
signer: Jws.createSigner(alice),
|
|
636
627
|
});
|
|
637
|
-
const threadsReply =
|
|
628
|
+
const threadsReply = await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
638
629
|
expect(threadsReply.status.code).toBe(202);
|
|
639
630
|
// Install comments protocol on Alice's DWN
|
|
640
|
-
const commentsConfigure =
|
|
631
|
+
const commentsConfigure = await ProtocolsConfigure.create({
|
|
641
632
|
definition: commentsProtocol,
|
|
642
633
|
signer: Jws.createSigner(alice),
|
|
643
634
|
});
|
|
644
|
-
const commentsReply =
|
|
635
|
+
const commentsReply = await dwn.processMessage(alice.did, commentsConfigure.message);
|
|
645
636
|
expect(commentsReply.status.code).toBe(202);
|
|
646
637
|
// Alice creates a thread
|
|
647
|
-
const threadWrite =
|
|
638
|
+
const threadWrite = await TestDataGenerator.generateRecordsWrite({
|
|
648
639
|
author: alice,
|
|
649
640
|
protocol: threadsProtocol.protocol,
|
|
650
641
|
protocolPath: 'thread',
|
|
651
642
|
schema: 'https://threads.example.com/schemas/thread',
|
|
652
643
|
dataFormat: 'application/json',
|
|
653
644
|
});
|
|
654
|
-
const threadReply =
|
|
645
|
+
const threadReply = await dwn.processMessage(alice.did, threadWrite.message, { dataStream: threadWrite.dataStream });
|
|
655
646
|
expect(threadReply.status.code).toBe(202);
|
|
656
647
|
const threadContextId = threadWrite.message.contextId;
|
|
657
648
|
// Alice assigns Bob as a participant in the thread (role record in threads protocol)
|
|
658
|
-
const participantWrite =
|
|
649
|
+
const participantWrite = await TestDataGenerator.generateRecordsWrite({
|
|
659
650
|
author: alice,
|
|
660
651
|
recipient: bob.did,
|
|
661
652
|
protocol: threadsProtocol.protocol,
|
|
@@ -664,10 +655,10 @@ export function testProtocolComposition() {
|
|
|
664
655
|
dataFormat: 'application/json',
|
|
665
656
|
parentContextId: threadContextId,
|
|
666
657
|
});
|
|
667
|
-
const participantReply =
|
|
658
|
+
const participantReply = await dwn.processMessage(alice.did, participantWrite.message, { dataStream: participantWrite.dataStream });
|
|
668
659
|
expect(participantReply.status.code).toBe(202);
|
|
669
660
|
// Bob invokes the cross-protocol role to read comments
|
|
670
|
-
const commentWrite =
|
|
661
|
+
const commentWrite = await TestDataGenerator.generateRecordsWrite({
|
|
671
662
|
author: alice,
|
|
672
663
|
protocol: commentsProtocol.protocol,
|
|
673
664
|
protocolPath: 'thread/comment',
|
|
@@ -675,10 +666,10 @@ export function testProtocolComposition() {
|
|
|
675
666
|
dataFormat: 'application/json',
|
|
676
667
|
parentContextId: threadContextId,
|
|
677
668
|
});
|
|
678
|
-
const commentReply =
|
|
669
|
+
const commentReply = await dwn.processMessage(alice.did, commentWrite.message, { dataStream: commentWrite.dataStream });
|
|
679
670
|
expect(commentReply.status.code).toBe(202);
|
|
680
671
|
// Bob reads the comment using the cross-protocol role
|
|
681
|
-
const bobRead =
|
|
672
|
+
const bobRead = await RecordsRead.create({
|
|
682
673
|
signer: Jws.createSigner(bob),
|
|
683
674
|
protocolRole: 'threads:thread/participant',
|
|
684
675
|
filter: {
|
|
@@ -687,36 +678,35 @@ export function testProtocolComposition() {
|
|
|
687
678
|
contextId: threadContextId,
|
|
688
679
|
},
|
|
689
680
|
});
|
|
690
|
-
const bobReadReply =
|
|
681
|
+
const bobReadReply = await dwn.processMessage(alice.did, bobRead.message);
|
|
691
682
|
expect(bobReadReply.status.code).toBe(200);
|
|
692
|
-
})
|
|
693
|
-
it('should allow a cross-protocol role holder to query records in the composing protocol', () =>
|
|
694
|
-
|
|
695
|
-
const
|
|
696
|
-
const bob = yield TestDataGenerator.generateDidKeyPersona();
|
|
683
|
+
});
|
|
684
|
+
it('should allow a cross-protocol role holder to query records in the composing protocol', async () => {
|
|
685
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
686
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
697
687
|
// Install both protocols on Alice's DWN
|
|
698
|
-
const threadsConfigure =
|
|
688
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
699
689
|
definition: threadsProtocol,
|
|
700
690
|
signer: Jws.createSigner(alice),
|
|
701
691
|
});
|
|
702
|
-
|
|
703
|
-
const commentsConfigure =
|
|
692
|
+
await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
693
|
+
const commentsConfigure = await ProtocolsConfigure.create({
|
|
704
694
|
definition: commentsProtocol,
|
|
705
695
|
signer: Jws.createSigner(alice),
|
|
706
696
|
});
|
|
707
|
-
|
|
697
|
+
await dwn.processMessage(alice.did, commentsConfigure.message);
|
|
708
698
|
// Alice creates a thread
|
|
709
|
-
const threadWrite =
|
|
699
|
+
const threadWrite = await TestDataGenerator.generateRecordsWrite({
|
|
710
700
|
author: alice,
|
|
711
701
|
protocol: threadsProtocol.protocol,
|
|
712
702
|
protocolPath: 'thread',
|
|
713
703
|
schema: 'https://threads.example.com/schemas/thread',
|
|
714
704
|
dataFormat: 'application/json',
|
|
715
705
|
});
|
|
716
|
-
|
|
706
|
+
await dwn.processMessage(alice.did, threadWrite.message, { dataStream: threadWrite.dataStream });
|
|
717
707
|
const threadContextId = threadWrite.message.contextId;
|
|
718
708
|
// Alice assigns Bob as a participant
|
|
719
|
-
const participantWrite =
|
|
709
|
+
const participantWrite = await TestDataGenerator.generateRecordsWrite({
|
|
720
710
|
author: alice,
|
|
721
711
|
recipient: bob.did,
|
|
722
712
|
protocol: threadsProtocol.protocol,
|
|
@@ -725,9 +715,9 @@ export function testProtocolComposition() {
|
|
|
725
715
|
dataFormat: 'application/json',
|
|
726
716
|
parentContextId: threadContextId,
|
|
727
717
|
});
|
|
728
|
-
|
|
718
|
+
await dwn.processMessage(alice.did, participantWrite.message, { dataStream: participantWrite.dataStream });
|
|
729
719
|
// Alice creates two comments
|
|
730
|
-
const comment1 =
|
|
720
|
+
const comment1 = await TestDataGenerator.generateRecordsWrite({
|
|
731
721
|
author: alice,
|
|
732
722
|
protocol: commentsProtocol.protocol,
|
|
733
723
|
protocolPath: 'thread/comment',
|
|
@@ -735,8 +725,8 @@ export function testProtocolComposition() {
|
|
|
735
725
|
dataFormat: 'application/json',
|
|
736
726
|
parentContextId: threadContextId,
|
|
737
727
|
});
|
|
738
|
-
|
|
739
|
-
const comment2 =
|
|
728
|
+
await dwn.processMessage(alice.did, comment1.message, { dataStream: comment1.dataStream });
|
|
729
|
+
const comment2 = await TestDataGenerator.generateRecordsWrite({
|
|
740
730
|
author: alice,
|
|
741
731
|
protocol: commentsProtocol.protocol,
|
|
742
732
|
protocolPath: 'thread/comment',
|
|
@@ -744,9 +734,9 @@ export function testProtocolComposition() {
|
|
|
744
734
|
dataFormat: 'application/json',
|
|
745
735
|
parentContextId: threadContextId,
|
|
746
736
|
});
|
|
747
|
-
|
|
737
|
+
await dwn.processMessage(alice.did, comment2.message, { dataStream: comment2.dataStream });
|
|
748
738
|
// Bob queries comments using the cross-protocol role
|
|
749
|
-
const bobQuery =
|
|
739
|
+
const bobQuery = await RecordsQuery.create({
|
|
750
740
|
signer: Jws.createSigner(bob),
|
|
751
741
|
protocolRole: 'threads:thread/participant',
|
|
752
742
|
filter: {
|
|
@@ -755,37 +745,37 @@ export function testProtocolComposition() {
|
|
|
755
745
|
contextId: threadContextId,
|
|
756
746
|
},
|
|
757
747
|
});
|
|
758
|
-
const bobQueryReply =
|
|
748
|
+
const bobQueryReply = await dwn.processMessage(alice.did, bobQuery.message);
|
|
759
749
|
expect(bobQueryReply.status.code).toBe(200);
|
|
760
|
-
expect(
|
|
761
|
-
})
|
|
762
|
-
it('should allow a cross-protocol role holder to co-delete records in the composing protocol', () =>
|
|
763
|
-
const alice =
|
|
764
|
-
const bob =
|
|
765
|
-
const carol =
|
|
750
|
+
expect(bobQueryReply.entries?.length).toBe(2);
|
|
751
|
+
});
|
|
752
|
+
it('should allow a cross-protocol role holder to co-delete records in the composing protocol', async () => {
|
|
753
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
754
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
755
|
+
const carol = await TestDataGenerator.generateDidKeyPersona();
|
|
766
756
|
// Install both protocols on Alice's DWN
|
|
767
|
-
const threadsConfigure =
|
|
757
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
768
758
|
definition: threadsProtocol,
|
|
769
759
|
signer: Jws.createSigner(alice),
|
|
770
760
|
});
|
|
771
|
-
|
|
772
|
-
const commentsConfigure =
|
|
761
|
+
await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
762
|
+
const commentsConfigure = await ProtocolsConfigure.create({
|
|
773
763
|
definition: commentsProtocol,
|
|
774
764
|
signer: Jws.createSigner(alice),
|
|
775
765
|
});
|
|
776
|
-
|
|
766
|
+
await dwn.processMessage(alice.did, commentsConfigure.message);
|
|
777
767
|
// Alice creates a thread
|
|
778
|
-
const threadWrite =
|
|
768
|
+
const threadWrite = await TestDataGenerator.generateRecordsWrite({
|
|
779
769
|
author: alice,
|
|
780
770
|
protocol: threadsProtocol.protocol,
|
|
781
771
|
protocolPath: 'thread',
|
|
782
772
|
schema: 'https://threads.example.com/schemas/thread',
|
|
783
773
|
dataFormat: 'application/json',
|
|
784
774
|
});
|
|
785
|
-
|
|
775
|
+
await dwn.processMessage(alice.did, threadWrite.message, { dataStream: threadWrite.dataStream });
|
|
786
776
|
const threadContextId = threadWrite.message.contextId;
|
|
787
777
|
// Alice assigns Bob as a participant (role record)
|
|
788
|
-
const participantWrite =
|
|
778
|
+
const participantWrite = await TestDataGenerator.generateRecordsWrite({
|
|
789
779
|
author: alice,
|
|
790
780
|
recipient: bob.did,
|
|
791
781
|
protocol: threadsProtocol.protocol,
|
|
@@ -794,9 +784,9 @@ export function testProtocolComposition() {
|
|
|
794
784
|
dataFormat: 'application/json',
|
|
795
785
|
parentContextId: threadContextId,
|
|
796
786
|
});
|
|
797
|
-
|
|
787
|
+
await dwn.processMessage(alice.did, participantWrite.message, { dataStream: participantWrite.dataStream });
|
|
798
788
|
// Carol creates a comment (via 'anyone' can 'create')
|
|
799
|
-
const carolComment =
|
|
789
|
+
const carolComment = await TestDataGenerator.generateRecordsWrite({
|
|
800
790
|
author: carol,
|
|
801
791
|
protocol: commentsProtocol.protocol,
|
|
802
792
|
protocolPath: 'thread/comment',
|
|
@@ -804,43 +794,43 @@ export function testProtocolComposition() {
|
|
|
804
794
|
dataFormat: 'application/json',
|
|
805
795
|
parentContextId: threadContextId,
|
|
806
796
|
});
|
|
807
|
-
|
|
797
|
+
await dwn.processMessage(alice.did, carolComment.message, { dataStream: carolComment.dataStream });
|
|
808
798
|
// Bob (participant) co-deletes Carol's comment using the cross-protocol role
|
|
809
799
|
// The commentsProtocol grants 'threads:thread/participant' the 'co-delete' action on comments
|
|
810
|
-
const bobDelete =
|
|
800
|
+
const bobDelete = await RecordsDelete.create({
|
|
811
801
|
protocolRole: 'threads:thread/participant',
|
|
812
802
|
recordId: carolComment.message.recordId,
|
|
813
803
|
signer: Jws.createSigner(bob),
|
|
814
804
|
});
|
|
815
|
-
const deleteReply =
|
|
805
|
+
const deleteReply = await dwn.processMessage(alice.did, bobDelete.message);
|
|
816
806
|
expect(deleteReply.status.code).toBe(202);
|
|
817
|
-
})
|
|
818
|
-
it('should deny cross-protocol role access when the role record has been deleted (revocation)', () =>
|
|
819
|
-
const alice =
|
|
820
|
-
const bob =
|
|
807
|
+
});
|
|
808
|
+
it('should deny cross-protocol role access when the role record has been deleted (revocation)', async () => {
|
|
809
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
810
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
821
811
|
// Install both protocols on Alice's DWN
|
|
822
|
-
const threadsConfigure =
|
|
812
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
823
813
|
definition: threadsProtocol,
|
|
824
814
|
signer: Jws.createSigner(alice),
|
|
825
815
|
});
|
|
826
|
-
|
|
827
|
-
const commentsConfigure =
|
|
816
|
+
await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
817
|
+
const commentsConfigure = await ProtocolsConfigure.create({
|
|
828
818
|
definition: commentsProtocol,
|
|
829
819
|
signer: Jws.createSigner(alice),
|
|
830
820
|
});
|
|
831
|
-
|
|
821
|
+
await dwn.processMessage(alice.did, commentsConfigure.message);
|
|
832
822
|
// Alice creates a thread
|
|
833
|
-
const threadWrite =
|
|
823
|
+
const threadWrite = await TestDataGenerator.generateRecordsWrite({
|
|
834
824
|
author: alice,
|
|
835
825
|
protocol: threadsProtocol.protocol,
|
|
836
826
|
protocolPath: 'thread',
|
|
837
827
|
schema: 'https://threads.example.com/schemas/thread',
|
|
838
828
|
dataFormat: 'application/json',
|
|
839
829
|
});
|
|
840
|
-
|
|
830
|
+
await dwn.processMessage(alice.did, threadWrite.message, { dataStream: threadWrite.dataStream });
|
|
841
831
|
const threadContextId = threadWrite.message.contextId;
|
|
842
832
|
// Alice assigns Bob as a participant
|
|
843
|
-
const participantWrite =
|
|
833
|
+
const participantWrite = await TestDataGenerator.generateRecordsWrite({
|
|
844
834
|
author: alice,
|
|
845
835
|
recipient: bob.did,
|
|
846
836
|
protocol: threadsProtocol.protocol,
|
|
@@ -849,9 +839,9 @@ export function testProtocolComposition() {
|
|
|
849
839
|
dataFormat: 'application/json',
|
|
850
840
|
parentContextId: threadContextId,
|
|
851
841
|
});
|
|
852
|
-
|
|
842
|
+
await dwn.processMessage(alice.did, participantWrite.message, { dataStream: participantWrite.dataStream });
|
|
853
843
|
// Alice creates a comment
|
|
854
|
-
const commentWrite =
|
|
844
|
+
const commentWrite = await TestDataGenerator.generateRecordsWrite({
|
|
855
845
|
author: alice,
|
|
856
846
|
protocol: commentsProtocol.protocol,
|
|
857
847
|
protocolPath: 'thread/comment',
|
|
@@ -859,9 +849,9 @@ export function testProtocolComposition() {
|
|
|
859
849
|
dataFormat: 'application/json',
|
|
860
850
|
parentContextId: threadContextId,
|
|
861
851
|
});
|
|
862
|
-
|
|
852
|
+
await dwn.processMessage(alice.did, commentWrite.message, { dataStream: commentWrite.dataStream });
|
|
863
853
|
// Verify Bob CAN read the comment (role is active)
|
|
864
|
-
const bobRead =
|
|
854
|
+
const bobRead = await RecordsRead.create({
|
|
865
855
|
signer: Jws.createSigner(bob),
|
|
866
856
|
protocolRole: 'threads:thread/participant',
|
|
867
857
|
filter: {
|
|
@@ -870,17 +860,17 @@ export function testProtocolComposition() {
|
|
|
870
860
|
contextId: threadContextId,
|
|
871
861
|
},
|
|
872
862
|
});
|
|
873
|
-
const bobReadReply =
|
|
863
|
+
const bobReadReply = await dwn.processMessage(alice.did, bobRead.message);
|
|
874
864
|
expect(bobReadReply.status.code).toBe(200);
|
|
875
865
|
// Alice deletes Bob's participant role record (revocation)
|
|
876
|
-
const deleteRole =
|
|
866
|
+
const deleteRole = await RecordsDelete.create({
|
|
877
867
|
recordId: participantWrite.message.recordId,
|
|
878
868
|
signer: Jws.createSigner(alice),
|
|
879
869
|
});
|
|
880
|
-
const deleteRoleReply =
|
|
870
|
+
const deleteRoleReply = await dwn.processMessage(alice.did, deleteRole.message);
|
|
881
871
|
expect(deleteRoleReply.status.code).toBe(202);
|
|
882
872
|
// Bob tries to read the comment again — should be denied because role was deleted
|
|
883
|
-
const bobRead2 =
|
|
873
|
+
const bobRead2 = await RecordsRead.create({
|
|
884
874
|
signer: Jws.createSigner(bob),
|
|
885
875
|
protocolRole: 'threads:thread/participant',
|
|
886
876
|
filter: {
|
|
@@ -889,36 +879,36 @@ export function testProtocolComposition() {
|
|
|
889
879
|
contextId: threadContextId,
|
|
890
880
|
},
|
|
891
881
|
});
|
|
892
|
-
const bobRead2Reply =
|
|
882
|
+
const bobRead2Reply = await dwn.processMessage(alice.did, bobRead2.message);
|
|
893
883
|
expect(bobRead2Reply.status.code).toBe(401);
|
|
894
884
|
expect(bobRead2Reply.status.detail).toContain(DwnErrorCode.ProtocolAuthorizationMatchingRoleRecordNotFound);
|
|
895
|
-
})
|
|
896
|
-
it('should reject a cross-protocol role invocation if the invoker lacks the role record', () =>
|
|
897
|
-
const alice =
|
|
898
|
-
const carol =
|
|
885
|
+
});
|
|
886
|
+
it('should reject a cross-protocol role invocation if the invoker lacks the role record', async () => {
|
|
887
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
888
|
+
const carol = await TestDataGenerator.generateDidKeyPersona();
|
|
899
889
|
// Install both protocols
|
|
900
|
-
const threadsConfigure =
|
|
890
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
901
891
|
definition: threadsProtocol,
|
|
902
892
|
signer: Jws.createSigner(alice),
|
|
903
893
|
});
|
|
904
|
-
|
|
905
|
-
const commentsConfigure =
|
|
894
|
+
await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
895
|
+
const commentsConfigure = await ProtocolsConfigure.create({
|
|
906
896
|
definition: commentsProtocol,
|
|
907
897
|
signer: Jws.createSigner(alice),
|
|
908
898
|
});
|
|
909
|
-
|
|
899
|
+
await dwn.processMessage(alice.did, commentsConfigure.message);
|
|
910
900
|
// Alice creates a thread
|
|
911
|
-
const threadWrite =
|
|
901
|
+
const threadWrite = await TestDataGenerator.generateRecordsWrite({
|
|
912
902
|
author: alice,
|
|
913
903
|
protocol: threadsProtocol.protocol,
|
|
914
904
|
protocolPath: 'thread',
|
|
915
905
|
schema: 'https://threads.example.com/schemas/thread',
|
|
916
906
|
dataFormat: 'application/json',
|
|
917
907
|
});
|
|
918
|
-
|
|
908
|
+
await dwn.processMessage(alice.did, threadWrite.message, { dataStream: threadWrite.dataStream });
|
|
919
909
|
const threadContextId = threadWrite.message.contextId;
|
|
920
910
|
// Alice creates a comment
|
|
921
|
-
const commentWrite =
|
|
911
|
+
const commentWrite = await TestDataGenerator.generateRecordsWrite({
|
|
922
912
|
author: alice,
|
|
923
913
|
protocol: commentsProtocol.protocol,
|
|
924
914
|
protocolPath: 'thread/comment',
|
|
@@ -926,9 +916,9 @@ export function testProtocolComposition() {
|
|
|
926
916
|
dataFormat: 'application/json',
|
|
927
917
|
parentContextId: threadContextId,
|
|
928
918
|
});
|
|
929
|
-
|
|
919
|
+
await dwn.processMessage(alice.did, commentWrite.message, { dataStream: commentWrite.dataStream });
|
|
930
920
|
// Carol (who has NO participant role) tries to read the comment using the cross-protocol role
|
|
931
|
-
const carolRead =
|
|
921
|
+
const carolRead = await RecordsRead.create({
|
|
932
922
|
signer: Jws.createSigner(carol),
|
|
933
923
|
protocolRole: 'threads:thread/participant',
|
|
934
924
|
filter: {
|
|
@@ -937,42 +927,42 @@ export function testProtocolComposition() {
|
|
|
937
927
|
contextId: threadContextId,
|
|
938
928
|
},
|
|
939
929
|
});
|
|
940
|
-
const carolReadReply =
|
|
930
|
+
const carolReadReply = await dwn.processMessage(alice.did, carolRead.message);
|
|
941
931
|
expect(carolReadReply.status.code).toBe(401);
|
|
942
932
|
expect(carolReadReply.status.detail).toContain(DwnErrorCode.ProtocolAuthorizationMatchingRoleRecordNotFound);
|
|
943
|
-
})
|
|
933
|
+
});
|
|
944
934
|
});
|
|
945
935
|
// =========================================================================
|
|
946
936
|
// Cross-protocol `who`/`of` actor checks
|
|
947
937
|
// =========================================================================
|
|
948
938
|
describe('cross-protocol `who`/`of` actor checks', () => {
|
|
949
|
-
it('should allow `author` of a cross-protocol parent to perform actions in the composing protocol', () =>
|
|
950
|
-
const alice =
|
|
951
|
-
const bob =
|
|
939
|
+
it('should allow `author` of a cross-protocol parent to perform actions in the composing protocol', async () => {
|
|
940
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
941
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
952
942
|
// Install both protocols
|
|
953
|
-
const threadsConfigure =
|
|
943
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
954
944
|
definition: threadsProtocol,
|
|
955
945
|
signer: Jws.createSigner(alice),
|
|
956
946
|
});
|
|
957
|
-
|
|
958
|
-
const commentsConfigure =
|
|
947
|
+
await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
948
|
+
const commentsConfigure = await ProtocolsConfigure.create({
|
|
959
949
|
definition: commentsProtocol,
|
|
960
950
|
signer: Jws.createSigner(alice),
|
|
961
951
|
});
|
|
962
|
-
|
|
952
|
+
await dwn.processMessage(alice.did, commentsConfigure.message);
|
|
963
953
|
// Bob creates a thread (via the 'anyone' can 'create' rule)
|
|
964
|
-
const threadWrite =
|
|
954
|
+
const threadWrite = await TestDataGenerator.generateRecordsWrite({
|
|
965
955
|
author: bob,
|
|
966
956
|
protocol: threadsProtocol.protocol,
|
|
967
957
|
protocolPath: 'thread',
|
|
968
958
|
schema: 'https://threads.example.com/schemas/thread',
|
|
969
959
|
dataFormat: 'application/json',
|
|
970
960
|
});
|
|
971
|
-
const threadReply =
|
|
961
|
+
const threadReply = await dwn.processMessage(alice.did, threadWrite.message, { dataStream: threadWrite.dataStream });
|
|
972
962
|
expect(threadReply.status.code).toBe(202);
|
|
973
963
|
const threadContextId = threadWrite.message.contextId;
|
|
974
964
|
// Anyone can create a comment under the thread (via 'anyone' can 'create' rule)
|
|
975
|
-
const commentWrite =
|
|
965
|
+
const commentWrite = await TestDataGenerator.generateRecordsWrite({
|
|
976
966
|
author: alice,
|
|
977
967
|
protocol: commentsProtocol.protocol,
|
|
978
968
|
protocolPath: 'thread/comment',
|
|
@@ -980,10 +970,10 @@ export function testProtocolComposition() {
|
|
|
980
970
|
dataFormat: 'application/json',
|
|
981
971
|
parentContextId: threadContextId,
|
|
982
972
|
});
|
|
983
|
-
const commentReply =
|
|
973
|
+
const commentReply = await dwn.processMessage(alice.did, commentWrite.message, { dataStream: commentWrite.dataStream });
|
|
984
974
|
expect(commentReply.status.code).toBe(202);
|
|
985
975
|
// Anyone can also read (via 'anyone' can 'read' rule)
|
|
986
|
-
const readComment =
|
|
976
|
+
const readComment = await RecordsRead.create({
|
|
987
977
|
signer: Jws.createSigner(bob),
|
|
988
978
|
filter: {
|
|
989
979
|
protocol: commentsProtocol.protocol,
|
|
@@ -991,18 +981,18 @@ export function testProtocolComposition() {
|
|
|
991
981
|
contextId: threadContextId,
|
|
992
982
|
},
|
|
993
983
|
});
|
|
994
|
-
const readReply =
|
|
984
|
+
const readReply = await dwn.processMessage(alice.did, readComment.message);
|
|
995
985
|
expect(readReply.status.code).toBe(200);
|
|
996
|
-
})
|
|
986
|
+
});
|
|
997
987
|
});
|
|
998
988
|
// =========================================================================
|
|
999
989
|
// Cross-protocol `of` actor check — happy path
|
|
1000
990
|
// =========================================================================
|
|
1001
991
|
describe('cross-protocol `of` actor check — happy path', () => {
|
|
1002
|
-
it('should allow author of cross-protocol parent to create records via `who: author, of: alias:path` rule', () =>
|
|
1003
|
-
const alice =
|
|
1004
|
-
const bob =
|
|
1005
|
-
const carol =
|
|
992
|
+
it('should allow author of cross-protocol parent to create records via `who: author, of: alias:path` rule', async () => {
|
|
993
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
994
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
995
|
+
const carol = await TestDataGenerator.generateDidKeyPersona();
|
|
1006
996
|
// A protocol that grants the author of a thread (from the threads protocol) the ability to create moderation actions
|
|
1007
997
|
const moderationProtocol = {
|
|
1008
998
|
protocol: 'https://moderation.example.com',
|
|
@@ -1024,30 +1014,30 @@ export function testProtocolComposition() {
|
|
|
1024
1014
|
},
|
|
1025
1015
|
};
|
|
1026
1016
|
// Install both protocols on Alice's DWN
|
|
1027
|
-
const threadsConfigure =
|
|
1017
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
1028
1018
|
definition: threadsProtocol,
|
|
1029
1019
|
signer: Jws.createSigner(alice),
|
|
1030
1020
|
});
|
|
1031
|
-
|
|
1032
|
-
const moderationConfigure =
|
|
1021
|
+
await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
1022
|
+
const moderationConfigure = await ProtocolsConfigure.create({
|
|
1033
1023
|
definition: moderationProtocol,
|
|
1034
1024
|
signer: Jws.createSigner(alice),
|
|
1035
1025
|
});
|
|
1036
|
-
const modReply =
|
|
1026
|
+
const modReply = await dwn.processMessage(alice.did, moderationConfigure.message);
|
|
1037
1027
|
expect(modReply.status.code).toBe(202);
|
|
1038
1028
|
// Bob creates a thread (via 'anyone' can 'create' in threadsProtocol)
|
|
1039
|
-
const threadWrite =
|
|
1029
|
+
const threadWrite = await TestDataGenerator.generateRecordsWrite({
|
|
1040
1030
|
author: bob,
|
|
1041
1031
|
protocol: threadsProtocol.protocol,
|
|
1042
1032
|
protocolPath: 'thread',
|
|
1043
1033
|
schema: 'https://threads.example.com/schemas/thread',
|
|
1044
1034
|
dataFormat: 'application/json',
|
|
1045
1035
|
});
|
|
1046
|
-
const threadReply =
|
|
1036
|
+
const threadReply = await dwn.processMessage(alice.did, threadWrite.message, { dataStream: threadWrite.dataStream });
|
|
1047
1037
|
expect(threadReply.status.code).toBe(202);
|
|
1048
1038
|
const threadContextId = threadWrite.message.contextId;
|
|
1049
1039
|
// Bob (as author of the thread) creates a moderation action — should succeed
|
|
1050
|
-
const actionWrite =
|
|
1040
|
+
const actionWrite = await TestDataGenerator.generateRecordsWrite({
|
|
1051
1041
|
author: bob,
|
|
1052
1042
|
protocol: moderationProtocol.protocol,
|
|
1053
1043
|
protocolPath: 'thread/action',
|
|
@@ -1055,10 +1045,10 @@ export function testProtocolComposition() {
|
|
|
1055
1045
|
dataFormat: 'application/json',
|
|
1056
1046
|
parentContextId: threadContextId,
|
|
1057
1047
|
});
|
|
1058
|
-
const actionReply =
|
|
1048
|
+
const actionReply = await dwn.processMessage(alice.did, actionWrite.message, { dataStream: actionWrite.dataStream });
|
|
1059
1049
|
expect(actionReply.status.code).toBe(202);
|
|
1060
1050
|
// Carol (NOT author of the thread, NOT the tenant) tries to create a moderation action — should fail
|
|
1061
|
-
const carolActionWrite =
|
|
1051
|
+
const carolActionWrite = await TestDataGenerator.generateRecordsWrite({
|
|
1062
1052
|
author: carol,
|
|
1063
1053
|
protocol: moderationProtocol.protocol,
|
|
1064
1054
|
protocolPath: 'thread/action',
|
|
@@ -1066,17 +1056,17 @@ export function testProtocolComposition() {
|
|
|
1066
1056
|
dataFormat: 'application/json',
|
|
1067
1057
|
parentContextId: threadContextId,
|
|
1068
1058
|
});
|
|
1069
|
-
const carolActionReply =
|
|
1059
|
+
const carolActionReply = await dwn.processMessage(alice.did, carolActionWrite.message, { dataStream: carolActionWrite.dataStream });
|
|
1070
1060
|
expect(carolActionReply.status.code).toBe(401);
|
|
1071
1061
|
expect(carolActionReply.status.detail).toContain(DwnErrorCode.ProtocolAuthorizationActionNotAllowed);
|
|
1072
|
-
})
|
|
1062
|
+
});
|
|
1073
1063
|
});
|
|
1074
1064
|
// =========================================================================
|
|
1075
1065
|
// Edge case and error tests
|
|
1076
1066
|
// =========================================================================
|
|
1077
1067
|
describe('composition error cases', () => {
|
|
1078
|
-
it('should reject `$ref` with malformed format (no colon separator)', () =>
|
|
1079
|
-
const alice =
|
|
1068
|
+
it('should reject `$ref` with malformed format (no colon separator)', async () => {
|
|
1069
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1080
1070
|
const badDefinition = {
|
|
1081
1071
|
protocol: 'https://bad.example.com',
|
|
1082
1072
|
published: true,
|
|
@@ -1092,7 +1082,7 @@ export function testProtocolComposition() {
|
|
|
1092
1082
|
},
|
|
1093
1083
|
};
|
|
1094
1084
|
try {
|
|
1095
|
-
|
|
1085
|
+
await ProtocolsConfigure.create({
|
|
1096
1086
|
definition: badDefinition,
|
|
1097
1087
|
signer: Jws.createSigner(alice),
|
|
1098
1088
|
});
|
|
@@ -1102,9 +1092,9 @@ export function testProtocolComposition() {
|
|
|
1102
1092
|
// JSON schema enforces `$ref` must match pattern `^[a-zA-Z][a-zA-Z0-9_-]*:.+$`
|
|
1103
1093
|
expect(error.message).toContain('must match pattern');
|
|
1104
1094
|
}
|
|
1105
|
-
})
|
|
1106
|
-
it('should reject `$ref` that references own protocol', () =>
|
|
1107
|
-
const alice =
|
|
1095
|
+
});
|
|
1096
|
+
it('should reject `$ref` that references own protocol', async () => {
|
|
1097
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1108
1098
|
const badDefinition = {
|
|
1109
1099
|
protocol: 'https://self.example.com',
|
|
1110
1100
|
published: true,
|
|
@@ -1120,7 +1110,7 @@ export function testProtocolComposition() {
|
|
|
1120
1110
|
},
|
|
1121
1111
|
};
|
|
1122
1112
|
try {
|
|
1123
|
-
|
|
1113
|
+
await ProtocolsConfigure.create({
|
|
1124
1114
|
definition: badDefinition,
|
|
1125
1115
|
signer: Jws.createSigner(alice),
|
|
1126
1116
|
});
|
|
@@ -1129,9 +1119,9 @@ export function testProtocolComposition() {
|
|
|
1129
1119
|
catch (error) {
|
|
1130
1120
|
expect(error.message).toContain(DwnErrorCode.ProtocolsConfigureInvalidUsesSelfReference);
|
|
1131
1121
|
}
|
|
1132
|
-
})
|
|
1133
|
-
it('should reject `uses` with invalid alias name (starts with a number)', () =>
|
|
1134
|
-
const alice =
|
|
1122
|
+
});
|
|
1123
|
+
it('should reject `uses` with invalid alias name (starts with a number)', async () => {
|
|
1124
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1135
1125
|
const badDefinition = {
|
|
1136
1126
|
protocol: 'https://bad.example.com',
|
|
1137
1127
|
published: true,
|
|
@@ -1140,7 +1130,7 @@ export function testProtocolComposition() {
|
|
|
1140
1130
|
structure: {},
|
|
1141
1131
|
};
|
|
1142
1132
|
try {
|
|
1143
|
-
|
|
1133
|
+
await ProtocolsConfigure.create({
|
|
1144
1134
|
definition: badDefinition,
|
|
1145
1135
|
signer: Jws.createSigner(alice),
|
|
1146
1136
|
});
|
|
@@ -1150,9 +1140,9 @@ export function testProtocolComposition() {
|
|
|
1150
1140
|
// JSON schema enforces alias pattern `^[a-zA-Z][a-zA-Z0-9_-]*$` via additionalProperties: false
|
|
1151
1141
|
expect(error.message).toContain('must NOT have additional properties');
|
|
1152
1142
|
}
|
|
1153
|
-
})
|
|
1154
|
-
it('should reject cross-protocol `of` with alias not in `uses`', () =>
|
|
1155
|
-
const alice =
|
|
1143
|
+
});
|
|
1144
|
+
it('should reject cross-protocol `of` with alias not in `uses`', async () => {
|
|
1145
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1156
1146
|
const badDefinition = {
|
|
1157
1147
|
protocol: 'https://bad.example.com',
|
|
1158
1148
|
published: true,
|
|
@@ -1170,7 +1160,7 @@ export function testProtocolComposition() {
|
|
|
1170
1160
|
},
|
|
1171
1161
|
};
|
|
1172
1162
|
try {
|
|
1173
|
-
|
|
1163
|
+
await ProtocolsConfigure.create({
|
|
1174
1164
|
definition: badDefinition,
|
|
1175
1165
|
signer: Jws.createSigner(alice),
|
|
1176
1166
|
});
|
|
@@ -1179,23 +1169,23 @@ export function testProtocolComposition() {
|
|
|
1179
1169
|
catch (error) {
|
|
1180
1170
|
expect(error.message).toContain(DwnErrorCode.ProtocolsConfigureInvalidCrossProtocolOf);
|
|
1181
1171
|
}
|
|
1182
|
-
})
|
|
1183
|
-
it('should return 400 when cross-protocol parent record does not exist at runtime', () =>
|
|
1184
|
-
const alice =
|
|
1172
|
+
});
|
|
1173
|
+
it('should return 400 when cross-protocol parent record does not exist at runtime', async () => {
|
|
1174
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1185
1175
|
// Install both protocols
|
|
1186
|
-
const threadsConfigure =
|
|
1176
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
1187
1177
|
definition: threadsProtocol,
|
|
1188
1178
|
signer: Jws.createSigner(alice),
|
|
1189
1179
|
});
|
|
1190
|
-
|
|
1191
|
-
const commentsConfigure =
|
|
1180
|
+
await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
1181
|
+
const commentsConfigure = await ProtocolsConfigure.create({
|
|
1192
1182
|
definition: commentsProtocol,
|
|
1193
1183
|
signer: Jws.createSigner(alice),
|
|
1194
1184
|
});
|
|
1195
|
-
|
|
1185
|
+
await dwn.processMessage(alice.did, commentsConfigure.message);
|
|
1196
1186
|
// Try to create a comment under a non-existent thread (fabricate a contextId)
|
|
1197
1187
|
const fakeThreadContextId = 'bafybeifake1234567890';
|
|
1198
|
-
const commentWrite =
|
|
1188
|
+
const commentWrite = await TestDataGenerator.generateRecordsWrite({
|
|
1199
1189
|
author: alice,
|
|
1200
1190
|
protocol: commentsProtocol.protocol,
|
|
1201
1191
|
protocolPath: 'thread/comment',
|
|
@@ -1203,12 +1193,12 @@ export function testProtocolComposition() {
|
|
|
1203
1193
|
dataFormat: 'application/json',
|
|
1204
1194
|
parentContextId: fakeThreadContextId,
|
|
1205
1195
|
});
|
|
1206
|
-
const reply =
|
|
1196
|
+
const reply = await dwn.processMessage(alice.did, commentWrite.message, { dataStream: commentWrite.dataStream });
|
|
1207
1197
|
expect(reply.status.code).toBe(400);
|
|
1208
1198
|
expect(reply.status.detail).toContain(DwnErrorCode.ProtocolAuthorizationCrossProtocolParentNotFound);
|
|
1209
|
-
})
|
|
1210
|
-
it('should reject `$ref` at non-root protocol path', () =>
|
|
1211
|
-
const alice =
|
|
1199
|
+
});
|
|
1200
|
+
it('should reject `$ref` at non-root protocol path', async () => {
|
|
1201
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1212
1202
|
const badDefinition = {
|
|
1213
1203
|
protocol: 'https://bad.example.com',
|
|
1214
1204
|
published: true,
|
|
@@ -1223,7 +1213,7 @@ export function testProtocolComposition() {
|
|
|
1223
1213
|
},
|
|
1224
1214
|
};
|
|
1225
1215
|
try {
|
|
1226
|
-
|
|
1216
|
+
await ProtocolsConfigure.create({
|
|
1227
1217
|
definition: badDefinition,
|
|
1228
1218
|
signer: Jws.createSigner(alice),
|
|
1229
1219
|
});
|
|
@@ -1232,9 +1222,9 @@ export function testProtocolComposition() {
|
|
|
1232
1222
|
catch (error) {
|
|
1233
1223
|
expect(error.message).toContain(DwnErrorCode.ProtocolsConfigureInvalidRefNotAtRoot);
|
|
1234
1224
|
}
|
|
1235
|
-
})
|
|
1236
|
-
it('should reject `uses` with empty alias map', () =>
|
|
1237
|
-
const alice =
|
|
1225
|
+
});
|
|
1226
|
+
it('should reject `uses` with empty alias map', async () => {
|
|
1227
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1238
1228
|
const badDefinition = {
|
|
1239
1229
|
protocol: 'https://bad.example.com',
|
|
1240
1230
|
published: true,
|
|
@@ -1243,7 +1233,7 @@ export function testProtocolComposition() {
|
|
|
1243
1233
|
structure: {},
|
|
1244
1234
|
};
|
|
1245
1235
|
try {
|
|
1246
|
-
|
|
1236
|
+
await ProtocolsConfigure.create({
|
|
1247
1237
|
definition: badDefinition,
|
|
1248
1238
|
signer: Jws.createSigner(alice),
|
|
1249
1239
|
});
|
|
@@ -1253,13 +1243,13 @@ export function testProtocolComposition() {
|
|
|
1253
1243
|
// JSON schema enforces minProperties: 1 on `uses`
|
|
1254
1244
|
expect(error.message).toContain('must NOT have fewer than 1 properties');
|
|
1255
1245
|
}
|
|
1256
|
-
})
|
|
1246
|
+
});
|
|
1257
1247
|
});
|
|
1258
1248
|
// =========================================================================
|
|
1259
1249
|
// Temporal correctness — governing timestamp for cross-protocol lookups
|
|
1260
1250
|
// =========================================================================
|
|
1261
1251
|
describe('temporal correctness — governing timestamp', () => {
|
|
1262
|
-
it('should use the governing timestamp when fetching the referenced protocol for role verification', () =>
|
|
1252
|
+
it('should use the governing timestamp when fetching the referenced protocol for role verification', async () => {
|
|
1263
1253
|
// Scenario:
|
|
1264
1254
|
// 1. Install threads V1 (participant has $role: true)
|
|
1265
1255
|
// 2. Install comments protocol (uses threads, references threads:thread/participant role)
|
|
@@ -1267,8 +1257,8 @@ export function testProtocolComposition() {
|
|
|
1267
1257
|
// 4. Update threads to V2 where participant is no longer a role ($role removed)
|
|
1268
1258
|
// 5. Bob reads the comment using the cross-protocol role
|
|
1269
1259
|
// → should SUCCEED because the comment's governing timestamp pins to threads V1
|
|
1270
|
-
const alice =
|
|
1271
|
-
const bob =
|
|
1260
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
1261
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
1272
1262
|
// threads V1: participant is a role
|
|
1273
1263
|
const threadsV1 = {
|
|
1274
1264
|
protocol: 'https://threads-versioned.example.com',
|
|
@@ -1311,31 +1301,31 @@ export function testProtocolComposition() {
|
|
|
1311
1301
|
},
|
|
1312
1302
|
};
|
|
1313
1303
|
// Install threads V1
|
|
1314
|
-
const threadsV1Configure =
|
|
1304
|
+
const threadsV1Configure = await ProtocolsConfigure.create({
|
|
1315
1305
|
definition: threadsV1,
|
|
1316
1306
|
signer: Jws.createSigner(alice),
|
|
1317
1307
|
});
|
|
1318
|
-
const threadsV1Reply =
|
|
1308
|
+
const threadsV1Reply = await dwn.processMessage(alice.did, threadsV1Configure.message);
|
|
1319
1309
|
expect(threadsV1Reply.status.code).toBe(202);
|
|
1320
1310
|
// Install comments protocol (depends on threads)
|
|
1321
|
-
const commentsConfigure =
|
|
1311
|
+
const commentsConfigure = await ProtocolsConfigure.create({
|
|
1322
1312
|
definition: commentsVersioned,
|
|
1323
1313
|
signer: Jws.createSigner(alice),
|
|
1324
1314
|
});
|
|
1325
|
-
const commentsReply =
|
|
1315
|
+
const commentsReply = await dwn.processMessage(alice.did, commentsConfigure.message);
|
|
1326
1316
|
expect(commentsReply.status.code).toBe(202);
|
|
1327
1317
|
// Alice creates a thread
|
|
1328
|
-
const threadWrite =
|
|
1318
|
+
const threadWrite = await TestDataGenerator.generateRecordsWrite({
|
|
1329
1319
|
author: alice,
|
|
1330
1320
|
protocol: threadsV1.protocol,
|
|
1331
1321
|
protocolPath: 'thread',
|
|
1332
1322
|
schema: 'https://threads-versioned.example.com/schemas/thread',
|
|
1333
1323
|
dataFormat: 'application/json',
|
|
1334
1324
|
});
|
|
1335
|
-
|
|
1325
|
+
await dwn.processMessage(alice.did, threadWrite.message, { dataStream: threadWrite.dataStream });
|
|
1336
1326
|
const threadContextId = threadWrite.message.contextId;
|
|
1337
1327
|
// Alice assigns Bob as participant (role record in threads V1)
|
|
1338
|
-
const participantWrite =
|
|
1328
|
+
const participantWrite = await TestDataGenerator.generateRecordsWrite({
|
|
1339
1329
|
author: alice,
|
|
1340
1330
|
recipient: bob.did,
|
|
1341
1331
|
protocol: threadsV1.protocol,
|
|
@@ -1344,9 +1334,9 @@ export function testProtocolComposition() {
|
|
|
1344
1334
|
dataFormat: 'application/json',
|
|
1345
1335
|
parentContextId: threadContextId,
|
|
1346
1336
|
});
|
|
1347
|
-
|
|
1337
|
+
await dwn.processMessage(alice.did, participantWrite.message, { dataStream: participantWrite.dataStream });
|
|
1348
1338
|
// Alice creates a comment (under V1)
|
|
1349
|
-
const commentWrite =
|
|
1339
|
+
const commentWrite = await TestDataGenerator.generateRecordsWrite({
|
|
1350
1340
|
author: alice,
|
|
1351
1341
|
protocol: commentsVersioned.protocol,
|
|
1352
1342
|
protocolPath: 'thread/comment',
|
|
@@ -1354,9 +1344,9 @@ export function testProtocolComposition() {
|
|
|
1354
1344
|
dataFormat: 'application/json',
|
|
1355
1345
|
parentContextId: threadContextId,
|
|
1356
1346
|
});
|
|
1357
|
-
|
|
1347
|
+
await dwn.processMessage(alice.did, commentWrite.message, { dataStream: commentWrite.dataStream });
|
|
1358
1348
|
// Wait to ensure V2 gets a later timestamp
|
|
1359
|
-
|
|
1349
|
+
await Time.minimalSleep();
|
|
1360
1350
|
// threads V2: participant is NO LONGER a role ($role removed)
|
|
1361
1351
|
const threadsV2 = {
|
|
1362
1352
|
protocol: 'https://threads-versioned.example.com',
|
|
@@ -1378,16 +1368,16 @@ export function testProtocolComposition() {
|
|
|
1378
1368
|
},
|
|
1379
1369
|
},
|
|
1380
1370
|
};
|
|
1381
|
-
const threadsV2Configure =
|
|
1371
|
+
const threadsV2Configure = await ProtocolsConfigure.create({
|
|
1382
1372
|
definition: threadsV2,
|
|
1383
1373
|
signer: Jws.createSigner(alice),
|
|
1384
1374
|
});
|
|
1385
|
-
const threadsV2Reply =
|
|
1375
|
+
const threadsV2Reply = await dwn.processMessage(alice.did, threadsV2Configure.message);
|
|
1386
1376
|
expect(threadsV2Reply.status.code).toBe(202);
|
|
1387
1377
|
// Bob reads the comment using the cross-protocol role.
|
|
1388
1378
|
// The comment was created under V1. The governing timestamp pins the referenced protocol
|
|
1389
1379
|
// lookup to V1 where participant IS a valid role. This should SUCCEED.
|
|
1390
|
-
const bobRead =
|
|
1380
|
+
const bobRead = await RecordsRead.create({
|
|
1391
1381
|
signer: Jws.createSigner(bob),
|
|
1392
1382
|
protocolRole: 'threads:thread/participant',
|
|
1393
1383
|
filter: {
|
|
@@ -1396,9 +1386,9 @@ export function testProtocolComposition() {
|
|
|
1396
1386
|
contextId: threadContextId,
|
|
1397
1387
|
},
|
|
1398
1388
|
});
|
|
1399
|
-
const bobReadReply =
|
|
1389
|
+
const bobReadReply = await dwn.processMessage(alice.did, bobRead.message);
|
|
1400
1390
|
expect(bobReadReply.status.code).toBe(200);
|
|
1401
|
-
})
|
|
1391
|
+
});
|
|
1402
1392
|
});
|
|
1403
1393
|
// =========================================================================
|
|
1404
1394
|
// Encryption + composition tests
|
|
@@ -1406,12 +1396,12 @@ export function testProtocolComposition() {
|
|
|
1406
1396
|
describe('encryption with protocol composition', () => {
|
|
1407
1397
|
let encryptionPrivateJwk;
|
|
1408
1398
|
let encryptionRootKeyId;
|
|
1409
|
-
beforeAll(() =>
|
|
1410
|
-
const privateKey =
|
|
1399
|
+
beforeAll(async () => {
|
|
1400
|
+
const privateKey = await X25519.generateKey();
|
|
1411
1401
|
encryptionPrivateJwk = privateKey;
|
|
1412
1402
|
encryptionRootKeyId = 'did:example:alice#enc';
|
|
1413
|
-
})
|
|
1414
|
-
it('should skip `$encryption` injection on `$ref` nodes but inject on their children (raw-key path)', () =>
|
|
1403
|
+
});
|
|
1404
|
+
it('should skip `$encryption` injection on `$ref` nodes but inject on their children (raw-key path)', async () => {
|
|
1415
1405
|
const composingProtocol = {
|
|
1416
1406
|
protocol: 'https://comments.example.com',
|
|
1417
1407
|
published: true,
|
|
@@ -1432,7 +1422,7 @@ export function testProtocolComposition() {
|
|
|
1432
1422
|
},
|
|
1433
1423
|
},
|
|
1434
1424
|
};
|
|
1435
|
-
const result =
|
|
1425
|
+
const result = await Protocols.deriveAndInjectPublicEncryptionKeys(composingProtocol, encryptionRootKeyId, encryptionPrivateJwk);
|
|
1436
1426
|
// $ref node must NOT have $encryption
|
|
1437
1427
|
expect(result.structure.thread.$encryption).toBeUndefined();
|
|
1438
1428
|
// Children of $ref node MUST have $encryption
|
|
@@ -1444,8 +1434,8 @@ export function testProtocolComposition() {
|
|
|
1444
1434
|
const reactionRuleSet = commentRuleSet.reaction;
|
|
1445
1435
|
expect(reactionRuleSet.$encryption).toBeDefined();
|
|
1446
1436
|
expect(reactionRuleSet.$encryption.rootKeyId).toBe(encryptionRootKeyId);
|
|
1447
|
-
})
|
|
1448
|
-
it('should skip `$encryption` injection on `$ref` nodes but inject on their children (callback path)', () =>
|
|
1437
|
+
});
|
|
1438
|
+
it('should skip `$encryption` injection on `$ref` nodes but inject on their children (callback path)', async () => {
|
|
1449
1439
|
const composingProtocol = {
|
|
1450
1440
|
protocol: 'https://comments.example.com',
|
|
1451
1441
|
published: true,
|
|
@@ -1470,15 +1460,15 @@ export function testProtocolComposition() {
|
|
|
1470
1460
|
const keyDeriver = {
|
|
1471
1461
|
rootKeyId: encryptionRootKeyId,
|
|
1472
1462
|
derivationScheme: KeyDerivationScheme.ProtocolPath,
|
|
1473
|
-
derivePublicKey: (fullDerivationPath) =>
|
|
1463
|
+
derivePublicKey: async (fullDerivationPath) => {
|
|
1474
1464
|
calledPaths.push([...fullDerivationPath]);
|
|
1475
|
-
const privateKeyBytes =
|
|
1476
|
-
const derivedPrivateKeyBytes =
|
|
1477
|
-
const derivedPrivateKeyJwk =
|
|
1478
|
-
return
|
|
1479
|
-
}
|
|
1465
|
+
const privateKeyBytes = await X25519.privateKeyToBytes({ privateKey: encryptionPrivateJwk });
|
|
1466
|
+
const derivedPrivateKeyBytes = await HdKey.derivePrivateKeyBytes(privateKeyBytes, fullDerivationPath);
|
|
1467
|
+
const derivedPrivateKeyJwk = await X25519.bytesToPrivateKey({ privateKeyBytes: derivedPrivateKeyBytes });
|
|
1468
|
+
return await X25519.getPublicKey({ key: derivedPrivateKeyJwk });
|
|
1469
|
+
},
|
|
1480
1470
|
};
|
|
1481
|
-
const result =
|
|
1471
|
+
const result = await Protocols.deriveAndInjectPublicEncryptionKeys(composingProtocol, keyDeriver);
|
|
1482
1472
|
// $ref node must NOT have $encryption
|
|
1483
1473
|
expect(result.structure.thread.$encryption).toBeUndefined();
|
|
1484
1474
|
// Children of $ref node MUST have $encryption
|
|
@@ -1493,8 +1483,8 @@ export function testProtocolComposition() {
|
|
|
1493
1483
|
const reactionPath = [KeyDerivationScheme.ProtocolPath, 'https://comments.example.com', 'thread', 'comment', 'reaction'];
|
|
1494
1484
|
expect(calledPaths).toContainEqual(commentPath);
|
|
1495
1485
|
expect(calledPaths).toContainEqual(reactionPath);
|
|
1496
|
-
})
|
|
1497
|
-
it('should produce identical $encryption for children across both overloads', () =>
|
|
1486
|
+
});
|
|
1487
|
+
it('should produce identical $encryption for children across both overloads', async () => {
|
|
1498
1488
|
const composingProtocol = {
|
|
1499
1489
|
protocol: 'https://comments.example.com',
|
|
1500
1490
|
published: true,
|
|
@@ -1510,19 +1500,19 @@ export function testProtocolComposition() {
|
|
|
1510
1500
|
},
|
|
1511
1501
|
};
|
|
1512
1502
|
// Raw-key path
|
|
1513
|
-
const resultA =
|
|
1503
|
+
const resultA = await Protocols.deriveAndInjectPublicEncryptionKeys(composingProtocol, encryptionRootKeyId, encryptionPrivateJwk);
|
|
1514
1504
|
// Callback path
|
|
1515
1505
|
const keyDeriver = {
|
|
1516
1506
|
rootKeyId: encryptionRootKeyId,
|
|
1517
1507
|
derivationScheme: KeyDerivationScheme.ProtocolPath,
|
|
1518
|
-
derivePublicKey: (fullDerivationPath) =>
|
|
1519
|
-
const privateKeyBytes =
|
|
1520
|
-
const derivedPrivateKeyBytes =
|
|
1521
|
-
const derivedPrivateKeyJwk =
|
|
1522
|
-
return
|
|
1523
|
-
}
|
|
1508
|
+
derivePublicKey: async (fullDerivationPath) => {
|
|
1509
|
+
const privateKeyBytes = await X25519.privateKeyToBytes({ privateKey: encryptionPrivateJwk });
|
|
1510
|
+
const derivedPrivateKeyBytes = await HdKey.derivePrivateKeyBytes(privateKeyBytes, fullDerivationPath);
|
|
1511
|
+
const derivedPrivateKeyJwk = await X25519.bytesToPrivateKey({ privateKeyBytes: derivedPrivateKeyBytes });
|
|
1512
|
+
return await X25519.getPublicKey({ key: derivedPrivateKeyJwk });
|
|
1513
|
+
},
|
|
1524
1514
|
};
|
|
1525
|
-
const resultB =
|
|
1515
|
+
const resultB = await Protocols.deriveAndInjectPublicEncryptionKeys(composingProtocol, keyDeriver);
|
|
1526
1516
|
// Both paths must skip $ref
|
|
1527
1517
|
expect(resultA.structure.thread.$encryption).toBeUndefined();
|
|
1528
1518
|
expect(resultB.structure.thread.$encryption).toBeUndefined();
|
|
@@ -1531,69 +1521,69 @@ export function testProtocolComposition() {
|
|
|
1531
1521
|
const commentB = resultB.structure.thread.comment;
|
|
1532
1522
|
expect(commentA.$encryption.publicKeyJwk).toEqual(commentB.$encryption.publicKeyJwk);
|
|
1533
1523
|
expect(commentA.$encryption.rootKeyId).toBe(commentB.$encryption.rootKeyId);
|
|
1534
|
-
})
|
|
1535
|
-
it('should successfully install a composing protocol with encryption after $ref skip', () =>
|
|
1524
|
+
});
|
|
1525
|
+
it('should successfully install a composing protocol with encryption after $ref skip', async () => {
|
|
1536
1526
|
// This test verifies the full pipeline: inject encryption keys → ProtocolsConfigure.create()
|
|
1537
1527
|
// → validateRefNode() passes because $ref node has no $encryption.
|
|
1538
|
-
const alice =
|
|
1528
|
+
const alice = await TestDataGenerator.generatePersona();
|
|
1539
1529
|
TestStubGenerator.stubDidResolver(didResolver, [alice]);
|
|
1540
1530
|
// Install the threads protocol first (required dependency)
|
|
1541
|
-
const threadsConfigure =
|
|
1531
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
1542
1532
|
definition: threadsProtocol,
|
|
1543
1533
|
signer: Jws.createSigner(alice),
|
|
1544
1534
|
});
|
|
1545
|
-
const threadsInstallReply =
|
|
1535
|
+
const threadsInstallReply = await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
1546
1536
|
expect(threadsInstallReply.status.code).toBe(202);
|
|
1547
1537
|
// Inject encryption keys into the composing protocol
|
|
1548
|
-
const encryptedComments =
|
|
1538
|
+
const encryptedComments = await Protocols.deriveAndInjectPublicEncryptionKeys(commentsProtocol, alice.keyId, alice.encryptionKeyPair.privateJwk);
|
|
1549
1539
|
// $ref node should not have $encryption
|
|
1550
1540
|
expect(encryptedComments.structure.thread.$encryption).toBeUndefined();
|
|
1551
1541
|
// Children should have $encryption
|
|
1552
1542
|
expect(encryptedComments.structure.thread.comment.$encryption).toBeDefined();
|
|
1553
1543
|
// ProtocolsConfigure.create() should NOT throw — validateRefNode() will pass
|
|
1554
1544
|
// because $ref node has no forbidden directives
|
|
1555
|
-
const commentsConfigure =
|
|
1545
|
+
const commentsConfigure = await ProtocolsConfigure.create({
|
|
1556
1546
|
definition: encryptedComments,
|
|
1557
1547
|
signer: Jws.createSigner(alice),
|
|
1558
1548
|
});
|
|
1559
1549
|
// Install should succeed
|
|
1560
|
-
const commentsInstallReply =
|
|
1550
|
+
const commentsInstallReply = await dwn.processMessage(alice.did, commentsConfigure.message);
|
|
1561
1551
|
expect(commentsInstallReply.status.code).toBe(202);
|
|
1562
|
-
})
|
|
1563
|
-
it('should encrypt and decrypt a child record written under a `$ref` parent', () =>
|
|
1552
|
+
});
|
|
1553
|
+
it('should encrypt and decrypt a child record written under a `$ref` parent', async () => {
|
|
1564
1554
|
// Full round-trip: install both protocols → write parent → write encrypted child → read and decrypt
|
|
1565
|
-
const alice =
|
|
1555
|
+
const alice = await TestDataGenerator.generatePersona();
|
|
1566
1556
|
TestStubGenerator.stubDidResolver(didResolver, [alice]);
|
|
1567
1557
|
// 1. Install the threads protocol (parent)
|
|
1568
|
-
const threadsConfigure =
|
|
1558
|
+
const threadsConfigure = await ProtocolsConfigure.create({
|
|
1569
1559
|
definition: threadsProtocol,
|
|
1570
1560
|
signer: Jws.createSigner(alice),
|
|
1571
1561
|
});
|
|
1572
|
-
const threadsReply =
|
|
1562
|
+
const threadsReply = await dwn.processMessage(alice.did, threadsConfigure.message);
|
|
1573
1563
|
expect(threadsReply.status.code).toBe(202);
|
|
1574
1564
|
// 2. Install the comments protocol with encryption keys
|
|
1575
|
-
const encryptedComments =
|
|
1576
|
-
const commentsConfigure =
|
|
1565
|
+
const encryptedComments = await Protocols.deriveAndInjectPublicEncryptionKeys(commentsProtocol, alice.keyId, alice.encryptionKeyPair.privateJwk);
|
|
1566
|
+
const commentsConfigure = await ProtocolsConfigure.create({
|
|
1577
1567
|
definition: encryptedComments,
|
|
1578
1568
|
signer: Jws.createSigner(alice),
|
|
1579
1569
|
});
|
|
1580
|
-
const commentsReply =
|
|
1570
|
+
const commentsReply = await dwn.processMessage(alice.did, commentsConfigure.message);
|
|
1581
1571
|
expect(commentsReply.status.code).toBe(202);
|
|
1582
1572
|
// 3. Write a thread record (in the threads protocol — the $ref parent)
|
|
1583
|
-
const threadWrite =
|
|
1573
|
+
const threadWrite = await TestDataGenerator.generateRecordsWrite({
|
|
1584
1574
|
author: alice,
|
|
1585
1575
|
protocol: threadsProtocol.protocol,
|
|
1586
1576
|
protocolPath: 'thread',
|
|
1587
1577
|
schema: 'https://threads.example.com/schemas/thread',
|
|
1588
1578
|
dataFormat: 'application/json',
|
|
1589
1579
|
});
|
|
1590
|
-
const threadWriteReply =
|
|
1580
|
+
const threadWriteReply = await dwn.processMessage(alice.did, threadWrite.message, { dataStream: threadWrite.dataStream });
|
|
1591
1581
|
expect(threadWriteReply.status.code).toBe(202);
|
|
1592
1582
|
const threadContextId = threadWrite.message.contextId;
|
|
1593
1583
|
// 4. Write an encrypted comment (child of $ref parent, in the comments protocol)
|
|
1594
1584
|
const plaintext = 'This is a secret comment';
|
|
1595
1585
|
const plaintextBytes = Encoder.stringToBytes(plaintext);
|
|
1596
|
-
const encryptedComment =
|
|
1586
|
+
const encryptedComment = await TestDataGenerator.generateProtocolEncryptedRecordsWrite({
|
|
1597
1587
|
plaintextBytes,
|
|
1598
1588
|
author: alice,
|
|
1599
1589
|
protocolDefinition: encryptedComments,
|
|
@@ -1602,14 +1592,14 @@ export function testProtocolComposition() {
|
|
|
1602
1592
|
encryptSymmetricKeyWithProtocolPathDerivedKey: true,
|
|
1603
1593
|
encryptSymmetricKeyWithProtocolContextDerivedKey: false,
|
|
1604
1594
|
});
|
|
1605
|
-
const commentWriteReply =
|
|
1595
|
+
const commentWriteReply = await dwn.processMessage(alice.did, encryptedComment.message, { dataStream: DataStream.fromBytes(encryptedComment.encryptedDataBytes) });
|
|
1606
1596
|
expect(commentWriteReply.status.code).toBe(202);
|
|
1607
1597
|
// 5. Read the encrypted comment back
|
|
1608
|
-
const readMessage =
|
|
1598
|
+
const readMessage = await RecordsRead.create({
|
|
1609
1599
|
signer: Jws.createSigner(alice),
|
|
1610
1600
|
filter: { recordId: encryptedComment.message.recordId },
|
|
1611
1601
|
});
|
|
1612
|
-
const readReply =
|
|
1602
|
+
const readReply = await dwn.processMessage(alice.did, readMessage.message);
|
|
1613
1603
|
expect(readReply.status.code).toBe(200);
|
|
1614
1604
|
// 6. Decrypt using the composing protocol's key hierarchy.
|
|
1615
1605
|
// The key derivation path is [protocolPath, commentsProtocol.protocol, 'thread', 'comment']
|
|
@@ -1620,11 +1610,11 @@ export function testProtocolComposition() {
|
|
|
1620
1610
|
derivationScheme: KeyDerivationScheme.ProtocolPath,
|
|
1621
1611
|
derivedPrivateKey: alice.encryptionKeyPair.privateJwk,
|
|
1622
1612
|
};
|
|
1623
|
-
const decryptedStream =
|
|
1624
|
-
const decryptedBytes =
|
|
1613
|
+
const decryptedStream = await Records.decrypt(readReply.entry.recordsWrite, rootKey, readReply.entry.data);
|
|
1614
|
+
const decryptedBytes = await DataStream.toBytes(decryptedStream);
|
|
1625
1615
|
expect(Encoder.bytesToString(decryptedBytes)).toBe(plaintext);
|
|
1626
|
-
})
|
|
1627
|
-
it('should not inject `$encryption` on the original protocol definition (immutability)', () =>
|
|
1616
|
+
});
|
|
1617
|
+
it('should not inject `$encryption` on the original protocol definition (immutability)', async () => {
|
|
1628
1618
|
const composingProtocol = {
|
|
1629
1619
|
protocol: 'https://comments.example.com',
|
|
1630
1620
|
published: true,
|
|
@@ -1639,11 +1629,11 @@ export function testProtocolComposition() {
|
|
|
1639
1629
|
},
|
|
1640
1630
|
},
|
|
1641
1631
|
};
|
|
1642
|
-
|
|
1632
|
+
await Protocols.deriveAndInjectPublicEncryptionKeys(composingProtocol, encryptionRootKeyId, encryptionPrivateJwk);
|
|
1643
1633
|
// Original must be unmodified
|
|
1644
1634
|
expect(composingProtocol.structure.thread.$encryption).toBeUndefined();
|
|
1645
1635
|
expect(composingProtocol.structure.thread.comment.$encryption).toBeUndefined();
|
|
1646
|
-
})
|
|
1636
|
+
});
|
|
1647
1637
|
});
|
|
1648
1638
|
});
|
|
1649
1639
|
}
|