@cosmicdrift/kumiko-framework 0.386.0 → 0.388.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 +6 -1
- package/LICENSE +21 -57
- package/README.md +2 -2
- package/agents/examples/anonymous-access.md +1 -1
- package/agents/examples/apex-landing.md +204 -0
- package/agents/examples/api-worker-split.md +64 -0
- package/agents/examples/app-config.md +14 -0
- package/agents/examples/auth-mfa.md +115 -0
- package/agents/examples/env-composition.md +28 -1
- package/agents/examples/legal-pages.md +1 -1
- package/agents/examples/prod-boot-options.md +16 -0
- package/agents/examples/rate-limiting.md +48 -0
- package/agents/examples/record-detail-layout.md +692 -0
- package/agents/examples/seed-migration.md +212 -0
- package/agents/examples/wizard-form.md +941 -0
- package/agents/examples/writeform-section.md +548 -0
- package/agents/features.md +19 -2
- package/agents/widgets.md +40 -39
- package/dist/api/api-constants.js +2 -2
- package/dist/api/auth-middleware.js +7 -7
- package/dist/api/auth-rate-limiters.js +7 -3
- package/dist/api/auth-routes-mfa.js +1 -1
- package/dist/api/auth-routes-session.js +1 -1
- package/dist/api/auth-routes-shared.js +7 -3
- package/dist/api/auth-routes-signup.js +1 -1
- package/dist/api/client-error-route.js +8 -2
- package/dist/api/client-ip.js +3 -1
- package/dist/api/extra-route.js +1 -1
- package/dist/api/index.d.ts +3 -1
- package/dist/api/index.js +3 -1
- package/dist/api/pii-leak-guard.js +4 -2
- package/dist/api/readiness.js +5 -5
- package/dist/api/redis-sse-broker.js +8 -6
- package/dist/api/request-context.d.ts +1 -1
- package/dist/api/request-context.js +1 -1
- package/dist/api/routes.js +2 -2
- package/dist/api/server-boot-checks.d.ts +10 -0
- package/dist/api/server-boot-checks.js +157 -0
- package/dist/api/server-event-dispatcher.d.ts +26 -0
- package/dist/api/server-event-dispatcher.js +208 -0
- package/dist/api/server-extra-routes.d.ts +11 -0
- package/dist/api/server-extra-routes.js +203 -0
- package/dist/api/server-middleware.d.ts +20 -0
- package/dist/api/server-middleware.js +211 -0
- package/dist/api/server-routes.d.ts +19 -0
- package/dist/api/server-routes.js +293 -0
- package/dist/api/server-websocket-routes.d.ts +4 -0
- package/dist/api/server-websocket-routes.js +108 -0
- package/dist/api/server-wiring.d.ts +32 -0
- package/dist/api/server-wiring.js +236 -0
- package/dist/api/server.d.ts +10 -15
- package/dist/api/server.js +48 -1250
- package/dist/api/session-cookies.js +4 -4
- package/dist/api/sse-broker.js +1 -1
- package/dist/api/sse-route.d.ts +13 -13
- package/dist/api/sse-route.js +31 -27
- package/dist/auth/index.js +4 -4
- package/dist/auth/roles.d.ts +4 -4
- package/dist/auth/roles.js +24 -24
- package/dist/compliance/duration-spec.js +18 -20
- package/dist/compliance/index.js +2 -3
- package/dist/compliance/override-schema.d.ts +4 -4
- package/dist/compliance/override-schema.js +19 -22
- package/dist/compliance/profiles.d.ts +26 -29
- package/dist/compliance/profiles.js +62 -69
- package/dist/compliance/sub-processors.d.ts +28 -30
- package/dist/compliance/sub-processors.js +17 -21
- package/dist/consumer-cli.js +4 -4
- package/dist/crypto/blind-index.js +18 -17
- package/dist/crypto/ciphertext-pattern.js +1 -1
- package/dist/crypto/event-pii.js +3 -3
- package/dist/crypto/kek-source.d.ts +1 -1
- package/dist/crypto/kek-source.js +3 -2
- package/dist/crypto/kms-adapter.d.ts +1 -1
- package/dist/crypto/kms-adapter.js +4 -6
- package/dist/crypto/kms-wiring.d.ts +1 -2
- package/dist/crypto/kms-wiring.js +2 -2
- package/dist/crypto/owner-transition-rekey.d.ts +5 -1
- package/dist/crypto/owner-transition-rekey.js +1 -1
- package/dist/crypto/pg-kms-adapter.js +2 -6
- package/dist/crypto/pii-field-encryption.d.ts +5 -1
- package/dist/crypto/pii-field-encryption.js +7 -5
- package/dist/crypto/subject-resolver.d.ts +1 -1
- package/dist/crypto/subject-resolver.js +2 -2
- package/dist/db/aggregate-sql.d.ts +21 -0
- package/dist/db/aggregate-sql.js +155 -0
- package/dist/db/apply-entity-event.d.ts +6 -6
- package/dist/db/apply-entity-event.js +55 -55
- package/dist/db/blind-index-cleanup.js +7 -7
- package/dist/db/closed-connection.d.ts +9 -0
- package/dist/db/closed-connection.js +95 -0
- package/dist/db/collect-table-metas.js +10 -11
- package/dist/db/compound-types.d.ts +1 -1
- package/dist/db/compound-types.js +12 -12
- package/dist/db/cursor.js +3 -4
- package/dist/db/dialect.d.ts +2 -2
- package/dist/db/dialect.js +3 -3
- package/dist/db/distinct-on.d.ts +1 -1
- package/dist/db/driver-row-coercion.d.ts +2 -0
- package/dist/db/driver-row-coercion.js +186 -0
- package/dist/db/driver-value-preparation.d.ts +16 -0
- package/dist/db/driver-value-preparation.js +99 -0
- package/dist/db/eagerload.d.ts +3 -3
- package/dist/db/eagerload.js +21 -12
- package/dist/db/entity-field-encryption.d.ts +1 -0
- package/dist/db/entity-field-encryption.js +1 -1
- package/dist/db/entity-table-meta.d.ts +2 -2
- package/dist/db/entity-table-meta.js +105 -112
- package/dist/db/event-store-executor-context.d.ts +3 -2
- package/dist/db/event-store-executor-context.js +13 -13
- package/dist/db/event-store-executor-read-aggregate.d.ts +8 -0
- package/dist/db/event-store-executor-read-aggregate.js +112 -0
- package/dist/db/event-store-executor-read-filter.d.ts +31 -0
- package/dist/db/event-store-executor-read-filter.js +203 -0
- package/dist/db/event-store-executor-read-paging.d.ts +14 -0
- package/dist/db/event-store-executor-read-paging.js +99 -0
- package/dist/db/event-store-executor-read-rows.d.ts +6 -0
- package/dist/db/event-store-executor-read-rows.js +32 -0
- package/dist/db/event-store-executor-read-search.d.ts +28 -0
- package/dist/db/event-store-executor-read-search.js +221 -0
- package/dist/db/event-store-executor-read-sort.d.ts +41 -0
- package/dist/db/event-store-executor-read-sort.js +130 -0
- package/dist/db/event-store-executor-read-where.d.ts +24 -0
- package/dist/db/event-store-executor-read-where.js +81 -0
- package/dist/db/event-store-executor-read.d.ts +2 -9
- package/dist/db/event-store-executor-read.js +50 -704
- package/dist/db/event-store-executor-write-steps.d.ts +20 -0
- package/dist/db/event-store-executor-write-steps.js +100 -0
- package/dist/db/event-store-executor-write.js +401 -510
- package/dist/db/index.d.ts +6 -2
- package/dist/db/index.js +5 -1
- package/dist/db/list-aggregate-labels.d.ts +14 -0
- package/dist/db/list-aggregate-labels.js +26 -0
- package/dist/db/located-timestamp.d.ts +11 -11
- package/dist/db/located-timestamp.js +29 -30
- package/dist/db/migrate-generator.d.ts +1 -1
- package/dist/db/migrate-generator.js +97 -105
- package/dist/db/migrate-runner.js +29 -26
- package/dist/db/money.d.ts +6 -6
- package/dist/db/money.js +29 -27
- package/dist/db/queries/backfill-pii.js +5 -5
- package/dist/db/queries/ddl.js +1 -1
- package/dist/db/queries/es-ops.d.ts +1 -1
- package/dist/db/queries/es-ops.js +1 -1
- package/dist/db/queries/event-consumer.js +3 -3
- package/dist/db/queries/event-store.js +4 -2
- package/dist/db/queries/projection-rebuild.js +3 -3
- package/dist/db/queries/raw-sql.d.ts +2 -2
- package/dist/db/queries/raw-sql.js +2 -2
- package/dist/db/queries/shadow-swap.js +19 -19
- package/dist/db/query.d.ts +3 -16
- package/dist/db/query.js +8 -761
- package/dist/db/rebuild-marker.js +20 -21
- package/dist/db/reference-data.js +6 -1
- package/dist/db/replay-migration-sql.js +2 -2
- package/dist/db/schema-inspection.js +4 -5
- package/dist/db/table-builder.d.ts +1 -2
- package/dist/db/table-builder.js +137 -190
- package/dist/db/table-info.d.ts +10 -0
- package/dist/db/table-info.js +45 -0
- package/dist/db/temporal-value-guards.d.ts +6 -0
- package/dist/db/temporal-value-guards.js +15 -0
- package/dist/db/tenant-db-runner.d.ts +1 -0
- package/dist/db/tenant-db-runner.js +3 -0
- package/dist/db/tenant-db.d.ts +2 -2
- package/dist/db/tenant-db.js +48 -11
- package/dist/db/where-clause.d.ts +6 -0
- package/dist/db/where-clause.js +236 -0
- package/dist/derivatives/delete-stored-file.js +6 -2
- package/dist/derivatives/derivatives-context.js +1 -1
- package/dist/engine/boot-validator/access-roles.js +4 -3
- package/dist/engine/boot-validator/api-ext.js +14 -14
- package/dist/engine/boot-validator/boot-check.js +1 -1
- package/dist/engine/boot-validator/config-deps.js +7 -6
- package/dist/engine/boot-validator/detail-screens.js +4 -4
- package/dist/engine/boot-validator/entity-handler.d.ts +1 -0
- package/dist/engine/boot-validator/entity-handler.js +77 -61
- package/dist/engine/boot-validator/form-derivations.js +35 -1
- package/dist/engine/boot-validator/gdpr-storage.js +4 -4
- package/dist/engine/boot-validator/i18n-keys.js +6 -4
- package/dist/engine/boot-validator/index.d.ts +2 -2
- package/dist/engine/boot-validator/index.js +22 -20
- package/dist/engine/boot-validator/nav.js +5 -5
- package/dist/engine/boot-validator/ownership.js +12 -9
- package/dist/engine/boot-validator/parent-ref.js +1 -1
- package/dist/engine/boot-validator/pii-retention.js +258 -187
- package/dist/engine/boot-validator/projection-list-screens.js +7 -7
- package/dist/engine/boot-validator/query-refs.js +1 -1
- package/dist/engine/boot-validator/screens-actions.d.ts +1 -0
- package/dist/engine/boot-validator/screens-actions.js +23 -17
- package/dist/engine/boot-validator/screens-dashboard.js +2 -5
- package/dist/engine/boot-validator/screens-forms.js +12 -17
- package/dist/engine/boot-validator/screens-kind-config-edit.d.ts +3 -0
- package/dist/engine/boot-validator/screens-kind-config-edit.js +88 -0
- package/dist/engine/boot-validator/screens-kind-entity-edit.d.ts +3 -0
- package/dist/engine/boot-validator/screens-kind-entity-edit.js +55 -0
- package/dist/engine/boot-validator/screens-kind-entity-list.d.ts +3 -0
- package/dist/engine/boot-validator/screens-kind-entity-list.js +228 -0
- package/dist/engine/boot-validator/screens-kind-projection-detail.d.ts +3 -0
- package/dist/engine/boot-validator/screens-kind-projection-detail.js +235 -0
- package/dist/engine/boot-validator/screens-kind-projection-list.d.ts +3 -0
- package/dist/engine/boot-validator/screens-kind-projection-list.js +52 -0
- package/dist/engine/boot-validator/screens-kind-secret-mint.d.ts +3 -0
- package/dist/engine/boot-validator/screens-kind-secret-mint.js +28 -0
- package/dist/engine/boot-validator/screens-kind-shared.d.ts +37 -0
- package/dist/engine/boot-validator/screens-kind-shared.js +142 -0
- package/dist/engine/boot-validator/screens-lists.d.ts +2 -1
- package/dist/engine/boot-validator/screens-lists.js +26 -24
- package/dist/engine/boot-validator/screens.d.ts +0 -2
- package/dist/engine/boot-validator/screens.js +102 -869
- package/dist/engine/boot-validator/security-baseline.js +3 -2
- package/dist/engine/boot-validator/transfer-graph.js +2 -2
- package/dist/engine/boot-validator/workspaces.js +3 -3
- package/dist/engine/bridge-stub.js +3 -4
- package/dist/engine/build-app-schema.js +130 -170
- package/dist/engine/build-config-feature-schema.js +50 -50
- package/dist/engine/build-target.js +20 -23
- package/dist/engine/codemod/pipeline-codemod.js +20 -13
- package/dist/engine/config-helpers.js +4 -4
- package/dist/engine/constants.js +2 -2
- package/dist/engine/create-app.js +2 -2
- package/dist/engine/define-feature.js +21 -13
- package/dist/engine/define-handler.js +13 -11
- package/dist/engine/define-step.js +1 -1
- package/dist/engine/define-workflow.d.ts +5 -5
- package/dist/engine/define-workflow.js +6 -6
- package/dist/engine/entity-handlers.d.ts +13 -0
- package/dist/engine/entity-handlers.js +22 -34
- package/dist/engine/entity-list-runtime-options.d.ts +8 -0
- package/dist/engine/entity-list-runtime-options.js +18 -0
- package/dist/engine/event-def.js +2 -2
- package/dist/engine/extension-names.d.ts +16 -17
- package/dist/engine/extension-names.js +37 -38
- package/dist/engine/extensions/escape-hatch-usage.js +1 -1
- package/dist/engine/extensions/tenant-data.js +2 -2
- package/dist/engine/extensions/user-data.d.ts +23 -24
- package/dist/engine/factories.d.ts +14 -13
- package/dist/engine/factories.js +38 -37
- package/dist/engine/feature-ast/entity-field-types.js +1 -1
- package/dist/engine/feature-ast/extractors/handlers.js +2 -1
- package/dist/engine/feature-ast/extractors/hooks.js +1 -1
- package/dist/engine/feature-ast/extractors/round2.js +25 -6
- package/dist/engine/feature-ast/extractors/shared.d.ts +2 -3
- package/dist/engine/feature-ast/extractors/shared.js +2 -3
- package/dist/engine/feature-ast/parse.js +13 -13
- package/dist/engine/feature-ast/patch.js +4 -182
- package/dist/engine/feature-ast/pattern-change-schema.d.ts +3 -0
- package/dist/engine/feature-ast/pattern-change-schema.js +2 -1
- package/dist/engine/feature-ast/pattern-id-matchers.d.ts +7 -0
- package/dist/engine/feature-ast/pattern-id-matchers.js +210 -0
- package/dist/engine/feature-ast/patterns.d.ts +11 -2
- package/dist/engine/feature-ast/patterns.js +43 -51
- package/dist/engine/feature-ast/render.js +50 -89
- package/dist/engine/feature-config-events-jobs.js +15 -12
- package/dist/engine/feature-entity-handlers.js +12 -5
- package/dist/engine/feature-manifest.d.ts +9 -9
- package/dist/engine/feature-manifest.js +6 -7
- package/dist/engine/feature-ui-extensions.d.ts +3 -3
- package/dist/engine/feature-ui-extensions.js +30 -22
- package/dist/engine/field-access.js +5 -6
- package/dist/engine/form-derivations.js +18 -7
- package/dist/engine/handler-field-references.js +1 -1
- package/dist/engine/index.d.ts +1 -0
- package/dist/engine/index.js +4 -4
- package/dist/engine/object-form.d.ts +1 -0
- package/dist/engine/object-form.js +14 -4
- package/dist/engine/ownership.js +3 -3
- package/dist/engine/parse-ref-target.js +5 -7
- package/dist/engine/pattern-library/index.js +2 -2
- package/dist/engine/pattern-library/library.js +2 -2
- package/dist/engine/pattern-library/types.js +3 -3
- package/dist/engine/pipeline.js +2 -2
- package/dist/engine/project-app-schema-for-roles.d.ts +2 -0
- package/dist/engine/project-app-schema-for-roles.js +7 -5
- package/dist/engine/projection-helpers.js +9 -9
- package/dist/engine/qualified-name.js +2 -2
- package/dist/engine/registry-facade.js +1 -1
- package/dist/engine/registry-ingest.js +13 -13
- package/dist/engine/registry-state.js +17 -19
- package/dist/engine/registry-validate.js +12 -12
- package/dist/engine/run-in.js +2 -2
- package/dist/engine/run-pipeline.js +7 -0
- package/dist/engine/schema-builder.js +251 -233
- package/dist/engine/screen-filter-ops.js +17 -20
- package/dist/engine/screen-helpers.js +4 -3
- package/dist/engine/screen-kind.d.ts +7 -0
- package/dist/engine/screen-kind.js +1 -0
- package/dist/engine/state-machine.d.ts +12 -12
- package/dist/engine/state-machine.js +7 -7
- package/dist/engine/steps/_resolver-utils.js +4 -3
- package/dist/engine/steps/for-each.js +4 -4
- package/dist/engine/steps/unsafe-projection-delete.js +1 -1
- package/dist/engine/steps/unsafe-projection-upsert.js +4 -4
- package/dist/engine/steps/wait-for-event.js +4 -4
- package/dist/engine/steps/workflow-system-events.js +3 -3
- package/dist/engine/strip-disabled-features-from-app-schema.js +51 -14
- package/dist/engine/tier-resolver-extension.d.ts +29 -27
- package/dist/engine/tier-resolver-extension.js +26 -26
- package/dist/engine/transfer-adjacency.js +2 -2
- package/dist/engine/validate-projection-allowlist.js +9 -28
- package/dist/engine/walk-step-instances.d.ts +2 -0
- package/dist/engine/walk-step-instances.js +38 -0
- package/dist/engine/where-rule-lint.js +1 -1
- package/dist/engine/write-handler-qn-extract.js +1 -1
- package/dist/entrypoint/index.d.ts +4 -1
- package/dist/entrypoint/index.js +10 -4
- package/dist/env/index.d.ts +7 -6
- package/dist/env/index.js +10 -9
- package/dist/errors/docs-url.d.ts +1 -1
- package/dist/errors/docs-url.js +22 -2
- package/dist/errors/transition-details.js +7 -7
- package/dist/errors/write-error-info.d.ts +6 -6
- package/dist/errors/write-error-info.js +6 -6
- package/dist/es-ops/context.d.ts +9 -9
- package/dist/es-ops/context.js +29 -29
- package/dist/es-ops/index.js +7 -9
- package/dist/es-ops/operations-schema.js +4 -10
- package/dist/es-ops/runner.d.ts +11 -11
- package/dist/es-ops/runner.js +49 -53
- package/dist/es-ops/types.d.ts +55 -55
- package/dist/es-ops/types.js +11 -11
- package/dist/event-store/admin-api.js +7 -8
- package/dist/event-store/errors.js +1 -1
- package/dist/event-store/event-store.js +12 -6
- package/dist/event-store/rebuild-dead-letter.js +1 -1
- package/dist/files/bind-pending-file-refs.js +3 -3
- package/dist/files/create-file-ref-from-bytes.js +4 -1
- package/dist/files/feature.js +9 -10
- package/dist/files/file-handle.js +7 -9
- package/dist/files/file-ref-entity.js +15 -15
- package/dist/files/file-ref-table.js +7 -8
- package/dist/files/file-routes.d.ts +7 -0
- package/dist/files/file-routes.js +22 -13
- package/dist/files/in-memory-provider.js +8 -9
- package/dist/files/local-provider.js +18 -25
- package/dist/files/provider-resolver.d.ts +7 -7
- package/dist/files/resolve-content-type.js +43 -0
- package/dist/files/storage-tracking.js +2 -2
- package/dist/files/upload-ledger.js +7 -0
- package/dist/files/zip-stream.d.ts +12 -19
- package/dist/files/zip-stream.js +44 -63
- package/dist/i18n/required-surface-keys.d.ts +1 -1
- package/dist/i18n/required-surface-keys.js +188 -212
- package/dist/internal/stack-support.d.ts +2 -1
- package/dist/internal/stack-support.js +1 -1
- package/dist/jobs/job-runner-context.d.ts +32 -0
- package/dist/jobs/job-runner-context.js +305 -0
- package/dist/jobs/job-runner-execution.d.ts +7 -0
- package/dist/jobs/job-runner-execution.js +160 -0
- package/dist/jobs/job-runner-gates.d.ts +19 -0
- package/dist/jobs/job-runner-gates.js +198 -0
- package/dist/jobs/job-runner-helpers.d.ts +17 -3
- package/dist/jobs/job-runner-helpers.js +69 -4
- package/dist/jobs/job-runner-schedulers.d.ts +1 -1
- package/dist/jobs/job-runner-schedulers.js +3 -4
- package/dist/jobs/job-runner-scope.d.ts +44 -0
- package/dist/jobs/job-runner-scope.js +102 -0
- package/dist/jobs/job-runner-types.d.ts +12 -0
- package/dist/jobs/job-runner.d.ts +0 -1
- package/dist/jobs/job-runner.js +57 -669
- package/dist/lifecycle/lifecycle.js +3 -5
- package/dist/lifecycle/signal-handlers.js +5 -4
- package/dist/logging/utils.d.ts +2 -1
- package/dist/logging/utils.js +38 -10
- package/dist/migrations/index.js +1 -1
- package/dist/migrations/kumiko-drift.js +14 -13
- package/dist/migrations/pending-rebuilds.d.ts +21 -20
- package/dist/migrations/pending-rebuilds.js +27 -27
- package/dist/migrations/projection-table-index.d.ts +3 -3
- package/dist/migrations/projection-table-index.js +8 -8
- package/dist/observability/escape-hatch-report.d.ts +3 -0
- package/dist/observability/escape-hatch-report.js +12 -1
- package/dist/observability/metric-validator.js +1 -1
- package/dist/observability/metrics-handle.js +3 -3
- package/dist/pipeline/append-event-core.js +11 -2
- package/dist/pipeline/cascade-handler.d.ts +1 -1
- package/dist/pipeline/cascade-handler.js +165 -138
- package/dist/pipeline/dispatch-batch.js +2 -2
- package/dist/pipeline/dispatch-query.js +20 -13
- package/dist/pipeline/dispatch-shared.d.ts +14 -3
- package/dist/pipeline/dispatch-shared.js +67 -721
- package/dist/pipeline/dispatch-stream.js +1 -1
- package/dist/pipeline/dispatch-write.js +297 -190
- package/dist/pipeline/dispatcher-utils.d.ts +1 -1
- package/dist/pipeline/dispatcher-utils.js +1 -1
- package/dist/pipeline/event-consumer-state.js +2 -2
- package/dist/pipeline/event-dispatcher-admin.js +2 -1
- package/dist/pipeline/event-dispatcher-delivery.js +4 -6
- package/dist/pipeline/event-dispatcher.js +17 -28
- package/dist/pipeline/handler-context-auth.d.ts +9 -0
- package/dist/pipeline/handler-context-auth.js +54 -0
- package/dist/pipeline/handler-context-config.d.ts +14 -0
- package/dist/pipeline/handler-context-config.js +113 -0
- package/dist/pipeline/handler-context-db.d.ts +24 -0
- package/dist/pipeline/handler-context-db.js +149 -0
- package/dist/pipeline/handler-context-dispatch.d.ts +21 -0
- package/dist/pipeline/handler-context-dispatch.js +89 -0
- package/dist/pipeline/handler-context-events.d.ts +43 -0
- package/dist/pipeline/handler-context-events.js +237 -0
- package/dist/pipeline/handler-context-notify.d.ts +12 -0
- package/dist/pipeline/handler-context-notify.js +55 -0
- package/dist/pipeline/handler-context-observability.d.ts +7 -0
- package/dist/pipeline/handler-context-observability.js +21 -0
- package/dist/pipeline/handler-context-scope.d.ts +48 -0
- package/dist/pipeline/handler-context-scope.js +88 -0
- package/dist/pipeline/irreversible-operation-gate.js +1 -1
- package/dist/pipeline/lifecycle-pipeline.js +9 -9
- package/dist/pipeline/member-read-only-transaction.js +1 -3
- package/dist/pipeline/msp-rebuild.js +1 -1
- package/dist/pipeline/notify-scope.js +12 -1
- package/dist/pipeline/pre-handler-gates.js +20 -4
- package/dist/pipeline/pre-transaction-reservations.d.ts +1 -0
- package/dist/pipeline/pre-transaction-reservations.js +9 -3
- package/dist/pipeline/projection-rebuild.js +15 -13
- package/dist/pipeline/system-hooks.js +39 -41
- package/dist/pipeline/system-identity-switch.js +1 -3
- package/dist/pipeline/tenant-timezone-cache.js +1 -1
- package/dist/random/generate.d.ts +29 -29
- package/dist/random/generate.js +30 -30
- package/dist/random/words.js +20 -20
- package/dist/rate-limit/middleware.js +9 -5
- package/dist/redis/client.js +2 -2
- package/dist/redis/pubsub-signal.js +14 -17
- package/dist/schema-cli/apply-command.d.ts +2 -0
- package/dist/schema-cli/apply-command.js +97 -0
- package/dist/schema-cli/baseline-command.d.ts +2 -0
- package/dist/schema-cli/baseline-command.js +33 -0
- package/dist/schema-cli/generate-command.d.ts +2 -0
- package/dist/schema-cli/generate-command.js +90 -0
- package/dist/schema-cli/shared.d.ts +39 -0
- package/dist/schema-cli/shared.js +95 -0
- package/dist/schema-cli/status-command.d.ts +2 -0
- package/dist/schema-cli/status-command.js +73 -0
- package/dist/schema-cli/validate-boot-input.d.ts +5 -0
- package/dist/schema-cli/validate-boot-input.js +130 -0
- package/dist/schema-cli/validate-command.d.ts +2 -0
- package/dist/schema-cli/validate-command.js +130 -0
- package/dist/schema-cli.d.ts +2 -18
- package/dist/schema-cli.js +47 -510
- package/dist/search/index.js +4 -4
- package/dist/search/meilisearch-adapter.js +2 -1
- package/dist/search/purge-subject.js +4 -5
- package/dist/search/reindex-entity.js +6 -9
- package/dist/time/boot-tz-warning.d.ts +2 -2
- package/dist/time/boot-tz-warning.js +8 -8
- package/dist/time/iana.js +10 -10
- package/dist/time/index.js +9 -9
- package/dist/time/legacy-date.d.ts +2 -2
- package/dist/time/legacy-date.js +6 -8
- package/dist/time/polyfill.js +1 -1
- package/dist/time/tz-context.d.ts +1 -1
- package/dist/time/tz-context.js +1 -1
- package/dist/ui-types/app-schema.js +7 -7
- package/dist/ui-types/list-row-meta.js +4 -4
- package/dist/upgrade-cli.js +159 -130
- package/dist/utils/compare.js +1 -1
- package/package.json +5 -5
- package/src/changes.json +358 -0
- package/src/scripts/codemod/crypto-shredding-testing-move.ts +2 -2
- package/src/scripts/codemod/feature-layout.ts +10 -2
- package/src/scripts/codemod/migrate-cross-tenant.ts +1 -1
- package/src/scripts/codemod/migrate-open-to-all.ts +1 -1
- package/src/scripts/codemod/object-form.ts +41 -4
- package/src/scripts/codemod/package-merge.ts +58 -8
- package/src/scripts/codemod/pii-personal-migration.ts +192 -153
- package/src/scripts/codemod/testing-injection.ts +122 -42
- package/src/scripts/codemod/testing-move.ts +29 -7
- package/src/scripts/codemod/unprocessable-error-details-reason.ts +2 -2
|
@@ -10,7 +10,7 @@ import type { Lifecycle } from "../lifecycle/index.ts";
|
|
|
10
10
|
import type { ObservabilityProvider } from "../observability/index.ts";
|
|
11
11
|
import type { Dispatcher, DispatcherOptions } from "../pipeline/dispatcher.ts";
|
|
12
12
|
import type { EventDedup, EventDispatcher } from "../pipeline/index.ts";
|
|
13
|
-
import type { SystemHooks } from "../pipeline/lifecycle-pipeline.ts";
|
|
13
|
+
import type { LifecycleHooks, SystemHooks } from "../pipeline/lifecycle-pipeline.ts";
|
|
14
14
|
export type BaseEntrypointOptions = {
|
|
15
15
|
readonly registry: Registry;
|
|
16
16
|
readonly context: AppContext;
|
|
@@ -21,6 +21,7 @@ export type BaseEntrypointOptions = {
|
|
|
21
21
|
readonly systemHooks?: SystemHooks;
|
|
22
22
|
readonly eventDedup?: EventDedup;
|
|
23
23
|
readonly lifecycle?: Lifecycle;
|
|
24
|
+
readonly instanceId?: ServerOptions["instanceId"];
|
|
24
25
|
};
|
|
25
26
|
type JobsBlock = {
|
|
26
27
|
readonly redisUrl: string;
|
|
@@ -49,6 +50,7 @@ export type ApiEntrypointOptions = BaseEntrypointOptions & {
|
|
|
49
50
|
readonly runLocal?: boolean;
|
|
50
51
|
};
|
|
51
52
|
readonly trustedProxyHops?: ServerOptions["trustedProxyHops"];
|
|
53
|
+
readonly errorDocs?: ServerOptions["errorDocs"];
|
|
52
54
|
};
|
|
53
55
|
export type WorkerEntrypointOptions = BaseEntrypointOptions & JobsBlock & {
|
|
54
56
|
readonly eventDispatcher?: ServerOptions["eventDispatcher"];
|
|
@@ -61,6 +63,7 @@ export type ApiEntrypoint = {
|
|
|
61
63
|
readonly lifecycle: Lifecycle;
|
|
62
64
|
readonly observability: ObservabilityProvider;
|
|
63
65
|
readonly dispatcher: Dispatcher;
|
|
66
|
+
readonly lifecycleHooks: LifecycleHooks;
|
|
64
67
|
readonly eventDispatcher?: EventDispatcher;
|
|
65
68
|
readonly mode: "api";
|
|
66
69
|
start(): Promise<void>;
|
package/dist/entrypoint/index.js
CHANGED
|
@@ -36,11 +36,12 @@
|
|
|
36
36
|
//
|
|
37
37
|
// SSE fanout across processes (split api/worker deploy, replicas > 1):
|
|
38
38
|
// buildServer's default sseBroker is Redis-backed whenever REDIS_URL is
|
|
39
|
-
// set
|
|
39
|
+
// set — a push on the worker's dispatcher reaches clients
|
|
40
40
|
// connected to any API instance via Redis Pub/Sub, no per-instance
|
|
41
41
|
// cursor needed. Without REDIS_URL, the in-memory broker still only
|
|
42
42
|
// reaches clients on the same process.
|
|
43
|
-
import { buildServer
|
|
43
|
+
import { buildServer } from "../api/server.js";
|
|
44
|
+
import { withFileProviderResolver } from "../api/server-wiring.js";
|
|
44
45
|
import { createJobRunner } from "../jobs/job-runner.js";
|
|
45
46
|
import { createLifecycle } from "../lifecycle/index.js";
|
|
46
47
|
import { createNoopProvider } from "../observability/index.js";
|
|
@@ -55,7 +56,7 @@ import { resolveCacheSyncBus } from "../redis/cache-sync-bus.js";
|
|
|
55
56
|
// so the command-dispatcher fires handleEvent as an afterCommit-hook for
|
|
56
57
|
// event-triggered jobs (dispatcher.ts:997). Without this plumbing,
|
|
57
58
|
// `r.job({ trigger: { on: … } })` silently drops on every write — that
|
|
58
|
-
// was the hidden
|
|
59
|
+
// was the hidden gap.
|
|
59
60
|
//
|
|
60
61
|
// Caller-supplied `dispatcherOptions.jobRunner` wins (tests sometimes
|
|
61
62
|
// inject a mock runner directly).
|
|
@@ -119,6 +120,8 @@ function buildApiServer(opts, lifecycle, dispatcherOverride, jobRunner, processL
|
|
|
119
120
|
jwtIssuer: opts.jwtIssuer,
|
|
120
121
|
auth: opts.auth,
|
|
121
122
|
trustedProxyHops: opts.trustedProxyHops,
|
|
123
|
+
errorDocs: opts.errorDocs,
|
|
124
|
+
instanceId: opts.instanceId,
|
|
122
125
|
anonymousAccess: opts.anonymousAccess,
|
|
123
126
|
sseBroker: opts.sseBroker,
|
|
124
127
|
rateLimit: opts.rateLimit,
|
|
@@ -145,6 +148,7 @@ function buildWorkerServer(opts, lifecycle, jobRunner) {
|
|
|
145
148
|
jwtSecret: opts.jwtSecret,
|
|
146
149
|
lifecycle,
|
|
147
150
|
processLane: "worker",
|
|
151
|
+
instanceId: opts.instanceId,
|
|
148
152
|
observability: opts.observability,
|
|
149
153
|
dispatcherOptions,
|
|
150
154
|
systemHooks: opts.systemHooks,
|
|
@@ -198,7 +202,7 @@ export function createApiEntrypoint(options) {
|
|
|
198
202
|
const lifecycle = options.lifecycle ?? createLifecycle({ startReady: true });
|
|
199
203
|
const observability = resolveObservability(options.observability);
|
|
200
204
|
const { options: busOptions, context } = resolveEntrypointCacheSync(options, lifecycle);
|
|
201
|
-
// Boot-validation
|
|
205
|
+
// Boot-validation — fail loud before traffic arrives:
|
|
202
206
|
// (a) Any jobs declared + no jobs-block → command-dispatcher would
|
|
203
207
|
// silently drop every event-triggered enqueue. Fix: add jobs:
|
|
204
208
|
// { redisUrl } so the API holds lane-queue-clients.
|
|
@@ -240,6 +244,7 @@ export function createApiEntrypoint(options) {
|
|
|
240
244
|
lifecycle,
|
|
241
245
|
observability: server.observability,
|
|
242
246
|
dispatcher: server.dispatcher,
|
|
247
|
+
lifecycleHooks: server.lifecycleHooks,
|
|
243
248
|
...(server.eventDispatcher && { eventDispatcher: server.eventDispatcher }),
|
|
244
249
|
mode: "api",
|
|
245
250
|
async start() {
|
|
@@ -319,6 +324,7 @@ export function createAllInOneEntrypoint(options) {
|
|
|
319
324
|
jobRunner: workerJobRunner,
|
|
320
325
|
observability: server.observability,
|
|
321
326
|
dispatcher: server.dispatcher,
|
|
327
|
+
lifecycleHooks: server.lifecycleHooks,
|
|
322
328
|
mode: "all-in-one",
|
|
323
329
|
async start() {
|
|
324
330
|
await eventDispatcher.start();
|
package/dist/env/index.d.ts
CHANGED
|
@@ -116,12 +116,13 @@ export type ParseEnvOptions = {
|
|
|
116
116
|
* is `undefined` in the result despite its `string` type — it is only set once
|
|
117
117
|
* the boot-time decrypt (resolvePlatformKeks) has run. */
|
|
118
118
|
export declare function parseEnv<S extends z.ZodObject<z.ZodRawShape>>(schema: S, env: Record<string, string | undefined>, options?: ParseEnvOptions): z.infer<S>;
|
|
119
|
-
/** Dry-
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
119
|
+
/** Dry-run counterpart to parseEnv (KUMIKO_DRY_RUN_ENV path): parses each
|
|
120
|
+
* field individually and returns an honest Partial — present values pass
|
|
121
|
+
* through with their types (coerced), while missing or invalid values are
|
|
122
|
+
* simply omitted. Never throws: the dry run renders the inventory instead
|
|
123
|
+
* of failing on required fields. Replaces the `({} as Shape)` pattern, where
|
|
124
|
+
* every access silently returned undefined and the compiler could not detect
|
|
125
|
+
* it. */
|
|
125
126
|
export declare function parseEnvDryRun<S extends z.ZodObject<z.ZodRawShape>>(schema: S, env: Record<string, string | undefined>): Partial<z.infer<S>>;
|
|
126
127
|
export type EnvFieldStatus = "set" | "unset" | "missing" | "invalid";
|
|
127
128
|
export type EnvFieldInspection = {
|
package/dist/env/index.js
CHANGED
|
@@ -209,7 +209,7 @@ export function composeEnvSchema(options) {
|
|
|
209
209
|
// rather than silently overwriting a deploy-critical default. The
|
|
210
210
|
// conflict-detection makes the order safe in both directions — both
|
|
211
211
|
// throw — but downstream tools that consume `sources` (e.g. the
|
|
212
|
-
// upcoming
|
|
212
|
+
// upcoming lint-guard) may rely on this insertion order.
|
|
213
213
|
if (options.core) {
|
|
214
214
|
for (const [key, field] of Object.entries(zodShape(options.core))) {
|
|
215
215
|
merged[key] = field;
|
|
@@ -356,12 +356,13 @@ export function parseEnv(schema, env, options = {}) {
|
|
|
356
356
|
function ucfirst(s) {
|
|
357
357
|
return s.length === 0 ? s : s.charAt(0).toUpperCase() + s.slice(1);
|
|
358
358
|
}
|
|
359
|
-
/** Dry-
|
|
360
|
-
*
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
*
|
|
359
|
+
/** Dry-run counterpart to parseEnv (KUMIKO_DRY_RUN_ENV path): parses each
|
|
360
|
+
* field individually and returns an honest Partial — present values pass
|
|
361
|
+
* through with their types (coerced), while missing or invalid values are
|
|
362
|
+
* simply omitted. Never throws: the dry run renders the inventory instead
|
|
363
|
+
* of failing on required fields. Replaces the `({} as Shape)` pattern, where
|
|
364
|
+
* every access silently returned undefined and the compiler could not detect
|
|
365
|
+
* it. */
|
|
365
366
|
export function parseEnvDryRun(schema, env) {
|
|
366
367
|
const out = {};
|
|
367
368
|
for (const [name, field] of Object.entries(zodShape(schema))) {
|
|
@@ -372,8 +373,8 @@ export function parseEnvDryRun(schema, env) {
|
|
|
372
373
|
if (result.success)
|
|
373
374
|
out[name] = result.data;
|
|
374
375
|
}
|
|
375
|
-
// @cast-boundary schema-walk — Partial<z.infer<S>> erasure
|
|
376
|
-
// per-
|
|
376
|
+
// @cast-boundary schema-walk — Partial<z.infer<S>> erasure through the
|
|
377
|
+
// per-field safeParse; every included value passed its field-level parse.
|
|
377
378
|
return out;
|
|
378
379
|
}
|
|
379
380
|
/** Checks every field of `schema` on its own against `env`, for the boot dry
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { KumikoError } from "./kumiko-error.ts";
|
|
2
|
-
/** Links an app's own error reasons to its own docs;
|
|
2
|
+
/** Links an app's own error reasons to its own docs; uncovered reasons fall back to the framework page of the error code. */
|
|
3
3
|
export type ErrorDocsConfig = {
|
|
4
4
|
readonly baseUrl: string;
|
|
5
5
|
readonly reasons?: readonly string[] | "all";
|
package/dist/errors/docs-url.js
CHANGED
|
@@ -5,6 +5,26 @@ const frameworkReasons = new Set([
|
|
|
5
5
|
...Object.values(FrameworkReasons),
|
|
6
6
|
...Object.values(AgentReasons),
|
|
7
7
|
]);
|
|
8
|
+
// Codes of the built-in error classes: only these have a framework docs page.
|
|
9
|
+
const frameworkErrorCodes = new Set([
|
|
10
|
+
"validation_error",
|
|
11
|
+
"feature_disabled",
|
|
12
|
+
"access_denied",
|
|
13
|
+
"unauthenticated",
|
|
14
|
+
"not_found",
|
|
15
|
+
"conflict",
|
|
16
|
+
"version_conflict",
|
|
17
|
+
"precondition_failed",
|
|
18
|
+
"record_locked",
|
|
19
|
+
"idempotent_replay",
|
|
20
|
+
"unique_violation",
|
|
21
|
+
"unprocessable",
|
|
22
|
+
"unconfigured",
|
|
23
|
+
"internal_error",
|
|
24
|
+
"member_read_timeout",
|
|
25
|
+
"rate_limited",
|
|
26
|
+
"rate_limit_unavailable",
|
|
27
|
+
]);
|
|
8
28
|
function reasonOf(err) {
|
|
9
29
|
if (!err.details || typeof err.details !== "object")
|
|
10
30
|
return undefined;
|
|
@@ -22,7 +42,7 @@ function errorsUrl(baseUrl, slug) {
|
|
|
22
42
|
}
|
|
23
43
|
// A reason the framework documents (or no reason, or the code itself) links to the framework docs, overridable via
|
|
24
44
|
// KUMIKO_DOCS_URL. An app's own reason links to the app docs where `errorDocs` covers it; every
|
|
25
|
-
// other reason falls back to the framework page of the error code,
|
|
45
|
+
// other reason falls back to the framework page of the error code, unless an app subclass overrode the code.
|
|
26
46
|
export function resolveErrorDocsUrl(err, errorDocs) {
|
|
27
47
|
const reason = reasonOf(err);
|
|
28
48
|
const frameworkBaseUrl = process.env["KUMIKO_DOCS_URL"] ?? DEFAULT_DOCS_BASE_URL;
|
|
@@ -32,5 +52,5 @@ export function resolveErrorDocsUrl(err, errorDocs) {
|
|
|
32
52
|
if (errorDocs && isCoveredByConfig(reason, errorDocs)) {
|
|
33
53
|
return errorsUrl(errorDocs.baseUrl, reason);
|
|
34
54
|
}
|
|
35
|
-
return errorsUrl(frameworkBaseUrl, err.code);
|
|
55
|
+
return frameworkErrorCodes.has(err.code) ? errorsUrl(frameworkBaseUrl, err.code) : undefined;
|
|
36
56
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
//
|
|
2
|
-
// (state-machine.assertTransition
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
1
|
+
// Shared detail shape for invalid_transition errors. Both paths
|
|
2
|
+
// (`state-machine.assertTransition` and `failTransition`) must provide
|
|
3
|
+
// identically structured details so HTTP clients can parse the 422 body uniformly:
|
|
4
|
+
// `from`/`to`/`allowed` are the structured fields, while `message` is the
|
|
5
|
+
// human-readable form.
|
|
6
6
|
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
7
|
+
// `validTargets` is not re-exported as a CSV string; callers that need CSV can use
|
|
8
|
+
// `allowed.join(", ")`. One shape defines the contract.
|
|
9
9
|
export function buildInvalidTransitionDetails(from, to, allowed) {
|
|
10
10
|
return {
|
|
11
11
|
from,
|
|
@@ -7,13 +7,13 @@ export declare function failUnprocessable(reason: string, details?: Readonly<Rec
|
|
|
7
7
|
readonly reason?: never;
|
|
8
8
|
}): WriteFailure;
|
|
9
9
|
/**
|
|
10
|
-
* Convenience
|
|
11
|
-
* reason="invalid_transition"
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
10
|
+
* Convenience for state-transition rejects: produces a WriteFailure with
|
|
11
|
+
* reason="invalid_transition", a structured `from`/`to`/`allowed` detail
|
|
12
|
+
* block, and a readable message. This pattern recurs in publicstatus
|
|
13
|
+
* maintenance and existing state-machine helpers, so the helper collects it
|
|
14
|
+
* in one call instead of requiring three manual detail fields.
|
|
15
15
|
*
|
|
16
|
-
* `allowed`
|
|
16
|
+
* `allowed` is typically `MAINTENANCE_TRANSITIONS.allowedFrom(from)`.
|
|
17
17
|
*/
|
|
18
18
|
export declare function failTransition(from: string, to: string, allowed: readonly string[]): WriteFailure;
|
|
19
19
|
export declare function toWriteErrorInfo(err: KumikoError): WriteErrorInfo;
|
|
@@ -24,13 +24,13 @@ export function failUnprocessable(reason, details) {
|
|
|
24
24
|
return writeFailure(new UnprocessableError(reason, details ? { details } : undefined));
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
|
-
* Convenience
|
|
28
|
-
* reason="invalid_transition"
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
27
|
+
* Convenience for state-transition rejects: produces a WriteFailure with
|
|
28
|
+
* reason="invalid_transition", a structured `from`/`to`/`allowed` detail
|
|
29
|
+
* block, and a readable message. This pattern recurs in publicstatus
|
|
30
|
+
* maintenance and existing state-machine helpers, so the helper collects it
|
|
31
|
+
* in one call instead of requiring three manual detail fields.
|
|
32
32
|
*
|
|
33
|
-
* `allowed`
|
|
33
|
+
* `allowed` is typically `MAINTENANCE_TRANSITIONS.allowedFrom(from)`.
|
|
34
34
|
*/
|
|
35
35
|
export function failTransition(from, to, allowed) {
|
|
36
36
|
return writeFailure(new UnprocessableError(FrameworkReasons.invalidTransition, {
|
package/dist/es-ops/context.d.ts
CHANGED
|
@@ -5,15 +5,15 @@ export type CreateSeedMigrationContextArgs = {
|
|
|
5
5
|
readonly dispatcher: Dispatcher;
|
|
6
6
|
readonly dbRunner: DbRunner;
|
|
7
7
|
};
|
|
8
|
-
/** Builder
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
/** Builder that returns a factory function called by the runner for each
|
|
9
|
+
* migration. dbRunner may be a top-level connection or a transaction—read
|
|
10
|
+
* helpers use it directly, while systemWriteAs delegates to the dispatcher.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* runner.integration.test.ts
|
|
12
|
+
* dispatcher.write does not receive the runner transaction: runBatch opens
|
|
13
|
+
* a separate transaction on context.db (using a separate pool connection).
|
|
14
|
+
* Writes therefore commit independently: a runner failure rolls back only
|
|
15
|
+
* the marker insert and dbRunner reads; dispatcher writes remain committed.
|
|
16
|
+
* Seeds must therefore be idempotent (verified in
|
|
17
|
+
* runner.integration.test.ts “dispatcher-writes vor throw bleiben committed”). */
|
|
18
18
|
export declare function createSeedMigrationContext(args: CreateSeedMigrationContextArgs): SeedMigrationContext;
|
|
19
19
|
export type { SeedMigrationContext } from "./types.ts";
|
package/dist/es-ops/context.js
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
// SeedMigrationContext
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
1
|
+
// SeedMigrationContext builder. The caller (runProdApp/CLI) supplies a
|
|
2
|
+
// preconfigured dispatcher; the builder creates a transaction-scoped context
|
|
3
|
+
// for each migration that uses the existing handler path through
|
|
4
|
+
// dispatcher.write—the same pattern as a user UI click.
|
|
5
5
|
//
|
|
6
|
-
//
|
|
7
|
-
// config-seed.ts:40). Events
|
|
8
|
-
//
|
|
6
|
+
// The system user bypasses access checks (the standard seed pattern; see
|
|
7
|
+
// config-seed.ts:40). Events have createdBy = SYSTEM_TENANT_ID user,
|
|
8
|
+
// making them auditable.
|
|
9
9
|
import { configuredPiiSubjectKms, decryptPiiFieldValues } from "../crypto/index.js";
|
|
10
10
|
import { selectAllTenants, selectMembershipsOfUser, selectTemplateResources, selectUserByEmail, } from "../db/queries/seed-context.js";
|
|
11
11
|
import { createSystemUser, SYSTEM_TENANT_ID } from "../engine/index.js";
|
|
12
12
|
import { parseStringArrayJson } from "../utils/parse-string-array-json.js";
|
|
13
|
-
/** Builder
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
/** Builder that returns a factory function called by the runner for each
|
|
14
|
+
* migration. dbRunner may be a top-level connection or a transaction—read
|
|
15
|
+
* helpers use it directly, while systemWriteAs delegates to the dispatcher.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* runner.integration.test.ts
|
|
17
|
+
* dispatcher.write does not receive the runner transaction: runBatch opens
|
|
18
|
+
* a separate transaction on context.db (using a separate pool connection).
|
|
19
|
+
* Writes therefore commit independently: a runner failure rolls back only
|
|
20
|
+
* the marker insert and dbRunner reads; dispatcher writes remain committed.
|
|
21
|
+
* Seeds must therefore be idempotent (verified in
|
|
22
|
+
* runner.integration.test.ts “dispatcher-writes vor throw bleiben committed”). */
|
|
23
23
|
export function createSeedMigrationContext(args) {
|
|
24
|
-
// Default
|
|
25
|
-
// text-content, etc.).
|
|
26
|
-
//
|
|
24
|
+
// Default executor for system-scope aggregates (config-values, system
|
|
25
|
+
// text-content, etc.). For tenant-scope aggregates, the caller must
|
|
26
|
+
// explicitly provide `tenantIdOverride`—see the documentation in types.ts.
|
|
27
27
|
const defaultSystemUser = createSystemUser(SYSTEM_TENANT_ID);
|
|
28
28
|
return {
|
|
29
29
|
systemWriteAs: async (handlerQualifiedName, payload, tenantIdOverride, extraRoles) => {
|
|
30
|
-
// tenantIdOverride
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
// feedback_event_store_tenant_consistency.md).
|
|
30
|
+
// tenantIdOverride creates a system user with the stream tenant ID so that
|
|
31
|
+
// the event-store executor finds the aggregate in the correct stream.
|
|
32
|
+
// This prevents the version_conflict failure.
|
|
34
33
|
const executor = tenantIdOverride !== undefined || (extraRoles && extraRoles.length > 0)
|
|
35
34
|
? createSystemUser(tenantIdOverride ?? SYSTEM_TENANT_ID, extraRoles)
|
|
36
35
|
: defaultSystemUser;
|
|
37
36
|
const result = await args.dispatcher.write(handlerQualifiedName, payload, executor);
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
//
|
|
37
|
+
// Without this check, WriteResult{isSuccess: false} would pass silently,
|
|
38
|
+
// causing the marker to be written despite the failed write and the
|
|
39
|
+
// migration to be incorrectly marked as "applied". Throw so the
|
|
40
|
+
// runner's outer transaction rolls back and the marker is not written.
|
|
41
|
+
// Seed authors can use try/catch for custom handling when a soft failure
|
|
42
|
+
// is expected.
|
|
43
43
|
if (!result.isSuccess) {
|
|
44
44
|
const code = result.error?.code ?? "unknown";
|
|
45
45
|
const message = result.error?.message ?? "(no message)";
|
|
46
|
-
throw new Error(`
|
|
46
|
+
throw new Error(`systemWriteAs("${handlerQualifiedName}") failed: ${code} — ${message}`);
|
|
47
47
|
}
|
|
48
48
|
return result;
|
|
49
49
|
},
|
package/dist/es-ops/index.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
// es-ops — ES
|
|
1
|
+
// es-ops — ES operations pattern for Kumiko apps.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
// (kumiko_es_operations
|
|
3
|
+
// Seed migrations use the same infrastructure as later operation types
|
|
4
|
+
// (the `kumiko_es_operations` table with an `operation_type` discriminator).
|
|
5
5
|
//
|
|
6
|
-
// App
|
|
7
|
-
// - SeedMigration
|
|
8
|
-
// - runProdApp({ seedsDir })
|
|
9
|
-
// - bunx kumiko ops seed:new|status|apply (CLI)
|
|
10
|
-
//
|
|
11
|
-
// Plan-Doc: kumiko-platform/docs/plans/features/es-ops.md
|
|
6
|
+
// App author API:
|
|
7
|
+
// - `SeedMigration`: default export type of a seed file
|
|
8
|
+
// - `runProdApp({ seedsDir })`: the framework runs pending migrations at boot
|
|
9
|
+
// - `bunx kumiko ops seed:new|status|apply` (CLI)
|
|
12
10
|
export { createSeedMigrationContext, } from "./context.js";
|
|
13
11
|
export { createEsOperationsTable, esOperationsTable, } from "./operations-schema.js";
|
|
14
12
|
export { runPendingSeedMigrations, } from "./runner.js";
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// File-ID-Tracking analog drizzle-kit: filename ist die ID, applied-set
|
|
6
|
-
// liegt in dieser Tabelle. Pending = files-on-disk MINUS applied-set.
|
|
7
|
-
//
|
|
8
|
-
// operation_type-Discriminator lässt Phase 2+ dieselbe Tabelle nutzen,
|
|
9
|
-
// kein Schema-Sprawl. CLI-Status filtert per type:
|
|
1
|
+
// Tracks ES operations. The filename is the ID, so pending operations are files on disk minus the
|
|
2
|
+
// applied set. The operation_type discriminator lets different operation types share one table
|
|
3
|
+
// without schema sprawl; CLI status commands filter by type:
|
|
10
4
|
// bunx kumiko ops seed:status → operation_type = "seed-migration"
|
|
11
5
|
// bunx kumiko ops projection:status → operation_type = "projection-rebuild"
|
|
12
6
|
import { index, integer, table as pgTable, sql, text, timestamp } from "../db/dialect.js";
|
|
@@ -24,7 +18,7 @@ export const esOperationsTable = pgTable("kumiko_es_operations", {
|
|
|
24
18
|
.default(sql `now()`),
|
|
25
19
|
durationMs: integer("duration_ms").notNull(),
|
|
26
20
|
// Trace: came from boot-time auto-apply, explicit CLI, or CI step.
|
|
27
|
-
//
|
|
21
|
+
// Supports forensic questions about who initiated the operation and when.
|
|
28
22
|
appliedBy: text("applied_by").notNull().$type(),
|
|
29
23
|
// Optional human-readable annotation — surfaced in `ops <op>:status`.
|
|
30
24
|
notes: text("notes"),
|
package/dist/es-ops/runner.d.ts
CHANGED
|
@@ -3,23 +3,23 @@ import type { Registry } from "../engine/index.ts";
|
|
|
3
3
|
import type { EsOperationAppliedBy, SeedMigrationContext } from "./types.ts";
|
|
4
4
|
export type RunPendingSeedMigrationsArgs = {
|
|
5
5
|
readonly db: DbConnection;
|
|
6
|
-
/**
|
|
6
|
+
/** Absolute path to the seeds directory (typically <appRoot>/seeds). */
|
|
7
7
|
readonly seedsDir: string;
|
|
8
|
-
/** Factory
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
/** Factory that creates the context for each seed migration.
|
|
9
|
+
* The caller receives a DbRunner (connection OR active transaction); the
|
|
10
|
+
* runner invokes this once per migration within the transaction scope. */
|
|
11
11
|
readonly createContext: (dbRunner: DbRunner) => SeedMigrationContext;
|
|
12
12
|
/** Trace-marker: boot | cli | ci-pipeline. Landet in applied_by. */
|
|
13
13
|
readonly appliedBy: EsOperationAppliedBy;
|
|
14
|
-
/** Optional registry
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
14
|
+
/** Optional registry for dry-run validation: parses each seed file and
|
|
15
|
+
* checks that all referenced handler QNs exist in the registry
|
|
16
|
+
* BEFORE the migration runs. This catches camelCase typos and other QN
|
|
17
|
+
* drift at boot rather than in the middle of a write cycle.
|
|
18
18
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* If omitted, no dry run is performed (backward compatibility for tests
|
|
20
|
+
* that do not provide a registry). runProdApp supplies the correct one. */
|
|
21
21
|
readonly registry?: Registry;
|
|
22
|
-
/** Optional
|
|
22
|
+
/** Optional line sink; the default logs under the "es-ops/seed-migration" namespace. */
|
|
23
23
|
readonly logger?: (line: string) => void;
|
|
24
24
|
};
|
|
25
25
|
export type RunPendingSeedMigrationsResult = {
|