@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
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { runInRowLevelSecurityScope, SYSTEM_ROW_LEVEL_SECURITY_SCOPE, tenantRowLevelSecurityScope, } from "../db/row-level-security-scope.js";
|
|
2
|
+
// Handlers declared with r.systemScope() act across tenants, so a single-type dispatch of one runs system-scoped.
|
|
3
|
+
// The caller picks the types of a batch, so a batch is system-scoped only when every command is; each command then
|
|
4
|
+
// narrows or widens to its own type's scope (runInDispatchScope in runReservedCommand).
|
|
5
|
+
export function dispatchRowLevelSecurityScope(registry, types, user) {
|
|
6
|
+
return types.length > 0 && types.every((type) => registry.isHandlerSystemScoped(type))
|
|
7
|
+
? SYSTEM_ROW_LEVEL_SECURITY_SCOPE
|
|
8
|
+
: tenantRowLevelSecurityScope(user.tenantId);
|
|
9
|
+
}
|
|
10
|
+
export function runInDispatchScope(registry, types, user, fn) {
|
|
11
|
+
return runInRowLevelSecurityScope(dispatchRowLevelSecurityScope(registry, types, user), fn);
|
|
12
|
+
}
|
|
13
|
+
// Generator bodies resume in the consumer's async context, so each step re-enters the scope.
|
|
14
|
+
export async function* streamInDispatchScope(scope, source) {
|
|
15
|
+
try {
|
|
16
|
+
while (true) {
|
|
17
|
+
const step = await runInRowLevelSecurityScope(scope, () => source.next());
|
|
18
|
+
// skip: source exhausted
|
|
19
|
+
if (step.done)
|
|
20
|
+
return;
|
|
21
|
+
yield step.value;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
await runInRowLevelSecurityScope(scope, () => source.return(undefined));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CacheSyncBus } from "@cosmicdrift/kumiko-types/cache-sync-types";
|
|
2
|
+
import type { JobRunnerRef, PayloadRateLimitOption, RateLimitDeclaration, WriteResult } from "@cosmicdrift/kumiko-types/handlers";
|
|
2
3
|
import type { SseBroker } from "../api/sse-broker.ts";
|
|
3
4
|
import type { DbConnection, DbTx } from "../db/connection.ts";
|
|
4
5
|
import type { buildEntityTable } from "../db/table-builder.ts";
|
|
@@ -6,9 +7,10 @@ import { type TenantDb } from "../db/tenant-db.ts";
|
|
|
6
7
|
import type { defineTransitions } from "../engine/state-machine.ts";
|
|
7
8
|
import type { EffectiveFeaturesResolver } from "../engine/tier-resolver-extension.ts";
|
|
8
9
|
import type { TenantId } from "../engine/types/identifiers.ts";
|
|
9
|
-
import type { AppContext,
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import type { AppContext, BeforeTransactionContext, HandlerContext, Registry, ReservationContext, SessionUser } from "../engine/types/index.ts";
|
|
11
|
+
import { type WriteErrorInfo } from "../errors/index.ts";
|
|
12
|
+
import type { EscapeHatchReportWindow } from "../observability/escape-hatch-report.ts";
|
|
13
|
+
import type { getFallbackMeter, getFallbackTracer } from "../observability/fallback.ts";
|
|
12
14
|
import { type AfterCommitHook } from "./dispatcher-utils.ts";
|
|
13
15
|
import type { IdempotencyGuard } from "./idempotency.ts";
|
|
14
16
|
import type { LifecycleHooks } from "./lifecycle-pipeline.ts";
|
|
@@ -54,12 +56,8 @@ export type DispatchContext = {
|
|
|
54
56
|
export declare const DEFAULT_MEMBER_READ_TIMEOUT_MS = 10000;
|
|
55
57
|
export declare function resolveDbSource(ctx: DispatchContext, tx: DbTx | undefined): DbConnection | DbTx | undefined;
|
|
56
58
|
export declare function resolveAppPoolDb(ctx: DispatchContext): DbConnection | undefined;
|
|
57
|
-
export declare function createSystemScopedDbGuard(handlerType: string, fieldName: "db" | "
|
|
59
|
+
export declare function createSystemScopedDbGuard(handlerType: string, fieldName: "db" | "db.outsideTransaction", hint: string): TenantDb;
|
|
58
60
|
export declare function isMemberResolutionPrincipal(user: SessionUser): boolean;
|
|
59
|
-
export declare function applyMemberResolutionReadOnly(handlerContext: HandlerContext): HandlerContext;
|
|
60
|
-
export declare function perCommandNestedDenied(targetType: string): InternalError;
|
|
61
|
-
export declare function denyTransactionBoundSurfaces(handlerContext: HandlerContext): HandlerContext;
|
|
62
|
-
export declare function applyBeforeTransactionReadOnly(handlerContext: HandlerContext): HandlerContext;
|
|
63
61
|
export type HandlerTransactionScope = "inTransaction" | "withoutTransaction" | "postCommit";
|
|
64
62
|
export type BuildHandlerContextOptions = {
|
|
65
63
|
tx?: DbTx;
|
|
@@ -67,8 +65,14 @@ export type BuildHandlerContextOptions = {
|
|
|
67
65
|
includeDeleted?: boolean;
|
|
68
66
|
transactionScope?: HandlerTransactionScope;
|
|
69
67
|
outerNotifySink?: AfterCommitHook[];
|
|
70
|
-
|
|
68
|
+
phase?: HandlerPhase;
|
|
71
69
|
};
|
|
70
|
+
export type HandlerPhase = "handler" | "reservation" | "beforeTransaction";
|
|
71
|
+
type PhaseOptions<TPhase extends HandlerPhase> = BuildHandlerContextOptions & {
|
|
72
|
+
phase: TPhase;
|
|
73
|
+
};
|
|
74
|
+
export declare function buildHandlerContext(ctx: DispatchContext, type: string, user: SessionUser, origin: WriteOrigin, options: PhaseOptions<"reservation">): Promise<ReservationContext>;
|
|
75
|
+
export declare function buildHandlerContext(ctx: DispatchContext, type: string, user: SessionUser, origin: WriteOrigin, options: PhaseOptions<"beforeTransaction">): Promise<BeforeTransactionContext>;
|
|
72
76
|
export declare function buildHandlerContext(ctx: DispatchContext, type: string, user: SessionUser, origin: WriteOrigin, options?: BuildHandlerContextOptions): Promise<HandlerContext>;
|
|
73
77
|
export declare function createHandlerBoundDigest(digest: (value: string) => string, handlerName: string): (value: string) => string;
|
|
74
78
|
export declare function runHandlerInstrumented<T>(ctx: DispatchContext, type: string, operation: "query" | "write" | "stream", user: SessionUser, inner: () => Promise<T>): Promise<T>;
|
|
@@ -1,23 +1,32 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolveAgentExposure } from "@cosmicdrift/kumiko-types/agent-exposure";
|
|
2
|
+
import { declaredRateLimitOptions, isRateLimitDisabled } from "@cosmicdrift/kumiko-types/handlers";
|
|
3
|
+
import { requestContext } from "../api/request-context.js";
|
|
4
|
+
import { runWithOrigin } from "../api/request-context-scopes.js";
|
|
5
|
+
import { runInSystemRowLevelSecurityScope } from "../db/row-level-security-scope.js";
|
|
2
6
|
import { createTenantDb } from "../db/tenant-db.js";
|
|
3
|
-
import {
|
|
4
|
-
import { FeatureDisabledError, InternalError,
|
|
7
|
+
import { RateLimitUnavailableError } from "../errors/classes.js";
|
|
8
|
+
import { FeatureDisabledError, InternalError, RateLimitError, } from "../errors/index.js";
|
|
5
9
|
import { createFallbackLogger } from "../logging/utils.js";
|
|
6
|
-
import {
|
|
10
|
+
import { observabilityContext } from "../observability/context.js";
|
|
11
|
+
import { createEscapeHatchReporter } from "../observability/escape-hatch-report.js";
|
|
12
|
+
import { emitDispatcherError, emitDispatcherHandler } from "../observability/standard-metrics.js";
|
|
7
13
|
import { buildBucketKey, buildPayloadBucketKey, normalizePayloadBucketValue, } from "../rate-limit/index.js";
|
|
8
14
|
import { isPlainObject } from "../utils/is-plain-object.js";
|
|
9
15
|
import { resolveAuthClaims as runAuthClaimsResolver } from "./auth-claims-resolver.js";
|
|
10
16
|
import { configAccessorFactoryOf } from "./config-accessor-factory.js";
|
|
17
|
+
import { buildContextServices } from "./context-services.js";
|
|
11
18
|
import { executeQuery } from "./dispatch-query.js";
|
|
12
19
|
import { dispatcherSpanAttributes, isFailedWriteResult, } from "./dispatcher-utils.js";
|
|
13
20
|
import { buildAuthFacet } from "./handler-context-auth.js";
|
|
14
21
|
import { buildConfigFacet, resolveHandlerLocale, resolveHandlerTz, } from "./handler-context-config.js";
|
|
15
|
-
import { buildFileFragment,
|
|
22
|
+
import { buildFileFragment, buildHandlerDbFacet, buildWriteTarget } from "./handler-context-db.js";
|
|
16
23
|
import { buildDispatchFacet, createCommitSinks } from "./handler-context-dispatch.js";
|
|
17
24
|
import { buildEventStoreFacet } from "./handler-context-events.js";
|
|
25
|
+
import { applyMemberResolutionReadOnly } from "./handler-context-member-resolution.js";
|
|
18
26
|
import { buildNotifyFacet } from "./handler-context-notify.js";
|
|
19
27
|
import { buildObservabilityFacet } from "./handler-context-observability.js";
|
|
20
|
-
import {
|
|
28
|
+
import { applyBeforeTransactionReadOnly, denyEventStoreSurfaces, denyTransactionBoundSurfaces, withoutTransactionDenied, } from "./handler-context-phase-denials.js";
|
|
29
|
+
import { buildLifecycleSignal, buildPreSave, buildRuntimeServices, resolveHandlerContextScope, } from "./handler-context-scope.js";
|
|
21
30
|
import { createGatedIdentitySwitch, isSystemIdentity } from "./system-identity-switch.js";
|
|
22
31
|
import { TENANT_TIMEZONE_CONFIG_KEY } from "./tenant-timezone-config-key.js";
|
|
23
32
|
import { rootWriteOrigin } from "./write-origin.js";
|
|
@@ -42,14 +51,17 @@ export function resolveAppPoolDb(ctx) {
|
|
|
42
51
|
// r.systemScope() handlers must go through ctx.systemDb's guarded methods
|
|
43
52
|
// (assertTenantMatch / acknowledgeCrossTenant) instead of plain ctx.db —
|
|
44
53
|
// "system" mode has no tenant filter at all, so silent ctx.db or
|
|
45
|
-
// ctx.
|
|
54
|
+
// ctx.db.outsideTransaction use there is a cross-tenant leak. HandlerContext
|
|
46
55
|
// has no way to make either field optional per handler (isSystem is a
|
|
47
56
|
// runtime-only registry lookup, not a type-level discriminant), so instead
|
|
48
57
|
// of omitting the key we hand back a Proxy that throws on first touch,
|
|
49
58
|
// naming the handler and pointing at the matching ctx.systemDb escape hatch.
|
|
59
|
+
// Only the db guard answers `outsideTransaction` (the inner guard, set by attachOutsideTransaction).
|
|
50
60
|
export function createSystemScopedDbGuard(handlerType, fieldName, hint) {
|
|
51
61
|
return new Proxy({}, {
|
|
52
|
-
get(
|
|
62
|
+
get(target, prop) {
|
|
63
|
+
if (fieldName === "db" && prop === "outsideTransaction")
|
|
64
|
+
return Reflect.get(target, prop);
|
|
53
65
|
throw new InternalError({
|
|
54
66
|
message: `Handler "${handlerType}" is r.systemScope()'d — ctx.${fieldName} is unavailable ` +
|
|
55
67
|
`(it would be unfiltered across every tenant). Use ${hint} ` +
|
|
@@ -61,219 +73,85 @@ export function createSystemScopedDbGuard(handlerType, fieldName, hint) {
|
|
|
61
73
|
export function isMemberResolutionPrincipal(user) {
|
|
62
74
|
return user.origin === "member-resolution";
|
|
63
75
|
}
|
|
64
|
-
async function denyMemberResolutionWrite() {
|
|
65
|
-
throw memberResolutionReadOnlyDenied();
|
|
66
|
-
}
|
|
67
|
-
// JobRunnerRef's declared type only carries handleEvent, but callers
|
|
68
|
-
// routinely bracket-access a fuller runner — a Proxy denies ANY property read.
|
|
69
|
-
function denyingJobRunnerProxy(denied = memberResolutionReadOnlyDenied) {
|
|
70
|
-
return new Proxy({}, {
|
|
71
|
-
get() {
|
|
72
|
-
throw denied();
|
|
73
|
-
},
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
// Allowlist (not denylist): a method added to the target later stays denied
|
|
77
|
-
// until someone decides it is read-only.
|
|
78
|
-
function allowlistedReadOnlyProxy(target, allowedMethods) {
|
|
79
|
-
return new Proxy(target, {
|
|
80
|
-
get(inner, prop) {
|
|
81
|
-
if (typeof prop === "string" && allowedMethods.has(prop)) {
|
|
82
|
-
const method = Reflect.get(inner, prop, inner);
|
|
83
|
-
return typeof method === "function" ? method.bind(inner) : method;
|
|
84
|
-
}
|
|
85
|
-
// Symbol reads and "then" come from await/Promise.resolve/inspect, not from handler code.
|
|
86
|
-
if (typeof prop === "symbol" || prop === "then")
|
|
87
|
-
return undefined;
|
|
88
|
-
throw memberResolutionReadOnlyDenied();
|
|
89
|
-
},
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
const MEMBER_READ_SEARCH_METHODS = new Set(["search"]);
|
|
93
|
-
const MEMBER_READ_ENTITY_CACHE_METHODS = new Set(["get", "mget"]);
|
|
94
|
-
const MEMBER_READ_REDIS_METHODS = new Set([
|
|
95
|
-
"get",
|
|
96
|
-
"mget",
|
|
97
|
-
"exists",
|
|
98
|
-
"ttl",
|
|
99
|
-
"pttl",
|
|
100
|
-
"strlen",
|
|
101
|
-
"type",
|
|
102
|
-
"hget",
|
|
103
|
-
"hmget",
|
|
104
|
-
"hgetall",
|
|
105
|
-
"hexists",
|
|
106
|
-
"hlen",
|
|
107
|
-
"sismember",
|
|
108
|
-
"smembers",
|
|
109
|
-
"scard",
|
|
110
|
-
"llen",
|
|
111
|
-
"lrange",
|
|
112
|
-
"zscore",
|
|
113
|
-
"zcard",
|
|
114
|
-
"zrange",
|
|
115
|
-
]);
|
|
116
|
-
// Every write/side-effect surface throws, so "no writeAsMember" holds even
|
|
117
|
-
// if a handler tries ctx.write directly on a resolved member principal.
|
|
118
|
-
// Deliberately open: `db` (guarded by the READ ONLY transaction + memberReadOnly grant),
|
|
119
|
-
// and read-only methods of searchAdapter / redis / entityCache (allowlisted).
|
|
120
|
-
export function applyMemberResolutionReadOnly(handlerContext) {
|
|
121
|
-
return {
|
|
122
|
-
...handlerContext,
|
|
123
|
-
// `db` stays open — executeQuery runs the whole handler in a Postgres READ ONLY
|
|
124
|
-
// transaction, and its `memberReadOnly` grant denies every raw-runner handout.
|
|
125
|
-
dbOutsideTransaction: undefined,
|
|
126
|
-
write: denyMemberResolutionWrite,
|
|
127
|
-
writeAs: denyMemberResolutionWrite,
|
|
128
|
-
// A resolved member cannot switch identity either — the target would get a normal, writable context.
|
|
129
|
-
queryAs: denyMemberResolutionWrite,
|
|
130
|
-
appendEvent: denyMemberResolutionWrite, // @cast-boundary engine-bridge
|
|
131
|
-
unsafeAppendEvent: denyMemberResolutionWrite,
|
|
132
|
-
tryAppendEvent: denyMemberResolutionWrite,
|
|
133
|
-
fetchForWriting: denyMemberResolutionWrite,
|
|
134
|
-
archiveStream: denyMemberResolutionWrite,
|
|
135
|
-
restoreStream: denyMemberResolutionWrite,
|
|
136
|
-
snapshotAggregate: denyMemberResolutionWrite,
|
|
137
|
-
queryAsMember: denyMemberResolutionWrite,
|
|
138
|
-
forTenant: undefined,
|
|
139
|
-
resolveActiveMembership: denyMemberResolutionWrite,
|
|
140
|
-
scheduleAfterCommit: () => {
|
|
141
|
-
throw memberResolutionReadOnlyDenied();
|
|
142
|
-
},
|
|
143
|
-
// A read as a member gets no system-scope DB, preSave pipeline or file storage.
|
|
144
|
-
runPreSave: undefined,
|
|
145
|
-
systemDb: undefined,
|
|
146
|
-
crossTenantReads: undefined,
|
|
147
|
-
files: undefined,
|
|
148
|
-
derivatives: undefined,
|
|
149
|
-
...(handlerContext.jobRunner && { jobRunner: denyingJobRunnerProxy() }),
|
|
150
|
-
...(handlerContext.notify && { notify: denyMemberResolutionWrite }),
|
|
151
|
-
...(handlerContext.searchAdapter && {
|
|
152
|
-
searchAdapter: allowlistedReadOnlyProxy(handlerContext.searchAdapter, MEMBER_READ_SEARCH_METHODS),
|
|
153
|
-
}),
|
|
154
|
-
...(handlerContext.redis && {
|
|
155
|
-
redis: allowlistedReadOnlyProxy(handlerContext.redis, MEMBER_READ_REDIS_METHODS),
|
|
156
|
-
}),
|
|
157
|
-
...(handlerContext.entityCache && {
|
|
158
|
-
entityCache: allowlistedReadOnlyProxy(handlerContext.entityCache, MEMBER_READ_ENTITY_CACHE_METHODS),
|
|
159
|
-
}),
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
function beforeTransactionDenied(surface) {
|
|
163
|
-
return new InternalError({
|
|
164
|
-
message: `ctx.${surface} is not available before the transaction; move it into the handler`,
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
function withoutTransactionDenied(surface) {
|
|
168
|
-
return new InternalError({
|
|
169
|
-
message: `ctx.${surface} is not available without an open transaction; run the write through ctx.write so it gets its own transaction`,
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
export function perCommandNestedDenied(targetType) {
|
|
173
|
-
return new InternalError({
|
|
174
|
-
message: `handler "${targetType}" runs without a transaction (transaction: "perCommand") and cannot run as a nested write inside an open transaction`,
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
function denySurface(buildError, surface) {
|
|
178
|
-
return () => {
|
|
179
|
-
throw buildError(surface);
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
function denyEventStoreSurfaces(handlerContext, buildError) {
|
|
183
|
-
return {
|
|
184
|
-
...handlerContext,
|
|
185
|
-
appendEvent: denySurface(buildError, "appendEvent"),
|
|
186
|
-
unsafeAppendEvent: denySurface(buildError, "unsafeAppendEvent"),
|
|
187
|
-
tryAppendEvent: denySurface(buildError, "tryAppendEvent"),
|
|
188
|
-
fetchForWriting: denySurface(buildError, "fetchForWriting"),
|
|
189
|
-
archiveStream: denySurface(buildError, "archiveStream"),
|
|
190
|
-
restoreStream: denySurface(buildError, "restoreStream"),
|
|
191
|
-
snapshotAggregate: denySurface(buildError, "snapshotAggregate"),
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
// Reservations write on purpose through the outside-transaction handles, so they keep those but
|
|
195
|
-
// lose every surface bound to the not-yet-open transaction.
|
|
196
|
-
export function denyTransactionBoundSurfaces(handlerContext) {
|
|
197
|
-
return {
|
|
198
|
-
...denyEventStoreSurfaces(handlerContext, beforeTransactionDenied),
|
|
199
|
-
write: denySurface(beforeTransactionDenied, "write"),
|
|
200
|
-
writeAs: denySurface(beforeTransactionDenied, "writeAs"),
|
|
201
|
-
scheduleAfterCommit: denySurface(beforeTransactionDenied, "scheduleAfterCommit"),
|
|
202
|
-
...(handlerContext.notify && { notify: denySurface(beforeTransactionDenied, "notify") }),
|
|
203
|
-
...(handlerContext.jobRunner && {
|
|
204
|
-
jobRunner: denyingJobRunnerProxy(() => beforeTransactionDenied("jobRunner")),
|
|
205
|
-
}),
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
// The beforeTransaction phase has no write need at all, so it also loses the outside-transaction handles.
|
|
209
|
-
export function applyBeforeTransactionReadOnly(handlerContext) {
|
|
210
|
-
return {
|
|
211
|
-
...denyTransactionBoundSurfaces(handlerContext),
|
|
212
|
-
dbOutsideTransaction: undefined,
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
76
|
export async function buildHandlerContext(ctx, type, user, origin, options = {}) {
|
|
216
|
-
const { tx, afterCommitHooks, includeDeleted, outerNotifySink,
|
|
77
|
+
const { tx, afterCommitHooks, includeDeleted, outerNotifySink, phase = "handler", transactionScope = tx ? "inTransaction" : "withoutTransaction", } = options;
|
|
78
|
+
const readOnlyForTenant = phase === "beforeTransaction";
|
|
217
79
|
const scope = resolveHandlerContextScope({ ctx, type, user, origin, tx, transactionScope });
|
|
218
80
|
const dbFacet = buildHandlerDbFacet(scope);
|
|
219
81
|
const observability = buildObservabilityFacet(scope);
|
|
220
82
|
const sinks = createCommitSinks(afterCommitHooks, transactionScope, outerNotifySink);
|
|
221
83
|
const notifyFacet = buildNotifyFacet(scope, sinks, dbFacet.outsideTxSource);
|
|
222
84
|
const configFacet = buildConfigFacet(scope, dbFacet.db);
|
|
223
|
-
const
|
|
85
|
+
const writeTarget = buildWriteTarget(scope, dbFacet.exposedDb, readOnlyForTenant);
|
|
224
86
|
const fileFragment = buildFileFragment(scope, dbFacet.db);
|
|
225
|
-
const dispatchFacet = buildDispatchFacet(scope, sinks);
|
|
226
87
|
const authFacet = buildAuthFacet(scope);
|
|
227
88
|
const eventStoreFacet = buildEventStoreFacet(scope);
|
|
89
|
+
const dispatchFacet = buildDispatchFacet(scope, sinks, {
|
|
90
|
+
queryAsMember: authFacet.queryAsMember,
|
|
91
|
+
queryProjection: eventStoreFacet.queryProjection,
|
|
92
|
+
});
|
|
228
93
|
const tz = await resolveHandlerTz(scope, configFacet.config);
|
|
229
94
|
const locale = resolveHandlerLocale(scope);
|
|
230
|
-
|
|
231
|
-
//
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
95
|
+
const { _rateLimitPayloadDigest: payloadDigest } = scope.context;
|
|
96
|
+
// The final context (after the phase wrappers below) is what preSave hooks must see.
|
|
97
|
+
const finalContext = {};
|
|
98
|
+
const runPreSave = buildPreSave(scope, () => {
|
|
99
|
+
if (finalContext.current === undefined) {
|
|
100
|
+
throw new InternalError({
|
|
101
|
+
message: "lifecycle.runPreSave called before the context was built",
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
return finalContext.current;
|
|
105
|
+
});
|
|
235
106
|
const handlerContext = {
|
|
236
|
-
...contextForHandler,
|
|
237
|
-
...(payloadDigest && { rateLimitDigest: createHandlerBoundDigest(payloadDigest, type) }),
|
|
238
|
-
...notifyFacet.factoryFragment,
|
|
239
107
|
// Registry is always the dispatcher's registry — injecting it here lets
|
|
240
108
|
// tests/callers pass `context` without `registry` and still get a valid
|
|
241
|
-
// HandlerContext.
|
|
242
|
-
// `context` can be overridden, but we want the authoritative registry
|
|
243
|
-
// from the dispatcher's own closure to win.
|
|
109
|
+
// HandlerContext.
|
|
244
110
|
registry: scope.registry,
|
|
245
111
|
...dbFacet.fragment,
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
...
|
|
249
|
-
...
|
|
250
|
-
...
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
112
|
+
// The payload-bucket digest is dispatcher-internal; handlers get one bound to their own name.
|
|
113
|
+
...(payloadDigest && { rateLimitDigest: createHandlerBoundDigest(payloadDigest, type) }),
|
|
114
|
+
...observability,
|
|
115
|
+
...(notifyFacet.notify && { notify: notifyFacet.notify }),
|
|
116
|
+
...(configFacet.config && { config: configFacet.config }),
|
|
117
|
+
services: buildContextServices(scope.context, {
|
|
118
|
+
...fileFragment,
|
|
119
|
+
...buildRuntimeServices(scope),
|
|
120
|
+
...notifyFacet.factoryServices,
|
|
121
|
+
}),
|
|
122
|
+
lifecycle: {
|
|
123
|
+
...(runPreSave && { runPreSave }),
|
|
124
|
+
...dispatchFacet.commitHooks,
|
|
125
|
+
...buildLifecycleSignal(scope),
|
|
126
|
+
},
|
|
127
|
+
tenants: {
|
|
128
|
+
...(configFacet.configFor && { config: configFacet.configFor }),
|
|
129
|
+
...(writeTarget && { writeTarget }),
|
|
130
|
+
},
|
|
255
131
|
tz,
|
|
256
132
|
locale,
|
|
257
|
-
|
|
258
|
-
// ctx.user as a convenience alias for event.user. The intuitive path—"the
|
|
259
|
-
// context knows its user"—lets handlers avoid writing `event.user.tenantId`
|
|
260
|
-
// and reduces errors in ctx.user access patterns. It is identical to
|
|
261
|
-
// event.user; identity switches still use queryAs/writeAs.
|
|
133
|
+
// ctx.user as a convenience alias for event.user. Identity switches still use queryAs/writeAs.
|
|
262
134
|
user,
|
|
263
|
-
_tenantId: user.tenantId,
|
|
264
|
-
...dispatchFacet.scheduleFragment,
|
|
265
135
|
...(includeDeleted && { includeDeleted: true }),
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
136
|
+
dispatch: dispatchFacet.dispatch,
|
|
137
|
+
events: eventStoreFacet.events,
|
|
138
|
+
auth: authFacet.auth,
|
|
139
|
+
hasFeature: authFacet.hasFeature,
|
|
269
140
|
}; // @cast-boundary engine-bridge
|
|
270
141
|
const scopedContext = transactionScope === "withoutTransaction"
|
|
271
142
|
? denyEventStoreSurfaces(handlerContext, withoutTransactionDenied)
|
|
272
143
|
: handlerContext;
|
|
273
144
|
// A resolved member principal is read-only by construction.
|
|
274
|
-
|
|
145
|
+
const memberSafeContext = isMemberResolutionPrincipal(user)
|
|
275
146
|
? applyMemberResolutionReadOnly(scopedContext)
|
|
276
147
|
: scopedContext;
|
|
148
|
+
const phasedContext = phase === "reservation"
|
|
149
|
+
? denyTransactionBoundSurfaces(memberSafeContext)
|
|
150
|
+
: phase === "beforeTransaction"
|
|
151
|
+
? applyBeforeTransactionReadOnly(memberSafeContext)
|
|
152
|
+
: memberSafeContext;
|
|
153
|
+
finalContext.current = phasedContext;
|
|
154
|
+
return phasedContext;
|
|
277
155
|
}
|
|
278
156
|
// The handler-name prefix keeps a handler from reproducing the digests the
|
|
279
157
|
// dispatcher uses for payload buckets (those hash the bare normalized value).
|
|
@@ -655,7 +533,10 @@ function buildAuthClaimsContext(ctx, user) {
|
|
|
655
533
|
...(configAccessor && { config: configAccessor }),
|
|
656
534
|
};
|
|
657
535
|
}
|
|
658
|
-
export
|
|
536
|
+
export function resolveAuthClaimsFn(ctx, user) {
|
|
537
|
+
return runInSystemRowLevelSecurityScope("auth claims resolution reads memberships before a tenant is known", () => resolveAuthClaimsInScope(ctx, user));
|
|
538
|
+
}
|
|
539
|
+
async function resolveAuthClaimsInScope(ctx, user) {
|
|
659
540
|
const { registry, appContext: context } = ctx;
|
|
660
541
|
const hooks = registry.getAuthClaimsHooks();
|
|
661
542
|
if (hooks.length === 0)
|
|
@@ -2,8 +2,11 @@ import { accessInvalidationCredentialFor } from "../api/sse-broker.js";
|
|
|
2
2
|
import { scheduleTokenExpiry } from "../api/token-expiry-timer.js";
|
|
3
3
|
import { hasAccess } from "../engine/access.js";
|
|
4
4
|
import { tenantOverrideDenied } from "../engine/cross-tenant.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { UnauthenticatedError } from "../errors/classes.js";
|
|
6
|
+
import { AccessDeniedError, NotFoundError, validationErrorFromZod } from "../errors/index.js";
|
|
7
|
+
import { memberResolutionReadOnlyDenied } from "../errors/member-resolution.js";
|
|
8
|
+
import { assertNoSecretLeak } from "../secrets/leak-guard.js";
|
|
9
|
+
import { dispatchRowLevelSecurityScope, streamInDispatchScope } from "./dispatch-scope.js";
|
|
7
10
|
import { buildHandlerContext, enforceRateLimit, ensureFeatureEnabled, isMemberResolutionPrincipal, runStreamInstrumented, } from "./dispatch-shared.js";
|
|
8
11
|
import { handlerAccessError } from "./handler-access-error.js";
|
|
9
12
|
// Standalone stream execution — used by the public dispatcher.stream().
|
|
@@ -13,14 +16,15 @@ import { handlerAccessError } from "./handler-access-error.js";
|
|
|
13
16
|
// write/queryHandler — see feature-entity-handlers.ts), so there's no
|
|
14
17
|
// field-access filter or postQuery-hook stage to run here.
|
|
15
18
|
export async function* executeStream(ctx, type, payload, user, origin, options) {
|
|
16
|
-
|
|
19
|
+
const scope = dispatchRowLevelSecurityScope(ctx.registry, [type], user);
|
|
20
|
+
yield* streamInDispatchScope(scope, runStreamInstrumented(ctx, type, user, () => executeStreamInner(ctx, type, payload, user, origin, options)));
|
|
17
21
|
}
|
|
18
22
|
async function* executeStreamInner(ctx, type, payload, user, origin, options) {
|
|
19
23
|
const { registry } = ctx;
|
|
20
24
|
const handler = registry.getStreamHandler(type);
|
|
21
25
|
if (!handler)
|
|
22
26
|
throw new NotFoundError("handler", type);
|
|
23
|
-
// A resolved member principal (ctx.queryAsMember) is read-only — streams
|
|
27
|
+
// A resolved member principal (ctx.dispatch.queryAsMember) is read-only — streams
|
|
24
28
|
// are excluded the same way executeWriteInner excludes writes.
|
|
25
29
|
if (isMemberResolutionPrincipal(user)) {
|
|
26
30
|
throw memberResolutionReadOnlyDenied();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { WriteResult } from "@cosmicdrift/kumiko-types/handlers";
|
|
1
2
|
import type { DbTx } from "../db/connection.ts";
|
|
2
|
-
import type { SessionUser
|
|
3
|
+
import type { SessionUser } from "../engine/types/index.ts";
|
|
3
4
|
import type { DispatchContext, WriteOrigin } from "./dispatch-shared.ts";
|
|
4
5
|
import { type AfterCommitHook } from "./dispatcher-utils.ts";
|
|
5
6
|
export declare function executeWrite(ctx: DispatchContext, type: string, payload: unknown, user: SessionUser, origin: WriteOrigin, tx: DbTx | undefined, afterCommitHooks: AfterCommitHook[]): Promise<WriteResult>;
|
|
@@ -5,17 +5,19 @@ import { createTenantDb, hasTenantColumn } from "../db/tenant-db.js";
|
|
|
5
5
|
import { tenantDbRunner } from "../db/tenant-db-runner.js";
|
|
6
6
|
import { ConfigScopes } from "../engine/constants.js";
|
|
7
7
|
import { checkWriteFieldOwnership, maskWriteOnlyFields } from "../engine/field-access.js";
|
|
8
|
+
import { HookPhases } from "../engine/hook-helpers.js";
|
|
8
9
|
import { defineTransitions, guardTransition } from "../engine/state-machine.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
10
|
+
import { AccessDeniedError, FrameworkReasons, InternalError, NotFoundError, ValidationError, writeFailure, } from "../errors/index.js";
|
|
11
|
+
import { memberResolutionReadOnlyDenied } from "../errors/member-resolution.js";
|
|
11
12
|
import { assertFileRefsBelongToTenant } from "../files/assert-file-refs-belong-to-tenant.js";
|
|
12
13
|
import { bindPendingFileRefs } from "../files/bind-pending-file-refs.js";
|
|
13
14
|
import { disposeRemovedFileRefs } from "../files/dispose-removed-file-refs.js";
|
|
14
15
|
import { loadSaveFileRefs } from "../files/load-save-file-refs.js";
|
|
15
16
|
import { CACHE_SYNC_TOPICS } from "../redis/cache-sync-topics.js";
|
|
16
|
-
import { assertNoSecretLeak } from "../secrets/
|
|
17
|
-
import { buildHandlerContext, CONFIG_WRITE_RESET_TYPE, CONFIG_WRITE_SET_TYPE, isMemberResolutionPrincipal,
|
|
17
|
+
import { assertNoSecretLeak } from "../secrets/leak-guard.js";
|
|
18
|
+
import { buildHandlerContext, CONFIG_WRITE_RESET_TYPE, CONFIG_WRITE_SET_TYPE, isMemberResolutionPrincipal, resolveDbSource, runHandlerInstrumented, TENANT_TIMEZONE_CONFIG_KEY, } from "./dispatch-shared.js";
|
|
18
19
|
import { describeShape, extractNestedSpecs, isLifecycleResult, isWriteResultShape, prefixValidationPath, wrapToKumiko, } from "./dispatcher-utils.js";
|
|
20
|
+
import { perCommandNestedDenied } from "./handler-context-phase-denials.js";
|
|
19
21
|
import { runPreHandlerGates } from "./pre-handler-gates.js";
|
|
20
22
|
import { consumeReservation, hasPreTransactionPhase, } from "./pre-transaction-reservations.js";
|
|
21
23
|
import { runProjections } from "./projections-runner.js";
|
|
@@ -108,11 +110,11 @@ async function settleSaveFileRefs(handlerContext, result, user) {
|
|
|
108
110
|
async function runLifecycle(ctx, type, data, handlerContext, user, origin, afterCommitHooks, runner) {
|
|
109
111
|
const { lifecycle } = ctx;
|
|
110
112
|
if (!lifecycle) {
|
|
111
|
-
handlerContext.log
|
|
113
|
+
handlerContext.obs.log.debug(`runLifecycle: skipping ${type} — no lifecycle pipeline`);
|
|
112
114
|
return;
|
|
113
115
|
}
|
|
114
116
|
if (!isLifecycleResult(data)) {
|
|
115
|
-
handlerContext.log
|
|
117
|
+
handlerContext.obs.log.debug(`runLifecycle: skipping ${type} — result is not a lifecycle kind`);
|
|
116
118
|
return;
|
|
117
119
|
}
|
|
118
120
|
const result = data;
|
|
@@ -369,7 +371,7 @@ function resolveWriteEntry(ctx, type, user, tx) {
|
|
|
369
371
|
if (!handler)
|
|
370
372
|
return failedStep(writeFailure(new NotFoundError("handler", type)));
|
|
371
373
|
// Defense in depth — covers runBatch and a spread-copied user that kept
|
|
372
|
-
// `origin`, beyond buildHandlerContext's own ctx.write replacement.
|
|
374
|
+
// `origin`, beyond buildHandlerContext's own ctx.dispatch.write replacement.
|
|
373
375
|
if (isMemberResolutionPrincipal(user)) {
|
|
374
376
|
return failedStep(writeFailure(memberResolutionReadOnlyDenied()));
|
|
375
377
|
}
|
|
@@ -389,7 +391,7 @@ async function runWriteGates(ctx, handler, type, payload, user) {
|
|
|
389
391
|
return failedStep(gates);
|
|
390
392
|
const parsedPayload = reservation ? reservation.parsedPayload : gates.payload;
|
|
391
393
|
// A handler with a pre-transaction phase cannot run that phase from inside an open transaction;
|
|
392
|
-
// running it without would skip the reservation or the prepared data, so a nested ctx.write of
|
|
394
|
+
// running it without would skip the reservation or the prepared data, so a nested ctx.dispatch.write of
|
|
393
395
|
// such a handler is rejected instead.
|
|
394
396
|
if (needsPreTransactionPhase && !reservation) {
|
|
395
397
|
return failedStep(writeFailure(new InternalError({
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type { HandlerRef,
|
|
1
|
+
import type { HandlerRef, WriteResult } from "@cosmicdrift/kumiko-types/handlers";
|
|
2
|
+
import type { LifecycleResult } from "@cosmicdrift/kumiko-types/hooks";
|
|
3
|
+
import type { Registry, SessionUser } from "../engine/types/index.ts";
|
|
2
4
|
import { type KumikoError, type WriteErrorInfo } from "../errors/index.ts";
|
|
3
5
|
export type FailedWriteResult = Extract<WriteResult, {
|
|
4
6
|
isSuccess: false;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { isInvalidDateTimeValue } from "../db/pg-error.js";
|
|
1
2
|
import { parseQn, qn } from "../engine/qualified-name.js";
|
|
2
|
-
import {
|
|
3
|
+
import { ValidationError, VersionConflictError, } from "../errors/index.js";
|
|
4
|
+
import { toKumikoError } from "../errors/to-kumiko-error.js";
|
|
3
5
|
import { VersionConflictError as EventStoreVersionConflictError } from "../event-store/errors.js";
|
|
4
6
|
export function isFailedWriteResult(result) {
|
|
5
7
|
return (!!result && typeof result === "object" && "isSuccess" in result && result.isSuccess === false);
|
|
@@ -140,7 +142,7 @@ export class NestedWriteRollback extends Error {
|
|
|
140
142
|
export function resolveType(type) {
|
|
141
143
|
return typeof type === "string" ? type : type.name;
|
|
142
144
|
}
|
|
143
|
-
// A custom write losing an append race (ctx.
|
|
145
|
+
// A custom write losing an append race (ctx.events.append, stream.append) is a
|
|
144
146
|
// retryable 409 like the CRUD executor's, not an internal error. Mapped here
|
|
145
147
|
// because errors/ is client code and must not import the event store.
|
|
146
148
|
// currentVersion -1 is the "not looked up" sentinel for a bare 23505 fallback.
|
|
@@ -152,5 +154,9 @@ export function wrapToKumiko(e) {
|
|
|
152
154
|
currentVersion: e.currentVersion ?? -1,
|
|
153
155
|
}, { cause: e });
|
|
154
156
|
}
|
|
157
|
+
// Payload schemas without z.iso.date() let impossible dates reach the column; that is bad input, not a 500.
|
|
158
|
+
if (isInvalidDateTimeValue(e)) {
|
|
159
|
+
return new ValidationError({ fields: [] }, { cause: e instanceof Error ? e : undefined });
|
|
160
|
+
}
|
|
155
161
|
return toKumikoError(e);
|
|
156
162
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import type { CacheSyncBus } from "@cosmicdrift/kumiko-types/cache-sync-types";
|
|
2
|
+
import type { ActiveMembershipResult, DispatchWriteRef, JobRunnerRef, MemberReader, WriteResult } from "@cosmicdrift/kumiko-types/handlers";
|
|
2
3
|
import type { SseBroker } from "../api/sse-broker.ts";
|
|
3
4
|
import type { DbConnection } from "../db/connection.ts";
|
|
4
5
|
import type { EffectiveFeaturesResolver } from "../engine/tier-resolver-extension.ts";
|
|
5
6
|
import type { TenantId } from "../engine/types/identifiers.ts";
|
|
6
|
-
import type {
|
|
7
|
+
import type { AppContext, Registry, SessionUser } from "../engine/types/index.ts";
|
|
7
8
|
import type { BatchCommand, BatchResult } from "./dispatch-shared.ts";
|
|
8
9
|
import { type StreamOptions } from "./dispatch-stream.ts";
|
|
9
10
|
import { type HandlerType } from "./dispatcher-utils.ts";
|
|
10
11
|
import type { IdempotencyGuard } from "./idempotency.ts";
|
|
11
12
|
import type { LifecycleHooks } from "./lifecycle-pipeline.ts";
|
|
12
|
-
export type { WriteResult } from "
|
|
13
|
+
export type { WriteResult } from "@cosmicdrift/kumiko-types/handlers";
|
|
13
14
|
export type { BatchCommand, BatchResult } from "./dispatch-shared.ts";
|
|
14
15
|
export type DispatcherOptions = {
|
|
15
16
|
idempotency?: IdempotencyGuard;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { runWithWriteOrigin } from "../api/request-context.js";
|
|
1
|
+
import { runWithWriteOrigin } from "../api/request-context-scopes.js";
|
|
2
2
|
import { TENANT_MEMBERSHIPS_QUERY } from "../engine/extension-names.js";
|
|
3
3
|
import { InternalError, reraiseAsKumikoError } from "../errors/index.js";
|
|
4
|
-
import { withEscapeHatchAuditScopeStream } from "../observability/escape-hatch-report.js";
|
|
5
|
-
import {
|
|
4
|
+
import { createEscapeHatchReportWindow, withEscapeHatchAuditScope, withEscapeHatchAuditScopeStream, } from "../observability/escape-hatch-report.js";
|
|
5
|
+
import { getFallbackMeter, getFallbackTracer } from "../observability/fallback.js";
|
|
6
|
+
import { registerStandardMetrics } from "../observability/standard-metrics.js";
|
|
6
7
|
import { CACHE_SYNC_TOPICS, isTenantConfigSyncMessage } from "../redis/cache-sync-topics.js";
|
|
7
8
|
import { INTERACTIVE_SIGN_IN_POLICY, resolveActiveMembershipFn } from "./active-membership.js";
|
|
8
9
|
import { runBatch, unwrapSingle } from "./dispatch-batch.js";
|
|
@@ -12,5 +12,4 @@ export declare const ConsumerStatuses: {
|
|
|
12
12
|
readonly dead: "dead";
|
|
13
13
|
readonly disabled: "disabled";
|
|
14
14
|
};
|
|
15
|
-
export type ConsumerStatus = (typeof ConsumerStatuses)[keyof typeof ConsumerStatuses];
|
|
16
15
|
export declare function createEventConsumerStateTable(db: DbConnection): Promise<void>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/// <reference types="temporal-polyfill/global" preserve="true" />
|
|
2
|
+
import type { Meter } from "@cosmicdrift/kumiko-types/observability";
|
|
2
3
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
3
4
|
import type { DbConnection, DbRunner, DbTx } from "../db/connection.ts";
|
|
4
5
|
import { type PendingIdRange } from "../db/queries/event-store.ts";
|
|
5
6
|
import type { AppContext } from "../engine/types/index.ts";
|
|
6
|
-
import { type Meter } from "../observability/index.ts";
|
|
7
7
|
import { type PendingGapEntry } from "./event-consumer-state.ts";
|
|
8
8
|
import type { EventConsumer } from "./event-dispatcher.ts";
|
|
9
9
|
export type ConsumerStateRowShape = {
|