@sixb/core 0.1.12 → 0.1.13
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/index.d.ts +2 -2
- package/dist/actions/index.d.ts.map +1 -1
- package/dist/actions/index.js +28 -26
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/read-facade.d.ts +14 -16
- package/dist/actions/read-facade.d.ts.map +1 -1
- package/dist/actions/request.d.ts.map +1 -1
- package/dist/actions/run-dispatch.d.ts +2 -0
- package/dist/actions/run-dispatch.d.ts.map +1 -1
- package/dist/actions/types/context.d.ts +18 -31
- package/dist/actions/types/context.d.ts.map +1 -1
- package/dist/actions/types/params.d.ts +2 -1
- package/dist/actions/types/params.d.ts.map +1 -1
- package/dist/actions/worker.js +1 -1
- package/dist/agents/index.js +41 -39
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/streams/index.js +2 -2
- package/dist/agents/streams/internal.js +2 -2
- package/dist/assert-never.d.ts +6 -0
- package/dist/assert-never.d.ts.map +1 -0
- package/dist/auth/client-address.d.ts +3 -0
- package/dist/auth/client-address.d.ts.map +1 -0
- package/dist/auth/csrf.d.ts +5 -1
- package/dist/auth/csrf.d.ts.map +1 -1
- package/dist/auth/index.d.ts +3 -2
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +14 -8
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/runtime.d.ts +58 -41
- package/dist/auth/runtime.d.ts.map +1 -1
- package/dist/auth/session-cache.d.ts +10 -3
- package/dist/auth/session-cache.d.ts.map +1 -1
- package/dist/auth/sessions.d.ts +12 -0
- package/dist/auth/sessions.d.ts.map +1 -1
- package/dist/auth/strategy.js +1 -1
- package/dist/auth/types.d.ts +8 -15
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/authorization/index.js +3 -3
- package/dist/bootstrap/index.d.ts +1 -1
- package/dist/bootstrap/index.d.ts.map +1 -1
- package/dist/bootstrap/index.js +45 -43
- package/dist/bootstrap/index.js.map +1 -1
- package/dist/bootstrap/ontology-type-manifest.d.ts +8 -0
- package/dist/bootstrap/ontology-type-manifest.d.ts.map +1 -1
- package/dist/{chunk-q5gz3g2j.js → chunk-0321g649.js} +2 -16
- package/dist/{chunk-q5gz3g2j.js.map → chunk-0321g649.js.map} +2 -2
- package/dist/{chunk-e1f1sqba.js → chunk-04h4t2b5.js} +3 -3
- package/dist/{chunk-y3ev53cq.js → chunk-2fv8sajb.js} +2 -2
- package/dist/{chunk-3bnt2wna.js → chunk-2hbhn1ff.js} +1 -1
- package/dist/{chunk-eyjzgav0.js → chunk-3nx8vj5a.js} +6 -4
- package/dist/chunk-3nx8vj5a.js.map +12 -0
- package/dist/{chunk-5tetw4hn.js → chunk-4tnrzqqh.js} +1 -1
- package/dist/{chunk-g50nxqs5.js → chunk-63fp9x3q.js} +63 -20
- package/dist/chunk-63fp9x3q.js.map +20 -0
- package/dist/{chunk-qm535afa.js → chunk-693f3zn8.js} +66 -24
- package/dist/chunk-693f3zn8.js.map +15 -0
- package/dist/{chunk-7zgecwy1.js → chunk-6x0pqh32.js} +12 -1
- package/dist/{chunk-7zgecwy1.js.map → chunk-6x0pqh32.js.map} +3 -3
- package/dist/{chunk-6ma8dvzc.js → chunk-898y24dd.js} +49 -42
- package/dist/chunk-898y24dd.js.map +15 -0
- package/dist/{chunk-7qnvhtcd.js → chunk-91wthfwe.js} +17 -17
- package/dist/{chunk-7qnvhtcd.js.map → chunk-91wthfwe.js.map} +5 -5
- package/dist/chunk-96yw3pwd.js.map +2 -2
- package/dist/{chunk-2cxv584m.js → chunk-9pfw47qx.js} +309 -204
- package/dist/chunk-9pfw47qx.js.map +44 -0
- package/dist/{chunk-4k53sm9e.js → chunk-a0073121.js} +59 -59
- package/dist/{chunk-4k53sm9e.js.map → chunk-a0073121.js.map} +5 -5
- package/dist/{chunk-jjwhy3rs.js → chunk-a69fkrtr.js} +5 -5
- package/dist/{chunk-y1ahv8b7.js → chunk-bdhfn0ww.js} +1 -1
- package/dist/{chunk-4ph94nhd.js → chunk-bep5rrdq.js} +2 -2
- package/dist/{chunk-kept9cdd.js → chunk-bxx3ms5t.js} +1 -1
- package/dist/{chunk-xtfryrfb.js → chunk-cbn96bve.js} +2 -2
- package/dist/{chunk-nzsy3xrp.js → chunk-cvrbhvtr.js} +69 -44
- package/dist/{chunk-nzsy3xrp.js.map → chunk-cvrbhvtr.js.map} +7 -7
- package/dist/{chunk-vsg0g7h9.js → chunk-d8yes9yx.js} +304 -45
- package/dist/chunk-d8yes9yx.js.map +20 -0
- package/dist/{chunk-tg4g4zh0.js → chunk-darm7eeg.js} +9 -9
- package/dist/{chunk-tg4g4zh0.js.map → chunk-darm7eeg.js.map} +3 -3
- package/dist/{chunk-vpxss818.js → chunk-drz59ve0.js} +9 -8
- package/dist/chunk-drz59ve0.js.map +10 -0
- package/dist/{chunk-7c2g3sz9.js → chunk-dsfw1bdr.js} +5 -5
- package/dist/{chunk-7c2g3sz9.js.map → chunk-dsfw1bdr.js.map} +1 -1
- package/dist/{chunk-p6r1ex7t.js → chunk-ffwvdgk1.js} +5 -13
- package/dist/chunk-ffwvdgk1.js.map +10 -0
- package/dist/{chunk-r5zythxp.js → chunk-gbcrz0gr.js} +7 -7
- package/dist/{chunk-ybhz3j9g.js → chunk-gc226ten.js} +104 -148
- package/dist/{chunk-ybhz3j9g.js.map → chunk-gc226ten.js.map} +7 -8
- package/dist/{chunk-3ghw2t5q.js → chunk-gmt22nxx.js} +10 -16
- package/dist/chunk-gmt22nxx.js.map +10 -0
- package/dist/chunk-h89wz928.js +42 -0
- package/dist/chunk-h89wz928.js.map +10 -0
- package/dist/{chunk-hkw8rykk.js → chunk-ht4a7mjg.js} +74 -4
- package/dist/chunk-ht4a7mjg.js.map +15 -0
- package/dist/{chunk-t7dzd1tm.js → chunk-jhyc777j.js} +2 -2
- package/dist/{chunk-xn686q2e.js → chunk-jmwy25mf.js} +75 -57
- package/dist/{chunk-xn686q2e.js.map → chunk-jmwy25mf.js.map} +3 -3
- package/dist/{chunk-f06sf7rr.js → chunk-k4kkp58d.js} +18 -5
- package/dist/chunk-k4kkp58d.js.map +11 -0
- package/dist/{chunk-2h63nrde.js → chunk-ky7zpbtt.js} +5 -7
- package/dist/{chunk-2h63nrde.js.map → chunk-ky7zpbtt.js.map} +3 -4
- package/dist/chunk-m4ehq95f.js +9 -0
- package/dist/chunk-m4ehq95f.js.map +10 -0
- package/dist/{chunk-0mza4xb2.js → chunk-m8zkvep1.js} +2 -2
- package/dist/{chunk-b768c93y.js → chunk-mf6hwpzh.js} +83 -28
- package/dist/{chunk-b768c93y.js.map → chunk-mf6hwpzh.js.map} +5 -5
- package/dist/{chunk-yxb4c62x.js → chunk-mr60an99.js} +3 -2
- package/dist/{chunk-yxb4c62x.js.map → chunk-mr60an99.js.map} +3 -3
- package/dist/chunk-n33e8dz8.js +191 -0
- package/dist/chunk-n33e8dz8.js.map +11 -0
- package/dist/chunk-rdghfsss.js.map +2 -2
- package/dist/{chunk-m7cx05vp.js → chunk-rqtdtm43.js} +126 -59
- package/dist/{chunk-m7cx05vp.js.map → chunk-rqtdtm43.js.map} +13 -12
- package/dist/{chunk-bbaa1fet.js → chunk-rzcjp5m2.js} +7 -3
- package/dist/chunk-rzcjp5m2.js.map +25 -0
- package/dist/{chunk-hzw7yv5g.js → chunk-rzkr70gr.js} +5 -1
- package/dist/{chunk-hzw7yv5g.js.map → chunk-rzkr70gr.js.map} +3 -3
- package/dist/{chunk-sfypc7mk.js → chunk-s24qbp32.js} +4 -4
- package/dist/{chunk-axndsymr.js → chunk-tw03bsmb.js} +2 -2
- package/dist/{chunk-axndsymr.js.map → chunk-tw03bsmb.js.map} +3 -3
- package/dist/{chunk-y0v18c2j.js → chunk-vef6qa14.js} +2 -2
- package/dist/{chunk-gzt6v1ja.js → chunk-vn3yh259.js} +1 -1
- package/dist/{chunk-bg2bs62d.js → chunk-w9bp61e7.js} +5 -5
- package/dist/{chunk-3h7ctayx.js → chunk-xgptywp0.js} +4 -3
- package/dist/chunk-xgptywp0.js.map +11 -0
- package/dist/{chunk-gswwr35f.js → chunk-y487ywrv.js} +4 -4
- package/dist/{chunk-bet1rb9h.js → chunk-y6vnvayj.js} +1 -1
- package/dist/{chunk-x9tmx3fc.js → chunk-ypj2wqtj.js} +3 -6
- package/dist/{chunk-x9tmx3fc.js.map → chunk-ypj2wqtj.js.map} +4 -4
- package/dist/{chunk-g2gezsg5.js → chunk-z9h698s8.js} +1 -1
- package/dist/{chunk-wjffn5m4.js → chunk-zdkcdshk.js} +3 -36
- package/dist/{chunk-wjffn5m4.js.map → chunk-zdkcdshk.js.map} +3 -4
- package/dist/{chunk-bfjv1adk.js → chunk-znw0zvy4.js} +1 -1
- package/dist/edits/types.d.ts +19 -19
- package/dist/edits/types.d.ts.map +1 -1
- package/dist/error-reporting/internal.js +3 -3
- package/dist/errors/catalog.d.ts +4 -0
- package/dist/errors/catalog.d.ts.map +1 -1
- package/dist/errors/internal.js +1 -1
- package/dist/events/envelope.d.ts +0 -12
- package/dist/events/envelope.d.ts.map +1 -1
- package/dist/events/index.d.ts +1 -1
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +3 -3
- package/dist/events/service.d.ts +1 -2
- package/dist/events/service.d.ts.map +1 -1
- package/dist/events/toStoredEvent.d.ts +1 -2
- package/dist/events/toStoredEvent.d.ts.map +1 -1
- package/dist/events/types/index.d.ts +2 -1
- package/dist/events/types/index.d.ts.map +1 -1
- package/dist/execution/agent.d.ts +1 -2
- package/dist/execution/agent.d.ts.map +1 -1
- package/dist/execution/agent.js +39 -37
- package/dist/execution/agent.js.map +1 -1
- package/dist/execution/authorized-object-reader.d.ts.map +1 -1
- package/dist/execution/primitive.d.ts +1 -2
- package/dist/execution/primitive.d.ts.map +1 -1
- package/dist/execution/primitive.js +38 -36
- package/dist/execution/primitive.js.map +3 -3
- package/dist/execution/request.d.ts +1 -2
- package/dist/execution/request.d.ts.map +1 -1
- package/dist/execution/request.js +39 -37
- package/dist/execution/request.js.map +3 -3
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +56 -50
- package/dist/index.js.map +1 -1
- package/dist/maintenance/ontology-maintenance.d.ts +11 -1
- package/dist/maintenance/ontology-maintenance.d.ts.map +1 -1
- package/dist/materialization/errors.d.ts +3 -1
- package/dist/materialization/errors.d.ts.map +1 -1
- package/dist/materialization/events.d.ts +27 -2
- package/dist/materialization/events.d.ts.map +1 -1
- package/dist/materializer/edits/commit.d.ts.map +1 -1
- package/dist/materializer/edits/operations.d.ts +2 -1
- package/dist/materializer/edits/operations.d.ts.map +1 -1
- package/dist/materializer/edits/plan.d.ts +2 -2
- package/dist/materializer/edits/plan.d.ts.map +1 -1
- package/dist/materializer/edits/user-refs.d.ts +30 -0
- package/dist/materializer/edits/user-refs.d.ts.map +1 -0
- package/dist/materializer/effective/build-events.d.ts +2 -2
- package/dist/materializer/effective/build-events.d.ts.map +1 -1
- package/dist/materializer/execution/scope.d.ts +11 -3
- package/dist/materializer/execution/scope.d.ts.map +1 -1
- package/dist/materializer/index.js +23 -21
- package/dist/materializer/index.js.map +1 -1
- package/dist/materializer/projections/replacement-plan.d.ts +2 -0
- package/dist/materializer/projections/replacement-plan.d.ts.map +1 -1
- package/dist/materializer/telemetry/plan.d.ts +2 -2
- package/dist/materializer/telemetry/plan.d.ts.map +1 -1
- package/dist/models/execution/index.js +23 -21
- package/dist/models/execution/index.js.map +1 -1
- package/dist/models/index.js +1 -1
- package/dist/objects/execution.d.ts +21 -27
- package/dist/objects/execution.d.ts.map +1 -1
- package/dist/objects/index.js +28 -26
- package/dist/objects/index.js.map +1 -1
- package/dist/objects/query/executor.d.ts.map +1 -1
- package/dist/objects/query/index.js +27 -25
- package/dist/objects/query/index.js.map +1 -1
- package/dist/objects/query/ir.d.ts +8 -1
- package/dist/objects/query/ir.d.ts.map +1 -1
- package/dist/objects/query/scalar-values.d.ts.map +1 -1
- package/dist/objects/query/validate.d.ts.map +1 -1
- package/dist/objects/sdk/object-handle.d.ts +1 -2
- package/dist/objects/sdk/object-handle.d.ts.map +1 -1
- package/dist/objects/sdk/object-set.d.ts +2 -3
- package/dist/objects/sdk/object-set.d.ts.map +1 -1
- package/dist/objects/sdk/query-builder.d.ts +8 -10
- package/dist/objects/sdk/query-builder.d.ts.map +1 -1
- package/dist/objects/sdk/telemetry-channel.d.ts +1 -2
- package/dist/objects/sdk/telemetry-channel.d.ts.map +1 -1
- package/dist/objects/sdk/where.d.ts +2 -3
- package/dist/objects/sdk/where.d.ts.map +1 -1
- package/dist/ontology/builders.d.ts +11 -10
- package/dist/ontology/builders.d.ts.map +1 -1
- package/dist/ontology/index.d.ts +4 -2
- package/dist/ontology/index.d.ts.map +1 -1
- package/dist/ontology/index.js +6 -4
- package/dist/ontology/index.js.map +1 -1
- package/dist/ontology/inference/index.d.ts +34 -22
- package/dist/ontology/inference/index.d.ts.map +1 -1
- package/dist/ontology/internal.d.ts +1 -0
- package/dist/ontology/internal.d.ts.map +1 -1
- package/dist/ontology/internal.js +9 -7
- package/dist/ontology/internal.js.map +1 -1
- package/dist/ontology/primitives.d.ts +38 -0
- package/dist/ontology/primitives.d.ts.map +1 -0
- package/dist/ontology/query-capabilities.d.ts +38 -0
- package/dist/ontology/query-capabilities.d.ts.map +1 -0
- package/dist/ontology/refs.d.ts +23 -2
- package/dist/ontology/refs.d.ts.map +1 -1
- package/dist/ontology/registered.d.ts +16 -0
- package/dist/ontology/registered.d.ts.map +1 -0
- package/dist/ontology/registry.d.ts.map +1 -1
- package/dist/ontology/tokens.d.ts +35 -1
- package/dist/ontology/tokens.d.ts.map +1 -1
- package/dist/ontology/types.d.ts +18 -4
- package/dist/ontology/types.d.ts.map +1 -1
- package/dist/ontology/user-ref.d.ts +35 -0
- package/dist/ontology/user-ref.d.ts.map +1 -0
- package/dist/ontology/validation/definition.d.ts.map +1 -1
- package/dist/ontology/validation/index.d.ts +1 -1
- package/dist/ontology/validation/index.d.ts.map +1 -1
- package/dist/ontology/validation/normalize.d.ts.map +1 -1
- package/dist/ontology/validation/properties.d.ts +6 -1
- package/dist/ontology/validation/properties.d.ts.map +1 -1
- package/dist/ontology/validation/query.d.ts.map +1 -1
- package/dist/ontology/validation/schema.d.ts.map +1 -1
- package/dist/pipelines/index.js +26 -24
- package/dist/pipelines/index.js.map +1 -1
- package/dist/predicates/types.d.ts +53 -3
- package/dist/predicates/types.d.ts.map +1 -1
- package/dist/projections/builders.d.ts +19 -1
- package/dist/projections/builders.d.ts.map +1 -1
- package/dist/projections/internal.js +23 -21
- package/dist/projections/internal.js.map +1 -1
- package/dist/projections/validation.d.ts.map +1 -1
- package/dist/query.js +2 -2
- package/dist/queues/in-memory.d.ts +1 -1
- package/dist/queues/in-memory.d.ts.map +1 -1
- package/dist/runtime/create.d.ts +1 -1
- package/dist/runtime/create.d.ts.map +1 -1
- package/dist/runtime/host.d.ts +5 -5
- package/dist/runtime/host.d.ts.map +1 -1
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/internal.js +27 -25
- package/dist/runtime/internal.js.map +1 -1
- package/dist/runtime/sixb.d.ts +5 -5
- package/dist/runtime/sixb.d.ts.map +1 -1
- package/dist/runtime/types.d.ts +171 -188
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/sandboxes/index.js +5 -5
- package/dist/sandboxes/sandbox.d.ts +4 -1
- package/dist/sandboxes/sandbox.d.ts.map +1 -1
- package/dist/shared/params/types.d.ts +4 -3
- package/dist/shared/params/types.d.ts.map +1 -1
- package/dist/shared/params/user-refs.d.ts +19 -0
- package/dist/shared/params/user-refs.d.ts.map +1 -0
- package/dist/shares/compiler.d.ts.map +1 -1
- package/dist/shares/internal.js +24 -22
- package/dist/shares/internal.js.map +2 -2
- package/dist/storage/action-runs/failure.js +2 -2
- package/dist/storage/action-runs/types.d.ts +1 -1
- package/dist/storage/action-runs/types.d.ts.map +1 -1
- package/dist/storage/agents/provider.js +1 -1
- package/dist/storage/ai-limits/enforcement.js +2 -2
- package/dist/storage/auth/in-memory/access-tokens.d.ts.map +1 -1
- package/dist/storage/auth/in-memory/auth-storage.d.ts.map +1 -1
- package/dist/storage/auth/in-memory/device-authorizations.d.ts.map +1 -1
- package/dist/storage/auth/in-memory/sessions.d.ts +8 -1
- package/dist/storage/auth/in-memory/sessions.d.ts.map +1 -1
- package/dist/storage/auth/in-memory/shared.d.ts.map +1 -1
- package/dist/storage/auth/index.d.ts +1 -1
- package/dist/storage/auth/index.d.ts.map +1 -1
- package/dist/storage/auth/types.d.ts +62 -13
- package/dist/storage/auth/types.d.ts.map +1 -1
- package/dist/storage/connector-connections/provider.js +1 -1
- package/dist/storage/executions/provider.js +1 -1
- package/dist/storage/file-upload-sessions/in-memory.d.ts +9 -18
- package/dist/storage/file-upload-sessions/in-memory.d.ts.map +1 -1
- package/dist/storage/file-upload-sessions/index.d.ts +1 -1
- package/dist/storage/file-upload-sessions/index.d.ts.map +1 -1
- package/dist/storage/file-upload-sessions/provider.d.ts +52 -0
- package/dist/storage/file-upload-sessions/provider.d.ts.map +1 -0
- package/dist/storage/file-upload-sessions/provider.js +24 -0
- package/dist/storage/file-upload-sessions/provider.js.map +9 -0
- package/dist/storage/file-upload-sessions/types.d.ts +19 -1
- package/dist/storage/file-upload-sessions/types.d.ts.map +1 -1
- package/dist/storage/file-upload-sessions/utils.d.ts +8 -2
- package/dist/storage/file-upload-sessions/utils.d.ts.map +1 -1
- package/dist/storage/index.d.ts +3 -3
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +29 -25
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/internal.js +11 -9
- package/dist/storage/internal.js.map +1 -1
- package/dist/storage/objects/in-memory/query.d.ts.map +1 -1
- package/dist/storage/ontology/commits.d.ts +6 -2
- package/dist/storage/ontology/commits.d.ts.map +1 -1
- package/dist/storage/ontology/in-memory/materializations.d.ts.map +1 -1
- package/dist/storage/ontology/provider-work.d.ts.map +1 -1
- package/dist/storage/ontology/provider.d.ts +14 -1
- package/dist/storage/ontology/provider.d.ts.map +1 -1
- package/dist/storage/ontology/provider.js +8 -2
- package/dist/storage/ontology/provider.js.map +1 -1
- package/dist/storage/operation-scope.d.ts.map +1 -1
- package/dist/storage/operation-scope.js +1 -1
- package/dist/storage/projection-runs/provider.js +2 -2
- package/dist/storage/types.d.ts +1 -1
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/storage/workflow-interventions/index.d.ts +1 -1
- package/dist/storage/workflow-interventions/index.d.ts.map +1 -1
- package/dist/storage/workflow-interventions/types.d.ts +5 -8
- package/dist/storage/workflow-interventions/types.d.ts.map +1 -1
- package/dist/storage/workflow-runs/provider.js +8 -8
- package/dist/syncs/index.js +27 -25
- package/dist/syncs/index.js.map +1 -1
- package/dist/testing/action-execution.d.ts +4 -0
- package/dist/testing/action-execution.d.ts.map +1 -1
- package/dist/testing/auth-storage-contract.d.ts.map +1 -1
- package/dist/testing/execution.d.ts +1 -2
- package/dist/testing/execution.d.ts.map +1 -1
- package/dist/testing/file-upload-session-storage-contract.d.ts +12 -0
- package/dist/testing/file-upload-session-storage-contract.d.ts.map +1 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +1951 -1242
- package/dist/testing/index.js.map +15 -13
- package/dist/testing/materializer-storage-contract.d.ts.map +1 -1
- package/dist/testing/object-query-contract.d.ts.map +1 -1
- package/dist/testing/ontology-contract-fixture.d.ts +8 -0
- package/dist/testing/ontology-contract-fixture.d.ts.map +1 -1
- package/dist/testing/ontology-storage-contract.d.ts.map +1 -1
- package/dist/testing/sandboxes-contract.d.ts.map +1 -1
- package/dist/testing/workflow-intervention-storage-contract.d.ts +8 -0
- package/dist/testing/workflow-intervention-storage-contract.d.ts.map +1 -0
- package/dist/webhooks/internal.js +24 -22
- package/dist/webhooks/internal.js.map +2 -2
- package/dist/webhooks/types.d.ts +2 -2
- package/dist/webhooks/types.d.ts.map +1 -1
- package/dist/workers/index.js +1 -1
- package/dist/workflows/index.js +42 -40
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/run-dispatch.d.ts.map +1 -1
- package/dist/workflows/types.d.ts +2 -2
- package/dist/workflows/types.d.ts.map +1 -1
- package/package.json +7 -1
- package/src/actions/index.ts +0 -3
- package/src/actions/read-facade.ts +102 -62
- package/src/actions/request.ts +13 -0
- package/src/actions/run-dispatch.ts +3 -0
- package/src/actions/types/context.ts +17 -65
- package/src/actions/types/params.ts +2 -1
- package/src/agents/authority.ts +1 -1
- package/src/assert-never.ts +7 -0
- package/src/auth/client-address.ts +12 -0
- package/src/auth/csrf.ts +14 -5
- package/src/auth/index.ts +3 -2
- package/src/auth/runtime.ts +299 -277
- package/src/auth/session-cache.ts +18 -6
- package/src/auth/sessions.ts +30 -0
- package/src/auth/types.ts +7 -17
- package/src/bootstrap/index.ts +1 -0
- package/src/bootstrap/ontology-type-manifest.ts +112 -60
- package/src/edits/types.ts +47 -63
- package/src/errors/catalog.ts +4 -0
- package/src/events/envelope.ts +0 -13
- package/src/events/index.ts +1 -1
- package/src/events/service.ts +1 -11
- package/src/events/toStoredEvent.ts +1 -3
- package/src/events/types/index.ts +1 -1
- package/src/execution/agent.ts +1 -2
- package/src/execution/authorized-object-reader.ts +5 -7
- package/src/execution/primitive.ts +1 -2
- package/src/execution/request.ts +1 -2
- package/src/index.ts +8 -7
- package/src/maintenance/ontology-maintenance.ts +77 -1
- package/src/materialization/errors.ts +2 -0
- package/src/materialization/events.ts +27 -2
- package/src/materializer/README.md +2 -0
- package/src/materializer/edits/commit.ts +21 -12
- package/src/materializer/edits/operations.ts +32 -4
- package/src/materializer/edits/plan.ts +4 -5
- package/src/materializer/edits/user-refs.ts +115 -0
- package/src/materializer/effective/build-events.ts +4 -5
- package/src/materializer/execution/scope.ts +40 -7
- package/src/materializer/projections/replace.ts +2 -0
- package/src/materializer/projections/replacement-plan.ts +4 -0
- package/src/materializer/telemetry/append.ts +4 -12
- package/src/materializer/telemetry/plan.ts +4 -5
- package/src/objects/execution.ts +33 -62
- package/src/objects/query/executor.ts +12 -3
- package/src/objects/query/ir.ts +7 -0
- package/src/objects/query/planner.ts +1 -0
- package/src/objects/query/scalar-values.ts +19 -0
- package/src/objects/query/validate.ts +55 -44
- package/src/objects/sdk/object-handle.ts +8 -8
- package/src/objects/sdk/object-set.ts +8 -15
- package/src/objects/sdk/query-builder.ts +59 -71
- package/src/objects/sdk/telemetry-channel.ts +6 -7
- package/src/objects/sdk/where.ts +6 -13
- package/src/ontology/builders.ts +15 -11
- package/src/ontology/index.ts +4 -0
- package/src/ontology/inference/index.ts +56 -36
- package/src/ontology/internal.ts +1 -0
- package/src/ontology/json-schema.ts +12 -0
- package/src/ontology/primitives.ts +91 -0
- package/src/ontology/query-capabilities.ts +136 -0
- package/src/ontology/refs.ts +33 -6
- package/src/ontology/registered.ts +22 -0
- package/src/ontology/registry.ts +6 -3
- package/src/ontology/tokens.ts +41 -2
- package/src/ontology/types.ts +19 -3
- package/src/ontology/user-ref.ts +120 -0
- package/src/ontology/validation/definition.ts +2 -13
- package/src/ontology/validation/index.ts +1 -0
- package/src/ontology/validation/normalize.ts +39 -3
- package/src/ontology/validation/properties.ts +95 -19
- package/src/ontology/validation/query.ts +11 -42
- package/src/ontology/validation/schema.ts +16 -0
- package/src/predicates/types.ts +43 -33
- package/src/projections/builders.ts +24 -3
- package/src/projections/validation.ts +15 -1
- package/src/runtime/create.ts +2 -2
- package/src/runtime/host.ts +10 -12
- package/src/runtime/index.ts +3 -2
- package/src/runtime/sixb.ts +13 -23
- package/src/runtime/types.ts +277 -479
- package/src/sandboxes/sandbox.ts +4 -1
- package/src/shared/params/types.ts +4 -3
- package/src/shared/params/user-refs.ts +48 -0
- package/src/shares/compiler.ts +6 -16
- package/src/storage/action-runs/types.ts +1 -0
- package/src/storage/auth/in-memory/access-tokens.ts +5 -2
- package/src/storage/auth/in-memory/auth-storage.ts +5 -8
- package/src/storage/auth/in-memory/device-authorizations.ts +0 -2
- package/src/storage/auth/in-memory/sessions.ts +69 -1
- package/src/storage/auth/in-memory/shared.ts +13 -7
- package/src/storage/auth/index.ts +2 -1
- package/src/storage/auth/types.ts +57 -13
- package/src/storage/executions/validation.ts +1 -1
- package/src/storage/file-upload-sessions/in-memory.ts +64 -113
- package/src/storage/file-upload-sessions/index.ts +1 -0
- package/src/storage/file-upload-sessions/provider.ts +258 -0
- package/src/storage/file-upload-sessions/types.ts +20 -1
- package/src/storage/file-upload-sessions/utils.ts +25 -9
- package/src/storage/index.ts +3 -2
- package/src/storage/objects/in-memory/query.ts +13 -3
- package/src/storage/ontology/commits.ts +6 -2
- package/src/storage/ontology/in-memory/materializations.ts +6 -34
- package/src/storage/ontology/provider-header-validation.ts +57 -0
- package/src/storage/ontology/provider-work.ts +15 -3
- package/src/storage/ontology/provider.ts +59 -1
- package/src/storage/operation-scope.ts +1 -0
- package/src/storage/types.ts +0 -1
- package/src/storage/workflow-interventions/index.ts +0 -1
- package/src/storage/workflow-interventions/types.ts +5 -9
- package/src/testing/action-execution.ts +13 -3
- package/src/testing/auth-storage-contract.ts +149 -62
- package/src/testing/execution-storage-contract.ts +1 -2
- package/src/testing/execution.ts +4 -7
- package/src/testing/file-upload-session-storage-contract.ts +335 -0
- package/src/testing/index.ts +8 -0
- package/src/testing/materializer-storage-contract.ts +86 -4
- package/src/testing/object-query-contract.ts +121 -2
- package/src/testing/ontology-contract-fixture.ts +23 -3
- package/src/testing/ontology-storage-contract.ts +58 -0
- package/src/testing/sandboxes-contract.ts +27 -0
- package/src/testing/workflow-intervention-storage-contract.ts +203 -0
- package/src/webhooks/types.ts +2 -2
- package/src/workflows/run-dispatch.ts +12 -1
- package/src/workflows/snapshot.ts +16 -7
- package/src/workflows/types.ts +2 -2
- package/dist/chunk-2cxv584m.js.map +0 -43
- package/dist/chunk-3ghw2t5q.js.map +0 -10
- package/dist/chunk-3h7ctayx.js.map +0 -11
- package/dist/chunk-6ma8dvzc.js.map +0 -15
- package/dist/chunk-bbaa1fet.js.map +0 -25
- package/dist/chunk-eyjzgav0.js.map +0 -12
- package/dist/chunk-f06sf7rr.js.map +0 -11
- package/dist/chunk-g50nxqs5.js.map +0 -18
- package/dist/chunk-hkw8rykk.js.map +0 -15
- package/dist/chunk-p6r1ex7t.js.map +0 -10
- package/dist/chunk-qm535afa.js.map +0 -15
- package/dist/chunk-vpxss818.js.map +0 -10
- package/dist/chunk-vsg0g7h9.js.map +0 -17
- /package/dist/{chunk-e1f1sqba.js.map → chunk-04h4t2b5.js.map} +0 -0
- /package/dist/{chunk-y3ev53cq.js.map → chunk-2fv8sajb.js.map} +0 -0
- /package/dist/{chunk-3bnt2wna.js.map → chunk-2hbhn1ff.js.map} +0 -0
- /package/dist/{chunk-5tetw4hn.js.map → chunk-4tnrzqqh.js.map} +0 -0
- /package/dist/{chunk-jjwhy3rs.js.map → chunk-a69fkrtr.js.map} +0 -0
- /package/dist/{chunk-y1ahv8b7.js.map → chunk-bdhfn0ww.js.map} +0 -0
- /package/dist/{chunk-4ph94nhd.js.map → chunk-bep5rrdq.js.map} +0 -0
- /package/dist/{chunk-kept9cdd.js.map → chunk-bxx3ms5t.js.map} +0 -0
- /package/dist/{chunk-xtfryrfb.js.map → chunk-cbn96bve.js.map} +0 -0
- /package/dist/{chunk-r5zythxp.js.map → chunk-gbcrz0gr.js.map} +0 -0
- /package/dist/{chunk-t7dzd1tm.js.map → chunk-jhyc777j.js.map} +0 -0
- /package/dist/{chunk-0mza4xb2.js.map → chunk-m8zkvep1.js.map} +0 -0
- /package/dist/{chunk-sfypc7mk.js.map → chunk-s24qbp32.js.map} +0 -0
- /package/dist/{chunk-y0v18c2j.js.map → chunk-vef6qa14.js.map} +0 -0
- /package/dist/{chunk-gzt6v1ja.js.map → chunk-vn3yh259.js.map} +0 -0
- /package/dist/{chunk-bg2bs62d.js.map → chunk-w9bp61e7.js.map} +0 -0
- /package/dist/{chunk-gswwr35f.js.map → chunk-y487ywrv.js.map} +0 -0
- /package/dist/{chunk-bet1rb9h.js.map → chunk-y6vnvayj.js.map} +0 -0
- /package/dist/{chunk-g2gezsg5.js.map → chunk-z9h698s8.js.map} +0 -0
- /package/dist/{chunk-bfjv1adk.js.map → chunk-znw0zvy4.js.map} +0 -0
|
@@ -37,6 +37,24 @@ function sessionInput(
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
function bearerSessionInput(id: string) {
|
|
41
|
+
return {
|
|
42
|
+
id,
|
|
43
|
+
projectId,
|
|
44
|
+
userId: "usr_1",
|
|
45
|
+
strategyId: "magic-link",
|
|
46
|
+
audience: "atlas" as const,
|
|
47
|
+
tokenHash: "access-1",
|
|
48
|
+
createdAt: at("2026-05-14T10:00:00.000Z"),
|
|
49
|
+
expiresAt: at("2026-06-14T10:00:00.000Z"),
|
|
50
|
+
bearer: {
|
|
51
|
+
clientName: "sixb CLI",
|
|
52
|
+
accessExpiresAt: at("2026-05-14T10:15:00.000Z"),
|
|
53
|
+
refreshTokenHash: "refresh-1",
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
40
58
|
async function expectAuthError(
|
|
41
59
|
promise: Promise<unknown>,
|
|
42
60
|
code: AuthStorageErrorCode
|
|
@@ -851,8 +869,7 @@ export function runAuthStorageContractSuite<TStorage extends AuthStorage>(
|
|
|
851
869
|
projectId,
|
|
852
870
|
name: "Local CLI",
|
|
853
871
|
kind: "personal",
|
|
854
|
-
|
|
855
|
-
subjectId: "usr_1",
|
|
872
|
+
subject: { type: "user", id: "usr_1" },
|
|
856
873
|
tokenHash: "hash-personal",
|
|
857
874
|
groupIds: ["commercial", "commercial", "finance"],
|
|
858
875
|
createdAt: at("2026-05-14T10:01:00.000Z"),
|
|
@@ -893,8 +910,7 @@ export function runAuthStorageContractSuite<TStorage extends AuthStorage>(
|
|
|
893
910
|
projectId,
|
|
894
911
|
name: "Sandbox agent",
|
|
895
912
|
kind: "serviceAccount",
|
|
896
|
-
|
|
897
|
-
subjectId: "svc_ingest",
|
|
913
|
+
subject: { type: "serviceAccount", id: "svc_ingest" },
|
|
898
914
|
tokenHash: "hash-service",
|
|
899
915
|
createdAt: at("2026-05-14T10:04:00.000Z"),
|
|
900
916
|
expiresAt: at("2026-05-21T10:04:00.000Z"),
|
|
@@ -902,8 +918,7 @@ export function runAuthStorageContractSuite<TStorage extends AuthStorage>(
|
|
|
902
918
|
await expect(
|
|
903
919
|
storage.accessTokens.list({
|
|
904
920
|
projectId,
|
|
905
|
-
|
|
906
|
-
subjectId: "svc_ingest",
|
|
921
|
+
subject: { type: "serviceAccount", id: "svc_ingest" },
|
|
907
922
|
})
|
|
908
923
|
).resolves.toMatchObject({
|
|
909
924
|
accessTokens: [{ id: "tok_service" }],
|
|
@@ -978,8 +993,7 @@ export function runAuthStorageContractSuite<TStorage extends AuthStorage>(
|
|
|
978
993
|
projectId,
|
|
979
994
|
name: `Token by ${principal.type}`,
|
|
980
995
|
kind: "personal",
|
|
981
|
-
|
|
982
|
-
subjectId: "usr_creator",
|
|
996
|
+
subject: { type: "user", id: "usr_creator" },
|
|
983
997
|
tokenHash: `hash-${tokenId}`,
|
|
984
998
|
createdByPrincipal: principal,
|
|
985
999
|
createdBySessionId: "ses_creator",
|
|
@@ -1019,8 +1033,7 @@ export function runAuthStorageContractSuite<TStorage extends AuthStorage>(
|
|
|
1019
1033
|
projectId,
|
|
1020
1034
|
name: "Touch token",
|
|
1021
1035
|
kind: "personal",
|
|
1022
|
-
|
|
1023
|
-
subjectId: "usr_1",
|
|
1036
|
+
subject: { type: "user", id: "usr_1" },
|
|
1024
1037
|
tokenHash: "hash-touch",
|
|
1025
1038
|
createdAt: at("2026-05-14T10:00:00.000Z"),
|
|
1026
1039
|
expiresAt: at("2026-05-21T10:00:00.000Z"),
|
|
@@ -1066,8 +1079,7 @@ export function runAuthStorageContractSuite<TStorage extends AuthStorage>(
|
|
|
1066
1079
|
projectId,
|
|
1067
1080
|
name: `Token ${id}`,
|
|
1068
1081
|
kind: "personal",
|
|
1069
|
-
|
|
1070
|
-
subjectId: "usr_1",
|
|
1082
|
+
subject: { type: "user", id: "usr_1" },
|
|
1071
1083
|
tokenHash: `hash-${id}`,
|
|
1072
1084
|
createdAt: at(`2026-05-14T10:0${index}:00.000Z`),
|
|
1073
1085
|
expiresAt: at(`2026-05-21T10:0${index}:00.000Z`),
|
|
@@ -1182,8 +1194,7 @@ export function runAuthStorageContractSuite<TStorage extends AuthStorage>(
|
|
|
1182
1194
|
projectId,
|
|
1183
1195
|
name: "Bad kind",
|
|
1184
1196
|
kind: "serviceAccount",
|
|
1185
|
-
|
|
1186
|
-
subjectId: "usr_1",
|
|
1197
|
+
subject: { type: "user", id: "usr_1" },
|
|
1187
1198
|
tokenHash: "hash",
|
|
1188
1199
|
createdAt: at("2026-05-14T10:00:00.000Z"),
|
|
1189
1200
|
expiresAt: at("2026-05-21T10:00:00.000Z"),
|
|
@@ -1196,8 +1207,7 @@ export function runAuthStorageContractSuite<TStorage extends AuthStorage>(
|
|
|
1196
1207
|
projectId,
|
|
1197
1208
|
name: "Missing subject",
|
|
1198
1209
|
kind: "serviceAccount",
|
|
1199
|
-
|
|
1200
|
-
subjectId: "svc_missing",
|
|
1210
|
+
subject: { type: "serviceAccount", id: "svc_missing" },
|
|
1201
1211
|
tokenHash: "hash",
|
|
1202
1212
|
createdAt: at("2026-05-14T10:00:00.000Z"),
|
|
1203
1213
|
expiresAt: at("2026-05-21T10:00:00.000Z"),
|
|
@@ -1316,11 +1326,11 @@ export function runAuthStorageContractSuite<TStorage extends AuthStorage>(
|
|
|
1316
1326
|
})
|
|
1317
1327
|
})
|
|
1318
1328
|
|
|
1319
|
-
test("authorizes a device and atomically
|
|
1329
|
+
test("authorizes a device and atomically starts its bearer session", async () => {
|
|
1320
1330
|
await withStorage(async (storage) => {
|
|
1321
1331
|
await createUser(storage)
|
|
1322
1332
|
await storage.sessions.create({
|
|
1323
|
-
id: "
|
|
1333
|
+
id: "ses_browser",
|
|
1324
1334
|
projectId,
|
|
1325
1335
|
userId: "usr_1",
|
|
1326
1336
|
strategyId: "magic-link",
|
|
@@ -1335,69 +1345,146 @@ export function runAuthStorageContractSuite<TStorage extends AuthStorage>(
|
|
|
1335
1345
|
deviceCodeHash: "device-code-hash",
|
|
1336
1346
|
userCode: "BCDF-HJKM",
|
|
1337
1347
|
clientName: "sixb CLI",
|
|
1338
|
-
tokenName: "codex",
|
|
1339
|
-
tokenExpiresAt: at("2026-08-12T10:00:00.000Z"),
|
|
1340
1348
|
createdAt: at("2026-05-14T10:00:00.000Z"),
|
|
1341
1349
|
expiresAt: at("2026-05-14T10:10:00.000Z"),
|
|
1342
1350
|
})
|
|
1343
1351
|
|
|
1344
1352
|
await expect(
|
|
1345
1353
|
storage.deviceAuthorizations.getByUserCode({ projectId, userCode: "BCDF-HJKM" })
|
|
1346
|
-
).resolves.toMatchObject({ id: "dva_1", status: "pending" })
|
|
1354
|
+
).resolves.toMatchObject({ id: "dva_1", status: "pending", clientName: "sixb CLI" })
|
|
1347
1355
|
await storage.deviceAuthorizations.approve({
|
|
1348
1356
|
projectId,
|
|
1349
1357
|
id: "dva_1",
|
|
1350
1358
|
userId: "usr_1",
|
|
1351
|
-
sessionId: "
|
|
1359
|
+
sessionId: "ses_browser",
|
|
1352
1360
|
approvedAt: at("2026-05-14T10:01:00.000Z"),
|
|
1353
1361
|
})
|
|
1354
1362
|
|
|
1355
|
-
const
|
|
1356
|
-
projectId,
|
|
1357
|
-
id: "dva_1",
|
|
1358
|
-
deviceCodeHash: "device-code-hash",
|
|
1359
|
-
completedAt: at("2026-05-14T10:02:00.000Z"),
|
|
1360
|
-
accessToken: {
|
|
1361
|
-
id: "tok_device",
|
|
1362
|
-
projectId,
|
|
1363
|
-
name: "codex",
|
|
1364
|
-
kind: "personal",
|
|
1365
|
-
subjectType: "user",
|
|
1366
|
-
subjectId: "usr_1",
|
|
1367
|
-
tokenHash: "access-token-hash",
|
|
1368
|
-
createdByPrincipal: { type: "user", id: "usr_1" },
|
|
1369
|
-
createdBySessionId: "ses_device",
|
|
1370
|
-
createdAt: at("2026-05-14T10:02:00.000Z"),
|
|
1371
|
-
expiresAt: at("2026-08-12T10:00:00.000Z"),
|
|
1372
|
-
},
|
|
1373
|
-
})
|
|
1374
|
-
|
|
1375
|
-
expect(completed.authorization).toMatchObject({ status: "consumed" })
|
|
1376
|
-
expect(completed.accessToken).toMatchObject({ id: "tok_device", subjectId: "usr_1" })
|
|
1377
|
-
await expectAuthError(
|
|
1363
|
+
const complete = (id: string) =>
|
|
1378
1364
|
storage.completeDeviceAuthorization({
|
|
1379
1365
|
projectId,
|
|
1380
1366
|
id: "dva_1",
|
|
1381
1367
|
deviceCodeHash: "device-code-hash",
|
|
1382
|
-
completedAt: at("2026-05-14T10:
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1368
|
+
completedAt: at("2026-05-14T10:02:00.000Z"),
|
|
1369
|
+
session: bearerSessionInput(id),
|
|
1370
|
+
})
|
|
1371
|
+
const completed = await complete("ses_cli")
|
|
1372
|
+
|
|
1373
|
+
expect(completed.authorization).toMatchObject({ status: "consumed" })
|
|
1374
|
+
expect(completed.session).toMatchObject({
|
|
1375
|
+
id: "ses_cli",
|
|
1376
|
+
userId: "usr_1",
|
|
1377
|
+
bearer: { clientName: "sixb CLI", refreshTokenHash: "refresh-1" },
|
|
1378
|
+
})
|
|
1379
|
+
await expectAuthError(complete("ses_cli_2"), "invalid_device_authorization")
|
|
1380
|
+
await expect(storage.sessions.getById({ projectId, id: "ses_cli_2" })).resolves.toBeNull()
|
|
1381
|
+
})
|
|
1382
|
+
})
|
|
1383
|
+
|
|
1384
|
+
test("keeps bearer and cookie session credentials apart", async () => {
|
|
1385
|
+
await withStorage(async (storage) => {
|
|
1386
|
+
await createUser(storage)
|
|
1387
|
+
await storage.sessions.create(bearerSessionInput("ses_cli"))
|
|
1388
|
+
await storage.sessions.create({
|
|
1389
|
+
...bearerSessionInput("ses_cookie"),
|
|
1390
|
+
tokenHash: "cookie-hash",
|
|
1391
|
+
bearer: undefined,
|
|
1392
|
+
})
|
|
1393
|
+
const now = at("2026-05-14T10:05:00.000Z")
|
|
1394
|
+
|
|
1395
|
+
await expect(
|
|
1396
|
+
storage.sessions.findValidByAccessTokenHash({
|
|
1397
|
+
projectId,
|
|
1398
|
+
id: "ses_cli",
|
|
1399
|
+
tokenHash: "access-1",
|
|
1400
|
+
now,
|
|
1401
|
+
})
|
|
1402
|
+
).resolves.toMatchObject({ id: "ses_cli" })
|
|
1403
|
+
// A bearer access token never works as a cookie secret, and a cookie never as a token.
|
|
1404
|
+
await expect(
|
|
1405
|
+
storage.sessions.findValidByTokenHash({
|
|
1406
|
+
projectId,
|
|
1407
|
+
id: "ses_cli",
|
|
1408
|
+
audience: "atlas",
|
|
1409
|
+
tokenHash: "access-1",
|
|
1410
|
+
now,
|
|
1411
|
+
})
|
|
1412
|
+
).resolves.toBeNull()
|
|
1398
1413
|
await expect(
|
|
1399
|
-
storage.
|
|
1414
|
+
storage.sessions.findValidByAccessTokenHash({
|
|
1415
|
+
projectId,
|
|
1416
|
+
id: "ses_cookie",
|
|
1417
|
+
tokenHash: "cookie-hash",
|
|
1418
|
+
now,
|
|
1419
|
+
})
|
|
1400
1420
|
).resolves.toBeNull()
|
|
1421
|
+
// The access token expires before its session.
|
|
1422
|
+
await expect(
|
|
1423
|
+
storage.sessions.findValidByAccessTokenHash({
|
|
1424
|
+
projectId,
|
|
1425
|
+
id: "ses_cli",
|
|
1426
|
+
tokenHash: "access-1",
|
|
1427
|
+
now: at("2026-05-14T10:15:00.000Z"),
|
|
1428
|
+
})
|
|
1429
|
+
).resolves.toBeNull()
|
|
1430
|
+
})
|
|
1431
|
+
})
|
|
1432
|
+
|
|
1433
|
+
test("rotates refresh tokens, tolerates a lost response, and revokes on reuse", async () => {
|
|
1434
|
+
await withStorage(async (storage) => {
|
|
1435
|
+
await createUser(storage)
|
|
1436
|
+
await storage.sessions.create({
|
|
1437
|
+
...bearerSessionInput("ses_cli"),
|
|
1438
|
+
absoluteExpiresAt: at("2026-06-20T00:00:00.000Z"),
|
|
1439
|
+
})
|
|
1440
|
+
const rotate = (refreshTokenHash: string, now: string, generation: number) =>
|
|
1441
|
+
storage.sessions.rotateRefreshToken({
|
|
1442
|
+
projectId,
|
|
1443
|
+
id: "ses_cli",
|
|
1444
|
+
refreshTokenHash,
|
|
1445
|
+
now: at(now),
|
|
1446
|
+
reuseGraceMs: 60_000,
|
|
1447
|
+
next: {
|
|
1448
|
+
tokenHash: `access-${generation}`,
|
|
1449
|
+
accessExpiresAt: new Date(at(now).getTime() + 15 * 60_000),
|
|
1450
|
+
refreshTokenHash: `refresh-${generation}`,
|
|
1451
|
+
expiresAt: at("2026-07-01T00:00:00.000Z"),
|
|
1452
|
+
},
|
|
1453
|
+
})
|
|
1454
|
+
|
|
1455
|
+
const rotated = await rotate("refresh-1", "2026-05-15T10:00:00.000Z", 2)
|
|
1456
|
+
expect(rotated).toMatchObject({
|
|
1457
|
+
status: "rotated",
|
|
1458
|
+
session: {
|
|
1459
|
+
tokenHash: "access-2",
|
|
1460
|
+
bearer: { refreshTokenHash: "refresh-2", previousRefreshTokenHash: "refresh-1" },
|
|
1461
|
+
},
|
|
1462
|
+
})
|
|
1463
|
+
// The idle deadline moves, but never past the absolute one.
|
|
1464
|
+
expect(rotated.status === "rotated" && rotated.session.expiresAt.toISOString()).toBe(
|
|
1465
|
+
"2026-06-20T00:00:00.000Z"
|
|
1466
|
+
)
|
|
1467
|
+
// The response was lost; the client retries with the token it still has.
|
|
1468
|
+
await expect(rotate("refresh-1", "2026-05-15T10:00:30.000Z", 3)).resolves.toMatchObject({
|
|
1469
|
+
status: "rotated",
|
|
1470
|
+
session: { bearer: { refreshTokenHash: "refresh-3" } },
|
|
1471
|
+
})
|
|
1472
|
+
// An unknown token fails without touching the session.
|
|
1473
|
+
await expect(rotate("guess", "2026-05-15T10:01:00.000Z", 4)).resolves.toEqual({
|
|
1474
|
+
status: "invalid",
|
|
1475
|
+
})
|
|
1476
|
+
expect((await storage.sessions.getById({ projectId, id: "ses_cli" }))?.revokedAt).toBe(
|
|
1477
|
+
undefined
|
|
1478
|
+
)
|
|
1479
|
+
// A replaced token after the grace window means a copy is in use: end the session.
|
|
1480
|
+
await expect(rotate("refresh-2", "2026-05-15T10:05:00.000Z", 4)).resolves.toEqual({
|
|
1481
|
+
status: "reused",
|
|
1482
|
+
})
|
|
1483
|
+
await expect(rotate("refresh-3", "2026-05-15T10:05:01.000Z", 5)).resolves.toEqual({
|
|
1484
|
+
status: "invalid",
|
|
1485
|
+
})
|
|
1486
|
+
const session = await storage.sessions.getById({ projectId, id: "ses_cli" })
|
|
1487
|
+
expect(session?.revokedAt).toBeInstanceOf(Date)
|
|
1401
1488
|
})
|
|
1402
1489
|
})
|
|
1403
1490
|
|
|
@@ -402,8 +402,7 @@ async function seedAuth(auth: AuthStorage): Promise<void> {
|
|
|
402
402
|
projectId,
|
|
403
403
|
name: "Service token",
|
|
404
404
|
kind: "serviceAccount",
|
|
405
|
-
|
|
406
|
-
subjectId: "service-one",
|
|
405
|
+
subject: { type: "serviceAccount", id: "service-one" },
|
|
407
406
|
tokenHash: "service-token-hash",
|
|
408
407
|
createdAt,
|
|
409
408
|
expiresAt,
|
package/src/testing/execution.ts
CHANGED
|
@@ -2,7 +2,6 @@ import type { AuthorizationContext } from "../authorization"
|
|
|
2
2
|
import { createTestingScope } from "../execution/scopes"
|
|
3
3
|
import type { ExecutionScope } from "../execution/types"
|
|
4
4
|
import { bindModelExecutionAttempt } from "../models/execution/binding"
|
|
5
|
-
import type { OntologySource } from "../ontology"
|
|
6
5
|
import { SixbHost, type SixbHostOptions } from "../runtime/host"
|
|
7
6
|
import { isBoundSixb, type Sixb } from "../runtime/sixb"
|
|
8
7
|
|
|
@@ -26,12 +25,10 @@ export interface TestExecutionHost {
|
|
|
26
25
|
withScope(scope: ExecutionScope): object
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
export function createTestSixb
|
|
30
|
-
|
|
31
|
-
>(
|
|
32
|
-
hostOrOptions: TestExecutionHost | SixbHostOptions<TOntologySources>,
|
|
28
|
+
export function createTestSixb(
|
|
29
|
+
hostOrOptions: TestExecutionHost | SixbHostOptions,
|
|
33
30
|
options: TestExecutionOptions = {}
|
|
34
|
-
): Sixb
|
|
31
|
+
): Sixb {
|
|
35
32
|
const host: TestExecutionHost =
|
|
36
33
|
"withScope" in hostOrOptions ? hostOrOptions : new SixbHost(hostOrOptions)
|
|
37
34
|
const sixb = host.withScope(
|
|
@@ -43,7 +40,7 @@ export function createTestSixb<
|
|
|
43
40
|
...(options.correlationId === undefined ? {} : { correlationId: options.correlationId }),
|
|
44
41
|
})
|
|
45
42
|
)
|
|
46
|
-
if (!isBoundSixb
|
|
43
|
+
if (!isBoundSixb(sixb)) {
|
|
47
44
|
throw new Error("[Sixb] Test host did not return an execution-bound Sixb SDK.")
|
|
48
45
|
}
|
|
49
46
|
bindModelExecutionAttempt(sixb.models, {
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test"
|
|
2
|
+
import type { Principal } from "../auth"
|
|
3
|
+
import type { BlobUploadSession, FileRef, SignedBlobUploadPart } from "../blob-storage"
|
|
4
|
+
import {
|
|
5
|
+
type CreateFileUploadSessionInput,
|
|
6
|
+
DEFAULT_FILE_UPLOAD_TERMINAL_SESSION_TTL_MS,
|
|
7
|
+
type FileUploadSessionStore,
|
|
8
|
+
} from "../storage/file-upload-sessions"
|
|
9
|
+
|
|
10
|
+
export interface FileUploadSessionStorageContractSuiteOptions<
|
|
11
|
+
TStorage extends FileUploadSessionStore = FileUploadSessionStore,
|
|
12
|
+
> {
|
|
13
|
+
readonly createStorage: () => TStorage | Promise<TStorage>
|
|
14
|
+
readonly cleanup?: (storage: TStorage) => void | Promise<void>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const HOUR_MS = 60 * 60 * 1000
|
|
18
|
+
const projectId = "file-upload-contract"
|
|
19
|
+
const principal: Principal = { type: "user", id: "usr_contract" }
|
|
20
|
+
const fileRef: FileRef = {
|
|
21
|
+
blobId: `blob_${"a".repeat(64)}`,
|
|
22
|
+
digest: `sha256:${"a".repeat(64)}`,
|
|
23
|
+
sizeBytes: 3,
|
|
24
|
+
fileName: "report.pdf",
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Provider-neutral lifecycle, retention, and abandoned-upload contract for file upload
|
|
29
|
+
* sessions. Stores read their own clock, so fixtures place `expiresAt` relative to the
|
|
30
|
+
* real time instead of controlling it.
|
|
31
|
+
*/
|
|
32
|
+
export function runFileUploadSessionStorageContractSuite<TStorage extends FileUploadSessionStore>(
|
|
33
|
+
label: string,
|
|
34
|
+
options: FileUploadSessionStorageContractSuiteOptions<TStorage>
|
|
35
|
+
): void {
|
|
36
|
+
const withStorage = async (run: (storage: TStorage) => Promise<void>): Promise<void> => {
|
|
37
|
+
const storage = await options.createStorage()
|
|
38
|
+
try {
|
|
39
|
+
await run(storage)
|
|
40
|
+
} finally {
|
|
41
|
+
await options.cleanup?.(storage)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
describe(label, () => {
|
|
46
|
+
test("round-trips every field, including provider fields it does not know", async () => {
|
|
47
|
+
await withStorage(async (storage) => {
|
|
48
|
+
// Provider-specific session fields must survive the JSON round-trip.
|
|
49
|
+
const providerUpload = { ...multipart("upload_roundtrip"), partReceipt: "etag" as const }
|
|
50
|
+
const input = sessionInput("upload_roundtrip", {
|
|
51
|
+
fileName: "report.pdf",
|
|
52
|
+
mediaType: "application/pdf",
|
|
53
|
+
logicalPath: "reports/q3.pdf",
|
|
54
|
+
expectedSizeBytes: 3,
|
|
55
|
+
expectedDigest: fileRef.digest,
|
|
56
|
+
providerUpload,
|
|
57
|
+
})
|
|
58
|
+
const created = await storage.create(input)
|
|
59
|
+
|
|
60
|
+
expect(created).toMatchObject({ status: "pending", principal })
|
|
61
|
+
const read = await storage.getForPrincipal("upload_roundtrip", principal)
|
|
62
|
+
expect(read).toEqual(created)
|
|
63
|
+
expect(read.providerUpload?.expiresAt).toBeInstanceOf(Date)
|
|
64
|
+
expect(read.providerUpload).toMatchObject({ partReceipt: "etag" })
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test("hides a session from other principals and unknown ids", async () => {
|
|
69
|
+
await withStorage(async (storage) => {
|
|
70
|
+
await storage.create(sessionInput("upload_private"))
|
|
71
|
+
|
|
72
|
+
await expect(
|
|
73
|
+
storage.getForPrincipal("upload_private", { type: "user", id: "usr_other" })
|
|
74
|
+
).rejects.toMatchObject({ reason: "not_found" })
|
|
75
|
+
await expect(storage.getForPrincipal("upload_missing", principal)).rejects.toMatchObject({
|
|
76
|
+
reason: "not_found",
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
test("rejects a duplicate id", async () => {
|
|
82
|
+
await withStorage(async (storage) => {
|
|
83
|
+
await storage.create(sessionInput("upload_duplicate"))
|
|
84
|
+
await expect(storage.create(sessionInput("upload_duplicate"))).rejects.toThrow(
|
|
85
|
+
"already exists"
|
|
86
|
+
)
|
|
87
|
+
})
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
test("keeps signed parts unique and ordered by part number", async () => {
|
|
91
|
+
await withStorage(async (storage) => {
|
|
92
|
+
await storage.create(
|
|
93
|
+
sessionInput("upload_parts", { providerUpload: multipart("upload_parts") })
|
|
94
|
+
)
|
|
95
|
+
// Insertion order differs from sorted order at every step, so dropping the sort fails.
|
|
96
|
+
await storage.addSignedPart("upload_parts", signedPart(3))
|
|
97
|
+
await storage.addSignedPart("upload_parts", signedPart(1))
|
|
98
|
+
await storage.addSignedPart("upload_parts", signedPart(2))
|
|
99
|
+
const updated = await storage.addSignedPart("upload_parts", signedPart(2, "replaced"))
|
|
100
|
+
|
|
101
|
+
expect(updated.signedParts.map((part) => [part.partNumber, part.url])).toEqual([
|
|
102
|
+
[1, "https://blob.test/part-1"],
|
|
103
|
+
[2, "https://blob.test/part-2-replaced"],
|
|
104
|
+
[3, "https://blob.test/part-3"],
|
|
105
|
+
])
|
|
106
|
+
const read = await storage.getForPrincipal("upload_parts", principal)
|
|
107
|
+
expect(read.signedParts).toEqual(updated.signedParts)
|
|
108
|
+
expect(read.signedParts[0]?.expiresAt).toBeInstanceOf(Date)
|
|
109
|
+
})
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
test("does not lose a part signed concurrently with another", async () => {
|
|
113
|
+
await withStorage(async (storage) => {
|
|
114
|
+
await storage.create(
|
|
115
|
+
sessionInput("upload_race", { providerUpload: multipart("upload_race") })
|
|
116
|
+
)
|
|
117
|
+
await Promise.all(
|
|
118
|
+
[1, 2, 3, 4, 5].map((n) => storage.addSignedPart("upload_race", signedPart(n)))
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
const read = await storage.getForPrincipal("upload_race", principal)
|
|
122
|
+
expect(read.signedParts.map((part) => part.partNumber)).toEqual([1, 2, 3, 4, 5])
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
test("moves through markUploaded to one terminal state", async () => {
|
|
127
|
+
await withStorage(async (storage) => {
|
|
128
|
+
await storage.create(sessionInput("upload_done"))
|
|
129
|
+
const uploaded = await storage.markUploaded("upload_done", fileRef)
|
|
130
|
+
expect(uploaded).toMatchObject({ status: "pending", fileRef })
|
|
131
|
+
|
|
132
|
+
const completed = await storage.complete("upload_done", fileRef)
|
|
133
|
+
expect(completed.status).toBe("completed")
|
|
134
|
+
expect(completed.completedAt).toBeInstanceOf(Date)
|
|
135
|
+
await expect(storage.complete("upload_done", fileRef)).rejects.toMatchObject({
|
|
136
|
+
reason: "already_completed",
|
|
137
|
+
})
|
|
138
|
+
await expect(storage.abort("upload_done")).rejects.toMatchObject({
|
|
139
|
+
reason: "already_completed",
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
await storage.create(sessionInput("upload_cancelled"))
|
|
143
|
+
expect((await storage.abort("upload_cancelled")).status).toBe("aborted")
|
|
144
|
+
await expect(storage.abort("upload_cancelled")).rejects.toMatchObject({
|
|
145
|
+
reason: "already_aborted",
|
|
146
|
+
})
|
|
147
|
+
})
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
test("checks expiry at the gate only, so a request that passed it can finish", async () => {
|
|
151
|
+
await withStorage(async (storage) => {
|
|
152
|
+
// Provider uploads keep both rows unreapable while pending.
|
|
153
|
+
for (const id of ["upload_late", "upload_abort_late"]) {
|
|
154
|
+
await storage.create(
|
|
155
|
+
sessionInput(id, { expiresAt: ago(HOUR_MS), providerUpload: multipart(id) })
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
await expect(storage.getForPrincipal("upload_late", principal)).rejects.toMatchObject({
|
|
160
|
+
reason: "expired",
|
|
161
|
+
})
|
|
162
|
+
// Transitions run after slow blob I/O that began before `expiresAt`.
|
|
163
|
+
await storage.addSignedPart("upload_late", signedPart(1))
|
|
164
|
+
await storage.markUploaded("upload_late", fileRef)
|
|
165
|
+
expect((await storage.complete("upload_late", fileRef)).status).toBe("completed")
|
|
166
|
+
expect((await storage.abort("upload_abort_late")).status).toBe("aborted")
|
|
167
|
+
})
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
test("lists abandoned sessions for one project only", async () => {
|
|
171
|
+
await withStorage(async (storage) => {
|
|
172
|
+
await storage.create(
|
|
173
|
+
sessionInput("upload_ours", {
|
|
174
|
+
expiresAt: ago(HOUR_MS),
|
|
175
|
+
providerUpload: multipart("ours"),
|
|
176
|
+
})
|
|
177
|
+
)
|
|
178
|
+
await storage.create(
|
|
179
|
+
sessionInput("upload_theirs", {
|
|
180
|
+
projectId: "other-project",
|
|
181
|
+
expiresAt: ago(HOUR_MS),
|
|
182
|
+
providerUpload: multipart("theirs"),
|
|
183
|
+
})
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
const ids = (await storage.listAbandoned({ projectId, now: new Date(), limit: 10 })).map(
|
|
187
|
+
(session) => session.id
|
|
188
|
+
)
|
|
189
|
+
expect(ids).toEqual(["upload_ours"])
|
|
190
|
+
})
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
test("never deletes an abandoned session, on read or on cleanup", async () => {
|
|
194
|
+
await withStorage(async (storage) => {
|
|
195
|
+
await storage.create(
|
|
196
|
+
sessionInput("upload_abandoned", {
|
|
197
|
+
expiresAt: ago(HOUR_MS),
|
|
198
|
+
providerUpload: multipart("upload_abandoned"),
|
|
199
|
+
})
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
// Reading an expired session must not delete it: nothing would abort its provider upload.
|
|
203
|
+
await expect(storage.getForPrincipal("upload_abandoned", principal)).rejects.toMatchObject({
|
|
204
|
+
reason: "expired",
|
|
205
|
+
})
|
|
206
|
+
expect(await storage.cleanupExpired(later(HOUR_MS))).toBe(0)
|
|
207
|
+
expect(
|
|
208
|
+
(await storage.listAbandoned({ projectId, now: new Date(), limit: 10 })).map(
|
|
209
|
+
(session) => session.id
|
|
210
|
+
)
|
|
211
|
+
).toEqual(["upload_abandoned"])
|
|
212
|
+
})
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
test("lists only abandoned sessions, oldest expiry first, within the limit", async () => {
|
|
216
|
+
await withStorage(async (storage) => {
|
|
217
|
+
await storage.create(
|
|
218
|
+
sessionInput("upload_newer", { expiresAt: ago(HOUR_MS), providerUpload: multipart("n") })
|
|
219
|
+
)
|
|
220
|
+
await storage.create(
|
|
221
|
+
sessionInput("upload_older", {
|
|
222
|
+
expiresAt: ago(2 * HOUR_MS),
|
|
223
|
+
providerUpload: multipart("o"),
|
|
224
|
+
})
|
|
225
|
+
)
|
|
226
|
+
await storage.create(sessionInput("upload_live", { providerUpload: multipart("live") }))
|
|
227
|
+
await storage.create(sessionInput("upload_server", { expiresAt: ago(HOUR_MS) }))
|
|
228
|
+
await storage.create(
|
|
229
|
+
sessionInput("upload_aborted", {
|
|
230
|
+
expiresAt: ago(HOUR_MS),
|
|
231
|
+
providerUpload: multipart("a"),
|
|
232
|
+
})
|
|
233
|
+
)
|
|
234
|
+
await storage.abort("upload_aborted")
|
|
235
|
+
|
|
236
|
+
const ids = async (limit: number) =>
|
|
237
|
+
(await storage.listAbandoned({ projectId, now: new Date(), limit })).map(
|
|
238
|
+
(session) => session.id
|
|
239
|
+
)
|
|
240
|
+
expect(await ids(10)).toEqual(["upload_older", "upload_newer"])
|
|
241
|
+
expect(await ids(1)).toEqual(["upload_older"])
|
|
242
|
+
const [oldest] = await storage.listAbandoned({ projectId, now: new Date(), limit: 1 })
|
|
243
|
+
expect(oldest?.providerUpload?.expiresAt).toBeInstanceOf(Date)
|
|
244
|
+
await expect(
|
|
245
|
+
storage.listAbandoned({ projectId, now: new Date(), limit: 0 })
|
|
246
|
+
).rejects.toThrow("positive integer")
|
|
247
|
+
})
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
test("reaps expired sessions without a provider upload and terminal ones after their TTL", async () => {
|
|
251
|
+
await withStorage(async (storage) => {
|
|
252
|
+
await storage.create(sessionInput("upload_live"))
|
|
253
|
+
await storage.create(sessionInput("upload_finished"))
|
|
254
|
+
await storage.complete("upload_finished", fileRef)
|
|
255
|
+
// Created last: a store may reap opportunistically on `create`.
|
|
256
|
+
await storage.create(sessionInput("upload_expired", { expiresAt: ago(HOUR_MS) }))
|
|
257
|
+
|
|
258
|
+
expect(await storage.cleanupExpired(new Date())).toBe(1)
|
|
259
|
+
await expect(storage.getForPrincipal("upload_expired", principal)).rejects.toMatchObject({
|
|
260
|
+
reason: "not_found",
|
|
261
|
+
})
|
|
262
|
+
// A completed session outlives its expiry so a retried `complete` stays idempotent.
|
|
263
|
+
expect((await storage.getForPrincipal("upload_finished", principal)).status).toBe(
|
|
264
|
+
"completed"
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
expect(
|
|
268
|
+
await storage.cleanupExpired(later(DEFAULT_FILE_UPLOAD_TERMINAL_SESSION_TTL_MS + 60_000))
|
|
269
|
+
).toBe(1)
|
|
270
|
+
await expect(storage.getForPrincipal("upload_finished", principal)).rejects.toMatchObject({
|
|
271
|
+
reason: "not_found",
|
|
272
|
+
})
|
|
273
|
+
expect((await storage.getForPrincipal("upload_live", principal)).status).toBe("pending")
|
|
274
|
+
})
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
test("reaps an abandoned session once it has been aborted", async () => {
|
|
278
|
+
await withStorage(async (storage) => {
|
|
279
|
+
await storage.create(
|
|
280
|
+
sessionInput("upload_swept", { expiresAt: ago(HOUR_MS), providerUpload: multipart("s") })
|
|
281
|
+
)
|
|
282
|
+
await storage.abort("upload_swept")
|
|
283
|
+
|
|
284
|
+
expect(await storage.listAbandoned({ projectId, now: new Date(), limit: 10 })).toEqual([])
|
|
285
|
+
expect(await storage.cleanupExpired(new Date())).toBe(0)
|
|
286
|
+
expect(
|
|
287
|
+
await storage.cleanupExpired(later(DEFAULT_FILE_UPLOAD_TERMINAL_SESSION_TTL_MS + 60_000))
|
|
288
|
+
).toBe(1)
|
|
289
|
+
})
|
|
290
|
+
})
|
|
291
|
+
})
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function sessionInput(
|
|
295
|
+
id: string,
|
|
296
|
+
overrides: Partial<CreateFileUploadSessionInput> = {}
|
|
297
|
+
): CreateFileUploadSessionInput {
|
|
298
|
+
return {
|
|
299
|
+
id,
|
|
300
|
+
projectId,
|
|
301
|
+
principal,
|
|
302
|
+
strategy: overrides.providerUpload?.strategy ?? "server",
|
|
303
|
+
expiresAt: later(HOUR_MS),
|
|
304
|
+
...overrides,
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function multipart(uploadId: string): BlobUploadSession {
|
|
309
|
+
return {
|
|
310
|
+
strategy: "multipart",
|
|
311
|
+
uploadId,
|
|
312
|
+
partSizeBytes: 5 * 1024 * 1024,
|
|
313
|
+
expiresAt: later(HOUR_MS),
|
|
314
|
+
stagingKey: `staging/${uploadId}`,
|
|
315
|
+
providerUploadId: `provider-${uploadId}`,
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function signedPart(partNumber: number, suffix?: string): SignedBlobUploadPart {
|
|
320
|
+
return {
|
|
321
|
+
partNumber,
|
|
322
|
+
method: "PUT",
|
|
323
|
+
url: `https://blob.test/part-${partNumber}${suffix ? `-${suffix}` : ""}`,
|
|
324
|
+
headers: {},
|
|
325
|
+
expiresAt: later(HOUR_MS),
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function ago(ms: number): Date {
|
|
330
|
+
return new Date(Date.now() - ms)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function later(ms: number): Date {
|
|
334
|
+
return new Date(Date.now() + ms)
|
|
335
|
+
}
|