@enbox/dwn-sdk-js 0.4.5 → 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 +4465 -3861
- 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 +142 -34
- 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 +240 -67
- 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/grant-key.spec.js +25 -16
- package/dist/esm/tests/validation/json-schemas/encryption/grant-key.spec.js.map +1 -1
- 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 +58 -22
- 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 +247 -69
- 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/src/types/mitt.d.ts +0 -28
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import type { PermissionScope, RecordsPermissionScope } from '../types/permission-types.js';
|
|
2
|
+
import type { ProtocolDefinition, ProtocolRuleSet } from '../types/protocols-types.js';
|
|
3
|
+
|
|
4
|
+
import { KeyDerivationScheme } from './hd-key.js';
|
|
5
|
+
import { ProtocolAction } from '../types/protocols-types.js';
|
|
6
|
+
import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
|
|
7
|
+
import { getRuleSetAtPath, parseCrossProtocolRef } from './protocols.js';
|
|
8
|
+
|
|
9
|
+
type GrantKeyRecordsScopeBase = RecordsPermissionScope & {
|
|
10
|
+
interface: typeof DwnInterfaceName.Records;
|
|
11
|
+
protocol: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type GrantKeyRecordsScope = GrantKeyRecordsScopeBase & {
|
|
15
|
+
method: typeof DwnMethodName.Read | typeof DwnMethodName.Write;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type GrantKeyReadRecordsScope = GrantKeyRecordsScopeBase & {
|
|
19
|
+
contextId?: undefined;
|
|
20
|
+
method: typeof DwnMethodName.Read;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type GrantKeyWriteRecordsScope = GrantKeyRecordsScopeBase & {
|
|
24
|
+
contextId?: undefined;
|
|
25
|
+
method: typeof DwnMethodName.Write;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type GrantKeyEligibleRecordsScope = GrantKeyReadRecordsScope | GrantKeyWriteRecordsScope;
|
|
29
|
+
|
|
30
|
+
export type GrantKeyProtocolPathScope = {
|
|
31
|
+
scheme: typeof KeyDerivationScheme.ProtocolPath;
|
|
32
|
+
protocol: string;
|
|
33
|
+
protocolPath?: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
type GrantKeyDeliveryScopeBuilder = (
|
|
37
|
+
grantScope: GrantKeyEligibleRecordsScope,
|
|
38
|
+
protocolDefinition?: ProtocolDefinition,
|
|
39
|
+
) => GrantKeyProtocolPathScope[];
|
|
40
|
+
|
|
41
|
+
type GrantKeyCoveragePredicate = (
|
|
42
|
+
input: {
|
|
43
|
+
grantScope: GrantKeyEligibleRecordsScope;
|
|
44
|
+
deliveredScope: Pick<GrantKeyProtocolPathScope, 'protocol' | 'protocolPath'>;
|
|
45
|
+
protocolDefinition?: ProtocolDefinition;
|
|
46
|
+
},
|
|
47
|
+
) => boolean;
|
|
48
|
+
|
|
49
|
+
const grantKeyRecordsMethods = new Set<string>([
|
|
50
|
+
DwnMethodName.Read,
|
|
51
|
+
DwnMethodName.Write,
|
|
52
|
+
]);
|
|
53
|
+
|
|
54
|
+
const grantKeyDeliveryScopeBuilders: Record<GrantKeyRecordsScope['method'], GrantKeyDeliveryScopeBuilder> = {
|
|
55
|
+
[DwnMethodName.Read] : getReadGrantKeyDeliveryScopes,
|
|
56
|
+
[DwnMethodName.Write] : getWriteGrantKeyDeliveryScopes,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const grantKeyCoveragePredicates: Record<GrantKeyRecordsScope['method'], GrantKeyCoveragePredicate> = {
|
|
60
|
+
[DwnMethodName.Read] : readGrantKeyScopeCoversDeliveredScope,
|
|
61
|
+
[DwnMethodName.Write] : writeGrantKeyScopeCoversDeliveredScope,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export function isGrantKeyRecordsScope(scope: PermissionScope): scope is GrantKeyRecordsScope {
|
|
65
|
+
const maybeProtocol = (scope as { protocol?: unknown }).protocol;
|
|
66
|
+
return [
|
|
67
|
+
scope.interface === DwnInterfaceName.Records,
|
|
68
|
+
grantKeyRecordsMethods.has(scope.method),
|
|
69
|
+
typeof maybeProtocol === 'string',
|
|
70
|
+
].every(Boolean);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function isGrantKeyEligibleRecordsScope(scope: PermissionScope): scope is GrantKeyEligibleRecordsScope {
|
|
74
|
+
return isGrantKeyRecordsScope(scope) &&
|
|
75
|
+
!('contextId' in scope && scope.contextId !== undefined);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function getGrantKeyDeliveryScopes(
|
|
79
|
+
grantScope: GrantKeyReadRecordsScope,
|
|
80
|
+
protocolDefinition?: ProtocolDefinition,
|
|
81
|
+
): GrantKeyProtocolPathScope[];
|
|
82
|
+
|
|
83
|
+
export function getGrantKeyDeliveryScopes(
|
|
84
|
+
grantScope: GrantKeyWriteRecordsScope,
|
|
85
|
+
protocolDefinition: ProtocolDefinition,
|
|
86
|
+
): GrantKeyProtocolPathScope[];
|
|
87
|
+
|
|
88
|
+
export function getGrantKeyDeliveryScopes(
|
|
89
|
+
grantScope: GrantKeyEligibleRecordsScope,
|
|
90
|
+
protocolDefinition?: ProtocolDefinition,
|
|
91
|
+
): GrantKeyProtocolPathScope[] {
|
|
92
|
+
return uniqueGrantKeyScopes(grantKeyDeliveryScopeBuilders[grantScope.method](grantScope, protocolDefinition));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function grantKeyScopeCoversDeliveredScope(input: {
|
|
96
|
+
grantScope: GrantKeyEligibleRecordsScope;
|
|
97
|
+
deliveredScope: Pick<GrantKeyProtocolPathScope, 'protocol' | 'protocolPath'>;
|
|
98
|
+
protocolDefinition?: ProtocolDefinition;
|
|
99
|
+
}): boolean {
|
|
100
|
+
const { grantScope, deliveredScope, protocolDefinition } = input;
|
|
101
|
+
if (grantScope.protocol !== deliveredScope.protocol) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return grantKeyCoveragePredicates[grantScope.method]({ grantScope, deliveredScope, protocolDefinition });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function getReadGrantKeyDeliveryScopes(
|
|
109
|
+
grantScope: GrantKeyEligibleRecordsScope,
|
|
110
|
+
protocolDefinition?: ProtocolDefinition,
|
|
111
|
+
): GrantKeyProtocolPathScope[] {
|
|
112
|
+
if (grantScope.protocolPath === undefined) {
|
|
113
|
+
return [createProtocolGrantKeyScope(grantScope.protocol)];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const scopes = [
|
|
117
|
+
createProtocolPathGrantKeyScope(grantScope.protocol, grantScope.protocolPath),
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
if (protocolDefinition === undefined) {
|
|
121
|
+
return scopes;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
for (const rolePath of getGrantKeyReadRolePathsForScope(protocolDefinition, grantScope.protocolPath)) {
|
|
125
|
+
scopes.push(createProtocolPathGrantKeyScope(grantScope.protocol, rolePath));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return scopes;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function getWriteGrantKeyDeliveryScopes(
|
|
132
|
+
grantScope: GrantKeyEligibleRecordsScope,
|
|
133
|
+
protocolDefinition?: ProtocolDefinition,
|
|
134
|
+
): GrantKeyProtocolPathScope[] {
|
|
135
|
+
if (protocolDefinition === undefined) {
|
|
136
|
+
throw new Error('getGrantKeyDeliveryScopes: write grants require a protocol definition.');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return getGrantKeyRolePathsCoveredByScope(protocolDefinition, grantScope.protocolPath)
|
|
140
|
+
.map((rolePath) => createProtocolPathGrantKeyScope(grantScope.protocol, rolePath));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function createProtocolGrantKeyScope(protocol: string): GrantKeyProtocolPathScope {
|
|
144
|
+
return {
|
|
145
|
+
scheme: KeyDerivationScheme.ProtocolPath,
|
|
146
|
+
protocol,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function createProtocolPathGrantKeyScope(protocol: string, protocolPath: string): GrantKeyProtocolPathScope {
|
|
151
|
+
return {
|
|
152
|
+
scheme: KeyDerivationScheme.ProtocolPath,
|
|
153
|
+
protocol,
|
|
154
|
+
protocolPath,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function readGrantKeyScopeCoversDeliveredScope(input: {
|
|
159
|
+
grantScope: GrantKeyEligibleRecordsScope;
|
|
160
|
+
deliveredScope: Pick<GrantKeyProtocolPathScope, 'protocol' | 'protocolPath'>;
|
|
161
|
+
protocolDefinition?: ProtocolDefinition;
|
|
162
|
+
}): boolean {
|
|
163
|
+
const { grantScope, deliveredScope, protocolDefinition } = input;
|
|
164
|
+
const grantProtocolPath = grantScope.protocolPath;
|
|
165
|
+
if (grantProtocolPath === undefined) {
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const deliveredProtocolPath = deliveredScope.protocolPath;
|
|
170
|
+
if (deliveredProtocolPath === undefined) {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (isBoundaryAwareSubtree(grantProtocolPath, deliveredProtocolPath)) {
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (protocolDefinition === undefined) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return grantKeyReadScopeReferencesRolePath(protocolDefinition, grantProtocolPath, deliveredProtocolPath);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function writeGrantKeyScopeCoversDeliveredScope(input: {
|
|
186
|
+
grantScope: GrantKeyEligibleRecordsScope;
|
|
187
|
+
deliveredScope: Pick<GrantKeyProtocolPathScope, 'protocol' | 'protocolPath'>;
|
|
188
|
+
protocolDefinition?: ProtocolDefinition;
|
|
189
|
+
}): boolean {
|
|
190
|
+
const { grantScope, deliveredScope, protocolDefinition } = input;
|
|
191
|
+
const deliveredProtocolPath = deliveredScope.protocolPath;
|
|
192
|
+
if (deliveredProtocolPath === undefined) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (protocolDefinition === undefined) {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (!isGrantKeyLocalRolePath(protocolDefinition, deliveredProtocolPath)) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const grantProtocolPath = grantScope.protocolPath;
|
|
205
|
+
if (grantProtocolPath === undefined) {
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return isBoundaryAwareSubtree(grantProtocolPath, deliveredProtocolPath);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function getGrantKeyReadRolePathsForScope(protocolDefinition: ProtocolDefinition, scopeProtocolPath: string): string[] {
|
|
213
|
+
const scopedRuleSet = getRuleSetAtPath(scopeProtocolPath, protocolDefinition.structure);
|
|
214
|
+
if (scopedRuleSet === undefined) {
|
|
215
|
+
return [];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return [...collectReadRolePaths(protocolDefinition, scopedRuleSet)];
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function grantKeyReadScopeReferencesRolePath(
|
|
222
|
+
protocolDefinition: ProtocolDefinition,
|
|
223
|
+
scopeProtocolPath: string,
|
|
224
|
+
rolePath: string,
|
|
225
|
+
): boolean {
|
|
226
|
+
if (!isGrantKeyLocalRolePath(protocolDefinition, rolePath)) {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return getGrantKeyReadRolePathsForScope(protocolDefinition, scopeProtocolPath).includes(rolePath);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function collectReadRolePaths(protocolDefinition: ProtocolDefinition, ruleSet: ProtocolRuleSet): Set<string> {
|
|
234
|
+
const rolePaths = new Set<string>();
|
|
235
|
+
|
|
236
|
+
for (const actionRule of ruleSet.$actions ?? []) {
|
|
237
|
+
if (!actionRule.can.includes(ProtocolAction.Read) || actionRule.role === undefined || parseCrossProtocolRef(actionRule.role) !== undefined) {
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (isGrantKeyLocalRolePath(protocolDefinition, actionRule.role)) {
|
|
242
|
+
rolePaths.add(actionRule.role);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
for (const [key, value] of Object.entries(ruleSet)) {
|
|
247
|
+
if (key.startsWith('$')) {
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
for (const rolePath of collectReadRolePaths(protocolDefinition, value as ProtocolRuleSet)) {
|
|
251
|
+
rolePaths.add(rolePath);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return rolePaths;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function getGrantKeyRolePathsCoveredByScope(protocolDefinition: ProtocolDefinition, scopeProtocolPath?: string): string[] {
|
|
259
|
+
return collectRolePaths(protocolDefinition, protocolDefinition.structure as ProtocolRuleSet)
|
|
260
|
+
.filter((rolePath) => scopeProtocolPath === undefined || isBoundaryAwareSubtree(scopeProtocolPath, rolePath));
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function collectRolePaths(protocolDefinition: ProtocolDefinition, ruleSet: ProtocolRuleSet, parentPath: string[] = []): string[] {
|
|
264
|
+
const rolePaths: string[] = [];
|
|
265
|
+
|
|
266
|
+
for (const [key, value] of Object.entries(ruleSet)) {
|
|
267
|
+
if (key.startsWith('$')) {
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const path = [...parentPath, key];
|
|
272
|
+
const protocolPath = path.join('/');
|
|
273
|
+
const childRuleSet = value as ProtocolRuleSet;
|
|
274
|
+
if (isGrantKeyLocalRolePath(protocolDefinition, protocolPath)) {
|
|
275
|
+
rolePaths.push(protocolPath);
|
|
276
|
+
}
|
|
277
|
+
rolePaths.push(...collectRolePaths(protocolDefinition, childRuleSet, path));
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return rolePaths;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function isGrantKeyLocalRolePath(protocolDefinition: ProtocolDefinition, protocolPath: string): boolean {
|
|
284
|
+
const ruleSet = getRuleSetAtPath(protocolPath, protocolDefinition.structure);
|
|
285
|
+
return ruleSet?.$role === true && ruleSet.$keyAgreement !== undefined;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function isBoundaryAwareSubtree(scopePath: string, candidatePath: string): boolean {
|
|
289
|
+
return `${candidatePath}/`.startsWith(`${scopePath}/`);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function getGrantKeyScopeCacheKey(scope: GrantKeyProtocolPathScope): string {
|
|
293
|
+
return JSON.stringify([scope.protocol, scope.protocolPath]);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function uniqueGrantKeyScopes(scopes: GrantKeyProtocolPathScope[]): GrantKeyProtocolPathScope[] {
|
|
297
|
+
const deliveredScopes = new Map<string, GrantKeyProtocolPathScope>();
|
|
298
|
+
for (const scope of scopes) {
|
|
299
|
+
deliveredScopes.set(getGrantKeyScopeCacheKey(scope), scope);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return [...deliveredScopes.values()];
|
|
303
|
+
}
|
package/src/utils/hd-key.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { PrivateKeyJwk, PublicKeyJwk } from '../types/jose-types.js';
|
|
2
2
|
|
|
3
3
|
import { Encoder } from './encoder.js';
|
|
4
|
-
import { getWebcryptoSubtle } from '@noble/ciphers/webcrypto';
|
|
5
4
|
import { X25519 } from '@enbox/crypto';
|
|
6
5
|
import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
|
|
7
6
|
|
|
@@ -82,7 +81,7 @@ export class HdKey {
|
|
|
82
81
|
}): Promise<Uint8Array> {
|
|
83
82
|
const { hashAlgorithm, initialKeyMaterial, info, keyLengthInBytes } = params;
|
|
84
83
|
|
|
85
|
-
const webCrypto =
|
|
84
|
+
const webCrypto = globalThis.crypto.subtle;
|
|
86
85
|
|
|
87
86
|
// Import the `initialKeyMaterial` into the Web Crypto API to use for the key derivation operation.
|
|
88
87
|
const webCryptoKey = await webCrypto.importKey('raw', initialKeyMaterial as BufferSource, { name: 'HKDF' }, false, ['deriveBits']);
|
package/src/utils/jws.ts
CHANGED
|
@@ -3,13 +3,19 @@ import type { MessageSigner } from '../types/signer.js';
|
|
|
3
3
|
import type { SignatureEntry } from '../types/jws-types.js';
|
|
4
4
|
import type { KeyMaterial, PublicKeyJwk } from '../types/jose-types.js';
|
|
5
5
|
|
|
6
|
-
import isPlainObject from 'lodash/isPlainObject.js';
|
|
7
|
-
|
|
8
6
|
import { Encoder } from './encoder.js';
|
|
9
7
|
import { PrivateKeySigner } from './private-key-signer.js';
|
|
10
8
|
import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
|
|
11
9
|
import { signatureAlgorithms, type SupportedCurve } from '../jose/algorithms/signing/signature-algorithms.js';
|
|
12
10
|
|
|
11
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
12
|
+
if (typeof value !== 'object' || value === null) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const prototype = Object.getPrototypeOf(value);
|
|
17
|
+
return prototype === Object.prototype || prototype === null;
|
|
18
|
+
}
|
|
13
19
|
|
|
14
20
|
/**
|
|
15
21
|
* Utility class for JWS related operations.
|
|
@@ -1,31 +1,62 @@
|
|
|
1
1
|
import type { Cache } from '../types/cache.js';
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
type CacheEntry = {
|
|
4
|
+
expiresAt: number;
|
|
5
|
+
value: unknown;
|
|
6
|
+
};
|
|
3
7
|
|
|
4
8
|
/**
|
|
5
9
|
* A cache using local memory.
|
|
6
10
|
*/
|
|
7
11
|
export class MemoryCache implements Cache {
|
|
8
|
-
private readonly
|
|
12
|
+
private static readonly maxEntries = 100_000;
|
|
13
|
+
|
|
14
|
+
private readonly cache = new Map<string, CacheEntry>();
|
|
9
15
|
|
|
10
16
|
/**
|
|
11
17
|
* @param timeToLiveInSeconds time-to-live for every key-value pair set in the cache
|
|
12
18
|
*/
|
|
13
|
-
public constructor
|
|
14
|
-
this.cache = new LRUCache({
|
|
15
|
-
max : 100_000,
|
|
16
|
-
ttl : timeToLiveInSeconds * 1000
|
|
17
|
-
});
|
|
19
|
+
public constructor(private readonly timeToLiveInSeconds: number) {
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
async set(key: string, value:
|
|
22
|
+
public async set<T = unknown>(key: string, value: T): Promise<void> {
|
|
21
23
|
try {
|
|
22
|
-
|
|
24
|
+
const entry = {
|
|
25
|
+
expiresAt : Date.now() + this.timeToLiveInSeconds * 1000,
|
|
26
|
+
value : value,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
this.cache.delete(key);
|
|
30
|
+
this.cache.set(key, entry);
|
|
31
|
+
this.evictOldestEntries();
|
|
23
32
|
} catch {
|
|
24
33
|
// let the code continue as this is a non-fatal error
|
|
25
34
|
}
|
|
26
35
|
}
|
|
27
36
|
|
|
28
|
-
async get(key: string): Promise<
|
|
29
|
-
|
|
37
|
+
public async get<T = unknown>(key: string): Promise<T | undefined> {
|
|
38
|
+
const entry = this.cache.get(key);
|
|
39
|
+
if (entry === undefined) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (Date.now() >= entry.expiresAt) {
|
|
44
|
+
this.cache.delete(key);
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.cache.delete(key);
|
|
49
|
+
this.cache.set(key, entry);
|
|
50
|
+
return entry.value as T;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private evictOldestEntries(): void {
|
|
54
|
+
while (this.cache.size > MemoryCache.maxEntries) {
|
|
55
|
+
const oldestKey = this.cache.keys().next().value;
|
|
56
|
+
if (oldestKey === undefined) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
this.cache.delete(oldestKey);
|
|
60
|
+
}
|
|
30
61
|
}
|
|
31
62
|
}
|
package/src/utils/protocols.ts
CHANGED
|
@@ -52,6 +52,38 @@ export function getTypeName(protocolPath: string): string {
|
|
|
52
52
|
return protocolPath.split('/').slice(-1)[0];
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Computes the role-audience context id for a role path relative to a source record context id.
|
|
57
|
+
* Root-level role audiences use the empty string; nested role audiences use the ancestor
|
|
58
|
+
* context prefix at the same depth as the role parent.
|
|
59
|
+
*/
|
|
60
|
+
export function getRoleAudienceContextId(rolePath: string, contextId?: string): string | undefined {
|
|
61
|
+
const roleParentDepth = rolePath.split('/').length - 1;
|
|
62
|
+
if (roleParentDepth === 0) {
|
|
63
|
+
return '';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (contextId === undefined) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const contextSegments = contextId.split('/');
|
|
71
|
+
if (contextSegments.length < roleParentDepth) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return contextSegments.slice(0, roleParentDepth).join('/');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Computes the context prefix used when querying for role records. Root-level
|
|
80
|
+
* role records are queried without a context prefix.
|
|
81
|
+
*/
|
|
82
|
+
export function getRoleContextPrefix(rolePath: string, contextId?: string): string | undefined {
|
|
83
|
+
const roleAudienceContextId = getRoleAudienceContextId(rolePath, contextId);
|
|
84
|
+
return roleAudienceContextId === '' ? undefined : roleAudienceContextId;
|
|
85
|
+
}
|
|
86
|
+
|
|
55
87
|
/**
|
|
56
88
|
* Gets the rule set at a given protocol path within a protocol definition's structure tree.
|
|
57
89
|
* Returns `undefined` if the path does not exist.
|
|
@@ -37,6 +37,13 @@ type RecordLimitFilterResolution = {
|
|
|
37
37
|
projectedFilters: Filter[];
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
+
type OccupancyProjectionInput<T extends RecordsWriteMessage> = {
|
|
41
|
+
records: T[];
|
|
42
|
+
max: number;
|
|
43
|
+
getScopeKey(record: T): string;
|
|
44
|
+
compareRecords(left: T, right: T): number;
|
|
45
|
+
};
|
|
46
|
+
|
|
40
47
|
/**
|
|
41
48
|
* Queries records with bounded `$recordLimit` occupancy projection when every limited filter targets one concrete scope.
|
|
42
49
|
*
|
|
@@ -285,11 +292,12 @@ async function findOccupantRecordIds(input: {
|
|
|
285
292
|
...boundaryCandidates,
|
|
286
293
|
];
|
|
287
294
|
|
|
288
|
-
return
|
|
289
|
-
rankedCandidates
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
295
|
+
return selectOccupantRecordIds({
|
|
296
|
+
records : rankedCandidates,
|
|
297
|
+
max : input.recordLimit.max,
|
|
298
|
+
getScopeKey : (): string => '',
|
|
299
|
+
compareRecords : compareRecordLimitCandidates,
|
|
300
|
+
});
|
|
293
301
|
}
|
|
294
302
|
|
|
295
303
|
function buildRecordLimitScopeFilter(scope: RecordLimitScope): Filter {
|
|
@@ -375,3 +383,24 @@ function compareRecordLimitCandidates(left: RecordsWriteMessage, right: RecordsW
|
|
|
375
383
|
|
|
376
384
|
return lexicographicalCompare(left.recordId, right.recordId);
|
|
377
385
|
}
|
|
386
|
+
|
|
387
|
+
export function selectOccupantRecordIds<T extends RecordsWriteMessage>(input: OccupancyProjectionInput<T>): Set<string> {
|
|
388
|
+
const occupants = new Set<string>();
|
|
389
|
+
const groups = new Map<string, T[]>();
|
|
390
|
+
|
|
391
|
+
for (const record of input.records) {
|
|
392
|
+
const scopeKey = input.getScopeKey(record);
|
|
393
|
+
const group = groups.get(scopeKey) ?? [];
|
|
394
|
+
group.push(record);
|
|
395
|
+
groups.set(scopeKey, group);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
for (const group of groups.values()) {
|
|
399
|
+
group.sort(input.compareRecords);
|
|
400
|
+
for (const record of group.slice(0, input.max)) {
|
|
401
|
+
occupants.add(record.recordId);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return occupants;
|
|
406
|
+
}
|
package/src/utils/records.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { DerivedPrivateJwk } from './hd-key.js';
|
|
2
2
|
import type { Jwk } from '@enbox/crypto';
|
|
3
3
|
import type { KeyDecrypter } from '../types/encryption-types.js';
|
|
4
|
-
import type { KeyEncryption } from './encryption.js';
|
|
5
4
|
import type { PublicKeyJwk } from '../types/jose-types.js';
|
|
5
|
+
import type { X25519KeyEncryption } from './encryption.js';
|
|
6
6
|
import type { Filter, KeyValues, StartsWithFilter } from '../types/query-types.js';
|
|
7
7
|
import type { GenericMessage, GenericSignaturePayload, MessageSort } from '../types/message-types.js';
|
|
8
8
|
import type { RecordsCountMessage, RecordsDeleteMessage, RecordsFilter, RecordsQueryMessage, RecordsReadMessage, RecordsSubscribeMessage, RecordsWriteDescriptor, RecordsWriteMessage, RecordsWriteTags, RecordsWriteTagsFilter } from '../types/records-types.js';
|
|
@@ -21,6 +21,7 @@ import { X25519 } from '@enbox/crypto';
|
|
|
21
21
|
import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
|
|
22
22
|
import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
|
|
23
23
|
import { Encryption, ROLE_AUDIENCE_DERIVATION_SCHEME } from './encryption.js';
|
|
24
|
+
import { ENCRYPTION_CONTROL_PATHS, isEncryptionControlPath } from '../core/constants.js';
|
|
24
25
|
import { HdKey, KeyDerivationScheme } from './hd-key.js';
|
|
25
26
|
import { normalizeProtocolUrl, normalizeSchemaUrl } from './url.js';
|
|
26
27
|
|
|
@@ -132,7 +133,7 @@ export class Records {
|
|
|
132
133
|
private static async findMatchingKeyEncryption(
|
|
133
134
|
recordsWrite: RecordsWriteMessage,
|
|
134
135
|
keyOrDecrypter: DerivedPrivateJwk | KeyDecrypter,
|
|
135
|
-
): Promise<{ fullDerivationPath: string[]; leafPrivateKey?: Jwk; matchingKeyEncryption?:
|
|
136
|
+
): Promise<{ fullDerivationPath: string[]; leafPrivateKey?: Jwk; matchingKeyEncryption?: X25519KeyEncryption }> {
|
|
136
137
|
const { encryption } = recordsWrite;
|
|
137
138
|
const fullDerivationPath = Records.constructKeyDerivationPath(keyOrDecrypter.derivationScheme, recordsWrite);
|
|
138
139
|
|
|
@@ -334,6 +335,10 @@ export class Records {
|
|
|
334
335
|
return;
|
|
335
336
|
}
|
|
336
337
|
|
|
338
|
+
if (isEncryptionControlPath(protocolPath)) {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
|
|
337
342
|
const expectedParentDepth = protocolPath.split('/').length - 1;
|
|
338
343
|
const contextIdSegments = contextId?.split('/');
|
|
339
344
|
if (
|
|
@@ -442,6 +447,35 @@ export class Records {
|
|
|
442
447
|
return filterCopy;
|
|
443
448
|
}
|
|
444
449
|
|
|
450
|
+
public static buildUnpublishedControlRecordsFilter(filter: RecordsFilter, dateSort?: DateSort): Filter {
|
|
451
|
+
return {
|
|
452
|
+
...Records.convertFilter(filter, dateSort),
|
|
453
|
+
interface : DwnInterfaceName.Records,
|
|
454
|
+
method : DwnMethodName.Write,
|
|
455
|
+
isLatestBaseState : true,
|
|
456
|
+
published : false,
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
public static buildControlRecordsFilters(filters: Filter[]): Filter[] {
|
|
461
|
+
const controlFilters: Filter[] = [];
|
|
462
|
+
for (const filter of filters) {
|
|
463
|
+
const protocolPath = filter.protocolPath;
|
|
464
|
+
if (typeof protocolPath === 'string') {
|
|
465
|
+
if (isEncryptionControlPath(protocolPath)) {
|
|
466
|
+
controlFilters.push(filter);
|
|
467
|
+
}
|
|
468
|
+
continue;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
for (const controlPath of ENCRYPTION_CONTROL_PATHS) {
|
|
472
|
+
controlFilters.push({ ...filter, protocolPath: controlPath });
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
return controlFilters;
|
|
477
|
+
}
|
|
478
|
+
|
|
445
479
|
/**
|
|
446
480
|
* Validates the referential integrity of both author-delegated grant and owner-delegated grant.
|
|
447
481
|
* @param authorSignaturePayload Decoded payload of the author signature of the message. Pass `undefined` if message is not signed.
|
package/src/utils/secp256k1.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { JwkParamsEcPrivate, JwkParamsEcPublic } from '@enbox/crypto';
|
|
2
2
|
import type { PrivateKeyJwk, PublicKeyJwk } from '../types/jose-types.js';
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import { bytesToNumberBE } from '@noble/curves/utils.js';
|
|
5
|
+
import { secp256k1 } from '@noble/curves/secp256k1.js';
|
|
5
6
|
|
|
6
7
|
import { Encoder } from '../utils/encoder.js';
|
|
7
8
|
import { sha256 } from 'multiformats/hashes/sha2';
|
|
@@ -30,8 +31,8 @@ export class Secp256k1 {
|
|
|
30
31
|
let uncompressedPublicKeyBytes;
|
|
31
32
|
if (publicKeyBytes.byteLength === 33) {
|
|
32
33
|
// this means given key is compressed
|
|
33
|
-
const curvePoints = secp256k1.
|
|
34
|
-
uncompressedPublicKeyBytes = curvePoints.
|
|
34
|
+
const curvePoints = secp256k1.Point.fromBytes(publicKeyBytes);
|
|
35
|
+
uncompressedPublicKeyBytes = curvePoints.toBytes(false); // isCompressed = false
|
|
35
36
|
} else {
|
|
36
37
|
uncompressedPublicKeyBytes = publicKeyBytes;
|
|
37
38
|
}
|
|
@@ -75,10 +76,10 @@ export class Secp256k1 {
|
|
|
75
76
|
const x = Encoder.base64UrlToBytes(ecJwk.x);
|
|
76
77
|
const y = Encoder.base64UrlToBytes(ecJwk.y!);
|
|
77
78
|
|
|
78
|
-
return secp256k1.
|
|
79
|
-
x :
|
|
80
|
-
y :
|
|
81
|
-
}).
|
|
79
|
+
return secp256k1.Point.fromAffine({
|
|
80
|
+
x : bytesToNumberBE(x),
|
|
81
|
+
y : bytesToNumberBE(y)
|
|
82
|
+
}).toBytes(true);
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
/**
|
|
@@ -100,7 +101,7 @@ export class Secp256k1 {
|
|
|
100
101
|
const hashedContent = await sha256.encode(content);
|
|
101
102
|
const privateKeyBytes = Secp256k1.privateJwkToBytes(privateJwk);
|
|
102
103
|
|
|
103
|
-
return
|
|
104
|
+
return secp256k1.sign(hashedContent, privateKeyBytes, { prehash: false });
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
/**
|
|
@@ -112,14 +113,14 @@ export class Secp256k1 {
|
|
|
112
113
|
|
|
113
114
|
const publicKeyBytes = Secp256k1.publicJwkToBytes(publicJwk);
|
|
114
115
|
const hashedContent = await sha256.encode(content);
|
|
115
|
-
return secp256k1.verify(signature, hashedContent, publicKeyBytes, { lowS: false });
|
|
116
|
+
return secp256k1.verify(signature, hashedContent, publicKeyBytes, { lowS: false, prehash: false });
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
/**
|
|
119
120
|
* Generates a random key pair in JWK format.
|
|
120
121
|
*/
|
|
121
122
|
public static async generateKeyPair(): Promise<{publicJwk: PublicKeyJwk, privateJwk: PrivateKeyJwk}> {
|
|
122
|
-
const privateKeyBytes = secp256k1.utils.
|
|
123
|
+
const privateKeyBytes = secp256k1.utils.randomSecretKey();
|
|
123
124
|
const publicKeyBytes = secp256k1.getPublicKey(privateKeyBytes, false); // `false` = uncompressed
|
|
124
125
|
|
|
125
126
|
const d = Encoder.bytesToBase64Url(privateKeyBytes);
|
|
@@ -133,7 +134,7 @@ export class Secp256k1 {
|
|
|
133
134
|
* Generates key pair in raw bytes, where the `publicKey` is compressed.
|
|
134
135
|
*/
|
|
135
136
|
public static async generateKeyPairRaw(): Promise<{publicKey: Uint8Array, privateKey: Uint8Array}> {
|
|
136
|
-
const privateKey = secp256k1.utils.
|
|
137
|
+
const privateKey = secp256k1.utils.randomSecretKey();
|
|
137
138
|
const publicKey = secp256k1.getPublicKey(privateKey, true); // `true` = compressed
|
|
138
139
|
|
|
139
140
|
return { publicKey, privateKey };
|
|
@@ -156,4 +157,3 @@ export class Secp256k1 {
|
|
|
156
157
|
return publicKey as PublicKeyJwk;
|
|
157
158
|
}
|
|
158
159
|
}
|
|
159
|
-
|