@cosmicdrift/kumiko-framework 0.389.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 +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/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 +83 -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 +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/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 +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 +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 +1 -9
- package/dist/upgrade-cli.js +10 -64
- 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 +22 -18
- package/src/changes.json +206 -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
|
@@ -2,6 +2,7 @@ import { escapeHatchFor } from "@cosmicdrift/kumiko-types/handlers";
|
|
|
2
2
|
import { withSystemDbUnsafeRawGrant, withUnsafeRawGrant } from "../db/tenant-db.js";
|
|
3
3
|
import { SYSTEM_ROLE, SYSTEM_USER_ID } from "../engine/system-user.js";
|
|
4
4
|
import { AccessDeniedError, FrameworkReasons, InternalError } from "../errors/index.js";
|
|
5
|
+
import { attachOutsideTransaction } from "./attach-outside-transaction.js";
|
|
5
6
|
export function isSystemIdentity(user) {
|
|
6
7
|
return user.id === SYSTEM_USER_ID || user.roles.includes(SYSTEM_ROLE);
|
|
7
8
|
}
|
|
@@ -49,14 +50,14 @@ export function identitySwitchDenied(callerLabel, asUser) {
|
|
|
49
50
|
}
|
|
50
51
|
export function unsafeAllTenantsDenied(callerLabel) {
|
|
51
52
|
return new AccessDeniedError({
|
|
52
|
-
message: `${callerLabel} may not call ctx.queryProjection(..., { unsafeAllTenants: true }) — declare ` +
|
|
53
|
+
message: `${callerLabel} may not call ctx.dispatch.queryProjection(..., { unsafeAllTenants: true }) — declare ` +
|
|
53
54
|
"r.systemScope() or escapeHatch: { reason } on it",
|
|
54
55
|
details: { reason: FrameworkReasons.unsafeAllTenantsDenied },
|
|
55
56
|
});
|
|
56
57
|
}
|
|
57
58
|
// Reverse-lookup so withHookEscapeHatchGrant can re-gate the SAME ungated pair (and caller) under a narrower grant.
|
|
58
59
|
const sourceByGated = new WeakMap();
|
|
59
|
-
// Same idea, for ctx.queryAsMember — a single function rather than a pair.
|
|
60
|
+
// Same idea, for ctx.dispatch.queryAsMember — a single function rather than a pair.
|
|
60
61
|
const ungatedMemberReaderByGated = new WeakMap();
|
|
61
62
|
function reportGrantedSwitch(caller, asUser, hasGrant, audit) {
|
|
62
63
|
// skip: no audit wired, switch wasn't grant-gated, or grant carries no reason to report
|
|
@@ -88,7 +89,7 @@ export function createGatedIdentitySwitch(callerLabel, caller, hasGrant, ungated
|
|
|
88
89
|
sourceByGated.set(writeAs, source);
|
|
89
90
|
return gated;
|
|
90
91
|
}
|
|
91
|
-
// ctx.queryAsMember's gate: the caller never names the target identity up
|
|
92
|
+
// ctx.dispatch.queryAsMember's gate: the caller never names the target identity up
|
|
92
93
|
// front (it's resolved internally), so this is a flat allow/deny.
|
|
93
94
|
export function createGatedMemberReader(callerLabel, allowSystemIdentity, ungated, audit) {
|
|
94
95
|
const gated = async (userId, qn, payload) => {
|
|
@@ -102,9 +103,9 @@ export function createGatedMemberReader(callerLabel, allowSystemIdentity, ungate
|
|
|
102
103
|
ungatedMemberReaderByGated.set(gated, { ungated, audit });
|
|
103
104
|
return gated;
|
|
104
105
|
}
|
|
105
|
-
// Same idea, for ctx.queryProjection — a single function rather than a pair.
|
|
106
|
+
// Same idea, for ctx.dispatch.queryProjection — a single function rather than a pair.
|
|
106
107
|
const ungatedProjectionReaderByGated = new WeakMap();
|
|
107
|
-
// ctx.queryProjection's gate: only { unsafeAllTenants: true } on a projection with a
|
|
108
|
+
// ctx.dispatch.queryProjection's gate: only { unsafeAllTenants: true } on a projection with a
|
|
108
109
|
// tenant column is grant-checked — a plain call always passes through, tenant-scoped
|
|
109
110
|
// by the projection's own table, and the flag is a no-op on a tenant-less one.
|
|
110
111
|
export function createGatedProjectionReader(callerLabel, hasGrant, ungated, audit, projectionHasTenantColumn = () => true) {
|
|
@@ -121,19 +122,20 @@ export function createGatedProjectionReader(callerLabel, hasGrant, ungated, audi
|
|
|
121
122
|
ungatedProjectionReaderByGated.set(gated, { ungated, report: audit?.report });
|
|
122
123
|
return gated;
|
|
123
124
|
}
|
|
124
|
-
|
|
125
|
-
|
|
125
|
+
// Reads own keys only — never touch a property of a resolved value, which may be a Proxy that throws on any get.
|
|
126
|
+
function readMember(namespace, key) {
|
|
127
|
+
if (namespace === undefined || !(key in namespace))
|
|
126
128
|
return undefined;
|
|
127
|
-
|
|
128
|
-
return typeof value === "function" ? value : undefined; // @cast-boundary engine-bridge — checked via typeof above
|
|
129
|
+
return Reflect.get(namespace, key);
|
|
129
130
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if (!(key in context))
|
|
133
|
-
return undefined;
|
|
134
|
-
const value = Reflect.get(context, key);
|
|
131
|
+
function readObjectMember(namespace, key) {
|
|
132
|
+
const value = readMember(namespace, key);
|
|
135
133
|
return typeof value === "object" && value !== null ? value : undefined;
|
|
136
134
|
}
|
|
135
|
+
function readFunctionMember(namespace, key) {
|
|
136
|
+
const value = readMember(namespace, key);
|
|
137
|
+
return typeof value === "function" ? value : undefined; // @cast-boundary engine-bridge — checked via typeof above
|
|
138
|
+
}
|
|
137
139
|
function unavailableIdentitySwitchFn(callerLabel, kind) {
|
|
138
140
|
return async () => {
|
|
139
141
|
throw new InternalError({
|
|
@@ -179,8 +181,8 @@ function gatedIdentitySwitchFields(callerLabel, escapeHatch, ctxQueryAs, ctxWrit
|
|
|
179
181
|
...(ctxWriteAs && { writeAs: gated.writeAs }),
|
|
180
182
|
};
|
|
181
183
|
}
|
|
182
|
-
// Unlike ctx.resolveActiveMembership (deny-only), a hook's own escapeHatch
|
|
183
|
-
// can grant queryAsMember even when the enclosing handler has none.
|
|
184
|
+
// Unlike ctx.auth.resolveActiveMembership (deny-only), a hook's own escapeHatch
|
|
185
|
+
// can grant dispatch.queryAsMember even when the enclosing handler has none.
|
|
184
186
|
function gatedMemberReaderField(callerLabel, escapeHatch, ctxQueryAsMember) {
|
|
185
187
|
if (!ctxQueryAsMember)
|
|
186
188
|
return {};
|
|
@@ -193,7 +195,7 @@ function gatedMemberReaderField(callerLabel, escapeHatch, ctxQueryAsMember) {
|
|
|
193
195
|
queryAsMember: createGatedMemberReader(callerLabel, escapeHatch !== undefined, ungated, audit),
|
|
194
196
|
};
|
|
195
197
|
}
|
|
196
|
-
// Re-gates ctx.queryProjection under the hook's own escapeHatch, same
|
|
198
|
+
// Re-gates ctx.dispatch.queryProjection under the hook's own escapeHatch, same
|
|
197
199
|
// re-gating rule as the other fields below — see withHookEscapeHatchGrant.
|
|
198
200
|
function gatedProjectionReaderField(callerLabel, escapeHatch, ctxQueryProjection) {
|
|
199
201
|
if (!ctxQueryProjection)
|
|
@@ -205,15 +207,26 @@ function gatedProjectionReaderField(callerLabel, escapeHatch, ctxQueryProjection
|
|
|
205
207
|
queryProjection: createGatedProjectionReader(callerLabel, escapeHatch !== undefined, ungated, audit),
|
|
206
208
|
};
|
|
207
209
|
}
|
|
210
|
+
// A rebound db is a new object, so the outsideTransaction property has to be carried over; an input
|
|
211
|
+
// withUnsafeRawGrant passes through unchanged keeps its own.
|
|
212
|
+
function regatedDb(ctxDb, ctxDbOutsideTransaction, rawHatch) {
|
|
213
|
+
const gatedDb = withUnsafeRawGrant(ctxDb, rawHatch);
|
|
214
|
+
if (gatedDb !== ctxDb && ctxDbOutsideTransaction) {
|
|
215
|
+
attachOutsideTransaction(gatedDb, withUnsafeRawGrant(ctxDbOutsideTransaction, rawHatch));
|
|
216
|
+
}
|
|
217
|
+
return gatedDb;
|
|
218
|
+
}
|
|
208
219
|
export function withHookEscapeHatchGrant(context, callerLabel, escapeHatch) {
|
|
209
|
-
const
|
|
210
|
-
const
|
|
211
|
-
const
|
|
212
|
-
const
|
|
213
|
-
const
|
|
214
|
-
const
|
|
215
|
-
const
|
|
216
|
-
const
|
|
220
|
+
const dispatch = readObjectMember(context, "dispatch");
|
|
221
|
+
const auth = readObjectMember(context, "auth");
|
|
222
|
+
const ctxQueryAs = readFunctionMember(dispatch, "queryAs");
|
|
223
|
+
const ctxWriteAs = readFunctionMember(dispatch, "writeAs");
|
|
224
|
+
const ctxResolveActiveMembership = readFunctionMember(auth, "resolveActiveMembership");
|
|
225
|
+
const ctxQueryAsMember = readFunctionMember(dispatch, "queryAsMember");
|
|
226
|
+
const ctxQueryProjection = readFunctionMember(dispatch, "queryProjection");
|
|
227
|
+
const ctxDb = readObjectMember(context, "db");
|
|
228
|
+
const ctxDbOutsideTransaction = readObjectMember(ctxDb, "outsideTransaction");
|
|
229
|
+
const ctxSystemDb = readObjectMember(context, "systemDb");
|
|
217
230
|
const identityHatch = escapeHatchFor(escapeHatch, "systemIdentity");
|
|
218
231
|
const rawHatch = escapeHatchFor(escapeHatch, "unsafeRaw");
|
|
219
232
|
if (!ctxQueryAs &&
|
|
@@ -222,29 +235,31 @@ export function withHookEscapeHatchGrant(context, callerLabel, escapeHatch) {
|
|
|
222
235
|
!ctxQueryAsMember &&
|
|
223
236
|
!ctxQueryProjection &&
|
|
224
237
|
!ctxDb &&
|
|
225
|
-
!ctxDbOutsideTransaction &&
|
|
226
238
|
!ctxSystemDb) {
|
|
227
239
|
return context;
|
|
228
240
|
}
|
|
229
241
|
return {
|
|
230
242
|
...context,
|
|
231
|
-
...
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
243
|
+
...(dispatch && {
|
|
244
|
+
dispatch: {
|
|
245
|
+
...dispatch,
|
|
246
|
+
...gatedIdentitySwitchFields(callerLabel, identityHatch, ctxQueryAs, ctxWriteAs),
|
|
247
|
+
...gatedMemberReaderField(callerLabel, identityHatch, ctxQueryAsMember),
|
|
248
|
+
...gatedProjectionReaderField(callerLabel, identityHatch, ctxQueryProjection),
|
|
249
|
+
},
|
|
235
250
|
}),
|
|
236
|
-
...
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
dbOutsideTransaction: withUnsafeRawGrant(ctxDbOutsideTransaction, rawHatch),
|
|
251
|
+
...(auth &&
|
|
252
|
+
ctxResolveActiveMembership &&
|
|
253
|
+
identityHatch === undefined && {
|
|
254
|
+
auth: { ...auth, resolveActiveMembership: deniedResolveActiveMembership(callerLabel) },
|
|
241
255
|
}),
|
|
256
|
+
...(ctxDb && { db: regatedDb(ctxDb, ctxDbOutsideTransaction, rawHatch) }),
|
|
242
257
|
...(ctxSystemDb && {
|
|
243
258
|
systemDb: withSystemDbUnsafeRawGrant(ctxSystemDb, rawHatch, callerLabel),
|
|
244
259
|
}),
|
|
245
260
|
};
|
|
246
261
|
}
|
|
247
|
-
// Re-gates a hook's own ctx.
|
|
262
|
+
// Re-gates a hook's own ctx.dispatch.*/ctx.auth.resolveActiveMembership/ctx.db (incl. db.outsideTransaction)/ctx.systemDb instead of inheriting the handler's grant.
|
|
248
263
|
export function bindHookEscapeHatchGrant(fn, label, escapeHatch) {
|
|
249
264
|
return ((payload, context) => fn(payload, withHookEscapeHatchGrant(context, label, escapeHatch))); // @cast-boundary engine-bridge — LifecycleHookFn union, same (payload, context) shape at runtime
|
|
250
265
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// The static check in boot-validator/access-declarations.ts only sees a handler's own
|
|
2
|
-
// input schema; writes reached via ctx.write/writeAs/queryAs, hooks or foreign-feature
|
|
2
|
+
// input schema; writes reached via ctx.dispatch.write/writeAs/queryAs, hooks or foreign-feature
|
|
3
3
|
// tables are only visible at the actual write, so the gate runs there at runtime.
|
|
4
4
|
import { isPersonalDataGated } from "@cosmicdrift/kumiko-types/event-store-types";
|
|
5
5
|
import * as z from "zod";
|
|
@@ -37,7 +37,7 @@ function declaresPublicIntake(access) {
|
|
|
37
37
|
return accessAllowsAnonymous(access) && declaredPersonalData(access) === "public-intake";
|
|
38
38
|
}
|
|
39
39
|
// Only the public dispatcher entry points compute a root; every nested call inherits
|
|
40
|
-
// it, so switching identity via ctx.writeAs(SYSTEM, ...) cannot shed an anonymous root.
|
|
40
|
+
// it, so switching identity via ctx.dispatch.writeAs(SYSTEM, ...) cannot shed an anonymous root.
|
|
41
41
|
export function rootWriteOrigin(registry, type, user) {
|
|
42
42
|
const rootHandler = registry.getWriteHandler(type) ?? registry.getQueryHandler(type);
|
|
43
43
|
return {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { WriteResult } from "
|
|
1
|
+
import type { WriteResult } from "@cosmicdrift/kumiko-types/handlers";
|
|
2
2
|
import type { BatchCommand, BatchResult, DispatchContext } from "./dispatch-shared.ts";
|
|
3
3
|
type EntityLookup = Pick<DispatchContext["registry"], "getHandlerEntity" | "getEntity">;
|
|
4
4
|
export declare function maskWriteResultForClient(registry: EntityLookup, handlerType: string, result: WriteResult): WriteResult;
|
package/dist/random/index.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export { ADJECTIVES, NOUNS } from "./words.ts";
|
|
1
|
+
export { generateUniqueName } from "./generate.ts";
|
package/dist/random/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export { ADJECTIVES, NOUNS } from "./words.js";
|
|
1
|
+
export { generateUniqueName } from "./generate.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { PayloadBucketNormalization, RateLimitOption
|
|
1
|
+
import type { PayloadBucketNormalization, RateLimitOption } from "@cosmicdrift/kumiko-types/handlers";
|
|
2
|
+
import type { SessionUser } from "../engine/types/index.ts";
|
|
2
3
|
export type BucketContext = {
|
|
3
4
|
readonly handlerName: string;
|
|
4
5
|
readonly user: SessionUser;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { isAuthRateLimitExempt } from "../api/api-constants.js";
|
|
2
2
|
import { clientIpSourceFromHonoContext, createClientIpResolver, } from "../api/client-ip.js";
|
|
3
3
|
import { requestContext } from "../api/request-context.js";
|
|
4
|
-
import { RateLimitError
|
|
4
|
+
import { RateLimitError } from "../errors/index.js";
|
|
5
|
+
import { serializeError } from "../errors/serialize.js";
|
|
5
6
|
import { createFallbackLogger, scrubLogText } from "../logging/index.js";
|
|
6
7
|
import { emitRateLimitFailOpen } from "../observability/standard-metrics.js";
|
|
7
8
|
import { toPublicBucketName } from "./bucket.js";
|
package/dist/redis/index.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
export type { CacheSyncBus,
|
|
2
|
-
export {
|
|
1
|
+
export type { CacheSyncBus, ClosableCacheSyncBus, } from "./cache-sync-bus.ts";
|
|
2
|
+
export { createDefaultCacheSyncBus, createLocalCacheSyncBus, createRedisCacheSyncBus, } from "./cache-sync-bus.ts";
|
|
3
3
|
export type { TenantConfigSyncMessage, TierAssignmentSyncMessage } from "./cache-sync-topics.ts";
|
|
4
|
-
export { CACHE_SYNC_TOPICS,
|
|
4
|
+
export { CACHE_SYNC_TOPICS, isTierAssignmentSyncMessage, } from "./cache-sync-topics.ts";
|
|
5
5
|
export type { RedisClientOptions } from "./client.ts";
|
|
6
6
|
export { createRedisClient, logRedisConnectionState, redisChannelPrefixFromEnv, redisClientOptionsFromEnv, } from "./client.ts";
|
|
7
|
-
export type { PubSubSignal, PubSubSignalOptions } from "./pubsub-signal.ts";
|
|
8
7
|
export { createRedisPubSubSignal } from "./pubsub-signal.ts";
|
package/dist/redis/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export { CACHE_SYNC_TOPICS,
|
|
1
|
+
export { createDefaultCacheSyncBus, createLocalCacheSyncBus, createRedisCacheSyncBus, } from "./cache-sync-bus.js";
|
|
2
|
+
export { CACHE_SYNC_TOPICS, isTierAssignmentSyncMessage, } from "./cache-sync-topics.js";
|
|
3
3
|
export { createRedisClient, logRedisConnectionState, redisChannelPrefixFromEnv, redisClientOptionsFromEnv, } from "./client.js";
|
|
4
4
|
export { createRedisPubSubSignal } from "./pubsub-signal.js";
|
|
@@ -4,7 +4,7 @@ import { createRegistry } from "../engine/registry.js";
|
|
|
4
4
|
import { createEventsTable } from "../event-store/index.js";
|
|
5
5
|
import { queueRebuildsFromMarkers, reportPendingRebuildRun, runPendingRebuilds, } from "../migrations/index.js";
|
|
6
6
|
import { createEventConsumerStateTable, createProjectionStateTable } from "../pipeline/index.js";
|
|
7
|
-
import { migrationsDirExistsOrReport, readDatabaseUrlOrReport, } from "./shared.js";
|
|
7
|
+
import { loadRowLevelSecurityModeOrReport, migrationsDirExistsOrReport, readDatabaseUrlOrReport, } from "./shared.js";
|
|
8
8
|
async function ensureFrameworkInfrastructureTables(db) {
|
|
9
9
|
// Framework infrastructure tables (event store + pipeline state) are not captured by
|
|
10
10
|
// `generate`, which handles only entity read tables. Existing databases have them
|
|
@@ -52,7 +52,10 @@ export async function runApplyCommand(ctx) {
|
|
|
52
52
|
return 1;
|
|
53
53
|
if (!migrationsDirExistsOrReport(ctx))
|
|
54
54
|
return 1;
|
|
55
|
-
const
|
|
55
|
+
const rowLevelSecurity = await loadRowLevelSecurityModeOrReport(ctx);
|
|
56
|
+
if (rowLevelSecurity === undefined)
|
|
57
|
+
return 1;
|
|
58
|
+
const { db, close } = createDbConnection({ url: dbUrl, rowLevelSecurity });
|
|
56
59
|
let wiring;
|
|
57
60
|
try {
|
|
58
61
|
const result = await runMigrationsFromDir(db, migrationsDir);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createDbConnection } from "../db/index.js";
|
|
2
|
+
import { baselineMigrations, loadMigrationsFromDir } from "../db/migrate-runner.js";
|
|
2
3
|
import { describeThrown, migrationsDirExistsOrReport, readDatabaseUrlOrReport, } from "./shared.js";
|
|
3
4
|
export async function runBaselineCommand(ctx) {
|
|
4
5
|
const { out, migrationsDir } = ctx;
|
|
@@ -10,7 +11,11 @@ export async function runBaselineCommand(ctx) {
|
|
|
10
11
|
return 1;
|
|
11
12
|
if (!migrationsDirExistsOrReport(ctx))
|
|
12
13
|
return 1;
|
|
13
|
-
const { db, close } = createDbConnection({
|
|
14
|
+
const { db, close } = createDbConnection({
|
|
15
|
+
url: dbUrl,
|
|
16
|
+
maxConnections: 1,
|
|
17
|
+
rowLevelSecurity: "off", // journal-only tool: touches no tenant rows
|
|
18
|
+
});
|
|
14
19
|
try {
|
|
15
20
|
const result = await baselineMigrations(db, loadMigrationsFromDir(migrationsDir));
|
|
16
21
|
out.log("");
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { generateMigration, writeSnapshotJson } from "../db/index.js";
|
|
4
|
+
import { assertValidMigrationName, hasNoSchemaChanges } from "../db/migrate-generator.js";
|
|
5
|
+
import { readMigrationSqlTexts } from "../db/migrate-runner.js";
|
|
6
|
+
import { rebuildTablesFromDiff, writeRebuildMarker } from "../db/rebuild-marker.js";
|
|
4
7
|
import { describeThrown, loadPreviousSnapshot, loadSchemaModOrReport, nextSequenceNumber, SNAPSHOT_FILENAME, } from "./shared.js";
|
|
5
8
|
const GENERATE_USAGE = " Usage: schema generate <name>";
|
|
6
9
|
function parseGenerateName(ctx) {
|
|
@@ -35,12 +38,6 @@ function parseGenerateName(ctx) {
|
|
|
35
38
|
}
|
|
36
39
|
return { kind: "name", name };
|
|
37
40
|
}
|
|
38
|
-
function isEmptyMigration(result) {
|
|
39
|
-
return (result.diff.newTables.length === 0 &&
|
|
40
|
-
result.diff.changedTables.length === 0 &&
|
|
41
|
-
result.diff.droppedTables.length === 0 &&
|
|
42
|
-
result.retiredDrops.length === 0);
|
|
43
|
-
}
|
|
44
41
|
function writeMigrationFiles(migrationsDir, snapshotPath, result) {
|
|
45
42
|
if (!existsSync(migrationsDir))
|
|
46
43
|
mkdirSync(migrationsDir, { recursive: true });
|
|
@@ -50,7 +47,7 @@ function writeMigrationFiles(migrationsDir, snapshotPath, result) {
|
|
|
50
47
|
function reportGeneratedMigration(out, result, rebuildTables) {
|
|
51
48
|
out.log("");
|
|
52
49
|
out.log(` ✓ ${result.filename}`);
|
|
53
|
-
out.log(` new tables: ${result.diff.newTables.length}, changed: ${result.diff.changedTables.length}, dropped: ${result.diff.droppedTables.length}, retired framework tables dropped: ${result.retiredDrops.length}`);
|
|
50
|
+
out.log(` new tables: ${result.diff.newTables.length}, changed: ${result.diff.changedTables.length}, dropped: ${result.diff.droppedTables.length}, retired framework tables dropped: ${result.retiredDrops.length}, row level security changes: ${result.rowLevelSecurityChanges.length}`);
|
|
54
51
|
if (rebuildTables.length > 0) {
|
|
55
52
|
out.log(` rebuild-marker: ${result.filename.replace(/\.sql$/, ".rebuild.json")} (${rebuildTables.length} table(s))`);
|
|
56
53
|
}
|
|
@@ -70,12 +67,13 @@ export async function runGenerateCommand(ctx) {
|
|
|
70
67
|
const prevSnapshot = loadPreviousSnapshot(snapshotPath);
|
|
71
68
|
const result = generateMigration({
|
|
72
69
|
metas: schemaMod.entityMetas,
|
|
70
|
+
rowLevelSecurity: schemaMod.rowLevelSecurity,
|
|
73
71
|
prevSnapshot,
|
|
74
72
|
name: parsed.name,
|
|
75
73
|
sequenceNumber: nextSequenceNumber(migrationsDir),
|
|
76
74
|
priorMigrationsSql: readMigrationSqlTexts(migrationsDir),
|
|
77
75
|
});
|
|
78
|
-
if (
|
|
76
|
+
if (hasNoSchemaChanges(result)) {
|
|
79
77
|
out.log(" No schema changes detected — no new migration file written.");
|
|
80
78
|
return 0;
|
|
81
79
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type renderTablesDdl } from "../db/index.ts";
|
|
2
|
+
import { type RowLevelSecurityMode } from "../db/render-rls-ddl.ts";
|
|
2
3
|
import type { FeatureDefinition } from "../engine/types/feature.ts";
|
|
3
4
|
export type SchemaCliOut = {
|
|
4
5
|
readonly log: (line: string) => void;
|
|
@@ -30,10 +31,13 @@ export type SchemaMod = {
|
|
|
30
31
|
readonly entityMetas: Parameters<typeof renderTablesDdl>[0];
|
|
31
32
|
readonly features?: unknown;
|
|
32
33
|
readonly validateBootOptions?: unknown;
|
|
34
|
+
readonly rowLevelSecurity: RowLevelSecurityMode;
|
|
33
35
|
};
|
|
36
|
+
export declare function parseSchemaRowLevelSecurity(value: unknown, schemaFile: string): RowLevelSecurityMode;
|
|
34
37
|
export declare function describeThrown(e: unknown): string;
|
|
35
38
|
export declare function nextSequenceNumber(migrationsDir: string): number;
|
|
36
39
|
export declare function loadPreviousSnapshot(snapshotPath: string): import("../db/migrate-generator.ts").Snapshot | null;
|
|
37
40
|
export declare function loadSchemaModOrReport(ctx: SchemaCliContext): Promise<SchemaMod | undefined>;
|
|
41
|
+
export declare function loadRowLevelSecurityModeOrReport(ctx: SchemaCliContext): Promise<RowLevelSecurityMode | undefined>;
|
|
38
42
|
export declare function readDatabaseUrlOrReport(out: SchemaCliOut): string | undefined;
|
|
39
43
|
export declare function migrationsDirExistsOrReport(ctx: SchemaCliContext): boolean;
|
|
@@ -7,10 +7,20 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
7
7
|
return path;
|
|
8
8
|
};
|
|
9
9
|
import { existsSync, readdirSync } from "node:fs";
|
|
10
|
-
import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
11
|
-
import {
|
|
10
|
+
import { isOneOf, isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
11
|
+
import { loadSnapshotJson } from "../db/index.js";
|
|
12
|
+
import { assertUniqueTableNames } from "../db/migrate-generator.js";
|
|
13
|
+
import { DEFAULT_ROW_LEVEL_SECURITY_MODE, ROW_LEVEL_SECURITY_MODES, } from "../db/render-rls-ddl.js";
|
|
12
14
|
import { isEntityTableMeta } from "../db/table-introspection.js";
|
|
13
15
|
export const SNAPSHOT_FILENAME = ".snapshot.json";
|
|
16
|
+
// An absent export means the default mode; a typo must not silently switch tenant isolation off.
|
|
17
|
+
export function parseSchemaRowLevelSecurity(value, schemaFile) {
|
|
18
|
+
if (value === undefined)
|
|
19
|
+
return DEFAULT_ROW_LEVEL_SECURITY_MODE;
|
|
20
|
+
if (isOneOf(ROW_LEVEL_SECURITY_MODES, value))
|
|
21
|
+
return value;
|
|
22
|
+
throw new Error(`Schema file ${schemaFile}: ROW_LEVEL_SECURITY must be one of ${ROW_LEVEL_SECURITY_MODES.join(", ")}, got ${String(value)}.`);
|
|
23
|
+
}
|
|
14
24
|
export function describeThrown(e) {
|
|
15
25
|
return e instanceof Error ? e.message : String(e);
|
|
16
26
|
}
|
|
@@ -43,6 +53,7 @@ async function loadSchemaModFromApp(schemaFile) {
|
|
|
43
53
|
entityMetas: validMetas,
|
|
44
54
|
features: mod["FEATURES"],
|
|
45
55
|
validateBootOptions: mod["VALIDATE_BOOT_OPTIONS"],
|
|
56
|
+
rowLevelSecurity: parseSchemaRowLevelSecurity(mod["ROW_LEVEL_SECURITY"], schemaFile),
|
|
46
57
|
};
|
|
47
58
|
}
|
|
48
59
|
export function nextSequenceNumber(migrationsDir) {
|
|
@@ -79,6 +90,14 @@ export async function loadSchemaModOrReport(ctx) {
|
|
|
79
90
|
return undefined;
|
|
80
91
|
}
|
|
81
92
|
}
|
|
93
|
+
// `apply` needs only the mode: migrations and rebuilds on a role that RLS binds see nothing unless
|
|
94
|
+
// the connection runs in system scope, which only an "on" connection sets. Without a schema file
|
|
95
|
+
// (dev CLI against a bare checkout) there is nothing to enforce.
|
|
96
|
+
export async function loadRowLevelSecurityModeOrReport(ctx) {
|
|
97
|
+
if (!existsSync(ctx.schemaFile))
|
|
98
|
+
return "off";
|
|
99
|
+
return (await loadSchemaModOrReport(ctx))?.rowLevelSecurity;
|
|
100
|
+
}
|
|
82
101
|
export function readDatabaseUrlOrReport(out) {
|
|
83
102
|
const dbUrl = process.env["DATABASE_URL"];
|
|
84
103
|
if (!dbUrl) {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { createDbConnection,
|
|
3
|
+
import { createDbConnection, tableExists } from "../db/index.js";
|
|
4
|
+
import { fetchAppliedMigrations, loadMigrationsFromDir, readMigrationSqlTexts, } from "../db/migrate-runner.js";
|
|
5
|
+
import { findCommentedDropTables, isRetiredFrameworkTable, } from "../db/retired-framework-tables.js";
|
|
4
6
|
import { describeThrown, loadPreviousSnapshot, readDatabaseUrlOrReport, SNAPSHOT_FILENAME, } from "./shared.js";
|
|
5
7
|
// A table that a migration only drops as a commented DESTRUCTIVE marker and
|
|
6
8
|
// that the snapshot no longer has is gone on paper but still in the live DB.
|
|
@@ -42,7 +44,11 @@ export async function runStatusCommand(ctx) {
|
|
|
42
44
|
return 0;
|
|
43
45
|
}
|
|
44
46
|
const local = loadMigrationsFromDir(migrationsDir);
|
|
45
|
-
const { db, close } = createDbConnection({
|
|
47
|
+
const { db, close } = createDbConnection({
|
|
48
|
+
url: dbUrl,
|
|
49
|
+
maxConnections: 1,
|
|
50
|
+
rowLevelSecurity: "off", // journal-only tool: touches no tenant rows
|
|
51
|
+
});
|
|
46
52
|
try {
|
|
47
53
|
const applied = await fetchAppliedMigrationIds(db);
|
|
48
54
|
out.log("");
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { assertRowLevelSecurityTableState, createDbConnection, generateMigration, } from "../db/index.js";
|
|
4
|
+
import { knownTablesOf } from "../db/known-table-names.js";
|
|
5
|
+
import { readMigrationSqlTexts } from "../db/migrate-runner.js";
|
|
6
|
+
import { diffReplayAgainstSnapshot, replayMigrationsDir } from "../db/replay-migration-sql.js";
|
|
4
7
|
import { validateBoot } from "../engine/boot-validator.js";
|
|
5
8
|
import { describeThrown, loadPreviousSnapshot, loadSchemaModOrReport, nextSequenceNumber, SNAPSHOT_FILENAME, } from "./shared.js";
|
|
6
9
|
import { featureDefinitionsOf, parseValidateBootOptions, withFileStoragePresence, } from "./validate-boot-input.js";
|
|
@@ -9,6 +12,7 @@ function checkSchemaDrift(ctx, schemaMod, prevSnapshot) {
|
|
|
9
12
|
const { out, migrationsDir } = ctx;
|
|
10
13
|
const drift = generateMigration({
|
|
11
14
|
metas: schemaMod.entityMetas,
|
|
15
|
+
rowLevelSecurity: schemaMod.rowLevelSecurity,
|
|
12
16
|
prevSnapshot,
|
|
13
17
|
name: "validate",
|
|
14
18
|
sequenceNumber: nextSequenceNumber(migrationsDir),
|
|
@@ -19,13 +23,14 @@ function checkSchemaDrift(ctx, schemaMod, prevSnapshot) {
|
|
|
19
23
|
...drift.diff.changedTables.map((t) => t.tableName),
|
|
20
24
|
...drift.diff.droppedTables,
|
|
21
25
|
...drift.retiredDrops.map((t) => t.tableName),
|
|
26
|
+
...drift.rowLevelSecurityChanges.map((c) => c.tableName),
|
|
22
27
|
];
|
|
23
28
|
if (pendingTables.length === 0) {
|
|
24
29
|
out.log(" ✓ schema: migrations match the entity definitions");
|
|
25
30
|
return true;
|
|
26
31
|
}
|
|
27
32
|
out.err(" ✗ schema drift: entity definitions are ahead of kumiko/migrations.");
|
|
28
|
-
out.err(` pending — new: ${drift.diff.newTables.length}, changed: ${drift.diff.changedTables.length}, dropped: ${drift.diff.droppedTables.length}`);
|
|
33
|
+
out.err(` pending — new: ${drift.diff.newTables.length}, changed: ${drift.diff.changedTables.length}, dropped: ${drift.diff.droppedTables.length}, row level security: ${drift.rowLevelSecurityChanges.length}`);
|
|
29
34
|
out.err(` tables: ${pendingTables.join(", ")}`);
|
|
30
35
|
out.err(" Fix: `kumiko-schema generate <name>`, then commit the migration.");
|
|
31
36
|
return false;
|
|
@@ -57,6 +62,46 @@ function checkBootValidity(out, schemaMod) {
|
|
|
57
62
|
return false;
|
|
58
63
|
}
|
|
59
64
|
}
|
|
65
|
+
// 4. Live row-level security table state — the table half of the boot check. Only with a DATABASE_URL;
|
|
66
|
+
// without one the command stays database-free.
|
|
67
|
+
async function checkLiveRowLevelSecurity(out, schemaMod) {
|
|
68
|
+
const dbUrl = process.env["DATABASE_URL"];
|
|
69
|
+
if (!dbUrl) {
|
|
70
|
+
out.log(" · row-level security: skipped — set DATABASE_URL to check the live database.");
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
let features;
|
|
74
|
+
try {
|
|
75
|
+
features = featureDefinitionsOf(schemaMod.features);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// skip: the boot check already reported the unreadable FEATURES export
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
const knownTables = features === undefined ? { has: () => true } : knownTablesOf(features);
|
|
82
|
+
const { db, close } = createDbConnection({
|
|
83
|
+
url: dbUrl,
|
|
84
|
+
maxConnections: 1,
|
|
85
|
+
rowLevelSecurity: schemaMod.rowLevelSecurity,
|
|
86
|
+
});
|
|
87
|
+
try {
|
|
88
|
+
await assertRowLevelSecurityTableState(db, schemaMod.rowLevelSecurity, knownTables);
|
|
89
|
+
out.log(" ✓ row-level security: live database matches the configured mode");
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
out.err(` ✗ row-level security: ${describeThrown(e)}`);
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
try {
|
|
98
|
+
await close();
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// The check result is already reported; a failing close must not hide it.
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
60
105
|
function reportMigrationContentMismatches(out, mismatches) {
|
|
61
106
|
out.err(" ✗ migration-content drift: committed *.sql files don't produce .snapshot.json.");
|
|
62
107
|
for (const m of mismatches) {
|
|
@@ -72,7 +117,7 @@ function reportMigrationContentMismatches(out, mismatches) {
|
|
|
72
117
|
"job-run-log store table for the pattern.");
|
|
73
118
|
}
|
|
74
119
|
if (mismatches.some((m) => m.kind !== "unexpected-table")) {
|
|
75
|
-
out.err(" Fix (missing-table/column-drift): a migration file's body doesn't match " +
|
|
120
|
+
out.err(" Fix (missing-table/column-drift/row-level-security-drift): a migration file's body doesn't match " +
|
|
76
121
|
"what it (or the snapshot) claims — hand-fix the file, or ship a corrective " +
|
|
77
122
|
"migration if it's already applied in prod.");
|
|
78
123
|
}
|
|
@@ -117,6 +162,8 @@ function checkMigrationContentDrift(ctx, prevSnapshot) {
|
|
|
117
162
|
// Layer 1 alone misses this: it only compares ENTITY_METAS to the
|
|
118
163
|
// snapshot, never the snapshot to the SQL that's supposed to have
|
|
119
164
|
// produced it.
|
|
165
|
+
// 4. live row-level security (only with DATABASE_URL): the boot's
|
|
166
|
+
// table-state check against the real database (not the role: that is a boot-time property).
|
|
120
167
|
// The DB-level gate (assertKumikoSchemaCurrent) stays at boot/deploy.
|
|
121
168
|
export async function runValidateCommand(ctx) {
|
|
122
169
|
const schemaMod = await loadSchemaModOrReport(ctx);
|
|
@@ -126,5 +173,6 @@ export async function runValidateCommand(ctx) {
|
|
|
126
173
|
const schemaOk = checkSchemaDrift(ctx, schemaMod, prevSnapshot);
|
|
127
174
|
const bootOk = checkBootValidity(ctx.out, schemaMod);
|
|
128
175
|
const migrationsOk = checkMigrationContentDrift(ctx, prevSnapshot);
|
|
129
|
-
|
|
176
|
+
const rowLevelSecurityOk = await checkLiveRowLevelSecurity(ctx.out, schemaMod);
|
|
177
|
+
return schemaOk && bootOk && migrationsOk && rowLevelSecurityOk ? 0 : 1;
|
|
130
178
|
}
|
package/dist/schema-cli.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { RunSchemaCliOptions, SchemaCliOut } from "./schema-cli/shared.ts";
|
|
2
|
-
export type { RunSchemaCliOptions, SchemaCliOut } from "./schema-cli/shared.ts";
|
|
3
2
|
/**
|
|
4
3
|
* Runs a schema-CLI subcommand. `appCwd` is the app workspace root (where
|
|
5
4
|
* `kumiko/schema.ts` + `kumiko/migrations/` live). Returns a process exit code.
|
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
import type { Registry
|
|
2
|
-
import type { SearchAdapter } from "./types.ts";
|
|
1
|
+
import type { Registry } from "../engine/types/index.ts";
|
|
3
2
|
export declare function collectSearchableFieldNames(registry: Registry): readonly string[];
|
|
4
|
-
export declare function configureTenantSearchIndex(searchAdapter: SearchAdapter, registry: Registry, tenantId: TenantId): Promise<void>;
|
|
@@ -2,7 +2,3 @@ import { deriveSearchAdapterConfig } from "./derive-search-adapter-config.js";
|
|
|
2
2
|
export function collectSearchableFieldNames(registry) {
|
|
3
3
|
return deriveSearchAdapterConfig(registry)?.searchableFields ?? [];
|
|
4
4
|
}
|
|
5
|
-
export async function configureTenantSearchIndex(searchAdapter, registry, tenantId) {
|
|
6
|
-
const fields = collectSearchableFieldNames(registry);
|
|
7
|
-
await searchAdapter.configure(tenantId, { searchableFields: fields, rankingFields: fields });
|
|
8
|
-
}
|
package/dist/search/index.d.ts
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
export { collectSearchableFieldNames, configureTenantSearchIndex, } from "./configure-tenant-index.ts";
|
|
2
|
-
export { deriveSearchAdapterConfig } from "./derive-search-adapter-config.ts";
|
|
3
1
|
export { createInMemorySearchAdapter } from "./in-memory-adapter.ts";
|
|
4
2
|
export { purgeSearchDocumentsForSubject } from "./purge-subject.ts";
|
|
5
|
-
export type { ReindexEntityFailure, ReindexEntityOptions, ReindexEntityResult, } from "./reindex-entity.ts";
|
|
6
3
|
export { reindexEntity } from "./reindex-entity.ts";
|
|
7
|
-
export type { SearchAdapter, SearchAdapterConfig,
|
|
4
|
+
export type { SearchAdapter, SearchAdapterConfig, } from "./types.ts";
|
package/dist/search/index.js
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
// `@cosmicdrift/kumiko-framework/search/meilisearch`. This keeps the main barrel from loading a
|
|
3
3
|
// Meilisearch client when consumers only use SearchAdapter types, so apps that do not use
|
|
4
4
|
// Meilisearch do not pull in the client code.
|
|
5
|
-
export { collectSearchableFieldNames, configureTenantSearchIndex, } from "./configure-tenant-index.js";
|
|
6
|
-
export { deriveSearchAdapterConfig } from "./derive-search-adapter-config.js";
|
|
7
5
|
export { createInMemorySearchAdapter } from "./in-memory-adapter.js";
|
|
8
6
|
export { purgeSearchDocumentsForSubject } from "./purge-subject.js";
|
|
9
7
|
export { reindexEntity } from "./reindex-entity.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { EntityId, TenantId } from "../engine/types/identifiers.ts";
|
|
2
|
+
export type MeilisearchAdapterOptions = {
|
|
3
|
+
url: string;
|
|
4
|
+
apiKey: string;
|
|
5
|
+
indexPrefix?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function meilisearchTenantIndex(prefix: string, tenantId: TenantId): string;
|
|
8
|
+
export declare function meilisearchDocId(entityType: string, entityId: EntityId): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Exported for unit tests (index-name / primary-key shape) without a live Meili.
|
|
2
|
+
export function meilisearchTenantIndex(prefix, tenantId) {
|
|
3
|
+
return `${prefix}t${tenantId}`;
|
|
4
|
+
}
|
|
5
|
+
// Meilisearch primary-key-ids: alphanumerics, `-`, `_`. UUIDs contain `-` —
|
|
6
|
+
// legal. Replace anything else just in case callers pass unexpected shapes.
|
|
7
|
+
export function meilisearchDocId(entityType, entityId) {
|
|
8
|
+
return `${entityType}_${String(entityId).replace(/[^0-9A-Za-z_-]/g, "_")}`;
|
|
9
|
+
}
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type MeilisearchAdapterOptions } from "./meilisearch-adapter-internals.ts";
|
|
2
2
|
import type { SearchAdapter } from "./types.ts";
|
|
3
|
-
export type MeilisearchAdapterOptions = {
|
|
4
|
-
url: string;
|
|
5
|
-
apiKey: string;
|
|
6
|
-
indexPrefix?: string;
|
|
7
|
-
};
|
|
8
|
-
export declare function meilisearchTenantIndex(prefix: string, tenantId: TenantId): string;
|
|
9
|
-
export declare function meilisearchDocId(entityType: string, entityId: EntityId): string;
|
|
10
3
|
export declare function createMeilisearchAdapter(options: MeilisearchAdapterOptions): SearchAdapter;
|