@cosmicdrift/kumiko-framework 0.389.0 → 0.390.1
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 +9 -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/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 +3 -3
- package/agents/examples/managed-config.md +4 -4
- package/agents/examples/managed-pages.md +1 -1
- 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 +2 -2
- 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 +4 -4
- package/agents/features.md +1 -1
- package/dist/api/auth-middleware.js +1 -1
- package/dist/api/auth-routes-invite.js +2 -1
- package/dist/api/entity-read-access.d.ts +3 -1
- package/dist/api/export/export-columns.d.ts +3 -1
- package/dist/api/export/export-route.js +3 -2
- package/dist/api/export/export-screen.d.ts +2 -1
- package/dist/api/extra-route.d.ts +3 -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/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.js +7 -3
- 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 +2 -1
- package/dist/api/server-middleware.js +3 -1
- package/dist/api/server-routes.d.ts +2 -1
- package/dist/api/server-wiring.js +6 -4
- package/dist/api/server.d.ts +2 -1
- package/dist/api/sse-route.d.ts +2 -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 +10 -10
- 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.js +6 -1
- 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/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 +3 -1
- package/dist/db/connection.js +15 -5
- 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-value-preparation.js +23 -2
- 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-filter.d.ts +1 -1
- 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.js +8 -7
- package/dist/db/event-store-executor-write-steps.d.ts +3 -2
- package/dist/db/event-store-executor-write.js +7 -4
- package/dist/db/event-store-executor.d.ts +1 -1
- package/dist/db/executor-managed-tables.d.ts +7 -1
- package/dist/db/executor-managed-tables.js +11 -2
- 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 +4 -0
- 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 +11 -0
- 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 +9 -25
- package/dist/db/queries/test-stack.d.ts +4 -1
- package/dist/db/queries/test-stack.js +84 -2
- package/dist/db/query.js +11 -7
- package/dist/db/reference-data.d.ts +1 -1
- package/dist/db/reference-data.js +6 -1
- 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 +6 -0
- package/dist/db/row-level-security-boot-check.js +86 -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/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.d.ts +17 -12
- package/dist/db/tenant-db.js +49 -120
- 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/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 +1 -1
- package/dist/engine/boot-validator/list-table-aggregate-options.d.ts +1 -1
- package/dist/engine/boot-validator/list-table-aggregate-query.d.ts +2 -1
- 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/query-refs.d.ts +2 -1
- package/dist/engine/boot-validator/screens-forms.d.ts +2 -1
- package/dist/engine/boot-validator/screens-kind-shared.d.ts +3 -1
- 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/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 +1 -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 +8 -1
- 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.js +1 -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 +2 -1
- package/dist/engine/handler-field-references.d.ts +0 -4
- package/dist/engine/index.d.ts +57 -54
- package/dist/engine/index.js +22 -27
- 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 +0 -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/template-variables.d.ts +2 -1
- package/dist/engine/transfer-adjacency.d.ts +1 -1
- package/dist/engine/types/index.d.ts +8 -31
- package/dist/engine/types/index.js +2 -10
- package/dist/engine/validation.d.ts +2 -1
- package/dist/entrypoint/index.d.ts +7 -35
- package/dist/entrypoint/index.js +7 -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.js +41 -34
- 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/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 +3 -3
- package/dist/files/create-file-ref.d.ts +3 -2
- package/dist/files/create-file-ref.js +2 -2
- 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 +1 -1
- package/dist/files/file-routes.js +12 -2
- 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 +5 -4
- package/dist/files/provider-resolver.js +4 -4
- 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/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/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 +9 -5
- 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-types.d.ts +2 -1
- package/dist/jobs/job-runner.js +19 -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/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/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 +31 -18
- 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 -198
- 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 +4 -2
- package/dist/pipeline/event-dispatcher.d.ts +2 -2
- package/dist/pipeline/event-dispatcher.js +7 -3
- 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 +13 -7
- package/dist/pipeline/handler-context-dispatch.js +9 -8
- package/dist/pipeline/handler-context-events.d.ts +22 -36
- package/dist/pipeline/handler-context-events.js +36 -31
- 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 +3 -1
- package/dist/pipeline/system-hooks.js +6 -4
- 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/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 +12 -2
- package/dist/schema-cli/shared.js +24 -2
- package/dist/schema-cli/status-command.js +8 -2
- package/dist/schema-cli/validate-command.js +48 -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 +93 -87
- 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 -2
- package/dist/upgrade-changelog.js +12 -8
- package/dist/upgrade-cli-internals.d.ts +8 -0
- package/dist/upgrade-cli-internals.js +63 -0
- package/dist/upgrade-cli.d.ts +2 -9
- package/dist/upgrade-cli.js +28 -70
- 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 +23 -19
- package/src/changes.json +236 -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 -11
- package/dist/engine/feature-ast/extractors/round1.js +0 -87
- 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 -485
- package/dist/engine/feature-ast/patch.d.ts +0 -212
- package/dist/engine/feature-ast/patch.js +0 -611
- 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 -1238
- package/dist/engine/feature-ast/pattern-change-schema.js +0 -1072
- package/dist/engine/feature-ast/pattern-id-matchers.d.ts +0 -7
- package/dist/engine/feature-ast/pattern-id-matchers.js +0 -211
- package/dist/engine/feature-ast/pattern-id-schema.d.ts +0 -251
- package/dist/engine/feature-ast/pattern-id-schema.js +0 -166
- package/dist/engine/feature-ast/patterns.d.ts +0 -322
- package/dist/engine/feature-ast/patterns.js +0 -107
- package/dist/engine/feature-ast/render.d.ts +0 -47
- package/dist/engine/feature-ast/render.js +0 -666
- 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 -94
- 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 -21
- package/dist/engine/pattern-library/static-schemas.js +0 -487
- package/dist/engine/pattern-library/types.d.ts +0 -158
- package/dist/engine/pattern-library/types.js +0 -36
- 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
|
@@ -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,223 +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
|
-
scheduleAfterRollback: () => {
|
|
144
|
-
throw memberResolutionReadOnlyDenied();
|
|
145
|
-
},
|
|
146
|
-
// A read as a member gets no system-scope DB, preSave pipeline or file storage.
|
|
147
|
-
runPreSave: undefined,
|
|
148
|
-
systemDb: undefined,
|
|
149
|
-
crossTenantReads: undefined,
|
|
150
|
-
files: undefined,
|
|
151
|
-
derivatives: undefined,
|
|
152
|
-
...(handlerContext.jobRunner && { jobRunner: denyingJobRunnerProxy() }),
|
|
153
|
-
...(handlerContext.notify && { notify: denyMemberResolutionWrite }),
|
|
154
|
-
...(handlerContext.searchAdapter && {
|
|
155
|
-
searchAdapter: allowlistedReadOnlyProxy(handlerContext.searchAdapter, MEMBER_READ_SEARCH_METHODS),
|
|
156
|
-
}),
|
|
157
|
-
...(handlerContext.redis && {
|
|
158
|
-
redis: allowlistedReadOnlyProxy(handlerContext.redis, MEMBER_READ_REDIS_METHODS),
|
|
159
|
-
}),
|
|
160
|
-
...(handlerContext.entityCache && {
|
|
161
|
-
entityCache: allowlistedReadOnlyProxy(handlerContext.entityCache, MEMBER_READ_ENTITY_CACHE_METHODS),
|
|
162
|
-
}),
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
function beforeTransactionDenied(surface) {
|
|
166
|
-
return new InternalError({
|
|
167
|
-
message: `ctx.${surface} is not available before the transaction; move it into the handler`,
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
function withoutTransactionDenied(surface) {
|
|
171
|
-
return new InternalError({
|
|
172
|
-
message: `ctx.${surface} is not available without an open transaction; run the write through ctx.write so it gets its own transaction`,
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
export function perCommandNestedDenied(targetType) {
|
|
176
|
-
return new InternalError({
|
|
177
|
-
message: `handler "${targetType}" runs without a transaction (transaction: "perCommand") and cannot run as a nested write inside an open transaction`,
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
function denySurface(buildError, surface) {
|
|
181
|
-
return () => {
|
|
182
|
-
throw buildError(surface);
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
function denyEventStoreSurfaces(handlerContext, buildError) {
|
|
186
|
-
return {
|
|
187
|
-
...handlerContext,
|
|
188
|
-
appendEvent: denySurface(buildError, "appendEvent"),
|
|
189
|
-
unsafeAppendEvent: denySurface(buildError, "unsafeAppendEvent"),
|
|
190
|
-
tryAppendEvent: denySurface(buildError, "tryAppendEvent"),
|
|
191
|
-
fetchForWriting: denySurface(buildError, "fetchForWriting"),
|
|
192
|
-
archiveStream: denySurface(buildError, "archiveStream"),
|
|
193
|
-
restoreStream: denySurface(buildError, "restoreStream"),
|
|
194
|
-
snapshotAggregate: denySurface(buildError, "snapshotAggregate"),
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
// Reservations write on purpose through the outside-transaction handles, so they keep those but
|
|
198
|
-
// lose every surface bound to the not-yet-open transaction.
|
|
199
|
-
export function denyTransactionBoundSurfaces(handlerContext) {
|
|
200
|
-
return {
|
|
201
|
-
...denyEventStoreSurfaces(handlerContext, beforeTransactionDenied),
|
|
202
|
-
write: denySurface(beforeTransactionDenied, "write"),
|
|
203
|
-
writeAs: denySurface(beforeTransactionDenied, "writeAs"),
|
|
204
|
-
scheduleAfterCommit: denySurface(beforeTransactionDenied, "scheduleAfterCommit"),
|
|
205
|
-
scheduleAfterRollback: denySurface(beforeTransactionDenied, "scheduleAfterRollback"),
|
|
206
|
-
...(handlerContext.notify && { notify: denySurface(beforeTransactionDenied, "notify") }),
|
|
207
|
-
...(handlerContext.jobRunner && {
|
|
208
|
-
jobRunner: denyingJobRunnerProxy(() => beforeTransactionDenied("jobRunner")),
|
|
209
|
-
}),
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
// The beforeTransaction phase has no write need at all, so it also loses the outside-transaction handles.
|
|
213
|
-
export function applyBeforeTransactionReadOnly(handlerContext) {
|
|
214
|
-
return {
|
|
215
|
-
...denyTransactionBoundSurfaces(handlerContext),
|
|
216
|
-
dbOutsideTransaction: undefined,
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
76
|
export async function buildHandlerContext(ctx, type, user, origin, options = {}) {
|
|
220
|
-
const { tx, afterCommitHooks, includeDeleted, outerNotifySink,
|
|
77
|
+
const { tx, afterCommitHooks, includeDeleted, outerNotifySink, phase = "handler", transactionScope = tx ? "inTransaction" : "withoutTransaction", } = options;
|
|
78
|
+
const readOnlyForTenant = phase === "beforeTransaction";
|
|
221
79
|
const scope = resolveHandlerContextScope({ ctx, type, user, origin, tx, transactionScope });
|
|
222
80
|
const dbFacet = buildHandlerDbFacet(scope);
|
|
223
81
|
const observability = buildObservabilityFacet(scope);
|
|
224
82
|
const sinks = createCommitSinks(afterCommitHooks, transactionScope, outerNotifySink);
|
|
225
83
|
const notifyFacet = buildNotifyFacet(scope, sinks, dbFacet.outsideTxSource);
|
|
226
84
|
const configFacet = buildConfigFacet(scope, dbFacet.db);
|
|
227
|
-
const
|
|
85
|
+
const writeTarget = buildWriteTarget(scope, dbFacet.exposedDb, readOnlyForTenant);
|
|
228
86
|
const fileFragment = buildFileFragment(scope, dbFacet.db);
|
|
229
|
-
const dispatchFacet = buildDispatchFacet(scope, sinks);
|
|
230
87
|
const authFacet = buildAuthFacet(scope);
|
|
231
88
|
const eventStoreFacet = buildEventStoreFacet(scope);
|
|
89
|
+
const dispatchFacet = buildDispatchFacet(scope, sinks, {
|
|
90
|
+
queryAsMember: authFacet.queryAsMember,
|
|
91
|
+
queryProjection: eventStoreFacet.queryProjection,
|
|
92
|
+
});
|
|
232
93
|
const tz = await resolveHandlerTz(scope, configFacet.config);
|
|
233
94
|
const locale = resolveHandlerLocale(scope);
|
|
234
|
-
|
|
235
|
-
//
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
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
|
+
});
|
|
239
106
|
const handlerContext = {
|
|
240
|
-
...contextForHandler,
|
|
241
|
-
...(payloadDigest && { rateLimitDigest: createHandlerBoundDigest(payloadDigest, type) }),
|
|
242
|
-
...notifyFacet.factoryFragment,
|
|
243
107
|
// Registry is always the dispatcher's registry — injecting it here lets
|
|
244
108
|
// tests/callers pass `context` without `registry` and still get a valid
|
|
245
|
-
// HandlerContext.
|
|
246
|
-
// `context` can be overridden, but we want the authoritative registry
|
|
247
|
-
// from the dispatcher's own closure to win.
|
|
109
|
+
// HandlerContext.
|
|
248
110
|
registry: scope.registry,
|
|
249
111
|
...dbFacet.fragment,
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
...
|
|
253
|
-
...
|
|
254
|
-
...
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
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
|
+
},
|
|
259
131
|
tz,
|
|
260
132
|
locale,
|
|
261
|
-
|
|
262
|
-
// ctx.user as a convenience alias for event.user. The intuitive path—"the
|
|
263
|
-
// context knows its user"—lets handlers avoid writing `event.user.tenantId`
|
|
264
|
-
// and reduces errors in ctx.user access patterns. It is identical to
|
|
265
|
-
// event.user; identity switches still use queryAs/writeAs.
|
|
133
|
+
// ctx.user as a convenience alias for event.user. Identity switches still use queryAs/writeAs.
|
|
266
134
|
user,
|
|
267
|
-
_tenantId: user.tenantId,
|
|
268
|
-
...dispatchFacet.scheduleFragment,
|
|
269
135
|
...(includeDeleted && { includeDeleted: true }),
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
136
|
+
dispatch: dispatchFacet.dispatch,
|
|
137
|
+
events: eventStoreFacet.events,
|
|
138
|
+
auth: authFacet.auth,
|
|
139
|
+
hasFeature: authFacet.hasFeature,
|
|
273
140
|
}; // @cast-boundary engine-bridge
|
|
274
141
|
const scopedContext = transactionScope === "withoutTransaction"
|
|
275
142
|
? denyEventStoreSurfaces(handlerContext, withoutTransactionDenied)
|
|
276
143
|
: handlerContext;
|
|
277
144
|
// A resolved member principal is read-only by construction.
|
|
278
|
-
|
|
145
|
+
const memberSafeContext = isMemberResolutionPrincipal(user)
|
|
279
146
|
? applyMemberResolutionReadOnly(scopedContext)
|
|
280
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;
|
|
281
155
|
}
|
|
282
156
|
// The handler-name prefix keeps a handler from reproducing the digests the
|
|
283
157
|
// dispatcher uses for payload buckets (those hash the bare normalized value).
|
|
@@ -659,7 +533,10 @@ function buildAuthClaimsContext(ctx, user) {
|
|
|
659
533
|
...(configAccessor && { config: configAccessor }),
|
|
660
534
|
};
|
|
661
535
|
}
|
|
662
|
-
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) {
|
|
663
540
|
const { registry, appContext: context } = ctx;
|
|
664
541
|
const hooks = registry.getAuthClaimsHooks();
|
|
665
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 = {
|
|
@@ -6,8 +6,10 @@ import { selectEventsHeadId, selectPendingAndNewEventRows, } from "../db/queries
|
|
|
6
6
|
import { coerceRow } from "../db/query.js";
|
|
7
7
|
import { extractTableInfo } from "../db/table-info.js";
|
|
8
8
|
import { qnScope } from "../engine/qualified-name.js";
|
|
9
|
-
import { eventsTable
|
|
10
|
-
import {
|
|
9
|
+
import { eventsTable } from "../event-store/index.js";
|
|
10
|
+
import { toStoredEvent as rowToStoredEvent } from "../event-store/row-to-stored-event.js";
|
|
11
|
+
import { getFallbackMeter } from "../observability/fallback.js";
|
|
12
|
+
import { emitDispatcherError, emitEventConsumerLag, emitEventConsumerPendingGaps, } from "../observability/standard-metrics.js";
|
|
11
13
|
import { ConsumerStatuses, eventConsumerStateTable, SHARED_INSTANCE_SENTINEL, } from "./event-consumer-state.js";
|
|
12
14
|
import { parseWriteOrigin } from "./write-origin.js";
|
|
13
15
|
// Fails closed without throwing: a throw would poison the event for every consumer.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import type { Meter, Tracer } from "@cosmicdrift/kumiko-types/observability";
|
|
1
2
|
import type { PgListenClient } from "../db/connection.ts";
|
|
2
3
|
import type { AppContext } from "../engine/types/index.ts";
|
|
3
|
-
import {
|
|
4
|
-
import { type Meter, type Tracer } from "../observability/index.ts";
|
|
4
|
+
import type { StoredEvent } from "../event-store/index.ts";
|
|
5
5
|
export type EventConsumerHandler = (event: StoredEvent, ctx: AppContext) => Promise<void>;
|
|
6
6
|
export type EventConsumerBatchHandler = (events: readonly StoredEvent[], ctx: AppContext) => Promise<void>;
|
|
7
7
|
export type EventConsumerErrorPolicy = {
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { extractPgError } from "../db/pg-error.js";
|
|
2
2
|
import { recordConsumerPassFailure, selectSnapshotXmax, selectSnapshotXmin, } from "../db/queries/event-consumer.js";
|
|
3
|
+
import { assertNoActiveRowLevelSecurityScope, runInSystemRowLevelSecurityScope, } from "../db/row-level-security-scope.js";
|
|
3
4
|
import { SYSTEM_TENANT_ID } from "../engine/types/identifiers.js";
|
|
4
|
-
import { EVENTS_PUBSUB_CHANNEL } from "../event-store/
|
|
5
|
+
import { EVENTS_PUBSUB_CHANNEL } from "../event-store/event-store.js";
|
|
5
6
|
import { createFallbackLogger } from "../logging/utils.js";
|
|
6
|
-
import {
|
|
7
|
+
import { getFallbackMeter, getFallbackTracer } from "../observability/fallback.js";
|
|
8
|
+
import { emitEventConsumerPassOutcome, emitEventConsumerPassSkipped, emitEventConsumerRearmExhausted, emitEventDispatcherListenConnected, } from "../observability/standard-metrics.js";
|
|
7
9
|
import { SHARED_INSTANCE_SENTINEL } from "./event-consumer-state.js";
|
|
8
10
|
import { acquireConsumerState, consumerInstanceId, deliverEvents, emitLagFromTx, fetchPendingEvents, markProcessing, persistConsumerOutcome, preRegisterConsumers, selectIdleConsumerKeys, } from "./event-dispatcher-delivery.js";
|
|
9
11
|
import { mergeContiguousGapRanges, partitionBurntGaps, splitRangeExcludingIds, toIdRanges, } from "./pending-gap-ranges.js";
|
|
@@ -221,7 +223,8 @@ export function createEventDispatcher(options) {
|
|
|
221
223
|
if (!preRegistered) {
|
|
222
224
|
throw new Error("EventDispatcher.runOnce() called before start() — consumer state rows are not registered. Call start() first (production) or ensureRegistered() (tests after truncating kumiko_event_consumers).");
|
|
223
225
|
}
|
|
224
|
-
|
|
226
|
+
// Per pass, never around start(): the poll loop itself must stay outside any scope.
|
|
227
|
+
const pass = runInSystemRowLevelSecurityScope("event dispatcher pass runs consumers for every tenant", doPass);
|
|
225
228
|
inFlightPasses.add(pass);
|
|
226
229
|
try {
|
|
227
230
|
return await pass;
|
|
@@ -457,6 +460,7 @@ export function createEventDispatcher(options) {
|
|
|
457
460
|
return {
|
|
458
461
|
consumers,
|
|
459
462
|
async start() {
|
|
463
|
+
assertNoActiveRowLevelSecurityScope("EventDispatcher");
|
|
460
464
|
// skip: already running, idempotent
|
|
461
465
|
if (running)
|
|
462
466
|
return;
|