@opendatalabs/personal-server-ts-core 1.34.1 → 1.35.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/additions/durable.d.ts +32 -2
- package/dist/additions/durable.d.ts.map +1 -1
- package/dist/additions/durable.js +237 -88
- package/dist/additions/durable.js.map +1 -1
- package/dist/additions/version-inventory.d.ts +4 -0
- package/dist/additions/version-inventory.d.ts.map +1 -1
- package/dist/additions/version-inventory.js +11 -1
- package/dist/additions/version-inventory.js.map +1 -1
- package/dist/api/index.d.ts +19 -2
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +185 -13
- package/dist/api/index.js.map +1 -1
- package/dist/api/oura-collection-requirements.d.ts +16 -0
- package/dist/api/oura-collection-requirements.d.ts.map +1 -0
- package/dist/api/oura-collection-requirements.js +70 -0
- package/dist/api/oura-collection-requirements.js.map +1 -0
- package/dist/api/scope-upload-batches.d.ts +18 -0
- package/dist/api/scope-upload-batches.d.ts.map +1 -0
- package/dist/api/scope-upload-batches.js +71 -0
- package/dist/api/scope-upload-batches.js.map +1 -0
- package/dist/api/scope-uploads.d.ts +112 -0
- package/dist/api/scope-uploads.d.ts.map +1 -0
- package/dist/api/scope-uploads.js +369 -0
- package/dist/api/scope-uploads.js.map +1 -0
- package/dist/client.d.ts +70 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +1 -0
- package/dist/client.js.map +1 -1
- package/dist/contracts/data.d.ts +8 -0
- package/dist/contracts/data.d.ts.map +1 -1
- package/dist/contracts/data.js +31 -1
- package/dist/contracts/data.js.map +1 -1
- package/dist/contracts/grants.d.ts.map +1 -1
- package/dist/contracts/grants.js +3 -0
- package/dist/contracts/grants.js.map +1 -1
- package/dist/contracts/index.d.ts +3 -1
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js +3 -1
- package/dist/contracts/index.js.map +1 -1
- package/dist/contracts/oura-collection-requirements.d.ts +17 -0
- package/dist/contracts/oura-collection-requirements.d.ts.map +1 -0
- package/dist/contracts/oura-collection-requirements.js +49 -0
- package/dist/contracts/oura-collection-requirements.js.map +1 -0
- package/dist/legacy-projection/bindings.d.ts +1 -7
- package/dist/legacy-projection/bindings.d.ts.map +1 -1
- package/dist/legacy-projection/bindings.js +162 -28
- package/dist/legacy-projection/bindings.js.map +1 -1
- package/dist/legacy-projection/index.d.ts +6 -5
- package/dist/legacy-projection/index.d.ts.map +1 -1
- package/dist/legacy-projection/index.js +9 -21
- package/dist/legacy-projection/index.js.map +1 -1
- package/dist/legacy-projection/oura-browser-bindings.d.ts +2 -0
- package/dist/legacy-projection/oura-browser-bindings.d.ts.map +1 -1
- package/dist/legacy-projection/oura-browser-bindings.js +2 -0
- package/dist/legacy-projection/oura-browser-bindings.js.map +1 -1
- package/dist/legacy-projection/strava-browser-bindings.d.ts +3 -0
- package/dist/legacy-projection/strava-browser-bindings.d.ts.map +1 -0
- package/dist/legacy-projection/strava-browser-bindings.js +32 -0
- package/dist/legacy-projection/strava-browser-bindings.js.map +1 -0
- package/dist/legacy-projection/types.d.ts +44 -12
- package/dist/legacy-projection/types.d.ts.map +1 -1
- package/dist/mcp/connection-api.d.ts +11 -1
- package/dist/mcp/connection-api.d.ts.map +1 -1
- package/dist/mcp/connection-api.js +94 -9
- package/dist/mcp/connection-api.js.map +1 -1
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +1 -0
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/server.d.ts +9 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +19 -6
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/store.d.ts +10 -1
- package/dist/mcp/store.d.ts.map +1 -1
- package/dist/mcp/store.js +51 -0
- package/dist/mcp/store.js.map +1 -1
- package/dist/mcp/tools.d.ts +52 -2
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +395 -11
- package/dist/mcp/tools.js.map +1 -1
- package/dist/mcp/types.d.ts +36 -2
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/mcp/types.js +12 -0
- package/dist/mcp/types.js.map +1 -1
- package/dist/mcp/write-client.d.ts +81 -0
- package/dist/mcp/write-client.d.ts.map +1 -0
- package/dist/mcp/write-client.js +140 -0
- package/dist/mcp/write-client.js.map +1 -0
- package/dist/oura/history-policy.d.ts +12 -0
- package/dist/oura/history-policy.d.ts.map +1 -0
- package/dist/oura/history-policy.js +54 -0
- package/dist/oura/history-policy.js.map +1 -0
- package/dist/oura/index.d.ts +51 -0
- package/dist/oura/index.d.ts.map +1 -0
- package/dist/oura/index.js +315 -0
- package/dist/oura/index.js.map +1 -0
- package/dist/pdpp/approval.d.ts +1 -1
- package/dist/pdpp/approval.d.ts.map +1 -1
- package/dist/pdpp/approval.js +29 -10
- package/dist/pdpp/approval.js.map +1 -1
- package/dist/pdpp/declaration-limits.d.ts +7 -0
- package/dist/pdpp/declaration-limits.d.ts.map +1 -0
- package/dist/pdpp/declaration-limits.js +7 -0
- package/dist/pdpp/declaration-limits.js.map +1 -0
- package/dist/pdpp/declaration.d.ts +2 -1
- package/dist/pdpp/declaration.d.ts.map +1 -1
- package/dist/pdpp/declaration.js +2 -1
- package/dist/pdpp/declaration.js.map +1 -1
- package/dist/pdpp/index.d.ts +3 -2
- package/dist/pdpp/index.d.ts.map +1 -1
- package/dist/pdpp/index.js +3 -2
- package/dist/pdpp/index.js.map +1 -1
- package/dist/pdpp/issuance.d.ts.map +1 -1
- package/dist/pdpp/issuance.js +6 -2
- package/dist/pdpp/issuance.js.map +1 -1
- package/dist/pdpp/resolve.d.ts +12 -1
- package/dist/pdpp/resolve.d.ts.map +1 -1
- package/dist/pdpp/resolve.js +156 -58
- package/dist/pdpp/resolve.js.map +1 -1
- package/dist/pdpp/selection.d.ts +30 -1
- package/dist/pdpp/selection.d.ts.map +1 -1
- package/dist/pdpp/selection.js +77 -26
- package/dist/pdpp/selection.js.map +1 -1
- package/dist/pdpp/time.d.ts +39 -0
- package/dist/pdpp/time.d.ts.map +1 -0
- package/dist/pdpp/time.js +173 -0
- package/dist/pdpp/time.js.map +1 -0
- package/dist/pdpp/tokens.d.ts.map +1 -1
- package/dist/pdpp/tokens.js +4 -2
- package/dist/pdpp/tokens.js.map +1 -1
- package/dist/pdpp/types.d.ts +18 -2
- package/dist/pdpp/types.d.ts.map +1 -1
- package/dist/pdpp/types.js +7 -0
- package/dist/pdpp/types.js.map +1 -1
- package/dist/policy/reserved-scopes.d.ts +7 -0
- package/dist/policy/reserved-scopes.d.ts.map +1 -1
- package/dist/policy/reserved-scopes.js +12 -1
- package/dist/policy/reserved-scopes.js.map +1 -1
- package/dist/ports/index.d.ts +89 -1
- package/dist/ports/index.d.ts.map +1 -1
- package/dist/ports/index.js.map +1 -1
- package/dist/ports/pdpp-auth.d.ts +17 -27
- package/dist/ports/pdpp-auth.d.ts.map +1 -1
- package/dist/ports/pdpp-auth.js +14 -28
- package/dist/ports/pdpp-auth.js.map +1 -1
- package/dist/publication/publish.d.ts +96 -0
- package/dist/publication/publish.d.ts.map +1 -0
- package/dist/publication/publish.js +261 -0
- package/dist/publication/publish.js.map +1 -0
- package/dist/replication/completion.d.ts +20 -0
- package/dist/replication/completion.d.ts.map +1 -0
- package/dist/replication/completion.js +73 -0
- package/dist/replication/completion.js.map +1 -0
- package/dist/replication/coordinator-state.d.ts +29 -0
- package/dist/replication/coordinator-state.d.ts.map +1 -0
- package/dist/replication/coordinator-state.js +88 -0
- package/dist/replication/coordinator-state.js.map +1 -0
- package/dist/replication/coordinator-state.test-utils.d.ts +32 -0
- package/dist/replication/coordinator-state.test-utils.d.ts.map +1 -0
- package/dist/replication/coordinator-state.test-utils.js +113 -0
- package/dist/replication/coordinator-state.test-utils.js.map +1 -0
- package/dist/replication/coordinator.d.ts +264 -0
- package/dist/replication/coordinator.d.ts.map +1 -0
- package/dist/replication/coordinator.js +499 -0
- package/dist/replication/coordinator.js.map +1 -0
- package/dist/replication/copies.d.ts +126 -0
- package/dist/replication/copies.d.ts.map +1 -0
- package/dist/replication/copies.js +437 -0
- package/dist/replication/copies.js.map +1 -0
- package/dist/replication/copy-promotion.d.ts +132 -0
- package/dist/replication/copy-promotion.d.ts.map +1 -0
- package/dist/replication/copy-promotion.js +126 -0
- package/dist/replication/copy-promotion.js.map +1 -0
- package/dist/replication/door.d.ts +33 -0
- package/dist/replication/door.d.ts.map +1 -0
- package/dist/replication/door.js +10 -0
- package/dist/replication/door.js.map +1 -0
- package/dist/replication/dpv2.d.ts +141 -0
- package/dist/replication/dpv2.d.ts.map +1 -0
- package/dist/replication/dpv2.js +320 -0
- package/dist/replication/dpv2.js.map +1 -0
- package/dist/replication/effects.d.ts +68 -0
- package/dist/replication/effects.d.ts.map +1 -0
- package/dist/replication/effects.js +89 -0
- package/dist/replication/effects.js.map +1 -0
- package/dist/replication/engine.d.ts +378 -0
- package/dist/replication/engine.d.ts.map +1 -0
- package/dist/replication/engine.js +3197 -0
- package/dist/replication/engine.js.map +1 -0
- package/dist/replication/envelope.d.ts +481 -0
- package/dist/replication/envelope.d.ts.map +1 -0
- package/dist/replication/envelope.js +192 -0
- package/dist/replication/envelope.js.map +1 -0
- package/dist/replication/evidence.d.ts +118 -0
- package/dist/replication/evidence.d.ts.map +1 -0
- package/dist/replication/evidence.js +198 -0
- package/dist/replication/evidence.js.map +1 -0
- package/dist/replication/finality.d.ts +16 -0
- package/dist/replication/finality.d.ts.map +1 -0
- package/dist/replication/finality.js +11 -0
- package/dist/replication/finality.js.map +1 -0
- package/dist/replication/fixtures.d.ts +16 -0
- package/dist/replication/fixtures.d.ts.map +1 -0
- package/dist/replication/fixtures.js +47 -0
- package/dist/replication/fixtures.js.map +1 -0
- package/dist/replication/host-config.d.ts +52 -0
- package/dist/replication/host-config.d.ts.map +1 -0
- package/dist/replication/host-config.js +111 -0
- package/dist/replication/host-config.js.map +1 -0
- package/dist/replication/host-driver.d.ts +95 -0
- package/dist/replication/host-driver.d.ts.map +1 -0
- package/dist/replication/host-driver.js +202 -0
- package/dist/replication/host-driver.js.map +1 -0
- package/dist/replication/host-ports.d.ts +48 -0
- package/dist/replication/host-ports.d.ts.map +1 -0
- package/dist/replication/host-ports.js +69 -0
- package/dist/replication/host-ports.js.map +1 -0
- package/dist/replication/identity.d.ts +13 -0
- package/dist/replication/identity.d.ts.map +1 -0
- package/dist/replication/identity.js +22 -0
- package/dist/replication/identity.js.map +1 -0
- package/dist/replication/limits.d.ts +124 -0
- package/dist/replication/limits.d.ts.map +1 -0
- package/dist/replication/limits.js +182 -0
- package/dist/replication/limits.js.map +1 -0
- package/dist/replication/merge-plan.d.ts +92 -0
- package/dist/replication/merge-plan.d.ts.map +1 -0
- package/dist/replication/merge-plan.js +229 -0
- package/dist/replication/merge-plan.js.map +1 -0
- package/dist/replication/namespace.d.ts +4 -0
- package/dist/replication/namespace.d.ts.map +1 -0
- package/dist/replication/namespace.js +7 -0
- package/dist/replication/namespace.js.map +1 -0
- package/dist/replication/outcome.d.ts +178 -0
- package/dist/replication/outcome.d.ts.map +1 -0
- package/dist/replication/outcome.js +83 -0
- package/dist/replication/outcome.js.map +1 -0
- package/dist/replication/payload.d.ts +39 -0
- package/dist/replication/payload.d.ts.map +1 -0
- package/dist/replication/payload.js +137 -0
- package/dist/replication/payload.js.map +1 -0
- package/dist/replication/preparation.d.ts +42 -0
- package/dist/replication/preparation.d.ts.map +1 -0
- package/dist/replication/preparation.js +118 -0
- package/dist/replication/preparation.js.map +1 -0
- package/dist/replication/rebaseline.d.ts +33 -0
- package/dist/replication/rebaseline.d.ts.map +1 -0
- package/dist/replication/rebaseline.js +40 -0
- package/dist/replication/rebaseline.js.map +1 -0
- package/dist/replication/rebinding.d.ts +43 -0
- package/dist/replication/rebinding.d.ts.map +1 -0
- package/dist/replication/rebinding.js +52 -0
- package/dist/replication/rebinding.js.map +1 -0
- package/dist/replication/receive.d.ts +57 -0
- package/dist/replication/receive.d.ts.map +1 -0
- package/dist/replication/receive.js +114 -0
- package/dist/replication/receive.js.map +1 -0
- package/dist/replication/record-reducer.d.ts +16 -0
- package/dist/replication/record-reducer.d.ts.map +1 -0
- package/dist/replication/record-reducer.js +52 -0
- package/dist/replication/record-reducer.js.map +1 -0
- package/dist/replication/revision.d.ts +24 -0
- package/dist/replication/revision.d.ts.map +1 -0
- package/dist/replication/revision.js +35 -0
- package/dist/replication/revision.js.map +1 -0
- package/dist/replication/roster.d.ts +53 -0
- package/dist/replication/roster.d.ts.map +1 -0
- package/dist/replication/roster.js +115 -0
- package/dist/replication/roster.js.map +1 -0
- package/dist/replication/schedule.d.ts +73 -0
- package/dist/replication/schedule.d.ts.map +1 -0
- package/dist/replication/schedule.js +182 -0
- package/dist/replication/schedule.js.map +1 -0
- package/dist/replication/stream.d.ts +73 -0
- package/dist/replication/stream.d.ts.map +1 -0
- package/dist/replication/stream.js +542 -0
- package/dist/replication/stream.js.map +1 -0
- package/dist/replication/transport.d.ts +236 -0
- package/dist/replication/transport.d.ts.map +1 -0
- package/dist/replication/transport.js +440 -0
- package/dist/replication/transport.js.map +1 -0
- package/dist/replication/visibility-engine.d.ts +337 -0
- package/dist/replication/visibility-engine.d.ts.map +1 -0
- package/dist/replication/visibility-engine.js +602 -0
- package/dist/replication/visibility-engine.js.map +1 -0
- package/dist/replication/visibility-policy.d.ts +26 -0
- package/dist/replication/visibility-policy.d.ts.map +1 -0
- package/dist/replication/visibility-policy.js +33 -0
- package/dist/replication/visibility-policy.js.map +1 -0
- package/dist/replication/writer-identity-store.d.ts +100 -0
- package/dist/replication/writer-identity-store.d.ts.map +1 -0
- package/dist/replication/writer-identity-store.js +218 -0
- package/dist/replication/writer-identity-store.js.map +1 -0
- package/dist/replication/writer-identity.d.ts +252 -0
- package/dist/replication/writer-identity.d.ts.map +1 -0
- package/dist/replication/writer-identity.js +281 -0
- package/dist/replication/writer-identity.js.map +1 -0
- package/dist/replication/writer-identity.test-utils.d.ts +24 -0
- package/dist/replication/writer-identity.test-utils.d.ts.map +1 -0
- package/dist/replication/writer-identity.test-utils.js +86 -0
- package/dist/replication/writer-identity.test-utils.js.map +1 -0
- package/dist/schemas/server-config.d.ts +13 -0
- package/dist/schemas/server-config.d.ts.map +1 -1
- package/dist/schemas/server-config.js +24 -0
- package/dist/schemas/server-config.js.map +1 -1
- package/dist/storage/adapters/index.d.ts +3 -1
- package/dist/storage/adapters/index.d.ts.map +1 -1
- package/dist/storage/adapters/index.js +2 -0
- package/dist/storage/adapters/index.js.map +1 -1
- package/dist/storage/adapters/interface.d.ts +18 -1
- package/dist/storage/adapters/interface.d.ts.map +1 -1
- package/dist/storage/adapters/interface.js +13 -1
- package/dist/storage/adapters/interface.js.map +1 -1
- package/dist/storage/adapters/sdk.d.ts +2 -1
- package/dist/storage/adapters/sdk.d.ts.map +1 -1
- package/dist/storage/adapters/sdk.js +21 -3
- package/dist/storage/adapters/sdk.js.map +1 -1
- package/dist/storage/adapters/vana-audience.d.ts +17 -5
- package/dist/storage/adapters/vana-audience.d.ts.map +1 -1
- package/dist/storage/adapters/vana-audience.js +24 -9
- package/dist/storage/adapters/vana-audience.js.map +1 -1
- package/dist/storage/adapters/vana.d.ts +2 -2
- package/dist/storage/adapters/vana.d.ts.map +1 -1
- package/dist/storage/adapters/vana.js +30 -22
- package/dist/storage/adapters/vana.js.map +1 -1
- package/dist/storage/canonical-legacy-projection.d.ts +1 -1
- package/dist/storage/canonical-legacy-projection.d.ts.map +1 -1
- package/dist/storage/canonical-legacy-projection.js +13 -15
- package/dist/storage/canonical-legacy-projection.js.map +1 -1
- package/dist/storage/legacy-projection.d.ts.map +1 -1
- package/dist/storage/legacy-projection.js +17 -9
- package/dist/storage/legacy-projection.js.map +1 -1
- package/dist/storage/legacy-scope-coverage-exceptions.d.ts +5 -0
- package/dist/storage/legacy-scope-coverage-exceptions.d.ts.map +1 -1
- package/dist/storage/legacy-scope-coverage-exceptions.js +4 -0
- package/dist/storage/legacy-scope-coverage-exceptions.js.map +1 -1
- package/dist/storage/legacy-scope-coverage.d.ts.map +1 -1
- package/dist/storage/legacy-scope-coverage.js +14 -1
- package/dist/storage/legacy-scope-coverage.js.map +1 -1
- package/dist/storage/legacy-scope-entity-keys.d.ts +14 -1
- package/dist/storage/legacy-scope-entity-keys.d.ts.map +1 -1
- package/dist/storage/legacy-scope-entity-keys.js +18 -1
- package/dist/storage/legacy-scope-entity-keys.js.map +1 -1
- package/dist/storage/legacy-scope-view.d.ts +57 -5
- package/dist/storage/legacy-scope-view.d.ts.map +1 -1
- package/dist/storage/legacy-scope-view.js +644 -318
- package/dist/storage/legacy-scope-view.js.map +1 -1
- package/dist/storage/pdpp-records/cursor.d.ts +47 -2
- package/dist/storage/pdpp-records/cursor.d.ts.map +1 -1
- package/dist/storage/pdpp-records/cursor.js +7 -0
- package/dist/storage/pdpp-records/cursor.js.map +1 -1
- package/dist/storage/pdpp-records/enforcement.d.ts +3 -16
- package/dist/storage/pdpp-records/enforcement.d.ts.map +1 -1
- package/dist/storage/pdpp-records/enforcement.js +40 -13
- package/dist/storage/pdpp-records/enforcement.js.map +1 -1
- package/dist/storage/pdpp-records/index.d.ts +2 -0
- package/dist/storage/pdpp-records/index.d.ts.map +1 -1
- package/dist/storage/pdpp-records/index.js +1 -0
- package/dist/storage/pdpp-records/index.js.map +1 -1
- package/dist/storage/pdpp-records/interface.d.ts +8 -1
- package/dist/storage/pdpp-records/interface.d.ts.map +1 -1
- package/dist/storage/pdpp-records/list-page.d.ts +35 -0
- package/dist/storage/pdpp-records/list-page.d.ts.map +1 -0
- package/dist/storage/pdpp-records/list-page.js +106 -0
- package/dist/storage/pdpp-records/list-page.js.map +1 -0
- package/dist/storage/pdpp-records/memory-store.d.ts.map +1 -1
- package/dist/storage/pdpp-records/memory-store.js +95 -99
- package/dist/storage/pdpp-records/memory-store.js.map +1 -1
- package/dist/storage/pdpp-records/portable.d.ts +3 -0
- package/dist/storage/pdpp-records/portable.d.ts.map +1 -1
- package/dist/storage/pdpp-records/portable.js +3 -0
- package/dist/storage/pdpp-records/portable.js.map +1 -1
- package/dist/storage/pdpp-records/replication-journal.d.ts +20 -0
- package/dist/storage/pdpp-records/replication-journal.d.ts.map +1 -0
- package/dist/storage/pdpp-records/replication-journal.js +2 -0
- package/dist/storage/pdpp-records/replication-journal.js.map +1 -0
- package/dist/storage/pdpp-records/stream-declaration.d.ts +0 -2
- package/dist/storage/pdpp-records/stream-declaration.d.ts.map +1 -1
- package/dist/storage/pdpp-records/stream-declaration.js +0 -9
- package/dist/storage/pdpp-records/stream-declaration.js.map +1 -1
- package/dist/storage/pdpp-records/sync-selection.d.ts +4 -0
- package/dist/storage/pdpp-records/sync-selection.d.ts.map +1 -0
- package/dist/storage/pdpp-records/sync-selection.js +37 -0
- package/dist/storage/pdpp-records/sync-selection.js.map +1 -0
- package/dist/storage/pdpp-records/types.d.ts +64 -0
- package/dist/storage/pdpp-records/types.d.ts.map +1 -1
- package/dist/storage/pdpp-records/types.js.map +1 -1
- package/dist/sync/data-point-feed.d.ts.map +1 -1
- package/dist/sync/data-point-feed.js +4 -1
- package/dist/sync/data-point-feed.js.map +1 -1
- package/dist/sync/delete-data-port.d.ts +15 -0
- package/dist/sync/delete-data-port.d.ts.map +1 -1
- package/dist/sync/delete-data-port.js +19 -7
- package/dist/sync/delete-data-port.js.map +1 -1
- package/dist/sync/index.d.ts +2 -1
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +2 -1
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/pending-blob-deletions.d.ts +18 -2
- package/dist/sync/pending-blob-deletions.d.ts.map +1 -1
- package/dist/sync/pending-blob-deletions.js +69 -23
- package/dist/sync/pending-blob-deletions.js.map +1 -1
- package/dist/sync/scope-deletions.d.ts +2 -0
- package/dist/sync/scope-deletions.d.ts.map +1 -1
- package/dist/sync/scope-deletions.js +60 -19
- package/dist/sync/scope-deletions.js.map +1 -1
- package/dist/sync/workers/delete.d.ts.map +1 -1
- package/dist/sync/workers/delete.js +316 -142
- package/dist/sync/workers/delete.js.map +1 -1
- package/dist/sync/workers/download.d.ts.map +1 -1
- package/dist/sync/workers/download.js +53 -5
- package/dist/sync/workers/download.js.map +1 -1
- package/dist/sync/workers/upload.d.ts +24 -5
- package/dist/sync/workers/upload.d.ts.map +1 -1
- package/dist/sync/workers/upload.js +160 -275
- package/dist/sync/workers/upload.js.map +1 -1
- package/dist/test-utils/memory-storage.d.ts.map +1 -1
- package/dist/test-utils/memory-storage.js +17 -2
- package/dist/test-utils/memory-storage.js.map +1 -1
- package/package.json +24 -2
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export { REPLICA_MAX_FRAGMENTS, REPLICA_MAX_BLOB_BYTES, REPLICA_FRAGMENT_OVERHEAD_BYTES, replicaFramedBytesBound, } from "./limits.js";
|
|
3
|
+
import { type ReplicaBatchFacts } from "./writer-identity.js";
|
|
4
|
+
export { REPLICA_SCOPE_PREFIX, isReplicaScope } from "./namespace.js";
|
|
5
|
+
/** Nesting that no manifest or fragment reaches. */
|
|
6
|
+
export declare const REPLICA_MAX_JSON_DEPTH = 16;
|
|
7
|
+
/**
|
|
8
|
+
* Structural characters (`[`, `{`, `,` and `:`) of a manifest at the
|
|
9
|
+
* fragment limit, with room for its statement. A small document of tiny
|
|
10
|
+
* values allocates far more than its size, so this is bounded before parsing.
|
|
11
|
+
*/
|
|
12
|
+
export declare const REPLICA_MAX_JSON_TOKENS: number;
|
|
13
|
+
export declare const predecessorSchema: z.ZodObject<{
|
|
14
|
+
batch: z.ZodString;
|
|
15
|
+
digest: z.ZodString;
|
|
16
|
+
}, z.core.$strict>;
|
|
17
|
+
export declare const replicaFragmentSchema: z.ZodObject<{
|
|
18
|
+
format: z.ZodLiteral<"vana-pdpp-replica-fragment">;
|
|
19
|
+
version: z.ZodLiteral<3>;
|
|
20
|
+
owner: z.ZodString;
|
|
21
|
+
writer: z.ZodString;
|
|
22
|
+
batch: z.ZodString;
|
|
23
|
+
sequence: z.ZodNumber;
|
|
24
|
+
previous: z.ZodNullable<z.ZodObject<{
|
|
25
|
+
batch: z.ZodString;
|
|
26
|
+
digest: z.ZodString;
|
|
27
|
+
}, z.core.$strict>>;
|
|
28
|
+
collectedAt: z.ZodString;
|
|
29
|
+
digest: z.ZodString;
|
|
30
|
+
totalBytes: z.ZodNumber;
|
|
31
|
+
count: z.ZodNumber;
|
|
32
|
+
index: z.ZodNumber;
|
|
33
|
+
offset: z.ZodNumber;
|
|
34
|
+
chunkDigest: z.ZodString;
|
|
35
|
+
content: z.ZodString;
|
|
36
|
+
}, z.core.$strict>;
|
|
37
|
+
export type ReplicaFragment = z.infer<typeof replicaFragmentSchema>;
|
|
38
|
+
export type Predecessor = z.infer<typeof predecessorSchema>;
|
|
39
|
+
/**
|
|
40
|
+
* One fragment's entry in its batch manifest: the sha256 of the exact
|
|
41
|
+
* encrypted object and its length. The digest is also the storage address,
|
|
42
|
+
* so a receiver checks fetched bytes against the finalized manifest before
|
|
43
|
+
* it decrypts them.
|
|
44
|
+
*/
|
|
45
|
+
export declare const manifestEntrySchema: z.ZodObject<{
|
|
46
|
+
digest: z.ZodString;
|
|
47
|
+
bytes: z.ZodNumber;
|
|
48
|
+
}, z.core.$strict>;
|
|
49
|
+
export type ManifestEntry = z.infer<typeof manifestEntrySchema>;
|
|
50
|
+
/**
|
|
51
|
+
* The one registered object of a batch. Its DPv2 slot is the writer's scope at
|
|
52
|
+
* the next free version. It lists every fragment, in index order, by digest
|
|
53
|
+
* and size, and carries the batch statement signed by the writer's server
|
|
54
|
+
* key, which covers every other field and the slot. The version is a
|
|
55
|
+
* publication slot, not the batch sequence: a batch that cannot be framed
|
|
56
|
+
* takes no slot, so its successors still publish.
|
|
57
|
+
*/
|
|
58
|
+
export declare const replicaManifestSchema: z.ZodObject<{
|
|
59
|
+
format: z.ZodLiteral<"vana-pdpp-replica-manifest">;
|
|
60
|
+
version: z.ZodLiteral<1>;
|
|
61
|
+
owner: z.ZodString;
|
|
62
|
+
writer: z.ZodString;
|
|
63
|
+
batch: z.ZodString;
|
|
64
|
+
sequence: z.ZodNumber;
|
|
65
|
+
previous: z.ZodNullable<z.ZodObject<{
|
|
66
|
+
batch: z.ZodString;
|
|
67
|
+
digest: z.ZodString;
|
|
68
|
+
}, z.core.$strict>>;
|
|
69
|
+
collectedAt: z.ZodString;
|
|
70
|
+
digest: z.ZodString;
|
|
71
|
+
totalBytes: z.ZodNumber;
|
|
72
|
+
fragments: z.ZodArray<z.ZodObject<{
|
|
73
|
+
digest: z.ZodString;
|
|
74
|
+
bytes: z.ZodNumber;
|
|
75
|
+
}, z.core.$strict>>;
|
|
76
|
+
authority: z.ZodObject<{
|
|
77
|
+
chainId: z.ZodNumber;
|
|
78
|
+
statement: z.ZodObject<{
|
|
79
|
+
owner: z.ZodString;
|
|
80
|
+
server: z.ZodString;
|
|
81
|
+
serverId: z.ZodString;
|
|
82
|
+
environment: z.ZodEnum<{
|
|
83
|
+
dev: "dev";
|
|
84
|
+
prod: "prod";
|
|
85
|
+
}>;
|
|
86
|
+
writerNonce: z.ZodString;
|
|
87
|
+
version: z.ZodNumber;
|
|
88
|
+
batch: z.ZodString;
|
|
89
|
+
sequence: z.ZodNumber;
|
|
90
|
+
previous: z.ZodString;
|
|
91
|
+
previousBatch: z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<"">]>;
|
|
92
|
+
collectedAt: z.ZodString;
|
|
93
|
+
digest: z.ZodString;
|
|
94
|
+
totalBytes: z.ZodNumber;
|
|
95
|
+
count: z.ZodNumber;
|
|
96
|
+
fragments: z.ZodString;
|
|
97
|
+
}, z.core.$strict>;
|
|
98
|
+
signature: z.ZodString;
|
|
99
|
+
}, z.core.$strict>;
|
|
100
|
+
}, z.core.$strict>;
|
|
101
|
+
export type ReplicaManifest = z.infer<typeof replicaManifestSchema>;
|
|
102
|
+
/** An unregistered, content-addressed fragment ready for storage. */
|
|
103
|
+
export interface PreparedFragment {
|
|
104
|
+
/** The writer scope whose key encrypts the fragment. */
|
|
105
|
+
scope: string;
|
|
106
|
+
index: number;
|
|
107
|
+
plaintext: Uint8Array;
|
|
108
|
+
encrypted: Uint8Array;
|
|
109
|
+
/** sha256 of `encrypted`: the manifest entry and the storage address. */
|
|
110
|
+
digest: string;
|
|
111
|
+
}
|
|
112
|
+
/** A batch manifest ready for storage and its single registration. */
|
|
113
|
+
export interface PreparedManifest {
|
|
114
|
+
scope: string;
|
|
115
|
+
/** The DPv2 version this manifest registers, claimed when the batch is prepared. */
|
|
116
|
+
version: number;
|
|
117
|
+
plaintext: Uint8Array;
|
|
118
|
+
encrypted: Uint8Array;
|
|
119
|
+
dataHash: `0x${string}`;
|
|
120
|
+
metadataHash: `0x${string}`;
|
|
121
|
+
}
|
|
122
|
+
/** One stable scope per writer. Each batch appends one version to it. */
|
|
123
|
+
export declare function replicaScope(writer: string): string;
|
|
124
|
+
/** The writer of a replica scope, or undefined for any other name. */
|
|
125
|
+
export declare function replicaWriterOf(scope: string): string | undefined;
|
|
126
|
+
/** Storage key of a content-addressed fragment. Never registered. */
|
|
127
|
+
export declare function replicaFragmentKey(scope: string, fragmentDigest: string): string;
|
|
128
|
+
/** Storage key of a manifest: the ordinary DPv2 `<scope>/<version>` key. */
|
|
129
|
+
export declare function replicaManifestKey(scope: string, version: number): string;
|
|
130
|
+
export declare function replicaDigest(bytes: Uint8Array): string;
|
|
131
|
+
export declare function toBase64(bytes: Uint8Array): string;
|
|
132
|
+
export declare function fromBase64(value: string): Uint8Array;
|
|
133
|
+
export declare function replicaMetadataHash(scope: string, collectedAt: string, sizeBytes: number): `0x${string}`;
|
|
134
|
+
/**
|
|
135
|
+
* A manifest that can never be valid at its slot, with the refusal of the
|
|
136
|
+
* first check it fails. The caller has already matched its bytes to the
|
|
137
|
+
* slot's finalized commitment, so the refusal is terminal.
|
|
138
|
+
*/
|
|
139
|
+
export declare class ReplicaManifestRefused extends Error {
|
|
140
|
+
readonly reason: "signature_invalid" | "partition_mismatch" | "writer_mismatch" | "manifest_invalid";
|
|
141
|
+
constructor(reason: "signature_invalid" | "partition_mismatch" | "writer_mismatch" | "manifest_invalid");
|
|
142
|
+
}
|
|
143
|
+
/** Replica JSON over a bound that no writer reaches. */
|
|
144
|
+
export declare class ReplicaJsonRefused extends Error {
|
|
145
|
+
constructor();
|
|
146
|
+
}
|
|
147
|
+
export interface ParsedReplicaJson {
|
|
148
|
+
encoded: string;
|
|
149
|
+
value: unknown;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Parse replica JSON. One pass without recursion bounds nesting and
|
|
153
|
+
* structural tokens before `JSON.parse` allocates anything, so the recursive
|
|
154
|
+
* work after it (schemas, `canonicalJson`) stays inside those bounds. Throws
|
|
155
|
+
* ReplicaJsonRefused over a bound, and the parser's own error for bytes that
|
|
156
|
+
* are not UTF-8 JSON.
|
|
157
|
+
*/
|
|
158
|
+
export declare function parseReplicaJson(plaintext: Uint8Array): ParsedReplicaJson;
|
|
159
|
+
/**
|
|
160
|
+
* The most encrypted fragment bytes a batch of `totalBytes` needs in `count`
|
|
161
|
+
* fragments: the base64 of every chunk plus a fixed overhead per fragment.
|
|
162
|
+
*/
|
|
163
|
+
/** The facts a manifest at `version` claims; its statement must sign exactly these. */
|
|
164
|
+
export declare function replicaManifestFacts(manifest: Omit<ReplicaManifest, "authority">, version: number): ReplicaBatchFacts;
|
|
165
|
+
export declare function decodeReplicaFragment(plaintext: Uint8Array, scope: string, owner: string): ReplicaFragment;
|
|
166
|
+
/** Fragment decoding after the shared receive boundary's bounded parse. */
|
|
167
|
+
export declare function decodeParsedReplicaFragment({ encoded, value }: ParsedReplicaJson, scope: string, owner: string): ReplicaFragment;
|
|
168
|
+
/** Exact framing size without allocating a base64 content string or encrypting. */
|
|
169
|
+
export declare function replicaFragmentPlaintextByteLength(input: Omit<ReplicaFragment, "format" | "version" | "chunkDigest" | "content"> & {
|
|
170
|
+
chunkBytes: number;
|
|
171
|
+
}): number;
|
|
172
|
+
/** The single fragment encoder shared by buffered and streaming publishers.
|
|
173
|
+
* Freeze returned bytes before I/O: encryption is randomized. */
|
|
174
|
+
export declare function prepareReplicaFragment(input: {
|
|
175
|
+
owner: string;
|
|
176
|
+
writer: string;
|
|
177
|
+
batch: string;
|
|
178
|
+
sequence: number;
|
|
179
|
+
previous: Predecessor | null;
|
|
180
|
+
collectedAt: string;
|
|
181
|
+
digest: string;
|
|
182
|
+
totalBytes: number;
|
|
183
|
+
count: number;
|
|
184
|
+
index: number;
|
|
185
|
+
offset: number;
|
|
186
|
+
chunk: Uint8Array;
|
|
187
|
+
encrypt: (scope: string, bytes: Uint8Array) => Promise<Uint8Array>;
|
|
188
|
+
}): Promise<PreparedFragment>;
|
|
189
|
+
/**
|
|
190
|
+
* Encode, sign, check and encrypt the manifest of a fully prepared batch for
|
|
191
|
+
* its registration at `version`. `sign` receives the facts of exactly this
|
|
192
|
+
* manifest and slot.
|
|
193
|
+
*/
|
|
194
|
+
export declare function prepareReplicaManifest(input: {
|
|
195
|
+
owner: string;
|
|
196
|
+
writer: string;
|
|
197
|
+
version: number;
|
|
198
|
+
batch: string;
|
|
199
|
+
sequence: number;
|
|
200
|
+
previous: Predecessor | null;
|
|
201
|
+
collectedAt: string;
|
|
202
|
+
digest: string;
|
|
203
|
+
totalBytes: number;
|
|
204
|
+
fragments: readonly ManifestEntry[];
|
|
205
|
+
sign: (facts: ReplicaBatchFacts) => Promise<unknown>;
|
|
206
|
+
encrypt: (scope: string, bytes: Uint8Array) => Promise<Uint8Array>;
|
|
207
|
+
}): Promise<PreparedManifest>;
|
|
208
|
+
/**
|
|
209
|
+
* Decode manifest plaintext. A received manifest goes through
|
|
210
|
+
* `receiveReplicaManifest`, which matches its bytes to the slot's finalized
|
|
211
|
+
* commitment first. The caller then authorizes its statement against
|
|
212
|
+
* `replicaManifestFacts(manifest, version)`; this check binds only owner and
|
|
213
|
+
* writer scope. Throws ReplicaManifestRefused and nothing else.
|
|
214
|
+
*/
|
|
215
|
+
export declare function decodeReplicaManifest(plaintext: Uint8Array, scope: string, owner: string): ReplicaManifest;
|
|
216
|
+
/** `decodeReplicaManifest` after `parseReplicaJson`. Throws ReplicaManifestRefused and nothing else. */
|
|
217
|
+
export declare function decodeParsedReplicaManifest({ encoded, value }: ParsedReplicaJson, scope: string, owner: string): ReplicaManifest;
|
|
218
|
+
/**
|
|
219
|
+
* Check a decoded fragment against the entry of its finalized manifest. The
|
|
220
|
+
* fetched bytes already hash to the entry, so a mismatch here is a writer
|
|
221
|
+
* fault, never storage damage.
|
|
222
|
+
*/
|
|
223
|
+
export declare function fragmentMatchesManifest(fragment: ReplicaFragment, manifest: ReplicaManifest, index: number): boolean;
|
|
224
|
+
export declare function fragmentReplicaPayload(input: {
|
|
225
|
+
owner: string;
|
|
226
|
+
writer: string;
|
|
227
|
+
batch: string;
|
|
228
|
+
sequence: number;
|
|
229
|
+
previous: Predecessor | null;
|
|
230
|
+
bytes: Uint8Array;
|
|
231
|
+
collectedAt: string;
|
|
232
|
+
encrypt: (scope: string, bytes: Uint8Array) => Promise<Uint8Array>;
|
|
233
|
+
maxBlobBytes?: number;
|
|
234
|
+
targetChunkBytes?: number;
|
|
235
|
+
}): Promise<PreparedFragment[]>;
|
|
236
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/replication/transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { DataFileEnvelopeSchema } from "@opendatalabs/vana-sdk/browser";
|
|
3
|
+
import { sha256, keccak256, stringToHex } from "viem";
|
|
4
|
+
import { canonicalJson } from "./envelope.js";
|
|
5
|
+
import { ReplicaFramingUnsupported } from "./outcome.js";
|
|
6
|
+
import { REPLICA_MAX_FRAGMENTS, REPLICA_MAX_BLOB_BYTES, replicaFramedBytesBound, } from "./limits.js";
|
|
7
|
+
export { REPLICA_MAX_FRAGMENTS, REPLICA_MAX_BLOB_BYTES, REPLICA_FRAGMENT_OVERHEAD_BYTES, replicaFramedBytesBound, } from "./limits.js";
|
|
8
|
+
import { replicaBatchAuthoritySchema, } from "./writer-identity.js";
|
|
9
|
+
/** Reserved across ordinary reads, grants, inventory, MCP and legacy sync. */
|
|
10
|
+
import { REPLICA_SCOPE_PREFIX } from "./namespace.js";
|
|
11
|
+
export { REPLICA_SCOPE_PREFIX, isReplicaScope } from "./namespace.js";
|
|
12
|
+
/** Nesting that no manifest or fragment reaches. */
|
|
13
|
+
export const REPLICA_MAX_JSON_DEPTH = 16;
|
|
14
|
+
/**
|
|
15
|
+
* Structural characters (`[`, `{`, `,` and `:`) of a manifest at the
|
|
16
|
+
* fragment limit, with room for its statement. A small document of tiny
|
|
17
|
+
* values allocates far more than its size, so this is bounded before parsing.
|
|
18
|
+
*/
|
|
19
|
+
export const REPLICA_MAX_JSON_TOKENS = 8 * REPLICA_MAX_FRAGMENTS + 4096;
|
|
20
|
+
const token = z.string().regex(/^[a-f0-9]{32}$/);
|
|
21
|
+
const digest = z.string().regex(/^sha256:[a-f0-9]{64}$/);
|
|
22
|
+
const integer = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
|
|
23
|
+
export const predecessorSchema = z.strictObject({ batch: token, digest });
|
|
24
|
+
export const replicaFragmentSchema = z.strictObject({
|
|
25
|
+
format: z.literal("vana-pdpp-replica-fragment"),
|
|
26
|
+
/**
|
|
27
|
+
* Version 3 is stored unregistered and is trusted only through the signed
|
|
28
|
+
* manifest that names its digest, so it carries no statement of its own.
|
|
29
|
+
* Versions 1 and 2 were registered one fragment per scope.
|
|
30
|
+
*/
|
|
31
|
+
version: z.literal(3),
|
|
32
|
+
owner: z.string().min(1),
|
|
33
|
+
writer: token,
|
|
34
|
+
batch: token,
|
|
35
|
+
sequence: integer.min(1),
|
|
36
|
+
previous: predecessorSchema.nullable(),
|
|
37
|
+
collectedAt: z.string().datetime({ offset: true }),
|
|
38
|
+
digest,
|
|
39
|
+
totalBytes: integer.min(1),
|
|
40
|
+
count: integer.min(1).max(REPLICA_MAX_FRAGMENTS),
|
|
41
|
+
index: integer,
|
|
42
|
+
offset: integer,
|
|
43
|
+
chunkDigest: digest,
|
|
44
|
+
content: z.string(),
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* One fragment's entry in its batch manifest: the sha256 of the exact
|
|
48
|
+
* encrypted object and its length. The digest is also the storage address,
|
|
49
|
+
* so a receiver checks fetched bytes against the finalized manifest before
|
|
50
|
+
* it decrypts them.
|
|
51
|
+
*/
|
|
52
|
+
export const manifestEntrySchema = z.strictObject({
|
|
53
|
+
digest,
|
|
54
|
+
bytes: integer.min(1).max(REPLICA_MAX_BLOB_BYTES),
|
|
55
|
+
});
|
|
56
|
+
/**
|
|
57
|
+
* The one registered object of a batch. Its DPv2 slot is the writer's scope at
|
|
58
|
+
* the next free version. It lists every fragment, in index order, by digest
|
|
59
|
+
* and size, and carries the batch statement signed by the writer's server
|
|
60
|
+
* key, which covers every other field and the slot. The version is a
|
|
61
|
+
* publication slot, not the batch sequence: a batch that cannot be framed
|
|
62
|
+
* takes no slot, so its successors still publish.
|
|
63
|
+
*/
|
|
64
|
+
export const replicaManifestSchema = z.strictObject({
|
|
65
|
+
format: z.literal("vana-pdpp-replica-manifest"),
|
|
66
|
+
version: z.literal(1),
|
|
67
|
+
owner: z.string().min(1),
|
|
68
|
+
writer: token,
|
|
69
|
+
batch: token,
|
|
70
|
+
sequence: integer.min(1),
|
|
71
|
+
previous: predecessorSchema.nullable(),
|
|
72
|
+
collectedAt: z.string().datetime({ offset: true }),
|
|
73
|
+
digest,
|
|
74
|
+
totalBytes: integer.min(1),
|
|
75
|
+
fragments: z.array(manifestEntrySchema).min(1).max(REPLICA_MAX_FRAGMENTS),
|
|
76
|
+
/** The batch statement signed by the writer's server key (host contract §3.3). */
|
|
77
|
+
authority: replicaBatchAuthoritySchema,
|
|
78
|
+
});
|
|
79
|
+
/** One stable scope per writer. Each batch appends one version to it. */
|
|
80
|
+
export function replicaScope(writer) {
|
|
81
|
+
token.parse(writer);
|
|
82
|
+
return `${REPLICA_SCOPE_PREFIX}.${writer}`;
|
|
83
|
+
}
|
|
84
|
+
/** The writer of a replica scope, or undefined for any other name. */
|
|
85
|
+
export function replicaWriterOf(scope) {
|
|
86
|
+
const writer = scope.slice(REPLICA_SCOPE_PREFIX.length + 1);
|
|
87
|
+
return scope === `${REPLICA_SCOPE_PREFIX}.${writer}` &&
|
|
88
|
+
token.safeParse(writer).success
|
|
89
|
+
? writer
|
|
90
|
+
: undefined;
|
|
91
|
+
}
|
|
92
|
+
/** Storage key of a content-addressed fragment. Never registered. */
|
|
93
|
+
export function replicaFragmentKey(scope, fragmentDigest) {
|
|
94
|
+
digest.parse(fragmentDigest);
|
|
95
|
+
return `${scope}/fragments/${fragmentDigest.slice("sha256:".length)}`;
|
|
96
|
+
}
|
|
97
|
+
/** Storage key of a manifest: the ordinary DPv2 `<scope>/<version>` key. */
|
|
98
|
+
export function replicaManifestKey(scope, version) {
|
|
99
|
+
integer.min(1).parse(version);
|
|
100
|
+
return `${scope}/${version}`;
|
|
101
|
+
}
|
|
102
|
+
export function replicaDigest(bytes) {
|
|
103
|
+
return `sha256:${sha256(bytes).slice(2)}`;
|
|
104
|
+
}
|
|
105
|
+
export function toBase64(bytes) {
|
|
106
|
+
let binary = "";
|
|
107
|
+
for (let i = 0; i < bytes.length; i += 8192)
|
|
108
|
+
binary += Reflect.apply(String.fromCharCode, null, bytes.subarray(i, i + 8192));
|
|
109
|
+
return btoa(binary);
|
|
110
|
+
}
|
|
111
|
+
export function fromBase64(value) {
|
|
112
|
+
if (typeof value !== "string")
|
|
113
|
+
throw new Error("noncanonical base64");
|
|
114
|
+
const binary = atob(value);
|
|
115
|
+
// atob validates the alphabet and padding placement, but accepts whitespace,
|
|
116
|
+
// omitted padding and nonzero unused bits. Reject those without re-encoding
|
|
117
|
+
// the whole decoded object into another binary string and base64 string.
|
|
118
|
+
if (value.length !== 4 * Math.ceil(binary.length / 3) ||
|
|
119
|
+
/[\t\n\f\r ]/.test(value))
|
|
120
|
+
throw new Error("noncanonical base64");
|
|
121
|
+
const remainder = binary.length % 3;
|
|
122
|
+
if (remainder) {
|
|
123
|
+
const padding = 3 - remainder;
|
|
124
|
+
const last = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".indexOf(value[value.length - padding - 1]);
|
|
125
|
+
// Two '=' leave four unused bits; one '=' leaves two unused bits.
|
|
126
|
+
if ((last & (padding === 2 ? 15 : 3)) !== 0)
|
|
127
|
+
throw new Error("noncanonical base64");
|
|
128
|
+
}
|
|
129
|
+
const bytes = new Uint8Array(binary.length);
|
|
130
|
+
for (let index = 0; index < binary.length; index++)
|
|
131
|
+
bytes[index] = binary.charCodeAt(index);
|
|
132
|
+
return bytes;
|
|
133
|
+
}
|
|
134
|
+
export function replicaMetadataHash(scope, collectedAt, sizeBytes) {
|
|
135
|
+
return keccak256(stringToHex(JSON.stringify({ scope, collectedAt, sizeBytes })));
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* A manifest that can never be valid at its slot, with the refusal of the
|
|
139
|
+
* first check it fails. The caller has already matched its bytes to the
|
|
140
|
+
* slot's finalized commitment, so the refusal is terminal.
|
|
141
|
+
*/
|
|
142
|
+
export class ReplicaManifestRefused extends Error {
|
|
143
|
+
reason;
|
|
144
|
+
constructor(reason) {
|
|
145
|
+
super(`replica manifest refused: ${reason}`);
|
|
146
|
+
this.reason = reason;
|
|
147
|
+
this.name = "ReplicaManifestRefused";
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/** Replica JSON over a bound that no writer reaches. */
|
|
151
|
+
export class ReplicaJsonRefused extends Error {
|
|
152
|
+
constructor() {
|
|
153
|
+
super("replica JSON over its depth or token bound");
|
|
154
|
+
this.name = "ReplicaJsonRefused";
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Parse replica JSON. One pass without recursion bounds nesting and
|
|
159
|
+
* structural tokens before `JSON.parse` allocates anything, so the recursive
|
|
160
|
+
* work after it (schemas, `canonicalJson`) stays inside those bounds. Throws
|
|
161
|
+
* ReplicaJsonRefused over a bound, and the parser's own error for bytes that
|
|
162
|
+
* are not UTF-8 JSON.
|
|
163
|
+
*/
|
|
164
|
+
export function parseReplicaJson(plaintext) {
|
|
165
|
+
const encoded = new TextDecoder("utf-8", { fatal: true }).decode(plaintext);
|
|
166
|
+
let depth = 0;
|
|
167
|
+
let tokens = 0;
|
|
168
|
+
let quoted = false;
|
|
169
|
+
for (let index = 0; index < encoded.length; index++) {
|
|
170
|
+
const code = encoded.charCodeAt(index);
|
|
171
|
+
if (quoted) {
|
|
172
|
+
if (code === 0x5c)
|
|
173
|
+
index++;
|
|
174
|
+
else if (code === 0x22)
|
|
175
|
+
quoted = false;
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
if (code === 0x22)
|
|
179
|
+
quoted = true;
|
|
180
|
+
else if (code === 0x5d || code === 0x7d)
|
|
181
|
+
depth--;
|
|
182
|
+
else if (code === 0x5b || code === 0x7b || code === 0x2c || code === 0x3a) {
|
|
183
|
+
if (++tokens > REPLICA_MAX_JSON_TOKENS ||
|
|
184
|
+
((code === 0x5b || code === 0x7b) && ++depth > REPLICA_MAX_JSON_DEPTH))
|
|
185
|
+
throw new ReplicaJsonRefused();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return { encoded, value: JSON.parse(encoded) };
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* The most encrypted fragment bytes a batch of `totalBytes` needs in `count`
|
|
192
|
+
* fragments: the base64 of every chunk plus a fixed overhead per fragment.
|
|
193
|
+
*/
|
|
194
|
+
/** The facts a manifest at `version` claims; its statement must sign exactly these. */
|
|
195
|
+
export function replicaManifestFacts(manifest, version) {
|
|
196
|
+
return {
|
|
197
|
+
version,
|
|
198
|
+
batch: manifest.batch,
|
|
199
|
+
sequence: manifest.sequence,
|
|
200
|
+
previous: manifest.previous,
|
|
201
|
+
collectedAt: manifest.collectedAt,
|
|
202
|
+
digest: manifest.digest,
|
|
203
|
+
totalBytes: manifest.totalBytes,
|
|
204
|
+
fragments: manifest.fragments,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
export function decodeReplicaFragment(plaintext, scope, owner) {
|
|
208
|
+
return decodeParsedReplicaFragment(parseReplicaJson(plaintext), scope, owner);
|
|
209
|
+
}
|
|
210
|
+
/** Fragment decoding after the shared receive boundary's bounded parse. */
|
|
211
|
+
export function decodeParsedReplicaFragment({ encoded, value }, scope, owner) {
|
|
212
|
+
const wrapper = DataFileEnvelopeSchema.parse(value);
|
|
213
|
+
const fragment = replicaFragmentSchema.parse(wrapper.data.fragment);
|
|
214
|
+
if (canonicalJson(wrapper) !== encoded ||
|
|
215
|
+
wrapper.scope !== scope ||
|
|
216
|
+
wrapper.collectedAt !== fragment.collectedAt ||
|
|
217
|
+
fragment.owner !== owner ||
|
|
218
|
+
scope !== replicaScope(fragment.writer) ||
|
|
219
|
+
fragment.index >= fragment.count ||
|
|
220
|
+
(fragment.sequence === 1) !== (fragment.previous === null))
|
|
221
|
+
throw new Error("invalid replica fragment binding");
|
|
222
|
+
const chunk = fromBase64(fragment.content);
|
|
223
|
+
if (!chunk.length ||
|
|
224
|
+
fragment.offset + chunk.length > fragment.totalBytes ||
|
|
225
|
+
replicaDigest(chunk) !== fragment.chunkDigest)
|
|
226
|
+
throw new Error("corrupt replica fragment");
|
|
227
|
+
return fragment;
|
|
228
|
+
}
|
|
229
|
+
function encodeFragmentPlaintext(fragment) {
|
|
230
|
+
return new TextEncoder().encode(canonicalJson({
|
|
231
|
+
version: "1.0",
|
|
232
|
+
scope: replicaScope(fragment.writer),
|
|
233
|
+
collectedAt: fragment.collectedAt,
|
|
234
|
+
data: { fragment },
|
|
235
|
+
}));
|
|
236
|
+
}
|
|
237
|
+
/** Exact framing size without allocating a base64 content string or encrypting. */
|
|
238
|
+
export function replicaFragmentPlaintextByteLength(input) {
|
|
239
|
+
const { chunkBytes, ...fields } = input;
|
|
240
|
+
return (encodeFragmentPlaintext({
|
|
241
|
+
...fields,
|
|
242
|
+
format: "vana-pdpp-replica-fragment",
|
|
243
|
+
version: 3,
|
|
244
|
+
chunkDigest: `sha256:${"0".repeat(64)}`,
|
|
245
|
+
content: "",
|
|
246
|
+
}).length +
|
|
247
|
+
4 * Math.ceil(chunkBytes / 3));
|
|
248
|
+
}
|
|
249
|
+
/** The single fragment encoder shared by buffered and streaming publishers.
|
|
250
|
+
* Freeze returned bytes before I/O: encryption is randomized. */
|
|
251
|
+
export async function prepareReplicaFragment(input) {
|
|
252
|
+
const scope = replicaScope(input.writer);
|
|
253
|
+
const fragment = replicaFragmentSchema.parse({
|
|
254
|
+
format: "vana-pdpp-replica-fragment",
|
|
255
|
+
version: 3,
|
|
256
|
+
owner: input.owner,
|
|
257
|
+
writer: input.writer,
|
|
258
|
+
batch: input.batch,
|
|
259
|
+
sequence: input.sequence,
|
|
260
|
+
previous: input.previous,
|
|
261
|
+
collectedAt: input.collectedAt,
|
|
262
|
+
digest: input.digest,
|
|
263
|
+
totalBytes: input.totalBytes,
|
|
264
|
+
count: input.count,
|
|
265
|
+
index: input.index,
|
|
266
|
+
offset: input.offset,
|
|
267
|
+
chunkDigest: replicaDigest(input.chunk),
|
|
268
|
+
content: toBase64(input.chunk),
|
|
269
|
+
});
|
|
270
|
+
const plaintext = encodeFragmentPlaintext(fragment);
|
|
271
|
+
// Validate writer/address/order grammar even for locally prepared inputs.
|
|
272
|
+
decodeReplicaFragment(plaintext, scope, input.owner);
|
|
273
|
+
const encrypted = await input.encrypt(scope, plaintext);
|
|
274
|
+
return {
|
|
275
|
+
scope,
|
|
276
|
+
index: input.index,
|
|
277
|
+
plaintext,
|
|
278
|
+
encrypted,
|
|
279
|
+
digest: replicaDigest(encrypted),
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Encode, sign, check and encrypt the manifest of a fully prepared batch for
|
|
284
|
+
* its registration at `version`. `sign` receives the facts of exactly this
|
|
285
|
+
* manifest and slot.
|
|
286
|
+
*/
|
|
287
|
+
export async function prepareReplicaManifest(input) {
|
|
288
|
+
const scope = replicaScope(input.writer);
|
|
289
|
+
const unsigned = replicaManifestSchema.omit({ authority: true }).parse({
|
|
290
|
+
format: "vana-pdpp-replica-manifest",
|
|
291
|
+
version: 1,
|
|
292
|
+
owner: input.owner,
|
|
293
|
+
writer: input.writer,
|
|
294
|
+
batch: input.batch,
|
|
295
|
+
sequence: input.sequence,
|
|
296
|
+
previous: input.previous,
|
|
297
|
+
collectedAt: input.collectedAt,
|
|
298
|
+
digest: input.digest,
|
|
299
|
+
totalBytes: input.totalBytes,
|
|
300
|
+
fragments: input.fragments.map((f) => ({
|
|
301
|
+
digest: f.digest,
|
|
302
|
+
bytes: f.bytes,
|
|
303
|
+
})),
|
|
304
|
+
});
|
|
305
|
+
const manifest = {
|
|
306
|
+
...unsigned,
|
|
307
|
+
authority: await input.sign(replicaManifestFacts(unsigned, input.version)),
|
|
308
|
+
};
|
|
309
|
+
const plaintext = new TextEncoder().encode(canonicalJson({
|
|
310
|
+
version: "1.0",
|
|
311
|
+
scope,
|
|
312
|
+
collectedAt: input.collectedAt,
|
|
313
|
+
data: { manifest },
|
|
314
|
+
}));
|
|
315
|
+
decodeReplicaManifest(plaintext, scope, input.owner);
|
|
316
|
+
const encrypted = await input.encrypt(scope, plaintext);
|
|
317
|
+
return {
|
|
318
|
+
scope,
|
|
319
|
+
version: integer.min(1).parse(input.version),
|
|
320
|
+
plaintext,
|
|
321
|
+
encrypted,
|
|
322
|
+
dataHash: keccak256(plaintext),
|
|
323
|
+
metadataHash: replicaMetadataHash(scope, input.collectedAt, encrypted.length),
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Decode manifest plaintext. A received manifest goes through
|
|
328
|
+
* `receiveReplicaManifest`, which matches its bytes to the slot's finalized
|
|
329
|
+
* commitment first. The caller then authorizes its statement against
|
|
330
|
+
* `replicaManifestFacts(manifest, version)`; this check binds only owner and
|
|
331
|
+
* writer scope. Throws ReplicaManifestRefused and nothing else.
|
|
332
|
+
*/
|
|
333
|
+
export function decodeReplicaManifest(plaintext, scope, owner) {
|
|
334
|
+
let parsed;
|
|
335
|
+
try {
|
|
336
|
+
parsed = parseReplicaJson(plaintext);
|
|
337
|
+
}
|
|
338
|
+
catch {
|
|
339
|
+
throw new ReplicaManifestRefused("manifest_invalid");
|
|
340
|
+
}
|
|
341
|
+
return decodeParsedReplicaManifest(parsed, scope, owner);
|
|
342
|
+
}
|
|
343
|
+
/** `decodeReplicaManifest` after `parseReplicaJson`. Throws ReplicaManifestRefused and nothing else. */
|
|
344
|
+
export function decodeParsedReplicaManifest({ encoded, value }, scope, owner) {
|
|
345
|
+
try {
|
|
346
|
+
const wrapper = DataFileEnvelopeSchema.safeParse(value);
|
|
347
|
+
if (!wrapper.success || canonicalJson(wrapper.data) !== encoded)
|
|
348
|
+
throw new ReplicaManifestRefused("manifest_invalid");
|
|
349
|
+
if (wrapper.data.scope !== scope)
|
|
350
|
+
throw new ReplicaManifestRefused("writer_mismatch");
|
|
351
|
+
const claimed = wrapper.data.data.manifest;
|
|
352
|
+
const parsed = replicaManifestSchema.safeParse(claimed);
|
|
353
|
+
if (!parsed.success)
|
|
354
|
+
throw new ReplicaManifestRefused(typeof claimed === "object" &&
|
|
355
|
+
claimed !== null &&
|
|
356
|
+
!replicaBatchAuthoritySchema.safeParse(claimed.authority).success
|
|
357
|
+
? "signature_invalid"
|
|
358
|
+
: "manifest_invalid");
|
|
359
|
+
const manifest = parsed.data;
|
|
360
|
+
if (manifest.owner !== owner)
|
|
361
|
+
throw new ReplicaManifestRefused("partition_mismatch");
|
|
362
|
+
if (scope !== replicaScope(manifest.writer))
|
|
363
|
+
throw new ReplicaManifestRefused("writer_mismatch");
|
|
364
|
+
if (wrapper.data.collectedAt !== manifest.collectedAt ||
|
|
365
|
+
(manifest.sequence === 1) !== (manifest.previous === null) ||
|
|
366
|
+
new Set(manifest.fragments.map((entry) => entry.digest)).size !==
|
|
367
|
+
manifest.fragments.length ||
|
|
368
|
+
manifest.fragments.length > manifest.totalBytes ||
|
|
369
|
+
manifest.fragments.reduce((sum, f) => sum + f.bytes, 0) >
|
|
370
|
+
replicaFramedBytesBound(manifest.totalBytes, manifest.fragments.length))
|
|
371
|
+
throw new ReplicaManifestRefused("manifest_invalid");
|
|
372
|
+
return manifest;
|
|
373
|
+
}
|
|
374
|
+
catch (error) {
|
|
375
|
+
// Pure checks of authentic bytes: whatever they throw is terminal.
|
|
376
|
+
if (error instanceof ReplicaManifestRefused)
|
|
377
|
+
throw error;
|
|
378
|
+
throw new ReplicaManifestRefused("manifest_invalid");
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Check a decoded fragment against the entry of its finalized manifest. The
|
|
383
|
+
* fetched bytes already hash to the entry, so a mismatch here is a writer
|
|
384
|
+
* fault, never storage damage.
|
|
385
|
+
*/
|
|
386
|
+
export function fragmentMatchesManifest(fragment, manifest, index) {
|
|
387
|
+
return (fragment.owner === manifest.owner &&
|
|
388
|
+
fragment.writer === manifest.writer &&
|
|
389
|
+
fragment.batch === manifest.batch &&
|
|
390
|
+
fragment.sequence === manifest.sequence &&
|
|
391
|
+
canonicalJson(fragment.previous) === canonicalJson(manifest.previous) &&
|
|
392
|
+
fragment.collectedAt === manifest.collectedAt &&
|
|
393
|
+
fragment.digest === manifest.digest &&
|
|
394
|
+
fragment.totalBytes === manifest.totalBytes &&
|
|
395
|
+
fragment.count === manifest.fragments.length &&
|
|
396
|
+
fragment.index === index);
|
|
397
|
+
}
|
|
398
|
+
export async function fragmentReplicaPayload(input) {
|
|
399
|
+
const cap = input.maxBlobBytes ?? REPLICA_MAX_BLOB_BYTES;
|
|
400
|
+
if (!Number.isSafeInteger(cap) ||
|
|
401
|
+
cap < 1 ||
|
|
402
|
+
cap > REPLICA_MAX_BLOB_BYTES ||
|
|
403
|
+
!input.bytes.length)
|
|
404
|
+
throw new RangeError("invalid replica size limit");
|
|
405
|
+
let chunkSize = input.targetChunkBytes ?? 4 * 1024 * 1024;
|
|
406
|
+
if (!Number.isSafeInteger(chunkSize) || chunkSize < 1)
|
|
407
|
+
throw new RangeError("invalid chunk size");
|
|
408
|
+
const digest = replicaDigest(input.bytes);
|
|
409
|
+
while (true) {
|
|
410
|
+
const count = Math.ceil(input.bytes.length / chunkSize);
|
|
411
|
+
if (count > REPLICA_MAX_FRAGMENTS)
|
|
412
|
+
throw new ReplicaFramingUnsupported(count, REPLICA_MAX_FRAGMENTS, "fragment_count");
|
|
413
|
+
const parts = [];
|
|
414
|
+
let oversized = 0;
|
|
415
|
+
for (let index = 0; index < count; index++) {
|
|
416
|
+
const offset = index * chunkSize;
|
|
417
|
+
const chunk = input.bytes.subarray(offset, offset + chunkSize);
|
|
418
|
+
const part = await prepareReplicaFragment({
|
|
419
|
+
...input,
|
|
420
|
+
digest,
|
|
421
|
+
totalBytes: input.bytes.length,
|
|
422
|
+
count,
|
|
423
|
+
index,
|
|
424
|
+
offset,
|
|
425
|
+
chunk,
|
|
426
|
+
});
|
|
427
|
+
if (part.encrypted.length > cap) {
|
|
428
|
+
oversized = part.encrypted.length;
|
|
429
|
+
break;
|
|
430
|
+
}
|
|
431
|
+
parts.push(part);
|
|
432
|
+
}
|
|
433
|
+
if (!oversized)
|
|
434
|
+
return parts;
|
|
435
|
+
if (chunkSize === 1)
|
|
436
|
+
throw new ReplicaFramingUnsupported(oversized, cap);
|
|
437
|
+
chunkSize = Math.max(1, Math.floor(chunkSize / 2));
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
//# sourceMappingURL=transport.js.map
|