@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,43 +1,23 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
11
|
-
var t = {};
|
|
12
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
13
|
-
t[p] = s[p];
|
|
14
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
15
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
16
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
17
|
-
t[p[i]] = s[p[i]];
|
|
18
|
-
}
|
|
19
|
-
return t;
|
|
20
|
-
};
|
|
21
1
|
import { Cid } from '../utils/cid.js';
|
|
22
|
-
import { Encoder } from '../utils/encoder.js';
|
|
23
|
-
import { Encryption } from '../utils/encryption.js';
|
|
24
|
-
import { GeneralJwsBuilder } from '../jose/jws/general/builder.js';
|
|
25
2
|
import { Jws } from '../utils/jws.js';
|
|
26
|
-
import { KeyDerivationScheme } from '../utils/hd-key.js';
|
|
27
3
|
import { Message } from '../core/message.js';
|
|
28
4
|
import { PermissionGrant } from '../protocols/permission-grant.js';
|
|
29
5
|
import { Records } from '../utils/records.js';
|
|
30
6
|
import { RecordsGrantAuthorization } from '../core/records-grant-authorization.js';
|
|
31
7
|
import { removeUndefinedProperties } from '../utils/object.js';
|
|
32
8
|
import { Time } from '../utils/time.js';
|
|
9
|
+
import { createAttestation, createEncryptionProperty, createSignerSignature, validateAttestationIntegrity, } from './records-write-signing.js';
|
|
33
10
|
import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
|
|
34
11
|
import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
|
|
12
|
+
import { fetchInitialRecordsWrite, fetchInitialRecordsWriteMessage, fetchNewestRecordsWrite, getAttesters, getInitialWrite, verifyEqualityOfImmutableProperties, } from './records-write-query.js';
|
|
35
13
|
import { normalizeProtocolUrl, normalizeSchemaUrl, validateProtocolUrlNormalized, validateSchemaUrlNormalized } from '../utils/url.js';
|
|
36
14
|
/**
|
|
37
15
|
* A class representing a RecordsWrite DWN message.
|
|
38
16
|
* NOTE: Unable to extend `AbstractMessage` directly because the incompatible `_message` type, which is not just a generic `<M>` type.
|
|
39
17
|
*/
|
|
40
18
|
export class RecordsWrite {
|
|
19
|
+
parentContextId;
|
|
20
|
+
_message;
|
|
41
21
|
/**
|
|
42
22
|
* Valid JSON message representing this RecordsWrite.
|
|
43
23
|
* @throws `DwnErrorCode.RecordsWriteMissingSigner` if the message is not signed yet.
|
|
@@ -48,12 +28,15 @@ export class RecordsWrite {
|
|
|
48
28
|
}
|
|
49
29
|
return this._message;
|
|
50
30
|
}
|
|
31
|
+
_author;
|
|
51
32
|
get author() {
|
|
52
33
|
return this._author;
|
|
53
34
|
}
|
|
35
|
+
_signaturePayload;
|
|
54
36
|
get signaturePayload() {
|
|
55
37
|
return this._signaturePayload;
|
|
56
38
|
}
|
|
39
|
+
_owner;
|
|
57
40
|
/**
|
|
58
41
|
* The owner DID of the message if owner signature is present in the message; `undefined` otherwise.
|
|
59
42
|
* This is the logical owner of the message, not to be confused with the actual signer of the owner signature,
|
|
@@ -62,6 +45,7 @@ export class RecordsWrite {
|
|
|
62
45
|
get owner() {
|
|
63
46
|
return this._owner;
|
|
64
47
|
}
|
|
48
|
+
_ownerSignaturePayload;
|
|
65
49
|
/**
|
|
66
50
|
* Decoded owner signature payload.
|
|
67
51
|
*/
|
|
@@ -94,13 +78,13 @@ export class RecordsWrite {
|
|
|
94
78
|
* In the case that the owner signature is signed by the actual DWN owner, this value will be the same as {@link #owner}.
|
|
95
79
|
*/
|
|
96
80
|
get ownerSignatureSigner() {
|
|
97
|
-
|
|
98
|
-
if (((_a = this._message.authorization) === null || _a === void 0 ? void 0 : _a.ownerSignature) === undefined) {
|
|
81
|
+
if (this._message.authorization?.ownerSignature === undefined) {
|
|
99
82
|
return undefined;
|
|
100
83
|
}
|
|
101
84
|
const signer = Jws.getSignerDid(this._message.authorization.ownerSignature.signatures[0]);
|
|
102
85
|
return signer;
|
|
103
86
|
}
|
|
87
|
+
attesters;
|
|
104
88
|
constructor(message, parentContextId) {
|
|
105
89
|
this.parentContextId = parentContextId;
|
|
106
90
|
this._message = message;
|
|
@@ -119,33 +103,31 @@ export class RecordsWrite {
|
|
|
119
103
|
this._ownerSignaturePayload = Jws.decodePlainObjectPayload(message.authorization.ownerSignature);
|
|
120
104
|
}
|
|
121
105
|
}
|
|
122
|
-
this.attesters =
|
|
106
|
+
this.attesters = getAttesters(message);
|
|
123
107
|
// consider converting isInitialWrite() & getEntryId() into properties for performance and convenience
|
|
124
108
|
}
|
|
125
109
|
/**
|
|
126
110
|
* Parses a RecordsWrite message and returns a {RecordsWrite} instance.
|
|
127
111
|
*/
|
|
128
|
-
static parse(recordsWriteMessage) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
return recordsWrite;
|
|
148
|
-
});
|
|
112
|
+
static async parse(recordsWriteMessage) {
|
|
113
|
+
// Make a copy so that the stored copy is not subject to external, unexpected modification.
|
|
114
|
+
const message = JSON.parse(JSON.stringify(recordsWriteMessage));
|
|
115
|
+
// Validate the message against the JSON schema.
|
|
116
|
+
// We strip internal properties that the MessageStore may attach to stored messages
|
|
117
|
+
// but are not part of the RecordsWrite JSON schema:
|
|
118
|
+
// - `encodedData`: base64url-encoded payload for small records
|
|
119
|
+
// - `initialWrite`: the initial RecordsWrite when this message is an update
|
|
120
|
+
const { encodedData: _, initialWrite: __, ...messageToValidate } = message;
|
|
121
|
+
Message.validateJsonSchema(messageToValidate);
|
|
122
|
+
// asynchronous checks that are required by the constructor to initialize members properly
|
|
123
|
+
await Message.validateSignatureStructure(message.authorization.signature, message.descriptor, 'RecordsWriteSignaturePayload');
|
|
124
|
+
if (message.authorization.ownerSignature !== undefined) {
|
|
125
|
+
await Message.validateSignatureStructure(message.authorization.ownerSignature, message.descriptor);
|
|
126
|
+
}
|
|
127
|
+
await validateAttestationIntegrity(message);
|
|
128
|
+
const recordsWrite = new RecordsWrite(message);
|
|
129
|
+
await recordsWrite.validateIntegrity(); // RecordsWrite specific data integrity check
|
|
130
|
+
return recordsWrite;
|
|
149
131
|
}
|
|
150
132
|
/**
|
|
151
133
|
* Creates a RecordsWrite message.
|
|
@@ -159,86 +141,83 @@ export class RecordsWrite {
|
|
|
159
141
|
* @param options.parentContextId Must be given if this message is for a non-root protocol record.
|
|
160
142
|
* If not given, it either means this write is for a root protocol record or a flat-space record.
|
|
161
143
|
*/
|
|
162
|
-
static create(options) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
144
|
+
static async create(options) {
|
|
145
|
+
if ((options.protocol === undefined && options.protocolPath !== undefined) ||
|
|
146
|
+
(options.protocol !== undefined && options.protocolPath === undefined)) {
|
|
147
|
+
throw new DwnError(DwnErrorCode.RecordsWriteCreateProtocolAndProtocolPathMutuallyInclusive, '`protocol` and `protocolPath` must both be defined or undefined at the same time');
|
|
148
|
+
}
|
|
149
|
+
if ((options.data === undefined && options.dataCid === undefined) ||
|
|
150
|
+
(options.data !== undefined && options.dataCid !== undefined)) {
|
|
151
|
+
throw new DwnError(DwnErrorCode.RecordsWriteCreateDataAndDataCidMutuallyExclusive, 'one and only one parameter between `data` and `dataCid` is required');
|
|
152
|
+
}
|
|
153
|
+
if ((options.dataCid === undefined && options.dataSize !== undefined) ||
|
|
154
|
+
(options.dataCid !== undefined && options.dataSize === undefined)) {
|
|
155
|
+
throw new DwnError(DwnErrorCode.RecordsWriteCreateDataCidAndDataSizeMutuallyInclusive, '`dataCid` and `dataSize` must both be defined or undefined at the same time');
|
|
156
|
+
}
|
|
157
|
+
if (options.signer === undefined && options.delegatedGrant !== undefined) {
|
|
158
|
+
throw new DwnError(DwnErrorCode.RecordsWriteCreateMissingSigner, '`signer` must be given when `delegatedGrant` is given');
|
|
159
|
+
}
|
|
160
|
+
const dataCid = options.dataCid ?? await Cid.computeDagPbCidFromBytes(options.data);
|
|
161
|
+
const dataSize = options.dataSize ?? options.data.length;
|
|
162
|
+
const currentTime = Time.getCurrentTimestamp();
|
|
163
|
+
const descriptor = {
|
|
164
|
+
interface: DwnInterfaceName.Records,
|
|
165
|
+
method: DwnMethodName.Write,
|
|
166
|
+
protocol: options.protocol !== undefined ? normalizeProtocolUrl(options.protocol) : undefined,
|
|
167
|
+
protocolPath: options.protocolPath,
|
|
168
|
+
recipient: options.recipient,
|
|
169
|
+
schema: options.schema !== undefined ? normalizeSchemaUrl(options.schema) : undefined,
|
|
170
|
+
tags: options.tags,
|
|
171
|
+
parentId: RecordsWrite.getRecordIdFromContextId(options.parentContextId),
|
|
172
|
+
dataCid,
|
|
173
|
+
dataSize,
|
|
174
|
+
dateCreated: options.dateCreated ?? currentTime,
|
|
175
|
+
messageTimestamp: options.messageTimestamp ?? currentTime,
|
|
176
|
+
published: options.published,
|
|
177
|
+
datePublished: options.datePublished,
|
|
178
|
+
dataFormat: options.dataFormat,
|
|
179
|
+
permissionGrantId: options.permissionGrantId,
|
|
180
|
+
};
|
|
181
|
+
// generate `datePublished` if the message is to be published but `datePublished` is not given
|
|
182
|
+
if (options.published === true &&
|
|
183
|
+
options.datePublished === undefined) {
|
|
184
|
+
descriptor.datePublished = currentTime;
|
|
185
|
+
}
|
|
186
|
+
// delete all descriptor properties that are `undefined` else the code will encounter the following IPLD issue when attempting to generate CID:
|
|
187
|
+
// Error: `undefined` is not supported by the IPLD Data Model and cannot be encoded
|
|
188
|
+
removeUndefinedProperties(descriptor);
|
|
189
|
+
// `recordId` computation
|
|
190
|
+
const recordId = options.recordId;
|
|
191
|
+
// `attestation` generation
|
|
192
|
+
const descriptorCid = await Cid.computeCid(descriptor);
|
|
193
|
+
const attestation = await createAttestation(descriptorCid, options.attestationSigners);
|
|
194
|
+
// `encryption` generation
|
|
195
|
+
const encryption = await createEncryptionProperty(descriptor, options.encryptionInput);
|
|
196
|
+
const message = {
|
|
197
|
+
recordId,
|
|
198
|
+
descriptor
|
|
199
|
+
};
|
|
200
|
+
// assign optional properties only if they exist
|
|
201
|
+
if (attestation !== undefined) {
|
|
202
|
+
message.attestation = attestation;
|
|
203
|
+
}
|
|
204
|
+
if (encryption !== undefined) {
|
|
205
|
+
message.encryption = encryption;
|
|
206
|
+
}
|
|
207
|
+
const recordsWrite = new RecordsWrite(message, options.parentContextId);
|
|
208
|
+
if (options.signer !== undefined) {
|
|
209
|
+
await recordsWrite.sign({
|
|
210
|
+
signer: options.signer,
|
|
211
|
+
delegatedGrant: options.delegatedGrant,
|
|
199
212
|
permissionGrantId: options.permissionGrantId,
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
// delete all descriptor properties that are `undefined` else the code will encounter the following IPLD issue when attempting to generate CID:
|
|
207
|
-
// Error: `undefined` is not supported by the IPLD Data Model and cannot be encoded
|
|
208
|
-
removeUndefinedProperties(descriptor);
|
|
209
|
-
// `recordId` computation
|
|
210
|
-
const recordId = options.recordId;
|
|
211
|
-
// `attestation` generation
|
|
212
|
-
const descriptorCid = yield Cid.computeCid(descriptor);
|
|
213
|
-
const attestation = yield RecordsWrite.createAttestation(descriptorCid, options.attestationSigners);
|
|
214
|
-
// `encryption` generation
|
|
215
|
-
const encryption = yield RecordsWrite.createEncryptionProperty(descriptor, options.encryptionInput);
|
|
216
|
-
const message = {
|
|
217
|
-
recordId,
|
|
218
|
-
descriptor
|
|
219
|
-
};
|
|
220
|
-
// assign optional properties only if they exist
|
|
221
|
-
if (attestation !== undefined) {
|
|
222
|
-
message.attestation = attestation;
|
|
223
|
-
}
|
|
224
|
-
if (encryption !== undefined) {
|
|
225
|
-
message.encryption = encryption;
|
|
226
|
-
}
|
|
227
|
-
const recordsWrite = new RecordsWrite(message, options.parentContextId);
|
|
228
|
-
if (options.signer !== undefined) {
|
|
229
|
-
yield recordsWrite.sign({
|
|
230
|
-
signer: options.signer,
|
|
231
|
-
delegatedGrant: options.delegatedGrant,
|
|
232
|
-
permissionGrantId: options.permissionGrantId,
|
|
233
|
-
protocolRole: options.protocolRole,
|
|
234
|
-
authorKeyDeliveryPublicKey: options.authorKeyDeliveryPublicKey,
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
return recordsWrite;
|
|
238
|
-
});
|
|
213
|
+
protocolRole: options.protocolRole,
|
|
214
|
+
authorKeyDeliveryPublicKey: options.authorKeyDeliveryPublicKey,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
return recordsWrite;
|
|
239
218
|
}
|
|
240
219
|
static getRecordIdFromContextId(contextId) {
|
|
241
|
-
return contextId
|
|
220
|
+
return contextId?.split('/').filter(segment => segment !== '').pop();
|
|
242
221
|
}
|
|
243
222
|
/**
|
|
244
223
|
* Convenience method that creates a message by:
|
|
@@ -255,60 +234,57 @@ export class RecordsWrite {
|
|
|
255
234
|
* - will be set to the same published date as the given message if it wss already published; else
|
|
256
235
|
* - will be set to current time (because this is a toggle from unpublished to published)
|
|
257
236
|
*/
|
|
258
|
-
static createFrom(options) {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
//
|
|
274
|
-
if (published) {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
// this is a toggle from unpublished to published, use current time
|
|
281
|
-
datePublished = currentTime;
|
|
282
|
-
}
|
|
237
|
+
static async createFrom(options) {
|
|
238
|
+
const sourceMessage = options.recordsWriteMessage;
|
|
239
|
+
const sourceRecordsWrite = await RecordsWrite.parse(sourceMessage);
|
|
240
|
+
const currentTime = Time.getCurrentTimestamp();
|
|
241
|
+
// inherit published value from parent if neither published nor datePublished is specified
|
|
242
|
+
const published = options.published ?? (options.datePublished ? true : sourceMessage.descriptor.published);
|
|
243
|
+
// use current time if published but no explicit time given
|
|
244
|
+
let datePublished = undefined;
|
|
245
|
+
// if given explicitly published dated
|
|
246
|
+
if (options.datePublished) {
|
|
247
|
+
datePublished = options.datePublished;
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
// if this RecordsWrite will publish the record
|
|
251
|
+
if (published) {
|
|
252
|
+
// the parent was already published, inherit the same published date
|
|
253
|
+
if (sourceMessage.descriptor.published) {
|
|
254
|
+
datePublished = sourceMessage.descriptor.datePublished;
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
// this is a toggle from unpublished to published, use current time
|
|
258
|
+
datePublished = currentTime;
|
|
283
259
|
}
|
|
284
260
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
261
|
+
}
|
|
262
|
+
const createOptions = {
|
|
263
|
+
// immutable properties below, just copy from the source message
|
|
264
|
+
recipient: sourceMessage.descriptor.recipient,
|
|
265
|
+
recordId: sourceMessage.recordId,
|
|
266
|
+
dateCreated: sourceMessage.descriptor.dateCreated,
|
|
267
|
+
protocol: sourceMessage.descriptor.protocol,
|
|
268
|
+
protocolPath: sourceMessage.descriptor.protocolPath,
|
|
269
|
+
schema: sourceMessage.descriptor.schema,
|
|
270
|
+
parentContextId: Records.getParentContextFromOfContextId(sourceMessage.contextId),
|
|
271
|
+
// mutable properties below
|
|
272
|
+
messageTimestamp: options.messageTimestamp ?? currentTime,
|
|
273
|
+
published,
|
|
274
|
+
datePublished,
|
|
275
|
+
tags: options.tags,
|
|
276
|
+
data: options.data,
|
|
277
|
+
dataCid: options.data ? undefined : sourceMessage.descriptor.dataCid, // if new `data` not given, use value from source message
|
|
278
|
+
dataSize: options.data ? undefined : sourceMessage.descriptor.dataSize, // if new `data` not given, use value from source message
|
|
279
|
+
dataFormat: options.dataFormat ?? sourceMessage.descriptor.dataFormat,
|
|
280
|
+
protocolRole: options.protocolRole ?? sourceRecordsWrite.signaturePayload.protocolRole, // if not given, use value from source message
|
|
281
|
+
delegatedGrant: options.delegatedGrant,
|
|
282
|
+
// finally still need signers
|
|
283
|
+
signer: options.signer,
|
|
284
|
+
attestationSigners: options.attestationSigners
|
|
285
|
+
};
|
|
286
|
+
const recordsWrite = await RecordsWrite.create(createOptions);
|
|
287
|
+
return recordsWrite;
|
|
312
288
|
}
|
|
313
289
|
/**
|
|
314
290
|
* Called by `JSON.stringify(...)` automatically.
|
|
@@ -325,503 +301,332 @@ export class RecordsWrite {
|
|
|
325
301
|
* root-record upgrade: adding a ProtocolContext recipient entry alongside an existing
|
|
326
302
|
* ProtocolPath entry so both the owner and context key holders can decrypt.
|
|
327
303
|
*/
|
|
328
|
-
encryptSymmetricEncryptionKey(encryptionInput, options) {
|
|
329
|
-
|
|
330
|
-
if (
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
}
|
|
360
|
-
});
|
|
304
|
+
async encryptSymmetricEncryptionKey(encryptionInput, options) {
|
|
305
|
+
if (options?.append) {
|
|
306
|
+
if (!this._message.encryption) {
|
|
307
|
+
throw new DwnError(DwnErrorCode.RecordsWriteMissingEncryption, 'Cannot append recipients: record does not have an existing `encryption` property.');
|
|
308
|
+
}
|
|
309
|
+
// Build only the new recipients (reuses createEncryptionProperty for ECDH-ES+A256KW logic)
|
|
310
|
+
const newEncryption = await createEncryptionProperty(this._message.descriptor, encryptionInput);
|
|
311
|
+
if (newEncryption) {
|
|
312
|
+
this._message.encryption.recipients.push(...newEncryption.recipients);
|
|
313
|
+
}
|
|
314
|
+
// In append mode, preserve the author's identity and authorization so
|
|
315
|
+
// that signAsOwner() can be called afterwards. The author's signature
|
|
316
|
+
// payload will have a stale encryptionCid (since we just appended new
|
|
317
|
+
// recipients), but the owner's signature vouches for the
|
|
318
|
+
// updated state. validateIntegrity() skips the encryptionCid check on
|
|
319
|
+
// the author's signature when an ownerSignature is present.
|
|
320
|
+
//
|
|
321
|
+
// NOTE: An alternative design would deliver the DEK out-of-band via the
|
|
322
|
+
// key-delivery protocol (as a field on the contextKey record) instead of
|
|
323
|
+
// mutating the record's encryption property. That avoids the stale
|
|
324
|
+
// encryptionCid issue entirely but adds complexity to the read path and
|
|
325
|
+
// the contextKey schema. We chose the in-record approach because it keeps
|
|
326
|
+
// records self-contained and the read/decrypt path unchanged.
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
this._message.encryption = await createEncryptionProperty(this._message.descriptor, encryptionInput);
|
|
330
|
+
// Full replacement invalidates the authorization — caller must re-sign.
|
|
331
|
+
delete this._message.authorization;
|
|
332
|
+
this._signaturePayload = undefined;
|
|
333
|
+
this._author = undefined;
|
|
334
|
+
}
|
|
361
335
|
}
|
|
362
336
|
/**
|
|
363
337
|
* Signs the RecordsWrite, the signer is commonly the author, but can also be a delegate.
|
|
364
338
|
*/
|
|
365
|
-
sign(options) {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
339
|
+
async sign(options) {
|
|
340
|
+
const { signer, delegatedGrant, permissionGrantId, protocolRole, authorKeyDeliveryPublicKey } = options;
|
|
341
|
+
// compute delegated grant ID and author if delegated grant is given
|
|
342
|
+
let delegatedGrantId;
|
|
343
|
+
let authorDid;
|
|
344
|
+
if (delegatedGrant !== undefined) {
|
|
345
|
+
delegatedGrantId = await Message.getCid(delegatedGrant);
|
|
346
|
+
authorDid = Jws.getSignerDid(delegatedGrant.authorization.signature.signatures[0]);
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
authorDid = Jws.extractDid(signer.keyId);
|
|
350
|
+
}
|
|
351
|
+
const descriptor = this._message.descriptor;
|
|
352
|
+
const descriptorCid = await Cid.computeCid(descriptor);
|
|
353
|
+
// compute `recordId` if not given at construction time
|
|
354
|
+
this._message.recordId = this._message.recordId ?? await RecordsWrite.getEntryId(authorDid, descriptor);
|
|
355
|
+
// compute `contextId` if this is a protocol-space record
|
|
356
|
+
if (this._message.descriptor.protocol !== undefined) {
|
|
357
|
+
// if `parentContextId` is not given, this is a root protocol record
|
|
358
|
+
if (this.parentContextId === undefined || this.parentContextId === '') {
|
|
359
|
+
this._message.contextId = this._message.recordId;
|
|
375
360
|
}
|
|
376
361
|
else {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
const descriptor = this._message.descriptor;
|
|
380
|
-
const descriptorCid = yield Cid.computeCid(descriptor);
|
|
381
|
-
// compute `recordId` if not given at construction time
|
|
382
|
-
this._message.recordId = (_a = this._message.recordId) !== null && _a !== void 0 ? _a : yield RecordsWrite.getEntryId(authorDid, descriptor);
|
|
383
|
-
// compute `contextId` if this is a protocol-space record
|
|
384
|
-
if (this._message.descriptor.protocol !== undefined) {
|
|
385
|
-
// if `parentContextId` is not given, this is a root protocol record
|
|
386
|
-
if (this.parentContextId === undefined || this.parentContextId === '') {
|
|
387
|
-
this._message.contextId = this._message.recordId;
|
|
388
|
-
}
|
|
389
|
-
else {
|
|
390
|
-
// else this is a non-root protocol record
|
|
391
|
-
this._message.contextId = this.parentContextId + '/' + this._message.recordId;
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
// `signature` generation
|
|
395
|
-
const signature = yield RecordsWrite.createSignerSignature({
|
|
396
|
-
recordId: this._message.recordId,
|
|
397
|
-
contextId: this._message.contextId,
|
|
398
|
-
descriptorCid,
|
|
399
|
-
attestation: this._message.attestation,
|
|
400
|
-
encryption: this._message.encryption,
|
|
401
|
-
signer,
|
|
402
|
-
delegatedGrantId,
|
|
403
|
-
permissionGrantId,
|
|
404
|
-
protocolRole
|
|
405
|
-
});
|
|
406
|
-
this._message.authorization = { signature };
|
|
407
|
-
if (delegatedGrant !== undefined) {
|
|
408
|
-
this._message.authorization.authorDelegatedGrant = delegatedGrant;
|
|
409
|
-
}
|
|
410
|
-
if (authorKeyDeliveryPublicKey !== undefined) {
|
|
411
|
-
this._message.authorization.authorKeyDeliveryPublicKey = authorKeyDeliveryPublicKey;
|
|
362
|
+
// else this is a non-root protocol record
|
|
363
|
+
this._message.contextId = this.parentContextId + '/' + this._message.recordId;
|
|
412
364
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
365
|
+
}
|
|
366
|
+
// `signature` generation
|
|
367
|
+
const signature = await createSignerSignature({
|
|
368
|
+
recordId: this._message.recordId,
|
|
369
|
+
contextId: this._message.contextId,
|
|
370
|
+
descriptorCid,
|
|
371
|
+
attestation: this._message.attestation,
|
|
372
|
+
encryption: this._message.encryption,
|
|
373
|
+
signer,
|
|
374
|
+
delegatedGrantId,
|
|
375
|
+
permissionGrantId,
|
|
376
|
+
protocolRole
|
|
416
377
|
});
|
|
378
|
+
this._message.authorization = { signature };
|
|
379
|
+
if (delegatedGrant !== undefined) {
|
|
380
|
+
this._message.authorization.authorDelegatedGrant = delegatedGrant;
|
|
381
|
+
}
|
|
382
|
+
if (authorKeyDeliveryPublicKey !== undefined) {
|
|
383
|
+
this._message.authorization.authorKeyDeliveryPublicKey = authorKeyDeliveryPublicKey;
|
|
384
|
+
}
|
|
385
|
+
// there is opportunity to optimize here as the payload is constructed within `createAuthorization(...)`
|
|
386
|
+
this._signaturePayload = Jws.decodePlainObjectPayload(signature);
|
|
387
|
+
this._author = authorDid;
|
|
417
388
|
}
|
|
418
389
|
/**
|
|
419
390
|
* Signs the `RecordsWrite` as the DWN owner.
|
|
420
391
|
* This is used when the DWN owner wants to retain a copy of a message that the owner did not author.
|
|
421
392
|
* NOTE: requires the `RecordsWrite` to already have the author's signature.
|
|
422
393
|
*/
|
|
423
|
-
signAsOwner(signer) {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
;
|
|
434
|
-
});
|
|
394
|
+
async signAsOwner(signer) {
|
|
395
|
+
if (this._author === undefined) {
|
|
396
|
+
throw new DwnError(DwnErrorCode.RecordsWriteSignAsOwnerUnknownAuthor, 'Unable to sign as owner without message signature because owner needs to sign over `recordId` which depends on author DID.');
|
|
397
|
+
}
|
|
398
|
+
const descriptor = this._message.descriptor;
|
|
399
|
+
const ownerSignature = await Message.createSignature(descriptor, signer);
|
|
400
|
+
this._message.authorization.ownerSignature = ownerSignature;
|
|
401
|
+
this._ownerSignaturePayload = Jws.decodePlainObjectPayload(ownerSignature);
|
|
402
|
+
this._owner = Jws.extractDid(signer.keyId);
|
|
403
|
+
;
|
|
435
404
|
}
|
|
436
405
|
/**
|
|
437
406
|
* Signs the `RecordsWrite` as the DWN owner-delegate.
|
|
438
407
|
* This is used when a DWN owner-delegate wants to retain a copy of a message that the owner did not author.
|
|
439
408
|
* NOTE: requires the `RecordsWrite` to already have the author's signature.
|
|
440
409
|
*/
|
|
441
|
-
signAsOwnerDelegate(signer, delegatedGrant) {
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
this._owner = Jws.getSignerDid(delegatedGrant.authorization.signature.signatures[0]);
|
|
453
|
-
});
|
|
410
|
+
async signAsOwnerDelegate(signer, delegatedGrant) {
|
|
411
|
+
if (this._author === undefined) {
|
|
412
|
+
throw new DwnError(DwnErrorCode.RecordsWriteSignAsOwnerDelegateUnknownAuthor, 'Unable to sign as owner delegate without message signature because owner delegate needs to sign over `recordId` which depends on author DID.');
|
|
413
|
+
}
|
|
414
|
+
const delegatedGrantId = await Message.getCid(delegatedGrant);
|
|
415
|
+
const descriptor = this._message.descriptor;
|
|
416
|
+
const ownerSignature = await Message.createSignature(descriptor, signer, { delegatedGrantId });
|
|
417
|
+
this._message.authorization.ownerSignature = ownerSignature;
|
|
418
|
+
this._message.authorization.ownerDelegatedGrant = delegatedGrant;
|
|
419
|
+
this._ownerSignaturePayload = Jws.decodePlainObjectPayload(ownerSignature);
|
|
420
|
+
this._owner = Jws.getSignerDid(delegatedGrant.authorization.signature.signatures[0]);
|
|
454
421
|
}
|
|
455
422
|
/**
|
|
456
423
|
* Validates the integrity of the RecordsWrite message assuming the message passed basic schema validation.
|
|
457
424
|
* There is opportunity to integrate better with `validateSchema(...)`
|
|
458
425
|
*/
|
|
459
|
-
validateIntegrity() {
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
426
|
+
async validateIntegrity() {
|
|
427
|
+
// if the new message is the initial write
|
|
428
|
+
const isInitialWrite = await this.isInitialWrite();
|
|
429
|
+
if (isInitialWrite) {
|
|
430
|
+
// `messageTimestamp` and `dateCreated` equality check
|
|
431
|
+
const dateRecordCreated = this.message.descriptor.dateCreated;
|
|
432
|
+
const messageTimestamp = this.message.descriptor.messageTimestamp;
|
|
433
|
+
if (messageTimestamp !== dateRecordCreated) {
|
|
434
|
+
throw new DwnError(DwnErrorCode.RecordsWriteValidateIntegrityDateCreatedMismatch, `messageTimestamp ${messageTimestamp} must match dateCreated ${dateRecordCreated} for the initial write`);
|
|
435
|
+
}
|
|
436
|
+
// if the message is also a protocol context root, the `contextId` must match the expected deterministic value
|
|
437
|
+
if (this.message.descriptor.protocol !== undefined &&
|
|
438
|
+
this.message.descriptor.parentId === undefined) {
|
|
439
|
+
const expectedContextId = await this.getEntryId();
|
|
440
|
+
if (this.message.contextId !== expectedContextId) {
|
|
441
|
+
throw new DwnError(DwnErrorCode.RecordsWriteValidateIntegrityContextIdMismatch, `contextId in message: ${this.message.contextId} does not match deterministic contextId: ${expectedContextId}`);
|
|
470
442
|
}
|
|
471
|
-
// if the message is also a protocol context root, the `contextId` must match the expected deterministic value
|
|
472
|
-
if (this.message.descriptor.protocol !== undefined &&
|
|
473
|
-
this.message.descriptor.parentId === undefined) {
|
|
474
|
-
const expectedContextId = yield this.getEntryId();
|
|
475
|
-
if (this.message.contextId !== expectedContextId) {
|
|
476
|
-
throw new DwnError(DwnErrorCode.RecordsWriteValidateIntegrityContextIdMismatch, `contextId in message: ${this.message.contextId} does not match deterministic contextId: ${expectedContextId}`);
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
// NOTE: validateSignatureStructure() call earlier enforces the presence of `authorization` and thus `signature` in RecordsWrite
|
|
481
|
-
const signaturePayload = this.signaturePayload;
|
|
482
|
-
// make sure the `recordId` in message is the same as the `recordId` in the payload of the message signature
|
|
483
|
-
if (this.message.recordId !== signaturePayload.recordId) {
|
|
484
|
-
throw new DwnError(DwnErrorCode.RecordsWriteValidateIntegrityRecordIdUnauthorized, `recordId in message ${this.message.recordId} does not match recordId in authorization: ${signaturePayload.recordId}`);
|
|
485
443
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
// updated encryption property, so the mismatch is expected and safe.
|
|
505
|
-
const hasOwnerSignature = ((_a = this.message.authorization) === null || _a === void 0 ? void 0 : _a.ownerSignature) !== undefined;
|
|
506
|
-
if (signaturePayload.encryptionCid !== undefined && !hasOwnerSignature) {
|
|
507
|
-
const expectedEncryptionCid = yield Cid.computeCid(this.message.encryption);
|
|
508
|
-
const actualEncryptionCid = signaturePayload.encryptionCid;
|
|
509
|
-
if (actualEncryptionCid !== expectedEncryptionCid) {
|
|
510
|
-
throw new DwnError(DwnErrorCode.RecordsWriteValidateIntegrityEncryptionCidMismatch, `CID ${expectedEncryptionCid} of encryption property in message does not match encryptionCid in authorization: ${actualEncryptionCid}`);
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
if (this.message.descriptor.protocol !== undefined) {
|
|
514
|
-
validateProtocolUrlNormalized(this.message.descriptor.protocol);
|
|
515
|
-
}
|
|
516
|
-
if (this.message.descriptor.schema !== undefined) {
|
|
517
|
-
validateSchemaUrlNormalized(this.message.descriptor.schema);
|
|
444
|
+
}
|
|
445
|
+
// NOTE: validateSignatureStructure() call earlier enforces the presence of `authorization` and thus `signature` in RecordsWrite
|
|
446
|
+
const signaturePayload = this.signaturePayload;
|
|
447
|
+
// make sure the `recordId` in message is the same as the `recordId` in the payload of the message signature
|
|
448
|
+
if (this.message.recordId !== signaturePayload.recordId) {
|
|
449
|
+
throw new DwnError(DwnErrorCode.RecordsWriteValidateIntegrityRecordIdUnauthorized, `recordId in message ${this.message.recordId} does not match recordId in authorization: ${signaturePayload.recordId}`);
|
|
450
|
+
}
|
|
451
|
+
// if `contextId` is given in message, make sure the same `contextId` is in the payload of the message signature
|
|
452
|
+
if (this.message.contextId !== signaturePayload.contextId) {
|
|
453
|
+
throw new DwnError(DwnErrorCode.RecordsWriteValidateIntegrityContextIdNotInSignerSignaturePayload, `contextId in message ${this.message.contextId} does not match contextId in authorization: ${signaturePayload.contextId}`);
|
|
454
|
+
}
|
|
455
|
+
await Records.validateDelegatedGrantReferentialIntegrity(this.message, signaturePayload, this.ownerSignaturePayload);
|
|
456
|
+
// if `attestation` is given in message, make sure the correct `attestationCid` is in the payload of the message signature
|
|
457
|
+
if (signaturePayload.attestationCid !== undefined) {
|
|
458
|
+
const expectedAttestationCid = await Cid.computeCid(this.message.attestation);
|
|
459
|
+
const actualAttestationCid = signaturePayload.attestationCid;
|
|
460
|
+
if (actualAttestationCid !== expectedAttestationCid) {
|
|
461
|
+
throw new DwnError(DwnErrorCode.RecordsWriteValidateIntegrityAttestationMismatch, `CID ${expectedAttestationCid} of attestation property in message does not match attestationCid in authorization: ${actualAttestationCid}`);
|
|
518
462
|
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
463
|
+
}
|
|
464
|
+
// If `encryption` is given in message, make sure the correct `encryptionCid`
|
|
465
|
+
// is in the payload of the message signature — UNLESS the message has an
|
|
466
|
+
// ownerSignature. When the DWN owner appends recipients to an
|
|
467
|
+
// externally-authored record (reactive root-record upgrade), the author's
|
|
468
|
+
// encryptionCid becomes stale. The owner's signature vouches for the
|
|
469
|
+
// updated encryption property, so the mismatch is expected and safe.
|
|
470
|
+
const hasOwnerSignature = this.message.authorization?.ownerSignature !== undefined;
|
|
471
|
+
if (signaturePayload.encryptionCid !== undefined && !hasOwnerSignature) {
|
|
472
|
+
const expectedEncryptionCid = await Cid.computeCid(this.message.encryption);
|
|
473
|
+
const actualEncryptionCid = signaturePayload.encryptionCid;
|
|
474
|
+
if (actualEncryptionCid !== expectedEncryptionCid) {
|
|
475
|
+
throw new DwnError(DwnErrorCode.RecordsWriteValidateIntegrityEncryptionCidMismatch, `CID ${expectedEncryptionCid} of encryption property in message does not match encryptionCid in authorization: ${actualEncryptionCid}`);
|
|
523
476
|
}
|
|
524
|
-
}
|
|
477
|
+
}
|
|
478
|
+
if (this.message.descriptor.protocol !== undefined) {
|
|
479
|
+
validateProtocolUrlNormalized(this.message.descriptor.protocol);
|
|
480
|
+
}
|
|
481
|
+
if (this.message.descriptor.schema !== undefined) {
|
|
482
|
+
validateSchemaUrlNormalized(this.message.descriptor.schema);
|
|
483
|
+
}
|
|
484
|
+
Time.validateTimestamp(this.message.descriptor.messageTimestamp);
|
|
485
|
+
Time.validateTimestamp(this.message.descriptor.dateCreated);
|
|
486
|
+
if (this.message.descriptor.datePublished) {
|
|
487
|
+
Time.validateTimestamp(this.message.descriptor.datePublished);
|
|
488
|
+
}
|
|
525
489
|
}
|
|
526
490
|
/**
|
|
527
|
-
*
|
|
528
|
-
* NOTE: Cryptographic verification of attestation signatures is performed in `authenticate()`.
|
|
491
|
+
* Delegate to the standalone `validateAttestationIntegrity` function for backward compatibility.
|
|
529
492
|
*/
|
|
530
|
-
static validateAttestationIntegrity(message) {
|
|
531
|
-
return
|
|
532
|
-
if (message.attestation === undefined) {
|
|
533
|
-
return;
|
|
534
|
-
}
|
|
535
|
-
// TODO: multi-attesters to be unblocked by #205 - Revisit database interfaces (https://github.com/enboxorg/enbox/issues/205)
|
|
536
|
-
if (message.attestation.signatures.length !== 1) {
|
|
537
|
-
throw new DwnError(DwnErrorCode.RecordsWriteAttestationIntegrityMoreThanOneSignature, `Currently implementation only supports 1 attester, but got ${message.attestation.signatures.length}`);
|
|
538
|
-
}
|
|
539
|
-
const payloadJson = Jws.decodePlainObjectPayload(message.attestation);
|
|
540
|
-
const { descriptorCid } = payloadJson;
|
|
541
|
-
// `descriptorCid` validation - ensure that the provided descriptorCid matches the CID of the actual message
|
|
542
|
-
const expectedDescriptorCid = yield Cid.computeCid(message.descriptor);
|
|
543
|
-
if (descriptorCid !== expectedDescriptorCid) {
|
|
544
|
-
throw new DwnError(DwnErrorCode.RecordsWriteAttestationIntegrityDescriptorCidMismatch, `descriptorCid ${descriptorCid} does not match expected descriptorCid ${expectedDescriptorCid}`);
|
|
545
|
-
}
|
|
546
|
-
// check to ensure that no other unexpected properties exist in payload.
|
|
547
|
-
const propertyCount = Object.keys(payloadJson).length;
|
|
548
|
-
if (propertyCount > 1) {
|
|
549
|
-
throw new DwnError(DwnErrorCode.RecordsWriteAttestationIntegrityInvalidPayloadProperty, `Only 'descriptorCid' is allowed in attestation payload, but got ${propertyCount} properties.`);
|
|
550
|
-
}
|
|
551
|
-
});
|
|
493
|
+
static async validateAttestationIntegrity(message) {
|
|
494
|
+
return validateAttestationIntegrity(message);
|
|
552
495
|
}
|
|
553
|
-
;
|
|
554
496
|
/**
|
|
555
497
|
* Computes the deterministic Entry ID of this message.
|
|
556
498
|
*/
|
|
557
|
-
getEntryId() {
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
return entryId;
|
|
561
|
-
});
|
|
499
|
+
async getEntryId() {
|
|
500
|
+
const entryId = await RecordsWrite.getEntryId(this.author, this.message.descriptor);
|
|
501
|
+
return entryId;
|
|
562
502
|
}
|
|
563
503
|
;
|
|
564
504
|
/**
|
|
565
505
|
* Computes the deterministic Entry ID of this message.
|
|
566
506
|
*/
|
|
567
|
-
static getEntryId(author, descriptor) {
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
return cid;
|
|
575
|
-
});
|
|
507
|
+
static async getEntryId(author, descriptor) {
|
|
508
|
+
if (author === undefined) {
|
|
509
|
+
throw new DwnError(DwnErrorCode.RecordsWriteGetEntryIdUndefinedAuthor, 'Property `author` is needed to compute entry ID.');
|
|
510
|
+
}
|
|
511
|
+
const entryIdInput = { ...descriptor, author };
|
|
512
|
+
const cid = await Cid.computeCid(entryIdInput);
|
|
513
|
+
return cid;
|
|
576
514
|
}
|
|
577
515
|
;
|
|
578
516
|
/**
|
|
579
517
|
* Checks if the given message is the initial entry of a record.
|
|
580
518
|
*/
|
|
581
|
-
isInitialWrite() {
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
//
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
519
|
+
async isInitialWrite() {
|
|
520
|
+
const entryId = await this.getEntryId();
|
|
521
|
+
return (entryId === this.message.recordId);
|
|
522
|
+
}
|
|
523
|
+
async constructIndexes(isLatestBaseState) {
|
|
524
|
+
const message = this.message;
|
|
525
|
+
// we want to process tags separately from the rest of descriptors as it is an object and not a primitive KeyValue type.
|
|
526
|
+
const { tags, ...descriptor } = message.descriptor;
|
|
527
|
+
delete descriptor.published; // handle `published` specifically further down
|
|
528
|
+
let indexes = {
|
|
529
|
+
...descriptor,
|
|
530
|
+
isLatestBaseState,
|
|
531
|
+
published: !!message.descriptor.published,
|
|
532
|
+
author: this.author, //author will not be undefined when indexes are constructed as it's been authorized
|
|
533
|
+
recordId: message.recordId,
|
|
534
|
+
entryId: await RecordsWrite.getEntryId(this.author, this.message.descriptor)
|
|
535
|
+
};
|
|
536
|
+
// in order to avoid name clashes with first-class index keys
|
|
537
|
+
// we build the indexes with `tag.property_name` for each tag property.
|
|
538
|
+
// we only index tags if the message is the latest base state, as that's the only time filtering for tags is relevant.
|
|
539
|
+
if (tags !== undefined && isLatestBaseState === true) {
|
|
540
|
+
const flattenedTags = Records.buildTagIndexes({ ...tags });
|
|
541
|
+
indexes = { ...indexes, ...flattenedTags };
|
|
542
|
+
}
|
|
543
|
+
// add additional indexes to optional values if given
|
|
544
|
+
// TODO: index multiple attesters (https://github.com/enboxorg/enbox/issues/223)
|
|
545
|
+
if (this.attesters.length > 0) {
|
|
546
|
+
indexes.attester = this.attesters[0];
|
|
547
|
+
}
|
|
548
|
+
if (message.contextId !== undefined) {
|
|
549
|
+
indexes.contextId = message.contextId;
|
|
550
|
+
}
|
|
551
|
+
return indexes;
|
|
611
552
|
}
|
|
612
553
|
/**
|
|
613
554
|
* Authorizes the author-delegate who signed this message.
|
|
614
555
|
* @param messageStore Used to check if the grant has been revoked.
|
|
615
556
|
*/
|
|
616
|
-
authorizeAuthorDelegate(messageStore) {
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
messageStore
|
|
625
|
-
});
|
|
557
|
+
async authorizeAuthorDelegate(messageStore) {
|
|
558
|
+
const delegatedGrant = await PermissionGrant.parse(this.message.authorization.authorDelegatedGrant);
|
|
559
|
+
await RecordsGrantAuthorization.authorizeWrite({
|
|
560
|
+
recordsWriteMessage: this.message,
|
|
561
|
+
expectedGrantor: this.author,
|
|
562
|
+
expectedGrantee: this.signer,
|
|
563
|
+
permissionGrant: delegatedGrant,
|
|
564
|
+
messageStore
|
|
626
565
|
});
|
|
627
566
|
}
|
|
628
567
|
/**
|
|
629
568
|
* Authorizes the owner-delegate who signed this message.
|
|
630
569
|
* @param messageStore Used to check if the grant has been revoked.
|
|
631
570
|
*/
|
|
632
|
-
authorizeOwnerDelegate(messageStore) {
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
messageStore
|
|
641
|
-
});
|
|
571
|
+
async authorizeOwnerDelegate(messageStore) {
|
|
572
|
+
const delegatedGrant = await PermissionGrant.parse(this.message.authorization.ownerDelegatedGrant);
|
|
573
|
+
await RecordsGrantAuthorization.authorizeWrite({
|
|
574
|
+
recordsWriteMessage: this.message,
|
|
575
|
+
expectedGrantor: this.owner,
|
|
576
|
+
expectedGrantee: this.ownerSignatureSigner,
|
|
577
|
+
permissionGrant: delegatedGrant,
|
|
578
|
+
messageStore
|
|
642
579
|
});
|
|
643
580
|
}
|
|
644
581
|
/**
|
|
645
582
|
* Checks if the given message is the initial entry of a record.
|
|
646
583
|
*/
|
|
647
|
-
static isInitialWrite(message) {
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
return (entryId === recordsWriteMessage.recordId);
|
|
658
|
-
});
|
|
584
|
+
static async isInitialWrite(message) {
|
|
585
|
+
// can't be the initial write if the message is not a Records Write
|
|
586
|
+
if (message.descriptor.interface !== DwnInterfaceName.Records ||
|
|
587
|
+
message.descriptor.method !== DwnMethodName.Write) {
|
|
588
|
+
return false;
|
|
589
|
+
}
|
|
590
|
+
const recordsWriteMessage = message;
|
|
591
|
+
const author = Message.getAuthor(recordsWriteMessage);
|
|
592
|
+
const entryId = await RecordsWrite.getEntryId(author, recordsWriteMessage.descriptor);
|
|
593
|
+
return (entryId === recordsWriteMessage.recordId);
|
|
659
594
|
}
|
|
660
|
-
/**
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
* @param descriptor Descriptor of the `RecordsWrite` message which contains the information needed by key path derivation schemes.
|
|
664
|
-
*/
|
|
665
|
-
/**
|
|
666
|
-
* Creates the JWE `encryption` property if encryption input is given. Else `undefined` is returned.
|
|
667
|
-
* Uses ECDH-ES+A256KW key agreement with X25519 and AEAD content encryption (A256GCM or XC20P).
|
|
668
|
-
* @param descriptor Descriptor of the `RecordsWrite` message which contains the information needed by key path derivation schemes.
|
|
669
|
-
* @param encryptionInput The encryption input containing CEK, IV, and recipient key encryption inputs.
|
|
670
|
-
* @param tag The authentication tag from the AEAD content encryption (stored in the JWE, separate from the ciphertext).
|
|
671
|
-
*/
|
|
672
|
-
/**
|
|
673
|
-
* Creates the JWE `encryption` property if encryption input is given. Else `undefined` is returned.
|
|
674
|
-
* Uses ECDH-ES+A256KW key agreement with X25519 and AEAD content encryption (A256GCM or XC20P).
|
|
675
|
-
* @param descriptor Descriptor of the `RecordsWrite` message which contains the information needed by key path derivation schemes.
|
|
676
|
-
* @param encryptionInput The encryption input containing CEK, IV, authentication tag, and recipient key encryption inputs.
|
|
677
|
-
*/
|
|
678
|
-
static createEncryptionProperty(descriptor, encryptionInput) {
|
|
679
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
680
|
-
if (encryptionInput === undefined) {
|
|
681
|
-
return undefined;
|
|
682
|
-
}
|
|
683
|
-
// Validate derivation scheme prerequisites
|
|
684
|
-
for (const keyEncryptionInput of encryptionInput.keyEncryptionInputs) {
|
|
685
|
-
if (keyEncryptionInput.derivationScheme === KeyDerivationScheme.ProtocolPath && descriptor.protocol === undefined) {
|
|
686
|
-
throw new DwnError(DwnErrorCode.RecordsWriteMissingProtocol, '`protocols` encryption scheme cannot be applied to record without the `protocol` property.');
|
|
687
|
-
}
|
|
688
|
-
if (keyEncryptionInput.derivationScheme === KeyDerivationScheme.Schemas && descriptor.schema === undefined) {
|
|
689
|
-
throw new DwnError(DwnErrorCode.RecordsWriteMissingSchema, '`schemas` encryption scheme cannot be applied to record without the `schema` property.');
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
// Build the JWE structure. The authentication tag comes from the AEAD encryption of record data.
|
|
693
|
-
const jwe = yield Encryption.buildJwe(encryptionInput, encryptionInput.authenticationTag);
|
|
694
|
-
return jwe;
|
|
695
|
-
});
|
|
595
|
+
/** Delegate to `createEncryptionProperty` in `records-write-signing.ts`. */
|
|
596
|
+
static async createEncryptionProperty(descriptor, encryptionInput) {
|
|
597
|
+
return createEncryptionProperty(descriptor, encryptionInput);
|
|
696
598
|
}
|
|
697
|
-
/**
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
static createAttestation(descriptorCid, signers) {
|
|
701
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
702
|
-
if (signers === undefined || signers.length === 0) {
|
|
703
|
-
return undefined;
|
|
704
|
-
}
|
|
705
|
-
const attestationPayload = { descriptorCid };
|
|
706
|
-
const attestationPayloadBytes = Encoder.objectToBytes(attestationPayload);
|
|
707
|
-
const builder = yield GeneralJwsBuilder.create(attestationPayloadBytes, signers);
|
|
708
|
-
return builder.getJws();
|
|
709
|
-
});
|
|
599
|
+
/** Delegate to `createAttestation` in `records-write-signing.ts`. */
|
|
600
|
+
static async createAttestation(descriptorCid, signers) {
|
|
601
|
+
return createAttestation(descriptorCid, signers);
|
|
710
602
|
}
|
|
711
|
-
/**
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
static createSignerSignature(input) {
|
|
715
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
716
|
-
const { recordId, contextId, descriptorCid, attestation, encryption, signer, delegatedGrantId, permissionGrantId, protocolRole } = input;
|
|
717
|
-
const attestationCid = attestation ? yield Cid.computeCid(attestation) : undefined;
|
|
718
|
-
const encryptionCid = encryption ? yield Cid.computeCid(encryption) : undefined;
|
|
719
|
-
const signaturePayload = {
|
|
720
|
-
recordId,
|
|
721
|
-
descriptorCid,
|
|
722
|
-
contextId,
|
|
723
|
-
attestationCid,
|
|
724
|
-
encryptionCid,
|
|
725
|
-
delegatedGrantId,
|
|
726
|
-
permissionGrantId,
|
|
727
|
-
protocolRole
|
|
728
|
-
};
|
|
729
|
-
removeUndefinedProperties(signaturePayload);
|
|
730
|
-
const signaturePayloadBytes = Encoder.objectToBytes(signaturePayload);
|
|
731
|
-
const builder = yield GeneralJwsBuilder.create(signaturePayloadBytes, [signer]);
|
|
732
|
-
const signature = builder.getJws();
|
|
733
|
-
return signature;
|
|
734
|
-
});
|
|
603
|
+
/** Delegate to `createSignerSignature` in `records-write-signing.ts`. */
|
|
604
|
+
static async createSignerSignature(input) {
|
|
605
|
+
return createSignerSignature(input);
|
|
735
606
|
}
|
|
736
|
-
/**
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
static getInitialWrite(messages) {
|
|
740
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
741
|
-
for (const message of messages) {
|
|
742
|
-
if (yield RecordsWrite.isInitialWrite(message)) {
|
|
743
|
-
return message;
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
throw new DwnError(DwnErrorCode.RecordsWriteGetInitialWriteNotFound, `Initial write is not found.`);
|
|
747
|
-
});
|
|
607
|
+
/** Delegate to `getInitialWrite` in `records-write-query.ts`. */
|
|
608
|
+
static async getInitialWrite(messages) {
|
|
609
|
+
return getInitialWrite(messages);
|
|
748
610
|
}
|
|
749
|
-
/**
|
|
750
|
-
* Verifies that immutable properties of the two given messages are identical.
|
|
751
|
-
* @throws {Error} if immutable properties between two RecordsWrite message
|
|
752
|
-
*/
|
|
611
|
+
/** Delegate to `verifyEqualityOfImmutableProperties` in `records-write-query.ts`. */
|
|
753
612
|
static verifyEqualityOfImmutableProperties(existingWriteMessage, newMessage) {
|
|
754
|
-
|
|
755
|
-
// get distinct property names that exist in either the existing message given or new message
|
|
756
|
-
let descriptorPropertyNames = [];
|
|
757
|
-
descriptorPropertyNames.push(...Object.keys(existingWriteMessage.descriptor));
|
|
758
|
-
descriptorPropertyNames.push(...Object.keys(newMessage.descriptor));
|
|
759
|
-
descriptorPropertyNames = [...new Set(descriptorPropertyNames)]; // step to remove duplicates
|
|
760
|
-
// ensure all immutable properties are not modified
|
|
761
|
-
for (const descriptorPropertyName of descriptorPropertyNames) {
|
|
762
|
-
// if property is supposed to be immutable
|
|
763
|
-
if (mutableDescriptorProperties.indexOf(descriptorPropertyName) === -1) {
|
|
764
|
-
const valueInExistingWrite = existingWriteMessage.descriptor[descriptorPropertyName];
|
|
765
|
-
const valueInNewMessage = newMessage.descriptor[descriptorPropertyName];
|
|
766
|
-
if (valueInNewMessage !== valueInExistingWrite) {
|
|
767
|
-
throw new DwnError(DwnErrorCode.RecordsWriteImmutablePropertyChanged, `${descriptorPropertyName} is an immutable property: cannot change '${valueInExistingWrite}' to '${valueInNewMessage}'`);
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
return true;
|
|
613
|
+
return verifyEqualityOfImmutableProperties(existingWriteMessage, newMessage);
|
|
772
614
|
}
|
|
773
|
-
/**
|
|
774
|
-
* Gets the DID of the attesters of the given message.
|
|
775
|
-
*/
|
|
615
|
+
/** Delegate to `getAttesters` in `records-write-query.ts`. */
|
|
776
616
|
static getAttesters(message) {
|
|
777
|
-
|
|
778
|
-
const attestationSignatures = (_b = (_a = message.attestation) === null || _a === void 0 ? void 0 : _a.signatures) !== null && _b !== void 0 ? _b : [];
|
|
779
|
-
const attesters = attestationSignatures.map((signature) => Jws.getSignerDid(signature));
|
|
780
|
-
return attesters;
|
|
781
|
-
}
|
|
782
|
-
static fetchNewestRecordsWrite(messageStore, tenant, recordId) {
|
|
783
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
784
|
-
// get existing RecordsWrite messages matching the `recordId`
|
|
785
|
-
const query = {
|
|
786
|
-
interface: DwnInterfaceName.Records,
|
|
787
|
-
method: DwnMethodName.Write,
|
|
788
|
-
recordId: recordId
|
|
789
|
-
};
|
|
790
|
-
const { messages: existingMessages } = yield messageStore.query(tenant, [query]);
|
|
791
|
-
const newestWrite = yield Message.getNewestMessage(existingMessages);
|
|
792
|
-
if (newestWrite !== undefined) {
|
|
793
|
-
return newestWrite;
|
|
794
|
-
}
|
|
795
|
-
throw new DwnError(DwnErrorCode.RecordsWriteGetNewestWriteRecordNotFound, 'record not found');
|
|
796
|
-
});
|
|
617
|
+
return getAttesters(message);
|
|
797
618
|
}
|
|
798
|
-
/**
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
*/
|
|
802
|
-
static fetchInitialRecordsWrite(messageStore, tenant, recordId) {
|
|
803
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
804
|
-
const initialRecordsWriteMessage = yield RecordsWrite.fetchInitialRecordsWriteMessage(messageStore, tenant, recordId);
|
|
805
|
-
if (initialRecordsWriteMessage === undefined) {
|
|
806
|
-
return undefined;
|
|
807
|
-
}
|
|
808
|
-
const initialRecordsWrite = yield RecordsWrite.parse(initialRecordsWriteMessage);
|
|
809
|
-
return initialRecordsWrite;
|
|
810
|
-
});
|
|
619
|
+
/** Delegate to `fetchNewestRecordsWrite` in `records-write-query.ts`. */
|
|
620
|
+
static async fetchNewestRecordsWrite(messageStore, tenant, recordId) {
|
|
621
|
+
return fetchNewestRecordsWrite(messageStore, tenant, recordId);
|
|
811
622
|
}
|
|
812
|
-
/**
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
const { messages } = yield messageStore.query(tenant, [query]);
|
|
820
|
-
if (messages.length === 0) {
|
|
821
|
-
return undefined;
|
|
822
|
-
}
|
|
823
|
-
return messages[0];
|
|
824
|
-
});
|
|
623
|
+
/** Delegate to `fetchInitialRecordsWrite` in `records-write-query.ts`. */
|
|
624
|
+
static async fetchInitialRecordsWrite(messageStore, tenant, recordId) {
|
|
625
|
+
return fetchInitialRecordsWrite(messageStore, tenant, recordId);
|
|
626
|
+
}
|
|
627
|
+
/** Delegate to `fetchInitialRecordsWriteMessage` in `records-write-query.ts`. */
|
|
628
|
+
static async fetchInitialRecordsWriteMessage(messageStore, tenant, recordId) {
|
|
629
|
+
return fetchInitialRecordsWriteMessage(messageStore, tenant, recordId);
|
|
825
630
|
}
|
|
826
631
|
}
|
|
827
632
|
//# sourceMappingURL=records-write.js.map
|