@enbox/dwn-sdk-js 0.4.6 → 0.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/browser.mjs +19 -78
- package/dist/browser.mjs.map +4 -4
- package/dist/esm/generated/precompiled-validators.js +2324 -1525
- package/dist/esm/generated/precompiled-validators.js.map +1 -1
- package/dist/esm/src/core/constants.js +50 -0
- package/dist/esm/src/core/constants.js.map +1 -1
- package/dist/esm/src/core/dwn-error.js +29 -11
- package/dist/esm/src/core/dwn-error.js.map +1 -1
- package/dist/esm/src/core/encryption-control.js +785 -0
- package/dist/esm/src/core/encryption-control.js.map +1 -0
- package/dist/esm/src/core/message.js +6 -0
- package/dist/esm/src/core/message.js.map +1 -1
- package/dist/esm/src/core/messages-grant-authorization.js +36 -5
- package/dist/esm/src/core/messages-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization-action.js +3 -12
- package/dist/esm/src/core/protocol-authorization-action.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization-validation.js +31 -30
- package/dist/esm/src/core/protocol-authorization-validation.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization.js +6 -0
- package/dist/esm/src/core/protocol-authorization.js.map +1 -1
- package/dist/esm/src/core/recording-validation-state-reader.js +3 -3
- package/dist/esm/src/core/recording-validation-state-reader.js.map +1 -1
- package/dist/esm/src/core/replication-apply.js +62 -108
- package/dist/esm/src/core/replication-apply.js.map +1 -1
- package/dist/esm/src/core/validation-state-reader.js +5 -6
- package/dist/esm/src/core/validation-state-reader.js.map +1 -1
- package/dist/esm/src/dwn.js +1 -2
- package/dist/esm/src/dwn.js.map +1 -1
- package/dist/esm/src/event-stream/event-emitter-wake-publisher.js +11 -11
- package/dist/esm/src/event-stream/event-emitter-wake-publisher.js.map +1 -1
- package/dist/esm/src/handlers/messages-query.js +6 -16
- package/dist/esm/src/handlers/messages-query.js.map +1 -1
- package/dist/esm/src/handlers/messages-read.js +4 -3
- package/dist/esm/src/handlers/messages-read.js.map +1 -1
- package/dist/esm/src/handlers/messages-subscribe.js +26 -30
- package/dist/esm/src/handlers/messages-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/protocols-configure.js +6 -4
- package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
- package/dist/esm/src/handlers/records-count.js +85 -10
- package/dist/esm/src/handlers/records-count.js.map +1 -1
- package/dist/esm/src/handlers/records-delete.js +11 -0
- package/dist/esm/src/handlers/records-delete.js.map +1 -1
- package/dist/esm/src/handlers/records-query.js +140 -18
- package/dist/esm/src/handlers/records-query.js.map +1 -1
- package/dist/esm/src/handlers/records-read.js +20 -4
- package/dist/esm/src/handlers/records-read.js.map +1 -1
- package/dist/esm/src/handlers/records-subscribe.js +127 -11
- package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/records-write.js +15 -0
- package/dist/esm/src/handlers/records-write.js.map +1 -1
- package/dist/esm/src/index.js +8 -11
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/interfaces/protocols-configure.js +66 -9
- package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
- package/dist/esm/src/interfaces/records-write.js +43 -36
- package/dist/esm/src/interfaces/records-write.js.map +1 -1
- package/dist/esm/src/jose/algorithms/signing/ed25519.js +5 -5
- package/dist/esm/src/jose/algorithms/signing/ed25519.js.map +1 -1
- package/dist/esm/src/jose/jws/general/verifier.js +1 -1
- package/dist/esm/src/jose/jws/general/verifier.js.map +1 -1
- package/dist/esm/src/protocols/encryption.js +60 -270
- package/dist/esm/src/protocols/encryption.js.map +1 -1
- package/dist/esm/src/store/blockstore-level.js +14 -23
- package/dist/esm/src/store/blockstore-level.js.map +1 -1
- package/dist/esm/src/store/blockstore-mock.js +10 -27
- package/dist/esm/src/store/blockstore-mock.js.map +1 -1
- package/dist/esm/src/store/blockstore-utils.js +45 -0
- package/dist/esm/src/store/blockstore-utils.js.map +1 -0
- package/dist/esm/src/store/blockstore.js +2 -0
- package/dist/esm/src/store/blockstore.js.map +1 -0
- package/dist/esm/src/store/data-store-level.js +4 -12
- package/dist/esm/src/store/data-store-level.js.map +1 -1
- package/dist/esm/src/store/level.js +7 -0
- package/dist/esm/src/store/level.js.map +1 -0
- package/dist/esm/src/types/encryption-types.js +4 -1
- package/dist/esm/src/types/encryption-types.js.map +1 -1
- package/dist/esm/src/utils/data-stream.js +25 -0
- package/dist/esm/src/utils/data-stream.js.map +1 -1
- package/dist/esm/src/utils/encryption.js +107 -19
- package/dist/esm/src/utils/encryption.js.map +1 -1
- package/dist/esm/src/utils/grant-key-coverage.js +180 -0
- package/dist/esm/src/utils/grant-key-coverage.js.map +1 -0
- package/dist/esm/src/utils/hd-key.js +1 -2
- package/dist/esm/src/utils/hd-key.js.map +1 -1
- package/dist/esm/src/utils/jws.js +7 -1
- package/dist/esm/src/utils/jws.js.map +1 -1
- package/dist/esm/src/utils/memory-cache.js +29 -8
- package/dist/esm/src/utils/memory-cache.js.map +1 -1
- package/dist/esm/src/utils/protocols.js +27 -0
- package/dist/esm/src/utils/protocols.js.map +1 -1
- package/dist/esm/src/utils/record-limit-occupancy.js +23 -3
- package/dist/esm/src/utils/record-limit-occupancy.js.map +1 -1
- package/dist/esm/src/utils/records.js +29 -0
- package/dist/esm/src/utils/records.js.map +1 -1
- package/dist/esm/src/utils/secp256k1.js +12 -11
- package/dist/esm/src/utils/secp256k1.js.map +1 -1
- package/dist/esm/src/utils/secp256r1.js +12 -20
- package/dist/esm/src/utils/secp256r1.js.map +1 -1
- package/dist/esm/src/utils/time.js +103 -25
- package/dist/esm/src/utils/time.js.map +1 -1
- package/dist/esm/tests/core/constants.spec.js +35 -0
- package/dist/esm/tests/core/constants.spec.js.map +1 -0
- package/dist/esm/tests/core/encryption-control.spec.js +100 -0
- package/dist/esm/tests/core/encryption-control.spec.js.map +1 -0
- package/dist/esm/tests/core/message.spec.js +35 -0
- package/dist/esm/tests/core/message.spec.js.map +1 -1
- package/dist/esm/tests/core/protocol-authorization.spec.js +1 -1
- package/dist/esm/tests/core/protocol-authorization.spec.js.map +1 -1
- package/dist/esm/tests/core/replication-apply.spec.js +157 -74
- package/dist/esm/tests/core/replication-apply.spec.js.map +1 -1
- package/dist/esm/tests/core/replication-replay-property.spec.js +2 -1
- package/dist/esm/tests/core/replication-replay-property.spec.js.map +1 -1
- package/dist/esm/tests/core/validation-read-closure.spec.js +14 -28
- package/dist/esm/tests/core/validation-read-closure.spec.js.map +1 -1
- package/dist/esm/tests/core/validation-state-reader.spec.js +19 -23
- package/dist/esm/tests/core/validation-state-reader.spec.js.map +1 -1
- package/dist/esm/tests/dwn.spec.js +2 -1
- package/dist/esm/tests/dwn.spec.js.map +1 -1
- package/dist/esm/tests/event-emitter-wake-publisher.spec.js +51 -0
- package/dist/esm/tests/event-emitter-wake-publisher.spec.js.map +1 -0
- package/dist/esm/tests/features/protocol-composition.spec.js +1 -1
- package/dist/esm/tests/features/protocol-composition.spec.js.map +1 -1
- package/dist/esm/tests/features/records-record-limit.spec.js +1 -1
- package/dist/esm/tests/features/records-record-limit.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/encryption.fuzz.spec.js +9 -1
- package/dist/esm/tests/fuzz/encryption.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/process-message.fuzz.spec.js +1 -1
- package/dist/esm/tests/fuzz/process-message.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/protocols-utils.fuzz.spec.js +29 -1
- package/dist/esm/tests/fuzz/protocols-utils.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/secp256k1.fuzz.spec.js +2 -2
- package/dist/esm/tests/fuzz/secp256k1.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/time.fuzz.spec.js +7 -1
- package/dist/esm/tests/fuzz/time.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-query.spec.js +123 -11
- package/dist/esm/tests/handlers/messages-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-read.spec.js +95 -0
- package/dist/esm/tests/handlers/messages-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-subscribe.spec.js +90 -0
- package/dist/esm/tests/handlers/messages-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/protocols-configure.spec.js +66 -0
- package/dist/esm/tests/handlers/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-count.spec.js +370 -0
- package/dist/esm/tests/handlers/records-count.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-delete.spec.js +70 -1
- package/dist/esm/tests/handlers/records-delete.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-query.spec.js +562 -1
- package/dist/esm/tests/handlers/records-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-read.spec.js +140 -2
- package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js +241 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-write.spec.js +1187 -29
- package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/protocols-configure.spec.js +290 -2
- package/dist/esm/tests/interfaces/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-write.spec.js +47 -5
- package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
- package/dist/esm/tests/protocols/encryption.spec.js +187 -452
- package/dist/esm/tests/protocols/encryption.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js +13 -27
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js.map +1 -1
- package/dist/esm/tests/store/blockstore-level.spec.js +33 -10
- package/dist/esm/tests/store/blockstore-level.spec.js.map +1 -1
- package/dist/esm/tests/store/blockstore-mock.spec.js +31 -7
- package/dist/esm/tests/store/blockstore-mock.spec.js.map +1 -1
- package/dist/esm/tests/store/blockstore-utils.spec.js +115 -0
- package/dist/esm/tests/store/blockstore-utils.spec.js.map +1 -0
- package/dist/esm/tests/store/index-level.spec.js +3 -3
- package/dist/esm/tests/store/index-level.spec.js.map +1 -1
- package/dist/esm/tests/test-stores.js +2 -1
- package/dist/esm/tests/test-stores.js.map +1 -1
- package/dist/esm/tests/utils/cid.spec.js +15 -0
- package/dist/esm/tests/utils/cid.spec.js.map +1 -1
- package/dist/esm/tests/utils/data-stream.spec.js +30 -0
- package/dist/esm/tests/utils/data-stream.spec.js.map +1 -1
- package/dist/esm/tests/utils/encryption-control-test-utils.js +111 -0
- package/dist/esm/tests/utils/encryption-control-test-utils.js.map +1 -0
- package/dist/esm/tests/utils/encryption.spec.js +198 -5
- package/dist/esm/tests/utils/encryption.spec.js.map +1 -1
- package/dist/esm/tests/utils/grant-key-coverage.spec.js +262 -0
- package/dist/esm/tests/utils/grant-key-coverage.spec.js.map +1 -0
- package/dist/esm/tests/utils/memory-cache.spec.js +12 -0
- package/dist/esm/tests/utils/memory-cache.spec.js.map +1 -1
- package/dist/esm/tests/utils/secp256r1.spec.js +2 -2
- package/dist/esm/tests/utils/secp256r1.spec.js.map +1 -1
- package/dist/esm/tests/utils/test-data-generator.js +2 -1
- package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
- package/dist/esm/tests/utils/test-validation-state-reader.js +1 -1
- package/dist/esm/tests/utils/test-validation-state-reader.js.map +1 -1
- package/dist/esm/tests/utils/time.spec.js +26 -0
- package/dist/esm/tests/utils/time.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/encryption/audience.spec.js +45 -0
- package/dist/esm/tests/validation/json-schemas/encryption/audience.spec.js.map +1 -0
- package/dist/esm/tests/validation/json-schemas/encryption/delivery.spec.js +47 -0
- package/dist/esm/tests/validation/json-schemas/encryption/delivery.spec.js.map +1 -0
- package/dist/esm/tests/validation/json-schemas/encryption/wrapped-grant-key-envelope.spec.js +43 -0
- package/dist/esm/tests/validation/json-schemas/encryption/wrapped-grant-key-envelope.spec.js.map +1 -0
- package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js +152 -0
- package/dist/esm/tests/validation/json-schemas/protocols/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js +46 -1
- package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js.map +1 -1
- package/dist/types/generated/precompiled-validators.d.ts +20 -4
- package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
- package/dist/types/src/core/constants.d.ts +39 -0
- package/dist/types/src/core/constants.d.ts.map +1 -1
- package/dist/types/src/core/dwn-error.d.ts +29 -11
- package/dist/types/src/core/dwn-error.d.ts.map +1 -1
- package/dist/types/src/core/encryption-control.d.ts +128 -0
- package/dist/types/src/core/encryption-control.d.ts.map +1 -0
- package/dist/types/src/core/message.d.ts +4 -0
- package/dist/types/src/core/message.d.ts.map +1 -1
- package/dist/types/src/core/messages-grant-authorization.d.ts +11 -0
- package/dist/types/src/core/messages-grant-authorization.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization-action.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization-validation.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization.d.ts.map +1 -1
- package/dist/types/src/core/recording-validation-state-reader.d.ts +2 -3
- package/dist/types/src/core/recording-validation-state-reader.d.ts.map +1 -1
- package/dist/types/src/core/replication-apply.d.ts +10 -1
- package/dist/types/src/core/replication-apply.d.ts.map +1 -1
- package/dist/types/src/core/validation-state-reader.d.ts +2 -3
- package/dist/types/src/core/validation-state-reader.d.ts.map +1 -1
- package/dist/types/src/dwn.d.ts.map +1 -1
- package/dist/types/src/event-stream/event-emitter-wake-publisher.d.ts +1 -1
- package/dist/types/src/event-stream/event-emitter-wake-publisher.d.ts.map +1 -1
- package/dist/types/src/handlers/messages-query.d.ts.map +1 -1
- package/dist/types/src/handlers/messages-read.d.ts.map +1 -1
- package/dist/types/src/handlers/messages-subscribe.d.ts.map +1 -1
- package/dist/types/src/handlers/protocols-configure.d.ts +1 -0
- package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/handlers/records-count.d.ts +2 -0
- package/dist/types/src/handlers/records-count.d.ts.map +1 -1
- package/dist/types/src/handlers/records-delete.d.ts.map +1 -1
- package/dist/types/src/handlers/records-query.d.ts +3 -0
- package/dist/types/src/handlers/records-query.d.ts.map +1 -1
- package/dist/types/src/handlers/records-read.d.ts.map +1 -1
- package/dist/types/src/handlers/records-subscribe.d.ts +2 -0
- package/dist/types/src/handlers/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/handlers/records-write.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +12 -18
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/interfaces/protocols-configure.d.ts +13 -1
- package/dist/types/src/interfaces/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-write.d.ts +5 -1
- package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
- package/dist/types/src/jose/algorithms/signing/ed25519.d.ts.map +1 -1
- package/dist/types/src/protocols/encryption.d.ts +15 -19
- package/dist/types/src/protocols/encryption.d.ts.map +1 -1
- package/dist/types/src/store/blockstore-level.d.ts +11 -11
- package/dist/types/src/store/blockstore-level.d.ts.map +1 -1
- package/dist/types/src/store/blockstore-mock.d.ts +12 -12
- package/dist/types/src/store/blockstore-mock.d.ts.map +1 -1
- package/dist/types/src/store/blockstore-utils.d.ts +23 -0
- package/dist/types/src/store/blockstore-utils.d.ts.map +1 -0
- package/dist/types/src/store/blockstore.d.ts +3 -0
- package/dist/types/src/store/blockstore.d.ts.map +1 -0
- package/dist/types/src/store/data-store-level.d.ts.map +1 -1
- package/dist/types/src/store/level.d.ts +13 -0
- package/dist/types/src/store/level.d.ts.map +1 -0
- package/dist/types/src/types/cache.d.ts +2 -2
- package/dist/types/src/types/cache.d.ts.map +1 -1
- package/dist/types/src/types/encryption-types.d.ts +31 -2
- package/dist/types/src/types/encryption-types.d.ts.map +1 -1
- package/dist/types/src/types/validation-state-reader.d.ts +3 -5
- package/dist/types/src/types/validation-state-reader.d.ts.map +1 -1
- package/dist/types/src/utils/data-stream.d.ts +5 -0
- package/dist/types/src/utils/data-stream.d.ts.map +1 -1
- package/dist/types/src/utils/encryption.d.ts +53 -24
- package/dist/types/src/utils/encryption.d.ts.map +1 -1
- package/dist/types/src/utils/grant-key-coverage.d.ts +36 -0
- package/dist/types/src/utils/grant-key-coverage.d.ts.map +1 -0
- package/dist/types/src/utils/hd-key.d.ts.map +1 -1
- package/dist/types/src/utils/jws.d.ts.map +1 -1
- package/dist/types/src/utils/memory-cache.d.ts +4 -2
- package/dist/types/src/utils/memory-cache.d.ts.map +1 -1
- package/dist/types/src/utils/protocols.d.ts +11 -0
- package/dist/types/src/utils/protocols.d.ts.map +1 -1
- package/dist/types/src/utils/record-limit-occupancy.d.ts +7 -0
- package/dist/types/src/utils/record-limit-occupancy.d.ts.map +1 -1
- package/dist/types/src/utils/records.d.ts +2 -0
- package/dist/types/src/utils/records.d.ts.map +1 -1
- package/dist/types/src/utils/secp256k1.d.ts.map +1 -1
- package/dist/types/src/utils/secp256r1.d.ts.map +1 -1
- package/dist/types/src/utils/time.d.ts +21 -13
- package/dist/types/src/utils/time.d.ts.map +1 -1
- package/dist/types/tests/core/constants.spec.d.ts +2 -0
- package/dist/types/tests/core/constants.spec.d.ts.map +1 -0
- package/dist/types/tests/core/encryption-control.spec.d.ts +2 -0
- package/dist/types/tests/core/encryption-control.spec.d.ts.map +1 -0
- package/dist/types/tests/dwn.spec.d.ts.map +1 -1
- package/dist/types/tests/event-emitter-wake-publisher.spec.d.ts +2 -0
- package/dist/types/tests/event-emitter-wake-publisher.spec.d.ts.map +1 -0
- package/dist/types/tests/handlers/messages-query.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/messages-read.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/messages-subscribe.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/protocols-configure.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-count.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-delete.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-query.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-read.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-subscribe.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-write.spec.d.ts.map +1 -1
- package/dist/types/tests/scenarios/end-to-end-tests.spec.d.ts.map +1 -1
- package/dist/types/tests/store/blockstore-utils.spec.d.ts +2 -0
- package/dist/types/tests/store/blockstore-utils.spec.d.ts.map +1 -0
- package/dist/types/tests/test-stores.d.ts.map +1 -1
- package/dist/types/tests/utils/encryption-control-test-utils.d.ts +46 -0
- package/dist/types/tests/utils/encryption-control-test-utils.d.ts.map +1 -0
- package/dist/types/tests/utils/grant-key-coverage.spec.d.ts +2 -0
- package/dist/types/tests/utils/grant-key-coverage.spec.d.ts.map +1 -0
- package/dist/types/tests/utils/test-data-generator.d.ts.map +1 -1
- package/dist/types/tests/validation/json-schemas/encryption/audience.spec.d.ts +2 -0
- package/dist/types/tests/validation/json-schemas/encryption/audience.spec.d.ts.map +1 -0
- package/dist/types/tests/validation/json-schemas/encryption/delivery.spec.d.ts +2 -0
- package/dist/types/tests/validation/json-schemas/encryption/delivery.spec.d.ts.map +1 -0
- package/dist/types/tests/validation/json-schemas/encryption/wrapped-grant-key-envelope.spec.d.ts +2 -0
- package/dist/types/tests/validation/json-schemas/encryption/wrapped-grant-key-envelope.spec.d.ts.map +1 -0
- package/package.json +47 -28
- package/src/core/constants.ts +61 -0
- package/src/core/dwn-error.ts +29 -11
- package/src/core/encryption-control.ts +1249 -0
- package/src/core/message.ts +7 -0
- package/src/core/messages-grant-authorization.ts +60 -9
- package/src/core/protocol-authorization-action.ts +3 -13
- package/src/core/protocol-authorization-validation.ts +66 -46
- package/src/core/protocol-authorization.ts +7 -0
- package/src/core/recording-validation-state-reader.ts +4 -5
- package/src/core/replication-apply.ts +77 -133
- package/src/core/validation-state-reader.ts +6 -8
- package/src/dwn.ts +1 -2
- package/src/event-stream/event-emitter-wake-publisher.ts +10 -14
- package/src/handlers/messages-query.ts +6 -22
- package/src/handlers/messages-read.ts +4 -3
- package/src/handlers/messages-subscribe.ts +34 -30
- package/src/handlers/protocols-configure.ts +7 -4
- package/src/handlers/records-count.ts +111 -10
- package/src/handlers/records-delete.ts +15 -0
- package/src/handlers/records-query.ts +176 -20
- package/src/handlers/records-read.ts +19 -6
- package/src/handlers/records-subscribe.ts +158 -8
- package/src/handlers/records-write.ts +19 -0
- package/src/index.ts +50 -22
- package/src/interfaces/protocols-configure.ts +102 -11
- package/src/interfaces/records-write.ts +49 -43
- package/src/jose/algorithms/signing/ed25519.ts +7 -6
- package/src/jose/jws/general/verifier.ts +3 -3
- package/src/protocols/encryption.ts +94 -411
- package/src/store/blockstore-level.ts +33 -37
- package/src/store/blockstore-mock.ts +24 -38
- package/src/store/blockstore-utils.ts +85 -0
- package/src/store/blockstore.ts +8 -0
- package/src/store/data-store-level.ts +5 -12
- package/src/store/level.ts +19 -0
- package/src/types/cache.ts +3 -3
- package/src/types/encryption-types.ts +39 -2
- package/src/types/validation-state-reader.ts +3 -5
- package/src/utils/data-stream.ts +29 -1
- package/src/utils/encryption.ts +190 -60
- package/src/utils/grant-key-coverage.ts +303 -0
- package/src/utils/hd-key.ts +1 -2
- package/src/utils/jws.ts +8 -2
- package/src/utils/memory-cache.ts +42 -11
- package/src/utils/protocols.ts +32 -0
- package/src/utils/record-limit-occupancy.ts +34 -5
- package/src/utils/records.ts +36 -2
- package/src/utils/secp256k1.ts +12 -12
- package/src/utils/secp256r1.ts +12 -22
- package/src/utils/time.ts +145 -27
- package/dist/esm/tests/validation/json-schemas/encryption/audience-key.spec.js +0 -40
- package/dist/esm/tests/validation/json-schemas/encryption/audience-key.spec.js.map +0 -1
- package/dist/types/tests/validation/json-schemas/encryption/audience-key.spec.d.ts +0 -2
- package/dist/types/tests/validation/json-schemas/encryption/audience-key.spec.d.ts.map +0 -1
- package/src/types/mitt.d.ts +0 -28
|
@@ -1,95 +1,61 @@
|
|
|
1
1
|
import type { CoreProtocol } from '../core/core-protocol.js';
|
|
2
2
|
import type { Filter } from '../types/query-types.js';
|
|
3
|
-
import type { GenericSignaturePayload } from '../types/message-types.js';
|
|
4
3
|
import type { MessagesFilter } from '../types/messages-types.js';
|
|
5
4
|
import type { PermissionGrant } from './permission-grant.js';
|
|
6
5
|
import type { PermissionScope } from '../types/permission-types.js';
|
|
7
|
-
import type {
|
|
6
|
+
import type { ProtocolDefinition } from '../types/protocols-types.js';
|
|
8
7
|
import type { RecordsWriteMessage } from '../types/records-types.js';
|
|
9
8
|
import type { ValidationStateReader } from '../types/validation-state-reader.js';
|
|
10
|
-
import type {
|
|
9
|
+
import type { ContentEncryptionAlgorithm, X25519KeyEncryptionBase } from '../utils/encryption.js';
|
|
11
10
|
|
|
12
|
-
import {
|
|
11
|
+
import { DwnConstant } from '../core/dwn-constant.js';
|
|
13
12
|
import { Encoder } from '../utils/encoder.js';
|
|
14
|
-
import { Encryption } from '../utils/encryption.js';
|
|
15
13
|
import { ENCRYPTION_PROTOCOL_URI } from '../core/constants.js';
|
|
16
14
|
import { FilterUtility } from '../utils/filter.js';
|
|
17
|
-
import { Jws } from '../utils/jws.js';
|
|
18
15
|
import { Message } from '../core/message.js';
|
|
19
16
|
import { Records } from '../utils/records.js';
|
|
20
17
|
import { validateJsonSchema } from '../schema-validator.js';
|
|
21
18
|
import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
type AudienceTags = {
|
|
27
|
-
protocol: string;
|
|
28
|
-
contextId: string;
|
|
29
|
-
role: string;
|
|
30
|
-
epoch: number;
|
|
31
|
-
keyId: string;
|
|
32
|
-
};
|
|
19
|
+
import { grantKeyScopeCoversDeliveredScope, isGrantKeyEligibleRecordsScope, isGrantKeyRecordsScope } from '../utils/grant-key-coverage.js';
|
|
20
|
+
|
|
21
|
+
export const WRAPPED_GRANT_KEY_FORMAT = 'enbox/wrapped-grant-key@1';
|
|
33
22
|
|
|
34
|
-
type
|
|
35
|
-
|
|
23
|
+
export type WrappedGrantKeyEnvelope = {
|
|
24
|
+
format: typeof WRAPPED_GRANT_KEY_FORMAT;
|
|
25
|
+
keyEncryption: X25519KeyEncryptionBase;
|
|
26
|
+
contentEncryption: {
|
|
27
|
+
algorithm: typeof ContentEncryptionAlgorithm.A256CTR;
|
|
28
|
+
initializationVector: string;
|
|
29
|
+
};
|
|
30
|
+
ciphertext: string;
|
|
36
31
|
};
|
|
37
32
|
|
|
33
|
+
export function assertWrappedGrantKeyEnvelope(envelope: unknown): asserts envelope is WrappedGrantKeyEnvelope {
|
|
34
|
+
try {
|
|
35
|
+
validateJsonSchema('WrappedGrantKeyEnvelope', envelope);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
38
|
+
throw new DwnError(
|
|
39
|
+
DwnErrorCode.EncryptionProtocolValidateGrantKeyWrappedDeliveryInvalid,
|
|
40
|
+
`wrapped grantKey envelope is invalid: ${detail}`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
38
45
|
export class EncryptionProtocol implements CoreProtocol {
|
|
39
46
|
public static readonly uri = ENCRYPTION_PROTOCOL_URI;
|
|
40
|
-
public static readonly audienceEpochPath = 'audienceEpoch';
|
|
41
|
-
public static readonly audienceKeyPath = 'audienceKey';
|
|
42
47
|
public static readonly grantKeyPath = 'grantKey';
|
|
43
48
|
|
|
44
49
|
public static readonly definition: ProtocolDefinition = {
|
|
45
50
|
published : true,
|
|
46
51
|
protocol : EncryptionProtocol.uri,
|
|
47
52
|
types : {
|
|
48
|
-
audienceEpoch: {
|
|
49
|
-
dataFormats : ['application/json'],
|
|
50
|
-
schema : 'https://identity.foundation/dwn/json-schemas/encryption/audience-epoch.json',
|
|
51
|
-
},
|
|
52
|
-
audienceKey: {
|
|
53
|
-
dataFormats : ['application/json'],
|
|
54
|
-
schema : 'https://identity.foundation/dwn/json-schemas/encryption/audience-key.json',
|
|
55
|
-
},
|
|
56
53
|
grantKey: {
|
|
57
54
|
dataFormats : ['application/json'],
|
|
58
55
|
schema : 'https://identity.foundation/dwn/json-schemas/encryption/grant-key.json',
|
|
59
56
|
},
|
|
60
57
|
},
|
|
61
58
|
structure: {
|
|
62
|
-
audienceEpoch: {
|
|
63
|
-
$actions: [
|
|
64
|
-
{ can: ['create', 'read'], who: 'anyone' },
|
|
65
|
-
],
|
|
66
|
-
$immutable : true,
|
|
67
|
-
$tags : {
|
|
68
|
-
$allowUndefinedTags : false,
|
|
69
|
-
$requiredTags : ['protocol', 'contextId', 'role', 'epoch', 'keyId'],
|
|
70
|
-
contextId : { type: 'string' },
|
|
71
|
-
epoch : { minimum: 1, type: 'integer' },
|
|
72
|
-
keyId : { pattern: '^[A-Za-z0-9_-]{43}$', type: 'string' },
|
|
73
|
-
protocol : { type: 'string' },
|
|
74
|
-
role : { type: 'string' },
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
audienceKey: {
|
|
78
|
-
$actions: [
|
|
79
|
-
{ can: ['create'], who: 'anyone' },
|
|
80
|
-
{ can: ['read'], of: 'audienceKey', who: 'recipient' },
|
|
81
|
-
],
|
|
82
|
-
$immutable : true,
|
|
83
|
-
$tags : {
|
|
84
|
-
$allowUndefinedTags : false,
|
|
85
|
-
$requiredTags : ['protocol', 'contextId', 'role', 'epoch', 'keyId'],
|
|
86
|
-
contextId : { type: 'string' },
|
|
87
|
-
epoch : { minimum: 1, type: 'integer' },
|
|
88
|
-
keyId : { pattern: '^[A-Za-z0-9_-]{43}$', type: 'string' },
|
|
89
|
-
protocol : { type: 'string' },
|
|
90
|
-
role : { type: 'string' },
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
59
|
grantKey: {
|
|
94
60
|
$actions: [
|
|
95
61
|
{ can: ['create'], who: 'anyone' },
|
|
@@ -121,119 +87,21 @@ export class EncryptionProtocol implements CoreProtocol {
|
|
|
121
87
|
message: RecordsWriteMessage,
|
|
122
88
|
validationStateReader: ValidationStateReader,
|
|
123
89
|
): Promise<void> {
|
|
124
|
-
|
|
125
|
-
case EncryptionProtocol.audienceEpochPath:
|
|
126
|
-
await EncryptionProtocol.preProcessAudienceEpoch(tenant, message, validationStateReader);
|
|
127
|
-
return;
|
|
128
|
-
case EncryptionProtocol.audienceKeyPath:
|
|
129
|
-
await EncryptionProtocol.preProcessAudienceKey(tenant, message, validationStateReader);
|
|
130
|
-
return;
|
|
131
|
-
case EncryptionProtocol.grantKeyPath:
|
|
90
|
+
if (message.descriptor.protocolPath === EncryptionProtocol.grantKeyPath) {
|
|
132
91
|
await EncryptionProtocol.preProcessGrantKey(tenant, message, validationStateReader);
|
|
133
|
-
return;
|
|
134
|
-
default:
|
|
135
|
-
return;
|
|
136
92
|
}
|
|
137
93
|
}
|
|
138
94
|
|
|
139
95
|
public async validateRecord(message: RecordsWriteMessage, dataBytes: Uint8Array): Promise<void> {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
await EncryptionProtocol.validateAudienceEpoch(message, dataBytes);
|
|
143
|
-
return;
|
|
144
|
-
case EncryptionProtocol.audienceKeyPath:
|
|
145
|
-
case EncryptionProtocol.grantKeyPath:
|
|
146
|
-
EncryptionProtocol.verifyEncryptedDelivery(message);
|
|
96
|
+
if (message.descriptor.protocolPath === EncryptionProtocol.grantKeyPath) {
|
|
97
|
+
EncryptionProtocol.verifyGrantKeyDelivery(message, dataBytes);
|
|
147
98
|
return;
|
|
148
|
-
default:
|
|
149
|
-
throw new DwnError(
|
|
150
|
-
DwnErrorCode.EncryptionProtocolValidateSchemaUnexpectedRecord,
|
|
151
|
-
`Unexpected encryption record: ${message.descriptor.protocolPath}`
|
|
152
|
-
);
|
|
153
99
|
}
|
|
154
|
-
}
|
|
155
100
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
): Promise<void> {
|
|
161
|
-
if (message.encryption !== undefined) {
|
|
162
|
-
throw new DwnError(
|
|
163
|
-
DwnErrorCode.EncryptionProtocolValidateAudienceEpochEncrypted,
|
|
164
|
-
'audienceEpoch records must be plaintext.'
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const tags = EncryptionProtocol.getAudienceTags(message, 'audienceEpoch');
|
|
169
|
-
const { ruleSet, protocolDefinition } = await EncryptionProtocol.verifyRoleAudienceDefinition(tenant, tags, message, validationStateReader);
|
|
170
|
-
await EncryptionProtocol.verifyWriterCanCreateRole({
|
|
171
|
-
tenant,
|
|
172
|
-
message,
|
|
173
|
-
tags,
|
|
174
|
-
ruleSet,
|
|
175
|
-
protocolDefinition,
|
|
176
|
-
validationStateReader,
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
private static async preProcessAudienceKey(
|
|
182
|
-
tenant: string,
|
|
183
|
-
message: RecordsWriteMessage,
|
|
184
|
-
validationStateReader: ValidationStateReader,
|
|
185
|
-
): Promise<void> {
|
|
186
|
-
EncryptionProtocol.verifyEncryptedDelivery(message);
|
|
187
|
-
|
|
188
|
-
const recipient = message.descriptor.recipient;
|
|
189
|
-
if (recipient === undefined) {
|
|
190
|
-
throw new DwnError(
|
|
191
|
-
DwnErrorCode.EncryptionProtocolValidateAudienceKeyRecipientMissing,
|
|
192
|
-
'audienceKey records must have a recipient.'
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const tags = EncryptionProtocol.getAudienceTags(message, 'audienceKey');
|
|
197
|
-
const { ruleSet, protocolDefinition } = await EncryptionProtocol.verifyRoleAudienceDefinition(tenant, tags, message, validationStateReader);
|
|
198
|
-
await EncryptionProtocol.verifyWriterCanCreateRole({
|
|
199
|
-
tenant,
|
|
200
|
-
message,
|
|
201
|
-
tags,
|
|
202
|
-
ruleSet,
|
|
203
|
-
protocolDefinition,
|
|
204
|
-
validationStateReader,
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
const matchingEpochs = await validationStateReader.queryAudienceEpochs({
|
|
208
|
-
tenant,
|
|
209
|
-
protocol : tags.protocol,
|
|
210
|
-
contextId : tags.contextId,
|
|
211
|
-
role : tags.role,
|
|
212
|
-
epoch : tags.epoch,
|
|
213
|
-
keyId : tags.keyId,
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
if (matchingEpochs.length === 0) {
|
|
217
|
-
throw new DwnError(
|
|
218
|
-
DwnErrorCode.EncryptionProtocolValidateAudienceEpochMissing,
|
|
219
|
-
'audienceKey references a missing audienceEpoch.'
|
|
220
|
-
);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
const hasRoleRecord = await validationStateReader.hasMatchingRoleRecord({
|
|
224
|
-
tenant,
|
|
225
|
-
protocol : tags.protocol,
|
|
226
|
-
protocolPath : tags.role,
|
|
227
|
-
recipient,
|
|
228
|
-
contextIdPrefix : tags.contextId === '' ? undefined : tags.contextId,
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
if (!hasRoleRecord) {
|
|
232
|
-
throw new DwnError(
|
|
233
|
-
DwnErrorCode.EncryptionProtocolValidateAudienceKeyRoleRecordMissing,
|
|
234
|
-
'audienceKey recipient is not an active holder of the referenced role.'
|
|
235
|
-
);
|
|
236
|
-
}
|
|
101
|
+
throw new DwnError(
|
|
102
|
+
DwnErrorCode.EncryptionProtocolValidateSchemaUnexpectedRecord,
|
|
103
|
+
`Unexpected encryption record: ${message.descriptor.protocolPath}`
|
|
104
|
+
);
|
|
237
105
|
}
|
|
238
106
|
|
|
239
107
|
private static async preProcessGrantKey(
|
|
@@ -241,7 +109,7 @@ export class EncryptionProtocol implements CoreProtocol {
|
|
|
241
109
|
message: RecordsWriteMessage,
|
|
242
110
|
validationStateReader: ValidationStateReader,
|
|
243
111
|
): Promise<void> {
|
|
244
|
-
EncryptionProtocol.
|
|
112
|
+
EncryptionProtocol.verifyInlineWrappedGrantKeyDelivery(message);
|
|
245
113
|
|
|
246
114
|
const grantId = EncryptionProtocol.getRequiredStringTag(message, 'grantId');
|
|
247
115
|
const protocol = EncryptionProtocol.getRequiredStringTag(message, 'protocol');
|
|
@@ -252,91 +120,62 @@ export class EncryptionProtocol implements CoreProtocol {
|
|
|
252
120
|
await EncryptionProtocol.verifyGrantActive(tenant, message, grant, validationStateReader);
|
|
253
121
|
EncryptionProtocol.verifyGrantKeyAuthor(message, grant);
|
|
254
122
|
EncryptionProtocol.verifyGrantKeyRecipient(message, grant);
|
|
255
|
-
EncryptionProtocol.verifyGrantKeyScope(
|
|
123
|
+
await EncryptionProtocol.verifyGrantKeyScope({
|
|
124
|
+
tenant,
|
|
125
|
+
message,
|
|
126
|
+
grantScope: grant.scope,
|
|
127
|
+
protocol,
|
|
128
|
+
protocolPath,
|
|
129
|
+
validationStateReader,
|
|
130
|
+
});
|
|
256
131
|
}
|
|
257
132
|
|
|
258
|
-
private static
|
|
259
|
-
if (message.encryption
|
|
133
|
+
private static verifyInlineWrappedGrantKeyDelivery(message: RecordsWriteMessage): void {
|
|
134
|
+
if (message.encryption !== undefined) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (message.descriptor.dataSize > DwnConstant.maxDataSizeAllowedToBeEncoded) {
|
|
260
139
|
throw new DwnError(
|
|
261
140
|
DwnErrorCode.EncryptionProtocolValidateEncryptedDeliveryMissingEncryption,
|
|
262
|
-
|
|
141
|
+
'plaintext grantKey records must carry an inline wrapped grantKey envelope.'
|
|
263
142
|
);
|
|
264
143
|
}
|
|
265
144
|
}
|
|
266
145
|
|
|
267
|
-
private static
|
|
146
|
+
private static verifyGrantKeyDelivery(message: RecordsWriteMessage, dataBytes: Uint8Array): void {
|
|
268
147
|
if (message.encryption !== undefined) {
|
|
269
|
-
|
|
270
|
-
DwnErrorCode.EncryptionProtocolValidateAudienceEpochEncrypted,
|
|
271
|
-
'audienceEpoch records must be plaintext.'
|
|
272
|
-
);
|
|
148
|
+
return;
|
|
273
149
|
}
|
|
274
150
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
if (keyId !== dataObject.keyId) {
|
|
283
|
-
throw new DwnError(
|
|
284
|
-
DwnErrorCode.EncryptionProtocolValidateAudienceEpochKeyIdMismatch,
|
|
285
|
-
'audienceEpoch keyId must match publicKeyJwk thumbprint.'
|
|
286
|
-
);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
151
|
+
try {
|
|
152
|
+
const envelope = Encoder.bytesToObject(dataBytes);
|
|
153
|
+
assertWrappedGrantKeyEnvelope(envelope);
|
|
154
|
+
} catch (error) {
|
|
155
|
+
if (error instanceof DwnError) {
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
289
158
|
|
|
290
|
-
|
|
291
|
-
if (payload.protocol !== tags.protocol ||
|
|
292
|
-
payload.contextId !== tags.contextId ||
|
|
293
|
-
payload.role !== tags.role ||
|
|
294
|
-
payload.epoch !== tags.epoch ||
|
|
295
|
-
payload.keyId !== tags.keyId) {
|
|
159
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
296
160
|
throw new DwnError(
|
|
297
|
-
DwnErrorCode.
|
|
298
|
-
|
|
161
|
+
DwnErrorCode.EncryptionProtocolValidateEncryptedDeliveryMissingEncryption,
|
|
162
|
+
`${message.descriptor.protocolPath} records must be encrypted or carry a valid wrapped grantKey envelope: ${detail}`
|
|
299
163
|
);
|
|
300
164
|
}
|
|
301
165
|
}
|
|
302
166
|
|
|
303
|
-
private static getRequiredStringTag(message: RecordsWriteMessage, tag: string
|
|
167
|
+
private static getRequiredStringTag(message: RecordsWriteMessage, tag: string): string {
|
|
304
168
|
const value = message.descriptor.tags?.[tag];
|
|
305
169
|
if (typeof value !== 'string') {
|
|
306
|
-
const errorCode = recordType === 'grantKey'
|
|
307
|
-
? DwnErrorCode.EncryptionProtocolValidateGrantKeyMissingRequiredTag
|
|
308
|
-
: DwnErrorCode.EncryptionProtocolValidateAudienceMissingRequiredTag;
|
|
309
170
|
throw new DwnError(
|
|
310
|
-
|
|
311
|
-
|
|
171
|
+
DwnErrorCode.EncryptionProtocolValidateGrantKeyMissingRequiredTag,
|
|
172
|
+
`grantKey records must include string tag '${tag}'.`
|
|
312
173
|
);
|
|
313
174
|
}
|
|
314
175
|
|
|
315
176
|
return value;
|
|
316
177
|
}
|
|
317
178
|
|
|
318
|
-
private static getRequiredIntegerTag(message: RecordsWriteMessage, tag: string, recordType: string): number {
|
|
319
|
-
const value = message.descriptor.tags?.[tag];
|
|
320
|
-
if (!Number.isInteger(value)) {
|
|
321
|
-
throw new DwnError(
|
|
322
|
-
DwnErrorCode.EncryptionProtocolValidateAudienceMissingRequiredTag,
|
|
323
|
-
`${recordType} records must include integer tag '${tag}'.`
|
|
324
|
-
);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
return value as number;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
private static getAudienceTags(message: RecordsWriteMessage, recordType: string): AudienceTags {
|
|
331
|
-
return {
|
|
332
|
-
protocol : EncryptionProtocol.getRequiredStringTag(message, 'protocol', recordType),
|
|
333
|
-
contextId : EncryptionProtocol.getRequiredStringTag(message, 'contextId', recordType),
|
|
334
|
-
role : EncryptionProtocol.getRequiredStringTag(message, 'role', recordType),
|
|
335
|
-
epoch : EncryptionProtocol.getRequiredIntegerTag(message, 'epoch', recordType),
|
|
336
|
-
keyId : EncryptionProtocol.getRequiredStringTag(message, 'keyId', recordType),
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
|
|
340
179
|
private static getOptionalStringTag(message: RecordsWriteMessage, tag: string): string | undefined {
|
|
341
180
|
const value = message.descriptor.tags?.[tag];
|
|
342
181
|
if (value === undefined) {
|
|
@@ -405,220 +244,64 @@ export class EncryptionProtocol implements CoreProtocol {
|
|
|
405
244
|
);
|
|
406
245
|
}
|
|
407
246
|
|
|
408
|
-
private static verifyGrantKeyScope(
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
247
|
+
private static async verifyGrantKeyScope(params: {
|
|
248
|
+
tenant: string;
|
|
249
|
+
message: RecordsWriteMessage;
|
|
250
|
+
grantScope: PermissionScope;
|
|
251
|
+
protocol: string;
|
|
252
|
+
protocolPath: string | undefined;
|
|
253
|
+
validationStateReader: ValidationStateReader;
|
|
254
|
+
}): Promise<void> {
|
|
255
|
+
const { grantScope, protocol, protocolPath } = params;
|
|
415
256
|
|
|
416
|
-
if (
|
|
257
|
+
if (!isGrantKeyRecordsScope(grantScope)) {
|
|
417
258
|
throw new DwnError(
|
|
418
259
|
DwnErrorCode.EncryptionProtocolValidateGrantKeyGrantScopeMismatch,
|
|
419
|
-
|
|
260
|
+
'grantKey must reference a Records.Read or Records.Write permission grant.'
|
|
420
261
|
);
|
|
421
262
|
}
|
|
422
263
|
|
|
423
|
-
if (!(
|
|
424
|
-
return;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
if (protocolPath === undefined || !EncryptionProtocol.isBoundaryAwareSubtree(grantScope.protocolPath, protocolPath)) {
|
|
264
|
+
if (!isGrantKeyEligibleRecordsScope(grantScope)) {
|
|
428
265
|
throw new DwnError(
|
|
429
266
|
DwnErrorCode.EncryptionProtocolValidateGrantKeyGrantScopeMismatch,
|
|
430
|
-
|
|
267
|
+
'grantKey must not reference a context-scoped permission grant.'
|
|
431
268
|
);
|
|
432
269
|
}
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
private static isReadScope(scope: PermissionScope): boolean {
|
|
436
|
-
return (scope.interface === DwnInterfaceName.Records || scope.interface === DwnInterfaceName.Messages) &&
|
|
437
|
-
scope.method === DwnMethodName.Read;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
private static isBoundaryAwareSubtree(scopePath: string, candidatePath: string): boolean {
|
|
441
|
-
return candidatePath === scopePath || candidatePath.startsWith(scopePath + '/');
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
private static async verifyRoleAudienceDefinition(
|
|
445
|
-
tenant: string,
|
|
446
|
-
tags: AudienceTags,
|
|
447
|
-
message: RecordsWriteMessage,
|
|
448
|
-
validationStateReader: ValidationStateReader,
|
|
449
|
-
): Promise<{ protocolDefinition: ProtocolDefinition; ruleSet: ProtocolRuleSet }> {
|
|
450
|
-
EncryptionProtocol.verifyRoleAudienceContext(tags.role, tags.contextId);
|
|
451
|
-
|
|
452
|
-
const protocolDefinition = await validationStateReader.fetchProtocolDefinition(
|
|
453
|
-
tenant,
|
|
454
|
-
tags.protocol,
|
|
455
|
-
message.descriptor.messageTimestamp,
|
|
456
|
-
);
|
|
457
|
-
const ruleSet = getRuleSetAtPath(tags.role, protocolDefinition.structure);
|
|
458
270
|
|
|
459
|
-
if (
|
|
271
|
+
if (grantScope.protocol !== protocol) {
|
|
460
272
|
throw new DwnError(
|
|
461
|
-
DwnErrorCode.
|
|
462
|
-
`
|
|
463
|
-
);
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
return { protocolDefinition, ruleSet };
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
private static verifyRoleAudienceContext(rolePath: string, contextId: string): void {
|
|
470
|
-
const parentDepth = rolePath.split('/').length - 1;
|
|
471
|
-
if ((parentDepth === 0 && contextId !== '') || (parentDepth > 0 && contextId === '')) {
|
|
472
|
-
throw new DwnError(
|
|
473
|
-
DwnErrorCode.EncryptionProtocolValidateRoleAudienceContextInvalid,
|
|
474
|
-
'role audience contextId is inconsistent with role path depth.'
|
|
273
|
+
DwnErrorCode.EncryptionProtocolValidateGrantKeyGrantScopeMismatch,
|
|
274
|
+
`grantKey protocol ${protocol} is outside the permission grant scope.`
|
|
475
275
|
);
|
|
476
276
|
}
|
|
477
|
-
}
|
|
478
277
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
message: RecordsWriteMessage;
|
|
482
|
-
tags: AudienceTags;
|
|
483
|
-
ruleSet: ProtocolRuleSet;
|
|
484
|
-
protocolDefinition: ProtocolDefinition;
|
|
485
|
-
validationStateReader: ValidationStateReader;
|
|
486
|
-
}): Promise<void> {
|
|
487
|
-
const author = Message.getAuthor(input.message);
|
|
488
|
-
if (author === input.tenant) {
|
|
278
|
+
const deliveredScope = { protocol, protocolPath };
|
|
279
|
+
if (grantKeyScopeCoversDeliveredScope({ grantScope, deliveredScope })) {
|
|
489
280
|
return;
|
|
490
281
|
}
|
|
491
282
|
|
|
492
|
-
if (
|
|
283
|
+
if (protocolPath === undefined) {
|
|
493
284
|
throw new DwnError(
|
|
494
|
-
DwnErrorCode.
|
|
495
|
-
|
|
285
|
+
DwnErrorCode.EncryptionProtocolValidateGrantKeyGrantScopeMismatch,
|
|
286
|
+
`grantKey protocolPath ${protocolPath ?? '<protocol>'} is outside the permission grant scope.`
|
|
496
287
|
);
|
|
497
288
|
}
|
|
498
289
|
|
|
499
|
-
const
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
if (actionRule.who === ProtocolActor.Anyone) {
|
|
509
|
-
return;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
if (await EncryptionProtocol.roleRuleAllowsAuthor(
|
|
513
|
-
input.tenant,
|
|
514
|
-
author,
|
|
515
|
-
actionRule,
|
|
516
|
-
input.tags,
|
|
517
|
-
input.protocolDefinition,
|
|
518
|
-
input.validationStateReader,
|
|
519
|
-
signaturePayload.protocolRole,
|
|
520
|
-
)) {
|
|
521
|
-
return;
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
if (await checkActor(author, actionRule, recordChain, input.protocolDefinition)) {
|
|
525
|
-
return;
|
|
526
|
-
}
|
|
290
|
+
const protocolDefinition = await params.validationStateReader.fetchProtocolDefinition(
|
|
291
|
+
params.tenant,
|
|
292
|
+
params.protocol,
|
|
293
|
+
params.message.descriptor.messageTimestamp,
|
|
294
|
+
);
|
|
295
|
+
if (grantKeyScopeCoversDeliveredScope({ grantScope, deliveredScope, protocolDefinition })) {
|
|
296
|
+
return;
|
|
527
297
|
}
|
|
528
298
|
|
|
529
299
|
throw new DwnError(
|
|
530
|
-
DwnErrorCode.
|
|
531
|
-
|
|
300
|
+
DwnErrorCode.EncryptionProtocolValidateGrantKeyGrantScopeMismatch,
|
|
301
|
+
`grantKey protocolPath ${protocolPath ?? '<protocol>'} is outside the permission grant scope.`
|
|
532
302
|
);
|
|
533
303
|
}
|
|
534
304
|
|
|
535
|
-
private static async constructRoleParentChain(
|
|
536
|
-
tenant: string,
|
|
537
|
-
tags: AudienceTags,
|
|
538
|
-
validationStateReader: ValidationStateReader,
|
|
539
|
-
): Promise<RecordsWriteMessage[]> {
|
|
540
|
-
if (tags.contextId === '') {
|
|
541
|
-
return [];
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
const parentRecordId = tags.contextId.split('/').pop();
|
|
545
|
-
if (parentRecordId === undefined || parentRecordId === '') {
|
|
546
|
-
return [];
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
return validationStateReader.constructRecordChain(tenant, parentRecordId);
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
private static async roleRuleAllowsAuthor(
|
|
553
|
-
tenant: string,
|
|
554
|
-
author: string,
|
|
555
|
-
actionRule: ProtocolActionRule,
|
|
556
|
-
tags: AudienceTags,
|
|
557
|
-
protocolDefinition: ProtocolDefinition,
|
|
558
|
-
validationStateReader: ValidationStateReader,
|
|
559
|
-
invokedRole: string | undefined,
|
|
560
|
-
): Promise<boolean> {
|
|
561
|
-
if (actionRule.role === undefined || invokedRole !== actionRule.role) {
|
|
562
|
-
return false;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
const roleRef = actionRule.role;
|
|
566
|
-
return EncryptionProtocol.hasInvokedRole(tenant, author, roleRef, tags, protocolDefinition, validationStateReader);
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
private static async hasInvokedRole(
|
|
570
|
-
tenant: string,
|
|
571
|
-
author: string,
|
|
572
|
-
roleRef: string,
|
|
573
|
-
tags: AudienceTags,
|
|
574
|
-
protocolDefinition: ProtocolDefinition,
|
|
575
|
-
validationStateReader: ValidationStateReader,
|
|
576
|
-
): Promise<boolean> {
|
|
577
|
-
const resolved = EncryptionProtocol.resolveRoleReference(roleRef, tags.protocol, protocolDefinition);
|
|
578
|
-
if (resolved === undefined) {
|
|
579
|
-
return false;
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
const ancestorDepth = resolved.protocolPath.split('/').length - 1;
|
|
583
|
-
let contextIdPrefix: string | undefined;
|
|
584
|
-
if (ancestorDepth > 0) {
|
|
585
|
-
contextIdPrefix = tags.contextId.split('/').slice(0, ancestorDepth).join('/');
|
|
586
|
-
if (contextIdPrefix === '') {
|
|
587
|
-
return false;
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
return validationStateReader.hasMatchingRoleRecord({
|
|
592
|
-
tenant,
|
|
593
|
-
protocol : resolved.protocol,
|
|
594
|
-
protocolPath : resolved.protocolPath,
|
|
595
|
-
recipient : author,
|
|
596
|
-
contextIdPrefix,
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
private static resolveRoleReference(
|
|
601
|
-
roleRef: string,
|
|
602
|
-
currentProtocol: string,
|
|
603
|
-
protocolDefinition: ProtocolDefinition,
|
|
604
|
-
): { protocol: string; protocolPath: string } | undefined {
|
|
605
|
-
if (!isCrossProtocolRef(roleRef)) {
|
|
606
|
-
return { protocol: currentProtocol, protocolPath: roleRef };
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
const parsed = parseCrossProtocolRef(roleRef);
|
|
610
|
-
if (parsed === undefined) {
|
|
611
|
-
return undefined;
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
const protocol = protocolDefinition.uses?.[parsed.alias];
|
|
615
|
-
if (protocol === undefined) {
|
|
616
|
-
return undefined;
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
return { protocol, protocolPath: parsed.protocolPath };
|
|
620
|
-
}
|
|
621
|
-
|
|
622
305
|
public mapErrorToStatusCode(errorCode: string): number | undefined {
|
|
623
306
|
if (errorCode.startsWith('EncryptionProtocolValidate')) {
|
|
624
307
|
return 400;
|