@enbox/dwn-sdk-js 0.4.0 → 0.4.2
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 +4 -4
- package/dist/browser.mjs +3 -10
- package/dist/browser.mjs.map +4 -4
- package/dist/esm/generated/precompiled-validators.js +799 -885
- package/dist/esm/generated/precompiled-validators.js.map +1 -1
- package/dist/esm/src/core/dwn-constant.js +5 -0
- package/dist/esm/src/core/dwn-constant.js.map +1 -1
- package/dist/esm/src/core/dwn-error.js +12 -4
- package/dist/esm/src/core/dwn-error.js.map +1 -1
- package/dist/esm/src/core/grant-authorization.js +9 -18
- package/dist/esm/src/core/grant-authorization.js.map +1 -1
- package/dist/esm/src/core/message-reply.js.map +1 -1
- package/dist/esm/src/core/messages-grant-authorization.js +28 -45
- package/dist/esm/src/core/messages-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization-action.js +25 -27
- package/dist/esm/src/core/protocol-authorization-action.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization-validation.js +34 -89
- package/dist/esm/src/core/protocol-authorization-validation.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization.js +44 -118
- package/dist/esm/src/core/protocol-authorization.js.map +1 -1
- package/dist/esm/src/core/protocols-grant-authorization.js +5 -5
- package/dist/esm/src/core/protocols-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/recording-validation-state-reader.js +84 -0
- package/dist/esm/src/core/recording-validation-state-reader.js.map +1 -0
- package/dist/esm/src/core/records-grant-authorization.js +11 -11
- package/dist/esm/src/core/records-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/replication-apply.js +123 -28
- package/dist/esm/src/core/replication-apply.js.map +1 -1
- package/dist/esm/src/core/resumable-task-manager.js +5 -4
- package/dist/esm/src/core/resumable-task-manager.js.map +1 -1
- package/dist/esm/src/core/validation-state-reader.js +237 -0
- package/dist/esm/src/core/validation-state-reader.js.map +1 -0
- package/dist/esm/src/dwn.js +165 -132
- package/dist/esm/src/dwn.js.map +1 -1
- package/dist/esm/src/enums/dwn-interface-method.js +0 -1
- package/dist/esm/src/enums/dwn-interface-method.js.map +1 -1
- package/dist/esm/src/event-stream/durable-event-log.js +365 -0
- package/dist/esm/src/event-stream/durable-event-log.js.map +1 -0
- package/dist/esm/src/event-stream/event-emitter-wake-publisher.js +25 -0
- package/dist/esm/src/event-stream/event-emitter-wake-publisher.js.map +1 -0
- package/dist/esm/src/handlers/messages-query.js +159 -0
- package/dist/esm/src/handlers/messages-query.js.map +1 -0
- package/dist/esm/src/handlers/messages-read.js +5 -5
- package/dist/esm/src/handlers/messages-read.js.map +1 -1
- package/dist/esm/src/handlers/messages-subscribe.js +8 -8
- package/dist/esm/src/handlers/messages-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/protocols-configure.js +30 -49
- package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
- package/dist/esm/src/handlers/protocols-query.js +1 -1
- package/dist/esm/src/handlers/protocols-query.js.map +1 -1
- package/dist/esm/src/handlers/records-count.js +20 -11
- package/dist/esm/src/handlers/records-count.js.map +1 -1
- package/dist/esm/src/handlers/records-delete.js +20 -16
- package/dist/esm/src/handlers/records-delete.js.map +1 -1
- package/dist/esm/src/handlers/records-query.js +35 -11
- package/dist/esm/src/handlers/records-query.js.map +1 -1
- package/dist/esm/src/handlers/records-read.js +52 -42
- package/dist/esm/src/handlers/records-read.js.map +1 -1
- package/dist/esm/src/handlers/records-subscribe.js +107 -11
- package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/records-write.js +62 -116
- package/dist/esm/src/handlers/records-write.js.map +1 -1
- package/dist/esm/src/index.js +6 -7
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/interfaces/{messages-sync.js → messages-query.js} +21 -15
- package/dist/esm/src/interfaces/messages-query.js.map +1 -0
- package/dist/esm/src/interfaces/protocols-configure.js +12 -9
- package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
- package/dist/esm/src/interfaces/protocols-query.js +3 -4
- package/dist/esm/src/interfaces/protocols-query.js.map +1 -1
- package/dist/esm/src/interfaces/records-count.js +4 -3
- package/dist/esm/src/interfaces/records-count.js.map +1 -1
- package/dist/esm/src/interfaces/records-delete.js +21 -4
- package/dist/esm/src/interfaces/records-delete.js.map +1 -1
- package/dist/esm/src/interfaces/records-query.js +4 -3
- package/dist/esm/src/interfaces/records-query.js.map +1 -1
- package/dist/esm/src/interfaces/records-read.js +3 -3
- package/dist/esm/src/interfaces/records-read.js.map +1 -1
- package/dist/esm/src/interfaces/records-subscribe.js +4 -3
- package/dist/esm/src/interfaces/records-subscribe.js.map +1 -1
- package/dist/esm/src/interfaces/records-write.js +27 -13
- package/dist/esm/src/interfaces/records-write.js.map +1 -1
- package/dist/esm/src/protocols/permissions.js +27 -34
- package/dist/esm/src/protocols/permissions.js.map +1 -1
- package/dist/esm/src/store/index-level.js +24 -9
- package/dist/esm/src/store/index-level.js.map +1 -1
- package/dist/esm/src/store/level-wrapper.js +7 -0
- package/dist/esm/src/store/level-wrapper.js.map +1 -1
- package/dist/esm/src/store/message-store-level.js +536 -42
- package/dist/esm/src/store/message-store-level.js.map +1 -1
- package/dist/esm/src/store/storage-controller.js +58 -49
- package/dist/esm/src/store/storage-controller.js.map +1 -1
- package/dist/esm/src/types/message-types.js.map +1 -1
- package/dist/esm/src/types/validation-state-reader.js +2 -0
- package/dist/esm/src/types/validation-state-reader.js.map +1 -0
- package/dist/esm/src/utils/messages.js +17 -0
- package/dist/esm/src/utils/messages.js.map +1 -1
- package/dist/esm/src/utils/protocol-tags.js +262 -0
- package/dist/esm/src/utils/protocol-tags.js.map +1 -0
- package/dist/esm/src/utils/record-limit-occupancy.js +244 -0
- package/dist/esm/src/utils/record-limit-occupancy.js.map +1 -0
- package/dist/esm/src/utils/records.js +50 -14
- package/dist/esm/src/utils/records.js.map +1 -1
- package/dist/esm/src/utils/replication.js +85 -0
- package/dist/esm/src/utils/replication.js.map +1 -0
- package/dist/esm/tests/core/grant-authorization.spec.js +4 -4
- package/dist/esm/tests/core/grant-authorization.spec.js.map +1 -1
- package/dist/esm/tests/core/process-message-parity.spec.js +222 -0
- package/dist/esm/tests/core/process-message-parity.spec.js.map +1 -0
- package/dist/esm/tests/core/protocol-authorization.spec.js +5 -2
- package/dist/esm/tests/core/protocol-authorization.spec.js.map +1 -1
- package/dist/esm/tests/core/records-grant-authorization.spec.js +5 -5
- package/dist/esm/tests/core/records-grant-authorization.spec.js.map +1 -1
- package/dist/esm/tests/core/replication-apply.spec.js +55 -1
- package/dist/esm/tests/core/replication-apply.spec.js.map +1 -1
- package/dist/esm/tests/core/replication-replay-property.spec.js +350 -0
- package/dist/esm/tests/core/replication-replay-property.spec.js.map +1 -0
- package/dist/esm/tests/core/validation-read-closure.spec.js +469 -0
- package/dist/esm/tests/core/validation-read-closure.spec.js.map +1 -0
- package/dist/esm/tests/core/validation-state-reader.spec.js +716 -0
- package/dist/esm/tests/core/validation-state-reader.spec.js.map +1 -0
- package/dist/esm/tests/durable-event-log.spec.js +373 -0
- package/dist/esm/tests/durable-event-log.spec.js.map +1 -0
- package/dist/esm/tests/dwn.spec.js +504 -35
- package/dist/esm/tests/dwn.spec.js.map +1 -1
- package/dist/esm/tests/features/author-delegated-grant.spec.js +9 -6
- package/dist/esm/tests/features/author-delegated-grant.spec.js.map +1 -1
- package/dist/esm/tests/features/owner-delegated-grant.spec.js +1 -4
- package/dist/esm/tests/features/owner-delegated-grant.spec.js.map +1 -1
- package/dist/esm/tests/features/owner-signature.spec.js +1 -4
- package/dist/esm/tests/features/owner-signature.spec.js.map +1 -1
- package/dist/esm/tests/features/permissions.spec.js +165 -4
- package/dist/esm/tests/features/permissions.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-composition.spec.js +8 -11
- package/dist/esm/tests/features/protocol-composition.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-create-action.spec.js +1 -4
- package/dist/esm/tests/features/protocol-create-action.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-delete-action.spec.js +3 -5
- package/dist/esm/tests/features/protocol-delete-action.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-update-action.spec.js +3 -6
- package/dist/esm/tests/features/protocol-update-action.spec.js.map +1 -1
- package/dist/esm/tests/features/records-delivery.spec.js +1 -4
- package/dist/esm/tests/features/records-delivery.spec.js.map +1 -1
- package/dist/esm/tests/features/records-immutable.spec.js +1 -4
- package/dist/esm/tests/features/records-immutable.spec.js.map +1 -1
- package/dist/esm/tests/features/records-nested-query-scope.spec.js +281 -0
- package/dist/esm/tests/features/records-nested-query-scope.spec.js.map +1 -0
- package/dist/esm/tests/features/records-prune-cross-protocol.spec.js +3 -7
- package/dist/esm/tests/features/records-prune-cross-protocol.spec.js.map +1 -1
- package/dist/esm/tests/features/records-prune.spec.js +11 -22
- package/dist/esm/tests/features/records-prune.spec.js.map +1 -1
- package/dist/esm/tests/features/records-record-limit.spec.js +441 -231
- package/dist/esm/tests/features/records-record-limit.spec.js.map +1 -1
- package/dist/esm/tests/features/records-squash.spec.js +6 -4
- package/dist/esm/tests/features/records-squash.spec.js.map +1 -1
- package/dist/esm/tests/features/records-tags.spec.js +1 -4
- package/dist/esm/tests/features/records-tags.spec.js.map +1 -1
- package/dist/esm/tests/features/resumable-tasks.spec.js +3 -5
- package/dist/esm/tests/features/resumable-tasks.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/message-store.fuzz.spec.js +1 -2
- package/dist/esm/tests/fuzz/message-store.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/process-message.fuzz.spec.js +2 -4
- package/dist/esm/tests/fuzz/process-message.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/schema-validation.fuzz.spec.js +1 -1
- package/dist/esm/tests/fuzz/schema-validation.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-query.spec.js +246 -0
- package/dist/esm/tests/handlers/messages-query.spec.js.map +1 -0
- package/dist/esm/tests/handlers/messages-read.spec.js +2 -5
- package/dist/esm/tests/handlers/messages-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-subscribe.spec.js +3 -14
- package/dist/esm/tests/handlers/messages-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/protocols-configure.spec.js +27 -26
- package/dist/esm/tests/handlers/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/handlers/protocols-query.spec.js +1 -4
- package/dist/esm/tests/handlers/protocols-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-count.spec.js +1 -4
- package/dist/esm/tests/handlers/records-count.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-delete.spec.js +312 -30
- package/dist/esm/tests/handlers/records-delete.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-query.spec.js +32 -9
- package/dist/esm/tests/handlers/records-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-read.spec.js +4 -4
- package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js +33 -14
- package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-write.spec.js +82 -36
- package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-delete.spec.js +69 -2
- package/dist/esm/tests/interfaces/records-delete.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-write.spec.js +4 -3
- package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
- package/dist/esm/tests/protocols/permissions.spec.js +55 -6
- package/dist/esm/tests/protocols/permissions.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/aggregator.spec.js +1 -4
- package/dist/esm/tests/scenarios/aggregator.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/deleted-record.spec.js +1 -4
- package/dist/esm/tests/scenarios/deleted-record.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js +1 -4
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/nested-roles.spec.js +1 -4
- package/dist/esm/tests/scenarios/nested-roles.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/subscriptions.spec.js +1 -4
- package/dist/esm/tests/scenarios/subscriptions.spec.js.map +1 -1
- package/dist/esm/tests/store/message-store-level.spec.js +361 -5
- package/dist/esm/tests/store/message-store-level.spec.js.map +1 -1
- package/dist/esm/tests/store/message-store.spec.js +60 -0
- package/dist/esm/tests/store/message-store.spec.js.map +1 -1
- package/dist/esm/tests/test-event-stream.js +7 -3
- package/dist/esm/tests/test-event-stream.js.map +1 -1
- package/dist/esm/tests/test-stores.js +19 -9
- package/dist/esm/tests/test-stores.js.map +1 -1
- package/dist/esm/tests/test-suite.js +4 -2
- package/dist/esm/tests/test-suite.js.map +1 -1
- package/dist/esm/tests/utils/protocol-tags.spec.js +96 -0
- package/dist/esm/tests/utils/protocol-tags.spec.js.map +1 -0
- package/dist/esm/tests/utils/test-data-generator.js +25 -0
- package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
- package/dist/esm/tests/utils/test-stub-generator.js.map +1 -1
- package/dist/esm/tests/utils/test-validation-state-reader.js +16 -0
- package/dist/esm/tests/utils/test-validation-state-reader.js.map +1 -0
- package/dist/types/generated/precompiled-validators.d.ts +6 -6
- package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
- package/dist/types/src/core/core-protocol.d.ts +3 -3
- package/dist/types/src/core/core-protocol.d.ts.map +1 -1
- package/dist/types/src/core/dwn-constant.d.ts +5 -0
- package/dist/types/src/core/dwn-constant.d.ts.map +1 -1
- package/dist/types/src/core/dwn-error.d.ts +12 -4
- package/dist/types/src/core/dwn-error.d.ts.map +1 -1
- package/dist/types/src/core/grant-authorization.d.ts +5 -5
- package/dist/types/src/core/grant-authorization.d.ts.map +1 -1
- package/dist/types/src/core/message-reply.d.ts +5 -4
- package/dist/types/src/core/message-reply.d.ts.map +1 -1
- package/dist/types/src/core/messages-grant-authorization.d.ts +12 -14
- package/dist/types/src/core/messages-grant-authorization.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization-action.d.ts +4 -5
- package/dist/types/src/core/protocol-authorization-action.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization-validation.d.ts +14 -17
- package/dist/types/src/core/protocol-authorization-validation.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization.d.ts +8 -33
- package/dist/types/src/core/protocol-authorization.d.ts.map +1 -1
- package/dist/types/src/core/protocols-grant-authorization.d.ts +4 -4
- package/dist/types/src/core/protocols-grant-authorization.d.ts.map +1 -1
- package/dist/types/src/core/recording-validation-state-reader.d.ts +75 -0
- package/dist/types/src/core/recording-validation-state-reader.d.ts.map +1 -0
- package/dist/types/src/core/records-grant-authorization.d.ts +8 -8
- package/dist/types/src/core/records-grant-authorization.d.ts.map +1 -1
- package/dist/types/src/core/replication-apply.d.ts +36 -0
- package/dist/types/src/core/replication-apply.d.ts.map +1 -1
- package/dist/types/src/core/resumable-task-manager.d.ts +1 -1
- package/dist/types/src/core/resumable-task-manager.d.ts.map +1 -1
- package/dist/types/src/core/validation-state-reader.d.ts +79 -0
- package/dist/types/src/core/validation-state-reader.d.ts.map +1 -0
- package/dist/types/src/dwn.d.ts +33 -20
- package/dist/types/src/dwn.d.ts.map +1 -1
- package/dist/types/src/enums/dwn-interface-method.d.ts +0 -1
- package/dist/types/src/enums/dwn-interface-method.d.ts.map +1 -1
- package/dist/types/src/event-stream/durable-event-log.d.ts +69 -0
- package/dist/types/src/event-stream/durable-event-log.d.ts.map +1 -0
- package/dist/types/src/event-stream/event-emitter-wake-publisher.d.ts +13 -0
- package/dist/types/src/event-stream/event-emitter-wake-publisher.d.ts.map +1 -0
- package/dist/types/src/handlers/messages-query.d.ts +20 -0
- package/dist/types/src/handlers/messages-query.d.ts.map +1 -0
- package/dist/types/src/handlers/messages-read.d.ts +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 +0 -5
- package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/handlers/records-count.d.ts +2 -1
- package/dist/types/src/handlers/records-count.d.ts.map +1 -1
- package/dist/types/src/handlers/records-delete.d.ts +2 -2
- package/dist/types/src/handlers/records-delete.d.ts.map +1 -1
- package/dist/types/src/handlers/records-query.d.ts +1 -1
- package/dist/types/src/handlers/records-query.d.ts.map +1 -1
- package/dist/types/src/handlers/records-read.d.ts +2 -1
- package/dist/types/src/handlers/records-read.d.ts.map +1 -1
- package/dist/types/src/handlers/records-subscribe.d.ts +4 -5
- package/dist/types/src/handlers/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/handlers/records-write.d.ts +3 -11
- package/dist/types/src/handlers/records-write.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +14 -16
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/interfaces/messages-query.d.ts +23 -0
- package/dist/types/src/interfaces/messages-query.d.ts.map +1 -0
- package/dist/types/src/interfaces/protocols-configure.d.ts +3 -3
- package/dist/types/src/interfaces/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/interfaces/protocols-query.d.ts +2 -2
- package/dist/types/src/interfaces/protocols-query.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-count.d.ts +3 -3
- package/dist/types/src/interfaces/records-count.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-delete.d.ts +11 -3
- package/dist/types/src/interfaces/records-delete.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-query.d.ts +3 -3
- package/dist/types/src/interfaces/records-query.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-read.d.ts +3 -3
- package/dist/types/src/interfaces/records-read.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-subscribe.d.ts +3 -3
- package/dist/types/src/interfaces/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-write.d.ts +15 -7
- package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
- package/dist/types/src/protocols/permissions.d.ts +9 -12
- package/dist/types/src/protocols/permissions.d.ts.map +1 -1
- package/dist/types/src/store/index-level.d.ts +10 -1
- package/dist/types/src/store/index-level.d.ts.map +1 -1
- package/dist/types/src/store/level-wrapper.d.ts +5 -0
- package/dist/types/src/store/level-wrapper.d.ts.map +1 -1
- package/dist/types/src/store/message-store-level.d.ts +94 -14
- package/dist/types/src/store/message-store-level.d.ts.map +1 -1
- package/dist/types/src/store/storage-controller.d.ts +17 -14
- package/dist/types/src/store/storage-controller.d.ts.map +1 -1
- package/dist/types/src/types/message-store.d.ts +29 -1
- package/dist/types/src/types/message-store.d.ts.map +1 -1
- package/dist/types/src/types/message-types.d.ts +2 -0
- package/dist/types/src/types/message-types.d.ts.map +1 -1
- package/dist/types/src/types/messages-types.d.ts +21 -37
- package/dist/types/src/types/messages-types.d.ts.map +1 -1
- package/dist/types/src/types/method-handler.d.ts +2 -2
- package/dist/types/src/types/method-handler.d.ts.map +1 -1
- package/dist/types/src/types/permission-types.d.ts +1 -1
- package/dist/types/src/types/subscriptions.d.ts +50 -39
- package/dist/types/src/types/subscriptions.d.ts.map +1 -1
- package/dist/types/src/types/validation-state-reader.d.ts +116 -0
- package/dist/types/src/types/validation-state-reader.d.ts.map +1 -0
- package/dist/types/src/utils/messages.d.ts +10 -0
- package/dist/types/src/utils/messages.d.ts.map +1 -1
- package/dist/types/src/utils/protocol-tags.d.ts +15 -0
- package/dist/types/src/utils/protocol-tags.d.ts.map +1 -0
- package/dist/types/src/utils/record-limit-occupancy.d.ts +40 -0
- package/dist/types/src/utils/record-limit-occupancy.d.ts.map +1 -0
- package/dist/types/src/utils/records.d.ts +25 -3
- package/dist/types/src/utils/records.d.ts.map +1 -1
- package/dist/types/src/utils/replication.d.ts +22 -0
- package/dist/types/src/utils/replication.d.ts.map +1 -0
- package/dist/types/tests/core/process-message-parity.spec.d.ts +2 -0
- package/dist/types/tests/core/process-message-parity.spec.d.ts.map +1 -0
- package/dist/types/tests/core/replication-replay-property.spec.d.ts +2 -0
- package/dist/types/tests/core/replication-replay-property.spec.d.ts.map +1 -0
- package/dist/types/tests/core/validation-read-closure.spec.d.ts +2 -0
- package/dist/types/tests/core/validation-read-closure.spec.d.ts.map +1 -0
- package/dist/types/tests/core/validation-state-reader.spec.d.ts +2 -0
- package/dist/types/tests/core/validation-state-reader.spec.d.ts.map +1 -0
- package/dist/types/tests/durable-event-log.spec.d.ts +2 -0
- package/dist/types/tests/durable-event-log.spec.d.ts.map +1 -0
- package/dist/types/tests/dwn.spec.d.ts.map +1 -1
- 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/permissions.spec.d.ts.map +1 -1
- package/dist/types/tests/features/protocol-composition.spec.d.ts.map +1 -1
- package/dist/types/tests/features/protocol-create-action.spec.d.ts.map +1 -1
- package/dist/types/tests/features/protocol-delete-action.spec.d.ts.map +1 -1
- package/dist/types/tests/features/protocol-update-action.spec.d.ts.map +1 -1
- package/dist/types/tests/features/records-delivery.spec.d.ts.map +1 -1
- package/dist/types/tests/features/records-immutable.spec.d.ts.map +1 -1
- package/dist/types/tests/features/records-nested-query-scope.spec.d.ts +2 -0
- package/dist/types/tests/features/records-nested-query-scope.spec.d.ts.map +1 -0
- package/dist/types/tests/features/records-prune-cross-protocol.spec.d.ts.map +1 -1
- package/dist/types/tests/features/records-prune.spec.d.ts.map +1 -1
- package/dist/types/tests/features/records-record-limit.spec.d.ts.map +1 -1
- package/dist/types/tests/features/records-squash.spec.d.ts.map +1 -1
- 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-query.spec.d.ts +2 -0
- package/dist/types/tests/handlers/messages-query.spec.d.ts.map +1 -0
- 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/protocols-query.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/end-to-end-tests.spec.d.ts.map +1 -1
- package/dist/types/tests/scenarios/nested-roles.spec.d.ts.map +1 -1
- package/dist/types/tests/scenarios/subscriptions.spec.d.ts.map +1 -1
- package/dist/types/tests/store/message-store.spec.d.ts.map +1 -1
- package/dist/types/tests/test-event-stream.d.ts +1 -1
- package/dist/types/tests/test-event-stream.d.ts.map +1 -1
- package/dist/types/tests/test-stores.d.ts +5 -4
- package/dist/types/tests/test-stores.d.ts.map +1 -1
- package/dist/types/tests/test-suite.d.ts +1 -2
- package/dist/types/tests/test-suite.d.ts.map +1 -1
- package/dist/types/tests/utils/protocol-tags.spec.d.ts +2 -0
- package/dist/types/tests/utils/protocol-tags.spec.d.ts.map +1 -0
- package/dist/types/tests/utils/test-data-generator.d.ts +20 -1
- package/dist/types/tests/utils/test-data-generator.d.ts.map +1 -1
- package/dist/types/tests/utils/test-validation-state-reader.d.ts +15 -0
- package/dist/types/tests/utils/test-validation-state-reader.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/core/core-protocol.ts +3 -3
- package/src/core/dwn-constant.ts +7 -1
- package/src/core/dwn-error.ts +12 -4
- package/src/core/grant-authorization.ts +11 -20
- package/src/core/message-reply.ts +6 -5
- package/src/core/messages-grant-authorization.ts +37 -70
- package/src/core/protocol-authorization-action.ts +29 -38
- package/src/core/protocol-authorization-validation.ts +47 -121
- package/src/core/protocol-authorization.ts +56 -202
- package/src/core/protocols-grant-authorization.ts +9 -9
- package/src/core/recording-validation-state-reader.ts +130 -0
- package/src/core/records-grant-authorization.ts +16 -16
- package/src/core/replication-apply.ts +172 -32
- package/src/core/resumable-task-manager.ts +10 -8
- package/src/core/validation-state-reader.ts +350 -0
- package/src/dwn.ts +285 -192
- package/src/enums/dwn-interface-method.ts +0 -1
- package/src/event-stream/durable-event-log.ts +509 -0
- package/src/event-stream/event-emitter-wake-publisher.ts +34 -0
- package/src/handlers/messages-query.ts +203 -0
- package/src/handlers/messages-read.ts +9 -10
- package/src/handlers/messages-subscribe.ts +12 -13
- package/src/handlers/protocols-configure.ts +37 -58
- package/src/handlers/protocols-query.ts +1 -1
- package/src/handlers/records-count.ts +24 -17
- package/src/handlers/records-delete.ts +29 -27
- package/src/handlers/records-query.ts +38 -17
- package/src/handlers/records-read.ts +63 -50
- package/src/handlers/records-subscribe.ts +132 -19
- package/src/handlers/records-write.ts +77 -168
- package/src/index.ts +14 -17
- package/src/interfaces/messages-query.ts +70 -0
- package/src/interfaces/protocols-configure.ts +20 -10
- package/src/interfaces/protocols-query.ts +4 -5
- package/src/interfaces/records-count.ts +9 -4
- package/src/interfaces/records-delete.ts +25 -5
- package/src/interfaces/records-query.ts +9 -4
- package/src/interfaces/records-read.ts +4 -4
- package/src/interfaces/records-subscribe.ts +9 -4
- package/src/interfaces/records-write.ts +41 -13
- package/src/protocols/permissions.ts +32 -52
- package/src/store/index-level.ts +30 -9
- package/src/store/level-wrapper.ts +9 -1
- package/src/store/message-store-level.ts +757 -47
- package/src/store/storage-controller.ts +74 -63
- package/src/types/message-store.ts +45 -2
- package/src/types/message-types.ts +3 -1
- package/src/types/messages-types.ts +26 -45
- package/src/types/method-handler.ts +3 -3
- package/src/types/permission-types.ts +1 -1
- package/src/types/subscriptions.ts +53 -42
- package/src/types/validation-state-reader.ts +127 -0
- package/src/utils/messages.ts +25 -1
- package/src/utils/protocol-tags.ts +366 -0
- package/src/utils/record-limit-occupancy.ts +377 -0
- package/src/utils/records.ts +69 -13
- package/src/utils/replication.ts +122 -0
- package/dist/esm/src/core/record-chain.js +0 -64
- package/dist/esm/src/core/record-chain.js.map +0 -1
- package/dist/esm/src/event-stream/event-emitter-event-log.js +0 -334
- package/dist/esm/src/event-stream/event-emitter-event-log.js.map +0 -1
- package/dist/esm/src/handlers/messages-sync.js +0 -278
- package/dist/esm/src/handlers/messages-sync.js.map +0 -1
- package/dist/esm/src/interfaces/messages-sync.js.map +0 -1
- package/dist/esm/src/smt/smt-store-level.js +0 -103
- package/dist/esm/src/smt/smt-store-level.js.map +0 -1
- package/dist/esm/src/smt/smt-store-memory.js +0 -41
- package/dist/esm/src/smt/smt-store-memory.js.map +0 -1
- package/dist/esm/src/smt/smt-utils.js +0 -129
- package/dist/esm/src/smt/smt-utils.js.map +0 -1
- package/dist/esm/src/smt/sparse-merkle-tree.js +0 -577
- package/dist/esm/src/smt/sparse-merkle-tree.js.map +0 -1
- package/dist/esm/src/state-index/state-index-level.js +0 -191
- package/dist/esm/src/state-index/state-index-level.js.map +0 -1
- package/dist/esm/src/types/smt-types.js +0 -5
- package/dist/esm/src/types/smt-types.js.map +0 -1
- package/dist/esm/src/types/state-index.js +0 -2
- package/dist/esm/src/types/state-index.js.map +0 -1
- package/dist/esm/tests/event-emitter-event-log.spec.js +0 -499
- package/dist/esm/tests/event-emitter-event-log.spec.js.map +0 -1
- package/dist/esm/tests/handlers/messages-sync.spec.js +0 -1088
- package/dist/esm/tests/handlers/messages-sync.spec.js.map +0 -1
- package/dist/esm/tests/smt/smt-store-level.spec.js +0 -132
- package/dist/esm/tests/smt/smt-store-level.spec.js.map +0 -1
- package/dist/esm/tests/smt/sparse-merkle-tree.spec.js +0 -732
- package/dist/esm/tests/smt/sparse-merkle-tree.spec.js.map +0 -1
- package/dist/esm/tests/state-index/state-index-level.spec.js +0 -245
- package/dist/esm/tests/state-index/state-index-level.spec.js.map +0 -1
- package/dist/types/src/core/record-chain.d.ts +0 -24
- package/dist/types/src/core/record-chain.d.ts.map +0 -1
- package/dist/types/src/event-stream/event-emitter-event-log.d.ts +0 -80
- package/dist/types/src/event-stream/event-emitter-event-log.d.ts.map +0 -1
- package/dist/types/src/handlers/messages-sync.d.ts +0 -39
- package/dist/types/src/handlers/messages-sync.d.ts.map +0 -1
- package/dist/types/src/interfaces/messages-sync.d.ts +0 -20
- package/dist/types/src/interfaces/messages-sync.d.ts.map +0 -1
- package/dist/types/src/smt/smt-store-level.d.ts +0 -32
- package/dist/types/src/smt/smt-store-level.d.ts.map +0 -1
- package/dist/types/src/smt/smt-store-memory.d.ts +0 -22
- package/dist/types/src/smt/smt-store-memory.d.ts.map +0 -1
- package/dist/types/src/smt/smt-utils.d.ts +0 -58
- package/dist/types/src/smt/smt-utils.d.ts.map +0 -1
- package/dist/types/src/smt/sparse-merkle-tree.d.ts +0 -124
- package/dist/types/src/smt/sparse-merkle-tree.d.ts.map +0 -1
- package/dist/types/src/state-index/state-index-level.d.ts +0 -83
- package/dist/types/src/state-index/state-index-level.d.ts.map +0 -1
- package/dist/types/src/types/smt-types.d.ts +0 -81
- package/dist/types/src/types/smt-types.d.ts.map +0 -1
- package/dist/types/src/types/state-index.d.ts +0 -90
- package/dist/types/src/types/state-index.d.ts.map +0 -1
- package/dist/types/tests/event-emitter-event-log.spec.d.ts +0 -2
- package/dist/types/tests/event-emitter-event-log.spec.d.ts.map +0 -1
- package/dist/types/tests/handlers/messages-sync.spec.d.ts +0 -2
- package/dist/types/tests/handlers/messages-sync.spec.d.ts.map +0 -1
- package/dist/types/tests/smt/smt-store-level.spec.d.ts +0 -2
- package/dist/types/tests/smt/smt-store-level.spec.d.ts.map +0 -1
- package/dist/types/tests/smt/sparse-merkle-tree.spec.d.ts +0 -2
- package/dist/types/tests/smt/sparse-merkle-tree.spec.d.ts.map +0 -1
- package/dist/types/tests/state-index/state-index-level.spec.d.ts +0 -2
- package/dist/types/tests/state-index/state-index-level.spec.d.ts.map +0 -1
- package/src/core/record-chain.ts +0 -99
- package/src/event-stream/event-emitter-event-log.ts +0 -430
- package/src/handlers/messages-sync.ts +0 -403
- package/src/interfaces/messages-sync.ts +0 -69
- package/src/smt/smt-store-level.ts +0 -143
- package/src/smt/smt-store-memory.ts +0 -53
- package/src/smt/smt-utils.ts +0 -149
- package/src/smt/sparse-merkle-tree.ts +0 -698
- package/src/state-index/state-index-level.ts +0 -239
- package/src/types/smt-types.ts +0 -95
- package/src/types/state-index.ts +0 -100
|
@@ -10,6 +10,7 @@ import { ArrayUtility } from '../../src/utils/array.js';
|
|
|
10
10
|
import { DwnErrorCode } from '../../src/core/dwn-error.js';
|
|
11
11
|
import { Message } from '../../src/core/message.js';
|
|
12
12
|
import { normalizeSchemaUrl } from '../../src/utils/url.js';
|
|
13
|
+
import { Poller } from '../utils/poller.js';
|
|
13
14
|
import { RecordsDeleteHandler } from '../../src/handlers/records-delete.js';
|
|
14
15
|
import { TestDataGenerator } from '../utils/test-data-generator.js';
|
|
15
16
|
import { TestEventLog } from '../test-event-stream.js';
|
|
@@ -19,13 +20,13 @@ import { Time } from '../../src/utils/time.js';
|
|
|
19
20
|
import { DataStream, Dwn, Encoder, Jws, MessageStoreLevel, PermissionsProtocol, RecordsDelete, RecordsRead, RecordsWrite } from '../../src/index.js';
|
|
20
21
|
import { DidKey, UniversalResolver } from '@enbox/dids';
|
|
21
22
|
import { DwnInterfaceName, DwnMethodName } from '../../src/enums/dwn-interface-method.js';
|
|
23
|
+
import { createTestValidationStateReader } from '../utils/test-validation-state-reader.js';
|
|
22
24
|
export function testRecordsDeleteHandler() {
|
|
23
25
|
describe('RecordsDeleteHandler.handle()', () => {
|
|
24
26
|
let didResolver;
|
|
25
27
|
let messageStore;
|
|
26
28
|
let dataStore;
|
|
27
29
|
let resumableTaskStore;
|
|
28
|
-
let stateIndex;
|
|
29
30
|
let eventLog;
|
|
30
31
|
let dwn;
|
|
31
32
|
beforeEach(() => {
|
|
@@ -43,21 +44,19 @@ export function testRecordsDeleteHandler() {
|
|
|
43
44
|
messageStore = stores.messageStore;
|
|
44
45
|
dataStore = stores.dataStore;
|
|
45
46
|
resumableTaskStore = stores.resumableTaskStore;
|
|
46
|
-
stateIndex = stores.stateIndex;
|
|
47
47
|
eventLog = TestEventLog.get();
|
|
48
|
-
dwn = await Dwn.create({ didResolver, messageStore, dataStore,
|
|
48
|
+
dwn = await Dwn.create({ didResolver, messageStore, dataStore, eventLog, resumableTaskStore });
|
|
49
49
|
});
|
|
50
50
|
beforeEach(async () => {
|
|
51
51
|
// clean up before each test rather than after so that a test does not depend on other tests to do the clean up
|
|
52
52
|
await messageStore.clear();
|
|
53
53
|
await dataStore.clear();
|
|
54
54
|
await resumableTaskStore.clear();
|
|
55
|
-
await stateIndex.clear();
|
|
56
55
|
});
|
|
57
56
|
afterAll(async () => {
|
|
58
57
|
await dwn.close();
|
|
59
58
|
});
|
|
60
|
-
it('should handle RecordsDelete successfully and
|
|
59
|
+
it('should handle RecordsDelete successfully and accept a newer tombstone over a deleted record', async () => {
|
|
61
60
|
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
62
61
|
await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
|
|
63
62
|
// insert data
|
|
@@ -83,13 +82,13 @@ export function testRecordsDeleteHandler() {
|
|
|
83
82
|
const reply2 = await dwn.processMessage(alice.did, queryData.message);
|
|
84
83
|
expect(reply2.status.code).toBe(200);
|
|
85
84
|
expect(reply2.entries?.length).toBe(0);
|
|
86
|
-
//
|
|
85
|
+
// a newer tombstone displaces the older one — one canonical winner per record
|
|
87
86
|
const recordsDelete2 = await RecordsDelete.create({
|
|
88
87
|
recordId: message.recordId,
|
|
89
88
|
signer: Jws.createSigner(alice)
|
|
90
89
|
});
|
|
91
90
|
const recordsDelete2Reply = await dwn.processMessage(alice.did, recordsDelete2.message);
|
|
92
|
-
expect(recordsDelete2Reply.status.code).toBe(
|
|
91
|
+
expect(recordsDelete2Reply.status.code).toBe(202);
|
|
93
92
|
});
|
|
94
93
|
it('should not affect other records or tenants with the same data', async () => {
|
|
95
94
|
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
@@ -163,7 +162,7 @@ export function testRecordsDeleteHandler() {
|
|
|
163
162
|
const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
|
|
164
163
|
expect(deleteReply.status.code).toBe(404);
|
|
165
164
|
});
|
|
166
|
-
it('should
|
|
165
|
+
it('should apply a tombstone over a newer RecordsWrite (delete-wins)', async () => {
|
|
167
166
|
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
168
167
|
await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
|
|
169
168
|
// initial write
|
|
@@ -184,19 +183,63 @@ export function testRecordsDeleteHandler() {
|
|
|
184
183
|
// subsequent write
|
|
185
184
|
const subsequentWriteReply = await dwn.processMessage(alice.did, subsequentWriteData.message, { dataStream: subsequentWriteData.dataStream });
|
|
186
185
|
expect(subsequentWriteReply.status.code).toBe(202);
|
|
187
|
-
//
|
|
186
|
+
// the tombstone displaces the newer write regardless of timestamp (delete-wins) so
|
|
187
|
+
// that replicas converge on the same terminal state no matter the arrival order
|
|
188
188
|
const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
|
|
189
|
-
expect(deleteReply.status.code).toBe(
|
|
190
|
-
//
|
|
189
|
+
expect(deleteReply.status.code).toBe(202);
|
|
190
|
+
// the record reads as deleted and the displaced write is gone
|
|
191
191
|
const queryData = await TestDataGenerator.generateRecordsQuery({
|
|
192
192
|
author: alice,
|
|
193
193
|
filter: { recordId: initialWriteData.message.recordId }
|
|
194
194
|
});
|
|
195
|
-
const expectedEncodedData = Encoder.bytesToBase64Url(subsequentWriteData.dataBytes);
|
|
196
195
|
const reply = await dwn.processMessage(alice.did, queryData.message);
|
|
197
196
|
expect(reply.status.code).toBe(200);
|
|
198
|
-
expect(reply.entries?.length).toBe(
|
|
199
|
-
|
|
197
|
+
expect(reply.entries?.length).toBe(0);
|
|
198
|
+
});
|
|
199
|
+
it('should apply a stale prune over the record\'s newest plain tombstone (prune dominates)', async () => {
|
|
200
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
201
|
+
await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
|
|
202
|
+
const initialWriteData = await TestDataGenerator.generateRecordsWrite({ author: alice });
|
|
203
|
+
const initialWriteReply = await dwn.processMessage(alice.did, initialWriteData.message, { dataStream: initialWriteData.dataStream });
|
|
204
|
+
expect(initialWriteReply.status.code).toBe(202);
|
|
205
|
+
// generate the prune first so its timestamp is older than the tombstone admitted below
|
|
206
|
+
const stalePrune = await RecordsDelete.create({
|
|
207
|
+
recordId: initialWriteData.message.recordId,
|
|
208
|
+
prune: true,
|
|
209
|
+
signer: Jws.createSigner(alice)
|
|
210
|
+
});
|
|
211
|
+
await Time.minimalSleep();
|
|
212
|
+
const recordsDelete = await RecordsDelete.create({
|
|
213
|
+
recordId: initialWriteData.message.recordId,
|
|
214
|
+
signer: Jws.createSigner(alice)
|
|
215
|
+
});
|
|
216
|
+
const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
|
|
217
|
+
expect(deleteReply.status.code).toBe(202);
|
|
218
|
+
// prune dominates plain regardless of timestamp — the cascade must run on every replica
|
|
219
|
+
const stalePruneReply = await dwn.processMessage(alice.did, stalePrune.message);
|
|
220
|
+
expect(stalePruneReply.status.code).toBe(202);
|
|
221
|
+
});
|
|
222
|
+
it('should return 409 for a plain delete beaten by the record\'s newest tombstone', async () => {
|
|
223
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
224
|
+
await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
|
|
225
|
+
const initialWriteData = await TestDataGenerator.generateRecordsWrite({ author: alice });
|
|
226
|
+
const initialWriteReply = await dwn.processMessage(alice.did, initialWriteData.message, { dataStream: initialWriteData.dataStream });
|
|
227
|
+
expect(initialWriteReply.status.code).toBe(202);
|
|
228
|
+
// generate the losing delete first so its timestamp is older than the winner's
|
|
229
|
+
const staleDelete = await RecordsDelete.create({
|
|
230
|
+
recordId: initialWriteData.message.recordId,
|
|
231
|
+
signer: Jws.createSigner(alice)
|
|
232
|
+
});
|
|
233
|
+
await Time.minimalSleep();
|
|
234
|
+
const recordsDelete = await RecordsDelete.create({
|
|
235
|
+
recordId: initialWriteData.message.recordId,
|
|
236
|
+
signer: Jws.createSigner(alice)
|
|
237
|
+
});
|
|
238
|
+
const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
|
|
239
|
+
expect(deleteReply.status.code).toBe(202);
|
|
240
|
+
// same class, older timestamp: Conflict no-op, the canonical winner stands
|
|
241
|
+
const staleDeleteReply = await dwn.processMessage(alice.did, staleDelete.message);
|
|
242
|
+
expect(staleDeleteReply.status.code).toBe(409);
|
|
200
243
|
});
|
|
201
244
|
it('should be able to delete then rewrite the same data', async () => {
|
|
202
245
|
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
@@ -670,9 +713,250 @@ export function testRecordsDeleteHandler() {
|
|
|
670
713
|
const { messages } = await messageStore.query(alice.did, [{ schema: normalizeSchemaUrl('testSchema'), method: DwnMethodName.Delete }]);
|
|
671
714
|
expect(messages.length).toBe(1);
|
|
672
715
|
expect(await Message.getCid(messages[0])).toBe(deleteMessageCid);
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
716
|
+
});
|
|
717
|
+
describe('tombstone visibility facts', () => {
|
|
718
|
+
it('should construct a tombstone matching the permission shadow filter when a tagged permission record is deleted', async () => {
|
|
719
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
720
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
721
|
+
await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
|
|
722
|
+
// alice creates a permission grant scoped to a protocol — the grant record carries `tags: { protocol }`
|
|
723
|
+
const scopedProtocol = 'https://example.com/protocol/shadow-filter-test';
|
|
724
|
+
const permissionGrant = await PermissionsProtocol.createGrant({
|
|
725
|
+
signer: Jws.createSigner(alice),
|
|
726
|
+
grantedTo: bob.did,
|
|
727
|
+
dateExpires: Time.createOffsetTimestamp({ seconds: 60 * 60 * 24 }),
|
|
728
|
+
scope: {
|
|
729
|
+
interface: DwnInterfaceName.Records,
|
|
730
|
+
method: DwnMethodName.Write,
|
|
731
|
+
protocol: scopedProtocol,
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
const grantDataStream = DataStream.fromBytes(permissionGrant.permissionGrantBytes);
|
|
735
|
+
const grantWriteReply = await dwn.processMessage(alice.did, permissionGrant.recordsWrite.message, { dataStream: grantDataStream });
|
|
736
|
+
expect(grantWriteReply.status.code).toBe(202);
|
|
737
|
+
// the permission shadow filter shape matches the live grant record
|
|
738
|
+
const shadowFilter = { 'protocol': PermissionsProtocol.uri, 'tag.protocol': scopedProtocol };
|
|
739
|
+
const { messages: liveMatches } = await messageStore.query(alice.did, [shadowFilter]);
|
|
740
|
+
expect(liveMatches.length).toBe(1);
|
|
741
|
+
// alice deletes the grant record
|
|
742
|
+
const recordsDelete = await RecordsDelete.create({
|
|
743
|
+
recordId: permissionGrant.recordsWrite.message.recordId,
|
|
744
|
+
signer: Jws.createSigner(alice)
|
|
745
|
+
});
|
|
746
|
+
const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
|
|
747
|
+
expect(deleteReply.status.code).toBe(202);
|
|
748
|
+
// the tombstone is now the only message matching the shadow filter:
|
|
749
|
+
// the retained initial write no longer indexes tags once displaced from the latest base state
|
|
750
|
+
const { messages: matchesAfterDelete } = await messageStore.query(alice.did, [shadowFilter]);
|
|
751
|
+
expect(matchesAfterDelete.length).toBe(1);
|
|
752
|
+
expect(await Message.getCid(matchesAfterDelete[0])).toBe(await Message.getCid(recordsDelete.message));
|
|
753
|
+
expect(matchesAfterDelete[0].descriptor.method).toBe(DwnMethodName.Delete);
|
|
754
|
+
});
|
|
755
|
+
it('should carry `published` and `datePublished` onto the tombstone so it matches published queries and subscriptions', async () => {
|
|
756
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
757
|
+
const datePublished = '2025-01-01T00:00:00.000000Z';
|
|
758
|
+
await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
|
|
759
|
+
// subscribe to date-published records of the test schema before any writes
|
|
760
|
+
const receivedEvents = [];
|
|
761
|
+
const subscriptionHandler = (message) => {
|
|
762
|
+
if (message.type === 'event') {
|
|
763
|
+
receivedEvents.push(message.event);
|
|
764
|
+
}
|
|
765
|
+
};
|
|
766
|
+
const recordsSubscribe = await TestDataGenerator.generateRecordsSubscribe({
|
|
767
|
+
author: alice,
|
|
768
|
+
filter: { schema: 'http://published-tombstone', datePublished: { from: datePublished } },
|
|
769
|
+
});
|
|
770
|
+
const subscribeReply = await dwn.processMessage(alice.did, recordsSubscribe.message, { subscriptionHandler });
|
|
771
|
+
expect(subscribeReply.status.code).toBe(200);
|
|
772
|
+
// a published and an unpublished record
|
|
773
|
+
const publishedWrite = await TestDataGenerator.generateRecordsWrite({
|
|
774
|
+
author: alice,
|
|
775
|
+
schema: 'http://published-tombstone',
|
|
776
|
+
published: true,
|
|
777
|
+
datePublished,
|
|
778
|
+
});
|
|
779
|
+
const publishedWriteReply = await dwn.processMessage(alice.did, publishedWrite.message, { dataStream: publishedWrite.dataStream });
|
|
780
|
+
expect(publishedWriteReply.status.code).toBe(202);
|
|
781
|
+
const unpublishedWrite = await TestDataGenerator.generateRecordsWrite({
|
|
782
|
+
author: alice,
|
|
783
|
+
schema: 'http://published-tombstone',
|
|
784
|
+
});
|
|
785
|
+
const unpublishedWriteReply = await dwn.processMessage(alice.did, unpublishedWrite.message, { dataStream: unpublishedWrite.dataStream });
|
|
786
|
+
expect(unpublishedWriteReply.status.code).toBe(202);
|
|
787
|
+
// delete both records
|
|
788
|
+
const publishedDelete = await RecordsDelete.create({
|
|
789
|
+
recordId: publishedWrite.message.recordId,
|
|
790
|
+
signer: Jws.createSigner(alice)
|
|
791
|
+
});
|
|
792
|
+
const publishedDeleteReply = await dwn.processMessage(alice.did, publishedDelete.message);
|
|
793
|
+
expect(publishedDeleteReply.status.code).toBe(202);
|
|
794
|
+
const unpublishedDelete = await RecordsDelete.create({
|
|
795
|
+
recordId: unpublishedWrite.message.recordId,
|
|
796
|
+
signer: Jws.createSigner(alice)
|
|
797
|
+
});
|
|
798
|
+
const unpublishedDeleteReply = await dwn.processMessage(alice.did, unpublishedDelete.message);
|
|
799
|
+
expect(unpublishedDeleteReply.status.code).toBe(202);
|
|
800
|
+
// the published record's tombstone matches a `published: true` message store filter; the unpublished one's does not
|
|
801
|
+
const publishedTombstoneFilter = {
|
|
802
|
+
method: DwnMethodName.Delete,
|
|
803
|
+
published: true,
|
|
804
|
+
datePublished,
|
|
805
|
+
schema: normalizeSchemaUrl('http://published-tombstone'),
|
|
806
|
+
};
|
|
807
|
+
const { messages: publishedTombstones } = await messageStore.query(alice.did, [publishedTombstoneFilter]);
|
|
808
|
+
expect(publishedTombstones.length).toBe(1);
|
|
809
|
+
expect(await Message.getCid(publishedTombstones[0])).toBe(await Message.getCid(publishedDelete.message));
|
|
810
|
+
// the subscription receives the published record's write and delete events only
|
|
811
|
+
await Poller.pollUntilSuccessOrTimeout(async () => {
|
|
812
|
+
expect(receivedEvents.length).toBe(2);
|
|
813
|
+
});
|
|
814
|
+
const writeEvents = receivedEvents.filter((event) => event.message.descriptor.method === DwnMethodName.Write);
|
|
815
|
+
const deleteEvents = receivedEvents.filter((event) => event.message.descriptor.method === DwnMethodName.Delete);
|
|
816
|
+
expect(writeEvents.length).toBe(1);
|
|
817
|
+
expect(writeEvents[0].message.recordId).toBe(publishedWrite.message.recordId);
|
|
818
|
+
expect(deleteEvents.length).toBe(1);
|
|
819
|
+
expect(deleteEvents[0].message.descriptor.recordId).toBe(publishedWrite.message.recordId);
|
|
820
|
+
await subscribeReply.subscription.close();
|
|
821
|
+
});
|
|
822
|
+
it('should take mutable visibility facts from the latest pre-delete write and immutable facts from the initial write', async () => {
|
|
823
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
824
|
+
const datePublished = '2025-01-02T00:00:00.000000Z';
|
|
825
|
+
await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
|
|
826
|
+
// initial write: unpublished, tagged red
|
|
827
|
+
const initialWriteData = await TestDataGenerator.generateRecordsWrite({
|
|
828
|
+
author: alice,
|
|
829
|
+
schema: 'http://visibility-facts',
|
|
830
|
+
tags: { team: 'red' },
|
|
831
|
+
});
|
|
832
|
+
const initialWriteReply = await dwn.processMessage(alice.did, initialWriteData.message, { dataStream: initialWriteData.dataStream });
|
|
833
|
+
expect(initialWriteReply.status.code).toBe(202);
|
|
834
|
+
// update: published, tagged blue
|
|
835
|
+
const updateWrite = await RecordsWrite.createFrom({
|
|
836
|
+
recordsWriteMessage: initialWriteData.message,
|
|
837
|
+
published: true,
|
|
838
|
+
datePublished,
|
|
839
|
+
tags: { team: 'blue' },
|
|
840
|
+
signer: Jws.createSigner(alice),
|
|
841
|
+
});
|
|
842
|
+
const updateReply = await dwn.processMessage(alice.did, updateWrite.message);
|
|
843
|
+
expect(updateReply.status.code).toBe(202);
|
|
844
|
+
const recordsDelete = await RecordsDelete.create({
|
|
845
|
+
recordId: initialWriteData.message.recordId,
|
|
846
|
+
signer: Jws.createSigner(alice)
|
|
847
|
+
});
|
|
848
|
+
const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
|
|
849
|
+
expect(deleteReply.status.code).toBe(202);
|
|
850
|
+
const deleteMessageCid = await Message.getCid(recordsDelete.message);
|
|
851
|
+
// mutable facts come from the update that was the latest write immediately before deletion
|
|
852
|
+
const { messages: blueMatches } = await messageStore.query(alice.did, [{ 'method': DwnMethodName.Delete, 'tag.team': 'blue' }]);
|
|
853
|
+
expect(blueMatches.length).toBe(1);
|
|
854
|
+
expect(await Message.getCid(blueMatches[0])).toBe(deleteMessageCid);
|
|
855
|
+
const { messages: redMatches } = await messageStore.query(alice.did, [{ 'method': DwnMethodName.Delete, 'tag.team': 'red' }]);
|
|
856
|
+
expect(redMatches.length).toBe(0);
|
|
857
|
+
// immutable facts still come from the initial write
|
|
858
|
+
const { messages: immutableMatches } = await messageStore.query(alice.did, [{
|
|
859
|
+
method: DwnMethodName.Delete,
|
|
860
|
+
schema: normalizeSchemaUrl('http://visibility-facts'),
|
|
861
|
+
dateCreated: initialWriteData.message.descriptor.dateCreated,
|
|
862
|
+
published: true,
|
|
863
|
+
datePublished,
|
|
864
|
+
}]);
|
|
865
|
+
expect(immutableMatches.length).toBe(1);
|
|
866
|
+
expect(await Message.getCid(immutableMatches[0])).toBe(deleteMessageCid);
|
|
867
|
+
});
|
|
868
|
+
it('should carry the existing tombstone visibility facts forward when pruning an already-deleted record', async () => {
|
|
869
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
870
|
+
const datePublished = '2025-01-03T00:00:00.000000Z';
|
|
871
|
+
await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
|
|
872
|
+
// initial write: unpublished, tagged red
|
|
873
|
+
const initialWriteData = await TestDataGenerator.generateRecordsWrite({
|
|
874
|
+
author: alice,
|
|
875
|
+
tags: { team: 'red' },
|
|
876
|
+
});
|
|
877
|
+
const initialWriteReply = await dwn.processMessage(alice.did, initialWriteData.message, { dataStream: initialWriteData.dataStream });
|
|
878
|
+
expect(initialWriteReply.status.code).toBe(202);
|
|
879
|
+
// update: published, tagged blue
|
|
880
|
+
const updateWrite = await RecordsWrite.createFrom({
|
|
881
|
+
recordsWriteMessage: initialWriteData.message,
|
|
882
|
+
published: true,
|
|
883
|
+
datePublished,
|
|
884
|
+
tags: { team: 'blue' },
|
|
885
|
+
signer: Jws.createSigner(alice),
|
|
886
|
+
});
|
|
887
|
+
const updateReply = await dwn.processMessage(alice.did, updateWrite.message);
|
|
888
|
+
expect(updateReply.status.code).toBe(202);
|
|
889
|
+
// plain delete: the tombstone carries the record's visibility facts
|
|
890
|
+
const plainDelete = await RecordsDelete.create({
|
|
891
|
+
recordId: initialWriteData.message.recordId,
|
|
892
|
+
signer: Jws.createSigner(alice)
|
|
893
|
+
});
|
|
894
|
+
const plainDeleteReply = await dwn.processMessage(alice.did, plainDelete.message);
|
|
895
|
+
expect(plainDeleteReply.status.code).toBe(202);
|
|
896
|
+
await Time.minimalSleep();
|
|
897
|
+
// prune of the already-deleted record: displaces the plain tombstone (prune beats plain)
|
|
898
|
+
const pruneDelete = await RecordsDelete.create({
|
|
899
|
+
recordId: initialWriteData.message.recordId,
|
|
900
|
+
prune: true,
|
|
901
|
+
signer: Jws.createSigner(alice)
|
|
902
|
+
});
|
|
903
|
+
const pruneDeleteReply = await dwn.processMessage(alice.did, pruneDelete.message);
|
|
904
|
+
expect(pruneDeleteReply.status.code).toBe(202);
|
|
905
|
+
// exactly one tombstone matches the visibility facts and it is the prune
|
|
906
|
+
const { messages: tombstones } = await messageStore.query(alice.did, [{
|
|
907
|
+
'method': DwnMethodName.Delete,
|
|
908
|
+
'tag.team': 'blue',
|
|
909
|
+
'published': true,
|
|
910
|
+
'datePublished': datePublished
|
|
911
|
+
}]);
|
|
912
|
+
expect(tombstones.length).toBe(1);
|
|
913
|
+
expect(await Message.getCid(tombstones[0])).toBe(await Message.getCid(pruneDelete.message));
|
|
914
|
+
expect(tombstones[0].descriptor.prune).toBe(true);
|
|
915
|
+
const { messages: redMatches } = await messageStore.query(alice.did, [{ 'method': DwnMethodName.Delete, 'tag.team': 'red' }]);
|
|
916
|
+
expect(redMatches.length).toBe(0);
|
|
917
|
+
});
|
|
918
|
+
it('should carry the displaced newer write tags and published state when a tombstone applies over it (delete-wins)', async () => {
|
|
919
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
920
|
+
const datePublished = '2025-01-04T00:00:00.000000Z';
|
|
921
|
+
await TestDataGenerator.installDefaultTestProtocol(dwn, alice);
|
|
922
|
+
// initial write: unpublished, tagged red
|
|
923
|
+
const initialWriteData = await TestDataGenerator.generateRecordsWrite({
|
|
924
|
+
author: alice,
|
|
925
|
+
tags: { team: 'red' },
|
|
926
|
+
});
|
|
927
|
+
const initialWriteReply = await dwn.processMessage(alice.did, initialWriteData.message, { dataStream: initialWriteData.dataStream });
|
|
928
|
+
expect(initialWriteReply.status.code).toBe(202);
|
|
929
|
+
// create the tombstone BEFORE the update so its `messageTimestamp` is older than the update's
|
|
930
|
+
const recordsDelete = await RecordsDelete.create({
|
|
931
|
+
recordId: initialWriteData.message.recordId,
|
|
932
|
+
signer: Jws.createSigner(alice)
|
|
933
|
+
});
|
|
934
|
+
await Time.minimalSleep();
|
|
935
|
+
// newer update: published, tagged blue
|
|
936
|
+
const updateWrite = await RecordsWrite.createFrom({
|
|
937
|
+
recordsWriteMessage: initialWriteData.message,
|
|
938
|
+
published: true,
|
|
939
|
+
datePublished,
|
|
940
|
+
tags: { team: 'blue' },
|
|
941
|
+
signer: Jws.createSigner(alice),
|
|
942
|
+
});
|
|
943
|
+
const updateReply = await dwn.processMessage(alice.did, updateWrite.message);
|
|
944
|
+
expect(updateReply.status.code).toBe(202);
|
|
945
|
+
// the older tombstone still applies over the newer write (delete-wins)
|
|
946
|
+
const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
|
|
947
|
+
expect(deleteReply.status.code).toBe(202);
|
|
948
|
+
// tombstone visibility facts reflect the displaced newer write
|
|
949
|
+
const { messages: blueMatches } = await messageStore.query(alice.did, [{
|
|
950
|
+
'method': DwnMethodName.Delete,
|
|
951
|
+
'tag.team': 'blue',
|
|
952
|
+
'published': true,
|
|
953
|
+
'datePublished': datePublished
|
|
954
|
+
}]);
|
|
955
|
+
expect(blueMatches.length).toBe(1);
|
|
956
|
+
expect(await Message.getCid(blueMatches[0])).toBe(await Message.getCid(recordsDelete.message));
|
|
957
|
+
const { messages: redMatches } = await messageStore.query(alice.did, [{ 'method': DwnMethodName.Delete, 'tag.team': 'red' }]);
|
|
958
|
+
expect(redMatches.length).toBe(0);
|
|
959
|
+
});
|
|
676
960
|
});
|
|
677
961
|
describe('state index', () => {
|
|
678
962
|
it('should include RecordsDelete event and keep initial RecordsWrite event', async () => {
|
|
@@ -687,18 +971,17 @@ export function testRecordsDeleteHandler() {
|
|
|
687
971
|
});
|
|
688
972
|
const deleteReply = await dwn.processMessage(alice.did, recordsDelete.message);
|
|
689
973
|
expect(deleteReply.status.code).toBe(202);
|
|
690
|
-
// NOTE: getLeaves returns ALL messageCids (including ProtocolsConfigure), so count is 3 not 2
|
|
691
|
-
const events = await stateIndex.getLeaves(alice.did, []);
|
|
692
|
-
expect(events.length).toBe(3);
|
|
693
974
|
const writeMessageCid = await Message.getCid(message);
|
|
694
975
|
const deleteMessageCid = await Message.getCid(recordsDelete.message);
|
|
695
976
|
const expectedMessageCids = new Set([writeMessageCid, deleteMessageCid]);
|
|
696
|
-
|
|
977
|
+
const { messages } = await messageStore.query(alice.did, [{ recordId: message.recordId }]);
|
|
978
|
+
for (const storedMessage of messages) {
|
|
979
|
+
const messageCid = await Message.getCid(storedMessage);
|
|
697
980
|
expectedMessageCids.delete(messageCid);
|
|
698
981
|
}
|
|
699
982
|
expect(expectedMessageCids.size).toBe(0);
|
|
700
983
|
});
|
|
701
|
-
it('should
|
|
984
|
+
it('should keep first write, latest pre-delete write, and delete when subsequent writes happen', async () => {
|
|
702
985
|
const author = await TestDataGenerator.generatePersona();
|
|
703
986
|
TestStubGenerator.stubDidResolver(didResolver, [author]);
|
|
704
987
|
await TestDataGenerator.installDefaultTestProtocol(dwn, author);
|
|
@@ -718,14 +1001,11 @@ export function testRecordsDeleteHandler() {
|
|
|
718
1001
|
});
|
|
719
1002
|
const deleteReply = await dwn.processMessage(author.did, recordsDelete.message);
|
|
720
1003
|
expect(deleteReply.status.code).toBe(202);
|
|
721
|
-
const
|
|
722
|
-
expect(
|
|
723
|
-
const
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
throw new Error(`${messageCid} should not exist`);
|
|
727
|
-
}
|
|
728
|
-
}
|
|
1004
|
+
const { messages } = await messageStore.query(author.did, [{ recordId: message.recordId }]);
|
|
1005
|
+
expect(messages.length).toBe(3); // first write + latest pre-delete write + delete
|
|
1006
|
+
const retainedWriteCid = await Message.getCid(newWrite.message);
|
|
1007
|
+
const retainedCids = await Promise.all(messages.map((storedMessage) => Message.getCid(storedMessage)));
|
|
1008
|
+
expect(retainedCids).toContain(retainedWriteCid);
|
|
729
1009
|
});
|
|
730
1010
|
});
|
|
731
1011
|
});
|
|
@@ -741,6 +1021,7 @@ export function testRecordsDeleteHandler() {
|
|
|
741
1021
|
const resumableTaskManagerStub = sinon.createStubInstance(ResumableTaskManager);
|
|
742
1022
|
const recordsDeleteHandler = new RecordsDeleteHandler({
|
|
743
1023
|
didResolver, messageStore: messageStoreStub, resumableTaskManager: resumableTaskManagerStub,
|
|
1024
|
+
validationStateReader: createTestValidationStateReader({ messageStore: messageStoreStub }),
|
|
744
1025
|
});
|
|
745
1026
|
const reply = await recordsDeleteHandler.handle({ tenant, message });
|
|
746
1027
|
expect(reply.status.code).toBe(401);
|
|
@@ -753,6 +1034,7 @@ export function testRecordsDeleteHandler() {
|
|
|
753
1034
|
const resumableTaskManagerStub = sinon.createStubInstance(ResumableTaskManager);
|
|
754
1035
|
const recordsDeleteHandler = new RecordsDeleteHandler({
|
|
755
1036
|
didResolver, messageStore: messageStoreStub, resumableTaskManager: resumableTaskManagerStub,
|
|
1037
|
+
validationStateReader: createTestValidationStateReader({ messageStore: messageStoreStub }),
|
|
756
1038
|
});
|
|
757
1039
|
// stub the `parse()` function to throw an error
|
|
758
1040
|
sinon.stub(RecordsDelete, 'parse').throws('anyError');
|