@enbox/dwn-sdk-js 0.4.6 → 0.4.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/README.md +3 -1
- package/dist/browser.mjs +19 -78
- package/dist/browser.mjs.map +4 -4
- package/dist/esm/generated/precompiled-validators.js +1997 -1517
- 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 +28 -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 +7 -10
- 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 +32 -274
- 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 +116 -472
- 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/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 +4 -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 +28 -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 +10 -17
- 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 +2 -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/package.json +47 -28
- package/src/core/constants.ts +61 -0
- package/src/core/dwn-error.ts +28 -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 +48 -21
- 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 +50 -420
- 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
|
@@ -6,6 +6,7 @@ import type { RecordsQueryReplyEntry, RecordsSubscribeMessage, RecordsSubscribeR
|
|
|
6
6
|
|
|
7
7
|
import { authenticate } from '../core/auth.js';
|
|
8
8
|
import { DateSort } from '../types/records-types.js';
|
|
9
|
+
import { EncryptionControl } from '../core/encryption-control.js';
|
|
9
10
|
import { Message } from '../core/message.js';
|
|
10
11
|
import { messageReplyFromError } from '../core/message-reply.js';
|
|
11
12
|
import { ProtocolAuthorization } from '../core/protocol-authorization.js';
|
|
@@ -52,6 +53,7 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
52
53
|
|
|
53
54
|
let eventFilters: Filter[] = [];
|
|
54
55
|
let queryFilters: Filter[] = [];
|
|
56
|
+
const requester = Message.getRequester(recordsSubscribe.message);
|
|
55
57
|
|
|
56
58
|
// if this is an anonymous subscribe and the filter supports published records, subscribe to only published records
|
|
57
59
|
if (Records.filterIncludesPublishedRecords(recordsSubscribe.message.descriptor.filter) && recordsSubscribe.author === undefined) {
|
|
@@ -82,6 +84,7 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
82
84
|
const { cursor: eventLogCursor } = recordsSubscribe.message.descriptor;
|
|
83
85
|
const projectedSubscriptionHandler = RecordsSubscribeHandler.createRecordLimitOccupancyGuard({
|
|
84
86
|
deps: this.deps,
|
|
87
|
+
eventFilters,
|
|
85
88
|
recordsSubscribe,
|
|
86
89
|
subscriptionHandler,
|
|
87
90
|
tenant,
|
|
@@ -130,15 +133,14 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
130
133
|
try {
|
|
131
134
|
const { dateSort, pagination } = recordsSubscribe.message.descriptor;
|
|
132
135
|
const messageSort = RecordsSubscribeHandler.convertDateSort(dateSort);
|
|
133
|
-
const queryResult = await
|
|
134
|
-
messageStore : this.deps.messageStore,
|
|
135
|
-
validationStateReader : this.deps.validationStateReader,
|
|
136
|
+
const queryResult = await this.queryRecordsWithVisibleControlFiltering(
|
|
136
137
|
tenant,
|
|
137
|
-
|
|
138
|
+
recordsSubscribe,
|
|
139
|
+
requester,
|
|
140
|
+
queryFilters,
|
|
138
141
|
messageSort,
|
|
139
142
|
pagination,
|
|
140
|
-
|
|
141
|
-
});
|
|
143
|
+
);
|
|
142
144
|
entries = queryResult.messages;
|
|
143
145
|
paginationCursor = queryResult.cursor;
|
|
144
146
|
|
|
@@ -194,11 +196,13 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
194
196
|
|
|
195
197
|
private static createRecordLimitOccupancyGuard(input: {
|
|
196
198
|
deps: HandlerDependencies;
|
|
199
|
+
eventFilters: Filter[];
|
|
197
200
|
recordsSubscribe: RecordsSubscribe;
|
|
198
201
|
subscriptionHandler: SubscriptionListener;
|
|
199
202
|
tenant: string;
|
|
200
203
|
}): ProjectedRecordsSubscriptionHandler {
|
|
201
|
-
const { deps, recordsSubscribe, subscriptionHandler, tenant } = input;
|
|
204
|
+
const { deps, eventFilters, recordsSubscribe, subscriptionHandler, tenant } = input;
|
|
205
|
+
const requester = Message.getRequester(recordsSubscribe.message);
|
|
202
206
|
let subscription: EventSubscription | undefined;
|
|
203
207
|
let closeRequested = false;
|
|
204
208
|
let terminalErrorEmitted = false;
|
|
@@ -230,6 +234,27 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
230
234
|
const deliverProjectedEvent = async (subscriptionEvent: SubscriptionEvent): Promise<void> => {
|
|
231
235
|
const { message } = subscriptionEvent.event;
|
|
232
236
|
if (Records.isRecordsWrite(message)) {
|
|
237
|
+
const visibleMessages = await EncryptionControl.filterVisibleControlRecords({
|
|
238
|
+
tenant,
|
|
239
|
+
incomingMessage : recordsSubscribe.message,
|
|
240
|
+
requester,
|
|
241
|
+
recordsWriteMessages : [message],
|
|
242
|
+
validationStateReader : deps.validationStateReader,
|
|
243
|
+
});
|
|
244
|
+
if (visibleMessages.length === 0) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const projectedMessages = await EncryptionControl.projectCurrentAudienceRecords({
|
|
249
|
+
messageStore : deps.messageStore,
|
|
250
|
+
tenant,
|
|
251
|
+
recordsWriteMessages : [message],
|
|
252
|
+
bypassFilters : eventFilters,
|
|
253
|
+
});
|
|
254
|
+
if (projectedMessages.length === 0) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
233
258
|
let isOccupant: boolean;
|
|
234
259
|
try {
|
|
235
260
|
isOccupant = await isRecordLimitOccupant({
|
|
@@ -315,6 +340,15 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
315
340
|
}
|
|
316
341
|
|
|
317
342
|
if (Records.filterIncludesUnpublishedRecords(filter)) {
|
|
343
|
+
if (EncryptionControl.isExactAudienceFilter(filter)) {
|
|
344
|
+
filters.push({
|
|
345
|
+
...Records.convertFilter(filter),
|
|
346
|
+
interface : DwnInterfaceName.Records,
|
|
347
|
+
method : [DwnMethodName.Write, DwnMethodName.Delete],
|
|
348
|
+
published : false,
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
|
|
318
352
|
if (Records.shouldBuildUnpublishedAuthorFilter(filter, recordsSubscribe.author!)) {
|
|
319
353
|
filters.push({
|
|
320
354
|
...Records.convertFilter(filter),
|
|
@@ -397,6 +431,10 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
397
431
|
}
|
|
398
432
|
|
|
399
433
|
if (Records.filterIncludesUnpublishedRecords(filter)) {
|
|
434
|
+
if (EncryptionControl.isExactAudienceFilter(filter)) {
|
|
435
|
+
filters.push(Records.buildUnpublishedControlRecordsFilter(filter, dateSort));
|
|
436
|
+
}
|
|
437
|
+
|
|
400
438
|
if (Records.shouldBuildUnpublishedAuthorFilter(filter, recordsSubscribe.author!)) {
|
|
401
439
|
filters.push({
|
|
402
440
|
...Records.convertFilter(filter, dateSort),
|
|
@@ -465,8 +503,16 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
465
503
|
deps: HandlerDependencies,
|
|
466
504
|
): Promise<void> {
|
|
467
505
|
|
|
468
|
-
if (Message.isSignedByAuthorDelegate(recordsSubscribe.message)
|
|
506
|
+
if (Message.isSignedByAuthorDelegate(recordsSubscribe.message) &&
|
|
507
|
+
!EncryptionControl.filterTargetsOnlyControlRecords(recordsSubscribe.message.descriptor.filter)) {
|
|
469
508
|
await recordsSubscribe.authorizeDelegate(deps.validationStateReader);
|
|
509
|
+
} else if (EncryptionControl.filterTargetsOnlyControlRecords(recordsSubscribe.message.descriptor.filter)) {
|
|
510
|
+
await EncryptionControl.authorizeControlReadRequest({
|
|
511
|
+
tenant,
|
|
512
|
+
incomingMessage : recordsSubscribe.message,
|
|
513
|
+
requester : Message.getRequester(recordsSubscribe.message),
|
|
514
|
+
validationStateReader : deps.validationStateReader,
|
|
515
|
+
});
|
|
470
516
|
}
|
|
471
517
|
|
|
472
518
|
const permissionGrantId = Message.getPermissionGrantId(recordsSubscribe.signaturePayload!);
|
|
@@ -489,4 +535,108 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
489
535
|
await ProtocolAuthorization.authorizeQueryOrSubscribe(tenant, recordsSubscribe, deps.validationStateReader);
|
|
490
536
|
}
|
|
491
537
|
}
|
|
538
|
+
|
|
539
|
+
private async filterControlRecordsForNonOwner(
|
|
540
|
+
tenant: string,
|
|
541
|
+
recordsSubscribe: RecordsSubscribe,
|
|
542
|
+
requester: string | undefined,
|
|
543
|
+
recordsWrites: RecordsQueryReplyEntry[],
|
|
544
|
+
): Promise<RecordsQueryReplyEntry[]> {
|
|
545
|
+
return EncryptionControl.filterVisibleControlRecords({
|
|
546
|
+
tenant,
|
|
547
|
+
incomingMessage : recordsSubscribe.message,
|
|
548
|
+
requester,
|
|
549
|
+
recordsWriteMessages : recordsWrites,
|
|
550
|
+
validationStateReader : this.deps.validationStateReader,
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
private async queryRecordsWithVisibleControlFiltering(
|
|
555
|
+
tenant: string,
|
|
556
|
+
recordsSubscribe: RecordsSubscribe,
|
|
557
|
+
requester: string | undefined,
|
|
558
|
+
filters: Filter[],
|
|
559
|
+
messageSort: MessageSort,
|
|
560
|
+
pagination: { cursor?: PaginationCursor; limit?: number } | undefined,
|
|
561
|
+
): Promise<{ messages: RecordsQueryReplyEntry[], cursor?: PaginationCursor }> {
|
|
562
|
+
const controlFilters = Records.buildControlRecordsFilters(filters);
|
|
563
|
+
const currentAudienceRecordIdCache = new Map<string, string | undefined>();
|
|
564
|
+
if (controlFilters.length === 0) {
|
|
565
|
+
const result = await queryRecordsWithRecordLimitOccupancy({
|
|
566
|
+
messageStore : this.deps.messageStore,
|
|
567
|
+
validationStateReader : this.deps.validationStateReader,
|
|
568
|
+
tenant,
|
|
569
|
+
filters,
|
|
570
|
+
messageSort,
|
|
571
|
+
pagination,
|
|
572
|
+
messageTimestamp : recordsSubscribe.message.descriptor.messageTimestamp,
|
|
573
|
+
});
|
|
574
|
+
return EncryptionControl.projectCurrentAudienceRecordPage({
|
|
575
|
+
messageStore: this.deps.messageStore,
|
|
576
|
+
tenant,
|
|
577
|
+
filters,
|
|
578
|
+
currentAudienceRecordIdCache,
|
|
579
|
+
result,
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
if (pagination?.limit === undefined || pagination.limit <= 0) {
|
|
584
|
+
const result = await queryRecordsWithRecordLimitOccupancy({
|
|
585
|
+
messageStore : this.deps.messageStore,
|
|
586
|
+
validationStateReader : this.deps.validationStateReader,
|
|
587
|
+
tenant,
|
|
588
|
+
filters,
|
|
589
|
+
messageSort,
|
|
590
|
+
pagination,
|
|
591
|
+
messageTimestamp : recordsSubscribe.message.descriptor.messageTimestamp,
|
|
592
|
+
});
|
|
593
|
+
const projectedResult = await EncryptionControl.projectCurrentAudienceRecordPage({
|
|
594
|
+
messageStore: this.deps.messageStore,
|
|
595
|
+
tenant,
|
|
596
|
+
filters,
|
|
597
|
+
currentAudienceRecordIdCache,
|
|
598
|
+
result,
|
|
599
|
+
});
|
|
600
|
+
return {
|
|
601
|
+
messages : await this.filterControlRecordsForNonOwner(tenant, recordsSubscribe, requester, projectedResult.messages),
|
|
602
|
+
cursor : projectedResult.cursor,
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
const visibleMessages: RecordsQueryReplyEntry[] = [];
|
|
607
|
+
let cursor = pagination.cursor;
|
|
608
|
+
let nextCursor: PaginationCursor | undefined;
|
|
609
|
+
// Keeps visible-page pagination stable until #1100 moves control visibility into indexed store filters.
|
|
610
|
+
do {
|
|
611
|
+
const remainingLimit = pagination.limit - visibleMessages.length;
|
|
612
|
+
const result = await queryRecordsWithRecordLimitOccupancy({
|
|
613
|
+
messageStore : this.deps.messageStore,
|
|
614
|
+
validationStateReader : this.deps.validationStateReader,
|
|
615
|
+
tenant,
|
|
616
|
+
filters,
|
|
617
|
+
messageSort,
|
|
618
|
+
pagination : { ...pagination, cursor, limit: remainingLimit },
|
|
619
|
+
messageTimestamp : recordsSubscribe.message.descriptor.messageTimestamp,
|
|
620
|
+
});
|
|
621
|
+
const projectedResult = await EncryptionControl.projectCurrentAudienceRecordPage({
|
|
622
|
+
messageStore: this.deps.messageStore,
|
|
623
|
+
tenant,
|
|
624
|
+
filters,
|
|
625
|
+
currentAudienceRecordIdCache,
|
|
626
|
+
result,
|
|
627
|
+
});
|
|
628
|
+
const filteredMessages = await this.filterControlRecordsForNonOwner(
|
|
629
|
+
tenant,
|
|
630
|
+
recordsSubscribe,
|
|
631
|
+
requester,
|
|
632
|
+
projectedResult.messages,
|
|
633
|
+
);
|
|
634
|
+
visibleMessages.push(...filteredMessages);
|
|
635
|
+
nextCursor = projectedResult.cursor;
|
|
636
|
+
cursor = projectedResult.cursor;
|
|
637
|
+
} while (visibleMessages.length < pagination.limit && cursor !== undefined);
|
|
638
|
+
|
|
639
|
+
return { messages: visibleMessages, cursor: nextCursor };
|
|
640
|
+
}
|
|
641
|
+
|
|
492
642
|
}
|
|
@@ -8,6 +8,7 @@ import { Cid } from '../utils/cid.js';
|
|
|
8
8
|
import { DataStream } from '../utils/data-stream.js';
|
|
9
9
|
import { DwnConstant } from '../core/dwn-constant.js';
|
|
10
10
|
import { Encoder } from '../utils/encoder.js';
|
|
11
|
+
import { EncryptionControl } from '../core/encryption-control.js';
|
|
11
12
|
import { Message } from '../core/message.js';
|
|
12
13
|
import { messageReplyFromError } from '../core/message-reply.js';
|
|
13
14
|
import { ProtocolAuthorization } from '../core/protocol-authorization.js';
|
|
@@ -135,6 +136,15 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
135
136
|
if (coreProtocol?.preProcessWrite !== undefined) {
|
|
136
137
|
await coreProtocol.preProcessWrite(tenant, message, this.deps.validationStateReader);
|
|
137
138
|
}
|
|
139
|
+
if (EncryptionControl.isControlMessage(message)) {
|
|
140
|
+
await EncryptionControl.preProcessWrite(tenant, message, this.deps.validationStateReader);
|
|
141
|
+
if (dataStream === undefined) {
|
|
142
|
+
throw new DwnError(
|
|
143
|
+
DwnErrorCode.EncryptionControlValidateUnexpectedRecord,
|
|
144
|
+
'encryption control records require data.'
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
138
148
|
|
|
139
149
|
// NOTE: We allow isLatestBaseState to be true ONLY if the incoming message comes with data, or if the incoming message is NOT an initial write
|
|
140
150
|
// This would allow an initial write to be written to the DB without data, but having it not queryable,
|
|
@@ -170,6 +180,7 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
170
180
|
error.code === DwnErrorCode.RecordsWriteDataCidMismatch ||
|
|
171
181
|
error.code === DwnErrorCode.RecordsWriteDataSizeMismatch ||
|
|
172
182
|
error.code.startsWith('SchemaValidator') ||
|
|
183
|
+
EncryptionControl.mapErrorToStatusCode(error.code) !== undefined ||
|
|
173
184
|
this.deps.coreProtocols?.mapErrorToStatusCode(error.code) !== undefined) {
|
|
174
185
|
return messageReplyFromError(error, 400);
|
|
175
186
|
}
|
|
@@ -246,6 +257,9 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
246
257
|
if (coreProtocol?.validateRecord !== undefined) {
|
|
247
258
|
await coreProtocol.validateRecord(message, dataBytes);
|
|
248
259
|
}
|
|
260
|
+
if (EncryptionControl.isControlMessage(message)) {
|
|
261
|
+
await EncryptionControl.validateRecord({ tenant, message, dataBytes, validationStateReader: this.deps.validationStateReader });
|
|
262
|
+
}
|
|
249
263
|
|
|
250
264
|
messageWithOptionalEncodedData = await this.cloneAndAddEncodedData(message, dataBytes);
|
|
251
265
|
} else {
|
|
@@ -414,6 +428,11 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
414
428
|
);
|
|
415
429
|
}
|
|
416
430
|
|
|
431
|
+
if (EncryptionControl.isControlMessage(recordsWrite.message)) {
|
|
432
|
+
await EncryptionControl.authorizeWrite(tenant, recordsWrite, this.deps.validationStateReader);
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
|
|
417
436
|
if (recordsWrite.isSignedByAuthorDelegate) {
|
|
418
437
|
await recordsWrite.authorizeAuthorDelegate(this.deps.validationStateReader);
|
|
419
438
|
}
|
package/src/index.ts
CHANGED
|
@@ -16,7 +16,20 @@ export type { DataEncodedRecordsWriteMessage, RecordsCountDescriptor, RecordsCou
|
|
|
16
16
|
export type { GeneralJws, SignatureEntry } from './types/jws-types.js';
|
|
17
17
|
export { authenticate } from './core/auth.js';
|
|
18
18
|
export { CoreProtocolRegistry } from './core/core-protocol.js';
|
|
19
|
-
export {
|
|
19
|
+
export { EncryptionControl } from './core/encryption-control.js';
|
|
20
|
+
export {
|
|
21
|
+
ENCRYPTION_CONTROL_AUDIENCE_PATH,
|
|
22
|
+
ENCRYPTION_CONTROL_AUDIENCE_SCHEMA_URI,
|
|
23
|
+
ENCRYPTION_CONTROL_DELIVERY_PATH,
|
|
24
|
+
ENCRYPTION_CONTROL_DELIVERY_SCHEMA_URI,
|
|
25
|
+
ENCRYPTION_CONTROL_PATHS,
|
|
26
|
+
ENCRYPTION_CONTROL_ROOT_PATH,
|
|
27
|
+
ENCRYPTION_PROTOCOL_URI,
|
|
28
|
+
EncryptionControlRecordType,
|
|
29
|
+
PERMISSIONS_REVOCATION_PATH,
|
|
30
|
+
isEncryptionControlPath,
|
|
31
|
+
} from './core/constants.js';
|
|
32
|
+
export type { EncryptionControlPath } from './core/constants.js';
|
|
20
33
|
export type { CoreProtocol, CoreProtocolStores } from './core/core-protocol.js';
|
|
21
34
|
export { AllowAllTenantGate } from './core/tenant-gate.js';
|
|
22
35
|
export type { ActiveTenantCheckResult, TenantGate } from './core/tenant-gate.js';
|
|
@@ -28,6 +41,8 @@ export type { RecordsQueryOptions } from './interfaces/records-query.js';
|
|
|
28
41
|
export type { DataStore, DataStorePutResult, DataStoreGetResult } from './types/data-store.js';
|
|
29
42
|
export type { ResumableTaskStore, ManagedResumableTask } from './types/resumable-task-store.js';
|
|
30
43
|
export { DataStream } from './utils/data-stream.js';
|
|
44
|
+
export { getGrantKeyDeliveryScopes, grantKeyScopeCoversDeliveredScope, isGrantKeyEligibleRecordsScope, isGrantKeyRecordsScope } from './utils/grant-key-coverage.js';
|
|
45
|
+
export type { GrantKeyEligibleRecordsScope, GrantKeyProtocolPathScope, GrantKeyReadRecordsScope, GrantKeyRecordsScope, GrantKeyWriteRecordsScope } from './utils/grant-key-coverage.js';
|
|
31
46
|
export { HdKey, KeyDerivationScheme } from './utils/hd-key.js';
|
|
32
47
|
export type { DerivedPrivateJwk } from './utils/hd-key.js';
|
|
33
48
|
export { Dwn } from './dwn.js';
|
|
@@ -38,16 +53,21 @@ export { DwnInterfaceName, DwnMethodName } from './enums/dwn-interface-method.js
|
|
|
38
53
|
export { Encoder } from './utils/encoder.js';
|
|
39
54
|
export { MessagesSubscribe } from './interfaces/messages-subscribe.js';
|
|
40
55
|
export type { MessagesSubscribeOptions } from './interfaces/messages-subscribe.js';
|
|
41
|
-
export { Encryption, ContentEncryptionAlgorithm, KeyAgreementAlgorithm, ROLE_AUDIENCE_DERIVATION_SCHEME } from './utils/encryption.js';
|
|
56
|
+
export { Encryption, ContentEncryptionAlgorithm, KeyAgreementAlgorithm, ROLE_AUDIENCE_DERIVATION_SCHEME, SEAL_DERIVATION_SCHEME } from './utils/encryption.js';
|
|
42
57
|
export type {
|
|
43
58
|
DwnEncryption,
|
|
44
|
-
KeyEncryption,
|
|
45
|
-
KeyEncryptionInput,
|
|
46
59
|
KeyUnwrapPayload,
|
|
47
60
|
ProtocolPathKeyEncryption,
|
|
48
61
|
ProtocolPathKeyEncryptionInput,
|
|
49
|
-
|
|
50
|
-
|
|
62
|
+
SealKeyWrap,
|
|
63
|
+
SealKeyWrapInput,
|
|
64
|
+
SealUnwrapInput,
|
|
65
|
+
SealWrapInput,
|
|
66
|
+
SourceRoleAudienceKeyEncryption,
|
|
67
|
+
SourceRoleAudienceKeyEncryptionInput,
|
|
68
|
+
X25519KeyEncryption,
|
|
69
|
+
X25519KeyEncryptionInput,
|
|
70
|
+
X25519KeyWrapInput,
|
|
51
71
|
} from './utils/encryption.js';
|
|
52
72
|
export { RecordsWrite } from './interfaces/records-write.js';
|
|
53
73
|
export type { EncryptionInput, RecordsWriteOptions, CreateFromOptions } from './interfaces/records-write.js';
|
|
@@ -72,7 +92,14 @@ export { PermissionScopeMatcher } from './utils/permission-scope.js';
|
|
|
72
92
|
export type { ProtocolScope } from './utils/permission-scope.js';
|
|
73
93
|
export { PrivateKeySigner } from './utils/private-key-signer.js';
|
|
74
94
|
export type { PrivateKeySignerOptions } from './utils/private-key-signer.js';
|
|
75
|
-
export {
|
|
95
|
+
export {
|
|
96
|
+
Protocols,
|
|
97
|
+
getRoleAudienceContextId,
|
|
98
|
+
getRoleContextPrefix,
|
|
99
|
+
getRuleSetAtPath,
|
|
100
|
+
isCrossProtocolRef,
|
|
101
|
+
parseCrossProtocolRef,
|
|
102
|
+
} from './utils/protocols.js';
|
|
76
103
|
export type { CrossProtocolRef } from './utils/protocols.js';
|
|
77
104
|
export { ProtocolsConfigure } from './interfaces/protocols-configure.js';
|
|
78
105
|
export type { ProtocolsConfigureOptions } from './interfaces/protocols-configure.js';
|
|
@@ -90,24 +117,24 @@ export { Secp256r1 } from './utils/secp256r1.js';
|
|
|
90
117
|
export type { SupportedCurve } from './jose/algorithms/signing/signature-algorithms.js';
|
|
91
118
|
export type { MessageSigner } from './types/signer.js';
|
|
92
119
|
export { SortDirection } from './types/query-types.js';
|
|
93
|
-
export type {
|
|
120
|
+
export type {
|
|
121
|
+
EncryptionControlAudiencePayload,
|
|
122
|
+
EncryptionControlDeliveryPayload,
|
|
123
|
+
EncryptionControlDeliveryTags,
|
|
124
|
+
EncryptionControlSeal,
|
|
125
|
+
EncryptionKeyDeriver,
|
|
126
|
+
KeyDecrypter,
|
|
127
|
+
KeyDecrypterDerivationScheme,
|
|
128
|
+
RoleAudienceKeyId,
|
|
129
|
+
RoleAudienceKeyMaterial,
|
|
130
|
+
RoleAudienceTuple,
|
|
131
|
+
} from './types/encryption-types.js';
|
|
132
|
+
export { EncryptionControlDeliveryRecipientAuthority } from './types/encryption-types.js';
|
|
94
133
|
export { Time } from './utils/time.js';
|
|
95
134
|
export * from './types/permission-types.js';
|
|
96
135
|
export * from './types/records-types.js';
|
|
97
136
|
|
|
98
|
-
// concrete
|
|
99
|
-
export { BlockstoreLevel } from './store/blockstore-level.js';
|
|
100
|
-
export type { BlockstoreLevelConfig } from './store/blockstore-level.js';
|
|
101
|
-
export { DataStoreLevel } from './store/data-store-level.js';
|
|
102
|
-
export type { DataStoreLevelConfig } from './store/data-store-level.js';
|
|
103
|
-
export { IndexLevel } from './store/index-level.js';
|
|
104
|
-
export type { CompoundIndexDefinition, IndexLevelConfig, IndexedItem, IndexLevelOptions } from './store/index-level.js';
|
|
105
|
-
export { createLevelDatabase, LevelWrapper } from './store/level-wrapper.js';
|
|
106
|
-
export type { CreateLevelDatabaseOptions, LevelDatabase, LevelWrapperConfig, LevelWrapperBatchOperation, LevelWrapperOptions, LevelWrapperIteratorOptions } from './store/level-wrapper.js';
|
|
107
|
-
export { MessageStoreLevel } from './store/message-store-level.js';
|
|
108
|
-
export type { MessageStoreLevelConfig } from './store/message-store-level.js';
|
|
109
|
-
export { ResumableTaskStoreLevel } from './store/resumable-task-store-level.js';
|
|
110
|
-
export type { ResumableTaskStoreLevelConfig } from './store/resumable-task-store-level.js';
|
|
137
|
+
// concrete event log implementations
|
|
111
138
|
export { EventEmitterWakePublisher } from './event-stream/event-emitter-wake-publisher.js';
|
|
112
139
|
export { DurableEventLog } from './event-stream/durable-event-log.js';
|
|
113
140
|
export type { DurableEventLogConfig, DurableEventLogStore } from './event-stream/durable-event-log.js';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CrossProtocolRef } from '../utils/protocols.js';
|
|
1
2
|
import type { DataEncodedRecordsWriteMessage } from '../types/records-types.js';
|
|
2
3
|
import type { MessageSigner } from '../types/signer.js';
|
|
3
4
|
import type { ValidationStateReader } from '../types/validation-state-reader.js';
|
|
@@ -15,7 +16,7 @@ import { Time } from '../utils/time.js';
|
|
|
15
16
|
import { validateProtocolTagSchemaDefinition } from '../utils/protocol-tags.js';
|
|
16
17
|
import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
|
|
17
18
|
import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
|
|
18
|
-
import { getRuleSetAtPath, isCrossProtocolRef, parseCrossProtocolRef } from '../utils/protocols.js';
|
|
19
|
+
import { getRoleAudienceContextId, getRuleSetAtPath, isCrossProtocolRef, parseCrossProtocolRef } from '../utils/protocols.js';
|
|
19
20
|
import { normalizeProtocolUrl, normalizeSchemaUrl, validateProtocolUrlNormalized, validateSchemaUrlNormalized } from '../utils/url.js';
|
|
20
21
|
import { ProtocolAction, ProtocolActor, ProtocolRecordLimitStrategy } from '../types/protocols-types.js';
|
|
21
22
|
|
|
@@ -31,7 +32,10 @@ export type ProtocolsConfigureOptions = {
|
|
|
31
32
|
};
|
|
32
33
|
|
|
33
34
|
export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessage> {
|
|
35
|
+
private static readonly maxRecordNestingDepth = 10;
|
|
36
|
+
|
|
34
37
|
public static async parse(message: ProtocolsConfigureMessage): Promise<ProtocolsConfigure> {
|
|
38
|
+
ProtocolsConfigure.validateReservedEncryptionControlPath(message.descriptor?.definition);
|
|
35
39
|
Message.validateJsonSchema(message);
|
|
36
40
|
ProtocolsConfigure.validateProtocolDefinition(message.descriptor.definition);
|
|
37
41
|
await Message.validateSignatureStructure(message.authorization.signature, message.descriptor);
|
|
@@ -53,6 +57,8 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
53
57
|
...permissionGrantInvocation,
|
|
54
58
|
};
|
|
55
59
|
|
|
60
|
+
ProtocolsConfigure.validateReservedEncryptionControlPath(descriptor.definition);
|
|
61
|
+
|
|
56
62
|
const authorization = await Message.createAuthorization({
|
|
57
63
|
descriptor,
|
|
58
64
|
signer : options.signer,
|
|
@@ -109,6 +115,59 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
109
115
|
ProtocolsConfigure.validateStructure(definition);
|
|
110
116
|
}
|
|
111
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Validates the reserved encryption-control namespace before JSON Schema validation.
|
|
120
|
+
*/
|
|
121
|
+
private static validateReservedEncryptionControlPath(definition: unknown): void {
|
|
122
|
+
if (!ProtocolsConfigure.isRecord(definition)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (ProtocolsConfigure.isRecord(definition.types) && Object.hasOwn(definition.types, '$encryption')) {
|
|
127
|
+
throw new DwnError(
|
|
128
|
+
DwnErrorCode.ProtocolsConfigureReservedEncryptionControlPath,
|
|
129
|
+
`protocol type '$encryption' is reserved for DWN encryption control records.`
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
ProtocolsConfigure.validateReservedEncryptionControlStructure(definition.structure, '', 0);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
private static validateReservedEncryptionControlStructure(ruleSet: unknown, protocolPath: string, depth: number): void {
|
|
137
|
+
if (!ProtocolsConfigure.isRecord(ruleSet)) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
for (const recordType in ruleSet) {
|
|
142
|
+
const childDepth = depth + 1;
|
|
143
|
+
const childPath = protocolPath === '' ? recordType : `${protocolPath}/${recordType}`;
|
|
144
|
+
|
|
145
|
+
if (recordType === '$encryption') {
|
|
146
|
+
throw new DwnError(
|
|
147
|
+
DwnErrorCode.ProtocolsConfigureReservedEncryptionControlPath,
|
|
148
|
+
`protocol structure path '${childPath}' is reserved for DWN encryption control records.`
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (recordType.startsWith('$')) {
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (childDepth > ProtocolsConfigure.maxRecordNestingDepth) {
|
|
157
|
+
throw new DwnError(
|
|
158
|
+
DwnErrorCode.ProtocolsConfigureRecordNestingDepthExceeded,
|
|
159
|
+
`record nesting depth exceeded ${ProtocolsConfigure.maxRecordNestingDepth} levels.`
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
ProtocolsConfigure.validateReservedEncryptionControlStructure(ruleSet[recordType], childPath, childDepth);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private static isRecord(value: unknown): value is Record<string, unknown> {
|
|
168
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
169
|
+
}
|
|
170
|
+
|
|
112
171
|
/**
|
|
113
172
|
* Validates the `uses` map: alias names must match `^[a-zA-Z][a-zA-Z0-9_-]*$`,
|
|
114
173
|
* values must be normalized protocol URLs, and no alias may reference the protocol itself.
|
|
@@ -175,15 +234,8 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
175
234
|
|
|
176
235
|
/**
|
|
177
236
|
* Parses the given rule set hierarchy to get all the role protocol paths.
|
|
178
|
-
* @throws DwnError if the hierarchy depth goes beyond 10 levels.
|
|
179
237
|
*/
|
|
180
238
|
private static fetchAllRolePathsRecursively(ruleSetProtocolPath: string, ruleSet: ProtocolRuleSet, roles: string[]): string[] {
|
|
181
|
-
// Limit the depth of the record hierarchy to 10 levels
|
|
182
|
-
// There is opportunity to optimize here to avoid repeated string splitting
|
|
183
|
-
if (ruleSetProtocolPath.split('/').length > 10) {
|
|
184
|
-
throw new DwnError(DwnErrorCode.ProtocolsConfigureRecordNestingDepthExceeded, 'Record nesting depth exceeded 10 levels.');
|
|
185
|
-
}
|
|
186
|
-
|
|
187
239
|
for (const recordType in ruleSet) {
|
|
188
240
|
// ignore non-nested-record properties
|
|
189
241
|
if (recordType.startsWith('$')) {
|
|
@@ -300,7 +352,8 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
300
352
|
if (actionRule.role !== undefined) {
|
|
301
353
|
if (isCrossProtocolRef(actionRule.role)) {
|
|
302
354
|
// Cross-protocol role reference: validate alias exists in `uses`
|
|
303
|
-
ProtocolsConfigure.validateCrossProtocolAlias(actionRule.role, uses, ruleSetProtocolPath, 'role');
|
|
355
|
+
const parsedRole = ProtocolsConfigure.validateCrossProtocolAlias(actionRule.role, uses, ruleSetProtocolPath, 'role');
|
|
356
|
+
ProtocolsConfigure.validateRoleParentContextDepth(parsedRole.protocolPath, ruleSetProtocolPath, actionRule);
|
|
304
357
|
} else {
|
|
305
358
|
// Local role: make sure the role contains a valid protocol path to a role record
|
|
306
359
|
if (!roles.includes(actionRule.role)) {
|
|
@@ -309,6 +362,8 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
309
362
|
`Role in action ${JSON.stringify(actionRule)} for rule set ${ruleSetProtocolPath} does not exist.`
|
|
310
363
|
);
|
|
311
364
|
}
|
|
365
|
+
|
|
366
|
+
ProtocolsConfigure.validateRoleParentContextDepth(actionRule.role, ruleSetProtocolPath, actionRule);
|
|
312
367
|
}
|
|
313
368
|
}
|
|
314
369
|
|
|
@@ -443,10 +498,17 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
443
498
|
}
|
|
444
499
|
|
|
445
500
|
for (const actionRule of actionRules) {
|
|
446
|
-
if (actionRule.role === undefined || !actionRule.can.includes(ProtocolAction.Read)
|
|
501
|
+
if (actionRule.role === undefined || !actionRule.can.includes(ProtocolAction.Read)) {
|
|
447
502
|
continue;
|
|
448
503
|
}
|
|
449
504
|
|
|
505
|
+
if (isCrossProtocolRef(actionRule.role)) {
|
|
506
|
+
throw new DwnError(
|
|
507
|
+
DwnErrorCode.ProtocolsConfigureInvalidEncryptedCrossProtocolRole,
|
|
508
|
+
`Encrypted protocol path '${ruleSetProtocolPath}' references cross-protocol read role '${actionRule.role}'.`
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
|
|
450
512
|
const roleRuleSet = getRuleSetAtPath(actionRule.role, rootStructure);
|
|
451
513
|
if (roleRuleSet?.$keyAgreement === undefined) {
|
|
452
514
|
throw new DwnError(
|
|
@@ -558,6 +620,33 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
558
620
|
}
|
|
559
621
|
}
|
|
560
622
|
|
|
623
|
+
/**
|
|
624
|
+
* Validates that a role rule only references a role whose parent context can be found
|
|
625
|
+
* from records at the rule set's protocol path.
|
|
626
|
+
*/
|
|
627
|
+
private static validateRoleParentContextDepth(rolePath: string, ruleSetProtocolPath: string, actionRule: ProtocolActionRule): void {
|
|
628
|
+
const syntheticContextId = ProtocolsConfigure.getSyntheticContextIdForProtocolPath(ruleSetProtocolPath);
|
|
629
|
+
|
|
630
|
+
if (getRoleAudienceContextId(rolePath, syntheticContextId) === undefined) {
|
|
631
|
+
throw new DwnError(
|
|
632
|
+
DwnErrorCode.ProtocolsConfigureRoleParentContextDepthExceeded,
|
|
633
|
+
`role '${rolePath}' in action ${JSON.stringify(actionRule)} at protocol path '${ruleSetProtocolPath}' ` +
|
|
634
|
+
`requires a context that records at the rule path cannot provide.`
|
|
635
|
+
);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
private static getSyntheticContextIdForProtocolPath(protocolPath: string): string | undefined {
|
|
640
|
+
if (protocolPath === '') {
|
|
641
|
+
return undefined;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
return protocolPath
|
|
645
|
+
.split('/')
|
|
646
|
+
.map((_segment, index): string => `context-${index}`)
|
|
647
|
+
.join('/');
|
|
648
|
+
}
|
|
649
|
+
|
|
561
650
|
/**
|
|
562
651
|
* Validates that a cross-protocol reference (in `alias:path` format) has a valid alias
|
|
563
652
|
* that exists in the `uses` map.
|
|
@@ -568,7 +657,7 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
568
657
|
*/
|
|
569
658
|
private static validateCrossProtocolAlias(
|
|
570
659
|
ref: string, uses: ProtocolUses | undefined, ruleSetProtocolPath: string, fieldName: string
|
|
571
|
-
):
|
|
660
|
+
): CrossProtocolRef {
|
|
572
661
|
const parsed = parseCrossProtocolRef(ref);
|
|
573
662
|
|
|
574
663
|
if (parsed === undefined) {
|
|
@@ -595,6 +684,8 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
595
684
|
`does not exist in the 'uses' map.`
|
|
596
685
|
);
|
|
597
686
|
}
|
|
687
|
+
|
|
688
|
+
return parsed;
|
|
598
689
|
}
|
|
599
690
|
|
|
600
691
|
private static normalizeDefinition(definition: ProtocolDefinition): ProtocolDefinition {
|