@cosmicdrift/kumiko-framework 0.388.0 → 0.390.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +12 -4
- package/README.md +1 -1
- package/agents/examples/apex-surface-auth.md +2 -3
- package/agents/examples/api-worker-split.md +9 -2
- package/agents/examples/auth-claims.md +1 -1
- package/agents/examples/cross-feature-events.md +12 -12
- package/agents/examples/crypto-shredding-hr.md +2 -2
- package/agents/examples/encrypted-tenant-config.md +1 -1
- package/agents/examples/error-contract.md +12 -7
- package/agents/examples/event-sourcing.md +29 -29
- package/agents/examples/files-post-processing.md +10 -8
- package/agents/examples/golden-path.md +13 -1
- package/agents/examples/inbound-mail-triage.md +1 -0
- package/agents/examples/lane-routing.md +2 -1
- package/agents/examples/legal-pages.md +2 -2
- package/agents/examples/lifecycle-hooks.md +55 -2
- package/agents/examples/list-table-options.md +466 -0
- package/agents/examples/managed-config.md +4 -4
- package/agents/examples/managed-pages.md +1 -1
- package/agents/examples/pdf-audit-export.md +4 -2
- package/agents/examples/relations.md +19 -4
- package/agents/examples/search.md +4 -4
- package/agents/examples/secrets-demo.md +9 -6
- package/agents/examples/state-machine.md +5 -4
- package/agents/examples/tenant-isolation.md +73 -1
- package/agents/examples/tenant-settings.md +1 -1
- package/agents/examples/user-data-rights.md +3 -6
- package/agents/examples/workflow-engine.md +53 -47
- package/agents/examples.md +5 -4
- package/agents/features.md +1 -1
- package/agents/widgets.md +1 -0
- package/dist/api/api-constants.d.ts +1 -0
- package/dist/api/api-constants.js +2 -0
- package/dist/api/auth-middleware.js +1 -1
- package/dist/api/auth-routes-invite.js +2 -1
- package/dist/api/auth-routes-shared.d.ts +2 -0
- package/dist/api/auth-routes-shared.js +5 -0
- package/dist/api/client-error-route.js +2 -3
- package/dist/api/entity-read-access.d.ts +4 -1
- package/dist/api/entity-read-access.js +14 -0
- package/dist/api/export/export-cells-reference.d.ts +9 -0
- package/dist/api/export/export-cells-reference.js +21 -0
- package/dist/api/export/export-cells.d.ts +11 -0
- package/dist/api/export/export-cells.js +136 -0
- package/dist/api/export/export-ciphertext-guard.d.ts +2 -0
- package/dist/api/export/export-ciphertext-guard.js +27 -0
- package/dist/api/export/export-columns.d.ts +31 -0
- package/dist/api/export/export-columns.js +85 -0
- package/dist/api/export/export-errors.d.ts +4 -0
- package/dist/api/export/export-errors.js +14 -0
- package/dist/api/export/export-route.d.ts +4 -0
- package/dist/api/export/export-route.js +75 -0
- package/dist/api/export/export-rows.d.ts +13 -0
- package/dist/api/export/export-rows.js +62 -0
- package/dist/api/export/export-screen.d.ts +13 -0
- package/dist/api/export/export-screen.js +47 -0
- package/dist/api/export/export-xlsx-writer.d.ts +4 -0
- package/dist/api/export/export-xlsx-writer.js +21 -0
- package/dist/api/extra-route.d.ts +7 -1
- package/dist/api/index.d.ts +23 -27
- package/dist/api/index.js +13 -15
- package/dist/api/jwt.js +1 -1
- package/dist/api/observability-middleware.d.ts +1 -1
- package/dist/api/observability-middleware.js +2 -1
- package/dist/api/pii-leak-guard.d.ts +3 -0
- package/dist/api/pii-leak-guard.js +3 -2
- package/dist/api/request-context-internals.d.ts +31 -0
- package/dist/api/request-context-internals.js +11 -0
- package/dist/api/request-context-scopes.d.ts +14 -0
- package/dist/api/request-context-scopes.js +69 -0
- package/dist/api/request-context.d.ts +1 -40
- package/dist/api/request-context.js +22 -51
- package/dist/api/request-id-middleware.d.ts +1 -1
- package/dist/api/route-registrars.d.ts +2 -1
- package/dist/api/route-registrars.js +1 -1
- package/dist/api/routes.d.ts +16 -0
- package/dist/api/routes.js +9 -5
- package/dist/api/server-boot-checks.d.ts +1 -1
- package/dist/api/server-boot-checks.js +2 -2
- package/dist/api/server-event-dispatcher.d.ts +6 -1
- package/dist/api/server-event-dispatcher.js +3 -4
- package/dist/api/server-extra-routes.d.ts +1 -1
- package/dist/api/server-extra-routes.js +5 -1
- package/dist/api/server-middleware.js +3 -1
- package/dist/api/server-routes.d.ts +3 -2
- package/dist/api/server-routes.js +8 -2
- package/dist/api/server-wiring.js +8 -4
- package/dist/api/server.d.ts +2 -1
- package/dist/api/sse-route.d.ts +3 -1
- package/dist/api/sse-route.js +11 -1
- package/dist/api/tenant-scoped-secrets.d.ts +2 -0
- package/dist/api/tenant-scoped-secrets.js +13 -0
- package/dist/api/websocket-route.d.ts +1 -1
- package/dist/auth/index.d.ts +0 -1
- package/dist/auth/roles.d.ts +0 -5
- package/dist/compliance/duration-spec.d.ts +0 -1
- package/dist/compliance/duration-spec.js +0 -5
- package/dist/compliance/index.d.ts +4 -4
- package/dist/compliance/index.js +2 -2
- package/dist/compliance/profiles.d.ts +0 -15
- package/dist/compliance/profiles.js +0 -23
- package/dist/config/index.d.ts +11 -9
- package/dist/config/index.js +13 -1
- package/dist/config/internals.d.ts +9 -0
- package/dist/config/internals.js +1 -0
- package/dist/consumer-cli-internals.d.ts +4 -0
- package/dist/consumer-cli-internals.js +1 -0
- package/dist/consumer-cli.d.ts +1 -4
- package/dist/consumer-cli.js +5 -1
- package/dist/crypto/event-pii.js +1 -1
- package/dist/crypto/index.d.ts +8 -9
- package/dist/crypto/index.js +7 -8
- package/dist/crypto/pg-kms-adapter.d.ts +1 -0
- package/dist/crypto/pg-kms-adapter.js +17 -18
- package/dist/db/aggregate-sql.d.ts +2 -0
- package/dist/db/aggregate-sql.js +10 -0
- package/dist/db/apply-entity-event.d.ts +1 -1
- package/dist/db/apply-entity-event.js +15 -47
- package/dist/db/blind-index-cleanup.js +91 -77
- package/dist/db/closed-connection.js +12 -19
- package/dist/db/collect-table-metas.js +1 -1
- package/dist/db/compound-types.d.ts +1 -1
- package/dist/db/compound-types.js +0 -7
- package/dist/db/config-seed.d.ts +2 -1
- package/dist/db/config-seed.js +6 -1
- package/dist/db/connection.d.ts +7 -6
- package/dist/db/connection.js +43 -24
- package/dist/db/cross-tenant-reads.d.ts +1 -1
- package/dist/db/cross-tenant-reads.js +1 -1
- package/dist/db/dialect.d.ts +0 -5
- package/dist/db/dialect.js +0 -3
- package/dist/db/driver-row-coercion.js +4 -4
- package/dist/db/driver-value-preparation.js +6 -4
- package/dist/db/eagerload.d.ts +2 -1
- package/dist/db/entity-field-encryption.d.ts +1 -1
- package/dist/db/entity-table-meta.d.ts +1 -1
- package/dist/db/event-store-executor-context.d.ts +3 -1
- package/dist/db/event-store-executor-context.js +4 -3
- package/dist/db/event-store-executor-read-aggregate-currencies.d.ts +17 -0
- package/dist/db/event-store-executor-read-aggregate-currencies.js +40 -0
- package/dist/db/event-store-executor-read-aggregate.js +36 -5
- package/dist/db/event-store-executor-read-filter.d.ts +1 -1
- package/dist/db/event-store-executor-read-filter.js +6 -3
- package/dist/db/event-store-executor-read-rows.d.ts +2 -1
- package/dist/db/event-store-executor-read-search.d.ts +2 -1
- package/dist/db/event-store-executor-read-sort.d.ts +2 -1
- package/dist/db/event-store-executor-read.js +2 -2
- package/dist/db/event-store-executor-write-atomic.d.ts +4 -0
- package/dist/db/event-store-executor-write-atomic.js +42 -0
- package/dist/db/event-store-executor-write-steps.d.ts +3 -5
- package/dist/db/event-store-executor-write-steps.js +0 -5
- package/dist/db/event-store-executor-write.js +22 -19
- package/dist/db/event-store-executor.d.ts +1 -1
- package/dist/db/event-store-executor.js +2 -1
- package/dist/db/executor-managed-tables.d.ts +7 -1
- package/dist/db/executor-managed-tables.js +12 -3
- package/dist/db/index.d.ts +29 -28
- package/dist/db/index.js +22 -20
- package/dist/db/known-table-names.d.ts +6 -0
- package/dist/db/known-table-names.js +21 -0
- package/dist/db/list-aggregate-labels.d.ts +1 -1
- package/dist/db/located-timestamp.d.ts +1 -1
- package/dist/db/located-timestamp.js +0 -5
- package/dist/db/migrate-generator.d.ts +17 -1
- package/dist/db/migrate-generator.js +50 -20
- package/dist/db/migrate-primary-key.d.ts +12 -0
- package/dist/db/migrate-primary-key.js +45 -0
- package/dist/db/migrate-rls-diff.d.ts +20 -0
- package/dist/db/migrate-rls-diff.js +61 -0
- package/dist/db/migrate-runner.js +7 -3
- package/dist/db/money.d.ts +1 -1
- package/dist/db/money.js +1 -1
- package/dist/db/parent-ref-clause.d.ts +2 -1
- package/dist/db/pg-error.d.ts +2 -0
- package/dist/db/pg-error.js +37 -21
- package/dist/db/queries/backfill-pii.js +3 -6
- package/dist/db/queries/database-now.js +2 -1
- package/dist/db/queries/ddl.d.ts +3 -0
- package/dist/db/queries/ddl.js +34 -1
- package/dist/db/queries/event-store.js +4 -2
- package/dist/db/queries/event-tenants.d.ts +2 -0
- package/dist/db/queries/event-tenants.js +17 -0
- package/dist/db/queries/rebuild-rls-guard.d.ts +2 -0
- package/dist/db/queries/rebuild-rls-guard.js +29 -0
- package/dist/db/queries/rls-boot-catalog.d.ts +16 -0
- package/dist/db/queries/rls-boot-catalog.js +39 -0
- package/dist/db/queries/rls-catalog.d.ts +6 -0
- package/dist/db/queries/rls-catalog.js +82 -0
- package/dist/db/queries/rls-scope.d.ts +3 -0
- package/dist/db/queries/rls-scope.js +17 -0
- package/dist/db/queries/rls-shape.d.ts +10 -0
- package/dist/db/queries/rls-shape.js +42 -0
- package/dist/db/queries/session-advisory-lock.d.ts +2 -0
- package/dist/db/queries/session-advisory-lock.js +23 -0
- package/dist/db/queries/shadow-swap.d.ts +1 -2
- package/dist/db/queries/shadow-swap.js +11 -28
- package/dist/db/queries/test-stack.d.ts +4 -1
- package/dist/db/queries/test-stack.js +83 -2
- package/dist/db/query.d.ts +14 -0
- package/dist/db/query.js +77 -48
- package/dist/db/reference-data.d.ts +1 -1
- package/dist/db/reference-data.js +20 -3
- package/dist/db/render-ddl.d.ts +6 -2
- package/dist/db/render-ddl.js +7 -7
- package/dist/db/render-rls-ddl.d.ts +35 -0
- package/dist/db/render-rls-ddl.js +127 -0
- package/dist/db/replay-migration-sql.d.ts +3 -1
- package/dist/db/replay-migration-sql.js +22 -5
- package/dist/db/replay-rls.d.ts +25 -0
- package/dist/db/replay-rls.js +156 -0
- package/dist/db/row-level-security-boot-check.d.ts +5 -0
- package/dist/db/row-level-security-boot-check.js +85 -0
- package/dist/db/row-level-security-connection.d.ts +3 -0
- package/dist/db/row-level-security-connection.js +213 -0
- package/dist/db/row-level-security-scope.d.ts +33 -0
- package/dist/db/row-level-security-scope.js +127 -0
- package/dist/db/scope-tenant-db-to-tenant.d.ts +3 -0
- package/dist/db/scope-tenant-db-to-tenant.js +14 -0
- package/dist/db/sql-identifier.d.ts +1 -0
- package/dist/db/sql-identifier.js +3 -0
- package/dist/db/statement-timeout.js +2 -1
- package/dist/db/table-builder.d.ts +2 -1
- package/dist/db/table-builder.js +1 -1
- package/dist/db/table-info.js +1 -1
- package/dist/db/table-push.d.ts +11 -2
- package/dist/db/table-push.js +15 -2
- package/dist/db/tenant-db-runner.d.ts +3 -1
- package/dist/db/tenant-db-runner.js +4 -3
- package/dist/db/tenant-db-scoped-rebind.d.ts +10 -0
- package/dist/db/tenant-db-scoped-rebind.js +33 -0
- package/dist/db/tenant-db-statement-runner.d.ts +13 -0
- package/dist/db/tenant-db-statement-runner.js +48 -0
- package/dist/db/tenant-db-upsert.d.ts +5 -0
- package/dist/db/tenant-db-upsert.js +91 -0
- package/dist/db/tenant-db.d.ts +17 -12
- package/dist/db/tenant-db.js +60 -121
- package/dist/db/tenant-id-filter.d.ts +3 -0
- package/dist/db/tenant-id-filter.js +30 -0
- package/dist/db/transaction-serialization.d.ts +6 -0
- package/dist/db/transaction-serialization.js +60 -0
- package/dist/derivatives/delete-stored-file.js +1 -1
- package/dist/derivatives/index.d.ts +2 -5
- package/dist/derivatives/index.js +2 -3
- package/dist/engine/access.d.ts +2 -1
- package/dist/engine/access.js +1 -1
- package/dist/engine/boot-validator/bundled-lists-table.d.ts +2 -0
- package/dist/engine/boot-validator/bundled-lists-table.js +36 -0
- package/dist/engine/boot-validator/entity-handler.d.ts +2 -1
- package/dist/engine/boot-validator/entity-handler.js +1 -1
- package/dist/engine/boot-validator/entity-list-aggregate-options.d.ts +3 -0
- package/dist/engine/boot-validator/entity-list-aggregate-options.js +23 -0
- package/dist/engine/boot-validator/list-bulk-actions.d.ts +3 -0
- package/dist/engine/boot-validator/list-bulk-actions.js +49 -0
- package/dist/engine/boot-validator/list-column-layout.d.ts +8 -0
- package/dist/engine/boot-validator/list-column-layout.js +41 -0
- package/dist/engine/boot-validator/list-table-aggregate-options.d.ts +24 -0
- package/dist/engine/boot-validator/list-table-aggregate-options.js +145 -0
- package/dist/engine/boot-validator/list-table-aggregate-query.d.ts +11 -0
- package/dist/engine/boot-validator/list-table-aggregate-query.js +31 -0
- package/dist/engine/boot-validator/list-table-export-options.d.ts +1 -0
- package/dist/engine/boot-validator/list-table-export-options.js +27 -0
- package/dist/engine/boot-validator/list-table-options.d.ts +3 -0
- package/dist/engine/boot-validator/list-table-options.js +77 -0
- package/dist/engine/boot-validator/list-table-reject-unknown-keys.d.ts +1 -0
- package/dist/engine/boot-validator/list-table-reject-unknown-keys.js +7 -0
- package/dist/engine/boot-validator/nav.d.ts +3 -1
- package/dist/engine/boot-validator/nav.js +1 -1
- package/dist/engine/boot-validator/ownership.d.ts +2 -1
- package/dist/engine/boot-validator/parent-ref.d.ts +2 -1
- package/dist/engine/boot-validator/projection-list-screens.d.ts +2 -1
- package/dist/engine/boot-validator/projection-list-screens.js +3 -13
- package/dist/engine/boot-validator/query-refs.d.ts +2 -1
- package/dist/engine/boot-validator/related-list-table-rules.d.ts +4 -0
- package/dist/engine/boot-validator/related-list-table-rules.js +42 -0
- package/dist/engine/boot-validator/screens-forms.d.ts +2 -1
- package/dist/engine/boot-validator/screens-kind-entity-list.js +7 -0
- package/dist/engine/boot-validator/screens-kind-projection-list.js +4 -0
- package/dist/engine/boot-validator/screens-kind-shared.d.ts +3 -1
- package/dist/engine/boot-validator/screens-lists.js +12 -2
- package/dist/engine/boot-validator/screens.d.ts +2 -1
- package/dist/engine/boot-validator/workspaces.d.ts +3 -1
- package/dist/engine/bridge-stub.d.ts +5 -2
- package/dist/engine/bridge-stub.js +39 -24
- package/dist/engine/build-app-schema.d.ts +2 -1
- package/dist/engine/build-app-schema.js +9 -1
- package/dist/engine/build-config-feature-schema.js +6 -1
- package/dist/engine/config-helpers.d.ts +2 -2
- package/dist/engine/config-helpers.js +0 -9
- package/dist/engine/constants.d.ts +0 -10
- package/dist/engine/constants.js +0 -8
- package/dist/engine/create-app.js +1 -1
- package/dist/engine/define-feature.d.ts +2 -1
- package/dist/engine/define-feature.js +5 -2
- package/dist/engine/define-handler.d.ts +1 -1
- package/dist/engine/define-step.d.ts +0 -1
- package/dist/engine/define-step.js +0 -3
- package/dist/engine/embedded-derived.d.ts +1 -1
- package/dist/engine/entity-handlers.d.ts +2 -1
- package/dist/engine/entity-handlers.js +7 -7
- package/dist/engine/entity-list-runtime-options.js +3 -1
- package/dist/engine/entity-list-searchability.d.ts +2 -1
- package/dist/engine/event-def.d.ts +2 -1
- package/dist/engine/event-helpers.d.ts +3 -1
- package/dist/engine/event-helpers.js +3 -3
- package/dist/engine/extension-names.d.ts +2 -8
- package/dist/engine/extension-names.js +2 -2
- package/dist/engine/extension-selector-plugins.d.ts +1 -1
- package/dist/engine/extensions/storage-provider.d.ts +1 -2
- package/dist/engine/extensions/user-data.d.ts +0 -8
- package/dist/engine/factories.d.ts +2 -1
- package/dist/engine/feature-builder-state.d.ts +9 -1
- package/dist/engine/feature-builder-state.js +1 -0
- package/dist/engine/feature-changelog.d.ts +1 -1
- package/dist/engine/feature-config-events-jobs.d.ts +4 -1
- package/dist/engine/feature-entity-handlers.d.ts +5 -1
- package/dist/engine/feature-manifest.d.ts +1 -0
- package/dist/engine/feature-manifest.js +2 -1
- package/dist/engine/feature-ui-extensions.d.ts +7 -1
- package/dist/engine/feature-ui-extensions.js +6 -4
- package/dist/engine/field-access.d.ts +3 -1
- package/dist/engine/field-access.js +12 -0
- package/dist/engine/handler-field-references.d.ts +0 -4
- package/dist/engine/index.d.ts +58 -55
- package/dist/engine/index.js +23 -28
- package/dist/engine/instruction-fields.d.ts +1 -1
- package/dist/engine/personal-data-fields.d.ts +1 -1
- package/dist/engine/qualified-name.d.ts +0 -1
- package/dist/engine/read-claim.d.ts +2 -1
- package/dist/engine/registry-facade.js +0 -3
- package/dist/engine/registry-ingest.d.ts +2 -1
- package/dist/engine/registry-ingest.js +1 -2
- package/dist/engine/registry-state.d.ts +12 -2
- package/dist/engine/registry-state.js +2 -3
- package/dist/engine/registry-validate.d.ts +3 -1
- package/dist/engine/registry-validate.js +7 -7
- package/dist/engine/run-in.d.ts +1 -1
- package/dist/engine/run-in.js +0 -1
- package/dist/engine/schema-builder.d.ts +1 -1
- package/dist/engine/schema-builder.js +1 -1
- package/dist/engine/screen-filter-ops.d.ts +2 -1
- package/dist/engine/screen-filter-ops.js +2 -5
- package/dist/engine/soft-delete-cleanup.d.ts +1 -1
- package/dist/engine/soft-delete-cleanup.js +4 -4
- package/dist/engine/state-machine.js +2 -1
- package/dist/engine/steps/_read-source.js +1 -1
- package/dist/engine/steps/aggregate-append-event.js +2 -2
- package/dist/engine/steps/call-feature.js +2 -2
- package/dist/engine/steps/mail-send.js +1 -1
- package/dist/engine/steps/retry.js +1 -1
- package/dist/engine/steps/wait-for-event.js +1 -1
- package/dist/engine/steps/wait.js +1 -1
- package/dist/engine/steps/webhook-send.js +1 -1
- package/dist/engine/strip-disabled-features-from-app-schema.js +7 -3
- package/dist/engine/template-variables.d.ts +2 -1
- package/dist/engine/transfer-adjacency.d.ts +1 -1
- package/dist/engine/types/feature.d.ts +1 -0
- package/dist/engine/types/index.d.ts +8 -30
- package/dist/engine/types/index.js +2 -10
- package/dist/engine/types/screen.d.ts +1 -1
- package/dist/engine/types/screen.js +1 -1
- package/dist/engine/validation.d.ts +2 -1
- package/dist/entrypoint/index.d.ts +9 -35
- package/dist/entrypoint/index.js +10 -1
- package/dist/entrypoint/internals.d.ts +40 -0
- package/dist/entrypoint/internals.js +1 -0
- package/dist/entrypoint/row-level-security-mode-check.d.ts +3 -0
- package/dist/entrypoint/row-level-security-mode-check.js +19 -0
- package/dist/env/dry-run-internals.d.ts +10 -0
- package/dist/env/dry-run-internals.js +1 -0
- package/dist/env/dry-run.d.ts +1 -10
- package/dist/env/dry-run.js +2 -1
- package/dist/env/index.d.ts +1 -85
- package/dist/env/index.js +6 -50
- package/dist/env/internals.d.ts +87 -0
- package/dist/env/internals.js +53 -0
- package/dist/errors/classes.js +2 -2
- package/dist/errors/index.d.ts +5 -14
- package/dist/errors/index.js +4 -9
- package/dist/errors/member-resolution.js +1 -1
- package/dist/errors/reasons.d.ts +0 -1
- package/dist/errors/reasons.js +7 -7
- package/dist/errors/serialize.d.ts +0 -18
- package/dist/errors/serialize.js +0 -27
- package/dist/es-ops/index.d.ts +4 -4
- package/dist/es-ops/index.js +2 -2
- package/dist/es-ops/operations-schema.d.ts +1 -1
- package/dist/es-ops/types.d.ts +4 -5
- package/dist/event-store/admin-api-internals.d.ts +14 -0
- package/dist/event-store/admin-api-internals.js +1 -0
- package/dist/event-store/admin-api.d.ts +1 -14
- package/dist/event-store/admin-api.js +11 -6
- package/dist/event-store/archive.js +4 -2
- package/dist/event-store/errors.js +2 -2
- package/dist/event-store/event-store.d.ts +1 -0
- package/dist/event-store/event-store.js +42 -32
- package/dist/event-store/events-schema.js +4 -1
- package/dist/event-store/index.d.ts +11 -13
- package/dist/event-store/index.js +7 -9
- package/dist/event-store/provenance-append.js +1 -1
- package/dist/event-store/rebuild-dead-letter.js +4 -2
- package/dist/event-store/snapshot.js +4 -3
- package/dist/event-store/stream-scope.d.ts +2 -0
- package/dist/event-store/stream-scope.js +6 -0
- package/dist/event-store/upcaster-dead-letter.js +4 -2
- package/dist/event-store/upcaster.d.ts +2 -1
- package/dist/files/action-form-upload.d.ts +2 -1
- package/dist/files/action-form-upload.js +1 -1
- package/dist/files/assert-file-refs-belong-to-tenant.d.ts +2 -1
- package/dist/files/assert-file-refs-belong-to-tenant.js +1 -1
- package/dist/files/bind-pending-file-refs.d.ts +2 -1
- package/dist/files/bind-pending-file-refs.js +2 -1
- package/dist/files/bind-referenced-files.write.js +1 -1
- package/dist/files/create-file-ref-from-bytes.d.ts +6 -3
- package/dist/files/create-file-ref-from-bytes.js +6 -3
- package/dist/files/create-file-ref.d.ts +6 -2
- package/dist/files/create-file-ref.js +13 -4
- package/dist/files/dispose-removed-file-refs.d.ts +2 -1
- package/dist/files/dispose-removed-file-refs.js +1 -1
- package/dist/files/feature.js +2 -2
- package/dist/files/file-handle.js +1 -1
- package/dist/files/file-routes.d.ts +3 -1
- package/dist/files/file-routes.js +41 -4
- package/dist/files/index.d.ts +11 -13
- package/dist/files/index.js +5 -7
- package/dist/files/load-save-file-refs.d.ts +2 -1
- package/dist/files/load-save-file-refs.js +1 -1
- package/dist/files/provider-resolver.d.ts +6 -4
- package/dist/files/provider-resolver.js +5 -5
- package/dist/files/record-write-check.d.ts +6 -0
- package/dist/files/record-write-check.js +13 -0
- package/dist/files/storage-tracking.js +4 -2
- package/dist/files/sweep-orphaned-uploads.d.ts +1 -1
- package/dist/files/sweep-orphaned-uploads.js +1 -1
- package/dist/files/upload-ledger.d.ts +2 -2
- package/dist/files/upload-ledger.js +4 -4
- package/dist/i18n/index.d.ts +2 -8
- package/dist/i18n/index.js +1 -1
- package/dist/i18n/internals.d.ts +7 -0
- package/dist/i18n/internals.js +1 -0
- package/dist/i18n/required-surface-keys.d.ts +4 -1
- package/dist/i18n/required-surface-keys.js +7 -2
- package/dist/internal/row-level-security.d.ts +3 -0
- package/dist/internal/row-level-security.js +3 -0
- package/dist/internal/stack-support.d.ts +1 -1
- package/dist/internal/stack-support.js +1 -1
- package/dist/internal/testing.d.ts +1 -0
- package/dist/internal/testing.js +10 -6
- package/dist/jobs/index.d.ts +1 -1
- package/dist/jobs/job-append-event.d.ts +12 -0
- package/dist/jobs/job-append-event.js +30 -0
- package/dist/jobs/job-runner-context.d.ts +2 -2
- package/dist/jobs/job-runner-context.js +46 -16
- package/dist/jobs/job-runner-execution.d.ts +1 -1
- package/dist/jobs/job-runner-execution.js +6 -4
- package/dist/jobs/job-runner-gates.d.ts +1 -1
- package/dist/jobs/job-runner-gates.js +0 -1
- package/dist/jobs/job-runner-helpers.d.ts +11 -4
- package/dist/jobs/job-runner-helpers.js +10 -1
- package/dist/jobs/job-runner-scope.d.ts +5 -2
- package/dist/jobs/job-runner-scope.js +6 -6
- package/dist/jobs/job-runner-types.d.ts +2 -1
- package/dist/jobs/job-runner.js +22 -6
- package/dist/jobs/max-per-tenant.d.ts +1 -1
- package/dist/logging/index.d.ts +1 -2
- package/dist/logging/index.js +1 -1
- package/dist/logging/pino-logger.js +1 -1
- package/dist/logging/utils.d.ts +1 -0
- package/dist/logging/utils.js +6 -0
- package/dist/migrations/index.d.ts +3 -3
- package/dist/migrations/index.js +3 -3
- package/dist/migrations/pending-rebuilds.d.ts +1 -1
- package/dist/migrations/pending-rebuilds.js +1 -1
- package/dist/migrations/pii-event-backfill.js +4 -1
- package/dist/observability/escape-hatch-report.d.ts +2 -1
- package/dist/observability/escape-hatch-report.js +9 -2
- package/dist/observability/index.d.ts +7 -15
- package/dist/observability/index.js +4 -12
- package/dist/observability/metric-validator.js +1 -1
- package/dist/observability/metrics-handle.d.ts +0 -1
- package/dist/observability/metrics-handle.js +2 -15
- package/dist/observability/recording-tracer.d.ts +1 -2
- package/dist/observability/recording-tracer.js +0 -6
- package/dist/observability/sensitive-filter.d.ts +0 -2
- package/dist/observability/sensitive-filter.js +0 -29
- package/dist/pipeline/active-membership.d.ts +2 -1
- package/dist/pipeline/active-membership.js +6 -2
- package/dist/pipeline/after-rollback-sink.d.ts +6 -0
- package/dist/pipeline/after-rollback-sink.js +32 -0
- package/dist/pipeline/append-event-core.d.ts +2 -1
- package/dist/pipeline/append-event-core.js +2 -2
- package/dist/pipeline/attach-outside-transaction.d.ts +3 -0
- package/dist/pipeline/attach-outside-transaction.js +13 -0
- package/dist/pipeline/auth-claims-resolver.d.ts +2 -1
- package/dist/pipeline/cascade-handler.d.ts +2 -1
- package/dist/pipeline/cascade-handler.js +3 -2
- package/dist/pipeline/config-accessor-factory.d.ts +1 -1
- package/dist/pipeline/config-accessor-factory.js +1 -1
- package/dist/pipeline/context-services.d.ts +56 -0
- package/dist/pipeline/context-services.js +73 -0
- package/dist/pipeline/dispatch-batch.d.ts +2 -1
- package/dist/pipeline/dispatch-batch.js +39 -19
- package/dist/pipeline/dispatch-query.js +5 -4
- package/dist/pipeline/dispatch-scope.d.ts +6 -0
- package/dist/pipeline/dispatch-scope.js +27 -0
- package/dist/pipeline/dispatch-shared.d.ts +13 -9
- package/dist/pipeline/dispatch-shared.js +75 -194
- package/dist/pipeline/dispatch-stream.js +8 -4
- package/dist/pipeline/dispatch-write.d.ts +2 -1
- package/dist/pipeline/dispatch-write.js +10 -8
- package/dist/pipeline/dispatcher-utils.d.ts +3 -1
- package/dist/pipeline/dispatcher-utils.js +8 -2
- package/dist/pipeline/dispatcher.d.ts +3 -2
- package/dist/pipeline/dispatcher.js +4 -3
- package/dist/pipeline/event-consumer-state.d.ts +0 -1
- package/dist/pipeline/event-dispatcher-delivery.d.ts +1 -1
- package/dist/pipeline/event-dispatcher-delivery.js +7 -3
- package/dist/pipeline/event-dispatcher.d.ts +3 -2
- package/dist/pipeline/event-dispatcher.js +13 -12
- package/dist/pipeline/event-retention.js +59 -56
- package/dist/pipeline/handler-access-error.js +2 -1
- package/dist/pipeline/handler-context-auth.d.ts +5 -6
- package/dist/pipeline/handler-context-auth.js +7 -4
- package/dist/pipeline/handler-context-config.d.ts +2 -5
- package/dist/pipeline/handler-context-config.js +2 -2
- package/dist/pipeline/handler-context-db.d.ts +32 -7
- package/dist/pipeline/handler-context-db.js +26 -17
- package/dist/pipeline/handler-context-dispatch.d.ts +14 -6
- package/dist/pipeline/handler-context-dispatch.js +18 -5
- package/dist/pipeline/handler-context-events.d.ts +22 -38
- package/dist/pipeline/handler-context-events.js +42 -35
- package/dist/pipeline/handler-context-member-resolution.d.ts +2 -0
- package/dist/pipeline/handler-context-member-resolution.js +110 -0
- package/dist/pipeline/handler-context-notify.d.ts +3 -2
- package/dist/pipeline/handler-context-notify.js +1 -1
- package/dist/pipeline/handler-context-observability.d.ts +2 -4
- package/dist/pipeline/handler-context-observability.js +7 -5
- package/dist/pipeline/handler-context-phase-denials.d.ts +11 -0
- package/dist/pipeline/handler-context-phase-denials.js +98 -0
- package/dist/pipeline/handler-context-scope.d.ts +7 -10
- package/dist/pipeline/handler-context-scope.js +18 -20
- package/dist/pipeline/index.d.ts +9 -21
- package/dist/pipeline/index.js +5 -7
- package/dist/pipeline/irreversible-operation-gate.d.ts +1 -1
- package/dist/pipeline/irreversible-operation-gate.js +2 -2
- package/dist/pipeline/lifecycle-pipeline.d.ts +8 -7
- package/dist/pipeline/lifecycle-pipeline.js +9 -15
- package/dist/pipeline/member-read-only-transaction.js +11 -3
- package/dist/pipeline/member-reader.d.ts +1 -1
- package/dist/pipeline/member-reader.js +2 -2
- package/dist/pipeline/msp-rebuild.js +5 -3
- package/dist/pipeline/multi-stream-apply-context.js +3 -2
- package/dist/pipeline/notify-scope.d.ts +2 -1
- package/dist/pipeline/pre-handler-gates.d.ts +2 -1
- package/dist/pipeline/pre-transaction-reservations.d.ts +3 -3
- package/dist/pipeline/pre-transaction-reservations.js +9 -7
- package/dist/pipeline/projection-rebuild.js +12 -5
- package/dist/pipeline/projection-state.d.ts +0 -6
- package/dist/pipeline/projection-state.js +0 -5
- package/dist/pipeline/projections-runner.d.ts +2 -1
- package/dist/pipeline/projections-runner.js +10 -6
- package/dist/pipeline/system-hooks.d.ts +6 -2
- package/dist/pipeline/system-hooks.js +61 -10
- package/dist/pipeline/system-identity-switch.d.ts +4 -2
- package/dist/pipeline/system-identity-switch.js +51 -36
- package/dist/pipeline/typed-append-event.d.ts +2 -0
- package/dist/pipeline/typed-append-event.js +4 -0
- package/dist/pipeline/write-origin.js +2 -2
- package/dist/pipeline/write-result-masking.d.ts +1 -1
- package/dist/pipeline/write-result-masking.js +13 -10
- package/dist/random/index.d.ts +1 -2
- package/dist/random/index.js +1 -2
- package/dist/rate-limit/bucket.d.ts +2 -1
- package/dist/rate-limit/middleware.js +2 -1
- package/dist/redis/index.d.ts +3 -4
- package/dist/redis/index.js +2 -2
- package/dist/schema-cli/apply-command.js +5 -2
- package/dist/schema-cli/baseline-command.js +7 -2
- package/dist/schema-cli/generate-command.js +7 -9
- package/dist/schema-cli/shared.d.ts +4 -0
- package/dist/schema-cli/shared.js +21 -2
- package/dist/schema-cli/status-command.js +8 -2
- package/dist/schema-cli/validate-command.js +52 -4
- package/dist/schema-cli.d.ts +0 -1
- package/dist/search/configure-tenant-index.d.ts +1 -3
- package/dist/search/configure-tenant-index.js +0 -4
- package/dist/search/index.d.ts +1 -4
- package/dist/search/index.js +0 -2
- package/dist/search/meilisearch-adapter-internals.d.ts +8 -0
- package/dist/search/meilisearch-adapter-internals.js +9 -0
- package/dist/search/meilisearch-adapter.d.ts +1 -8
- package/dist/search/meilisearch-adapter.js +6 -7
- package/dist/search/meilisearch-peer.d.ts +2 -0
- package/dist/search/meilisearch-peer.js +5 -0
- package/dist/search/reindex-entity.js +107 -91
- package/dist/secrets/index.d.ts +3 -4
- package/dist/secrets/index.js +2 -3
- package/dist/seeding/index.d.ts +2 -2
- package/dist/seeding/index.js +1 -2
- package/dist/time/index.d.ts +2 -2
- package/dist/time/index.js +1 -1
- package/dist/time/tz-context.d.ts +0 -5
- package/dist/time/tz-context.js +0 -9
- package/dist/ui-types/index.d.ts +8 -11
- package/dist/ui-types/index.js +3 -3
- package/dist/upgrade-changelog.d.ts +3 -0
- package/dist/upgrade-changelog.js +18 -0
- package/dist/upgrade-cli-internals.d.ts +8 -0
- package/dist/upgrade-cli-internals.js +63 -0
- package/dist/upgrade-cli.d.ts +1 -18
- package/dist/upgrade-cli.js +29 -137
- package/dist/upgrade-marker-parse.d.ts +32 -0
- package/dist/upgrade-marker-parse.js +73 -0
- package/dist/utils/import-optional-peer.d.ts +6 -0
- package/dist/utils/import-optional-peer.js +19 -0
- package/dist/utils/index.d.ts +1 -4
- package/dist/utils/index.js +1 -4
- package/package.json +27 -20
- package/src/changes.json +451 -0
- package/dist/crypto/request-kms-cache.d.ts +0 -8
- package/dist/crypto/request-kms-cache.js +0 -21
- package/dist/engine/codemod/index.d.ts +0 -2
- package/dist/engine/codemod/index.js +0 -1
- package/dist/engine/codemod/pipeline-codemod.d.ts +0 -50
- package/dist/engine/codemod/pipeline-codemod.js +0 -536
- package/dist/engine/feature-ast/entity-field-types.d.ts +0 -13
- package/dist/engine/feature-ast/entity-field-types.js +0 -35
- package/dist/engine/feature-ast/extractors/ai-steps.d.ts +0 -6
- package/dist/engine/feature-ast/extractors/ai-steps.js +0 -254
- package/dist/engine/feature-ast/extractors/events.d.ts +0 -5
- package/dist/engine/feature-ast/extractors/events.js +0 -275
- package/dist/engine/feature-ast/extractors/handlers.d.ts +0 -24
- package/dist/engine/feature-ast/extractors/handlers.js +0 -358
- package/dist/engine/feature-ast/extractors/hooks.d.ts +0 -24
- package/dist/engine/feature-ast/extractors/hooks.js +0 -248
- package/dist/engine/feature-ast/extractors/index.d.ts +0 -14
- package/dist/engine/feature-ast/extractors/index.js +0 -13
- package/dist/engine/feature-ast/extractors/jobs-routes.d.ts +0 -7
- package/dist/engine/feature-ast/extractors/jobs-routes.js +0 -145
- package/dist/engine/feature-ast/extractors/projections-screens.d.ts +0 -10
- package/dist/engine/feature-ast/extractors/projections-screens.js +0 -195
- package/dist/engine/feature-ast/extractors/resolve-import.d.ts +0 -21
- package/dist/engine/feature-ast/extractors/resolve-import.js +0 -180
- package/dist/engine/feature-ast/extractors/round1.d.ts +0 -10
- package/dist/engine/feature-ast/extractors/round1.js +0 -81
- package/dist/engine/feature-ast/extractors/round2.d.ts +0 -7
- package/dist/engine/feature-ast/extractors/round2.js +0 -191
- package/dist/engine/feature-ast/extractors/round3.d.ts +0 -23
- package/dist/engine/feature-ast/extractors/round3.js +0 -292
- package/dist/engine/feature-ast/extractors/round5.d.ts +0 -9
- package/dist/engine/feature-ast/extractors/round5.js +0 -68
- package/dist/engine/feature-ast/extractors/round6.d.ts +0 -4
- package/dist/engine/feature-ast/extractors/round6.js +0 -17
- package/dist/engine/feature-ast/extractors/shared.d.ts +0 -94
- package/dist/engine/feature-ast/extractors/shared.js +0 -343
- package/dist/engine/feature-ast/index.d.ts +0 -16
- package/dist/engine/feature-ast/index.js +0 -10
- package/dist/engine/feature-ast/parse.d.ts +0 -31
- package/dist/engine/feature-ast/parse.js +0 -483
- package/dist/engine/feature-ast/patch.d.ts +0 -210
- package/dist/engine/feature-ast/patch.js +0 -610
- package/dist/engine/feature-ast/patcher.d.ts +0 -217
- package/dist/engine/feature-ast/patcher.js +0 -281
- package/dist/engine/feature-ast/pattern-change-schema.d.ts +0 -1476
- package/dist/engine/feature-ast/pattern-change-schema.js +0 -1226
- package/dist/engine/feature-ast/pattern-id-matchers.d.ts +0 -7
- package/dist/engine/feature-ast/pattern-id-matchers.js +0 -210
- package/dist/engine/feature-ast/patterns.d.ts +0 -318
- package/dist/engine/feature-ast/patterns.js +0 -106
- package/dist/engine/feature-ast/render.d.ts +0 -47
- package/dist/engine/feature-ast/render.js +0 -662
- package/dist/engine/feature-ast/source-location.d.ts +0 -17
- package/dist/engine/feature-ast/source-location.js +0 -27
- package/dist/engine/pattern-library/index.d.ts +0 -2
- package/dist/engine/pattern-library/index.js +0 -3
- package/dist/engine/pattern-library/library.d.ts +0 -14
- package/dist/engine/pattern-library/library.js +0 -93
- package/dist/engine/pattern-library/mixed-schemas.d.ts +0 -16
- package/dist/engine/pattern-library/mixed-schemas.js +0 -559
- package/dist/engine/pattern-library/opaque-schemas.d.ts +0 -7
- package/dist/engine/pattern-library/opaque-schemas.js +0 -115
- package/dist/engine/pattern-library/shared-fields.d.ts +0 -122
- package/dist/engine/pattern-library/shared-fields.js +0 -88
- package/dist/engine/pattern-library/static-schemas.d.ts +0 -20
- package/dist/engine/pattern-library/static-schemas.js +0 -478
- package/dist/engine/pattern-library/types.d.ts +0 -158
- package/dist/engine/pattern-library/types.js +0 -36
- package/dist/engine/provider-plugin-context.d.ts +0 -3
- package/dist/engine/provider-plugin-context.js +0 -28
- package/dist/engine/resolve-config-or-param.d.ts +0 -18
- package/dist/engine/resolve-config-or-param.js +0 -76
- package/src/scripts/codemod/README.md +0 -187
- package/src/scripts/codemod/codemod-support.ts +0 -334
- package/src/scripts/codemod/collect-source-files.ts +0 -48
- package/src/scripts/codemod/crypto-shredding-testing-move.ts +0 -119
- package/src/scripts/codemod/db-factory.ts +0 -810
- package/src/scripts/codemod/feature-factory.ts +0 -429
- package/src/scripts/codemod/feature-layout.ts +0 -424
- package/src/scripts/codemod/import-extensions.ts +0 -118
- package/src/scripts/codemod/migrate-cross-tenant.ts +0 -328
- package/src/scripts/codemod/migrate-db-raw.ts +0 -401
- package/src/scripts/codemod/migrate-open-to-all.ts +0 -235
- package/src/scripts/codemod/object-form.ts +0 -746
- package/src/scripts/codemod/package-merge.ts +0 -299
- package/src/scripts/codemod/pii-personal-migration.ts +0 -816
- package/src/scripts/codemod/remove-engine-payload-casts.ts +0 -318
- package/src/scripts/codemod/s3-imports.ts +0 -236
- package/src/scripts/codemod/tenant-db-options.ts +0 -454
- package/src/scripts/codemod/testing-injection.ts +0 -215
- package/src/scripts/codemod/testing-move-targets.ts +0 -161
- package/src/scripts/codemod/testing-move.ts +0 -542
- package/src/scripts/codemod/unprocessable-error-details-reason.ts +0 -411
|
@@ -12,6 +12,7 @@ import { IdempotentAppendConflictError, SeedTimeOrderError, VersionConflictError
|
|
|
12
12
|
import { eventsTable } from "./events-schema.js";
|
|
13
13
|
import { toStoredEvent } from "./row-to-stored-event.js";
|
|
14
14
|
import { currentSeedCreatedAt } from "./seed-clock.js";
|
|
15
|
+
import { inEventStreamScope } from "./stream-scope.js";
|
|
15
16
|
// Append one event atomically. Two guarantees combined:
|
|
16
17
|
//
|
|
17
18
|
// 1. UNIQUE (tenant_id, aggregate_id, version) serializes concurrent writers
|
|
@@ -51,7 +52,7 @@ export async function append(db, event) {
|
|
|
51
52
|
const newVersion = toStore.expectedVersion + 1;
|
|
52
53
|
const eventVersion = toStore.eventVersion ?? 1;
|
|
53
54
|
try {
|
|
54
|
-
const row = await runAtomicEventWrite(db, async (runner) => {
|
|
55
|
+
const row = await inEventStreamScope(toStore.tenantId, () => runAtomicEventWrite(db, async (runner) => {
|
|
55
56
|
await claimXactId(runner);
|
|
56
57
|
// Inside the write transaction so a concurrent live append cannot slip
|
|
57
58
|
// between the check and the insert.
|
|
@@ -65,7 +66,7 @@ export async function append(db, event) {
|
|
|
65
66
|
// commit, so the dispatcher cannot wake before the row is visible.
|
|
66
67
|
await notifyPgChannel(runner, EVENTS_PUBSUB_CHANNEL);
|
|
67
68
|
return inserted;
|
|
68
|
-
});
|
|
69
|
+
}));
|
|
69
70
|
return buildStoredEvent(toStore, newVersion, eventVersion, row);
|
|
70
71
|
}
|
|
71
72
|
catch (e) {
|
|
@@ -208,15 +209,20 @@ export async function loadAggregate(db, aggregateId, tenantId, options) {
|
|
|
208
209
|
if (options?.aggregateType === "") {
|
|
209
210
|
throw new Error("loadAggregate: aggregateType must be a non-empty string when provided");
|
|
210
211
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
212
|
+
return inEventStreamScope(tenantId, async () => {
|
|
213
|
+
if (!options?.includeArchived) {
|
|
214
|
+
const archived = await isStreamArchived(db, tenantId, aggregateId);
|
|
215
|
+
if (archived)
|
|
216
|
+
return [];
|
|
217
|
+
}
|
|
218
|
+
const rows = await selectMany(db, eventsTable, {
|
|
219
|
+
aggregateId,
|
|
220
|
+
tenantId,
|
|
221
|
+
...(options?.aggregateType !== undefined && { aggregateType: options.aggregateType }),
|
|
222
|
+
...(options?.atVersion !== undefined && { version: options.atVersion }),
|
|
223
|
+
}, { orderBy: { col: "version", direction: "asc" } });
|
|
224
|
+
return rows.map(toStoredEvent);
|
|
225
|
+
});
|
|
220
226
|
}
|
|
221
227
|
// Events and the stream's latest version from ONE read, so both come from the same
|
|
222
228
|
// snapshot: a commit landing between two separate statements would leave the caller
|
|
@@ -227,40 +233,44 @@ export async function loadAggregateForWriting(db, aggregateId, tenantId, options
|
|
|
227
233
|
if (options.aggregateType === "") {
|
|
228
234
|
throw new Error("loadAggregateForWriting: aggregateType must be a non-empty string");
|
|
229
235
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
236
|
+
return inEventStreamScope(tenantId, async () => {
|
|
237
|
+
if (await isStreamArchived(db, tenantId, aggregateId)) {
|
|
238
|
+
return { events: [], streamVersion: await getStreamVersion(db, aggregateId, tenantId) };
|
|
239
|
+
}
|
|
240
|
+
const rows = await selectMany(db, eventsTable, { aggregateId, tenantId }, { orderBy: { col: "version", direction: "asc" } });
|
|
241
|
+
const all = rows.map(toStoredEvent);
|
|
242
|
+
return {
|
|
243
|
+
events: all.filter((e) => e.aggregateType === options.aggregateType),
|
|
244
|
+
streamVersion: all.at(-1)?.version ?? 0,
|
|
245
|
+
};
|
|
246
|
+
});
|
|
239
247
|
}
|
|
240
248
|
// Load events up to a point in time. Used for asOf queries that reconstruct
|
|
241
249
|
// historical state. Includes events whose created_at is <= asOf. Same
|
|
242
250
|
// archive semantics as loadAggregate.
|
|
243
251
|
export async function loadAggregateAsOf(db, aggregateId, tenantId, asOf, options) {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
252
|
+
return inEventStreamScope(tenantId, async () => {
|
|
253
|
+
if (!options?.includeArchived) {
|
|
254
|
+
const archived = await isStreamArchived(db, tenantId, aggregateId);
|
|
255
|
+
if (archived)
|
|
256
|
+
return [];
|
|
257
|
+
}
|
|
258
|
+
const rows = await selectMany(db, eventsTable, { aggregateId, tenantId, createdAt: { lte: asOf } }, { orderBy: { col: "version", direction: "asc" } });
|
|
259
|
+
return rows.map(toStoredEvent);
|
|
260
|
+
});
|
|
251
261
|
}
|
|
252
262
|
// Cheapest possible read of "what's the latest version on this stream?". The
|
|
253
263
|
// CRUD executor uses this as expectedVersion for its append, so a domain
|
|
254
|
-
// event appended via ctx.
|
|
264
|
+
// event appended via ctx.events.append between two CRUD writes doesn't cause
|
|
255
265
|
// the next CRUD write to fail with version_conflict. Indexed lookup on the
|
|
256
266
|
// existing (aggregate_id, version) unique index. Returns 0 for empty/unknown
|
|
257
267
|
// streams (matches create()'s expectedVersion=0 convention).
|
|
258
268
|
// @wrapper-known semantic-alias
|
|
259
269
|
export async function getStreamVersion(db, aggregateId, tenantId) {
|
|
260
|
-
return selectStreamMaxVersion(db, aggregateId, tenantId);
|
|
270
|
+
return inEventStreamScope(tenantId, () => selectStreamMaxVersion(db, aggregateId, tenantId));
|
|
261
271
|
}
|
|
262
272
|
export async function getStreamVersions(db, aggregateIds, tenantId) {
|
|
263
|
-
return selectStreamMaxVersions(db, aggregateIds, tenantId);
|
|
273
|
+
return inEventStreamScope(tenantId, () => selectStreamMaxVersions(db, aggregateIds, tenantId));
|
|
264
274
|
}
|
|
265
275
|
/** MAX(version) for one aggregate — no tenant filter. SECURITY: existence-oracle,
|
|
266
276
|
* a caller can probe whether an aggregateId has any events regardless of tenant
|
|
@@ -307,11 +317,11 @@ export async function loadEventsAfterVersion(db, aggregateId, tenantId, afterVer
|
|
|
307
317
|
// The caller may pause / do async work between yields; the next batch is
|
|
308
318
|
// only fetched when consumed.
|
|
309
319
|
//
|
|
310
|
-
// Cancellation: pass `signal` (typically `ctx.signal` from a handler) to
|
|
320
|
+
// Cancellation: pass `signal` (typically `ctx.lifecycle.signal` from a handler) to
|
|
311
321
|
// abort iteration. Checked both at batch boundaries (before the next
|
|
312
322
|
// fetch) AND between yields (so abort lands within one event regardless
|
|
313
323
|
// of batch size). Throws AbortError on the first check after abort;
|
|
314
|
-
// in-flight queries are not actively cancelled (
|
|
324
|
+
// in-flight queries are not actively cancelled (connection
|
|
315
325
|
// cancel is a separate, riskier concern handled per-query at the TenantDb
|
|
316
326
|
// boundary).
|
|
317
327
|
export async function* streamAllEventsByType(db, aggregateType, batchSize = 1000, signal) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { bigserial, index, instant, integer, jsonb, table as pgTable, sql, text, uniqueIndex, uuid, } from "../db/dialect.js";
|
|
3
3
|
import { tableExists } from "../db/index.js";
|
|
4
4
|
import { ensureIdempotencyKeyIndex, ensureMembershipPayloadTenantIndex, } from "../db/queries/event-store.js";
|
|
5
|
-
import { unsafePushTables } from "../db/table-push.js";
|
|
5
|
+
import { ensureTableRowLevelSecurity, unsafePushTables } from "../db/table-push.js";
|
|
6
6
|
import { createArchivedStreamsTable } from "./archive.js";
|
|
7
7
|
import { createSnapshotsTable } from "./snapshot.js";
|
|
8
8
|
// Event-store schema as a Drizzle table. The typed select/insert path handles
|
|
@@ -57,6 +57,9 @@ export async function createEventsTable(db) {
|
|
|
57
57
|
if (!(await tableExists(db, "public.kumiko_events"))) {
|
|
58
58
|
await unsafePushTables(db, { kumikoEvents: eventsTable });
|
|
59
59
|
}
|
|
60
|
+
else {
|
|
61
|
+
await ensureTableRowLevelSecurity(db, eventsTable);
|
|
62
|
+
}
|
|
60
63
|
// Runs unconditionally (both fresh + already-existing table) so installs
|
|
61
64
|
// that predate the idempotency-key index get healed the same way
|
|
62
65
|
// ensureSnapshotVersionColumn heals kumiko_snapshots.
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
export { APP_INSTANCE_STREAM_TYPE, APP_STARTED_EVENT_TYPE } from "../crypto/system-event-pii.ts";
|
|
2
|
-
export { backfillEventPiiEncryption, backfillEventPiiEncryptionBatch,
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
6
|
-
export { append,
|
|
2
|
+
export { backfillEventPiiEncryption, backfillEventPiiEncryptionBatch, } from "../db/queries/backfill-pii.ts";
|
|
3
|
+
export { deleteRowsWithoutReplayableStream } from "../db/queries/event-store-orphan-rows.ts";
|
|
4
|
+
export { archivedStreamsTable, archiveStream, createArchivedStreamsTable, isStreamArchived, } from "./archive.ts";
|
|
5
|
+
export { SeedTimeOrderError, VersionConflictError, } from "./errors.ts";
|
|
6
|
+
export { append, type EventMetadata, getEventsHighWaterMark, getStreamVersion, getStreamVersions, getUnscopedAggregateStreamMaxVersion, getUnscopedStreamMaxVersionForSeed, loadAggregate, type StoredEvent, streamAllEventsByType, } from "./event-store.ts";
|
|
7
7
|
export { createEventsTable, eventsTable } from "./events-schema.ts";
|
|
8
|
-
export { appendProvenanceEvent
|
|
9
|
-
export { createRebuildDeadLetterTable, listRebuildDeadLetters, type RebuildDeadLetterRow, rebuildDeadLetterTable, recordRebuildDeadLetters, type SkippedApply, } from "./rebuild-dead-letter.ts";
|
|
10
|
-
export { toStoredEvent } from "./row-to-stored-event.ts";
|
|
8
|
+
export { appendProvenanceEvent } from "./provenance-append.ts";
|
|
11
9
|
export { assertSeedModeNotInProduction, isSeedModeEnabled, runSeedWritesAt, SEED_MODE_ENV, SeedModeDisabledError, } from "./seed-clock.ts";
|
|
12
|
-
export {
|
|
13
|
-
export {
|
|
14
|
-
export { AGGREGATE_TRANSFER_STREAM_TYPE, AGGREGATE_TRANSFERRED_EVENT_TYPE,
|
|
15
|
-
export {
|
|
16
|
-
export {
|
|
10
|
+
export { snapshotsTable } from "./snapshot.ts";
|
|
11
|
+
export { appendEventInTenantDb, getStreamVersionInTenantDb, } from "./tenant-db-append.ts";
|
|
12
|
+
export { AGGREGATE_TRANSFER_STREAM_TYPE, AGGREGATE_TRANSFERRED_EVENT_TYPE, transferAggregateStreams, } from "./transfer.ts";
|
|
13
|
+
export { makeUpcastCtx, upcastStoredEvent, } from "./upcaster.ts";
|
|
14
|
+
export { upcasterDeadLetterTable } from "./upcaster-dead-letter.ts";
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
export { APP_INSTANCE_STREAM_TYPE, APP_STARTED_EVENT_TYPE } from "../crypto/system-event-pii.js";
|
|
2
2
|
export { backfillEventPiiEncryption, backfillEventPiiEncryptionBatch, } from "../db/queries/backfill-pii.js";
|
|
3
|
-
export { deleteRowsWithoutReplayableStream
|
|
4
|
-
export { archivedStreamsTable, archiveStream, createArchivedStreamsTable, isStreamArchived,
|
|
5
|
-
export {
|
|
6
|
-
export { append,
|
|
3
|
+
export { deleteRowsWithoutReplayableStream } from "../db/queries/event-store-orphan-rows.js";
|
|
4
|
+
export { archivedStreamsTable, archiveStream, createArchivedStreamsTable, isStreamArchived, } from "./archive.js";
|
|
5
|
+
export { SeedTimeOrderError, VersionConflictError, } from "./errors.js";
|
|
6
|
+
export { append, getEventsHighWaterMark, getStreamVersion, getStreamVersions, getUnscopedAggregateStreamMaxVersion, getUnscopedStreamMaxVersionForSeed, loadAggregate, streamAllEventsByType, } from "./event-store.js";
|
|
7
7
|
export { createEventsTable, eventsTable } from "./events-schema.js";
|
|
8
8
|
export { appendProvenanceEvent } from "./provenance-append.js";
|
|
9
|
-
export { createRebuildDeadLetterTable, listRebuildDeadLetters, rebuildDeadLetterTable, recordRebuildDeadLetters, } from "./rebuild-dead-letter.js";
|
|
10
|
-
export { toStoredEvent } from "./row-to-stored-event.js";
|
|
11
9
|
export { assertSeedModeNotInProduction, isSeedModeEnabled, runSeedWritesAt, SEED_MODE_ENV, SeedModeDisabledError, } from "./seed-clock.js";
|
|
12
|
-
export {
|
|
10
|
+
export { snapshotsTable } from "./snapshot.js";
|
|
13
11
|
export { appendEventInTenantDb, getStreamVersionInTenantDb, } from "./tenant-db-append.js";
|
|
14
12
|
export { AGGREGATE_TRANSFER_STREAM_TYPE, AGGREGATE_TRANSFERRED_EVENT_TYPE, transferAggregateStreams, } from "./transfer.js";
|
|
15
|
-
export { makeUpcastCtx, upcastStoredEvent,
|
|
16
|
-
export {
|
|
13
|
+
export { makeUpcastCtx, upcastStoredEvent, } from "./upcaster.js";
|
|
14
|
+
export { upcasterDeadLetterTable } from "./upcaster-dead-letter.js";
|
|
@@ -32,7 +32,7 @@ export async function appendProvenanceEvent(db, event) {
|
|
|
32
32
|
message: `appendProvenanceEvent: event tenant "${event.tenantId}" does not match the TenantDb's tenant "${db.tenantId}".`,
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
|
-
//
|
|
35
|
+
// Postgres aborts the whole surrounding transaction on a statement
|
|
36
36
|
// error (25P02) even when the caller's catch swallows it — the savepoint
|
|
37
37
|
// confines that to this scope. Pool connections have no ambient tx to poison.
|
|
38
38
|
await runInSavepointIfSupported(runner, async (sp) => {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// is a separate ops step — same stance as the upcaster dead-letter.
|
|
15
15
|
import { bigint, index, jsonb, table as pgTable, text, timestamp, uuid } from "../db/dialect.js";
|
|
16
16
|
import { tableExists } from "../db/schema-inspection.js";
|
|
17
|
-
import { unsafePushTables } from "../db/table-push.js";
|
|
17
|
+
import { ensureTableRowLevelSecurity, unsafePushTables } from "../db/table-push.js";
|
|
18
18
|
export const rebuildDeadLetterTable = pgTable("kumiko_rebuild_dead_letters", {
|
|
19
19
|
// Surrogate PK — the same event can land here across multiple rebuild
|
|
20
20
|
// attempts before the fix ships, without unique-violation noise.
|
|
@@ -39,8 +39,10 @@ export const rebuildDeadLetterTable = pgTable("kumiko_rebuild_dead_letters", {
|
|
|
39
39
|
// provisioned before this table existed.
|
|
40
40
|
export async function createRebuildDeadLetterTable(db) {
|
|
41
41
|
// skip: table already exists — bootstrap called from multiple paths
|
|
42
|
-
if (await tableExists(db, "public.kumiko_rebuild_dead_letters"))
|
|
42
|
+
if (await tableExists(db, "public.kumiko_rebuild_dead_letters")) {
|
|
43
|
+
await ensureTableRowLevelSecurity(db, rebuildDeadLetterTable);
|
|
43
44
|
return;
|
|
45
|
+
}
|
|
44
46
|
await unsafePushTables(db, { kumikoRebuildDeadLetters: rebuildDeadLetterTable });
|
|
45
47
|
}
|
|
46
48
|
// Bulk-write, called ONCE at the end of a quarantining rebuild (inside its
|
|
@@ -4,7 +4,7 @@ import { index, instant, integer, jsonb, table as pgTable, primaryKey, sql, text
|
|
|
4
4
|
import { ensureSnapshotVersionColumn, upsertSnapshot } from "../db/queries/event-store.js";
|
|
5
5
|
import { selectMany } from "../db/query.js";
|
|
6
6
|
import { tableExists } from "../db/schema-inspection.js";
|
|
7
|
-
import { unsafePushTables } from "../db/table-push.js";
|
|
7
|
+
import { ensureTableRowLevelSecurity, unsafePushTables } from "../db/table-push.js";
|
|
8
8
|
import { createFallbackLogger, scrubLogText } from "../logging/index.js";
|
|
9
9
|
import { isStreamArchived } from "./archive.js";
|
|
10
10
|
import { loadEventsAfterVersion } from "./event-store.js";
|
|
@@ -18,7 +18,7 @@ import { loadEventsAfterVersion } from "./event-store.js";
|
|
|
18
18
|
// 3. loadEventsAfterVersion(aggregate, N) → only the delta
|
|
19
19
|
// 4. reducer(snapshot, delta) → current state
|
|
20
20
|
//
|
|
21
|
-
// Write path: manual via ctx.
|
|
21
|
+
// Write path: manual via ctx.events.snapshot, or automatic via the
|
|
22
22
|
// { snapshotEvery: N } load option — the read path persists a fresh
|
|
23
23
|
// snapshot whenever it folded at least N delta events.
|
|
24
24
|
//
|
|
@@ -32,7 +32,7 @@ import { loadEventsAfterVersion } from "./event-store.js";
|
|
|
32
32
|
//
|
|
33
33
|
// Upcaster interaction: the raw API (loadAggregateWithSnapshot below) does
|
|
34
34
|
// NOT apply the upcaster chain on delta events — same layering as raw
|
|
35
|
-
// loadAggregate. The Dispatcher wraps this into ctx.
|
|
35
|
+
// loadAggregate. The Dispatcher wraps this into ctx.events.loadWithSnapshot
|
|
36
36
|
// and runs upcastStoredEvents on the delta before calling the reducer, so
|
|
37
37
|
// feature authors always see current-version payloads.
|
|
38
38
|
export const snapshotsTable = pgTable("kumiko_snapshots", {
|
|
@@ -64,6 +64,7 @@ export async function createSnapshotsTable(db) {
|
|
|
64
64
|
// Installs that predate snapshot_version get healed by the same
|
|
65
65
|
// idempotent ensure that `kumiko schema apply` / test-setup already runs.
|
|
66
66
|
await ensureSnapshotVersionColumn(db);
|
|
67
|
+
await ensureTableRowLevelSecurity(db, snapshotsTable);
|
|
67
68
|
// skip: table already ensured — only the column heal above was needed
|
|
68
69
|
return;
|
|
69
70
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { runInRowLevelSecurityScope, tenantRowLevelSecurityScope, } from "../db/row-level-security-scope.js";
|
|
2
|
+
// A stream belongs to exactly one tenant; its rows are only writable and reliably readable in
|
|
3
|
+
// that tenant's scope, which differs from the caller's for systemStream entities and ctx.tenants.writeTarget.
|
|
4
|
+
export function inEventStreamScope(streamTenantId, work) {
|
|
5
|
+
return runInRowLevelSecurityScope(tenantRowLevelSecurityScope(streamTenantId), work);
|
|
6
|
+
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
// separate CLI step — not implemented here, tracked as follow-up.
|
|
14
14
|
import { bigint, index, integer, jsonb, table as pgTable, text, timestamp, uuid, } from "../db/dialect.js";
|
|
15
15
|
import { tableExists } from "../db/schema-inspection.js";
|
|
16
|
-
import { unsafePushTables } from "../db/table-push.js";
|
|
16
|
+
import { ensureTableRowLevelSecurity, unsafePushTables } from "../db/table-push.js";
|
|
17
17
|
export const upcasterDeadLetterTable = pgTable("kumiko_upcaster_dead_letters", {
|
|
18
18
|
// Surrogate PK. We don't reuse eventId so a single event can land
|
|
19
19
|
// here multiple times (retry attempts across deploys before the fix
|
|
@@ -40,8 +40,10 @@ export const upcasterDeadLetterTable = pgTable("kumiko_upcaster_dead_letters", {
|
|
|
40
40
|
// exercise the quarantine path; production boot uses drizzle-kit push.
|
|
41
41
|
export async function createUpcasterDeadLetterTable(db) {
|
|
42
42
|
// skip: table already exists — bootstrap called from multiple paths
|
|
43
|
-
if (await tableExists(db, "public.kumiko_upcaster_dead_letters"))
|
|
43
|
+
if (await tableExists(db, "public.kumiko_upcaster_dead_letters")) {
|
|
44
|
+
await ensureTableRowLevelSecurity(db, upcasterDeadLetterTable);
|
|
44
45
|
return;
|
|
46
|
+
}
|
|
45
47
|
await unsafePushTables(db, { kumikoUpcasterDeadLetters: upcasterDeadLetterTable });
|
|
46
48
|
}
|
|
47
49
|
// Writes a dead-letter row. Called by upcastStoredEvent when errorPolicy
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { EventUpcastCtx, EventUpcastFn } from "@cosmicdrift/kumiko-types/handlers";
|
|
1
2
|
import type { DbRunner } from "../db/index.ts";
|
|
2
|
-
import type {
|
|
3
|
+
import type { TenantId } from "../engine/types/index.ts";
|
|
3
4
|
import type { StoredEvent } from "./event-store.ts";
|
|
4
5
|
export type UpcasterErrorPolicy = "throw" | "quarantine";
|
|
5
6
|
export type UpcastOptions = {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { AnyFileFieldDef } from "@cosmicdrift/kumiko-types/fields";
|
|
2
|
+
import type { Registry, SessionUser } from "../engine/types/index.ts";
|
|
2
3
|
export declare function isActionFormScreenQn(value: string): boolean;
|
|
3
4
|
/** The files/images field `fieldName` of the registered actionForm screen `screenQn`, if any. */
|
|
4
5
|
export declare function resolveActionFormFileField(registry: Pick<Registry, "getScreen"> | undefined, screenQn: string, fieldName: string): AnyFileFieldDef | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { hasAccess } from "../engine/access.js";
|
|
2
|
-
import { isFileField
|
|
2
|
+
import { isFileField } from "../engine/field-helpers.js";
|
|
3
3
|
// Same character set as the other upload identifiers: the screen QN is stored as the pending
|
|
4
4
|
// upload's entityType and compared by exact match, never interpolated into a storage key.
|
|
5
5
|
const ACTION_FORM_SCREEN_QN = /^[A-Za-z0-9_-]+:screen:[A-Za-z0-9_-]+$/;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { SaveContext } from "@cosmicdrift/kumiko-types/hooks";
|
|
2
|
+
import type { Registry } from "../engine/types/index.ts";
|
|
2
3
|
import type { FileRefRows } from "./load-save-file-refs.ts";
|
|
3
4
|
export declare function assertFileRefsBelongToTenant(args: {
|
|
4
5
|
readonly registry: Registry;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isFileField } from "../engine/
|
|
1
|
+
import { isFileField } from "../engine/field-helpers.js";
|
|
2
2
|
import { ValidationError } from "../errors/index.js";
|
|
3
3
|
import { fileRefIdsOf } from "./bind-pending-file-refs.js";
|
|
4
4
|
import { FILE_REF_ENTITY_NAME } from "./file-ref-entity.js";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { SaveContext } from "@cosmicdrift/kumiko-types/hooks";
|
|
1
2
|
import type { TenantDb } from "../db/tenant-db.ts";
|
|
2
|
-
import {
|
|
3
|
+
import type { Registry, SessionUser } from "../engine/types/index.ts";
|
|
3
4
|
import { type FileRefRows } from "./load-save-file-refs.ts";
|
|
4
5
|
export declare function fileRefIdsOf(value: unknown): readonly string[];
|
|
5
6
|
type FileRefRow = Readonly<Record<string, unknown>>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { isUuid } from "@cosmicdrift/kumiko-types/identifiers";
|
|
2
|
+
import { isFileField } from "../engine/field-helpers.js";
|
|
1
3
|
import { isAnonymousSessionUser } from "../engine/system-user.js";
|
|
2
|
-
import { isFileField, isUuid, } from "../engine/types/index.js";
|
|
3
4
|
import { FrameworkReasons, InternalError, reraiseAsKumikoError, UnprocessableError, } from "../errors/index.js";
|
|
4
5
|
import { getFileRefExecutor, resolveAttachedField } from "./create-file-ref.js";
|
|
5
6
|
import { FILE_REF_ENTITY_NAME } from "./file-ref-entity.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
+
import { isFileField } from "../engine/field-helpers.js";
|
|
2
3
|
import { defineWriteHandler, SYSTEM_ROLE, SYSTEM_USER_ID } from "../engine/index.js";
|
|
3
|
-
import { isFileField } from "../engine/types/index.js";
|
|
4
4
|
import { ValidationError } from "../errors/index.js";
|
|
5
5
|
import { fileRefIdsOf } from "./bind-pending-file-refs.js";
|
|
6
6
|
import { getFileRefExecutor } from "./create-file-ref.js";
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import type { BeforeTransactionResult, WriteResult } from "@cosmicdrift/kumiko-types/handlers";
|
|
1
2
|
import type { TenantDb } from "../db/tenant-db.ts";
|
|
2
|
-
import type {
|
|
3
|
+
import type { Registry, SessionUser } from "../engine/types/index.ts";
|
|
3
4
|
import { type CreatedFileRef, type UploadedFileBytes } from "./create-file-ref.ts";
|
|
4
5
|
import type { FileContext } from "./file-handle.ts";
|
|
5
6
|
export type { CreatedFileRef, UploadedFileBytes };
|
|
6
7
|
export type CreateFileRefContext = {
|
|
7
8
|
readonly db: TenantDb;
|
|
8
|
-
readonly
|
|
9
|
+
readonly services: {
|
|
10
|
+
readonly files?: FileContext | undefined;
|
|
11
|
+
};
|
|
9
12
|
readonly registry: Registry;
|
|
10
13
|
readonly user: SessionUser;
|
|
11
14
|
};
|
|
@@ -21,6 +24,6 @@ export type CreateFileRefInput = {
|
|
|
21
24
|
};
|
|
22
25
|
export declare function filesUnavailableMessage(caller: string): string;
|
|
23
26
|
export declare function createFileRefFromBytes(ctx: CreateFileRefContext, input: CreateFileRefInput): Promise<WriteResult<CreatedFileRef>>;
|
|
24
|
-
export type UploadFileBytesContext = Pick<CreateFileRefContext, "db" | "
|
|
27
|
+
export type UploadFileBytesContext = Pick<CreateFileRefContext, "db" | "services" | "registry" | "user">;
|
|
25
28
|
export declare function uploadFileBytesBeforeTransaction(ctx: UploadFileBytesContext, input: CreateFileRefInput): Promise<BeforeTransactionResult<UploadedFileBytes>>;
|
|
26
29
|
export declare function createFileRefFromUploadedBytes(ctx: Pick<CreateFileRefContext, "db" | "user">, uploaded: UploadedFileBytes): Promise<WriteResult<CreatedFileRef>>;
|
|
@@ -8,13 +8,13 @@ import { assertSafeStorageKey } from "./types.js";
|
|
|
8
8
|
// The handler context has no HTTP/job/seed marker to name, so the message states the actual
|
|
9
9
|
// cause: the dispatcher's AppContext carries no file-provider resolver.
|
|
10
10
|
export function filesUnavailableMessage(caller) {
|
|
11
|
-
return `${caller}: ctx.files is unavailable because no file-provider resolver is wired on this dispatcher context. Mount a file-provider-* feature and build the dispatcher context with withFileProviderResolver (HTTP, job and seed dispatchers each need it)`;
|
|
11
|
+
return `${caller}: ctx.services.files is unavailable because no file-provider resolver is wired on this dispatcher context. Mount a file-provider-* feature and build the dispatcher context with withFileProviderResolver (HTTP, job and seed dispatchers each need it)`;
|
|
12
12
|
}
|
|
13
13
|
// Server-side counterpart of POST /files for handlers/jobs that produce bytes
|
|
14
14
|
// themselves (generated PDFs, exports). Same validation, storage layout and
|
|
15
15
|
// fileRef.created event as an upload; the tenant is always ctx.user.tenantId.
|
|
16
16
|
export async function createFileRefFromBytes(ctx, input) {
|
|
17
|
-
const { files } = ctx;
|
|
17
|
+
const { files } = ctx.services;
|
|
18
18
|
if (!files) {
|
|
19
19
|
return writeFailure(new InternalError({
|
|
20
20
|
message: filesUnavailableMessage("createFileRefFromBytes"),
|
|
@@ -46,6 +46,9 @@ export async function createFileRefFromBytes(ctx, input) {
|
|
|
46
46
|
return fileRejectedFailure(outcome.error);
|
|
47
47
|
case "failed":
|
|
48
48
|
return outcome.failure;
|
|
49
|
+
case "target-locked":
|
|
50
|
+
// Only the HTTP route supplies the lock re-check, so this path cannot produce it.
|
|
51
|
+
return writeFailure(new InternalError({ message: "createFileRefFromBytes: unexpected target-locked outcome" }));
|
|
49
52
|
}
|
|
50
53
|
}
|
|
51
54
|
function fileRejectedFailure(error) {
|
|
@@ -56,7 +59,7 @@ function fileRejectedFailure(error) {
|
|
|
56
59
|
// A crash between this phase and the commit leaves the bytes in storage; the upload ledger sweep
|
|
57
60
|
// removes them after its grace period.
|
|
58
61
|
export async function uploadFileBytesBeforeTransaction(ctx, input) {
|
|
59
|
-
const { files } = ctx;
|
|
62
|
+
const { files } = ctx.services;
|
|
60
63
|
if (!files) {
|
|
61
64
|
return writeFailure(new InternalError({
|
|
62
65
|
message: filesUnavailableMessage("uploadFileBytesBeforeTransaction"),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import type { AnyFileFieldDef } from "@cosmicdrift/kumiko-types/fields";
|
|
2
|
+
import type { TenantDb } from "../db/tenant-db.ts";
|
|
3
|
+
import type { Registry, SessionUser } from "../engine/types/index.ts";
|
|
3
4
|
import { type WriteFailure } from "../errors/index.ts";
|
|
4
5
|
export declare const DEFAULT_MAX_UPLOAD_SIZE = "10mb";
|
|
5
6
|
declare function buildFileRefExecutor(): import("@cosmicdrift/kumiko-types/event-store-executor-types").EventStoreExecutor<{
|
|
@@ -50,6 +51,7 @@ export type StoreFileDeps = {
|
|
|
50
51
|
readonly defaultMaxUploadSize: string;
|
|
51
52
|
readonly writeBytes: (storageKey: string, data: Uint8Array, mimeType: string) => Promise<void>;
|
|
52
53
|
readonly deleteBytes: (storageKey: string) => Promise<void>;
|
|
54
|
+
readonly isAttachTargetLocked?: (rowDb: TenantDb) => Promise<boolean>;
|
|
53
55
|
};
|
|
54
56
|
export type CreatedFileRef = {
|
|
55
57
|
readonly id: string;
|
|
@@ -80,6 +82,8 @@ export type StoreFileOutcome = {
|
|
|
80
82
|
} | {
|
|
81
83
|
readonly kind: "rejected";
|
|
82
84
|
readonly error: string;
|
|
85
|
+
} | {
|
|
86
|
+
readonly kind: "target-locked";
|
|
83
87
|
} | {
|
|
84
88
|
readonly kind: "failed";
|
|
85
89
|
readonly failure: WriteFailure;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createEventStoreExecutor } from "../db/event-store-executor.js";
|
|
2
|
-
import { runInOwnTransaction } from "../db/tenant-db.js";
|
|
3
|
-
import { isFileField
|
|
2
|
+
import { runInOwnTransaction } from "../db/tenant-db-scoped-rebind.js";
|
|
3
|
+
import { isFileField } from "../engine/field-helpers.js";
|
|
4
4
|
import { InternalError } from "../errors/index.js";
|
|
5
5
|
import { generateId } from "../utils/index.js";
|
|
6
6
|
import { isActionFormScreenQn, resolveActionFormFileField } from "./action-form-upload.js";
|
|
@@ -41,6 +41,8 @@ export function resolveAttachedField(registry, entityType, fieldName) {
|
|
|
41
41
|
return { kind: "unresolvable" };
|
|
42
42
|
return { kind: "resolved", fieldDef };
|
|
43
43
|
}
|
|
44
|
+
class AttachTargetLockedError extends Error {
|
|
45
|
+
}
|
|
44
46
|
function resolveUploadField(registry, input) {
|
|
45
47
|
const { entityType, entityId, fieldName, actionForm } = input;
|
|
46
48
|
if (actionForm === undefined)
|
|
@@ -196,14 +198,21 @@ export async function storeFileAsFileRef(deps, input) {
|
|
|
196
198
|
// skip: the create failure is the error worth reporting; the leftover bytes stay in storage.
|
|
197
199
|
}
|
|
198
200
|
};
|
|
201
|
+
const createRow = async (rowDb) => {
|
|
202
|
+
if (await deps.isAttachTargetLocked?.(rowDb))
|
|
203
|
+
throw new AttachTargetLockedError();
|
|
204
|
+
return createFileRefRow({ user: deps.user, tenantDb: rowDb }, upload.uploaded);
|
|
205
|
+
};
|
|
199
206
|
let row;
|
|
200
207
|
try {
|
|
201
208
|
row = deps.rowInOwnTransaction
|
|
202
|
-
? await runInOwnTransaction(deps.tenantDb,
|
|
203
|
-
: await
|
|
209
|
+
? await runInOwnTransaction(deps.tenantDb, createRow)
|
|
210
|
+
: await createRow(deps.tenantDb);
|
|
204
211
|
}
|
|
205
212
|
catch (e) {
|
|
206
213
|
await deleteUploadedBytes();
|
|
214
|
+
if (e instanceof AttachTargetLockedError)
|
|
215
|
+
return { kind: "target-locked" };
|
|
207
216
|
throw e;
|
|
208
217
|
}
|
|
209
218
|
if ("failure" in row) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { SaveContext } from "@cosmicdrift/kumiko-types/hooks";
|
|
1
2
|
import type { TenantDb } from "../db/tenant-db.ts";
|
|
2
|
-
import {
|
|
3
|
+
import type { Registry, SessionUser } from "../engine/types/index.ts";
|
|
3
4
|
export declare function disposeRemovedFileRefs(args: {
|
|
4
5
|
readonly registry: Registry;
|
|
5
6
|
readonly result: SaveContext;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isFileField
|
|
1
|
+
import { isFileField } from "../engine/field-helpers.js";
|
|
2
2
|
import { reraiseAsKumikoError } from "../errors/index.js";
|
|
3
3
|
import { fileRefIdsOf } from "./bind-pending-file-refs.js";
|
|
4
4
|
import { getFileRefExecutor } from "./create-file-ref.js";
|
package/dist/files/feature.js
CHANGED
|
@@ -41,10 +41,10 @@ export function createFilesFeature(options = {}) {
|
|
|
41
41
|
handler: async (_payload, ctx) => {
|
|
42
42
|
await sweepOrphanedUploads({
|
|
43
43
|
db: ctx.db,
|
|
44
|
-
files: ctx.files,
|
|
44
|
+
files: ctx.services.files,
|
|
45
45
|
now: ctx.tz.now(),
|
|
46
46
|
graceHours: uploadSweepGraceHours,
|
|
47
|
-
log: ctx.log,
|
|
47
|
+
log: ctx.obs.log,
|
|
48
48
|
});
|
|
49
49
|
},
|
|
50
50
|
});
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// The contract the framework exposes to hook/handler code: a FileHandle lets
|
|
4
4
|
// you read/write/delete the binary behind a storage key without ever passing
|
|
5
5
|
// the binary through event payloads, job queues, or hook signatures. Events
|
|
6
|
-
// carry the key, hooks reach for `ctx.files.ref(key)` when they actually need
|
|
6
|
+
// carry the key, hooks reach for `ctx.services.files.ref(key)` when they actually need
|
|
7
7
|
// the bytes, and big files stay in the storage layer where they belong.
|
|
8
8
|
//
|
|
9
9
|
// `derive(suffix)` is the primitive for thumbnail/variant keys: it inserts a
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type { RateLimitResolver } from "@cosmicdrift/kumiko-types/rate-limit-types";
|
|
1
2
|
import type { WriteErrorInfo } from "@cosmicdrift/kumiko-types/write-error-info-types";
|
|
2
3
|
import { Hono } from "hono";
|
|
3
4
|
import type { DbConnection } from "../db/connection.ts";
|
|
4
|
-
import {
|
|
5
|
+
import type { Registry, SessionUser, TenantId } from "../engine/types/index.ts";
|
|
5
6
|
import type { FileProviderResolver } from "./provider-resolver.ts";
|
|
6
7
|
import type { RecordReadCheck } from "./record-read-check.ts";
|
|
7
8
|
import { type RecordWriteCheck } from "./record-write-check.ts";
|
|
@@ -30,6 +31,7 @@ export type FileAccessGuard = (args: {
|
|
|
30
31
|
}) => FileAccessDecision | Promise<FileAccessDecision>;
|
|
31
32
|
export type FileRoutesOptions = {
|
|
32
33
|
readonly db: DbConnection;
|
|
34
|
+
readonly metaBatchRateLimitResolver?: RateLimitResolver;
|
|
33
35
|
readonly resolveProvider: FileProviderResolver;
|
|
34
36
|
readonly registry?: Registry;
|
|
35
37
|
readonly maxUploadSize?: string;
|