@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
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { Filter } from '../types/query-types.js';
|
|
2
|
+
import type { MessageStore } from '../types/message-store.js';
|
|
3
|
+
import type { RecordsWriteMessage } from '../types/records-types.js';
|
|
4
|
+
|
|
5
|
+
import { RecordsWrite } from '../interfaces/records-write.js';
|
|
6
|
+
import { DwnError, DwnErrorCode } from './dwn-error.js';
|
|
7
|
+
import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Fetches the initial RecordsWrite message associated with the given (tenant + recordId).
|
|
11
|
+
*/
|
|
12
|
+
export async function fetchInitialWrite(
|
|
13
|
+
tenant: string,
|
|
14
|
+
recordId: string,
|
|
15
|
+
messageStore: MessageStore
|
|
16
|
+
): Promise<RecordsWriteMessage | undefined> {
|
|
17
|
+
|
|
18
|
+
const query: Filter = {
|
|
19
|
+
interface : DwnInterfaceName.Records,
|
|
20
|
+
method : DwnMethodName.Write,
|
|
21
|
+
recordId : recordId
|
|
22
|
+
};
|
|
23
|
+
const { messages } = await messageStore.query(tenant, [query]);
|
|
24
|
+
|
|
25
|
+
if (messages.length === 0) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const initialWrite = await RecordsWrite.getInitialWrite(messages);
|
|
30
|
+
return initialWrite;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Constructs the chain of EXISTING records in the datastore where the first record is the root initial `RecordsWrite` of the record chain
|
|
35
|
+
* and last record is the initial `RecordsWrite` of the descendant record specified.
|
|
36
|
+
* @param descendantRecordId The ID of the descendent record to start constructing the record chain from by repeatedly looking up the parent.
|
|
37
|
+
* @returns the record chain where each record is represented by its initial `RecordsWrite`;
|
|
38
|
+
* returns empty array if `descendantRecordId` is `undefined`.
|
|
39
|
+
* @throws {DwnError} if `descendantRecordId` is defined but any initial `RecordsWrite` is not found in the chain of records.
|
|
40
|
+
*/
|
|
41
|
+
export async function constructRecordChain(
|
|
42
|
+
tenant: string,
|
|
43
|
+
descendantRecordId: string | undefined,
|
|
44
|
+
messageStore: MessageStore
|
|
45
|
+
): Promise<RecordsWriteMessage[]> {
|
|
46
|
+
|
|
47
|
+
if (descendantRecordId === undefined) {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const recordChain: RecordsWriteMessage[] = [];
|
|
52
|
+
|
|
53
|
+
// keep walking up the chain from the inbound message's parent, until there is no more parent
|
|
54
|
+
let currentRecordId: string | undefined = descendantRecordId;
|
|
55
|
+
while (currentRecordId !== undefined) {
|
|
56
|
+
|
|
57
|
+
const initialWrite = await fetchInitialWrite(tenant, currentRecordId, messageStore);
|
|
58
|
+
|
|
59
|
+
// RecordsWrite needed should be available since we perform necessary checks at the time of writes,
|
|
60
|
+
// eg. check the immediate parent in `verifyProtocolPathAndContextId` at the time of writing,
|
|
61
|
+
// so if this condition is triggered, it means there is an unexpected bug that caused an incomplete chain.
|
|
62
|
+
// We add additional defensive check here because returning an unexpected/incorrect record chain could lead to security vulnerabilities.
|
|
63
|
+
if (initialWrite === undefined) {
|
|
64
|
+
throw new DwnError(
|
|
65
|
+
DwnErrorCode.ProtocolAuthorizationParentNotFoundConstructingRecordChain,
|
|
66
|
+
`Unexpected error that should never trigger: no parent found with ID ${currentRecordId} when constructing record chain.`
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
recordChain.push(initialWrite);
|
|
71
|
+
currentRecordId = initialWrite.descriptor.parentId;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return recordChain.reverse(); // root record first
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Determines the timestamp that governs which protocol definition version applies to the given RecordsWrite.
|
|
79
|
+
* For an update, this is the initial write's `messageTimestamp` (the protocol version is locked at creation time).
|
|
80
|
+
* For a new initial write, returns `undefined` — the latest protocol definition should be used because the
|
|
81
|
+
* record is being created now and must conform to the current protocol rules.
|
|
82
|
+
*/
|
|
83
|
+
export async function getGoverningTimestamp(
|
|
84
|
+
tenant: string,
|
|
85
|
+
incomingMessage: RecordsWrite,
|
|
86
|
+
messageStore: MessageStore,
|
|
87
|
+
): Promise<string | undefined> {
|
|
88
|
+
const existingInitialWrite = await fetchInitialWrite(
|
|
89
|
+
tenant, incomingMessage.message.recordId, messageStore
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
if (existingInitialWrite !== undefined) {
|
|
93
|
+
// update case: use the initial write's timestamp
|
|
94
|
+
return existingInitialWrite.descriptor.messageTimestamp;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// initial write case: validate against the latest protocol definition
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
@@ -62,7 +62,7 @@ export class RecordsReadHandler implements MethodHandler {
|
|
|
62
62
|
const matchedMessage = existingMessages[0];
|
|
63
63
|
|
|
64
64
|
// if the matched message is a RecordsDelete, we mark the record as not-found and return both the RecordsDelete and the initial RecordsWrite
|
|
65
|
-
// TODO: https://github.com/enboxorg/enbox/issues/
|
|
65
|
+
// TODO: https://github.com/enboxorg/enbox/issues/222
|
|
66
66
|
// Consider performing authorization checks like when records exists before returning RecordsDelete and initial RecordsWrite of a deleted record
|
|
67
67
|
if (matchedMessage.descriptor.method === DwnMethodName.Delete) {
|
|
68
68
|
const recordsDeleteMessage = matchedMessage as RecordsDeleteMessage;
|
|
@@ -215,31 +215,47 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
215
215
|
|
|
216
216
|
/**
|
|
217
217
|
* Performs additional necessary tasks if the RecordsWrite handled is a core DWN RecordsWrite that need additional processing.
|
|
218
|
-
* For instance: a Permission revocation
|
|
218
|
+
* For instance: when a Permission revocation is written, all messages authorized by the revoked grant
|
|
219
|
+
* that were created after the revocation timestamp are deleted from all stores.
|
|
219
220
|
*/
|
|
220
221
|
private async postProcessingForCoreRecordsWrite(tenant: string, recordsWrite: RecordsWrite): Promise<void> {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
//
|
|
227
|
-
//
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
222
|
+
if (recordsWrite.message.descriptor.protocol !== PermissionsProtocol.uri ||
|
|
223
|
+
recordsWrite.message.descriptor.protocolPath !== PermissionsProtocol.revocationPath) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Delete all messages authorized by the revoked grant that were created after the revocation.
|
|
228
|
+
// `permissionGrantId` is indexed via the RecordsWriteDescriptor spread in constructIndexes().
|
|
229
|
+
const permissionGrantId = recordsWrite.message.descriptor.parentId!;
|
|
230
|
+
const grantAuthorizedMessagesQuery = {
|
|
231
|
+
permissionGrantId,
|
|
232
|
+
dateCreated: { gte: recordsWrite.message.descriptor.messageTimestamp },
|
|
233
|
+
};
|
|
234
|
+
const { messages: grantAuthorizedMessages } = await this.messageStore.query(tenant, [grantAuthorizedMessagesQuery]);
|
|
235
|
+
|
|
236
|
+
if (grantAuthorizedMessages.length === 0) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Delete data from the data store first to avoid orphaned data blobs in case of crash.
|
|
241
|
+
// Only RecordsWrite messages with data larger than maxDataSizeAllowedToBeEncoded have data in the data store.
|
|
242
|
+
for (const message of grantAuthorizedMessages) {
|
|
243
|
+
if (message.descriptor.method === DwnMethodName.Write) {
|
|
244
|
+
const recordsWriteMessage = message as RecordsWriteMessage;
|
|
245
|
+
if (recordsWriteMessage.descriptor.dataSize > DwnConstant.maxDataSizeAllowedToBeEncoded) {
|
|
246
|
+
await this.dataStore.delete(tenant, recordsWriteMessage.recordId, recordsWriteMessage.descriptor.dataCid);
|
|
247
|
+
}
|
|
240
248
|
}
|
|
241
|
-
this.stateIndex.delete(tenant, grantAuthorizedMessageCidsAfterRevoke);
|
|
242
249
|
}
|
|
250
|
+
|
|
251
|
+
// Compute CIDs for all messages to delete.
|
|
252
|
+
const messageCids = await Promise.all(grantAuthorizedMessages.map((message): Promise<string> => Message.getCid(message)));
|
|
253
|
+
|
|
254
|
+
// Delete from state index before message store so we don't have orphaned state entries.
|
|
255
|
+
await this.stateIndex.delete(tenant, messageCids);
|
|
256
|
+
|
|
257
|
+
// Finally delete all messages from the message store.
|
|
258
|
+
await Promise.all(messageCids.map((cid): Promise<void> => this.messageStore.delete(tenant, cid)));
|
|
243
259
|
}
|
|
244
260
|
|
|
245
261
|
/**
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { DataEncodedRecordsWriteMessage } from '../types/records-types.js';
|
|
2
2
|
import type { MessageSigner } from '../types/signer.js';
|
|
3
3
|
import type { MessageStore } from '../types/message-store.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
ProtocolActionRule, ProtocolDefinition, ProtocolRuleSet, ProtocolsConfigureDescriptor,
|
|
6
|
+
ProtocolsConfigureMessage, ProtocolTypes, ProtocolUses
|
|
7
|
+
} from '../types/protocols-types.js';
|
|
5
8
|
|
|
6
9
|
import { AbstractMessage } from '../core/abstract-message.js';
|
|
7
10
|
import Ajv from 'ajv/dist/2020.js';
|
|
@@ -151,7 +154,8 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
151
154
|
ruleSetProtocolPath : '',
|
|
152
155
|
recordTypes,
|
|
153
156
|
roles,
|
|
154
|
-
uses
|
|
157
|
+
uses,
|
|
158
|
+
types : definition.types,
|
|
155
159
|
});
|
|
156
160
|
}
|
|
157
161
|
|
|
@@ -196,9 +200,12 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
196
200
|
* Validates the given rule set structure then recursively validates its nested child rule sets.
|
|
197
201
|
*/
|
|
198
202
|
private static validateRuleSetRecursively(
|
|
199
|
-
input: {
|
|
203
|
+
input: {
|
|
204
|
+
ruleSet: ProtocolRuleSet, ruleSetProtocolPath: string, recordTypes: string[],
|
|
205
|
+
roles: string[], uses?: ProtocolUses, types: ProtocolTypes
|
|
206
|
+
}
|
|
200
207
|
): void {
|
|
201
|
-
const { ruleSet, ruleSetProtocolPath, recordTypes, roles, uses } = input;
|
|
208
|
+
const { ruleSet, ruleSetProtocolPath, recordTypes, roles, uses, types } = input;
|
|
202
209
|
|
|
203
210
|
// Validate $ref constraints: $ref is only supported at root level (no `/` in protocol path),
|
|
204
211
|
// and a $ref node is a pure attachment point with no other directives.
|
|
@@ -370,6 +377,26 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
370
377
|
}
|
|
371
378
|
}
|
|
372
379
|
|
|
380
|
+
// Warn when `encryptionRequired: true` is combined with `{ who: 'anyone', can: ['read'] }`.
|
|
381
|
+
// Authorization allows anyone to read the record, but encryption prevents them from
|
|
382
|
+
// decrypting the data — almost certainly unintentional. (issue #115)
|
|
383
|
+
if (ruleSetProtocolPath !== '') {
|
|
384
|
+
const typeName = ruleSetProtocolPath.split('/').pop()!;
|
|
385
|
+
const protocolType = types[typeName];
|
|
386
|
+
if (protocolType?.encryptionRequired === true) {
|
|
387
|
+
const anyoneCanRead = actionRules.some(
|
|
388
|
+
(rule: ProtocolActionRule): boolean => rule.who === ProtocolActor.Anyone && rule.can.includes(ProtocolAction.Read)
|
|
389
|
+
);
|
|
390
|
+
if (anyoneCanRead) {
|
|
391
|
+
console.warn(
|
|
392
|
+
`ProtocolsConfigure: type '${typeName}' at path '${ruleSetProtocolPath}' has ` +
|
|
393
|
+
`encryptionRequired: true but allows { who: 'anyone', can: ['read'] }. ` +
|
|
394
|
+
`Anyone can read the record but no one outside the key holders can decrypt it.`
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
373
400
|
// Validate nested rule sets
|
|
374
401
|
for (const recordType in ruleSet) {
|
|
375
402
|
if (recordType.startsWith('$')) {
|
|
@@ -399,7 +426,8 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
399
426
|
ruleSetProtocolPath : childRuleSetProtocolPath,
|
|
400
427
|
recordTypes,
|
|
401
428
|
roles,
|
|
402
|
-
uses
|
|
429
|
+
uses,
|
|
430
|
+
types,
|
|
403
431
|
});
|
|
404
432
|
}
|
|
405
433
|
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { GenericMessage } from '../types/message-types.js';
|
|
2
|
+
import type { MessageStore } from '../types/message-store.js';
|
|
3
|
+
import type { RecordsWrite } from './records-write.js';
|
|
4
|
+
import type { InternalRecordsWriteMessage, RecordsWriteMessage } from '../types/records-types.js';
|
|
5
|
+
|
|
6
|
+
import { Jws } from '../utils/jws.js';
|
|
7
|
+
import { Message } from '../core/message.js';
|
|
8
|
+
import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
|
|
9
|
+
import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
|
|
10
|
+
|
|
11
|
+
// Late-bound import to avoid circular dependency at module-evaluation time.
|
|
12
|
+
// `RecordsWrite` imports this module; this module needs `RecordsWrite.isInitialWrite` and `.parse`.
|
|
13
|
+
let _RecordsWriteClass: typeof RecordsWrite;
|
|
14
|
+
async function getRecordsWrite(): Promise<typeof RecordsWrite> {
|
|
15
|
+
if (!_RecordsWriteClass) {
|
|
16
|
+
const mod = await import('./records-write.js');
|
|
17
|
+
_RecordsWriteClass = mod.RecordsWrite;
|
|
18
|
+
}
|
|
19
|
+
return _RecordsWriteClass;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Gets the initial write from the given list of messages.
|
|
24
|
+
*/
|
|
25
|
+
export async function getInitialWrite(messages: GenericMessage[]): Promise<RecordsWriteMessage> {
|
|
26
|
+
const RW = await getRecordsWrite();
|
|
27
|
+
for (const message of messages) {
|
|
28
|
+
if (await RW.isInitialWrite(message)) {
|
|
29
|
+
return message as RecordsWriteMessage;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
throw new DwnError(DwnErrorCode.RecordsWriteGetInitialWriteNotFound, `Initial write is not found.`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Verifies that immutable properties of the two given messages are identical.
|
|
38
|
+
* @throws {DwnError} if immutable properties between two RecordsWrite messages differ.
|
|
39
|
+
*/
|
|
40
|
+
export function verifyEqualityOfImmutableProperties(
|
|
41
|
+
existingWriteMessage: RecordsWriteMessage, newMessage: RecordsWriteMessage
|
|
42
|
+
): boolean {
|
|
43
|
+
const mutableDescriptorProperties = ['dataCid', 'dataSize', 'dataFormat', 'datePublished', 'published', 'messageTimestamp', 'tags'];
|
|
44
|
+
|
|
45
|
+
// get distinct property names that exist in either the existing message given or new message
|
|
46
|
+
let descriptorPropertyNames: string[] = [];
|
|
47
|
+
descriptorPropertyNames.push(...Object.keys(existingWriteMessage.descriptor));
|
|
48
|
+
descriptorPropertyNames.push(...Object.keys(newMessage.descriptor));
|
|
49
|
+
descriptorPropertyNames = [...new Set(descriptorPropertyNames)]; // step to remove duplicates
|
|
50
|
+
|
|
51
|
+
// ensure all immutable properties are not modified
|
|
52
|
+
for (const descriptorPropertyName of descriptorPropertyNames) {
|
|
53
|
+
// if property is supposed to be immutable
|
|
54
|
+
if (mutableDescriptorProperties.indexOf(descriptorPropertyName) === -1) {
|
|
55
|
+
const valueInExistingWrite = (existingWriteMessage.descriptor as Record<string, unknown>)[descriptorPropertyName];
|
|
56
|
+
const valueInNewMessage = (newMessage.descriptor as Record<string, unknown>)[descriptorPropertyName];
|
|
57
|
+
if (valueInNewMessage !== valueInExistingWrite) {
|
|
58
|
+
throw new DwnError(
|
|
59
|
+
DwnErrorCode.RecordsWriteImmutablePropertyChanged,
|
|
60
|
+
`${descriptorPropertyName} is an immutable property: cannot change '${valueInExistingWrite}' to '${valueInNewMessage}'`
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Gets the DID of the attesters of the given message.
|
|
71
|
+
*/
|
|
72
|
+
export function getAttesters(message: InternalRecordsWriteMessage): string[] {
|
|
73
|
+
const attestationSignatures = message.attestation?.signatures ?? [];
|
|
74
|
+
const attesters = attestationSignatures.map((signature): string => Jws.getSignerDid(signature));
|
|
75
|
+
return attesters;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Fetches the newest RecordsWrite for a given recordId from the message store.
|
|
80
|
+
* @throws {DwnError} if no write is found.
|
|
81
|
+
*/
|
|
82
|
+
export async function fetchNewestRecordsWrite(
|
|
83
|
+
messageStore: MessageStore,
|
|
84
|
+
tenant: string,
|
|
85
|
+
recordId: string,
|
|
86
|
+
): Promise<RecordsWriteMessage> {
|
|
87
|
+
// get existing RecordsWrite messages matching the `recordId`
|
|
88
|
+
const query = {
|
|
89
|
+
interface : DwnInterfaceName.Records,
|
|
90
|
+
method : DwnMethodName.Write,
|
|
91
|
+
recordId : recordId
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const { messages: existingMessages } = await messageStore.query(tenant, [ query ]);
|
|
95
|
+
const newestWrite = await Message.getNewestMessage(existingMessages);
|
|
96
|
+
if (newestWrite !== undefined) {
|
|
97
|
+
return newestWrite as RecordsWriteMessage;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
throw new DwnError(DwnErrorCode.RecordsWriteGetNewestWriteRecordNotFound, 'record not found');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Fetches the initial RecordsWrite of a record.
|
|
105
|
+
* @returns The initial RecordsWrite if found; `undefined` otherwise.
|
|
106
|
+
*/
|
|
107
|
+
export async function fetchInitialRecordsWrite(
|
|
108
|
+
messageStore: MessageStore,
|
|
109
|
+
tenant: string,
|
|
110
|
+
recordId: string
|
|
111
|
+
): Promise<RecordsWrite | undefined> {
|
|
112
|
+
const initialRecordsWriteMessage = await fetchInitialRecordsWriteMessage(messageStore, tenant, recordId);
|
|
113
|
+
if (initialRecordsWriteMessage === undefined) {
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const RW = await getRecordsWrite();
|
|
118
|
+
const initialRecordsWrite = await RW.parse(initialRecordsWriteMessage);
|
|
119
|
+
return initialRecordsWrite;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Fetches the initial RecordsWrite message of a record.
|
|
124
|
+
* @returns The initial RecordsWriteMessage if found; `undefined` otherwise.
|
|
125
|
+
*/
|
|
126
|
+
export async function fetchInitialRecordsWriteMessage(
|
|
127
|
+
messageStore: MessageStore,
|
|
128
|
+
tenant: string,
|
|
129
|
+
recordId: string
|
|
130
|
+
): Promise<RecordsWriteMessage | undefined> {
|
|
131
|
+
const query = { entryId: recordId };
|
|
132
|
+
const { messages } = await messageStore.query(tenant, [query]);
|
|
133
|
+
|
|
134
|
+
if (messages.length === 0) {
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return messages[0] as RecordsWriteMessage;
|
|
139
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type { GeneralJws } from '../types/jws-types.js';
|
|
2
|
+
import type { MessageSigner } from '../types/signer.js';
|
|
3
|
+
import type { EncryptionInput, JweEncryption } from '../utils/encryption.js';
|
|
4
|
+
import type { RecordsWriteAttestationPayload, RecordsWriteDescriptor, RecordsWriteMessage, RecordsWriteSignaturePayload } from '../types/records-types.js';
|
|
5
|
+
|
|
6
|
+
import { Cid } from '../utils/cid.js';
|
|
7
|
+
import { Encoder } from '../utils/encoder.js';
|
|
8
|
+
import { Encryption } from '../utils/encryption.js';
|
|
9
|
+
import { GeneralJwsBuilder } from '../jose/jws/general/builder.js';
|
|
10
|
+
import { Jws } from '../utils/jws.js';
|
|
11
|
+
import { KeyDerivationScheme } from '../utils/hd-key.js';
|
|
12
|
+
import { removeUndefinedProperties } from '../utils/object.js';
|
|
13
|
+
import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates the JWE `encryption` property if encryption input is given. Else `undefined` is returned.
|
|
17
|
+
* Uses ECDH-ES+A256KW key agreement with X25519 and AEAD content encryption (A256GCM or XC20P).
|
|
18
|
+
* @param descriptor Descriptor of the `RecordsWrite` message which contains the information needed by key path derivation schemes.
|
|
19
|
+
* @param encryptionInput The encryption input containing CEK, IV, authentication tag, and recipient key encryption inputs.
|
|
20
|
+
*/
|
|
21
|
+
export async function createEncryptionProperty(
|
|
22
|
+
descriptor: RecordsWriteDescriptor,
|
|
23
|
+
encryptionInput: EncryptionInput | undefined,
|
|
24
|
+
): Promise<JweEncryption | undefined> {
|
|
25
|
+
if (encryptionInput === undefined) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Validate derivation scheme prerequisites
|
|
30
|
+
for (const keyEncryptionInput of encryptionInput.keyEncryptionInputs) {
|
|
31
|
+
if (keyEncryptionInput.derivationScheme === KeyDerivationScheme.ProtocolPath && descriptor.protocol === undefined) {
|
|
32
|
+
throw new DwnError(
|
|
33
|
+
DwnErrorCode.RecordsWriteMissingProtocol,
|
|
34
|
+
'`protocols` encryption scheme cannot be applied to record without the `protocol` property.'
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (keyEncryptionInput.derivationScheme === KeyDerivationScheme.Schemas && descriptor.schema === undefined) {
|
|
39
|
+
throw new DwnError(
|
|
40
|
+
DwnErrorCode.RecordsWriteMissingSchema,
|
|
41
|
+
'`schemas` encryption scheme cannot be applied to record without the `schema` property.'
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Build the JWE structure. The authentication tag comes from the AEAD encryption of record data.
|
|
47
|
+
const jwe = await Encryption.buildJwe(encryptionInput, encryptionInput.authenticationTag);
|
|
48
|
+
|
|
49
|
+
return jwe;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Creates the `attestation` property of a RecordsWrite message if given signature inputs; returns `undefined` otherwise.
|
|
54
|
+
*/
|
|
55
|
+
export async function createAttestation(descriptorCid: string, signers?: MessageSigner[]): Promise<GeneralJws | undefined> {
|
|
56
|
+
if (signers === undefined || signers.length === 0) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const attestationPayload: RecordsWriteAttestationPayload = { descriptorCid };
|
|
61
|
+
const attestationPayloadBytes = Encoder.objectToBytes(attestationPayload);
|
|
62
|
+
|
|
63
|
+
const builder = await GeneralJwsBuilder.create(attestationPayloadBytes, signers);
|
|
64
|
+
return builder.getJws();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Creates the `signature` property in the `authorization` of a `RecordsWrite` message.
|
|
69
|
+
*/
|
|
70
|
+
export async function createSignerSignature(input: {
|
|
71
|
+
recordId: string,
|
|
72
|
+
contextId: string | undefined,
|
|
73
|
+
descriptorCid: string,
|
|
74
|
+
attestation: GeneralJws | undefined,
|
|
75
|
+
encryption: JweEncryption | undefined,
|
|
76
|
+
signer: MessageSigner,
|
|
77
|
+
delegatedGrantId?: string,
|
|
78
|
+
permissionGrantId?: string,
|
|
79
|
+
protocolRole?: string
|
|
80
|
+
}): Promise<GeneralJws> {
|
|
81
|
+
const { recordId, contextId, descriptorCid, attestation, encryption, signer, delegatedGrantId, permissionGrantId, protocolRole } = input;
|
|
82
|
+
|
|
83
|
+
const attestationCid = attestation ? await Cid.computeCid(attestation) : undefined;
|
|
84
|
+
const encryptionCid = encryption ? await Cid.computeCid(encryption) : undefined;
|
|
85
|
+
|
|
86
|
+
const signaturePayload: RecordsWriteSignaturePayload = {
|
|
87
|
+
recordId,
|
|
88
|
+
descriptorCid,
|
|
89
|
+
contextId,
|
|
90
|
+
attestationCid,
|
|
91
|
+
encryptionCid,
|
|
92
|
+
delegatedGrantId,
|
|
93
|
+
permissionGrantId,
|
|
94
|
+
protocolRole
|
|
95
|
+
};
|
|
96
|
+
removeUndefinedProperties(signaturePayload);
|
|
97
|
+
|
|
98
|
+
const signaturePayloadBytes = Encoder.objectToBytes(signaturePayload);
|
|
99
|
+
|
|
100
|
+
const builder = await GeneralJwsBuilder.create(signaturePayloadBytes, [signer]);
|
|
101
|
+
const signature = builder.getJws();
|
|
102
|
+
|
|
103
|
+
return signature;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Validates the structural integrity of the `attestation` property.
|
|
108
|
+
* NOTE: Cryptographic verification of attestation signatures is performed in `authenticate()`.
|
|
109
|
+
*/
|
|
110
|
+
export async function validateAttestationIntegrity(message: RecordsWriteMessage): Promise<void> {
|
|
111
|
+
if (message.attestation === undefined) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// TODO: support multiple attesters (https://github.com/enboxorg/enbox/issues/223)
|
|
116
|
+
if (message.attestation.signatures.length !== 1) {
|
|
117
|
+
throw new DwnError(
|
|
118
|
+
DwnErrorCode.RecordsWriteAttestationIntegrityMoreThanOneSignature,
|
|
119
|
+
`Currently implementation only supports 1 attester, but got ${message.attestation.signatures.length}`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const payloadJson = Jws.decodePlainObjectPayload(message.attestation);
|
|
124
|
+
const { descriptorCid } = payloadJson;
|
|
125
|
+
|
|
126
|
+
// `descriptorCid` validation - ensure that the provided descriptorCid matches the CID of the actual message
|
|
127
|
+
const expectedDescriptorCid = await Cid.computeCid(message.descriptor);
|
|
128
|
+
if (descriptorCid !== expectedDescriptorCid) {
|
|
129
|
+
throw new DwnError(
|
|
130
|
+
DwnErrorCode.RecordsWriteAttestationIntegrityDescriptorCidMismatch,
|
|
131
|
+
`descriptorCid ${descriptorCid} does not match expected descriptorCid ${expectedDescriptorCid}`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// check to ensure that no other unexpected properties exist in payload.
|
|
136
|
+
const propertyCount = Object.keys(payloadJson).length;
|
|
137
|
+
if (propertyCount > 1) {
|
|
138
|
+
throw new DwnError(
|
|
139
|
+
DwnErrorCode.RecordsWriteAttestationIntegrityInvalidPayloadProperty,
|
|
140
|
+
`Only 'descriptorCid' is allowed in attestation payload, but got ${propertyCount} properties.`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
}
|