@sixb/core 0.1.7 → 0.1.8
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/actions/delegated-admission.d.ts +24 -0
- package/dist/actions/delegated-admission.d.ts.map +1 -0
- package/dist/actions/descriptor.d.ts +29 -0
- package/dist/actions/descriptor.d.ts.map +1 -0
- package/dist/actions/execution.d.ts +5 -5
- package/dist/actions/execution.d.ts.map +1 -1
- package/dist/actions/index.js +36 -30
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/request.d.ts.map +1 -1
- package/dist/actions/run-authorization.d.ts +20 -0
- package/dist/actions/run-authorization.d.ts.map +1 -0
- package/dist/actions/run-dispatch.d.ts +3 -1
- package/dist/actions/run-dispatch.d.ts.map +1 -1
- package/dist/actions/worker.js +3 -3
- package/dist/actions/worker.js.map +1 -1
- package/dist/agents/adapters.d.ts +5 -122
- package/dist/agents/adapters.d.ts.map +1 -1
- package/dist/agents/authority.d.ts +1 -1
- package/dist/agents/authority.d.ts.map +1 -1
- package/dist/agents/context-resolution.d.ts.map +1 -1
- package/dist/agents/context.js +1 -1
- package/dist/agents/errors.d.ts +0 -9
- package/dist/agents/errors.d.ts.map +1 -1
- package/dist/agents/execution.d.ts.map +1 -1
- package/dist/agents/identity.d.ts +3 -0
- package/dist/agents/identity.d.ts.map +1 -0
- package/dist/agents/index.d.ts +3 -3
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +43 -43
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/message.d.ts +4 -5
- package/dist/agents/message.d.ts.map +1 -1
- package/dist/agents/model-loop.d.ts +2 -0
- package/dist/agents/model-loop.d.ts.map +1 -1
- package/dist/agents/request.d.ts.map +1 -1
- package/dist/agents/tool-definition.d.ts +0 -1
- package/dist/agents/tool-definition.d.ts.map +1 -1
- package/dist/agents/validation.d.ts +0 -4
- package/dist/agents/validation.d.ts.map +1 -1
- package/dist/ai-usage/execution.d.ts.map +1 -1
- package/dist/auth/index.js +8 -5
- package/dist/auth/index.js.map +1 -1
- package/dist/authorization/decision.d.ts +10 -2
- package/dist/authorization/decision.d.ts.map +1 -1
- package/dist/authorization/grant-kinds.d.ts +2 -1
- package/dist/authorization/grant-kinds.d.ts.map +1 -1
- package/dist/authorization/index.d.ts +1 -1
- package/dist/authorization/index.d.ts.map +1 -1
- package/dist/authorization/index.js +7 -4
- package/dist/authorization/index.js.map +1 -1
- package/dist/bootstrap/discovery.d.ts +7 -1
- package/dist/bootstrap/discovery.d.ts.map +1 -1
- package/dist/bootstrap/index.js +46 -39
- package/dist/bootstrap/index.js.map +1 -1
- package/dist/bootstrap/ontology-type-manifest.d.ts.map +1 -1
- package/dist/chunk-19jp6g9d.js +131 -0
- package/dist/chunk-19jp6g9d.js.map +11 -0
- package/dist/{chunk-x0qhkqje.js → chunk-2dw777qw.js} +50 -5
- package/dist/{chunk-x0qhkqje.js.map → chunk-2dw777qw.js.map} +4 -3
- package/dist/chunk-359jm1jw.js +147 -0
- package/dist/chunk-359jm1jw.js.map +10 -0
- package/dist/{chunk-2b5qtban.js → chunk-3xep5cjx.js} +56 -21
- package/dist/chunk-3xep5cjx.js.map +15 -0
- package/dist/{chunk-qjycjdj6.js → chunk-3z1qec12.js} +6 -8
- package/dist/{chunk-qjycjdj6.js.map → chunk-3z1qec12.js.map} +2 -2
- package/dist/{chunk-5jcdmjam.js → chunk-4jjp5k14.js} +1 -1
- package/dist/{chunk-n2arzn6e.js → chunk-4qfkag59.js} +44 -221
- package/dist/chunk-4qfkag59.js.map +20 -0
- package/dist/{chunk-rre42skh.js → chunk-4sm0aznx.js} +515 -80
- package/dist/{chunk-rre42skh.js.map → chunk-4sm0aznx.js.map} +11 -7
- package/dist/chunk-4yqmp43v.js +159 -0
- package/dist/chunk-4yqmp43v.js.map +11 -0
- package/dist/{chunk-atmkaf60.js → chunk-5e3pq99w.js} +2 -6
- package/dist/{chunk-atmkaf60.js.map → chunk-5e3pq99w.js.map} +3 -3
- package/dist/{chunk-agsvg9ar.js → chunk-5ntny1qx.js} +1 -1
- package/dist/{chunk-z2sery1b.js → chunk-9nbmsvn5.js} +60 -20
- package/dist/chunk-9nbmsvn5.js.map +11 -0
- package/dist/{chunk-e4rvtvpw.js → chunk-aa2pen2v.js} +250 -78
- package/dist/chunk-aa2pen2v.js.map +34 -0
- package/dist/{chunk-64sr682n.js → chunk-ajnan18g.js} +11 -8
- package/dist/chunk-ajnan18g.js.map +12 -0
- package/dist/{chunk-9aehf39w.js → chunk-f26bck4t.js} +4 -4
- package/dist/{chunk-7ds9620f.js → chunk-fvt9rjsa.js} +23 -7
- package/dist/chunk-fvt9rjsa.js.map +10 -0
- package/dist/{chunk-kt81c11h.js → chunk-gbejpkex.js} +5 -5
- package/dist/{chunk-kt81c11h.js.map → chunk-gbejpkex.js.map} +1 -1
- package/dist/{chunk-vjjv9mrb.js → chunk-gzasd5b6.js} +5 -5
- package/dist/{chunk-vjjv9mrb.js.map → chunk-gzasd5b6.js.map} +3 -3
- package/dist/{chunk-d63tybny.js → chunk-h0k55pc7.js} +4 -4
- package/dist/{chunk-d63tybny.js.map → chunk-h0k55pc7.js.map} +1 -1
- package/dist/chunk-h5vqbfmd.js +1537 -0
- package/dist/chunk-h5vqbfmd.js.map +19 -0
- package/dist/{chunk-3kv70xwp.js → chunk-j1sbhm7p.js} +18 -2
- package/dist/chunk-j1sbhm7p.js.map +10 -0
- package/dist/{chunk-hdz94br2.js → chunk-k522z7v6.js} +10 -5
- package/dist/chunk-k522z7v6.js.map +10 -0
- package/dist/{chunk-wjgm6jjt.js → chunk-mth82m8t.js} +128 -94
- package/dist/chunk-mth82m8t.js.map +14 -0
- package/dist/{chunk-qv38twt8.js → chunk-mwsxn98e.js} +46 -25
- package/dist/{chunk-qv38twt8.js.map → chunk-mwsxn98e.js.map} +6 -6
- package/dist/chunk-n4khvw9n.js +111 -0
- package/dist/chunk-n4khvw9n.js.map +11 -0
- package/dist/{chunk-qjzp9xyb.js → chunk-nn0tekr1.js} +6 -8
- package/dist/chunk-nn0tekr1.js.map +12 -0
- package/dist/chunk-nx7k8tpr.js +436 -0
- package/dist/chunk-nx7k8tpr.js.map +12 -0
- package/dist/{chunk-08twe8m6.js → chunk-p1rzczbt.js} +1 -1
- package/dist/{chunk-37wk412q.js → chunk-p1x242ad.js} +587 -70
- package/dist/chunk-p1x242ad.js.map +25 -0
- package/dist/{chunk-tn7xcs2n.js → chunk-pc7ys28c.js} +68 -5
- package/dist/chunk-pc7ys28c.js.map +14 -0
- package/dist/{chunk-3fqt22c4.js → chunk-q0k9nc5a.js} +280 -88
- package/dist/chunk-q0k9nc5a.js.map +14 -0
- package/dist/chunk-r8jrnexe.js +403 -0
- package/dist/chunk-r8jrnexe.js.map +10 -0
- package/dist/{chunk-gbrpsx4m.js → chunk-rafagrwr.js} +30 -2
- package/dist/chunk-rafagrwr.js.map +11 -0
- package/dist/{chunk-xdpwpkha.js → chunk-rv2hkwwa.js} +1 -1
- package/dist/{chunk-6ed5bwnd.js → chunk-sbzzr4kx.js} +1203 -691
- package/dist/{chunk-6ed5bwnd.js.map → chunk-sbzzr4kx.js.map} +15 -9
- package/dist/{chunk-d2ndstdf.js → chunk-v1xppd0y.js} +13 -11
- package/dist/{chunk-d2ndstdf.js.map → chunk-v1xppd0y.js.map} +2 -2
- package/dist/chunk-v4en4jc2.js +252 -0
- package/dist/chunk-v4en4jc2.js.map +10 -0
- package/dist/{chunk-1kamz6j0.js → chunk-w1tvjszy.js} +1 -1
- package/dist/{chunk-rp1mvzb4.js → chunk-w9tg6yyb.js} +11 -6
- package/dist/{chunk-rp1mvzb4.js.map → chunk-w9tg6yyb.js.map} +3 -3
- package/dist/{chunk-4nxeacx7.js → chunk-wdage1eb.js} +1 -1
- package/dist/{chunk-ha58tjtt.js → chunk-wtf06et8.js} +9 -5
- package/dist/{chunk-ha58tjtt.js.map → chunk-wtf06et8.js.map} +3 -3
- package/dist/{chunk-h0knpbz5.js → chunk-xajtptbw.js} +782 -211
- package/dist/chunk-xajtptbw.js.map +40 -0
- package/dist/{chunk-xc7hq65b.js → chunk-yp8ee62z.js} +49 -2
- package/dist/chunk-yp8ee62z.js.map +11 -0
- package/dist/chunk-z4ccwbkz.js +139 -0
- package/dist/chunk-z4ccwbkz.js.map +10 -0
- package/dist/datasets/builders.d.ts +11 -2
- package/dist/datasets/builders.d.ts.map +1 -1
- package/dist/datasets/changes.d.ts +14 -4
- package/dist/datasets/changes.d.ts.map +1 -1
- package/dist/datasets/execution.d.ts +15 -1
- package/dist/datasets/execution.d.ts.map +1 -1
- package/dist/datasets/index.d.ts +1 -0
- package/dist/datasets/index.d.ts.map +1 -1
- package/dist/datasets/sequence.d.ts +7 -0
- package/dist/datasets/sequence.d.ts.map +1 -0
- package/dist/datasets/types.d.ts +1 -0
- package/dist/datasets/types.d.ts.map +1 -1
- package/dist/datasets/validation.d.ts.map +1 -1
- package/dist/datasets/write.d.ts +37 -0
- package/dist/datasets/write.d.ts.map +1 -0
- package/dist/datasets/write.js +17 -0
- package/dist/datasets/write.js.map +9 -0
- package/dist/events/execution.d.ts.map +1 -1
- package/dist/events/types/datasets.d.ts +2 -6
- package/dist/events/types/datasets.d.ts.map +1 -1
- package/dist/execution/agent.d.ts.map +1 -1
- package/dist/execution/agent.js +39 -32
- package/dist/execution/agent.js.map +1 -1
- package/dist/execution/authorization.d.ts +58 -20
- package/dist/execution/authorization.d.ts.map +1 -1
- package/dist/execution/authorized-object-reader.d.ts +69 -0
- package/dist/execution/authorized-object-reader.d.ts.map +1 -0
- package/dist/execution/durable.d.ts.map +1 -1
- package/dist/execution/index.d.ts +1 -1
- package/dist/execution/index.d.ts.map +1 -1
- package/dist/execution/primitive.js +39 -32
- package/dist/execution/primitive.js.map +2 -2
- package/dist/execution/request.d.ts +11 -0
- package/dist/execution/request.d.ts.map +1 -1
- package/dist/execution/request.js +76 -40
- package/dist/execution/request.js.map +3 -3
- package/dist/execution/scopes.d.ts +16 -0
- package/dist/execution/scopes.d.ts.map +1 -1
- package/dist/execution/types.d.ts +9 -0
- package/dist/execution/types.d.ts.map +1 -1
- package/dist/http/api-routes.d.ts +2 -0
- package/dist/http/api-routes.d.ts.map +1 -1
- package/dist/http/index.js +1 -1
- package/dist/index.d.ts +8 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +92 -78
- package/dist/index.js.map +1 -1
- package/dist/lake-storage/definition-updates.d.ts.map +1 -1
- package/dist/lake-storage/errors.d.ts +5 -1
- package/dist/lake-storage/errors.d.ts.map +1 -1
- package/dist/lake-storage/in-memory.d.ts +1 -0
- package/dist/lake-storage/in-memory.d.ts.map +1 -1
- package/dist/lake-storage/index.d.ts +6 -1
- package/dist/lake-storage/index.d.ts.map +1 -1
- package/dist/lake-storage/index.js +24 -7
- package/dist/lake-storage/index.js.map +1 -1
- package/dist/lake-storage/merge-validation.d.ts.map +1 -1
- package/dist/lake-storage/merge.d.ts +13 -2
- package/dist/lake-storage/merge.d.ts.map +1 -1
- package/dist/lake-storage/source-ordering.d.ts +19 -0
- package/dist/lake-storage/source-ordering.d.ts.map +1 -0
- package/dist/lake-storage/sql-transforms.d.ts +2 -1
- package/dist/lake-storage/sql-transforms.d.ts.map +1 -1
- package/dist/lake-storage/types.d.ts +10 -5
- package/dist/lake-storage/types.d.ts.map +1 -1
- package/dist/lake-storage/version-inputs.d.ts +4 -0
- package/dist/lake-storage/version-inputs.d.ts.map +1 -0
- package/dist/materializer/index.js +25 -22
- package/dist/materializer/index.js.map +1 -1
- package/dist/objects/authorized-ontology-view.d.ts +25 -0
- package/dist/objects/authorized-ontology-view.d.ts.map +1 -0
- package/dist/objects/execution.d.ts +1 -1
- package/dist/objects/execution.d.ts.map +1 -1
- package/dist/objects/index.js +29 -26
- package/dist/objects/index.js.map +1 -1
- package/dist/objects/link/authorization.d.ts +2 -7
- package/dist/objects/link/authorization.d.ts.map +1 -1
- package/dist/objects/query/executor.d.ts +4 -2
- package/dist/objects/query/executor.d.ts.map +1 -1
- package/dist/objects/query/index.js +24 -21
- package/dist/objects/query/index.js.map +1 -1
- package/dist/objects/query/links.d.ts +22 -1
- package/dist/objects/query/links.d.ts.map +1 -1
- package/dist/objects/query/selected-read-admission.d.ts +27 -0
- package/dist/objects/query/selected-read-admission.d.ts.map +1 -0
- package/dist/objects/query/validate.d.ts +60 -2
- package/dist/objects/query/validate.d.ts.map +1 -1
- package/dist/objects/sdk/object-handle.d.ts.map +1 -1
- package/dist/objects/sdk/object-set.d.ts.map +1 -1
- package/dist/objects/sdk/runtime-query-executor.d.ts +2 -7
- package/dist/objects/sdk/runtime-query-executor.d.ts.map +1 -1
- package/dist/objects/sdk/telemetry-channel.d.ts.map +1 -1
- package/dist/objects/service/list-service.d.ts +2 -3
- package/dist/objects/service/list-service.d.ts.map +1 -1
- package/dist/objects/telemetry/history.d.ts +8 -6
- package/dist/objects/telemetry/history.d.ts.map +1 -1
- package/dist/objects/telemetry/index.d.ts +2 -2
- package/dist/objects/telemetry/index.d.ts.map +1 -1
- package/dist/objects/telemetry/workload.d.ts +11 -0
- package/dist/objects/telemetry/workload.d.ts.map +1 -0
- package/dist/ontology/index.d.ts +2 -1
- package/dist/ontology/index.d.ts.map +1 -1
- package/dist/ontology/index.js +13 -12
- package/dist/ontology/index.js.map +1 -1
- package/dist/ontology/inference/index.d.ts +2 -1
- package/dist/ontology/inference/index.d.ts.map +1 -1
- package/dist/ontology/internal.d.ts +0 -1
- package/dist/ontology/internal.d.ts.map +1 -1
- package/dist/ontology/internal.js +5 -10
- package/dist/ontology/internal.js.map +3 -3
- package/dist/ontology/json-schema.d.ts +10 -6
- package/dist/ontology/json-schema.d.ts.map +1 -1
- package/dist/ontology/link-path-selection.d.ts +35 -0
- package/dist/ontology/link-path-selection.d.ts.map +1 -0
- package/dist/ontology/refs.d.ts +2 -0
- package/dist/ontology/refs.d.ts.map +1 -1
- package/dist/ontology/tokens.d.ts +2 -1
- package/dist/ontology/tokens.d.ts.map +1 -1
- package/dist/pipelines/execution.d.ts.map +1 -1
- package/dist/pipelines/index.js +27 -24
- package/dist/pipelines/index.js.map +1 -1
- package/dist/pipelines/request.d.ts.map +1 -1
- package/dist/projections/execution.d.ts.map +1 -1
- package/dist/projections/internal.js +25 -22
- package/dist/projections/internal.js.map +1 -1
- package/dist/projections/run-dispatch.d.ts.map +1 -1
- package/dist/rules/execution.d.ts.map +1 -1
- package/dist/runtime/create.d.ts +4 -1
- package/dist/runtime/create.d.ts.map +1 -1
- package/dist/runtime/definitions.d.ts +2 -0
- package/dist/runtime/definitions.d.ts.map +1 -1
- package/dist/runtime/host.d.ts +2 -0
- package/dist/runtime/host.d.ts.map +1 -1
- package/dist/runtime/internal.d.ts +1 -0
- package/dist/runtime/internal.d.ts.map +1 -1
- package/dist/runtime/resolve-definitions.d.ts +2 -0
- package/dist/runtime/resolve-definitions.d.ts.map +1 -1
- package/dist/runtime/sixb.d.ts +4 -0
- package/dist/runtime/sixb.d.ts.map +1 -1
- package/dist/runtime/types.d.ts +3 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/schedules/execution.d.ts +2 -1
- package/dist/schedules/execution.d.ts.map +1 -1
- package/dist/security/every.d.ts +4 -1
- package/dist/security/every.d.ts.map +1 -1
- package/dist/security/grants.d.ts +7 -2
- package/dist/security/grants.d.ts.map +1 -1
- package/dist/security/index.d.ts +1 -1
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/registry.d.ts +1 -0
- package/dist/security/registry.d.ts.map +1 -1
- package/dist/security/types.d.ts +7 -1
- package/dist/security/types.d.ts.map +1 -1
- package/dist/security/validation.d.ts +2 -0
- package/dist/security/validation.d.ts.map +1 -1
- package/dist/shares/access-plan.d.ts +22 -0
- package/dist/shares/access-plan.d.ts.map +1 -0
- package/dist/shares/builders.d.ts +14 -0
- package/dist/shares/builders.d.ts.map +1 -0
- package/dist/shares/compiler.d.ts +14 -0
- package/dist/shares/compiler.d.ts.map +1 -0
- package/dist/shares/errors.d.ts +4 -0
- package/dist/shares/errors.d.ts.map +1 -0
- package/dist/shares/execution.d.ts +57 -0
- package/dist/shares/execution.d.ts.map +1 -0
- package/dist/shares/index.d.ts +10 -0
- package/dist/shares/index.d.ts.map +1 -0
- package/dist/shares/internal.d.ts +3 -0
- package/dist/shares/internal.d.ts.map +1 -0
- package/dist/shares/internal.js +239 -0
- package/dist/shares/internal.js.map +10 -0
- package/dist/shares/intersection.d.ts +9 -0
- package/dist/shares/intersection.d.ts.map +1 -0
- package/dist/shares/session-protocol.d.ts +41 -0
- package/dist/shares/session-protocol.d.ts.map +1 -0
- package/dist/shares/types.d.ts +51 -0
- package/dist/shares/types.d.ts.map +1 -0
- package/dist/shares/validation.d.ts +11 -0
- package/dist/shares/validation.d.ts.map +1 -0
- package/dist/storage/action-runs/provider.js +2 -2
- package/dist/storage/agents/provider.js +2 -2
- package/dist/storage/executions/in-memory.d.ts +3 -0
- package/dist/storage/executions/in-memory.d.ts.map +1 -1
- package/dist/storage/executions/provider.d.ts +4 -1
- package/dist/storage/executions/provider.d.ts.map +1 -1
- package/dist/storage/executions/provider.js +23 -3
- package/dist/storage/executions/provider.js.map +3 -3
- package/dist/storage/executions/run-link.d.ts +7 -0
- package/dist/storage/executions/run-link.d.ts.map +1 -1
- package/dist/storage/executions/validation.d.ts +6 -0
- package/dist/storage/executions/validation.d.ts.map +1 -1
- package/dist/storage/in-memory/index.d.ts +8 -0
- package/dist/storage/in-memory/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +8 -2
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +65 -36
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/objects/execution-limits.d.ts +25 -0
- package/dist/storage/objects/execution-limits.d.ts.map +1 -0
- package/dist/storage/objects/guard.d.ts +16 -0
- package/dist/storage/objects/guard.d.ts.map +1 -0
- package/dist/storage/objects/in-memory/index.d.ts +3 -0
- package/dist/storage/objects/in-memory/index.d.ts.map +1 -0
- package/dist/storage/objects/in-memory/keys.d.ts +10 -0
- package/dist/storage/objects/in-memory/keys.d.ts.map +1 -0
- package/dist/storage/objects/in-memory/query.d.ts +31 -0
- package/dist/storage/objects/in-memory/query.d.ts.map +1 -0
- package/dist/storage/objects/in-memory/read-scope.d.ts +18 -0
- package/dist/storage/objects/in-memory/read-scope.d.ts.map +1 -0
- package/dist/storage/objects/in-memory/read-source.d.ts +10 -0
- package/dist/storage/objects/in-memory/read-source.d.ts.map +1 -0
- package/dist/storage/objects/in-memory/selected-reader.d.ts +9 -0
- package/dist/storage/objects/in-memory/selected-reader.d.ts.map +1 -0
- package/dist/storage/objects/{in-memory.d.ts → in-memory/storage.d.ts} +13 -10
- package/dist/storage/objects/in-memory/storage.d.ts.map +1 -0
- package/dist/storage/objects/index.d.ts +4 -1
- package/dist/storage/objects/index.d.ts.map +1 -1
- package/dist/storage/objects/keys.d.ts +1 -1
- package/dist/storage/objects/keys.d.ts.map +1 -1
- package/dist/storage/objects/read-scope.d.ts +25 -0
- package/dist/storage/objects/read-scope.d.ts.map +1 -0
- package/dist/storage/objects/types.d.ts +114 -22
- package/dist/storage/objects/types.d.ts.map +1 -1
- package/dist/storage/operation-scope.d.ts +3 -0
- package/dist/storage/operation-scope.d.ts.map +1 -1
- package/dist/storage/operation-scope.js +4 -2
- package/dist/storage/operation-scope.js.map +1 -1
- package/dist/storage/pipeline-runs/provider.js +2 -2
- package/dist/storage/projection-runs/provider.js +2 -2
- package/dist/storage/share-grants/errors.d.ts +8 -0
- package/dist/storage/share-grants/errors.d.ts.map +1 -0
- package/dist/storage/share-grants/in-memory.d.ts +11 -0
- package/dist/storage/share-grants/in-memory.d.ts.map +1 -0
- package/dist/storage/share-grants/index.d.ts +5 -0
- package/dist/storage/share-grants/index.d.ts.map +1 -0
- package/dist/storage/share-grants/provider.d.ts +4 -0
- package/dist/storage/share-grants/provider.d.ts.map +1 -0
- package/dist/storage/share-grants/provider.js +24 -0
- package/dist/storage/share-grants/provider.js.map +9 -0
- package/dist/storage/share-grants/record.d.ts +11 -0
- package/dist/storage/share-grants/record.d.ts.map +1 -0
- package/dist/storage/share-grants/types.d.ts +97 -0
- package/dist/storage/share-grants/types.d.ts.map +1 -0
- package/dist/storage/share-sessions/errors.d.ts +8 -0
- package/dist/storage/share-sessions/errors.d.ts.map +1 -0
- package/dist/storage/share-sessions/in-memory.d.ts +14 -0
- package/dist/storage/share-sessions/in-memory.d.ts.map +1 -0
- package/dist/storage/share-sessions/index.d.ts +5 -0
- package/dist/storage/share-sessions/index.d.ts.map +1 -0
- package/dist/storage/share-sessions/provider.d.ts +3 -0
- package/dist/storage/share-sessions/provider.d.ts.map +1 -0
- package/dist/storage/share-sessions/provider.js +20 -0
- package/dist/storage/share-sessions/provider.js.map +9 -0
- package/dist/storage/share-sessions/record.d.ts +8 -0
- package/dist/storage/share-sessions/record.d.ts.map +1 -0
- package/dist/storage/share-sessions/types.d.ts +50 -0
- package/dist/storage/share-sessions/types.d.ts.map +1 -0
- package/dist/storage/sync-runs/provider.js +2 -2
- package/dist/storage/transaction.d.ts +2 -1
- package/dist/storage/transaction.d.ts.map +1 -1
- package/dist/storage/types.d.ts +8 -0
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/storage/webhook-runs/provider.js +2 -2
- package/dist/storage/workflow-runs/provider.js +10 -7
- package/dist/storage/workflow-runs/provider.js.map +1 -1
- package/dist/syncs/execution.d.ts.map +1 -1
- package/dist/syncs/index.js +27 -24
- package/dist/syncs/index.js.map +1 -1
- package/dist/syncs/request.d.ts.map +1 -1
- package/dist/testing/dataset-sequence-contract.d.ts +4 -0
- package/dist/testing/dataset-sequence-contract.d.ts.map +1 -0
- package/dist/testing/effective-storage-contract.d.ts.map +1 -1
- package/dist/testing/execution-storage-contract.d.ts +4 -0
- package/dist/testing/execution-storage-contract.d.ts.map +1 -1
- package/dist/testing/index.d.ts +3 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +2555 -908
- package/dist/testing/index.js.map +11 -7
- package/dist/testing/lake-merge-storage-contract.d.ts +1 -0
- package/dist/testing/lake-merge-storage-contract.d.ts.map +1 -1
- package/dist/testing/lake-storage-contract.d.ts.map +1 -1
- package/dist/testing/object-read-scope-contract.d.ts +22 -0
- package/dist/testing/object-read-scope-contract.d.ts.map +1 -0
- package/dist/testing/share-grant-storage-contract.d.ts +10 -0
- package/dist/testing/share-grant-storage-contract.d.ts.map +1 -0
- package/dist/testing/share-session-storage-contract.d.ts +9 -0
- package/dist/testing/share-session-storage-contract.d.ts.map +1 -0
- package/dist/webhooks/internal.js +24 -21
- package/dist/webhooks/internal.js.map +2 -2
- package/dist/workflows/execution.d.ts.map +1 -1
- package/dist/workflows/index.js +42 -35
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/request.d.ts.map +1 -1
- package/package.json +25 -1
- package/src/actions/delegated-admission.ts +72 -0
- package/src/actions/descriptor.ts +58 -0
- package/src/actions/execution.ts +99 -24
- package/src/actions/request.ts +136 -19
- package/src/actions/run-authorization.ts +53 -0
- package/src/actions/run-dispatch.ts +8 -1
- package/src/agents/adapters.ts +30 -420
- package/src/agents/authority.ts +3 -4
- package/src/agents/context-resolution.ts +1 -4
- package/src/agents/errors.ts +0 -10
- package/src/agents/execution.ts +13 -5
- package/src/agents/identity.ts +4 -0
- package/src/agents/index.ts +1 -20
- package/src/agents/message.ts +4 -5
- package/src/agents/model-loop.ts +54 -6
- package/src/agents/request.ts +16 -3
- package/src/agents/tool-definition.ts +0 -19
- package/src/agents/validation.ts +6 -65
- package/src/ai-usage/execution.ts +4 -11
- package/src/authorization/decision.ts +29 -14
- package/src/authorization/grant-kinds.ts +10 -0
- package/src/authorization/index.ts +1 -0
- package/src/bootstrap/discovery.ts +3 -0
- package/src/bootstrap/ontology-type-manifest.ts +12 -6
- package/src/datasets/builders.ts +23 -2
- package/src/datasets/changes.ts +16 -4
- package/src/datasets/execution.ts +76 -5
- package/src/datasets/index.ts +1 -0
- package/src/datasets/sequence.ts +77 -0
- package/src/datasets/types.ts +1 -0
- package/src/datasets/validation.ts +26 -0
- package/src/datasets/write.ts +240 -0
- package/src/events/execution.ts +57 -7
- package/src/events/types/datasets.ts +2 -6
- package/src/execution/agent.ts +1 -4
- package/src/execution/authorization.ts +470 -90
- package/src/execution/authorized-object-reader.ts +695 -0
- package/src/execution/durable.ts +10 -2
- package/src/execution/index.ts +1 -0
- package/src/execution/request.ts +63 -13
- package/src/execution/scopes.ts +36 -6
- package/src/execution/types.ts +8 -0
- package/src/http/api-routes.ts +45 -0
- package/src/index.ts +36 -15
- package/src/lake-storage/definition-updates.ts +9 -0
- package/src/lake-storage/errors.ts +6 -1
- package/src/lake-storage/in-memory.ts +53 -17
- package/src/lake-storage/index.ts +10 -1
- package/src/lake-storage/merge-validation.ts +12 -2
- package/src/lake-storage/merge.ts +40 -2
- package/src/lake-storage/source-ordering.ts +95 -0
- package/src/lake-storage/sql-transforms.ts +2 -1
- package/src/lake-storage/types.ts +10 -5
- package/src/lake-storage/version-inputs.ts +14 -0
- package/src/objects/authorized-ontology-view.ts +512 -0
- package/src/objects/execution.ts +98 -143
- package/src/objects/link/authorization.ts +3 -2
- package/src/objects/query/executor.ts +45 -34
- package/src/objects/query/links.ts +84 -25
- package/src/objects/query/selected-read-admission.ts +310 -0
- package/src/objects/query/validate.ts +353 -36
- package/src/objects/sdk/object-handle.ts +2 -8
- package/src/objects/sdk/object-set.ts +10 -11
- package/src/objects/sdk/runtime-query-executor.ts +8 -28
- package/src/objects/sdk/telemetry-channel.ts +11 -7
- package/src/objects/service/list-service.ts +15 -29
- package/src/objects/telemetry/history.ts +297 -17
- package/src/objects/telemetry/index.ts +2 -2
- package/src/objects/telemetry/workload.ts +79 -0
- package/src/ontology/index.ts +7 -1
- package/src/ontology/inference/index.ts +4 -1
- package/src/ontology/internal.ts +0 -1
- package/src/ontology/json-schema.ts +13 -12
- package/src/ontology/link-path-selection.ts +193 -0
- package/src/ontology/refs.ts +19 -0
- package/src/ontology/tokens.ts +15 -8
- package/src/pipelines/execution.ts +30 -7
- package/src/pipelines/request.ts +5 -0
- package/src/projections/execution.ts +72 -11
- package/src/projections/run-dispatch.ts +6 -12
- package/src/rules/execution.ts +20 -8
- package/src/runtime/create.ts +5 -1
- package/src/runtime/definitions.ts +2 -0
- package/src/runtime/host.ts +25 -6
- package/src/runtime/internal.ts +1 -0
- package/src/runtime/resolve-definitions.ts +9 -0
- package/src/runtime/sixb.ts +23 -2
- package/src/runtime/types.ts +3 -0
- package/src/schedules/execution.ts +24 -2
- package/src/security/every.ts +4 -0
- package/src/security/grants.ts +45 -3
- package/src/security/index.ts +1 -0
- package/src/security/registry.ts +3 -0
- package/src/security/types.ts +8 -0
- package/src/security/validation.ts +3 -0
- package/src/shares/access-plan.ts +225 -0
- package/src/shares/builders.ts +381 -0
- package/src/shares/compiler.ts +359 -0
- package/src/shares/errors.ts +3 -0
- package/src/shares/execution.ts +394 -0
- package/src/shares/index.ts +28 -0
- package/src/shares/internal.ts +9 -0
- package/src/shares/intersection.ts +178 -0
- package/src/shares/session-protocol.ts +258 -0
- package/src/shares/types.ts +76 -0
- package/src/shares/validation.ts +40 -0
- package/src/storage/executions/in-memory.ts +9 -1
- package/src/storage/executions/provider.ts +30 -1
- package/src/storage/executions/run-link.ts +29 -0
- package/src/storage/executions/validation.ts +46 -1
- package/src/storage/in-memory/index.ts +21 -2
- package/src/storage/index.ts +51 -0
- package/src/storage/objects/execution-limits.ts +283 -0
- package/src/storage/objects/guard.ts +55 -0
- package/src/storage/objects/in-memory/index.ts +2 -0
- package/src/storage/objects/in-memory/keys.ts +46 -0
- package/src/storage/objects/in-memory/query.ts +754 -0
- package/src/storage/objects/in-memory/read-scope.ts +211 -0
- package/src/storage/objects/in-memory/read-source.ts +10 -0
- package/src/storage/objects/in-memory/selected-reader.ts +252 -0
- package/src/storage/objects/in-memory/storage.ts +589 -0
- package/src/storage/objects/index.ts +21 -0
- package/src/storage/objects/keys.ts +1 -1
- package/src/storage/objects/read-scope.ts +672 -0
- package/src/storage/objects/types.ts +123 -19
- package/src/storage/operation-scope.ts +16 -0
- package/src/storage/share-grants/errors.ts +14 -0
- package/src/storage/share-grants/in-memory.ts +107 -0
- package/src/storage/share-grants/index.ts +14 -0
- package/src/storage/share-grants/provider.ts +11 -0
- package/src/storage/share-grants/record.ts +347 -0
- package/src/storage/share-grants/types.ts +112 -0
- package/src/storage/share-sessions/errors.ts +14 -0
- package/src/storage/share-sessions/in-memory.ts +105 -0
- package/src/storage/share-sessions/index.ts +11 -0
- package/src/storage/share-sessions/provider.ts +9 -0
- package/src/storage/share-sessions/record.ts +176 -0
- package/src/storage/share-sessions/types.ts +57 -0
- package/src/storage/transaction.ts +14 -2
- package/src/storage/types.ts +27 -0
- package/src/syncs/execution.ts +25 -5
- package/src/syncs/request.ts +5 -0
- package/src/testing/dataset-sequence-contract.ts +373 -0
- package/src/testing/effective-storage-contract.ts +34 -0
- package/src/testing/execution-storage-contract.ts +79 -0
- package/src/testing/index.ts +16 -0
- package/src/testing/lake-merge-storage-contract.ts +3 -0
- package/src/testing/lake-storage-contract.ts +58 -0
- package/src/testing/object-read-scope-contract.ts +939 -0
- package/src/testing/share-grant-storage-contract.ts +325 -0
- package/src/testing/share-session-storage-contract.ts +235 -0
- package/src/workflows/execution.ts +53 -14
- package/src/workflows/request.ts +5 -0
- package/dist/chunk-2b5qtban.js.map +0 -14
- package/dist/chunk-37wk412q.js.map +0 -23
- package/dist/chunk-3fqt22c4.js.map +0 -14
- package/dist/chunk-3kv70xwp.js.map +0 -10
- package/dist/chunk-64sr682n.js.map +0 -12
- package/dist/chunk-7ds9620f.js.map +0 -10
- package/dist/chunk-dqn23610.js +0 -72
- package/dist/chunk-dqn23610.js.map +0 -11
- package/dist/chunk-e4rvtvpw.js.map +0 -34
- package/dist/chunk-gbrpsx4m.js.map +0 -11
- package/dist/chunk-h0knpbz5.js.map +0 -38
- package/dist/chunk-hdz94br2.js.map +0 -10
- package/dist/chunk-n2arzn6e.js.map +0 -20
- package/dist/chunk-qjzp9xyb.js.map +0 -12
- package/dist/chunk-tn7xcs2n.js.map +0 -13
- package/dist/chunk-wjgm6jjt.js.map +0 -13
- package/dist/chunk-xc7hq65b.js.map +0 -10
- package/dist/chunk-y35ma3mj.js +0 -551
- package/dist/chunk-y35ma3mj.js.map +0 -15
- package/dist/chunk-z2sery1b.js.map +0 -11
- package/dist/storage/objects/in-memory.d.ts.map +0 -1
- package/src/storage/objects/in-memory.ts +0 -1241
- /package/dist/{chunk-5jcdmjam.js.map → chunk-4jjp5k14.js.map} +0 -0
- /package/dist/{chunk-agsvg9ar.js.map → chunk-5ntny1qx.js.map} +0 -0
- /package/dist/{chunk-9aehf39w.js.map → chunk-f26bck4t.js.map} +0 -0
- /package/dist/{chunk-08twe8m6.js.map → chunk-p1rzczbt.js.map} +0 -0
- /package/dist/{chunk-xdpwpkha.js.map → chunk-rv2hkwwa.js.map} +0 -0
- /package/dist/{chunk-1kamz6j0.js.map → chunk-w1tvjszy.js.map} +0 -0
- /package/dist/{chunk-4nxeacx7.js.map → chunk-wdage1eb.js.map} +0 -0
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test"
|
|
2
|
+
import { InMemoryBlobStorage } from "../blob-storage"
|
|
3
|
+
import { InMemoryBroker } from "../broker"
|
|
4
|
+
import { change, col, type DatasetDefinition, defineDataset, type MergeChange } from "../datasets"
|
|
5
|
+
import { writeDataset } from "../datasets/write"
|
|
6
|
+
import type { DatasetMergeCommitResult, DatasetRow, LakeStorage } from "../lake-storage"
|
|
7
|
+
import { InMemoryQueues } from "../queues"
|
|
8
|
+
import { SixbHost } from "../runtime/host"
|
|
9
|
+
import { InMemoryStorage } from "../storage"
|
|
10
|
+
import { createTestSixb } from "./execution"
|
|
11
|
+
import type { LakeMergeStorageContractSuiteOptions } from "./lake-merge-storage-contract"
|
|
12
|
+
|
|
13
|
+
const dataset = defineDataset("contract.source_order", {
|
|
14
|
+
schema: [
|
|
15
|
+
col("id", "string"),
|
|
16
|
+
col("revision", "int64"),
|
|
17
|
+
col("name", "string"),
|
|
18
|
+
col("details", "json", { nullable: true }),
|
|
19
|
+
],
|
|
20
|
+
primaryKey: "id",
|
|
21
|
+
sequenceBy: "revision",
|
|
22
|
+
})
|
|
23
|
+
const upsert = (revision: string | number, name = "Sam", id = "42") =>
|
|
24
|
+
change.upsert({ id, revision, name })
|
|
25
|
+
|
|
26
|
+
async function merge(
|
|
27
|
+
storage: LakeStorage,
|
|
28
|
+
changes: readonly MergeChange<DatasetRow, DatasetRow>[],
|
|
29
|
+
definition: DatasetDefinition = dataset
|
|
30
|
+
) {
|
|
31
|
+
const session = await storage.beginMerge({ dataset: definition })
|
|
32
|
+
try {
|
|
33
|
+
await session.writeChanges(changes)
|
|
34
|
+
return await session.commit()
|
|
35
|
+
} catch (error) {
|
|
36
|
+
await session.abort()
|
|
37
|
+
throw error
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function rows(storage: LakeStorage, definition: DatasetDefinition = dataset) {
|
|
42
|
+
const result: DatasetRow[] = []
|
|
43
|
+
for await (const row of storage.readRows({ datasetId: definition.id })) result.push(row)
|
|
44
|
+
return result
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function runDatasetSequenceContract<TStorage extends LakeStorage>(
|
|
48
|
+
options: LakeMergeStorageContractSuiteOptions<TStorage>
|
|
49
|
+
): void {
|
|
50
|
+
const withStorage = async (run: (storage: TStorage) => Promise<void>) => {
|
|
51
|
+
const storage = await options.createStorage()
|
|
52
|
+
try {
|
|
53
|
+
await storage.createDataset(dataset)
|
|
54
|
+
await run(storage)
|
|
55
|
+
} finally {
|
|
56
|
+
await options.teardown?.(storage)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
describe("source ordering", () => {
|
|
61
|
+
test("initializes empty snapshots and preserves versions across retries and reopen", async () => {
|
|
62
|
+
// Regression proof: remove createInitialVersion from the writer or provider; the first
|
|
63
|
+
// snapshot has no version. Ignore the rebased head and the concurrent-write assertion fails.
|
|
64
|
+
let storage = await options.createStorage()
|
|
65
|
+
const snapshot = () =>
|
|
66
|
+
writeDataset({
|
|
67
|
+
lakeStorage: storage,
|
|
68
|
+
blobStorage: new InMemoryBlobStorage(),
|
|
69
|
+
dataset,
|
|
70
|
+
mode: "snapshot",
|
|
71
|
+
signal: new AbortController().signal,
|
|
72
|
+
readValues: async () => [],
|
|
73
|
+
})
|
|
74
|
+
try {
|
|
75
|
+
await storage.createDataset(dataset)
|
|
76
|
+
expect(await merge(storage, [])).toEqual({ outcome: "unchanged", version: null })
|
|
77
|
+
const initialized = await Promise.all([snapshot(), snapshot()])
|
|
78
|
+
expect(initialized.map((result) => result.outcome).sort()).toEqual(["created", "unchanged"])
|
|
79
|
+
const initial = initialized.find((result) => result.outcome === "created")!
|
|
80
|
+
expect(initialized[0]?.version).toEqual(initialized[1]?.version)
|
|
81
|
+
expect(initial).toMatchObject({
|
|
82
|
+
outcome: "created",
|
|
83
|
+
version: { rowCount: 0, mode: "merge" },
|
|
84
|
+
})
|
|
85
|
+
expect(await rows(storage)).toEqual([])
|
|
86
|
+
if (options.reopen) storage = await options.reopen(storage)
|
|
87
|
+
expect(await storage.getLatestVersion(dataset.id)).toEqual(initial.version)
|
|
88
|
+
expect(await snapshot()).toMatchObject({ outcome: "unchanged", version: initial.version })
|
|
89
|
+
|
|
90
|
+
const concurrent = defineDataset("contract.empty_race", {
|
|
91
|
+
schema: dataset.schema.columns,
|
|
92
|
+
primaryKey: "id",
|
|
93
|
+
sequenceBy: "revision",
|
|
94
|
+
})
|
|
95
|
+
let committed: DatasetMergeCommitResult | undefined
|
|
96
|
+
const rebased = await writeDataset({
|
|
97
|
+
lakeStorage: storage,
|
|
98
|
+
blobStorage: new InMemoryBlobStorage(),
|
|
99
|
+
dataset: concurrent,
|
|
100
|
+
mode: "snapshot",
|
|
101
|
+
signal: new AbortController().signal,
|
|
102
|
+
readValues: async () => {
|
|
103
|
+
committed = await merge(storage, [upsert(8)], concurrent)
|
|
104
|
+
return []
|
|
105
|
+
},
|
|
106
|
+
})
|
|
107
|
+
expect(rebased).toMatchObject({ outcome: "unchanged", version: committed?.version })
|
|
108
|
+
expect(await rows(storage, concurrent)).toHaveLength(1)
|
|
109
|
+
} finally {
|
|
110
|
+
await options.teardown?.(storage)
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
test("rejects lossy timestamps outside the ordering column before changing source state", () =>
|
|
115
|
+
withStorage(async (storage) => {
|
|
116
|
+
// Regression proof: remove the sequenced timestamp check in getColumnValidationError;
|
|
117
|
+
// submillisecond content is accepted and its distinct values collapse to one digest.
|
|
118
|
+
const timestamps = defineDataset("contract.content_timestamps", {
|
|
119
|
+
schema: [...dataset.schema.columns, col("at", "timestamp", { nullable: true })],
|
|
120
|
+
primaryKey: "id",
|
|
121
|
+
sequenceBy: "revision",
|
|
122
|
+
})
|
|
123
|
+
await storage.createDataset(timestamps)
|
|
124
|
+
const row = (at: unknown, id = "42") => change.upsert({ id, revision: 1, name: "Sam", at })
|
|
125
|
+
const initial = await merge(storage, [row("2026-09-09T10:00:00.123Z")], timestamps)
|
|
126
|
+
for (const at of [
|
|
127
|
+
"2026-09-09T10:00:00.123001Z",
|
|
128
|
+
"2026-09-09T10:00:00.123999Z",
|
|
129
|
+
"2026-09-09T10:00:00",
|
|
130
|
+
"2026-02-30T00:00:00Z",
|
|
131
|
+
]) {
|
|
132
|
+
await expect(merge(storage, [row(at, "new")], timestamps)).rejects.toThrow("column 'at'")
|
|
133
|
+
expect(await storage.getLatestVersion(timestamps.id)).toEqual(initial.version)
|
|
134
|
+
}
|
|
135
|
+
for (const at of ["2026-09-09T12:00:00.123+02:00", new Date("2026-09-09T10:00:00.123Z")]) {
|
|
136
|
+
expect((await merge(storage, [row(at)], timestamps)).outcome).toBe("unchanged")
|
|
137
|
+
}
|
|
138
|
+
await expect(merge(storage, [row("2026-09-09T10:00:00.124Z")], timestamps)).rejects.toThrow(
|
|
139
|
+
"conflicting content"
|
|
140
|
+
)
|
|
141
|
+
await merge(storage, [row(null, "nullable")], timestamps)
|
|
142
|
+
expect((await merge(storage, [row(undefined, "nullable")], timestamps)).outcome).toBe(
|
|
143
|
+
"unchanged"
|
|
144
|
+
)
|
|
145
|
+
}))
|
|
146
|
+
|
|
147
|
+
test("ingests through the bound SDK and preserves execution provenance", async () => {
|
|
148
|
+
// Regression proof: remove ingest from DuckLake's producer parser; reopen loses provenance.
|
|
149
|
+
let storage = await options.createStorage()
|
|
150
|
+
const broker = new InMemoryBroker()
|
|
151
|
+
try {
|
|
152
|
+
const host = new SixbHost({
|
|
153
|
+
id: "ingest-contract",
|
|
154
|
+
ontology: [],
|
|
155
|
+
datasets: [dataset],
|
|
156
|
+
lakeStorage: storage,
|
|
157
|
+
broker,
|
|
158
|
+
storage: new InMemoryStorage(),
|
|
159
|
+
queues: new InMemoryQueues(),
|
|
160
|
+
blobStorage: new InMemoryBlobStorage(),
|
|
161
|
+
})
|
|
162
|
+
const sixb = createTestSixb(host)
|
|
163
|
+
const result = await sixb.datasets.ingest(dataset, { changes: [upsert(8)] })
|
|
164
|
+
expect(result.outcome).toBe("created")
|
|
165
|
+
if (options.reopen) storage = await options.reopen(storage)
|
|
166
|
+
expect((await storage.getLatestVersion(dataset.id))?.producer).toEqual({
|
|
167
|
+
kind: "ingest",
|
|
168
|
+
id: sixb.execution.id,
|
|
169
|
+
})
|
|
170
|
+
expect((await rows(storage)).map((row) => row.name)).toEqual(["Sam"])
|
|
171
|
+
expect(await host.events.read()).toMatchObject([
|
|
172
|
+
{ type: "dataset.version.committed", payload: { versionId: result.version?.versionId } },
|
|
173
|
+
])
|
|
174
|
+
} finally {
|
|
175
|
+
await options.teardown?.(storage)
|
|
176
|
+
}
|
|
177
|
+
})
|
|
178
|
+
test("rebases retained changes while preserving explicit version guards", () =>
|
|
179
|
+
withStorage(async (storage) => {
|
|
180
|
+
// Regression proof: disable retryOnConflict in retryDatasetMergeCommit; the second commit fails.
|
|
181
|
+
const first = await storage.beginMerge({ dataset })
|
|
182
|
+
const second = await storage.beginMerge({ dataset })
|
|
183
|
+
await first.writeChanges([upsert(8)])
|
|
184
|
+
await second.writeChanges([upsert(7, "stale"), upsert(1, "other", "other")])
|
|
185
|
+
const initial = await first.commit({ retryOnConflict: true })
|
|
186
|
+
await second.commit({ retryOnConflict: true })
|
|
187
|
+
expect((await rows(storage)).map((row) => row.name).sort()).toEqual(["Sam", "other"])
|
|
188
|
+
const guarded = await storage.beginMerge({
|
|
189
|
+
dataset,
|
|
190
|
+
expectedLatestVersionId: (await storage.getLatestVersion(dataset.id))?.versionId,
|
|
191
|
+
})
|
|
192
|
+
await guarded.writeChanges([upsert(10)])
|
|
193
|
+
await merge(storage, [change.delete({ id: "42" }, { sequence: 9 })])
|
|
194
|
+
await expect(guarded.commit({ retryOnConflict: true })).rejects.toThrow("Optimistic")
|
|
195
|
+
await guarded.abort()
|
|
196
|
+
const staleDelete = await storage.beginMerge({ dataset })
|
|
197
|
+
await staleDelete.writeChanges([change.delete({ id: "42" }, { sequence: 9 })])
|
|
198
|
+
await merge(storage, [upsert(10)])
|
|
199
|
+
expect((await staleDelete.commit({ retryOnConflict: true })).outcome).toBe("unchanged")
|
|
200
|
+
expect((await storage.getLatestVersion(dataset.id))?.versionId).not.toBe(
|
|
201
|
+
initial.version?.versionId
|
|
202
|
+
)
|
|
203
|
+
}))
|
|
204
|
+
// Regression proof: bypass reconcileDatasetSequences at the provider commit boundary.
|
|
205
|
+
// The stale-write, conflict, and deletion assertions below must then fail.
|
|
206
|
+
test("orders repeated keys exactly and conflicts atomically", () =>
|
|
207
|
+
withStorage(async (storage) => {
|
|
208
|
+
const first = await merge(storage, [upsert("9007199254740993")])
|
|
209
|
+
expect((await merge(storage, [upsert("9007199254740992", "stale")])).outcome).toBe(
|
|
210
|
+
"unchanged"
|
|
211
|
+
)
|
|
212
|
+
expect((await merge(storage, [upsert("09007199254740993")])).outcome).toBe("unchanged")
|
|
213
|
+
await expect(
|
|
214
|
+
merge(storage, [upsert("1", "other", "other"), upsert("9007199254740993", "conflict")])
|
|
215
|
+
).rejects.toThrow("conflicting content")
|
|
216
|
+
expect((await storage.getLatestVersion(dataset.id))?.versionId).toBe(
|
|
217
|
+
first.version?.versionId
|
|
218
|
+
)
|
|
219
|
+
expect(await rows(storage)).toHaveLength(1)
|
|
220
|
+
await merge(storage, [
|
|
221
|
+
upsert("9007199254740995", "newest"),
|
|
222
|
+
upsert("9007199254740994", "stale"),
|
|
223
|
+
])
|
|
224
|
+
expect((await rows(storage))[0]?.name).toBe("newest")
|
|
225
|
+
await expect(
|
|
226
|
+
merge(storage, [upsert("9007199254740996", "a"), upsert("9007199254740996", "b")])
|
|
227
|
+
).rejects.toThrow("conflicting content")
|
|
228
|
+
expect((await rows(storage))[0]?.name).toBe("newest")
|
|
229
|
+
}))
|
|
230
|
+
|
|
231
|
+
test("retains absent-key deletions and protects their version boundary", () =>
|
|
232
|
+
withStorage(async (storage) => {
|
|
233
|
+
const staleSession = await storage.beginMerge({ dataset })
|
|
234
|
+
await staleSession.writeChanges([upsert(8)])
|
|
235
|
+
const deleted = await merge(storage, [change.delete({ id: "42" }, { sequence: 9 })])
|
|
236
|
+
expect(deleted).toMatchObject({ outcome: "created", version: { rowCount: 0 } })
|
|
237
|
+
await expect(staleSession.commit()).rejects.toThrow("Optimistic")
|
|
238
|
+
await staleSession.abort()
|
|
239
|
+
expect((await merge(storage, [upsert(8)])).outcome).toBe("unchanged")
|
|
240
|
+
expect(
|
|
241
|
+
(await merge(storage, [change.delete({ id: "42" }, { sequence: "9" })])).outcome
|
|
242
|
+
).toBe("unchanged")
|
|
243
|
+
await expect(merge(storage, [upsert(9)])).rejects.toThrow("conflicting content")
|
|
244
|
+
await merge(storage, [upsert(10)])
|
|
245
|
+
expect(await rows(storage)).toHaveLength(1)
|
|
246
|
+
expect((await merge(storage, [change.delete({ id: "42" }, { sequence: 9 })])).outcome).toBe(
|
|
247
|
+
"unchanged"
|
|
248
|
+
)
|
|
249
|
+
await merge(storage, [change.delete({ id: "42" }, { sequence: 11 })])
|
|
250
|
+
expect(await rows(storage)).toEqual([])
|
|
251
|
+
}))
|
|
252
|
+
|
|
253
|
+
test("compares canonical content across JSON order and nullable representations", () =>
|
|
254
|
+
withStorage(async (storage) => {
|
|
255
|
+
await merge(storage, [
|
|
256
|
+
change.upsert({ id: "42", revision: 1, name: "Sam", details: { a: 1, b: 2 } }),
|
|
257
|
+
])
|
|
258
|
+
expect(
|
|
259
|
+
(
|
|
260
|
+
await merge(storage, [
|
|
261
|
+
change.upsert({ id: "42", revision: "01", name: "Sam", details: { b: 2, a: 1 } }),
|
|
262
|
+
])
|
|
263
|
+
).outcome
|
|
264
|
+
).toBe("unchanged")
|
|
265
|
+
await merge(storage, [upsert(2)])
|
|
266
|
+
expect(
|
|
267
|
+
(
|
|
268
|
+
await merge(storage, [
|
|
269
|
+
change.upsert({ id: "42", revision: "2", name: "Sam", details: null }),
|
|
270
|
+
])
|
|
271
|
+
).outcome
|
|
272
|
+
).toBe("unchanged")
|
|
273
|
+
}))
|
|
274
|
+
|
|
275
|
+
test("validates integer ranges and delete sequences at the provider boundary", () =>
|
|
276
|
+
withStorage(async (storage) => {
|
|
277
|
+
for (const revision of [
|
|
278
|
+
null,
|
|
279
|
+
undefined,
|
|
280
|
+
1.5,
|
|
281
|
+
Number.MAX_SAFE_INTEGER + 1,
|
|
282
|
+
"9223372036854775808",
|
|
283
|
+
"-9223372036854775809",
|
|
284
|
+
"1e3",
|
|
285
|
+
]) {
|
|
286
|
+
await expect(
|
|
287
|
+
merge(storage, [change.upsert({ id: "42", revision, name: "Sam" })])
|
|
288
|
+
).rejects.toThrow("sequence")
|
|
289
|
+
}
|
|
290
|
+
await expect(merge(storage, [change.delete({ id: "42" })])).rejects.toThrow("sequence")
|
|
291
|
+
await merge(storage, [upsert("-9223372036854775808"), upsert("9223372036854775807")])
|
|
292
|
+
expect((await rows(storage))[0]?.revision?.toString()).toBe("9223372036854775807")
|
|
293
|
+
}))
|
|
294
|
+
|
|
295
|
+
test("normalizes timezone-aware timestamps without discarding precision", () =>
|
|
296
|
+
withStorage(async (storage) => {
|
|
297
|
+
const timestamps = defineDataset("contract.source_timestamps", {
|
|
298
|
+
schema: [col("id", "string"), col("updated", "timestamp"), col("name", "string")],
|
|
299
|
+
primaryKey: "id",
|
|
300
|
+
sequenceBy: "updated",
|
|
301
|
+
})
|
|
302
|
+
await storage.createDataset(timestamps)
|
|
303
|
+
const row = (updated: unknown, name = "Sam") => change.upsert({ id: "42", updated, name })
|
|
304
|
+
await merge(storage, [row("2026-09-09T10:00:00.123Z")], timestamps)
|
|
305
|
+
for (const updated of [
|
|
306
|
+
"2026-09-09T12:00:00.123+02:00",
|
|
307
|
+
new Date("2026-09-09T10:00:00.123Z"),
|
|
308
|
+
]) {
|
|
309
|
+
expect((await merge(storage, [row(updated)], timestamps)).outcome).toBe("unchanged")
|
|
310
|
+
}
|
|
311
|
+
for (const updated of [
|
|
312
|
+
"2026-09-09T10:00:00.1234Z",
|
|
313
|
+
"2026-09-09T10:00:00",
|
|
314
|
+
"2026-02-30T00:00:00Z",
|
|
315
|
+
new Date(Number.NaN),
|
|
316
|
+
]) {
|
|
317
|
+
await expect(merge(storage, [row(updated)], timestamps)).rejects.toThrow("sequence")
|
|
318
|
+
}
|
|
319
|
+
await merge(
|
|
320
|
+
storage,
|
|
321
|
+
[change.delete({ id: "42" }, { sequence: "2026-09-09T10:00:00.124Z" })],
|
|
322
|
+
timestamps
|
|
323
|
+
)
|
|
324
|
+
expect((await merge(storage, [row("2026-09-09T10:00:00.123Z")], timestamps)).outcome).toBe(
|
|
325
|
+
"unchanged"
|
|
326
|
+
)
|
|
327
|
+
}))
|
|
328
|
+
|
|
329
|
+
test("round-trips immutable sequencing and rejects writes that bypass ordering", () =>
|
|
330
|
+
withStorage(async (storage) => {
|
|
331
|
+
expect((await storage.getDataset(dataset.id))?.sequenceBy).toBe("revision")
|
|
332
|
+
expect(
|
|
333
|
+
(await storage.listDatasets()).find((item) => item.id === dataset.id)?.sequenceBy
|
|
334
|
+
).toBe("revision")
|
|
335
|
+
const { sequenceBy: _, ...unsequenced } = dataset
|
|
336
|
+
await expect(storage.createDataset(unsequenced)).rejects.toThrow("immutable")
|
|
337
|
+
await storage.createDataset({ ...unsequenced, id: "legacy" })
|
|
338
|
+
await expect(storage.createDataset({ ...dataset, id: "legacy" })).rejects.toThrow(
|
|
339
|
+
"immutable"
|
|
340
|
+
)
|
|
341
|
+
await expect(
|
|
342
|
+
storage.createDataset({ ...dataset, id: "invalid", primaryKey: undefined })
|
|
343
|
+
).rejects.toThrow("sequenceBy")
|
|
344
|
+
await expect(
|
|
345
|
+
storage.createDataset({ ...dataset, id: "invalid", sequenceBy: "name" })
|
|
346
|
+
).rejects.toThrow("sequenceBy")
|
|
347
|
+
await expect(storage.beginWrite({ dataset })).rejects.toThrow("beginMerge")
|
|
348
|
+
}))
|
|
349
|
+
|
|
350
|
+
const reopen = options.reopen
|
|
351
|
+
if (reopen)
|
|
352
|
+
test("preserves source state after reopen", async () => {
|
|
353
|
+
let storage = await options.createStorage()
|
|
354
|
+
try {
|
|
355
|
+
await storage.createDataset(dataset)
|
|
356
|
+
await merge(storage, [
|
|
357
|
+
upsert(8, "visible", "visible"),
|
|
358
|
+
change.delete({ id: "42" }, { sequence: 9 }),
|
|
359
|
+
])
|
|
360
|
+
storage = await reopen(storage)
|
|
361
|
+
expect((await storage.getDataset(dataset.id))?.sequenceBy).toBe("revision")
|
|
362
|
+
expect((await merge(storage, [upsert(8), upsert(7, "stale", "visible")])).outcome).toBe(
|
|
363
|
+
"unchanged"
|
|
364
|
+
)
|
|
365
|
+
expect(await rows(storage)).toHaveLength(1)
|
|
366
|
+
await merge(storage, [upsert(10)])
|
|
367
|
+
expect(await rows(storage)).toHaveLength(2)
|
|
368
|
+
} finally {
|
|
369
|
+
await options.teardown?.(storage)
|
|
370
|
+
}
|
|
371
|
+
})
|
|
372
|
+
})
|
|
373
|
+
}
|
|
@@ -75,6 +75,17 @@ export function runEffectiveStorageContractSuite<TStorage extends Storage>(
|
|
|
75
75
|
],
|
|
76
76
|
})
|
|
77
77
|
expect([...batch.keys()]).toEqual([objectBatchKey(Device.id, "a")])
|
|
78
|
+
|
|
79
|
+
const selectedProperties = await storage.objects.selectsObjectProperties({
|
|
80
|
+
projectId,
|
|
81
|
+
items: [
|
|
82
|
+
{ objectTypeId: Device.id, primaryId: "a", propertyId: "name" },
|
|
83
|
+
{ objectTypeId: Device.id, primaryId: "a", propertyId: "not-materialized" },
|
|
84
|
+
{ objectTypeId: Device.id, primaryId: "missing", propertyId: "name" },
|
|
85
|
+
{ objectTypeId: Device.id, primaryId: "a", propertyId: "name" },
|
|
86
|
+
],
|
|
87
|
+
})
|
|
88
|
+
expect(selectedProperties).toEqual([true, true, false, true])
|
|
78
89
|
})
|
|
79
90
|
})
|
|
80
91
|
|
|
@@ -100,6 +111,28 @@ export function runEffectiveStorageContractSuite<TStorage extends Storage>(
|
|
|
100
111
|
items: [{ objectTypeId: Device.id, objectId: "a", linkId: "peers" }],
|
|
101
112
|
})
|
|
102
113
|
expect(linksByScope.get(linkBatchKey(Device.id, "a", "peers"))).toHaveLength(2)
|
|
114
|
+
|
|
115
|
+
const incomingByScope = await storage.objects.listLinksBatch({
|
|
116
|
+
projectId,
|
|
117
|
+
direction: "incoming",
|
|
118
|
+
items: [{ objectTypeId: Device.id, objectId: "b", linkId: "peers" }],
|
|
119
|
+
})
|
|
120
|
+
expect(incomingByScope.get(linkBatchKey(Device.id, "b", "peers"))).toMatchObject([
|
|
121
|
+
{ sourceId: "a", targetId: "b" },
|
|
122
|
+
])
|
|
123
|
+
|
|
124
|
+
const bothDirectionsByScope = await storage.objects.listLinksBatch({
|
|
125
|
+
projectId,
|
|
126
|
+
direction: "both",
|
|
127
|
+
items: [
|
|
128
|
+
{ objectTypeId: Device.id, objectId: "a", linkId: "peers" },
|
|
129
|
+
{ objectTypeId: Device.id, objectId: "b", linkId: "peers" },
|
|
130
|
+
],
|
|
131
|
+
})
|
|
132
|
+
expect(bothDirectionsByScope.get(linkBatchKey(Device.id, "a", "peers"))).toHaveLength(2)
|
|
133
|
+
expect(bothDirectionsByScope.get(linkBatchKey(Device.id, "b", "peers"))).toMatchObject([
|
|
134
|
+
{ sourceId: "a", targetId: "b" },
|
|
135
|
+
])
|
|
103
136
|
})
|
|
104
137
|
})
|
|
105
138
|
|
|
@@ -222,6 +255,7 @@ export function runEffectiveStorageContractSuite<TStorage extends Storage>(
|
|
|
222
255
|
|
|
223
256
|
const links = await storage.objects.listLinksBatch({
|
|
224
257
|
projectId: opaqueProjectId,
|
|
258
|
+
direction: "both",
|
|
225
259
|
items: [
|
|
226
260
|
{ objectTypeId: OpaqueA.id, objectId: "B:C", linkId: "D" },
|
|
227
261
|
{ objectTypeId: OpaqueAB.id, objectId: "C", linkId: "D" },
|
|
@@ -5,11 +5,15 @@ import type {
|
|
|
5
5
|
ExecutionStorage,
|
|
6
6
|
TrustedPrimitiveKind,
|
|
7
7
|
} from "../storage/executions"
|
|
8
|
+
import type { ShareGrantStorage } from "../storage/share-grants"
|
|
9
|
+
import type { ShareSessionStorage } from "../storage/share-sessions"
|
|
8
10
|
import type { Storage } from "../storage/types"
|
|
9
11
|
|
|
10
12
|
export type ExecutionStorageContractStorage = Storage & {
|
|
11
13
|
readonly auth: AuthStorage
|
|
12
14
|
readonly executions: ExecutionStorage
|
|
15
|
+
readonly shareGrants: ShareGrantStorage
|
|
16
|
+
readonly shareSessions: ShareSessionStorage
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
export interface ExecutionStorageContractSuiteOptions<
|
|
@@ -42,6 +46,7 @@ export function runExecutionStorageContractSuite<TStorage extends ExecutionStora
|
|
|
42
46
|
test("round-trips every durable executor and authority shape", async () => {
|
|
43
47
|
await withStorage(async (storage) => {
|
|
44
48
|
await seedAuth(storage.auth)
|
|
49
|
+
await seedSharedSession(storage)
|
|
45
50
|
|
|
46
51
|
const records = [
|
|
47
52
|
principalRequest({
|
|
@@ -54,6 +59,7 @@ export function runExecutionStorageContractSuite<TStorage extends ExecutionStora
|
|
|
54
59
|
credential: { type: "accessToken", id: "token-service" },
|
|
55
60
|
}),
|
|
56
61
|
disabledRequest("disabled-request"),
|
|
62
|
+
delegatedRequest("delegated-request"),
|
|
57
63
|
...trustedPrimitiveKinds.map((kind) => trustedPrimitive(`${kind}-execution`, {}, kind)),
|
|
58
64
|
agentExecution("agent-execution"),
|
|
59
65
|
kernelExecution("kernel-execution"),
|
|
@@ -169,6 +175,7 @@ export function runExecutionStorageContractSuite<TStorage extends ExecutionStora
|
|
|
169
175
|
test("requires every principal and verifies credential ownership", async () => {
|
|
170
176
|
await withStorage(async (storage) => {
|
|
171
177
|
await seedAuth(storage.auth)
|
|
178
|
+
await seedSharedSession(storage)
|
|
172
179
|
|
|
173
180
|
await expect(
|
|
174
181
|
storage.executions.create(
|
|
@@ -179,6 +186,34 @@ export function runExecutionStorageContractSuite<TStorage extends ExecutionStora
|
|
|
179
186
|
)
|
|
180
187
|
).rejects.toMatchObject({ code: "missing_principal" })
|
|
181
188
|
|
|
189
|
+
await expect(
|
|
190
|
+
storage.executions.create({
|
|
191
|
+
...delegatedRequest("missing-shared-session"),
|
|
192
|
+
authorizationRef: {
|
|
193
|
+
type: "delegated",
|
|
194
|
+
delegation: {
|
|
195
|
+
kind: "share",
|
|
196
|
+
grantId: "grant-one",
|
|
197
|
+
sessionId: "missing-shared-session",
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
})
|
|
201
|
+
).rejects.toMatchObject({ code: "missing_credential" })
|
|
202
|
+
|
|
203
|
+
await expect(
|
|
204
|
+
storage.executions.create({
|
|
205
|
+
...delegatedRequest("wrong-shared-grant"),
|
|
206
|
+
authorizationRef: {
|
|
207
|
+
type: "delegated",
|
|
208
|
+
delegation: {
|
|
209
|
+
kind: "share",
|
|
210
|
+
grantId: "grant-two",
|
|
211
|
+
sessionId: "share-session-one",
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
})
|
|
215
|
+
).rejects.toMatchObject({ code: "invalid_credential" })
|
|
216
|
+
|
|
182
217
|
await expect(
|
|
183
218
|
storage.executions.create(
|
|
184
219
|
principalRequest({
|
|
@@ -322,6 +357,32 @@ async function seedAuth(auth: AuthStorage): Promise<void> {
|
|
|
322
357
|
})
|
|
323
358
|
}
|
|
324
359
|
|
|
360
|
+
async function seedSharedSession(storage: ExecutionStorageContractStorage): Promise<void> {
|
|
361
|
+
for (const id of ["grant-one", "grant-two"] as const) {
|
|
362
|
+
await storage.shareGrants.create({
|
|
363
|
+
id,
|
|
364
|
+
projectId,
|
|
365
|
+
definitionId: "contract-share",
|
|
366
|
+
target: { objectTypeId: "ContractObject", primaryId: id },
|
|
367
|
+
issuedBy: { type: "user", id: "user-one" },
|
|
368
|
+
authoritySnapshot: { version: 1, access: { grants: [] } },
|
|
369
|
+
tokenHash: id === "grant-one" ? "a".repeat(64) : "b".repeat(64),
|
|
370
|
+
destinationPath: `/contract/${id}`,
|
|
371
|
+
createdAt,
|
|
372
|
+
expiresAt,
|
|
373
|
+
})
|
|
374
|
+
}
|
|
375
|
+
await storage.shareSessions.create({
|
|
376
|
+
id: "share-session-one",
|
|
377
|
+
projectId,
|
|
378
|
+
grantId: "grant-one",
|
|
379
|
+
tokenHash: "c".repeat(64),
|
|
380
|
+
createdAt,
|
|
381
|
+
expiresAt,
|
|
382
|
+
absoluteExpiresAt: expiresAt,
|
|
383
|
+
})
|
|
384
|
+
}
|
|
385
|
+
|
|
325
386
|
function principalRequest(input: {
|
|
326
387
|
readonly id: string
|
|
327
388
|
readonly principal?: { readonly type: "user" | "serviceAccount"; readonly id: string }
|
|
@@ -356,6 +417,24 @@ function disabledRequest(id: string, inputProjectId = projectId): CreateExecutio
|
|
|
356
417
|
}
|
|
357
418
|
}
|
|
358
419
|
|
|
420
|
+
function delegatedRequest(id: string): CreateExecutionInput {
|
|
421
|
+
return {
|
|
422
|
+
id,
|
|
423
|
+
projectId,
|
|
424
|
+
executor: { type: "request", requestId: `request-${id}` },
|
|
425
|
+
source: { type: "http", requestId: `request-${id}` },
|
|
426
|
+
correlationId: `correlation-${id}`,
|
|
427
|
+
authorizationRef: {
|
|
428
|
+
type: "delegated",
|
|
429
|
+
delegation: {
|
|
430
|
+
kind: "share",
|
|
431
|
+
grantId: "grant-one",
|
|
432
|
+
sessionId: "share-session-one",
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
359
438
|
function trustedPrimitive(
|
|
360
439
|
id: string,
|
|
361
440
|
overrides: Partial<Pick<CreateExecutionInput, "correlationId" | "requestedBy" | "source">> = {},
|
package/src/testing/index.ts
CHANGED
|
@@ -90,6 +90,12 @@ export {
|
|
|
90
90
|
runObjectQueryProviderContractSuite,
|
|
91
91
|
seedObjectQueryContractData,
|
|
92
92
|
} from "./object-query-contract"
|
|
93
|
+
export {
|
|
94
|
+
type ObjectReadScopeContractHarness,
|
|
95
|
+
type ObjectReadScopeContractSuiteOptions,
|
|
96
|
+
objectReadScopeContractOntology,
|
|
97
|
+
runObjectReadScopeContractSuite,
|
|
98
|
+
} from "./object-read-scope-contract"
|
|
93
99
|
export {
|
|
94
100
|
type OntologyStorageContractStorage,
|
|
95
101
|
type OntologyStorageContractSuiteOptions,
|
|
@@ -119,6 +125,16 @@ export {
|
|
|
119
125
|
type SandboxesContractCapabilities,
|
|
120
126
|
type SandboxesContractSuiteOptions,
|
|
121
127
|
} from "./sandboxes-contract"
|
|
128
|
+
export {
|
|
129
|
+
createShareGrantStorageContractInput,
|
|
130
|
+
runShareGrantStorageContractSuite,
|
|
131
|
+
type ShareGrantStorageContractSuiteOptions,
|
|
132
|
+
} from "./share-grant-storage-contract"
|
|
133
|
+
export {
|
|
134
|
+
createShareSessionStorageContractInput,
|
|
135
|
+
runShareSessionStorageContractSuite,
|
|
136
|
+
type ShareSessionStorageContractSuiteOptions,
|
|
137
|
+
} from "./share-session-storage-contract"
|
|
122
138
|
export {
|
|
123
139
|
createTestSyncExecution,
|
|
124
140
|
queueTestSyncRun,
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test"
|
|
2
2
|
import { change, col, defineDataset } from "../datasets"
|
|
3
3
|
import type { DatasetMergeCommitResult, DatasetRow, LakeStorage } from "../lake-storage"
|
|
4
|
+
import { runDatasetSequenceContract } from "./dataset-sequence-contract"
|
|
4
5
|
|
|
5
6
|
export interface LakeMergeStorageContractSuiteOptions<TStorage extends LakeStorage = LakeStorage> {
|
|
6
7
|
readonly createStorage: () => TStorage | Promise<TStorage>
|
|
7
8
|
readonly teardown?: (storage: TStorage) => void | Promise<void>
|
|
9
|
+
readonly reopen?: (storage: TStorage) => TStorage | Promise<TStorage>
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
const invoices = defineDataset("contract.merges.invoices", {
|
|
@@ -35,6 +37,7 @@ export function runLakeMergeStorageContractSuite<TStorage extends LakeStorage>(
|
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
describe(label, () => {
|
|
40
|
+
runDatasetSequenceContract(options)
|
|
38
41
|
test("creates an initial merge version from async changes", async () => {
|
|
39
42
|
await withStorage(async (storage) => {
|
|
40
43
|
await storage.createDataset(invoices)
|
|
@@ -471,6 +471,64 @@ export function runLakeStorageContractSuite<TStorage extends LakeStorage>(
|
|
|
471
471
|
})
|
|
472
472
|
})
|
|
473
473
|
|
|
474
|
+
test("guards initial and existing versions before accepting even an unchanged write", () =>
|
|
475
|
+
withStorage(async (storage) => {
|
|
476
|
+
// Regression proof: treat null like undefined or move the version guard after no-op
|
|
477
|
+
// detection. An old writer then succeeds after a competing version has committed.
|
|
478
|
+
await storage.createDataset(writeDataset)
|
|
479
|
+
const first = await storage.beginWrite({ dataset: writeDataset })
|
|
480
|
+
const stale = await storage.beginWrite({ dataset: writeDataset })
|
|
481
|
+
const initial = await first.commit({ expectedLatestVersionId: null })
|
|
482
|
+
await expect(stale.commit({ expectedLatestVersionId: null })).rejects.toThrow(
|
|
483
|
+
"Optimistic"
|
|
484
|
+
)
|
|
485
|
+
await stale.abort()
|
|
486
|
+
const replacement = await storage.beginWrite({ dataset: writeDataset })
|
|
487
|
+
await replacement.writeRows([{ orderId: "ord_1", customerName: "Ada" }])
|
|
488
|
+
const next = await replacement.commit({ expectedLatestVersionId: initial.versionId })
|
|
489
|
+
const identical = await storage.beginWrite({ dataset: writeDataset })
|
|
490
|
+
await identical.writeRows([{ orderId: "ord_1", customerName: "Ada" }])
|
|
491
|
+
await expect(
|
|
492
|
+
identical.commit({ expectedLatestVersionId: initial.versionId })
|
|
493
|
+
).rejects.toThrow("Optimistic")
|
|
494
|
+
await identical.abort()
|
|
495
|
+
expect((await storage.getLatestVersion(writeDataset.id))?.versionId).toBe(next.versionId)
|
|
496
|
+
}))
|
|
497
|
+
|
|
498
|
+
test("versions changed input lineage even when output rows are identical", () =>
|
|
499
|
+
withStorage(async (storage) => {
|
|
500
|
+
// Regression proof: omit hasDatasetInputChanges in the provider's no-op branch.
|
|
501
|
+
// The updated input reference is lost and the stale writer is no longer fenced.
|
|
502
|
+
await storage.createDataset(writeDataset)
|
|
503
|
+
await storage.createDataset(definitionDataset)
|
|
504
|
+
const sourceWrite = await storage.beginWrite({ dataset: definitionDataset })
|
|
505
|
+
const source1 = await sourceWrite.commit()
|
|
506
|
+
const rows = [{ orderId: "ord_1", customerName: "Ada" }]
|
|
507
|
+
const ref1 = { datasetId: definitionDataset.id, versionId: source1.versionId }
|
|
508
|
+
const first = await storage.beginWrite({ dataset: writeDataset, inputs: [ref1] })
|
|
509
|
+
await first.writeRows(rows)
|
|
510
|
+
const initial = await first.commit({ expectedLatestVersionId: null })
|
|
511
|
+
const stale = await storage.beginWrite({ dataset: writeDataset, inputs: [ref1] })
|
|
512
|
+
await stale.writeRows([{ orderId: "ord_1", customerName: "Stale" }])
|
|
513
|
+
const sourceUpdate = await storage.beginWrite({ dataset: definitionDataset })
|
|
514
|
+
await sourceUpdate.writeRows([{ orderId: "source", customerName: "Changed" }])
|
|
515
|
+
const source2 = await sourceUpdate.commit()
|
|
516
|
+
const ref2 = { datasetId: definitionDataset.id, versionId: source2.versionId }
|
|
517
|
+
const update = await storage.beginWrite({ dataset: writeDataset, inputs: [ref2] })
|
|
518
|
+
await update.writeRows(rows)
|
|
519
|
+
const newer = await update.commit({ expectedLatestVersionId: initial.versionId })
|
|
520
|
+
expect(newer).toMatchObject({ outcome: "created", inputs: [ref2] })
|
|
521
|
+
await expect(
|
|
522
|
+
stale.commit({ expectedLatestVersionId: initial.versionId })
|
|
523
|
+
).rejects.toThrow("Optimistic")
|
|
524
|
+
await stale.abort()
|
|
525
|
+
const same = await storage.beginWrite({ dataset: writeDataset, inputs: [ref2] })
|
|
526
|
+
await same.writeRows(rows)
|
|
527
|
+
const unchanged = await same.commit({ expectedLatestVersionId: newer.versionId })
|
|
528
|
+
expect(unchanged).toMatchObject({ outcome: "unchanged", versionId: newer.versionId })
|
|
529
|
+
expect(await collectRows(storage.readRows({ datasetId: writeDataset.id }))).toEqual(rows)
|
|
530
|
+
}))
|
|
531
|
+
|
|
474
532
|
test("creates an initial empty append version", async () => {
|
|
475
533
|
await withStorage(async (storage) => {
|
|
476
534
|
await storage.createDataset(writeDataset)
|