@enbox/dwn-sdk-js 0.0.7 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.mjs +8 -8
- package/dist/browser.mjs.map +4 -4
- package/dist/esm/generated/precompiled-validators.js +817 -911
- package/dist/esm/generated/precompiled-validators.js.map +1 -1
- package/dist/esm/src/core/constants.js +11 -0
- package/dist/esm/src/core/constants.js.map +1 -0
- package/dist/esm/src/core/core-protocol.js +44 -0
- package/dist/esm/src/core/core-protocol.js.map +1 -0
- package/dist/esm/src/core/dwn-error.js +12 -12
- package/dist/esm/src/core/dwn-error.js.map +1 -1
- package/dist/esm/src/core/grant-authorization.js +16 -3
- package/dist/esm/src/core/grant-authorization.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization-action.js +5 -0
- package/dist/esm/src/core/protocol-authorization-action.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization-validation.js +91 -0
- package/dist/esm/src/core/protocol-authorization-validation.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization.js +53 -30
- package/dist/esm/src/core/protocol-authorization.js.map +1 -1
- package/dist/esm/src/core/records-grant-authorization.js +6 -8
- package/dist/esm/src/core/records-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/resumable-task-manager.js +2 -0
- package/dist/esm/src/core/resumable-task-manager.js.map +1 -1
- package/dist/esm/src/dwn.js +42 -18
- package/dist/esm/src/dwn.js.map +1 -1
- package/dist/esm/src/event-stream/event-emitter-event-log.js +204 -0
- package/dist/esm/src/event-stream/event-emitter-event-log.js.map +1 -0
- package/dist/esm/src/handlers/messages-read.js +7 -11
- package/dist/esm/src/handlers/messages-read.js.map +1 -1
- package/dist/esm/src/handlers/messages-subscribe.js +22 -24
- package/dist/esm/src/handlers/messages-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/messages-sync.js +11 -15
- package/dist/esm/src/handlers/messages-sync.js.map +1 -1
- package/dist/esm/src/handlers/protocols-configure.js +37 -27
- package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
- package/dist/esm/src/handlers/protocols-query.js +7 -11
- package/dist/esm/src/handlers/protocols-query.js.map +1 -1
- package/dist/esm/src/handlers/records-count.js +10 -12
- package/dist/esm/src/handlers/records-count.js.map +1 -1
- package/dist/esm/src/handlers/records-delete.js +10 -18
- package/dist/esm/src/handlers/records-delete.js.map +1 -1
- package/dist/esm/src/handlers/records-query.js +11 -15
- package/dist/esm/src/handlers/records-query.js.map +1 -1
- package/dist/esm/src/handlers/records-read.js +31 -26
- package/dist/esm/src/handlers/records-read.js.map +1 -1
- package/dist/esm/src/handlers/records-subscribe.js +39 -26
- package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/records-write.js +128 -105
- package/dist/esm/src/handlers/records-write.js.map +1 -1
- package/dist/esm/src/index.js +5 -2
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/interfaces/messages-subscribe.js +1 -0
- package/dist/esm/src/interfaces/messages-subscribe.js.map +1 -1
- package/dist/esm/src/interfaces/protocols-configure.js +33 -3
- package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
- package/dist/esm/src/interfaces/records-count.js +1 -1
- package/dist/esm/src/interfaces/records-count.js.map +1 -1
- package/dist/esm/src/interfaces/records-delete.js +1 -1
- package/dist/esm/src/interfaces/records-delete.js.map +1 -1
- package/dist/esm/src/interfaces/records-query.js +1 -1
- package/dist/esm/src/interfaces/records-query.js.map +1 -1
- package/dist/esm/src/interfaces/records-read.js +1 -1
- package/dist/esm/src/interfaces/records-read.js.map +1 -1
- package/dist/esm/src/interfaces/records-subscribe.js +2 -1
- package/dist/esm/src/interfaces/records-subscribe.js.map +1 -1
- package/dist/esm/src/interfaces/records-write-signing.js +1 -12
- package/dist/esm/src/interfaces/records-write-signing.js.map +1 -1
- package/dist/esm/src/interfaces/records-write.js +25 -41
- package/dist/esm/src/interfaces/records-write.js.map +1 -1
- package/dist/esm/src/protocols/permission-grant.js +1 -1
- package/dist/esm/src/protocols/permission-grant.js.map +1 -1
- package/dist/esm/src/protocols/permission-request.js +1 -1
- package/dist/esm/src/protocols/permission-request.js.map +1 -1
- package/dist/esm/src/protocols/permissions.js +113 -5
- package/dist/esm/src/protocols/permissions.js.map +1 -1
- package/dist/esm/src/state-index/state-index-level.js +5 -7
- package/dist/esm/src/state-index/state-index-level.js.map +1 -1
- package/dist/esm/src/store/data-store-level.js +110 -33
- package/dist/esm/src/store/data-store-level.js.map +1 -1
- package/dist/esm/src/store/index-level.js +42 -32
- package/dist/esm/src/store/index-level.js.map +1 -1
- package/dist/esm/src/store/storage-controller.js +70 -6
- package/dist/esm/src/store/storage-controller.js.map +1 -1
- package/dist/esm/src/types/permission-types.js.map +1 -1
- package/dist/esm/src/types/protocols-types.js +11 -0
- package/dist/esm/src/types/protocols-types.js.map +1 -1
- package/dist/esm/src/types/records-types.js.map +1 -1
- package/dist/esm/src/utils/hd-key.js +0 -8
- package/dist/esm/src/utils/hd-key.js.map +1 -1
- package/dist/esm/src/utils/messages.js +16 -34
- package/dist/esm/src/utils/messages.js.map +1 -1
- package/dist/esm/src/utils/records.js +5 -43
- package/dist/esm/src/utils/records.js.map +1 -1
- package/dist/esm/tests/core/protocol-authorization.spec.js +2 -1
- package/dist/esm/tests/core/protocol-authorization.spec.js.map +1 -1
- package/dist/esm/tests/dwn.spec.js +32 -43
- package/dist/esm/tests/dwn.spec.js.map +1 -1
- package/dist/esm/tests/event-emitter-event-log.spec.js +305 -0
- package/dist/esm/tests/event-emitter-event-log.spec.js.map +1 -0
- package/dist/esm/tests/features/author-delegated-grant.spec.js +14 -7
- package/dist/esm/tests/features/author-delegated-grant.spec.js.map +1 -1
- package/dist/esm/tests/features/owner-delegated-grant.spec.js +9 -5
- package/dist/esm/tests/features/owner-delegated-grant.spec.js.map +1 -1
- package/dist/esm/tests/features/owner-signature.spec.js +14 -7
- package/dist/esm/tests/features/owner-signature.spec.js.map +1 -1
- package/dist/esm/tests/features/permissions.spec.js +12 -12
- package/dist/esm/tests/features/permissions.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-composition.spec.js +636 -5
- package/dist/esm/tests/features/protocol-composition.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-create-action.spec.js +4 -4
- package/dist/esm/tests/features/protocol-create-action.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-delete-action.spec.js +7 -7
- package/dist/esm/tests/features/protocol-delete-action.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-update-action.spec.js +4 -4
- package/dist/esm/tests/features/protocol-update-action.spec.js.map +1 -1
- package/dist/esm/tests/features/records-delivery.spec.js +236 -0
- package/dist/esm/tests/features/records-delivery.spec.js.map +1 -0
- package/dist/esm/tests/features/records-immutable.spec.js +315 -0
- package/dist/esm/tests/features/records-immutable.spec.js.map +1 -0
- package/dist/esm/tests/features/records-prune.spec.js +4 -4
- package/dist/esm/tests/features/records-prune.spec.js.map +1 -1
- package/dist/esm/tests/features/records-record-limit.spec.js +542 -0
- package/dist/esm/tests/features/records-record-limit.spec.js.map +1 -0
- package/dist/esm/tests/features/records-squash.spec.js +1055 -0
- package/dist/esm/tests/features/records-squash.spec.js.map +1 -0
- package/dist/esm/tests/features/records-tags.spec.js +16 -4
- package/dist/esm/tests/features/records-tags.spec.js.map +1 -1
- package/dist/esm/tests/features/resumable-tasks.spec.js +7 -8
- package/dist/esm/tests/features/resumable-tasks.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-read.spec.js +11 -5
- package/dist/esm/tests/handlers/messages-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-subscribe.spec.js +169 -22
- package/dist/esm/tests/handlers/messages-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-sync.spec.js +103 -21
- package/dist/esm/tests/handlers/messages-sync.spec.js.map +1 -1
- package/dist/esm/tests/handlers/protocols-configure.spec.js +5 -5
- package/dist/esm/tests/handlers/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/handlers/protocols-query.spec.js +5 -5
- package/dist/esm/tests/handlers/protocols-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-count.spec.js +9 -4
- package/dist/esm/tests/handlers/records-count.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-delete.spec.js +24 -25
- package/dist/esm/tests/handlers/records-delete.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-query.spec.js +68 -9
- package/dist/esm/tests/handlers/records-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-read.spec.js +24 -138
- package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js +175 -35
- package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-write.spec.js +176 -72
- package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-write.spec.js +52 -68
- package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
- package/dist/esm/tests/protocols/permission-grant.spec.js +6 -6
- package/dist/esm/tests/protocols/permission-grant.spec.js.map +1 -1
- package/dist/esm/tests/protocols/permission-request.spec.js +4 -4
- package/dist/esm/tests/protocols/permission-request.spec.js.map +1 -1
- package/dist/esm/tests/protocols/permissions.spec.js +4 -4
- package/dist/esm/tests/protocols/permissions.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/aggregator.spec.js +4 -4
- package/dist/esm/tests/scenarios/aggregator.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/deleted-record.spec.js +350 -5
- package/dist/esm/tests/scenarios/deleted-record.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js +4 -4
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/nested-roles.spec.js +4 -4
- package/dist/esm/tests/scenarios/nested-roles.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/subscriptions.spec.js +93 -40
- package/dist/esm/tests/scenarios/subscriptions.spec.js.map +1 -1
- package/dist/esm/tests/store/data-store-level.spec.js +102 -41
- package/dist/esm/tests/store/data-store-level.spec.js.map +1 -1
- package/dist/esm/tests/test-event-stream.js +12 -13
- package/dist/esm/tests/test-event-stream.js.map +1 -1
- package/dist/esm/tests/test-suite.js +10 -4
- package/dist/esm/tests/test-suite.js.map +1 -1
- package/dist/esm/tests/utils/messages.spec.js +12 -5
- package/dist/esm/tests/utils/messages.spec.js.map +1 -1
- package/dist/esm/tests/utils/records.spec.js +8 -12
- package/dist/esm/tests/utils/records.spec.js.map +1 -1
- package/dist/esm/tests/utils/test-data-generator.js +36 -2
- package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js +37 -8
- package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js.map +1 -1
- package/dist/types/generated/precompiled-validators.d.ts +49 -40
- package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
- package/dist/types/src/core/constants.d.ts +11 -0
- package/dist/types/src/core/constants.d.ts.map +1 -0
- package/dist/types/src/core/core-protocol.d.ts +89 -0
- package/dist/types/src/core/core-protocol.d.ts.map +1 -0
- package/dist/types/src/core/dwn-error.d.ts +12 -12
- package/dist/types/src/core/dwn-error.d.ts.map +1 -1
- package/dist/types/src/core/grant-authorization.d.ts +6 -2
- package/dist/types/src/core/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 +30 -0
- package/dist/types/src/core/protocol-authorization-validation.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization.d.ts +19 -11
- package/dist/types/src/core/protocol-authorization.d.ts.map +1 -1
- package/dist/types/src/core/records-grant-authorization.d.ts.map +1 -1
- package/dist/types/src/core/resumable-task-manager.d.ts +2 -1
- package/dist/types/src/core/resumable-task-manager.d.ts.map +1 -1
- package/dist/types/src/dwn.d.ts +19 -7
- package/dist/types/src/dwn.d.ts.map +1 -1
- package/dist/types/src/event-stream/event-emitter-event-log.d.ts +50 -0
- package/dist/types/src/event-stream/event-emitter-event-log.d.ts.map +1 -0
- package/dist/types/src/handlers/messages-read.d.ts +3 -8
- package/dist/types/src/handlers/messages-read.d.ts.map +1 -1
- package/dist/types/src/handlers/messages-subscribe.d.ts +6 -10
- package/dist/types/src/handlers/messages-subscribe.d.ts.map +1 -1
- package/dist/types/src/handlers/messages-sync.d.ts +3 -8
- package/dist/types/src/handlers/messages-sync.d.ts.map +1 -1
- package/dist/types/src/handlers/protocols-configure.d.ts +3 -10
- package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/handlers/protocols-query.d.ts +3 -8
- package/dist/types/src/handlers/protocols-query.d.ts.map +1 -1
- package/dist/types/src/handlers/records-count.d.ts +3 -6
- package/dist/types/src/handlers/records-count.d.ts.map +1 -1
- package/dist/types/src/handlers/records-delete.d.ts +3 -8
- package/dist/types/src/handlers/records-delete.d.ts.map +1 -1
- package/dist/types/src/handlers/records-query.d.ts +3 -8
- package/dist/types/src/handlers/records-query.d.ts.map +1 -1
- package/dist/types/src/handlers/records-read.d.ts +3 -8
- package/dist/types/src/handlers/records-read.d.ts.map +1 -1
- package/dist/types/src/handlers/records-subscribe.d.ts +8 -10
- package/dist/types/src/handlers/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/handlers/records-write.d.ts +12 -25
- package/dist/types/src/handlers/records-write.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +8 -4
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/interfaces/messages-subscribe.d.ts +5 -0
- package/dist/types/src/interfaces/messages-subscribe.d.ts.map +1 -1
- package/dist/types/src/interfaces/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-subscribe.d.ts +5 -0
- package/dist/types/src/interfaces/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-write-signing.d.ts +3 -4
- package/dist/types/src/interfaces/records-write-signing.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-write.d.ts +11 -11
- package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
- package/dist/types/src/protocols/permission-grant.d.ts +1 -1
- package/dist/types/src/protocols/permission-grant.d.ts.map +1 -1
- package/dist/types/src/protocols/permission-request.d.ts +1 -1
- package/dist/types/src/protocols/permission-request.d.ts.map +1 -1
- package/dist/types/src/protocols/permissions.d.ts +40 -3
- package/dist/types/src/protocols/permissions.d.ts.map +1 -1
- package/dist/types/src/state-index/state-index-level.d.ts.map +1 -1
- package/dist/types/src/store/data-store-level.d.ts +20 -4
- package/dist/types/src/store/data-store-level.d.ts.map +1 -1
- package/dist/types/src/store/index-level.d.ts +4 -0
- package/dist/types/src/store/index-level.d.ts.map +1 -1
- package/dist/types/src/store/storage-controller.d.ts +20 -6
- package/dist/types/src/store/storage-controller.d.ts.map +1 -1
- package/dist/types/src/types/message-types.d.ts +3 -3
- package/dist/types/src/types/message-types.d.ts.map +1 -1
- package/dist/types/src/types/messages-types.d.ts +12 -3
- package/dist/types/src/types/messages-types.d.ts.map +1 -1
- package/dist/types/src/types/method-handler.d.ts +24 -3
- package/dist/types/src/types/method-handler.d.ts.map +1 -1
- package/dist/types/src/types/permission-types.d.ts +7 -0
- package/dist/types/src/types/permission-types.d.ts.map +1 -1
- package/dist/types/src/types/protocols-types.d.ts +69 -2
- package/dist/types/src/types/protocols-types.d.ts.map +1 -1
- package/dist/types/src/types/records-types.d.ts +23 -6
- package/dist/types/src/types/records-types.d.ts.map +1 -1
- package/dist/types/src/types/subscriptions.d.ts +151 -13
- package/dist/types/src/types/subscriptions.d.ts.map +1 -1
- package/dist/types/src/utils/hd-key.d.ts +1 -9
- package/dist/types/src/utils/hd-key.d.ts.map +1 -1
- package/dist/types/src/utils/messages.d.ts +7 -5
- package/dist/types/src/utils/messages.d.ts.map +1 -1
- package/dist/types/src/utils/records.d.ts +1 -11
- package/dist/types/src/utils/records.d.ts.map +1 -1
- package/dist/types/tests/dwn.spec.d.ts.map +1 -1
- package/dist/types/tests/event-emitter-event-log.spec.d.ts +2 -0
- package/dist/types/tests/event-emitter-event-log.spec.d.ts.map +1 -0
- package/dist/types/tests/features/author-delegated-grant.spec.d.ts.map +1 -1
- package/dist/types/tests/features/owner-delegated-grant.spec.d.ts.map +1 -1
- package/dist/types/tests/features/owner-signature.spec.d.ts.map +1 -1
- package/dist/types/tests/features/protocol-composition.spec.d.ts.map +1 -1
- package/dist/types/tests/features/records-delivery.spec.d.ts +2 -0
- package/dist/types/tests/features/records-delivery.spec.d.ts.map +1 -0
- package/dist/types/tests/features/records-immutable.spec.d.ts +2 -0
- package/dist/types/tests/features/records-immutable.spec.d.ts.map +1 -0
- package/dist/types/tests/features/records-record-limit.spec.d.ts +2 -0
- package/dist/types/tests/features/records-record-limit.spec.d.ts.map +1 -0
- package/dist/types/tests/features/records-squash.spec.d.ts +2 -0
- package/dist/types/tests/features/records-squash.spec.d.ts.map +1 -0
- package/dist/types/tests/features/records-tags.spec.d.ts.map +1 -1
- package/dist/types/tests/features/resumable-tasks.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/messages-sync.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/deleted-record.spec.d.ts.map +1 -1
- package/dist/types/tests/scenarios/subscriptions.spec.d.ts.map +1 -1
- package/dist/types/tests/test-event-stream.d.ts +11 -12
- package/dist/types/tests/test-event-stream.d.ts.map +1 -1
- package/dist/types/tests/test-suite.d.ts +2 -2
- package/dist/types/tests/test-suite.d.ts.map +1 -1
- package/dist/types/tests/utils/test-data-generator.d.ts +19 -0
- package/dist/types/tests/utils/test-data-generator.d.ts.map +1 -1
- package/package.json +5 -4
- package/src/core/constants.ts +11 -0
- package/src/core/core-protocol.ts +129 -0
- package/src/core/dwn-error.ts +18 -12
- package/src/core/grant-authorization.ts +20 -3
- package/src/core/protocol-authorization-action.ts +5 -0
- package/src/core/protocol-authorization-validation.ts +133 -0
- package/src/core/protocol-authorization.ts +71 -23
- package/src/core/records-grant-authorization.ts +6 -8
- package/src/core/resumable-task-manager.ts +3 -1
- package/src/dwn.ts +58 -73
- package/src/event-stream/event-emitter-event-log.ts +283 -0
- package/src/handlers/messages-read.ts +8 -9
- package/src/handlers/messages-subscribe.ts +24 -28
- package/src/handlers/messages-sync.ts +10 -16
- package/src/handlers/protocols-configure.ts +47 -32
- package/src/handlers/protocols-query.ts +6 -9
- package/src/handlers/records-count.ts +11 -10
- package/src/handlers/records-delete.ts +12 -21
- package/src/handlers/records-query.ts +12 -12
- package/src/handlers/records-read.ts +34 -22
- package/src/handlers/records-subscribe.ts +47 -26
- package/src/handlers/records-write.ts +152 -119
- package/src/index.ts +9 -5
- package/src/interfaces/messages-subscribe.ts +7 -1
- package/src/interfaces/protocols-configure.ts +51 -3
- package/src/interfaces/records-count.ts +1 -1
- package/src/interfaces/records-delete.ts +1 -1
- package/src/interfaces/records-query.ts +1 -1
- package/src/interfaces/records-read.ts +1 -1
- package/src/interfaces/records-subscribe.ts +8 -1
- package/src/interfaces/records-write-signing.ts +2 -22
- package/src/interfaces/records-write.ts +35 -48
- package/src/protocols/permission-grant.ts +1 -1
- package/src/protocols/permission-request.ts +1 -1
- package/src/protocols/permissions.ts +148 -6
- package/src/state-index/state-index-level.ts +5 -7
- package/src/store/data-store-level.ts +124 -34
- package/src/store/index-level.ts +44 -35
- package/src/store/storage-controller.ts +89 -12
- package/src/types/message-types.ts +3 -3
- package/src/types/messages-types.ts +12 -3
- package/src/types/method-handler.ts +26 -4
- package/src/types/mitt.d.ts +28 -0
- package/src/types/permission-types.ts +7 -0
- package/src/types/protocols-types.ts +78 -1
- package/src/types/records-types.ts +24 -6
- package/src/types/subscriptions.ts +178 -14
- package/src/utils/hd-key.ts +0 -9
- package/src/utils/messages.ts +17 -37
- package/src/utils/records.ts +7 -58
- package/dist/esm/src/event-stream/event-emitter-stream.js +0 -46
- package/dist/esm/src/event-stream/event-emitter-stream.js.map +0 -1
- package/dist/esm/tests/event-stream/event-emitter-stream.spec.js +0 -68
- package/dist/esm/tests/event-stream/event-emitter-stream.spec.js.map +0 -1
- package/dist/esm/tests/event-stream/event-stream.spec.js +0 -114
- package/dist/esm/tests/event-stream/event-stream.spec.js.map +0 -1
- package/dist/types/src/event-stream/event-emitter-stream.d.ts +0 -23
- package/dist/types/src/event-stream/event-emitter-stream.d.ts.map +0 -1
- package/dist/types/tests/event-stream/event-emitter-stream.spec.d.ts +0 -2
- package/dist/types/tests/event-stream/event-emitter-stream.spec.d.ts.map +0 -1
- package/dist/types/tests/event-stream/event-stream.spec.d.ts +0 -2
- package/dist/types/tests/event-stream/event-stream.spec.d.ts.map +0 -1
- package/src/event-stream/event-emitter-stream.ts +0 -69
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CoreProtocolRegistry } from '../core/core-protocol.js';
|
|
2
2
|
import type { MessageSort } from '../types/message-types.js';
|
|
3
3
|
import type { MessageStore } from '../types//message-store.js';
|
|
4
|
-
import type {
|
|
5
|
-
import type { EventListener, EventStream } from '../types/subscriptions.js';
|
|
4
|
+
import type { SubscriptionListener } from '../types/subscriptions.js';
|
|
6
5
|
import type { Filter, PaginationCursor } from '../types/query-types.js';
|
|
7
|
-
import type {
|
|
6
|
+
import type { HandlerDependencies, MethodHandler } from '../types/method-handler.js';
|
|
7
|
+
import type { RecordsQueryReplyEntry, RecordsSubscribeMessage, RecordsSubscribeReply } from '../types/records-types.js';
|
|
8
8
|
|
|
9
9
|
import { authenticate } from '../core/auth.js';
|
|
10
10
|
import { DateSort } from '../types/records-types.js';
|
|
11
|
-
import { FilterUtility } from '../utils/filter.js';
|
|
12
11
|
import { Message } from '../core/message.js';
|
|
13
12
|
import { messageReplyFromError } from '../core/message-reply.js';
|
|
14
13
|
import { ProtocolAuthorization } from '../core/protocol-authorization.js';
|
|
@@ -21,7 +20,7 @@ import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.j
|
|
|
21
20
|
|
|
22
21
|
export class RecordsSubscribeHandler implements MethodHandler {
|
|
23
22
|
|
|
24
|
-
constructor(private
|
|
23
|
+
constructor(private deps: HandlerDependencies) { }
|
|
25
24
|
|
|
26
25
|
public async handle({
|
|
27
26
|
tenant,
|
|
@@ -30,11 +29,11 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
30
29
|
}: {
|
|
31
30
|
tenant: string,
|
|
32
31
|
message: RecordsSubscribeMessage,
|
|
33
|
-
subscriptionHandler:
|
|
32
|
+
subscriptionHandler: SubscriptionListener,
|
|
34
33
|
}): Promise<RecordsSubscribeReply> {
|
|
35
|
-
if (this.
|
|
34
|
+
if (this.deps.eventLog === undefined) {
|
|
36
35
|
return messageReplyFromError(new DwnError(
|
|
37
|
-
DwnErrorCode.
|
|
36
|
+
DwnErrorCode.RecordsSubscribeEventLogUnimplemented,
|
|
38
37
|
'Subscriptions are not supported'
|
|
39
38
|
), 501);
|
|
40
39
|
}
|
|
@@ -59,8 +58,8 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
59
58
|
} else {
|
|
60
59
|
// authentication and authorization
|
|
61
60
|
try {
|
|
62
|
-
await authenticate(message.authorization!, this.didResolver);
|
|
63
|
-
await RecordsSubscribeHandler.authorizeRecordsSubscribe(tenant, recordsSubscribe, this.messageStore);
|
|
61
|
+
await authenticate(message.authorization!, this.deps.didResolver);
|
|
62
|
+
await RecordsSubscribeHandler.authorizeRecordsSubscribe(tenant, recordsSubscribe, this.deps.messageStore, this.deps.coreProtocols);
|
|
64
63
|
} catch (error) {
|
|
65
64
|
return messageReplyFromError(error, 401);
|
|
66
65
|
}
|
|
@@ -74,30 +73,51 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
74
73
|
}
|
|
75
74
|
}
|
|
76
75
|
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
const messageCid = await Message.getCid(message);
|
|
77
|
+
const { cursor: eventLogCursor } = recordsSubscribe.message.descriptor;
|
|
78
|
+
|
|
79
|
+
if (eventLogCursor !== undefined) {
|
|
80
|
+
// ---- Cursor mode: catch-up from EventLog + EOSE + live ----
|
|
81
|
+
// All catch-up, buffering, dedup, and EOSE delivery are handled by the
|
|
82
|
+
// EventLog implementation. The handler just passes the cursor and filters.
|
|
83
|
+
// The subscriptionHandler receives SubscriptionMessage (event + EOSE) directly.
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
const subscription = await this.deps.eventLog!.subscribe(tenant, messageCid, subscriptionHandler, {
|
|
87
|
+
cursor : eventLogCursor,
|
|
88
|
+
filters : eventFilters,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
status: { code: 200, detail: 'OK' },
|
|
93
|
+
subscription,
|
|
94
|
+
};
|
|
95
|
+
} catch (error) {
|
|
96
|
+
return messageReplyFromError(error, 500);
|
|
81
97
|
}
|
|
82
|
-
}
|
|
98
|
+
}
|
|
83
99
|
|
|
84
|
-
|
|
85
|
-
|
|
100
|
+
// ---- No cursor: existing behavior (initial snapshot from MessageStore) ----
|
|
101
|
+
|
|
102
|
+
// Step 1: Register event listener FIRST to ensure no events are missed between query and subscribe
|
|
103
|
+
const subscription = await this.deps.eventLog!.subscribe(tenant, messageCid, subscriptionHandler, {
|
|
104
|
+
filters: eventFilters,
|
|
105
|
+
});
|
|
86
106
|
|
|
87
107
|
// Step 2: Query for initial snapshot of matching records
|
|
88
108
|
let entries: RecordsQueryReplyEntry[];
|
|
89
|
-
let
|
|
109
|
+
let paginationCursor: PaginationCursor | undefined;
|
|
90
110
|
try {
|
|
91
111
|
const { dateSort, pagination } = recordsSubscribe.message.descriptor;
|
|
92
112
|
const messageSort = RecordsSubscribeHandler.convertDateSort(dateSort);
|
|
93
|
-
const queryResult = await this.messageStore.query(tenant, queryFilters, messageSort, pagination);
|
|
113
|
+
const queryResult = await this.deps.messageStore.query(tenant, queryFilters, messageSort, pagination);
|
|
94
114
|
entries = queryResult.messages as RecordsQueryReplyEntry[];
|
|
95
|
-
|
|
115
|
+
paginationCursor = queryResult.cursor;
|
|
96
116
|
|
|
97
117
|
// attach initialWrite for non-initial writes
|
|
98
118
|
for (const entry of entries) {
|
|
99
119
|
if (!await RecordsWrite.isInitialWrite(entry)) {
|
|
100
|
-
const initialWriteResult = await this.messageStore.query(
|
|
120
|
+
const initialWriteResult = await this.deps.messageStore.query(
|
|
101
121
|
tenant,
|
|
102
122
|
[{ recordId: entry.recordId, isLatestBaseState: false, method: DwnMethodName.Write }]
|
|
103
123
|
);
|
|
@@ -114,10 +134,10 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
114
134
|
|
|
115
135
|
// Step 3: Return subscription + initial entries + cursor
|
|
116
136
|
return {
|
|
117
|
-
status: { code: 200, detail: 'OK' },
|
|
137
|
+
status : { code: 200, detail: 'OK' },
|
|
118
138
|
subscription,
|
|
119
139
|
entries,
|
|
120
|
-
cursor
|
|
140
|
+
cursor : paginationCursor,
|
|
121
141
|
};
|
|
122
142
|
}
|
|
123
143
|
|
|
@@ -300,7 +320,8 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
300
320
|
public static async authorizeRecordsSubscribe(
|
|
301
321
|
tenant: string,
|
|
302
322
|
recordsSubscribe: RecordsSubscribe,
|
|
303
|
-
messageStore: MessageStore
|
|
323
|
+
messageStore: MessageStore,
|
|
324
|
+
coreProtocols?: CoreProtocolRegistry,
|
|
304
325
|
): Promise<void> {
|
|
305
326
|
|
|
306
327
|
if (Message.isSignedByAuthorDelegate(recordsSubscribe.message)) {
|
|
@@ -311,7 +332,7 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
311
332
|
// this is because we dynamically filter out records that the caller is not authorized to see.
|
|
312
333
|
// Currently only run protocol authorization if message deliberately invokes a protocol role.
|
|
313
334
|
if (Records.shouldProtocolAuthorize(recordsSubscribe.signaturePayload!)) {
|
|
314
|
-
await ProtocolAuthorization.authorizeQueryOrSubscribe(tenant, recordsSubscribe, messageStore);
|
|
335
|
+
await ProtocolAuthorization.authorizeQueryOrSubscribe(tenant, recordsSubscribe, messageStore, coreProtocols);
|
|
315
336
|
}
|
|
316
337
|
}
|
|
317
338
|
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { DidResolver } from '@enbox/dids';
|
|
3
|
-
import type { EventStream } from '../types/subscriptions.js';
|
|
1
|
+
import type { Filter } from '../types/query-types.js';
|
|
4
2
|
import type { GenericMessageReply } from '../types/message-types.js';
|
|
5
3
|
import type { MessageStore } from '../types/message-store.js';
|
|
6
|
-
import type { MethodHandler } from '../types/method-handler.js';
|
|
7
|
-
import type { StateIndex } from '../types/state-index.js';
|
|
4
|
+
import type { HandlerDependencies, MethodHandler } from '../types/method-handler.js';
|
|
8
5
|
import type { RecordsQueryReplyEntry, RecordsWriteMessage } from '../types/records-types.js';
|
|
9
6
|
|
|
10
7
|
import { authenticate } from '../core/auth.js';
|
|
@@ -12,12 +9,16 @@ import { Cid } from '../utils/cid.js';
|
|
|
12
9
|
import { DataStream } from '../utils/data-stream.js';
|
|
13
10
|
import { DwnConstant } from '../core/dwn-constant.js';
|
|
14
11
|
import { Encoder } from '../utils/encoder.js';
|
|
12
|
+
import { FilterUtility } from '../utils/filter.js';
|
|
15
13
|
import { Message } from '../core/message.js';
|
|
16
14
|
import { messageReplyFromError } from '../core/message-reply.js';
|
|
17
15
|
import { PermissionsProtocol } from '../protocols/permissions.js';
|
|
18
16
|
import { ProtocolAuthorization } from '../core/protocol-authorization.js';
|
|
17
|
+
import { Records } from '../utils/records.js';
|
|
19
18
|
import { RecordsGrantAuthorization } from '../core/records-grant-authorization.js';
|
|
20
19
|
import { RecordsWrite } from '../interfaces/records-write.js';
|
|
20
|
+
import { ResumableTaskName } from '../core/resumable-task-manager.js';
|
|
21
|
+
import { SortDirection } from '../types/query-types.js';
|
|
21
22
|
import { StorageController } from '../store/storage-controller.js';
|
|
22
23
|
import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
|
|
23
24
|
import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
|
|
@@ -26,13 +27,7 @@ type HandlerArgs = { tenant: string, message: RecordsWriteMessage, dataStream?:
|
|
|
26
27
|
|
|
27
28
|
export class RecordsWriteHandler implements MethodHandler {
|
|
28
29
|
|
|
29
|
-
constructor(
|
|
30
|
-
private didResolver: DidResolver,
|
|
31
|
-
private messageStore: MessageStore,
|
|
32
|
-
private dataStore: DataStore,
|
|
33
|
-
private stateIndex: StateIndex,
|
|
34
|
-
private eventStream?: EventStream
|
|
35
|
-
) { }
|
|
30
|
+
constructor(private deps: HandlerDependencies) { }
|
|
36
31
|
|
|
37
32
|
public async handle({
|
|
38
33
|
tenant,
|
|
@@ -43,18 +38,15 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
43
38
|
try {
|
|
44
39
|
recordsWrite = await RecordsWrite.parse(message);
|
|
45
40
|
|
|
46
|
-
|
|
47
|
-
if (message.descriptor.protocol !== undefined) {
|
|
48
|
-
await ProtocolAuthorization.validateReferentialIntegrity(tenant, recordsWrite, this.messageStore);
|
|
49
|
-
}
|
|
41
|
+
await ProtocolAuthorization.validateReferentialIntegrity(tenant, recordsWrite, this.deps.messageStore, this.deps.coreProtocols);
|
|
50
42
|
} catch (e) {
|
|
51
43
|
return messageReplyFromError(e, 400);
|
|
52
44
|
}
|
|
53
45
|
|
|
54
46
|
// authentication & authorization
|
|
55
47
|
try {
|
|
56
|
-
await authenticate(message.authorization, this.didResolver, message.attestation);
|
|
57
|
-
await
|
|
48
|
+
await authenticate(message.authorization, this.deps.didResolver, message.attestation);
|
|
49
|
+
await this.authorizeRecordsWrite(tenant, recordsWrite, this.deps.messageStore);
|
|
58
50
|
} catch (e) {
|
|
59
51
|
return messageReplyFromError(e, 401);
|
|
60
52
|
}
|
|
@@ -64,7 +56,7 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
64
56
|
interface : DwnInterfaceName.Records,
|
|
65
57
|
recordId : message.recordId
|
|
66
58
|
};
|
|
67
|
-
const { messages: existingMessages } = await this.messageStore.query(tenant, [ query ]);
|
|
59
|
+
const { messages: existingMessages } = await this.deps.messageStore.query(tenant, [ query ]);
|
|
68
60
|
|
|
69
61
|
// if the incoming write is not the initial write, then it must not modify any immutable properties defined by the initial write
|
|
70
62
|
const newMessageIsInitialWrite = await recordsWrite.isInitialWrite();
|
|
@@ -78,6 +70,15 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
78
70
|
}
|
|
79
71
|
}
|
|
80
72
|
|
|
73
|
+
// Squash backstop: if the protocol path has $squash: true, reject any write whose
|
|
74
|
+
// messageTimestamp is <= the most recent squash record at the same path and parent context.
|
|
75
|
+
// The squash record acts as a temporal floor — no record older than the latest squash can exist.
|
|
76
|
+
try {
|
|
77
|
+
await this.enforceSquashBackstop(tenant, message);
|
|
78
|
+
} catch (e) {
|
|
79
|
+
return messageReplyFromError(e, 409);
|
|
80
|
+
}
|
|
81
|
+
|
|
81
82
|
const newestExistingMessage = await Message.getNewestMessage(existingMessages);
|
|
82
83
|
|
|
83
84
|
let incomingMessageIsNewest = false;
|
|
@@ -95,6 +96,12 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
95
96
|
};
|
|
96
97
|
}
|
|
97
98
|
|
|
99
|
+
// Look up the core protocol (if any) for the incoming message so that lifecycle hooks
|
|
100
|
+
// can be dispatched generically rather than checking for specific protocol URIs.
|
|
101
|
+
const coreProtocol = message.descriptor.protocol !== undefined
|
|
102
|
+
? this.deps.coreProtocols?.get(message.descriptor.protocol)
|
|
103
|
+
: undefined;
|
|
104
|
+
|
|
98
105
|
try {
|
|
99
106
|
if (newestExistingMessage?.descriptor.method === DwnMethodName.Delete) {
|
|
100
107
|
throw new DwnError(
|
|
@@ -103,11 +110,12 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
103
110
|
);
|
|
104
111
|
}
|
|
105
112
|
|
|
106
|
-
//
|
|
107
|
-
// This
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
|
|
113
|
+
// Dispatch pre-processing hooks to the core protocol, if applicable.
|
|
114
|
+
// This allows core protocols to perform cross-record validation before storage
|
|
115
|
+
// (e.g. ensuring revocation tag consistency with the parent grant's scoped protocol).
|
|
116
|
+
if (coreProtocol?.preProcessWrite !== undefined) {
|
|
117
|
+
await coreProtocol.preProcessWrite(tenant, message, this.deps.messageStore);
|
|
118
|
+
}
|
|
111
119
|
|
|
112
120
|
// 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
|
|
113
121
|
// This would allow an initial write to be written to the DB without data, but having it not queryable,
|
|
@@ -133,14 +141,14 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
133
141
|
}
|
|
134
142
|
|
|
135
143
|
const indexes = await recordsWrite.constructIndexes(isLatestBaseState);
|
|
136
|
-
await this.messageStore.put(tenant, messageWithOptionalEncodedData, indexes);
|
|
137
|
-
await this.stateIndex
|
|
144
|
+
await this.deps.messageStore.put(tenant, messageWithOptionalEncodedData, indexes);
|
|
145
|
+
await this.deps.stateIndex!.insert(tenant, await Message.getCid(message), indexes);
|
|
138
146
|
|
|
139
147
|
// NOTE: We only emit a `RecordsWrite` when the message is the latest base state.
|
|
140
148
|
// Because we allow a `RecordsWrite` which is not the latest state to be written, but not queried, we shouldn't emit it either.
|
|
141
149
|
// It will be emitted as a part of a subsequent next write, if it is the latest base state.
|
|
142
|
-
if (this.
|
|
143
|
-
this.
|
|
150
|
+
if (this.deps.eventLog !== undefined && isLatestBaseState) {
|
|
151
|
+
await this.deps.eventLog.emit(tenant, { message, initialWrite }, indexes);
|
|
144
152
|
}
|
|
145
153
|
} catch (error) {
|
|
146
154
|
if (error instanceof DwnError) {
|
|
@@ -149,8 +157,8 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
149
157
|
error.code === DwnErrorCode.RecordsWriteNotAllowedAfterDelete ||
|
|
150
158
|
error.code === DwnErrorCode.RecordsWriteDataCidMismatch ||
|
|
151
159
|
error.code === DwnErrorCode.RecordsWriteDataSizeMismatch ||
|
|
152
|
-
error.code.startsWith('
|
|
153
|
-
error.code
|
|
160
|
+
error.code.startsWith('SchemaValidator') ||
|
|
161
|
+
this.deps.coreProtocols?.mapErrorToStatusCode(error.code) !== undefined) {
|
|
154
162
|
return messageReplyFromError(error, 400);
|
|
155
163
|
}
|
|
156
164
|
}
|
|
@@ -170,93 +178,31 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
170
178
|
|
|
171
179
|
// delete all existing messages of the same record that are not newest, except for the initial write
|
|
172
180
|
await StorageController.deleteAllOlderMessagesButKeepInitialWrite(
|
|
173
|
-
tenant, existingMessages, newestMessage, this.messageStore, this.dataStore
|
|
181
|
+
tenant, existingMessages, newestMessage, this.deps.messageStore, this.deps.dataStore!, this.deps.stateIndex!
|
|
174
182
|
);
|
|
175
183
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
* For instance: a Permission revocation RecordsWrite.
|
|
184
|
-
*/
|
|
185
|
-
private async preProcessingForCoreRecordsWrite(tenant: string, recordsWriteMessage: RecordsWriteMessage): Promise<void> {
|
|
186
|
-
|
|
187
|
-
// we validate the protocol tag of the revocation message against the grant's scoped protocol
|
|
188
|
-
// to do this we will fetch the grant, and compare the the scoped protocol value to the protocol tag of the revocation message
|
|
189
|
-
if (recordsWriteMessage.descriptor.protocol === PermissionsProtocol.uri &&
|
|
190
|
-
recordsWriteMessage.descriptor.protocolPath === PermissionsProtocol.revocationPath) {
|
|
191
|
-
|
|
192
|
-
// get the parentId of the revocation message, which is the permissionGrantId
|
|
193
|
-
// fetch the grant in order to get the grant's protocol
|
|
194
|
-
const permissionGrantId = recordsWriteMessage.descriptor.parentId!;
|
|
195
|
-
const grant = await PermissionsProtocol.fetchGrant(tenant, this.messageStore, permissionGrantId);
|
|
196
|
-
|
|
197
|
-
// get the protocol values of the revocation message from the protocol tag and the protocol from the grant scope if they are defined
|
|
198
|
-
// compare the two values ensuring they must match
|
|
199
|
-
const revokeTagProtocol = recordsWriteMessage.descriptor.tags?.protocol;
|
|
200
|
-
const grantProtocol = 'protocol' in grant.scope ? grant.scope.protocol : undefined;
|
|
201
|
-
if (grantProtocol !== revokeTagProtocol) {
|
|
202
|
-
throw new DwnError(
|
|
203
|
-
DwnErrorCode.PermissionsProtocolValidateRevocationProtocolTagMismatch,
|
|
204
|
-
`Revocation protocol ${revokeTagProtocol} does not match grant protocol ${grantProtocol}`
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
private static validateSchemaForCoreRecordsWrite(recordsWriteMessage: RecordsWriteMessage, dataBytes: Uint8Array): void {
|
|
211
|
-
if (recordsWriteMessage.descriptor.protocol === PermissionsProtocol.uri) {
|
|
212
|
-
PermissionsProtocol.validateSchema(recordsWriteMessage, dataBytes);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Performs additional necessary tasks if the RecordsWrite handled is a core DWN RecordsWrite that need additional processing.
|
|
218
|
-
* For instance: when a Permission revocation is written, all messages authorized by the revoked grant
|
|
219
|
-
* that were created after the revocation timestamp are deleted from all stores.
|
|
220
|
-
*/
|
|
221
|
-
private async postProcessingForCoreRecordsWrite(tenant: string, recordsWrite: RecordsWrite): Promise<void> {
|
|
222
|
-
if (recordsWrite.message.descriptor.protocol !== PermissionsProtocol.uri ||
|
|
223
|
-
recordsWrite.message.descriptor.protocolPath !== PermissionsProtocol.revocationPath) {
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// Delete all messages authorized by the revoked grant that were created after the revocation.
|
|
228
|
-
// `permissionGrantId` is indexed via the RecordsWriteDescriptor spread in constructIndexes().
|
|
229
|
-
const permissionGrantId = recordsWrite.message.descriptor.parentId!;
|
|
230
|
-
const grantAuthorizedMessagesQuery = {
|
|
231
|
-
permissionGrantId,
|
|
232
|
-
dateCreated: { gte: recordsWrite.message.descriptor.messageTimestamp },
|
|
233
|
-
};
|
|
234
|
-
const { messages: grantAuthorizedMessages } = await this.messageStore.query(tenant, [grantAuthorizedMessagesQuery]);
|
|
235
|
-
|
|
236
|
-
if (grantAuthorizedMessages.length === 0) {
|
|
237
|
-
return;
|
|
184
|
+
// Squash processing: if the incoming write is a squash, delete all older sibling records
|
|
185
|
+
// at the same protocol path and parent context. Uses the resumable task system for crash safety.
|
|
186
|
+
if (message.descriptor.squash === true) {
|
|
187
|
+
await this.deps.resumableTaskManager!.run({
|
|
188
|
+
name : ResumableTaskName.RecordsSquash,
|
|
189
|
+
data : { tenant, message }
|
|
190
|
+
});
|
|
238
191
|
}
|
|
239
192
|
|
|
240
|
-
//
|
|
241
|
-
//
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
193
|
+
// Dispatch post-processing hooks to the core protocol, if applicable.
|
|
194
|
+
// This allows core protocols to perform cascading side effects after a successful write
|
|
195
|
+
// (e.g. deleting messages authorized by a revoked grant).
|
|
196
|
+
if (coreProtocol?.postProcessWrite !== undefined) {
|
|
197
|
+
await coreProtocol.postProcessWrite(tenant, recordsWrite, {
|
|
198
|
+
messageStore : this.deps.messageStore,
|
|
199
|
+
dataStore : this.deps.dataStore!,
|
|
200
|
+
stateIndex : this.deps.stateIndex!,
|
|
201
|
+
});
|
|
249
202
|
}
|
|
250
203
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
// Delete from state index before message store so we don't have orphaned state entries.
|
|
255
|
-
await this.stateIndex.delete(tenant, messageCids);
|
|
256
|
-
|
|
257
|
-
// Finally delete all messages from the message store.
|
|
258
|
-
await Promise.all(messageCids.map((cid): Promise<void> => this.messageStore.delete(tenant, cid)));
|
|
259
|
-
}
|
|
204
|
+
return messageReply;
|
|
205
|
+
};
|
|
260
206
|
|
|
261
207
|
/**
|
|
262
208
|
* Returns a `RecordsQueryReplyEntry` with a copy of the incoming message and the incoming data encoded to `Base64URL`.
|
|
@@ -281,7 +227,13 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
281
227
|
const dataCid = await Cid.computeDagPbCidFromBytes(dataBytes);
|
|
282
228
|
RecordsWriteHandler.validateDataIntegrity(message.descriptor.dataCid, message.descriptor.dataSize, dataCid, dataBytes.length);
|
|
283
229
|
|
|
284
|
-
|
|
230
|
+
// Dispatch schema validation to the core protocol, if applicable.
|
|
231
|
+
const coreProtocol = message.descriptor.protocol !== undefined
|
|
232
|
+
? this.deps.coreProtocols?.get(message.descriptor.protocol)
|
|
233
|
+
: undefined;
|
|
234
|
+
if (coreProtocol?.validateRecord !== undefined) {
|
|
235
|
+
coreProtocol.validateRecord(message, dataBytes);
|
|
236
|
+
}
|
|
285
237
|
|
|
286
238
|
messageWithOptionalEncodedData = await this.cloneAndAddEncodedData(message, dataBytes);
|
|
287
239
|
} else {
|
|
@@ -292,13 +244,13 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
292
244
|
// perform storage and CID computation in parallel
|
|
293
245
|
const [dataCid, DataStorePutResult] = await Promise.all([
|
|
294
246
|
Cid.computeDagPbCidFromStream(dataStreamCopy1),
|
|
295
|
-
this.dataStore
|
|
247
|
+
this.deps.dataStore!.put(tenant, message.recordId, message.descriptor.dataCid, dataStreamCopy2)
|
|
296
248
|
]);
|
|
297
249
|
|
|
298
250
|
RecordsWriteHandler.validateDataIntegrity(message.descriptor.dataCid, message.descriptor.dataSize, dataCid, DataStorePutResult.dataSize);
|
|
299
251
|
} catch (error) {
|
|
300
252
|
// unwind/delete data if we have issue with storage or the data failed integrity validation
|
|
301
|
-
await this.dataStore
|
|
253
|
+
await this.deps.dataStore!.delete(tenant, message.recordId, message.descriptor.dataCid);
|
|
302
254
|
|
|
303
255
|
throw error;
|
|
304
256
|
}
|
|
@@ -335,7 +287,7 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
335
287
|
// else just make sure the data is in the data store
|
|
336
288
|
|
|
337
289
|
// attempt to retrieve the data from the previous message
|
|
338
|
-
const DataStoreGetResult = await this.dataStore
|
|
290
|
+
const DataStoreGetResult = await this.deps.dataStore!.get(tenant, newestExistingWrite.recordId, message.descriptor.dataCid);
|
|
339
291
|
|
|
340
292
|
if (DataStoreGetResult === undefined) {
|
|
341
293
|
throw new DwnError(
|
|
@@ -377,7 +329,90 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
377
329
|
}
|
|
378
330
|
}
|
|
379
331
|
|
|
380
|
-
|
|
332
|
+
/**
|
|
333
|
+
* Enforces the squash backstop: if the incoming message is at a protocol path with `$squash: true`,
|
|
334
|
+
* and there exists a squash record at the same protocol path and parent context whose
|
|
335
|
+
* `messageTimestamp` is >= the incoming message's `messageTimestamp`, reject with 409.
|
|
336
|
+
*
|
|
337
|
+
* This check only applies to protocol-based records at `$squash: true` paths.
|
|
338
|
+
*/
|
|
339
|
+
private async enforceSquashBackstop(tenant: string, message: RecordsWriteMessage): Promise<void> {
|
|
340
|
+
// Only applies to protocol-based records
|
|
341
|
+
if (message.descriptor.protocol === undefined || message.descriptor.protocolPath === undefined) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Fetch the protocol definition to check if $squash is enabled at this path.
|
|
346
|
+
// Pass coreProtocols so that core protocols (e.g. permissions) are resolved from the registry.
|
|
347
|
+
let protocolDefinition;
|
|
348
|
+
try {
|
|
349
|
+
protocolDefinition = await ProtocolAuthorization.fetchProtocolDefinition(
|
|
350
|
+
tenant,
|
|
351
|
+
message.descriptor.protocol,
|
|
352
|
+
this.deps.messageStore,
|
|
353
|
+
undefined,
|
|
354
|
+
this.deps.coreProtocols,
|
|
355
|
+
);
|
|
356
|
+
} catch (error) {
|
|
357
|
+
// If the protocol definition can't be found, skip the backstop check.
|
|
358
|
+
// Authorization will handle the missing protocol error later.
|
|
359
|
+
console.warn(`enforceSquashBackstop: failed to fetch protocol definition for '${message.descriptor.protocol}':`, error);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Walk the structure to find the rule set for this protocol path
|
|
364
|
+
const pathSegments = message.descriptor.protocolPath.split('/');
|
|
365
|
+
let ruleSet = protocolDefinition.structure[pathSegments[0]];
|
|
366
|
+
for (let i = 1; i < pathSegments.length && ruleSet !== undefined; i++) {
|
|
367
|
+
ruleSet = ruleSet[pathSegments[i]] as typeof ruleSet;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (ruleSet === undefined || ruleSet.$squash !== true) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Find the most recent squash record at the same protocol path and parent context
|
|
375
|
+
const filter: Filter = {
|
|
376
|
+
interface : DwnInterfaceName.Records,
|
|
377
|
+
method : DwnMethodName.Write,
|
|
378
|
+
isLatestBaseState : true,
|
|
379
|
+
protocol : message.descriptor.protocol,
|
|
380
|
+
protocolPath : message.descriptor.protocolPath,
|
|
381
|
+
squash : true,
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
// Scope by parent context for nested records
|
|
385
|
+
const parentContextId = Records.getParentContextFromOfContextId(message.contextId);
|
|
386
|
+
if (parentContextId !== undefined && parentContextId !== '') {
|
|
387
|
+
const prefixFilter = FilterUtility.constructPrefixFilterAsRangeFilter(parentContextId);
|
|
388
|
+
filter.contextId = prefixFilter;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const { messages: squashMessages } = await this.deps.messageStore.query(
|
|
392
|
+
tenant,
|
|
393
|
+
[filter],
|
|
394
|
+
{ messageTimestamp: SortDirection.Descending },
|
|
395
|
+
{ limit: 1 },
|
|
396
|
+
);
|
|
397
|
+
|
|
398
|
+
if (squashMessages.length === 0) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const newestSquash = squashMessages[0] as RecordsWriteMessage;
|
|
403
|
+
|
|
404
|
+
// Reject if the incoming message's timestamp is <= the squash record's timestamp
|
|
405
|
+
if (message.descriptor.messageTimestamp <= newestSquash.descriptor.messageTimestamp) {
|
|
406
|
+
throw new DwnError(
|
|
407
|
+
DwnErrorCode.ProtocolAuthorizationSquashBackstop,
|
|
408
|
+
`incoming message timestamp '${message.descriptor.messageTimestamp}' is not newer than ` +
|
|
409
|
+
`the most recent squash record timestamp '${newestSquash.descriptor.messageTimestamp}' ` +
|
|
410
|
+
`at protocol path '${message.descriptor.protocolPath}'.`
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
private async authorizeRecordsWrite(tenant: string, recordsWrite: RecordsWrite, messageStore: MessageStore): Promise<void> {
|
|
381
416
|
// if owner signature is given (`owner` is not `undefined`), it must be the same as the tenant DID
|
|
382
417
|
if (recordsWrite.owner !== undefined && recordsWrite.owner !== tenant) {
|
|
383
418
|
throw new DwnError(
|
|
@@ -410,10 +445,8 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
410
445
|
permissionGrant,
|
|
411
446
|
messageStore
|
|
412
447
|
});
|
|
413
|
-
} else if (recordsWrite.message.descriptor.protocol !== undefined) {
|
|
414
|
-
await ProtocolAuthorization.authorizeWrite(tenant, recordsWrite, messageStore);
|
|
415
448
|
} else {
|
|
416
|
-
|
|
449
|
+
await ProtocolAuthorization.authorizeWrite(tenant, recordsWrite, messageStore, this.deps.coreProtocols);
|
|
417
450
|
}
|
|
418
451
|
}
|
|
419
452
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
// export everything that we want to be consumable
|
|
2
2
|
export type { DwnConfig } from './dwn.js';
|
|
3
|
-
export type { EventListener,
|
|
3
|
+
export type { EventListener, EventLog, EventLogEntry, EventLogReadOptions, EventLogReadResult, EventLogSubscribeOptions, EventSubscription, MessageEvent, SubscriptionEose, SubscriptionEvent, SubscriptionListener, SubscriptionMessage, SubscriptionReply } from './types/subscriptions.js';
|
|
4
4
|
export type { AuthorizationModel, Descriptor, DelegatedGrantRecordsWriteMessage, GenericMessage, GenericMessageReply, GenericSignaturePayload, MessageSort, MessageSubscription, Pagination, QueryResultEntry, Status } from './types/message-types.js';
|
|
5
5
|
export type { MessagesFilter, MessagesReadMessage as MessagesReadMessage, MessagesReadReply as MessagesReadReply, MessagesReadReplyEntry as MessagesReadReplyEntry, MessagesReadDescriptor, MessagesSubscribeDescriptor, MessagesSubscribeMessage, MessagesSubscribeReply, MessageSubscriptionHandler, MessagesSubscribeMessageOptions, MessagesSyncAction, MessagesSyncDescriptor, MessagesSyncMessage, MessagesSyncReply } from './types/messages-types.js';
|
|
6
6
|
export type { GT, LT, Filter, FilterValue, KeyValues, EqualFilter, OneOfFilter, RangeFilter, RangeCriterion, PaginationCursor, QueryOptions, RangeValue, StartsWithFilter } from './types/query-types.js';
|
|
7
|
-
export type { ProtocolsConfigureDescriptor, ProtocolDefinition, ProtocolTypes, ProtocolRuleSet, ProtocolsQueryFilter, ProtocolsConfigureMessage, ProtocolsQueryMessage, ProtocolsQueryReply, ProtocolActionRule, ProtocolPathEncryption, ProtocolsQueryDescriptor, ProtocolSizeDefinition, ProtocolTagsDefinition, ProtocolTagSchema, ProtocolType, ProtocolUses } from './types/protocols-types.js';
|
|
7
|
+
export type { ProtocolsConfigureDescriptor, ProtocolDefinition, ProtocolTypes, ProtocolRuleSet, ProtocolsQueryFilter, ProtocolsConfigureMessage, ProtocolsQueryMessage, ProtocolsQueryReply, ProtocolActionRule, ProtocolDeliveryStrategy, ProtocolPathEncryption, ProtocolsQueryDescriptor, ProtocolRecordLimitDefinition, ProtocolSizeDefinition, ProtocolTagsDefinition, ProtocolTagSchema, ProtocolType, ProtocolUses } from './types/protocols-types.js';
|
|
8
|
+
export { ProtocolRecordLimitStrategy } from './types/protocols-types.js';
|
|
8
9
|
export type { DataEncodedRecordsWriteMessage, RecordsCountDescriptor, RecordsCountMessage, RecordsCountReply, RecordsDeleteMessage, RecordsFilter, RecordsQueryMessage, RecordsQueryReply, RecordsQueryReplyEntry, RecordsReadMessage, RecordsReadReply, RecordsSubscribeDescriptor, RecordsSubscribeMessage, RecordsSubscribeReply, RecordSubscriptionHandler, RecordsWriteDescriptor, RecordsWriteTags, RecordsWriteTagValue, RecordsWriteMessage, RecordsWriteSignaturePayload, RecordsDeleteDescriptor, RecordsQueryDescriptor, RecordsReadDescriptor, RecordsSubscribeMessageOptions, RecordsWriteMessageOptions, InternalRecordsWriteMessage, RecordEvent, RecordsWriteTagsFilter } from './types/records-types.js';
|
|
9
10
|
export type { GeneralJws, SignatureEntry } from './types/jws-types.js';
|
|
10
11
|
export { authenticate } from './core/auth.js';
|
|
12
|
+
export { CoreProtocolRegistry } from './core/core-protocol.js';
|
|
13
|
+
export { PERMISSIONS_REVOCATION_PATH } from './core/constants.js';
|
|
14
|
+
export type { CoreProtocol, CoreProtocolStores } from './core/core-protocol.js';
|
|
11
15
|
export { AllowAllTenantGate } from './core/tenant-gate.js';
|
|
12
16
|
export type { ActiveTenantCheckResult, TenantGate } from './core/tenant-gate.js';
|
|
13
17
|
export { Cid } from './utils/cid.js';
|
|
@@ -72,7 +76,7 @@ export { Time } from './utils/time.js';
|
|
|
72
76
|
export * from './types/permission-types.js';
|
|
73
77
|
export * from './types/records-types.js';
|
|
74
78
|
|
|
75
|
-
// concrete implementations of stores and event
|
|
79
|
+
// concrete implementations of stores and event log
|
|
76
80
|
export { BlockstoreLevel } from './store/blockstore-level.js';
|
|
77
81
|
export type { BlockstoreLevelConfig } from './store/blockstore-level.js';
|
|
78
82
|
export { DataStoreLevel } from './store/data-store-level.js';
|
|
@@ -85,8 +89,8 @@ export { MessageStoreLevel } from './store/message-store-level.js';
|
|
|
85
89
|
export type { MessageStoreLevelConfig } from './store/message-store-level.js';
|
|
86
90
|
export { ResumableTaskStoreLevel } from './store/resumable-task-store-level.js';
|
|
87
91
|
export type { ResumableTaskStoreLevelConfig } from './store/resumable-task-store-level.js';
|
|
88
|
-
export {
|
|
89
|
-
export type {
|
|
92
|
+
export { EventEmitterEventLog } from './event-stream/event-emitter-event-log.js';
|
|
93
|
+
export type { EventEmitterEventLogConfig } from './event-stream/event-emitter-event-log.js';
|
|
90
94
|
|
|
91
95
|
// Sparse Merkle Tree and StateIndex
|
|
92
96
|
export type { StateIndex } from './types/state-index.js';
|
|
@@ -13,8 +13,13 @@ import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.j
|
|
|
13
13
|
export type MessagesSubscribeOptions = {
|
|
14
14
|
signer: MessageSigner;
|
|
15
15
|
messageTimestamp?: string;
|
|
16
|
-
filters?: MessagesFilter[]
|
|
16
|
+
filters?: MessagesFilter[];
|
|
17
17
|
permissionGrantId?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Opaque EventLog cursor string to resume from. When provided, catch-up events are
|
|
20
|
+
* replayed from the EventLog and an EOSE marker is delivered before live events.
|
|
21
|
+
*/
|
|
22
|
+
cursor?: string;
|
|
18
23
|
};
|
|
19
24
|
|
|
20
25
|
export class MessagesSubscribe extends AbstractMessage<MessagesSubscribeMessage> {
|
|
@@ -48,6 +53,7 @@ export class MessagesSubscribe extends AbstractMessage<MessagesSubscribeMessage>
|
|
|
48
53
|
filters : options.filters ?? [],
|
|
49
54
|
messageTimestamp : options.messageTimestamp ?? currentTime,
|
|
50
55
|
permissionGrantId : options.permissionGrantId,
|
|
56
|
+
cursor : options.cursor,
|
|
51
57
|
};
|
|
52
58
|
|
|
53
59
|
removeUndefinedProperties(descriptor);
|