@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,7 +1,9 @@
|
|
|
1
1
|
import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
2
2
|
import { readNonEmptyStringArray, } from "../api/sse-broker.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { configuredPiiSubjectKms, decryptPiiFieldValues, isPiiCiphertext, PII_ERASED_SENTINEL, } from "../crypto/index.js";
|
|
4
|
+
import { collectSearchableSubjectFields } from "../crypto/subject-resolver.js";
|
|
5
|
+
import { rehydrateCompoundTypes } from "../db/compound-types.js";
|
|
6
|
+
import { createTenantDb, entityTableFromRegistry } from "../db/index.js";
|
|
5
7
|
import { tenantChannel } from "../engine/constants.js";
|
|
6
8
|
import { InternalError } from "../errors/index.js";
|
|
7
9
|
import { createFallbackLogger } from "../logging/utils.js";
|
|
@@ -422,7 +424,7 @@ export function createSseBroadcastEventConsumer(sseBroker) {
|
|
|
422
424
|
// r.job's `trigger.on` historically only fired via the synchronous
|
|
423
425
|
// write-handler dispatch path (dispatch-write.ts's afterCommitHooks calling
|
|
424
426
|
// jobRunner.handleEvent). Events appended any other way — an
|
|
425
|
-
// r.multiStreamProjection's ctx.
|
|
427
|
+
// r.multiStreamProjection's ctx.events.unsafeAppend, or a raw
|
|
426
428
|
// event-store-executor write (e.g. `files`' fileRef.created) — never
|
|
427
429
|
// reached it, so a job could never trigger on an r.defineEvent-registered
|
|
428
430
|
// event.
|
|
@@ -431,7 +433,7 @@ export function createSseBroadcastEventConsumer(sseBroker) {
|
|
|
431
433
|
// committed event off the shared cursor and re-check job triggers. It is
|
|
432
434
|
// scoped EXACTLY to the gap — the write/query-handler-QN skip below is
|
|
433
435
|
// defense-in-depth: no stored event's `type` is a handler QN today (entity
|
|
434
|
-
// events are "entity.verb"; ctx.
|
|
436
|
+
// events are "entity.verb"; ctx.events.append enforces defineEvent-only
|
|
435
437
|
// ownership), but if that ever changes, this consumer must not re-fire a
|
|
436
438
|
// trigger the synchronous dispatch-write.ts path already handled.
|
|
437
439
|
//
|
|
@@ -552,9 +554,58 @@ function readPatRevokedScope(payload) {
|
|
|
552
554
|
const tokenIds = readNonEmptyStringArray(payload["tokenIds"]);
|
|
553
555
|
return tokenIds ? { kind: "pat-tokens", tokenIds } : { kind: "user" };
|
|
554
556
|
}
|
|
555
|
-
|
|
557
|
+
const ACCESS_INVALIDATION_BACKOFF_INITIAL_MS = 250;
|
|
558
|
+
const ACCESS_INVALIDATION_BACKOFF_MAX_MS = 10_000;
|
|
559
|
+
// Only the publish can fail because Redis is unreachable. The consumer must keep retrying those
|
|
560
|
+
// until Redis is back (dead-lettering would silently stop every later revocation reaching open
|
|
561
|
+
// streams), while any other failure keeps the dispatcher's attempt limit so one poison event
|
|
562
|
+
// cannot hold back every later revocation for good.
|
|
563
|
+
class AccessInvalidationTransportError extends Error {
|
|
564
|
+
constructor(cause) {
|
|
565
|
+
super(cause instanceof Error ? cause.message : String(cause), { cause });
|
|
566
|
+
this.name = "AccessInvalidationTransportError";
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
function isAccessInvalidationTransportError(error) {
|
|
570
|
+
return error instanceof AccessInvalidationTransportError;
|
|
571
|
+
}
|
|
572
|
+
// The gate rethrows without touching Redis until the backoff elapsed.
|
|
573
|
+
function withTransportBackoff(handle, now) {
|
|
574
|
+
let delayMs = ACCESS_INVALIDATION_BACKOFF_INITIAL_MS;
|
|
575
|
+
let retryNotBefore = 0;
|
|
576
|
+
let transportError = null;
|
|
577
|
+
return async (event) => {
|
|
578
|
+
if (transportError !== null && now() < retryNotBefore)
|
|
579
|
+
throw transportError;
|
|
580
|
+
try {
|
|
581
|
+
await handle(event);
|
|
582
|
+
delayMs = ACCESS_INVALIDATION_BACKOFF_INITIAL_MS;
|
|
583
|
+
transportError = null;
|
|
584
|
+
}
|
|
585
|
+
catch (err) {
|
|
586
|
+
if (isAccessInvalidationTransportError(err)) {
|
|
587
|
+
transportError = err;
|
|
588
|
+
retryNotBefore = now() + delayMs;
|
|
589
|
+
delayMs = Math.min(delayMs * 2, ACCESS_INVALIDATION_BACKOFF_MAX_MS);
|
|
590
|
+
}
|
|
591
|
+
throw err;
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
export function createAccessInvalidationEventConsumer(sseBroker, opts = {}) {
|
|
596
|
+
const now = opts.now ?? Date.now;
|
|
597
|
+
const publish = async (userId, scope) => {
|
|
598
|
+
try {
|
|
599
|
+
await sseBroker.publishAccessInvalidation(userId, scope);
|
|
600
|
+
}
|
|
601
|
+
catch (cause) {
|
|
602
|
+
throw new AccessInvalidationTransportError(cause);
|
|
603
|
+
}
|
|
604
|
+
};
|
|
556
605
|
return {
|
|
557
606
|
name: ACCESS_INVALIDATION_CONSUMER_NAME,
|
|
607
|
+
// Count-based dead-lettering would end after a few seconds of Redis downtime.
|
|
608
|
+
errorPolicy: { isTransientError: isAccessInvalidationTransportError },
|
|
558
609
|
// Shared delivery, same reasoning as SSE broadcast: one
|
|
559
610
|
// cursor reads every event once and calls sseBroker.publishAccessInvalidation
|
|
560
611
|
// below, which a Redis-backed broker republishes to every replica's
|
|
@@ -565,7 +616,7 @@ export function createAccessInvalidationEventConsumer(sseBroker) {
|
|
|
565
616
|
// existed has nothing to invalidate — replaying it would be a no-op at
|
|
566
617
|
// best and a spurious stream-close at worst.
|
|
567
618
|
startFrom: "now",
|
|
568
|
-
handler: async (event) => {
|
|
619
|
+
handler: withTransportBackoff(async (event) => {
|
|
569
620
|
if (event.type === SESSION_REVOKED_EVENT_TYPE) {
|
|
570
621
|
const userId = event.payload["userId"];
|
|
571
622
|
// skip: malformed session-revoked payload — fail open on this one
|
|
@@ -574,7 +625,7 @@ export function createAccessInvalidationEventConsumer(sseBroker) {
|
|
|
574
625
|
// every user behind one bad row).
|
|
575
626
|
if (typeof userId !== "string" || userId.length === 0)
|
|
576
627
|
return;
|
|
577
|
-
await
|
|
628
|
+
await publish(userId, readSessionRevokedScope(event.payload));
|
|
578
629
|
}
|
|
579
630
|
if (event.type === PAT_REVOKED_EVENT_TYPE) {
|
|
580
631
|
const userId = event.payload["userId"];
|
|
@@ -582,7 +633,7 @@ export function createAccessInvalidationEventConsumer(sseBroker) {
|
|
|
582
633
|
// session-revoked above.
|
|
583
634
|
if (typeof userId !== "string" || userId.length === 0)
|
|
584
635
|
return;
|
|
585
|
-
await
|
|
636
|
+
await publish(userId, readPatRevokedScope(event.payload));
|
|
586
637
|
}
|
|
587
638
|
if (event.type === TENANT_MEMBERSHIP_UPDATED_EVENT_TYPE ||
|
|
588
639
|
event.type === TENANT_MEMBERSHIP_DELETED_EVENT_TYPE) {
|
|
@@ -591,8 +642,8 @@ export function createAccessInvalidationEventConsumer(sseBroker) {
|
|
|
591
642
|
// reasoning as above.
|
|
592
643
|
if (userId === undefined)
|
|
593
644
|
return;
|
|
594
|
-
await
|
|
645
|
+
await publish(userId);
|
|
595
646
|
}
|
|
596
|
-
},
|
|
647
|
+
}, now),
|
|
597
648
|
};
|
|
598
649
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import type { ActiveMembershipResult, EscapeHatchDeclaration, EscapeHatchReporter, MemberReader, WriteResult } from "@cosmicdrift/kumiko-types/handlers";
|
|
2
|
+
import type { LifecycleHookFn } from "@cosmicdrift/kumiko-types/hooks";
|
|
1
3
|
import type { TenantId } from "../engine/types/identifiers.ts";
|
|
2
|
-
import type {
|
|
4
|
+
import type { HandlerContext, SessionUser } from "../engine/types/index.ts";
|
|
3
5
|
import { AccessDeniedError } from "../errors/index.ts";
|
|
4
6
|
export type QueryAsFn = (user: SessionUser, qn: string, payload: unknown) => Promise<unknown>;
|
|
5
7
|
export type WriteAsFn = (user: SessionUser, qn: string, payload: unknown) => Promise<WriteResult>;
|
|
6
8
|
export type ResolveActiveMembershipFn = (userId: string, tenantId: TenantId) => Promise<ActiveMembershipResult>;
|
|
7
|
-
export type ProjectionReader = HandlerContext["queryProjection"];
|
|
9
|
+
export type ProjectionReader = HandlerContext["dispatch"]["queryProjection"];
|
|
8
10
|
export type IdentitySwitch = {
|
|
9
11
|
readonly queryAs: QueryAsFn;
|
|
10
12
|
readonly writeAs: WriteAsFn;
|
|
@@ -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;
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
import { maskWriteOnlyFields } from "../engine/field-access.js";
|
|
2
2
|
import { isLifecycleResult } from "./dispatcher-utils.js";
|
|
3
|
+
// The echoed event carries plaintext entity data; only hooks and projections may read it.
|
|
3
4
|
function maskLifecycleOrRow(entity, data) {
|
|
4
5
|
if (typeof data !== "object" || data === null || Array.isArray(data))
|
|
5
6
|
return data;
|
|
6
|
-
if (!isLifecycleResult(data))
|
|
7
|
-
return maskWriteOnlyFields(entity, data); // @cast-boundary engine-payload
|
|
8
|
-
|
|
7
|
+
if (!isLifecycleResult(data)) {
|
|
8
|
+
return entity ? maskWriteOnlyFields(entity, data) : data; // @cast-boundary engine-payload
|
|
9
|
+
}
|
|
10
|
+
const { event: _event, ...lifecycle } = data;
|
|
11
|
+
if (!entity)
|
|
12
|
+
return lifecycle;
|
|
13
|
+
if (lifecycle.kind === "save") {
|
|
9
14
|
return {
|
|
10
|
-
...
|
|
11
|
-
data: maskWriteOnlyFields(entity,
|
|
12
|
-
changes: maskWriteOnlyFields(entity,
|
|
13
|
-
previous: maskWriteOnlyFields(entity,
|
|
15
|
+
...lifecycle,
|
|
16
|
+
data: maskWriteOnlyFields(entity, lifecycle.data),
|
|
17
|
+
changes: maskWriteOnlyFields(entity, lifecycle.changes),
|
|
18
|
+
previous: maskWriteOnlyFields(entity, lifecycle.previous),
|
|
14
19
|
};
|
|
15
20
|
}
|
|
16
|
-
return { ...
|
|
21
|
+
return { ...lifecycle, data: maskWriteOnlyFields(entity, lifecycle.data) };
|
|
17
22
|
}
|
|
18
23
|
// Copy-on-mask: the original results still feed postSaveBatch hooks, which
|
|
19
24
|
// need the plaintext. Only what leaves the dispatcher is masked.
|
|
@@ -22,8 +27,6 @@ export function maskWriteResultForClient(registry, handlerType, result) {
|
|
|
22
27
|
return result;
|
|
23
28
|
const entityName = registry.getHandlerEntity(handlerType);
|
|
24
29
|
const entity = entityName ? registry.getEntity(entityName) : undefined;
|
|
25
|
-
if (!entity)
|
|
26
|
-
return result;
|
|
27
30
|
const data = maskLifecycleOrRow(entity, result.data);
|
|
28
31
|
return data === result.data ? result : { ...result, data };
|
|
29
32
|
}
|
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("");
|