@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
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Meter, MetricsHandle } from "./types/index.ts";
|
|
2
2
|
export declare function createMetricsHandle(meter: Meter, featureName: string): MetricsHandle;
|
|
3
3
|
export declare function createSafeMetricsHandle(meter: Meter, featureName: string): MetricsHandle;
|
|
4
|
-
export declare function createUnboundMetricsHandle(meter: Meter): MetricsHandle;
|
|
5
4
|
export declare function createNoopMetricsHandle(): MetricsHandle;
|
|
6
5
|
export declare function createMetricsForFactory(meter: Meter | undefined): (featureName: string) => MetricsHandle;
|
|
@@ -26,7 +26,7 @@ export function createMetricsHandle(meter, featureName) {
|
|
|
26
26
|
// Same feature-bound resolution as createMetricsHandle, but for an
|
|
27
27
|
// explicit `featureName` chosen by the caller rather than the dispatching
|
|
28
28
|
// handler's own feature. Meant for shared/library code
|
|
29
|
-
// invoked from many features' HandlerContext (ctx.metricsFor) — the
|
|
29
|
+
// invoked from many features' HandlerContext (ctx.obs.metricsFor) — the
|
|
30
30
|
// library owns one stable metric name instead of splintering into
|
|
31
31
|
// kumiko_<caller>_x per consumer.
|
|
32
32
|
//
|
|
@@ -77,19 +77,6 @@ export function createSafeMetricsHandle(meter, featureName) {
|
|
|
77
77
|
// Fallback for contexts where the feature is unknown (e.g. system-hooks,
|
|
78
78
|
// internal pipeline code). Short names are used verbatim — useful for
|
|
79
79
|
// framework-level usage, but rejected by the Meter unless pre-registered.
|
|
80
|
-
export function createUnboundMetricsHandle(meter) {
|
|
81
|
-
return {
|
|
82
|
-
inc(name, labels, value) {
|
|
83
|
-
meter.counter(name).inc(value, labels);
|
|
84
|
-
},
|
|
85
|
-
observe(name, value, labels) {
|
|
86
|
-
meter.histogram(name).observe(value, labels);
|
|
87
|
-
},
|
|
88
|
-
set(name, value, labels) {
|
|
89
|
-
meter.gauge(name).set(value, labels);
|
|
90
|
-
},
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
80
|
// Noop fallback used when no provider is configured and for safety in
|
|
94
81
|
// contexts where we can't determine the feature. Every call is a no-op —
|
|
95
82
|
// tests and non-observability-aware features never crash.
|
|
@@ -100,7 +87,7 @@ export function createNoopMetricsHandle() {
|
|
|
100
87
|
set(_name, _value, _labels) { },
|
|
101
88
|
};
|
|
102
89
|
}
|
|
103
|
-
// Shared factory behind ctx.metricsFor for handler and job contexts, so both
|
|
90
|
+
// Shared factory behind ctx.obs.metricsFor for handler and job contexts, so both
|
|
104
91
|
// keep the same no-op-on-unregistered contract.
|
|
105
92
|
export function createMetricsForFactory(meter) {
|
|
106
93
|
return meter
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SensitiveFilterConfig,
|
|
1
|
+
import type { SensitiveFilterConfig, Span, SpanAttributeValue, SpanKind, SpanStatus, StartSpanOptions, Tracer } from "./types/index.ts";
|
|
2
2
|
export type RecordedSpan = {
|
|
3
3
|
readonly traceId: string;
|
|
4
4
|
readonly spanId: string;
|
|
@@ -28,5 +28,4 @@ export declare class RecordingTracer implements Tracer {
|
|
|
28
28
|
withSpan<T>(name: string, optionsOrFn: StartSpanOptions | ((span: Span) => Promise<T>), fn?: (span: Span) => Promise<T>): Promise<T>;
|
|
29
29
|
getActiveSpan(): Span | undefined;
|
|
30
30
|
}
|
|
31
|
-
export declare function serializeSpanContext(span: Span): SerializedTraceContext;
|
|
32
31
|
export {};
|
|
@@ -2,8 +2,6 @@ import type { SensitiveFilterConfig, SpanAttributeValue } from "./types/index.ts
|
|
|
2
2
|
export declare const REDACTED = "[REDACTED]";
|
|
3
3
|
export declare const DEFAULT_SENSITIVE_CONFIG: SensitiveFilterConfig;
|
|
4
4
|
export declare function mergeSensitiveConfig(override: Partial<SensitiveFilterConfig> | undefined): SensitiveFilterConfig;
|
|
5
|
-
export declare function redactHeaders(headers: Readonly<Record<string, string>>, config: SensitiveFilterConfig): Record<string, string>;
|
|
6
|
-
export declare function redactQueryString(input: string, config: SensitiveFilterConfig): string;
|
|
7
5
|
export declare function shouldRedactAttribute(key: string, config: SensitiveFilterConfig): boolean;
|
|
8
6
|
export declare function redactValue(value: SpanAttributeValue): SpanAttributeValue;
|
|
9
7
|
export declare function redactAttributes(attrs: Readonly<Record<string, SpanAttributeValue>>, config: SensitiveFilterConfig): Record<string, SpanAttributeValue>;
|
|
@@ -32,35 +32,6 @@ export function mergeSensitiveConfig(override) {
|
|
|
32
32
|
DEFAULT_SENSITIVE_CONFIG.redactedAttributeKeyPatterns,
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
|
-
function lowercaseSet(names) {
|
|
36
|
-
return new Set(names.map((n) => n.toLowerCase()));
|
|
37
|
-
}
|
|
38
|
-
export function redactHeaders(headers, config) {
|
|
39
|
-
const redacted = lowercaseSet(config.redactedHeaders);
|
|
40
|
-
const out = {};
|
|
41
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
42
|
-
out[key] = redacted.has(key.toLowerCase()) ? REDACTED : value;
|
|
43
|
-
}
|
|
44
|
-
return out;
|
|
45
|
-
}
|
|
46
|
-
// Redact sensitive query params in a URL or query string. Returns a new URL
|
|
47
|
-
// string with the same shape — path, fragment, and ordering preserved.
|
|
48
|
-
export function redactQueryString(input, config) {
|
|
49
|
-
const redacted = lowercaseSet(config.redactedQueryParams);
|
|
50
|
-
// URL wants absolute; handle both absolute and path-only forms.
|
|
51
|
-
const hasScheme = /^[a-z][a-z0-9+\-.]*:/i.test(input);
|
|
52
|
-
const base = hasScheme ? undefined : "http://_internal";
|
|
53
|
-
const url = base ? new URL(input, base) : new URL(input);
|
|
54
|
-
for (const key of Array.from(url.searchParams.keys())) {
|
|
55
|
-
if (redacted.has(key.toLowerCase())) {
|
|
56
|
-
url.searchParams.set(key, REDACTED);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
if (!hasScheme) {
|
|
60
|
-
return `${url.pathname}${url.search}${url.hash}`;
|
|
61
|
-
}
|
|
62
|
-
return url.toString();
|
|
63
|
-
}
|
|
64
35
|
// Check a single attribute key against the redaction patterns.
|
|
65
36
|
// Used by the Span implementation when setAttribute is called.
|
|
66
37
|
export function shouldRedactAttribute(key, config) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type { ActiveMembershipResult } from "@cosmicdrift/kumiko-types/handlers";
|
|
1
2
|
import { type PrincipalStatusPlugin, type TenantLifecycleStatusPlugin } from "../engine/active-membership.ts";
|
|
2
3
|
import type { TenantId } from "../engine/types/identifiers.ts";
|
|
3
|
-
import type {
|
|
4
|
+
import type { Registry } from "../engine/types/index.ts";
|
|
4
5
|
import { type DispatchContext } from "./dispatch-shared.ts";
|
|
5
6
|
export type ActiveMembershipPolicy = {
|
|
6
7
|
readonly allowPendingDestruction: boolean;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// One framework-owned composition of membership / principal-status /
|
|
2
2
|
// tenant-lifecycle checks so login, switch-tenant and MFA completion can't independently drift.
|
|
3
|
+
import { runInSystemRowLevelSecurityScope } from "../db/row-level-security-scope.js";
|
|
3
4
|
import { isPrincipalStatusPlugin, isTenantLifecycleStatusPlugin, TENANT_TEARDOWN_STATUSES, } from "../engine/active-membership.js";
|
|
4
5
|
import { EXT_PRINCIPAL_STATUS, EXT_TENANT_LIFECYCLE_STATUS } from "../engine/extension-names.js";
|
|
5
6
|
import { createSystemUser } from "../engine/system-user.js";
|
|
@@ -41,7 +42,7 @@ async function findMembership(ctx, userId, tenantId) {
|
|
|
41
42
|
}
|
|
42
43
|
return rawMemberships.find((m) => m.tenantId === tenantId);
|
|
43
44
|
}
|
|
44
|
-
// Exported so member-reader.ts (ctx.queryAsMember) can reach the registered
|
|
45
|
+
// Exported so member-reader.ts (ctx.dispatch.queryAsMember) can reach the registered
|
|
45
46
|
// PrincipalStatusPlugin's resolveProfile without duplicating this lookup.
|
|
46
47
|
export function resolvePrincipalPlugin(registry) {
|
|
47
48
|
const usages = registry.getExtensionUsages(EXT_PRINCIPAL_STATUS);
|
|
@@ -84,7 +85,10 @@ function isTeardownRejected(status, policy) {
|
|
|
84
85
|
}
|
|
85
86
|
// Order is load-bearing: a non-member must never learn a foreign tenant's
|
|
86
87
|
// lifecycle/blocked state, so membership is resolved and checked FIRST.
|
|
87
|
-
export
|
|
88
|
+
export function resolveActiveMembershipFn(ctx, userId, tenantId, policy) {
|
|
89
|
+
return runInSystemRowLevelSecurityScope("active membership lookup runs before the request tenant is established", () => resolveActiveMembershipInScope(ctx, userId, tenantId, policy));
|
|
90
|
+
}
|
|
91
|
+
async function resolveActiveMembershipInScope(ctx, userId, tenantId, policy) {
|
|
88
92
|
const { registry } = ctx;
|
|
89
93
|
const membership = await findMembership(ctx, userId, tenantId);
|
|
90
94
|
if (!membership) {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { createFallbackLogger } from "../logging/utils.ts";
|
|
2
|
+
import type { AfterCommitHook } from "./dispatcher-utils.ts";
|
|
3
|
+
export type AfterRollbackHook = () => Promise<void>;
|
|
4
|
+
export declare function afterRollbackHooksOf(commitSink: AfterCommitHook[]): AfterRollbackHook[];
|
|
5
|
+
export declare function carrySavepointRollbackHooks(innerCommitSink: AfterCommitHook[], outerCommitSink: AfterCommitHook[], savepointRolledBack: boolean): void;
|
|
6
|
+
export declare function flushAfterRollback(commitSink: AfterCommitHook[], logError: Pick<ReturnType<typeof createFallbackLogger>, "error">): Promise<void>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Side channel keyed by the afterCommit sink array, so executeWrite and friends keep their signatures.
|
|
2
|
+
// Invariant: every registration runs at most once, and only if the work it compensates was discarded.
|
|
3
|
+
const rollbackSinks = new WeakMap();
|
|
4
|
+
export function afterRollbackHooksOf(commitSink) {
|
|
5
|
+
const existing = rollbackSinks.get(commitSink);
|
|
6
|
+
if (existing)
|
|
7
|
+
return existing;
|
|
8
|
+
const created = [];
|
|
9
|
+
rollbackSinks.set(commitSink, created);
|
|
10
|
+
return created;
|
|
11
|
+
}
|
|
12
|
+
// A rolled-back savepoint is not compensated immediately: the compensation could wait on locks of
|
|
13
|
+
// the still-open outer transaction. It runs once after that transaction ends, via the commit sink
|
|
14
|
+
// on commit or the rollback sink on rollback.
|
|
15
|
+
export function carrySavepointRollbackHooks(innerCommitSink, outerCommitSink, savepointRolledBack) {
|
|
16
|
+
const innerHooks = rollbackSinks.get(innerCommitSink) ?? [];
|
|
17
|
+
if (innerHooks.length > 0) {
|
|
18
|
+
if (savepointRolledBack)
|
|
19
|
+
outerCommitSink.push(...innerHooks);
|
|
20
|
+
afterRollbackHooksOf(outerCommitSink).push(...innerHooks);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export async function flushAfterRollback(commitSink, logError) {
|
|
24
|
+
const hooks = rollbackSinks.get(commitSink) ?? [];
|
|
25
|
+
const outcomes = await Promise.allSettled(hooks.map((hook) => hook()));
|
|
26
|
+
for (const outcome of outcomes) {
|
|
27
|
+
if (outcome.status === "rejected") {
|
|
28
|
+
const detail = outcome.reason instanceof Error ? outcome.reason.message : String(outcome.reason);
|
|
29
|
+
logError.error("afterRollback hook failed", { error: detail });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { AppendEventArgs } from "@cosmicdrift/kumiko-types/handlers";
|
|
1
2
|
import type { DbRunner } from "../db/connection.ts";
|
|
2
|
-
import type {
|
|
3
|
+
import type { Registry, TenantId } from "../engine/types/index.ts";
|
|
3
4
|
import { type StoredEvent } from "../event-store/event-store.ts";
|
|
4
5
|
export type AppendDomainEventCoreDeps = {
|
|
5
6
|
readonly registry: Registry;
|
|
@@ -63,7 +63,7 @@ export async function appendDomainEventCore(deps, args) {
|
|
|
63
63
|
throw new ArchivedStreamError(deps.tenantId, args.aggregateId);
|
|
64
64
|
}
|
|
65
65
|
// Stream-version authoritative. See Block 0 / getStreamVersion doc for
|
|
66
|
-
// why row.version isn't sufficient once ctx.
|
|
66
|
+
// why row.version isn't sufficient once ctx.events.append enters the picture.
|
|
67
67
|
// A caller-pinned version (fetchForWriting handles) must reach append() so a
|
|
68
68
|
// write landing between fetch and append conflicts instead of being re-read.
|
|
69
69
|
const expectedVersion = args.expectedVersion ?? (await getStreamVersion(deps.db, args.aggregateId, deps.tenantId));
|
|
@@ -91,7 +91,7 @@ export async function appendDomainEventCore(deps, args) {
|
|
|
91
91
|
});
|
|
92
92
|
// Inline projections fire in the same tx — a throw rolls everything back
|
|
93
93
|
// together. Same semantics regardless of which call-site triggered the
|
|
94
|
-
// append (write-handler ctx.
|
|
94
|
+
// append (write-handler ctx.events.append vs. MSP-apply ctx.appendEvent).
|
|
95
95
|
await runProjectionsForEvent(stored, deps.registry, deps.db);
|
|
96
96
|
return stored;
|
|
97
97
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// TenantDb identity keys WeakMaps (rebinders, personal-data gates), so the exposed db is never
|
|
2
|
+
// wrapped or spread; the non-enumerable property keeps spreads and logging of the db unchanged.
|
|
3
|
+
function defineOutsideTransaction(db, outsideTransaction) {
|
|
4
|
+
Object.defineProperty(db, "outsideTransaction", {
|
|
5
|
+
value: outsideTransaction,
|
|
6
|
+
enumerable: false,
|
|
7
|
+
configurable: true,
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
export function attachOutsideTransaction(db, outsideTransaction) {
|
|
11
|
+
defineOutsideTransaction(db, outsideTransaction);
|
|
12
|
+
return db;
|
|
13
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { AuthClaimsContext, AuthClaimsHookDef
|
|
1
|
+
import type { AuthClaimsContext, AuthClaimsHookDef } from "@cosmicdrift/kumiko-types/handlers";
|
|
2
|
+
import type { SessionUser } from "../engine/types/index.ts";
|
|
2
3
|
import type { Logger } from "../logging/types.ts";
|
|
3
4
|
export type ResolveAuthClaimsArgs = {
|
|
4
5
|
readonly user: SessionUser;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { PreDeleteHookFn } from "@cosmicdrift/kumiko-types/hooks";
|
|
1
2
|
import type { TableColumns } from "../db/dialect.ts";
|
|
2
|
-
import type {
|
|
3
|
+
import type { Registry } from "../engine/types/index.ts";
|
|
3
4
|
import type { SystemHookDef } from "./lifecycle-pipeline.ts";
|
|
4
5
|
type TableMap = ReadonlyMap<string, TableColumns>;
|
|
5
6
|
export declare function createCascadeDeleteHook(registry: Registry, tables: TableMap): SystemHookDef<PreDeleteHookFn>;
|
|
@@ -4,7 +4,8 @@ import { isBoundTenantDb } from "../db/tenant-db-runner.js";
|
|
|
4
4
|
import { OnDeleteStrategies, SystemHookNames, SystemHookPriorities } from "../engine/constants.js";
|
|
5
5
|
import { isRecordLocked } from "../engine/screen-helpers.js";
|
|
6
6
|
import { createSystemUser } from "../engine/system-user.js";
|
|
7
|
-
import {
|
|
7
|
+
import { RecordLockedError } from "../errors/classes.js";
|
|
8
|
+
import { ConflictError, FrameworkReasons, InternalError, reraiseAsKumikoError, } from "../errors/index.js";
|
|
8
9
|
// The cascade is a consequence of the parent delete the caller was already authorized for, so the
|
|
9
10
|
// children are written as the framework system user and the lock decision is taken once, up front.
|
|
10
11
|
const CASCADE_CHILD_WRITE_OPTIONS = { unsafeSkipLockGuard: true };
|
|
@@ -18,7 +19,7 @@ export function createCascadeDeleteHook(registry, tables) {
|
|
|
18
19
|
? ctx.systemDb.acknowledgeCrossTenant(`cascade delete for r.systemScope() write handler (${entityName ?? "unknown"})`)
|
|
19
20
|
: ctx.db;
|
|
20
21
|
if (!entityName || !db) {
|
|
21
|
-
ctx.log?.debug(`cascadeDelete: skipping — ${!entityName ? "no entityName" : "no db"} on payload ${payload.id}`);
|
|
22
|
+
ctx.obs.log?.debug(`cascadeDelete: skipping — ${!entityName ? "no entityName" : "no db"} on payload ${payload.id}`);
|
|
22
23
|
return;
|
|
23
24
|
}
|
|
24
25
|
const writeDb = isBoundTenantDb(db) ? db : undefined;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { ConfigAccessorFactory } from "@cosmicdrift/kumiko-types/config";
|
|
2
2
|
import type { AppContext } from "@cosmicdrift/kumiko-types/handlers";
|
|
3
|
-
export declare function configAccessorFactoryOf(context: Pick<AppContext, "configAccessorFactory"
|
|
3
|
+
export declare function configAccessorFactoryOf(context: Pick<AppContext, "configAccessorFactory">): ConfigAccessorFactory | undefined;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { AppContext, ContextServices } from "../engine/types/index.ts";
|
|
2
|
+
type ServiceKey = Exclude<keyof ContextServices, "extensions">;
|
|
3
|
+
export declare const APP_CONTEXT_KEY_ROLES: {
|
|
4
|
+
readonly redis: "service";
|
|
5
|
+
readonly cacheSync: "service";
|
|
6
|
+
readonly jobRunner: "service";
|
|
7
|
+
readonly searchAdapter: "service";
|
|
8
|
+
readonly entityCache: "service";
|
|
9
|
+
readonly secrets: "service";
|
|
10
|
+
readonly kms: "service";
|
|
11
|
+
readonly files: "service";
|
|
12
|
+
readonly derivatives: "service";
|
|
13
|
+
readonly configResolver: "service";
|
|
14
|
+
readonly configEncryption: "service";
|
|
15
|
+
readonly rateLimit: "service";
|
|
16
|
+
readonly effectiveFeatures: "service";
|
|
17
|
+
readonly masterKeyProvider: "service";
|
|
18
|
+
readonly _fileProviderResolver: "service";
|
|
19
|
+
readonly _notifyFactory: "service";
|
|
20
|
+
readonly _notifyInTransactionFactory: "service";
|
|
21
|
+
readonly _notifyAfterCommitFactory: "service";
|
|
22
|
+
readonly _escapeHatchAuditSink: "service";
|
|
23
|
+
readonly db: "wiring";
|
|
24
|
+
readonly systemDb: "wiring";
|
|
25
|
+
readonly registry: "wiring";
|
|
26
|
+
readonly systemUser: "wiring";
|
|
27
|
+
readonly log: "wiring";
|
|
28
|
+
readonly triggeredBy: "wiring";
|
|
29
|
+
readonly triggerName: "wiring";
|
|
30
|
+
readonly geoTzProvider: "wiring";
|
|
31
|
+
readonly clock: "wiring";
|
|
32
|
+
readonly _tenantId: "wiring";
|
|
33
|
+
readonly defaultLocale: "wiring";
|
|
34
|
+
readonly configAccessorFactory: "wiring";
|
|
35
|
+
readonly _rateLimitPayloadDigest: "wiring";
|
|
36
|
+
readonly tracer: "wiring";
|
|
37
|
+
readonly meter: "wiring";
|
|
38
|
+
readonly config: "wiring";
|
|
39
|
+
readonly configFor: "wiring";
|
|
40
|
+
readonly forTenant: "wiring";
|
|
41
|
+
readonly notify: "wiring";
|
|
42
|
+
readonly signal: "wiring";
|
|
43
|
+
readonly scheduleAfterCommit: "wiring";
|
|
44
|
+
readonly scheduleAfterRollback: "wiring";
|
|
45
|
+
};
|
|
46
|
+
type ServiceRoleKey = {
|
|
47
|
+
[Key in keyof typeof APP_CONTEXT_KEY_ROLES]: (typeof APP_CONTEXT_KEY_ROLES)[Key] extends "service" ? Key : never;
|
|
48
|
+
}[keyof typeof APP_CONTEXT_KEY_ROLES];
|
|
49
|
+
type IsSame<Left, Right> = [Left] extends [Right] ? ([Right] extends [Left] ? true : false) : false;
|
|
50
|
+
type MustBeTrue<Value extends true> = Value;
|
|
51
|
+
export type ServiceRolesMatchContextServices = MustBeTrue<IsSame<ServiceRoleKey, ServiceKey>>;
|
|
52
|
+
export type ContextServiceOverrides = {
|
|
53
|
+
-readonly [Key in ServiceKey]?: ContextServices[Key];
|
|
54
|
+
};
|
|
55
|
+
export declare function buildContextServices(context: AppContext, overrides?: ContextServiceOverrides): ContextServices;
|
|
56
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Every AppContext key is either a service a handler or job may use, or boot wiring the framework
|
|
2
|
+
// consumes itself. The satisfies clause makes a new AppContext key a compile error until it is classified.
|
|
3
|
+
export const APP_CONTEXT_KEY_ROLES = {
|
|
4
|
+
redis: "service",
|
|
5
|
+
cacheSync: "service",
|
|
6
|
+
jobRunner: "service",
|
|
7
|
+
searchAdapter: "service",
|
|
8
|
+
entityCache: "service",
|
|
9
|
+
secrets: "service",
|
|
10
|
+
kms: "service",
|
|
11
|
+
files: "service",
|
|
12
|
+
derivatives: "service",
|
|
13
|
+
configResolver: "service",
|
|
14
|
+
configEncryption: "service",
|
|
15
|
+
rateLimit: "service",
|
|
16
|
+
effectiveFeatures: "service",
|
|
17
|
+
masterKeyProvider: "service",
|
|
18
|
+
_fileProviderResolver: "service",
|
|
19
|
+
_notifyFactory: "service",
|
|
20
|
+
_notifyInTransactionFactory: "service",
|
|
21
|
+
_notifyAfterCommitFactory: "service",
|
|
22
|
+
_escapeHatchAuditSink: "service",
|
|
23
|
+
db: "wiring",
|
|
24
|
+
systemDb: "wiring",
|
|
25
|
+
registry: "wiring",
|
|
26
|
+
systemUser: "wiring",
|
|
27
|
+
log: "wiring",
|
|
28
|
+
triggeredBy: "wiring",
|
|
29
|
+
triggerName: "wiring",
|
|
30
|
+
geoTzProvider: "wiring",
|
|
31
|
+
clock: "wiring",
|
|
32
|
+
_tenantId: "wiring",
|
|
33
|
+
defaultLocale: "wiring",
|
|
34
|
+
configAccessorFactory: "wiring",
|
|
35
|
+
_rateLimitPayloadDigest: "wiring",
|
|
36
|
+
tracer: "wiring",
|
|
37
|
+
meter: "wiring",
|
|
38
|
+
config: "wiring",
|
|
39
|
+
configFor: "wiring",
|
|
40
|
+
forTenant: "wiring",
|
|
41
|
+
notify: "wiring",
|
|
42
|
+
signal: "wiring",
|
|
43
|
+
scheduleAfterCommit: "wiring",
|
|
44
|
+
scheduleAfterRollback: "wiring",
|
|
45
|
+
};
|
|
46
|
+
function isAppContextKey(key) {
|
|
47
|
+
return Object.hasOwn(APP_CONTEXT_KEY_ROLES, key);
|
|
48
|
+
}
|
|
49
|
+
function isServiceKey(key) {
|
|
50
|
+
return isAppContextKey(key) && APP_CONTEXT_KEY_ROLES[key] === "service";
|
|
51
|
+
}
|
|
52
|
+
// The dispatcher binds these two to one call's transaction; a factory inherited from an outer
|
|
53
|
+
// context must not leak into a context that has none of its own.
|
|
54
|
+
const PER_CALL_FACTORY_KEYS = new Set([
|
|
55
|
+
"_notifyInTransactionFactory",
|
|
56
|
+
"_notifyAfterCommitFactory",
|
|
57
|
+
]);
|
|
58
|
+
function copyService(target, source, key) {
|
|
59
|
+
const value = source[key];
|
|
60
|
+
if (value !== undefined)
|
|
61
|
+
target[key] = value;
|
|
62
|
+
}
|
|
63
|
+
const SERVICE_KEYS = Object.keys(APP_CONTEXT_KEY_ROLES).filter(isServiceKey);
|
|
64
|
+
export function buildContextServices(context, overrides = {}) {
|
|
65
|
+
const services = {};
|
|
66
|
+
for (const key of SERVICE_KEYS) {
|
|
67
|
+
if (!PER_CALL_FACTORY_KEYS.has(key))
|
|
68
|
+
copyService(services, context, key);
|
|
69
|
+
copyService(services, overrides, key);
|
|
70
|
+
}
|
|
71
|
+
const extensions = Object.fromEntries(Object.entries(context).filter(([key]) => key !== "services" && !isAppContextKey(key)));
|
|
72
|
+
return { ...services, extensions };
|
|
73
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { WriteOrigin } from "@cosmicdrift/kumiko-types/event-store-types";
|
|
2
|
-
import type {
|
|
2
|
+
import type { WriteResult } from "@cosmicdrift/kumiko-types/handlers";
|
|
3
|
+
import type { SessionUser } from "../engine/types/index.ts";
|
|
3
4
|
import type { BatchCommand, BatchResult, DispatchContext } from "./dispatch-shared.ts";
|
|
4
5
|
export declare function runBatch(ctx: DispatchContext, commands: readonly BatchCommand[], user: SessionUser, requestId?: string, inheritedOrigin?: WriteOrigin): Promise<BatchResult>;
|
|
5
6
|
export declare function unwrapSingle(batchResult: BatchResult): WriteResult;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { requestContext
|
|
1
|
+
import { requestContext } from "../api/request-context.js";
|
|
2
|
+
import { runWithWriteOrigin } from "../api/request-context-scopes.js";
|
|
2
3
|
import { transaction } from "../db/query.js";
|
|
3
|
-
import { InternalError,
|
|
4
|
+
import { InternalError, UnprocessableError, writeFailure, } from "../errors/index.js";
|
|
5
|
+
import { toWriteErrorInfo } from "../errors/write-error-info.js";
|
|
4
6
|
import { createFallbackLogger } from "../logging/utils.js";
|
|
5
7
|
import { parseJsonSafe } from "../utils/safe-json.js";
|
|
6
|
-
import {
|
|
8
|
+
import { flushAfterRollback } from "./after-rollback-sink.js";
|
|
9
|
+
import { runInDispatchScope } from "./dispatch-scope.js";
|
|
10
|
+
import { buildHandlerContext, resolveAppPoolDb } from "./dispatch-shared.js";
|
|
7
11
|
import { executeNestedWrite, executeWrite } from "./dispatch-write.js";
|
|
8
12
|
import { BatchRollback, isLifecycleResult, wrapToKumiko, } from "./dispatcher-utils.js";
|
|
9
13
|
import { reserveBeforeTransaction, runAsCommand, } from "./pre-transaction-reservations.js";
|
|
@@ -32,10 +36,13 @@ async function runReservedCommand(scope, cmd, index, tx) {
|
|
|
32
36
|
const hookStart = afterCommitHooks.length;
|
|
33
37
|
// Nested-write children would run inline with the in-transaction scope, so a perCommand command skips the expansion.
|
|
34
38
|
const execute = isPerCommandHandler(ctx, cmd.type) ? executeWrite : executeNestedWrite;
|
|
35
|
-
const res = await runAsCommand(toReservedScope(reservations, index, cmd), () => runWithWriteOrigin(origin, () => execute(ctx, cmd.type, cmd.payload, user, origin, tx, afterCommitHooks)));
|
|
39
|
+
const res = await runAsCommand(toReservedScope(reservations, index, cmd), () => runWithWriteOrigin(origin, () => runInDispatchScope(ctx.registry, [cmd.type], user, () => execute(ctx, cmd.type, cmd.payload, user, origin, tx, afterCommitHooks))));
|
|
36
40
|
rewrapHooksWithOrigin(afterCommitHooks, hookStart, origin);
|
|
37
41
|
return res;
|
|
38
42
|
}
|
|
43
|
+
function rollbackLogger(scope) {
|
|
44
|
+
return createFallbackLogger("dispatcher", scope.ctx.appContext.log);
|
|
45
|
+
}
|
|
39
46
|
// Sequential fallback without an outer transaction. A failure result and a throw both end the
|
|
40
47
|
// batch, so both give the reserved capacity back.
|
|
41
48
|
async function runCommandsWithoutTransaction(scope, commands, results) {
|
|
@@ -50,12 +57,14 @@ async function runCommandsWithoutTransaction(scope, commands, results) {
|
|
|
50
57
|
// No tx means no rollback — but we still drop afterCommit hooks,
|
|
51
58
|
// matching the semantic "failure = side-effects don't fire".
|
|
52
59
|
await scope.reservations.releaseAll();
|
|
60
|
+
await flushAfterRollback(scope.afterCommitHooks, rollbackLogger(scope));
|
|
53
61
|
return { index: i, error: res.error };
|
|
54
62
|
}
|
|
55
63
|
}
|
|
56
64
|
}
|
|
57
65
|
catch (e) {
|
|
58
66
|
await scope.reservations.releaseAll();
|
|
67
|
+
await flushAfterRollback(scope.afterCommitHooks, rollbackLogger(scope));
|
|
59
68
|
throw e;
|
|
60
69
|
}
|
|
61
70
|
return undefined;
|
|
@@ -63,14 +72,16 @@ async function runCommandsWithoutTransaction(scope, commands, results) {
|
|
|
63
72
|
// Core batch logic extracted so write() and command() can reuse it
|
|
64
73
|
// (a single write = batch of one, running in its own transaction).
|
|
65
74
|
export async function runBatch(ctx, commands, user, requestId, inheritedOrigin) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
return runInDispatchScope(ctx.registry, commands.map((command) => command.type), user, () => {
|
|
76
|
+
const current = requestContext.get();
|
|
77
|
+
if (!current?.signal) {
|
|
78
|
+
return runBatchBody(ctx, commands, user, requestId, inheritedOrigin);
|
|
79
|
+
}
|
|
80
|
+
// Strip the signal: a client disconnect must not roll back a write whose
|
|
81
|
+
// afterCommit effects would then be lost.
|
|
82
|
+
const { signal: _signal, ...withoutSignal } = current;
|
|
83
|
+
return requestContext.run(withoutSignal, () => runBatchBody(ctx, commands, user, requestId, inheritedOrigin));
|
|
84
|
+
});
|
|
74
85
|
}
|
|
75
86
|
function perCommandBatchRejection(ctx, commands) {
|
|
76
87
|
const index = commands.findIndex((cmd) => isPerCommandHandler(ctx, cmd.type));
|
|
@@ -96,6 +107,7 @@ async function checkBatchIdempotency(ctx, user, requestId) {
|
|
|
96
107
|
// corrupted cache entry — treat as miss, let the request re-run
|
|
97
108
|
return parsed ? { cached: parsed } : {};
|
|
98
109
|
}
|
|
110
|
+
const BATCH_HOOKS_CONTEXT_TYPE = "dispatcher:batch-hooks";
|
|
99
111
|
async function runBatchBody(ctx, commands, user, requestId, inheritedOrigin) {
|
|
100
112
|
const { idempotency, lifecycle, appContext: context } = ctx;
|
|
101
113
|
if (commands.length === 0) {
|
|
@@ -157,7 +169,7 @@ async function runBatchBody(ctx, commands, user, requestId, inheritedOrigin) {
|
|
|
157
169
|
// Fires the batch-level system hooks with every successful save/delete
|
|
158
170
|
// context from this run. Called after flushAfterCommit so per-save hooks
|
|
159
171
|
// have all completed first; errors are isolated inside lifecycleHooks.
|
|
160
|
-
const flushBatchHooksInner = async () => {
|
|
172
|
+
const flushBatchHooksInner = async (origin) => {
|
|
161
173
|
try {
|
|
162
174
|
const saves = [];
|
|
163
175
|
const deletes = [];
|
|
@@ -171,10 +183,17 @@ async function runBatchBody(ctx, commands, user, requestId, inheritedOrigin) {
|
|
|
171
183
|
else if (r.data.kind === "delete")
|
|
172
184
|
deletes.push(r.data);
|
|
173
185
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
186
|
+
// skip: nothing to flush when there are no lifecycle hooks or no successful save/delete
|
|
187
|
+
if (!lifecycle || (saves.length === 0 && deletes.length === 0))
|
|
188
|
+
return;
|
|
189
|
+
// Post-commit context: batch hooks may write, but nothing is left to roll back.
|
|
190
|
+
const hookContext = await buildHandlerContext(ctx, BATCH_HOOKS_CONTEXT_TYPE, user, origin, {
|
|
191
|
+
transactionScope: "postCommit",
|
|
192
|
+
});
|
|
193
|
+
if (saves.length > 0)
|
|
194
|
+
await lifecycle.runPostSaveBatch(saves, hookContext);
|
|
195
|
+
if (deletes.length > 0)
|
|
196
|
+
await lifecycle.runPostDeleteBatch(deletes, hookContext);
|
|
178
197
|
}
|
|
179
198
|
catch (e) {
|
|
180
199
|
// Batch hooks must never fail the batch — the commit already happened.
|
|
@@ -190,7 +209,7 @@ async function runBatchBody(ctx, commands, user, requestId, inheritedOrigin) {
|
|
|
190
209
|
// skip: no command ran, so batch hooks have no saves or deletes to see
|
|
191
210
|
if (!strictest)
|
|
192
211
|
return;
|
|
193
|
-
await runWithWriteOrigin(strictest, flushBatchHooksInner);
|
|
212
|
+
await runWithWriteOrigin(strictest, () => flushBatchHooksInner(strictest));
|
|
194
213
|
};
|
|
195
214
|
const perCommandRejection = perCommandBatchRejection(ctx, commands);
|
|
196
215
|
if (perCommandRejection)
|
|
@@ -208,7 +227,7 @@ async function runBatchBody(ctx, commands, user, requestId, inheritedOrigin) {
|
|
|
208
227
|
}, reservations.error.httpStatus >= 500);
|
|
209
228
|
}
|
|
210
229
|
// batch() opens its own outer transaction — needs the top-level
|
|
211
|
-
// connection's `.begin()` (
|
|
230
|
+
// connection's `.begin()` (a transaction handle cannot begin another one).
|
|
212
231
|
const db = resolveAppPoolDb(ctx);
|
|
213
232
|
if (!db || runsWithoutTransaction) {
|
|
214
233
|
// Without a DB connection (or for a perCommand handler, whose writes open their own transactions)
|
|
@@ -250,6 +269,7 @@ async function runBatchBody(ctx, commands, user, requestId, inheritedOrigin) {
|
|
|
250
269
|
// Rollback or failed COMMIT: the transaction is over, so the reserved capacity goes back.
|
|
251
270
|
// The release is outcome-safe: it only gives back a reservation row the handler tx did not delete.
|
|
252
271
|
await reservations.releaseAll();
|
|
272
|
+
await flushAfterRollback(afterCommitHooks, createFallbackLogger("dispatcher", context.log));
|
|
253
273
|
if (e instanceof BatchRollback) {
|
|
254
274
|
// Thrown inside the callback, so the tx rolled back. A 4xx is
|
|
255
275
|
// deterministic and stays cached; a 5xx may be transient.
|
|
@@ -4,15 +4,16 @@ import { hasAccess } from "../engine/access.js";
|
|
|
4
4
|
import { tenantOverrideDenied } from "../engine/cross-tenant.js";
|
|
5
5
|
import { filterReadFields } from "../engine/field-access.js";
|
|
6
6
|
import { NotFoundError, validationErrorFromZod } from "../errors/index.js";
|
|
7
|
-
import { assertNoSecretLeak } from "../secrets/
|
|
7
|
+
import { assertNoSecretLeak } from "../secrets/leak-guard.js";
|
|
8
|
+
import { runInDispatchScope } from "./dispatch-scope.js";
|
|
8
9
|
import { buildHandlerContext, enforceRateLimit, ensureFeatureEnabled, isMemberResolutionPrincipal, runHandlerInstrumented, } from "./dispatch-shared.js";
|
|
9
10
|
import { handlerAccessError } from "./handler-access-error.js";
|
|
10
11
|
import { runInMemberReadOnlyTransaction } from "./member-read-only-transaction.js";
|
|
11
12
|
// Standalone query execution — used by the public dispatcher.query() and
|
|
12
|
-
// by ctx.query/ctx.queryAs inside handlers. Runs the handler, applies
|
|
13
|
+
// by ctx.dispatch.query/ctx.dispatch.queryAs inside handlers. Runs the handler, applies
|
|
13
14
|
// field-level read filters for the given user, logs the event.
|
|
14
15
|
export async function executeQuery(ctx, type, payload, user, origin, tx, outerNotifySink) {
|
|
15
|
-
return runHandlerInstrumented(ctx, type, "query", user, () => executeQueryInner(ctx, type, payload, user, origin, tx, outerNotifySink));
|
|
16
|
+
return runInDispatchScope(ctx.registry, [type], user, () => runHandlerInstrumented(ctx, type, "query", user, () => executeQueryInner(ctx, type, payload, user, origin, tx, outerNotifySink)));
|
|
16
17
|
}
|
|
17
18
|
async function executeQueryInner(ctx, type, payload, user, origin, tx, outerNotifySink) {
|
|
18
19
|
const { registry } = ctx;
|
|
@@ -52,7 +53,7 @@ async function executeQueryInner(ctx, type, payload, user, origin, tx, outerNoti
|
|
|
52
53
|
// so other handlers never see the flag. Visibility filters still apply
|
|
53
54
|
// downstream (see HandlerContext.includeDeleted) — safe from raw input.
|
|
54
55
|
const includeDeleted = propertyOf(parsed.data, "includeDeleted") === true;
|
|
55
|
-
// A resolved member (ctx.queryAsMember) runs in a Postgres READ ONLY transaction, not just the ctx surface below.
|
|
56
|
+
// A resolved member (ctx.dispatch.queryAsMember) runs in a Postgres READ ONLY transaction, not just the ctx surface below.
|
|
56
57
|
return isMemberResolutionPrincipal(user)
|
|
57
58
|
? runInMemberReadOnlyTransaction(ctx, tx, (readOnlyTx) => runQueryHandler(ctx, type, handler, parsed.data, includeDeleted, user, origin, readOnlyTx))
|
|
58
59
|
: runQueryHandler(ctx, type, handler, parsed.data, includeDeleted, user, origin, tx, outerNotifySink);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SessionUser } from "@cosmicdrift/kumiko-types/handlers";
|
|
2
|
+
import { type RowLevelSecurityScope } from "../db/row-level-security-scope.ts";
|
|
3
|
+
import type { Registry } from "../engine/types/index.ts";
|
|
4
|
+
export declare function dispatchRowLevelSecurityScope(registry: Registry, types: readonly string[], user: SessionUser): RowLevelSecurityScope;
|
|
5
|
+
export declare function runInDispatchScope<T>(registry: Registry, types: readonly string[], user: SessionUser, fn: () => T): T;
|
|
6
|
+
export declare function streamInDispatchScope<T>(scope: RowLevelSecurityScope, source: AsyncGenerator<T>): AsyncGenerator<T>;
|