@cosmicdrift/kumiko-framework 0.389.0 → 0.390.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +9 -4
- package/README.md +1 -1
- package/agents/examples/apex-surface-auth.md +2 -3
- package/agents/examples/api-worker-split.md +9 -2
- package/agents/examples/auth-claims.md +1 -1
- package/agents/examples/cross-feature-events.md +12 -12
- package/agents/examples/crypto-shredding-hr.md +2 -2
- package/agents/examples/encrypted-tenant-config.md +1 -1
- package/agents/examples/error-contract.md +12 -7
- package/agents/examples/event-sourcing.md +29 -29
- package/agents/examples/files-post-processing.md +10 -8
- package/agents/examples/inbound-mail-triage.md +1 -0
- package/agents/examples/lane-routing.md +2 -1
- package/agents/examples/legal-pages.md +2 -2
- package/agents/examples/lifecycle-hooks.md +3 -3
- package/agents/examples/managed-config.md +4 -4
- package/agents/examples/managed-pages.md +1 -1
- package/agents/examples/relations.md +19 -4
- package/agents/examples/search.md +4 -4
- package/agents/examples/secrets-demo.md +9 -6
- package/agents/examples/state-machine.md +2 -2
- package/agents/examples/tenant-settings.md +1 -1
- package/agents/examples/user-data-rights.md +3 -6
- package/agents/examples/workflow-engine.md +53 -47
- package/agents/examples.md +4 -4
- package/agents/features.md +1 -1
- package/dist/api/auth-middleware.js +1 -1
- package/dist/api/auth-routes-invite.js +2 -1
- package/dist/api/entity-read-access.d.ts +3 -1
- package/dist/api/export/export-columns.d.ts +3 -1
- package/dist/api/export/export-route.js +3 -2
- package/dist/api/export/export-screen.d.ts +2 -1
- package/dist/api/extra-route.d.ts +3 -1
- package/dist/api/index.d.ts +23 -27
- package/dist/api/index.js +13 -15
- package/dist/api/jwt.js +1 -1
- package/dist/api/observability-middleware.d.ts +1 -1
- package/dist/api/observability-middleware.js +2 -1
- package/dist/api/request-context-internals.d.ts +31 -0
- package/dist/api/request-context-internals.js +11 -0
- package/dist/api/request-context-scopes.d.ts +14 -0
- package/dist/api/request-context-scopes.js +69 -0
- package/dist/api/request-context.d.ts +1 -40
- package/dist/api/request-context.js +22 -51
- package/dist/api/request-id-middleware.d.ts +1 -1
- package/dist/api/route-registrars.d.ts +2 -1
- package/dist/api/route-registrars.js +1 -1
- package/dist/api/routes.js +7 -3
- package/dist/api/server-boot-checks.d.ts +1 -1
- package/dist/api/server-boot-checks.js +2 -2
- package/dist/api/server-event-dispatcher.d.ts +6 -1
- package/dist/api/server-event-dispatcher.js +3 -4
- package/dist/api/server-extra-routes.d.ts +1 -1
- package/dist/api/server-extra-routes.js +2 -1
- package/dist/api/server-middleware.js +3 -1
- package/dist/api/server-routes.d.ts +2 -1
- package/dist/api/server-wiring.js +6 -4
- package/dist/api/server.d.ts +2 -1
- package/dist/api/sse-route.d.ts +2 -1
- package/dist/api/tenant-scoped-secrets.d.ts +2 -0
- package/dist/api/tenant-scoped-secrets.js +13 -0
- package/dist/api/websocket-route.d.ts +1 -1
- package/dist/auth/index.d.ts +0 -1
- package/dist/auth/roles.d.ts +0 -5
- package/dist/compliance/duration-spec.d.ts +0 -1
- package/dist/compliance/duration-spec.js +0 -5
- package/dist/compliance/index.d.ts +4 -4
- package/dist/compliance/index.js +2 -2
- package/dist/compliance/profiles.d.ts +0 -15
- package/dist/compliance/profiles.js +0 -23
- package/dist/config/index.d.ts +10 -10
- package/dist/config/index.js +13 -1
- package/dist/config/internals.d.ts +9 -0
- package/dist/config/internals.js +1 -0
- package/dist/consumer-cli-internals.d.ts +4 -0
- package/dist/consumer-cli-internals.js +1 -0
- package/dist/consumer-cli.d.ts +1 -4
- package/dist/consumer-cli.js +5 -1
- package/dist/crypto/event-pii.js +1 -1
- package/dist/crypto/index.d.ts +8 -9
- package/dist/crypto/index.js +7 -8
- package/dist/crypto/pg-kms-adapter.js +6 -1
- package/dist/db/apply-entity-event.d.ts +1 -1
- package/dist/db/apply-entity-event.js +15 -47
- package/dist/db/blind-index-cleanup.js +91 -77
- package/dist/db/collect-table-metas.js +1 -1
- package/dist/db/compound-types.d.ts +1 -1
- package/dist/db/compound-types.js +0 -7
- package/dist/db/config-seed.d.ts +2 -1
- package/dist/db/config-seed.js +6 -1
- package/dist/db/connection.d.ts +3 -1
- package/dist/db/connection.js +15 -5
- package/dist/db/cross-tenant-reads.d.ts +1 -1
- package/dist/db/cross-tenant-reads.js +1 -1
- package/dist/db/dialect.d.ts +0 -5
- package/dist/db/dialect.js +0 -3
- package/dist/db/driver-value-preparation.js +23 -2
- package/dist/db/eagerload.d.ts +2 -1
- package/dist/db/entity-field-encryption.d.ts +1 -1
- package/dist/db/entity-table-meta.d.ts +1 -1
- package/dist/db/event-store-executor-context.d.ts +3 -1
- package/dist/db/event-store-executor-context.js +4 -3
- package/dist/db/event-store-executor-read-filter.d.ts +1 -1
- package/dist/db/event-store-executor-read-rows.d.ts +2 -1
- package/dist/db/event-store-executor-read-search.d.ts +2 -1
- package/dist/db/event-store-executor-read-sort.d.ts +2 -1
- package/dist/db/event-store-executor-read.js +2 -2
- package/dist/db/event-store-executor-write-atomic.js +8 -7
- package/dist/db/event-store-executor-write-steps.d.ts +3 -2
- package/dist/db/event-store-executor-write.js +7 -4
- package/dist/db/event-store-executor.d.ts +1 -1
- package/dist/db/executor-managed-tables.d.ts +7 -1
- package/dist/db/executor-managed-tables.js +11 -2
- package/dist/db/index.d.ts +29 -28
- package/dist/db/index.js +22 -20
- package/dist/db/known-table-names.d.ts +6 -0
- package/dist/db/known-table-names.js +21 -0
- package/dist/db/list-aggregate-labels.d.ts +1 -1
- package/dist/db/located-timestamp.d.ts +1 -1
- package/dist/db/located-timestamp.js +0 -5
- package/dist/db/migrate-generator.d.ts +17 -1
- package/dist/db/migrate-generator.js +50 -20
- package/dist/db/migrate-primary-key.d.ts +12 -0
- package/dist/db/migrate-primary-key.js +45 -0
- package/dist/db/migrate-rls-diff.d.ts +20 -0
- package/dist/db/migrate-rls-diff.js +61 -0
- package/dist/db/migrate-runner.js +4 -0
- package/dist/db/money.d.ts +1 -1
- package/dist/db/money.js +1 -1
- package/dist/db/parent-ref-clause.d.ts +2 -1
- package/dist/db/pg-error.d.ts +2 -0
- package/dist/db/pg-error.js +11 -0
- package/dist/db/queries/ddl.d.ts +3 -0
- package/dist/db/queries/ddl.js +34 -1
- package/dist/db/queries/event-store.js +4 -2
- package/dist/db/queries/event-tenants.d.ts +2 -0
- package/dist/db/queries/event-tenants.js +17 -0
- package/dist/db/queries/rebuild-rls-guard.d.ts +2 -0
- package/dist/db/queries/rebuild-rls-guard.js +29 -0
- package/dist/db/queries/rls-boot-catalog.d.ts +16 -0
- package/dist/db/queries/rls-boot-catalog.js +39 -0
- package/dist/db/queries/rls-catalog.d.ts +6 -0
- package/dist/db/queries/rls-catalog.js +82 -0
- package/dist/db/queries/rls-scope.d.ts +3 -0
- package/dist/db/queries/rls-scope.js +17 -0
- package/dist/db/queries/rls-shape.d.ts +10 -0
- package/dist/db/queries/rls-shape.js +42 -0
- package/dist/db/queries/session-advisory-lock.d.ts +2 -0
- package/dist/db/queries/session-advisory-lock.js +23 -0
- package/dist/db/queries/shadow-swap.d.ts +1 -2
- package/dist/db/queries/shadow-swap.js +9 -25
- package/dist/db/queries/test-stack.d.ts +4 -1
- package/dist/db/queries/test-stack.js +84 -2
- package/dist/db/query.js +11 -7
- package/dist/db/reference-data.d.ts +1 -1
- package/dist/db/reference-data.js +6 -1
- package/dist/db/render-ddl.d.ts +6 -2
- package/dist/db/render-ddl.js +7 -7
- package/dist/db/render-rls-ddl.d.ts +35 -0
- package/dist/db/render-rls-ddl.js +127 -0
- package/dist/db/replay-migration-sql.d.ts +3 -1
- package/dist/db/replay-migration-sql.js +22 -5
- package/dist/db/replay-rls.d.ts +25 -0
- package/dist/db/replay-rls.js +156 -0
- package/dist/db/row-level-security-boot-check.d.ts +6 -0
- package/dist/db/row-level-security-boot-check.js +86 -0
- package/dist/db/row-level-security-connection.d.ts +3 -0
- package/dist/db/row-level-security-connection.js +213 -0
- package/dist/db/row-level-security-scope.d.ts +33 -0
- package/dist/db/row-level-security-scope.js +127 -0
- package/dist/db/scope-tenant-db-to-tenant.d.ts +3 -0
- package/dist/db/scope-tenant-db-to-tenant.js +14 -0
- package/dist/db/sql-identifier.d.ts +1 -0
- package/dist/db/sql-identifier.js +3 -0
- package/dist/db/table-builder.d.ts +2 -1
- package/dist/db/table-builder.js +1 -1
- package/dist/db/table-info.js +1 -1
- package/dist/db/table-push.d.ts +11 -2
- package/dist/db/table-push.js +15 -2
- package/dist/db/tenant-db-runner.d.ts +3 -1
- package/dist/db/tenant-db-runner.js +4 -3
- package/dist/db/tenant-db-scoped-rebind.d.ts +10 -0
- package/dist/db/tenant-db-scoped-rebind.js +33 -0
- package/dist/db/tenant-db-statement-runner.d.ts +13 -0
- package/dist/db/tenant-db-statement-runner.js +48 -0
- package/dist/db/tenant-db.d.ts +17 -12
- package/dist/db/tenant-db.js +49 -120
- package/dist/db/tenant-id-filter.d.ts +3 -0
- package/dist/db/tenant-id-filter.js +30 -0
- package/dist/db/transaction-serialization.d.ts +6 -0
- package/dist/db/transaction-serialization.js +60 -0
- package/dist/derivatives/delete-stored-file.js +1 -1
- package/dist/derivatives/index.d.ts +2 -5
- package/dist/derivatives/index.js +2 -3
- package/dist/engine/access.d.ts +2 -1
- package/dist/engine/access.js +1 -1
- package/dist/engine/boot-validator/entity-handler.d.ts +2 -1
- package/dist/engine/boot-validator/entity-handler.js +1 -1
- package/dist/engine/boot-validator/entity-list-aggregate-options.d.ts +1 -1
- package/dist/engine/boot-validator/list-table-aggregate-options.d.ts +1 -1
- package/dist/engine/boot-validator/list-table-aggregate-query.d.ts +2 -1
- package/dist/engine/boot-validator/nav.d.ts +3 -1
- package/dist/engine/boot-validator/nav.js +1 -1
- package/dist/engine/boot-validator/ownership.d.ts +2 -1
- package/dist/engine/boot-validator/parent-ref.d.ts +2 -1
- package/dist/engine/boot-validator/projection-list-screens.d.ts +2 -1
- package/dist/engine/boot-validator/query-refs.d.ts +2 -1
- package/dist/engine/boot-validator/screens-forms.d.ts +2 -1
- package/dist/engine/boot-validator/screens-kind-shared.d.ts +3 -1
- package/dist/engine/boot-validator/screens.d.ts +2 -1
- package/dist/engine/boot-validator/workspaces.d.ts +3 -1
- package/dist/engine/bridge-stub.d.ts +5 -2
- package/dist/engine/bridge-stub.js +39 -24
- package/dist/engine/config-helpers.d.ts +2 -2
- package/dist/engine/config-helpers.js +0 -9
- package/dist/engine/constants.d.ts +0 -10
- package/dist/engine/constants.js +0 -8
- package/dist/engine/create-app.js +1 -1
- package/dist/engine/define-feature.d.ts +2 -1
- package/dist/engine/define-feature.js +1 -2
- package/dist/engine/define-handler.d.ts +1 -1
- package/dist/engine/define-step.d.ts +0 -1
- package/dist/engine/define-step.js +0 -3
- package/dist/engine/embedded-derived.d.ts +1 -1
- package/dist/engine/entity-handlers.d.ts +2 -1
- package/dist/engine/entity-handlers.js +7 -7
- package/dist/engine/entity-list-runtime-options.js +3 -1
- package/dist/engine/entity-list-searchability.d.ts +2 -1
- package/dist/engine/event-def.d.ts +2 -1
- package/dist/engine/event-helpers.d.ts +3 -1
- package/dist/engine/event-helpers.js +3 -3
- package/dist/engine/extension-names.d.ts +2 -8
- package/dist/engine/extension-names.js +2 -2
- package/dist/engine/extension-selector-plugins.d.ts +1 -1
- package/dist/engine/extensions/storage-provider.d.ts +1 -2
- package/dist/engine/extensions/user-data.d.ts +0 -8
- package/dist/engine/factories.d.ts +2 -1
- package/dist/engine/feature-builder-state.d.ts +8 -1
- package/dist/engine/feature-changelog.d.ts +1 -1
- package/dist/engine/feature-config-events-jobs.d.ts +4 -1
- package/dist/engine/feature-entity-handlers.d.ts +5 -1
- package/dist/engine/feature-manifest.js +1 -1
- package/dist/engine/feature-ui-extensions.d.ts +7 -1
- package/dist/engine/feature-ui-extensions.js +6 -4
- package/dist/engine/field-access.d.ts +2 -1
- package/dist/engine/handler-field-references.d.ts +0 -4
- package/dist/engine/index.d.ts +57 -54
- package/dist/engine/index.js +22 -27
- package/dist/engine/instruction-fields.d.ts +1 -1
- package/dist/engine/personal-data-fields.d.ts +1 -1
- package/dist/engine/qualified-name.d.ts +0 -1
- package/dist/engine/read-claim.d.ts +2 -1
- package/dist/engine/registry-facade.js +0 -3
- package/dist/engine/registry-ingest.d.ts +2 -1
- package/dist/engine/registry-ingest.js +1 -2
- package/dist/engine/registry-state.d.ts +12 -2
- package/dist/engine/registry-state.js +2 -3
- package/dist/engine/registry-validate.d.ts +3 -1
- package/dist/engine/registry-validate.js +7 -7
- package/dist/engine/run-in.d.ts +1 -1
- package/dist/engine/run-in.js +0 -1
- package/dist/engine/schema-builder.d.ts +1 -1
- package/dist/engine/schema-builder.js +1 -1
- package/dist/engine/screen-filter-ops.d.ts +2 -1
- package/dist/engine/screen-filter-ops.js +0 -5
- package/dist/engine/soft-delete-cleanup.d.ts +1 -1
- package/dist/engine/soft-delete-cleanup.js +4 -4
- package/dist/engine/state-machine.js +2 -1
- package/dist/engine/steps/_read-source.js +1 -1
- package/dist/engine/steps/aggregate-append-event.js +2 -2
- package/dist/engine/steps/call-feature.js +2 -2
- package/dist/engine/steps/mail-send.js +1 -1
- package/dist/engine/steps/retry.js +1 -1
- package/dist/engine/steps/wait-for-event.js +1 -1
- package/dist/engine/steps/wait.js +1 -1
- package/dist/engine/steps/webhook-send.js +1 -1
- package/dist/engine/template-variables.d.ts +2 -1
- package/dist/engine/transfer-adjacency.d.ts +1 -1
- package/dist/engine/types/index.d.ts +8 -31
- package/dist/engine/types/index.js +2 -10
- package/dist/engine/validation.d.ts +2 -1
- package/dist/entrypoint/index.d.ts +7 -35
- package/dist/entrypoint/index.js +7 -1
- package/dist/entrypoint/internals.d.ts +40 -0
- package/dist/entrypoint/internals.js +1 -0
- package/dist/entrypoint/row-level-security-mode-check.d.ts +3 -0
- package/dist/entrypoint/row-level-security-mode-check.js +19 -0
- package/dist/env/dry-run-internals.d.ts +10 -0
- package/dist/env/dry-run-internals.js +1 -0
- package/dist/env/dry-run.d.ts +1 -10
- package/dist/env/dry-run.js +2 -1
- package/dist/env/index.d.ts +1 -85
- package/dist/env/index.js +6 -50
- package/dist/env/internals.d.ts +87 -0
- package/dist/env/internals.js +53 -0
- package/dist/errors/classes.js +2 -2
- package/dist/errors/index.d.ts +5 -14
- package/dist/errors/index.js +4 -9
- package/dist/errors/member-resolution.js +1 -1
- package/dist/errors/reasons.d.ts +0 -1
- package/dist/errors/reasons.js +7 -7
- package/dist/errors/serialize.d.ts +0 -18
- package/dist/errors/serialize.js +0 -27
- package/dist/es-ops/index.d.ts +4 -4
- package/dist/es-ops/index.js +2 -2
- package/dist/es-ops/operations-schema.d.ts +1 -1
- package/dist/es-ops/types.d.ts +4 -5
- package/dist/event-store/admin-api-internals.d.ts +14 -0
- package/dist/event-store/admin-api-internals.js +1 -0
- package/dist/event-store/admin-api.d.ts +1 -14
- package/dist/event-store/admin-api.js +11 -6
- package/dist/event-store/archive.js +4 -2
- package/dist/event-store/errors.js +2 -2
- package/dist/event-store/event-store.js +41 -34
- package/dist/event-store/events-schema.js +4 -1
- package/dist/event-store/index.d.ts +11 -13
- package/dist/event-store/index.js +7 -9
- package/dist/event-store/rebuild-dead-letter.js +4 -2
- package/dist/event-store/snapshot.js +4 -3
- package/dist/event-store/stream-scope.d.ts +2 -0
- package/dist/event-store/stream-scope.js +6 -0
- package/dist/event-store/upcaster-dead-letter.js +4 -2
- package/dist/event-store/upcaster.d.ts +2 -1
- package/dist/files/action-form-upload.d.ts +2 -1
- package/dist/files/action-form-upload.js +1 -1
- package/dist/files/assert-file-refs-belong-to-tenant.d.ts +2 -1
- package/dist/files/assert-file-refs-belong-to-tenant.js +1 -1
- package/dist/files/bind-pending-file-refs.d.ts +2 -1
- package/dist/files/bind-pending-file-refs.js +2 -1
- package/dist/files/bind-referenced-files.write.js +1 -1
- package/dist/files/create-file-ref-from-bytes.d.ts +6 -3
- package/dist/files/create-file-ref-from-bytes.js +3 -3
- package/dist/files/create-file-ref.d.ts +3 -2
- package/dist/files/create-file-ref.js +2 -2
- package/dist/files/dispose-removed-file-refs.d.ts +2 -1
- package/dist/files/dispose-removed-file-refs.js +1 -1
- package/dist/files/feature.js +2 -2
- package/dist/files/file-handle.js +1 -1
- package/dist/files/file-routes.d.ts +1 -1
- package/dist/files/file-routes.js +12 -2
- package/dist/files/index.d.ts +11 -13
- package/dist/files/index.js +5 -7
- package/dist/files/load-save-file-refs.d.ts +2 -1
- package/dist/files/load-save-file-refs.js +1 -1
- package/dist/files/provider-resolver.d.ts +5 -4
- package/dist/files/provider-resolver.js +4 -4
- package/dist/files/storage-tracking.js +4 -2
- package/dist/files/sweep-orphaned-uploads.d.ts +1 -1
- package/dist/files/sweep-orphaned-uploads.js +1 -1
- package/dist/i18n/index.d.ts +2 -8
- package/dist/i18n/index.js +1 -1
- package/dist/i18n/internals.d.ts +7 -0
- package/dist/i18n/internals.js +1 -0
- package/dist/i18n/required-surface-keys.d.ts +4 -1
- package/dist/internal/row-level-security.d.ts +3 -0
- package/dist/internal/row-level-security.js +3 -0
- package/dist/internal/stack-support.d.ts +1 -1
- package/dist/internal/stack-support.js +1 -1
- package/dist/internal/testing.d.ts +1 -0
- package/dist/internal/testing.js +9 -5
- package/dist/jobs/index.d.ts +1 -1
- package/dist/jobs/job-append-event.d.ts +12 -0
- package/dist/jobs/job-append-event.js +30 -0
- package/dist/jobs/job-runner-context.d.ts +2 -2
- package/dist/jobs/job-runner-context.js +46 -16
- package/dist/jobs/job-runner-execution.d.ts +1 -1
- package/dist/jobs/job-runner-execution.js +6 -4
- package/dist/jobs/job-runner-gates.d.ts +1 -1
- package/dist/jobs/job-runner-gates.js +0 -1
- package/dist/jobs/job-runner-helpers.d.ts +11 -4
- package/dist/jobs/job-runner-helpers.js +10 -1
- package/dist/jobs/job-runner-scope.d.ts +5 -2
- package/dist/jobs/job-runner-types.d.ts +2 -1
- package/dist/jobs/job-runner.js +19 -6
- package/dist/jobs/max-per-tenant.d.ts +1 -1
- package/dist/logging/index.d.ts +1 -2
- package/dist/logging/index.js +1 -1
- package/dist/logging/pino-logger.js +1 -1
- package/dist/logging/utils.d.ts +1 -0
- package/dist/logging/utils.js +6 -0
- package/dist/migrations/index.d.ts +3 -3
- package/dist/migrations/index.js +3 -3
- package/dist/migrations/pending-rebuilds.d.ts +1 -1
- package/dist/migrations/pending-rebuilds.js +1 -1
- package/dist/migrations/pii-event-backfill.js +4 -1
- package/dist/observability/escape-hatch-report.d.ts +2 -1
- package/dist/observability/index.d.ts +7 -15
- package/dist/observability/index.js +4 -12
- package/dist/observability/metric-validator.js +1 -1
- package/dist/observability/metrics-handle.d.ts +0 -1
- package/dist/observability/metrics-handle.js +2 -15
- package/dist/observability/recording-tracer.d.ts +1 -2
- package/dist/observability/recording-tracer.js +0 -6
- package/dist/observability/sensitive-filter.d.ts +0 -2
- package/dist/observability/sensitive-filter.js +0 -29
- package/dist/pipeline/active-membership.d.ts +2 -1
- package/dist/pipeline/active-membership.js +6 -2
- package/dist/pipeline/append-event-core.d.ts +2 -1
- package/dist/pipeline/append-event-core.js +2 -2
- package/dist/pipeline/attach-outside-transaction.d.ts +3 -0
- package/dist/pipeline/attach-outside-transaction.js +13 -0
- package/dist/pipeline/auth-claims-resolver.d.ts +2 -1
- package/dist/pipeline/cascade-handler.d.ts +2 -1
- package/dist/pipeline/cascade-handler.js +3 -2
- package/dist/pipeline/config-accessor-factory.d.ts +1 -1
- package/dist/pipeline/config-accessor-factory.js +1 -1
- package/dist/pipeline/context-services.d.ts +56 -0
- package/dist/pipeline/context-services.js +73 -0
- package/dist/pipeline/dispatch-batch.d.ts +2 -1
- package/dist/pipeline/dispatch-batch.js +31 -18
- package/dist/pipeline/dispatch-query.js +5 -4
- package/dist/pipeline/dispatch-scope.d.ts +6 -0
- package/dist/pipeline/dispatch-scope.js +27 -0
- package/dist/pipeline/dispatch-shared.d.ts +13 -9
- package/dist/pipeline/dispatch-shared.js +75 -198
- package/dist/pipeline/dispatch-stream.js +8 -4
- package/dist/pipeline/dispatch-write.d.ts +2 -1
- package/dist/pipeline/dispatch-write.js +10 -8
- package/dist/pipeline/dispatcher-utils.d.ts +3 -1
- package/dist/pipeline/dispatcher-utils.js +8 -2
- package/dist/pipeline/dispatcher.d.ts +3 -2
- package/dist/pipeline/dispatcher.js +4 -3
- package/dist/pipeline/event-consumer-state.d.ts +0 -1
- package/dist/pipeline/event-dispatcher-delivery.d.ts +1 -1
- package/dist/pipeline/event-dispatcher-delivery.js +4 -2
- package/dist/pipeline/event-dispatcher.d.ts +2 -2
- package/dist/pipeline/event-dispatcher.js +7 -3
- package/dist/pipeline/event-retention.js +59 -56
- package/dist/pipeline/handler-access-error.js +2 -1
- package/dist/pipeline/handler-context-auth.d.ts +5 -6
- package/dist/pipeline/handler-context-auth.js +7 -4
- package/dist/pipeline/handler-context-config.d.ts +2 -5
- package/dist/pipeline/handler-context-config.js +2 -2
- package/dist/pipeline/handler-context-db.d.ts +32 -7
- package/dist/pipeline/handler-context-db.js +26 -17
- package/dist/pipeline/handler-context-dispatch.d.ts +13 -7
- package/dist/pipeline/handler-context-dispatch.js +9 -8
- package/dist/pipeline/handler-context-events.d.ts +22 -36
- package/dist/pipeline/handler-context-events.js +36 -31
- package/dist/pipeline/handler-context-member-resolution.d.ts +2 -0
- package/dist/pipeline/handler-context-member-resolution.js +110 -0
- package/dist/pipeline/handler-context-notify.d.ts +3 -2
- package/dist/pipeline/handler-context-notify.js +1 -1
- package/dist/pipeline/handler-context-observability.d.ts +2 -4
- package/dist/pipeline/handler-context-observability.js +7 -5
- package/dist/pipeline/handler-context-phase-denials.d.ts +11 -0
- package/dist/pipeline/handler-context-phase-denials.js +98 -0
- package/dist/pipeline/handler-context-scope.d.ts +7 -10
- package/dist/pipeline/handler-context-scope.js +18 -20
- package/dist/pipeline/index.d.ts +9 -21
- package/dist/pipeline/index.js +5 -7
- package/dist/pipeline/irreversible-operation-gate.d.ts +1 -1
- package/dist/pipeline/irreversible-operation-gate.js +2 -2
- package/dist/pipeline/lifecycle-pipeline.d.ts +8 -7
- package/dist/pipeline/lifecycle-pipeline.js +9 -15
- package/dist/pipeline/member-read-only-transaction.js +11 -3
- package/dist/pipeline/member-reader.d.ts +1 -1
- package/dist/pipeline/member-reader.js +2 -2
- package/dist/pipeline/msp-rebuild.js +5 -3
- package/dist/pipeline/multi-stream-apply-context.js +3 -2
- package/dist/pipeline/notify-scope.d.ts +2 -1
- package/dist/pipeline/pre-handler-gates.d.ts +2 -1
- package/dist/pipeline/pre-transaction-reservations.d.ts +3 -3
- package/dist/pipeline/pre-transaction-reservations.js +9 -7
- package/dist/pipeline/projection-rebuild.js +12 -5
- package/dist/pipeline/projection-state.d.ts +0 -6
- package/dist/pipeline/projection-state.js +0 -5
- package/dist/pipeline/projections-runner.d.ts +2 -1
- package/dist/pipeline/projections-runner.js +10 -6
- package/dist/pipeline/system-hooks.d.ts +3 -1
- package/dist/pipeline/system-hooks.js +6 -4
- package/dist/pipeline/system-identity-switch.d.ts +4 -2
- package/dist/pipeline/system-identity-switch.js +51 -36
- package/dist/pipeline/typed-append-event.d.ts +2 -0
- package/dist/pipeline/typed-append-event.js +4 -0
- package/dist/pipeline/write-origin.js +2 -2
- package/dist/pipeline/write-result-masking.d.ts +1 -1
- package/dist/random/index.d.ts +1 -2
- package/dist/random/index.js +1 -2
- package/dist/rate-limit/bucket.d.ts +2 -1
- package/dist/rate-limit/middleware.js +2 -1
- package/dist/redis/index.d.ts +3 -4
- package/dist/redis/index.js +2 -2
- package/dist/schema-cli/apply-command.js +5 -2
- package/dist/schema-cli/baseline-command.js +7 -2
- package/dist/schema-cli/generate-command.js +7 -9
- package/dist/schema-cli/shared.d.ts +12 -2
- package/dist/schema-cli/shared.js +24 -2
- package/dist/schema-cli/status-command.js +8 -2
- package/dist/schema-cli/validate-command.js +48 -4
- package/dist/schema-cli.d.ts +0 -1
- package/dist/search/configure-tenant-index.d.ts +1 -3
- package/dist/search/configure-tenant-index.js +0 -4
- package/dist/search/index.d.ts +1 -4
- package/dist/search/index.js +0 -2
- package/dist/search/meilisearch-adapter-internals.d.ts +8 -0
- package/dist/search/meilisearch-adapter-internals.js +9 -0
- package/dist/search/meilisearch-adapter.d.ts +1 -8
- package/dist/search/meilisearch-adapter.js +6 -7
- package/dist/search/meilisearch-peer.d.ts +2 -0
- package/dist/search/meilisearch-peer.js +5 -0
- package/dist/search/reindex-entity.js +93 -87
- package/dist/secrets/index.d.ts +3 -4
- package/dist/secrets/index.js +2 -3
- package/dist/seeding/index.d.ts +2 -2
- package/dist/seeding/index.js +1 -2
- package/dist/time/index.d.ts +2 -2
- package/dist/time/index.js +1 -1
- package/dist/time/tz-context.d.ts +0 -5
- package/dist/time/tz-context.js +0 -9
- package/dist/ui-types/index.d.ts +8 -11
- package/dist/ui-types/index.js +3 -3
- package/dist/upgrade-changelog.d.ts +3 -2
- package/dist/upgrade-changelog.js +12 -8
- package/dist/upgrade-cli-internals.d.ts +8 -0
- package/dist/upgrade-cli-internals.js +63 -0
- package/dist/upgrade-cli.d.ts +2 -9
- package/dist/upgrade-cli.js +28 -70
- package/dist/utils/import-optional-peer.d.ts +6 -0
- package/dist/utils/import-optional-peer.js +19 -0
- package/dist/utils/index.d.ts +1 -4
- package/dist/utils/index.js +1 -4
- package/package.json +23 -19
- package/src/changes.json +236 -0
- package/dist/crypto/request-kms-cache.d.ts +0 -8
- package/dist/crypto/request-kms-cache.js +0 -21
- package/dist/engine/codemod/index.d.ts +0 -2
- package/dist/engine/codemod/index.js +0 -1
- package/dist/engine/codemod/pipeline-codemod.d.ts +0 -50
- package/dist/engine/codemod/pipeline-codemod.js +0 -536
- package/dist/engine/feature-ast/entity-field-types.d.ts +0 -13
- package/dist/engine/feature-ast/entity-field-types.js +0 -35
- package/dist/engine/feature-ast/extractors/ai-steps.d.ts +0 -6
- package/dist/engine/feature-ast/extractors/ai-steps.js +0 -254
- package/dist/engine/feature-ast/extractors/events.d.ts +0 -5
- package/dist/engine/feature-ast/extractors/events.js +0 -275
- package/dist/engine/feature-ast/extractors/handlers.d.ts +0 -24
- package/dist/engine/feature-ast/extractors/handlers.js +0 -358
- package/dist/engine/feature-ast/extractors/hooks.d.ts +0 -24
- package/dist/engine/feature-ast/extractors/hooks.js +0 -248
- package/dist/engine/feature-ast/extractors/index.d.ts +0 -14
- package/dist/engine/feature-ast/extractors/index.js +0 -13
- package/dist/engine/feature-ast/extractors/jobs-routes.d.ts +0 -7
- package/dist/engine/feature-ast/extractors/jobs-routes.js +0 -145
- package/dist/engine/feature-ast/extractors/projections-screens.d.ts +0 -10
- package/dist/engine/feature-ast/extractors/projections-screens.js +0 -195
- package/dist/engine/feature-ast/extractors/resolve-import.d.ts +0 -21
- package/dist/engine/feature-ast/extractors/resolve-import.js +0 -180
- package/dist/engine/feature-ast/extractors/round1.d.ts +0 -11
- package/dist/engine/feature-ast/extractors/round1.js +0 -87
- package/dist/engine/feature-ast/extractors/round2.d.ts +0 -7
- package/dist/engine/feature-ast/extractors/round2.js +0 -191
- package/dist/engine/feature-ast/extractors/round3.d.ts +0 -23
- package/dist/engine/feature-ast/extractors/round3.js +0 -292
- package/dist/engine/feature-ast/extractors/round5.d.ts +0 -9
- package/dist/engine/feature-ast/extractors/round5.js +0 -68
- package/dist/engine/feature-ast/extractors/round6.d.ts +0 -4
- package/dist/engine/feature-ast/extractors/round6.js +0 -17
- package/dist/engine/feature-ast/extractors/shared.d.ts +0 -94
- package/dist/engine/feature-ast/extractors/shared.js +0 -343
- package/dist/engine/feature-ast/index.d.ts +0 -16
- package/dist/engine/feature-ast/index.js +0 -10
- package/dist/engine/feature-ast/parse.d.ts +0 -31
- package/dist/engine/feature-ast/parse.js +0 -485
- package/dist/engine/feature-ast/patch.d.ts +0 -212
- package/dist/engine/feature-ast/patch.js +0 -611
- package/dist/engine/feature-ast/patcher.d.ts +0 -217
- package/dist/engine/feature-ast/patcher.js +0 -281
- package/dist/engine/feature-ast/pattern-change-schema.d.ts +0 -1238
- package/dist/engine/feature-ast/pattern-change-schema.js +0 -1072
- package/dist/engine/feature-ast/pattern-id-matchers.d.ts +0 -7
- package/dist/engine/feature-ast/pattern-id-matchers.js +0 -211
- package/dist/engine/feature-ast/pattern-id-schema.d.ts +0 -251
- package/dist/engine/feature-ast/pattern-id-schema.js +0 -166
- package/dist/engine/feature-ast/patterns.d.ts +0 -322
- package/dist/engine/feature-ast/patterns.js +0 -107
- package/dist/engine/feature-ast/render.d.ts +0 -47
- package/dist/engine/feature-ast/render.js +0 -666
- package/dist/engine/feature-ast/source-location.d.ts +0 -17
- package/dist/engine/feature-ast/source-location.js +0 -27
- package/dist/engine/pattern-library/index.d.ts +0 -2
- package/dist/engine/pattern-library/index.js +0 -3
- package/dist/engine/pattern-library/library.d.ts +0 -14
- package/dist/engine/pattern-library/library.js +0 -94
- package/dist/engine/pattern-library/mixed-schemas.d.ts +0 -16
- package/dist/engine/pattern-library/mixed-schemas.js +0 -559
- package/dist/engine/pattern-library/opaque-schemas.d.ts +0 -7
- package/dist/engine/pattern-library/opaque-schemas.js +0 -115
- package/dist/engine/pattern-library/shared-fields.d.ts +0 -122
- package/dist/engine/pattern-library/shared-fields.js +0 -88
- package/dist/engine/pattern-library/static-schemas.d.ts +0 -21
- package/dist/engine/pattern-library/static-schemas.js +0 -487
- package/dist/engine/pattern-library/types.d.ts +0 -158
- package/dist/engine/pattern-library/types.js +0 -36
- package/dist/engine/resolve-config-or-param.d.ts +0 -18
- package/dist/engine/resolve-config-or-param.js +0 -76
- package/src/scripts/codemod/README.md +0 -187
- package/src/scripts/codemod/codemod-support.ts +0 -334
- package/src/scripts/codemod/collect-source-files.ts +0 -48
- package/src/scripts/codemod/crypto-shredding-testing-move.ts +0 -119
- package/src/scripts/codemod/db-factory.ts +0 -810
- package/src/scripts/codemod/feature-factory.ts +0 -429
- package/src/scripts/codemod/feature-layout.ts +0 -424
- package/src/scripts/codemod/import-extensions.ts +0 -118
- package/src/scripts/codemod/migrate-cross-tenant.ts +0 -328
- package/src/scripts/codemod/migrate-db-raw.ts +0 -401
- package/src/scripts/codemod/migrate-open-to-all.ts +0 -235
- package/src/scripts/codemod/object-form.ts +0 -746
- package/src/scripts/codemod/package-merge.ts +0 -299
- package/src/scripts/codemod/pii-personal-migration.ts +0 -816
- package/src/scripts/codemod/remove-engine-payload-casts.ts +0 -318
- package/src/scripts/codemod/s3-imports.ts +0 -236
- package/src/scripts/codemod/tenant-db-options.ts +0 -454
- package/src/scripts/codemod/testing-injection.ts +0 -215
- package/src/scripts/codemod/testing-move-targets.ts +0 -161
- package/src/scripts/codemod/testing-move.ts +0 -542
- package/src/scripts/codemod/unprocessable-error-details-reason.ts +0 -411
|
@@ -212,7 +212,7 @@ beforeAll(async () => {
|
|
|
212
212
|
// Wire ctx.config() so the branding query resolves the tenant's cascade.
|
|
213
213
|
extraContext: ({ registry }) => ({
|
|
214
214
|
configResolver: resolver,
|
|
215
|
-
|
|
215
|
+
configAccessorFactory: createConfigAccessorFactory(registry, resolver),
|
|
216
216
|
}),
|
|
217
217
|
});
|
|
218
218
|
await unsafeCreateEntityTable(stack.db, pageEntity);
|
|
@@ -38,7 +38,12 @@ bun test
|
|
|
38
38
|
|
|
39
39
|
import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
|
|
40
40
|
import { createTenantDb } from "@cosmicdrift/kumiko-framework/db";
|
|
41
|
-
import
|
|
41
|
+
import {
|
|
42
|
+
attachOutsideTransaction,
|
|
43
|
+
bridgeStub,
|
|
44
|
+
type HandlerContext,
|
|
45
|
+
type SaveContext,
|
|
46
|
+
} from "@cosmicdrift/kumiko-framework/engine";
|
|
42
47
|
import { createEventsTable } from "@cosmicdrift/kumiko-framework/event-store";
|
|
43
48
|
import { createCascadeDeleteHook } from "@cosmicdrift/kumiko-framework/pipeline";
|
|
44
49
|
import { TestUsers } from "@cosmicdrift/kumiko-framework/seeding";
|
|
@@ -77,6 +82,16 @@ beforeEach(() => {
|
|
|
77
82
|
stack.events.reset();
|
|
78
83
|
});
|
|
79
84
|
|
|
85
|
+
// The cascade hook runs against the same tenant-scoped db a dispatcher would hand it.
|
|
86
|
+
function hookContext(): HandlerContext {
|
|
87
|
+
const db = createTenantDb({ db: stack.db, tenantId: admin.tenantId });
|
|
88
|
+
return {
|
|
89
|
+
...bridgeStub({ user: admin }),
|
|
90
|
+
registry: stack.registry,
|
|
91
|
+
db: attachOutsideTransaction(db, undefined),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
80
95
|
describe("restrict: team cannot be deleted with members", () => {
|
|
81
96
|
test("delete team with members fails", async () => {
|
|
82
97
|
const team = await stack.http.writeOk<SaveContext>(
|
|
@@ -105,7 +120,7 @@ describe("restrict: team cannot be deleted with members", () => {
|
|
|
105
120
|
entityName: "team",
|
|
106
121
|
event: createTestStoredEvent(),
|
|
107
122
|
},
|
|
108
|
-
|
|
123
|
+
hookContext(),
|
|
109
124
|
),
|
|
110
125
|
).rejects.toMatchObject({ code: "conflict", details: { reason: "delete_restricted" } });
|
|
111
126
|
});
|
|
@@ -128,7 +143,7 @@ describe("restrict: team cannot be deleted with members", () => {
|
|
|
128
143
|
entityName: "team",
|
|
129
144
|
event: createTestStoredEvent(),
|
|
130
145
|
},
|
|
131
|
-
|
|
146
|
+
hookContext(),
|
|
132
147
|
),
|
|
133
148
|
).resolves.toBeUndefined();
|
|
134
149
|
});
|
|
@@ -178,7 +193,7 @@ describe("cascade: deleting member removes tasks", () => {
|
|
|
178
193
|
entityName: "member",
|
|
179
194
|
event: createTestStoredEvent(),
|
|
180
195
|
},
|
|
181
|
-
|
|
196
|
+
hookContext(),
|
|
182
197
|
);
|
|
183
198
|
|
|
184
199
|
// Tasks should be gone
|
|
@@ -13,7 +13,7 @@ Tenant-scoped full-text search (Meilisearch / in-memory adapter).
|
|
|
13
13
|
## What it shows
|
|
14
14
|
|
|
15
15
|
- `searchable` / `searchWeight` on fields
|
|
16
|
-
- Handler reads via `ctx.searchAdapter`
|
|
16
|
+
- Handler reads via `ctx.services.searchAdapter`
|
|
17
17
|
|
|
18
18
|
## Source
|
|
19
19
|
|
|
@@ -160,7 +160,7 @@ describe("search indexing", () => {
|
|
|
160
160
|
```ts
|
|
161
161
|
// Search Sample
|
|
162
162
|
// Shows: searchable fields, searchWeight, search via InMemory SearchAdapter.
|
|
163
|
-
// Each handler builds its executor inline so `ctx.searchAdapter` is read fresh
|
|
163
|
+
// Each handler builds its executor inline so `ctx.services.searchAdapter` is read fresh
|
|
164
164
|
// per call — tests swap the adapter between runs.
|
|
165
165
|
|
|
166
166
|
import { buildEntityTable, createEventStoreExecutor } from "@cosmicdrift/kumiko-framework/db";
|
|
@@ -198,7 +198,7 @@ export const productFeature = defineFeature("shop", (r) => {
|
|
|
198
198
|
}),
|
|
199
199
|
handler: async (event, ctx) => {
|
|
200
200
|
const crud = createEventStoreExecutor(productTable, productEntity, {
|
|
201
|
-
searchAdapter: ctx.searchAdapter,
|
|
201
|
+
searchAdapter: ctx.services.searchAdapter,
|
|
202
202
|
entityName: "product",
|
|
203
203
|
});
|
|
204
204
|
return crud.create(event.payload, event.user, ctx.db);
|
|
@@ -214,7 +214,7 @@ export const productFeature = defineFeature("shop", (r) => {
|
|
|
214
214
|
}),
|
|
215
215
|
handler: async (query, ctx) => {
|
|
216
216
|
const crud = createEventStoreExecutor(productTable, productEntity, {
|
|
217
|
-
searchAdapter: ctx.searchAdapter,
|
|
217
|
+
searchAdapter: ctx.services.searchAdapter,
|
|
218
218
|
entityName: "product",
|
|
219
219
|
});
|
|
220
220
|
return crud.list(query.payload, query.user, ctx.db);
|
|
@@ -12,7 +12,7 @@ Tenant-owned secrets with envelope encryption, DEK cache, and KEK rotation.
|
|
|
12
12
|
|
|
13
13
|
## What it shows
|
|
14
14
|
|
|
15
|
-
- `r.secret` + `ctx.secrets.get` (audited reads)
|
|
15
|
+
- `r.secret` + `ctx.services.secrets.get` (audited reads)
|
|
16
16
|
- Charge-style handler that never returns the plaintext key
|
|
17
17
|
|
|
18
18
|
## Source
|
|
@@ -39,7 +39,7 @@ bun test
|
|
|
39
39
|
// function calls into framework internals):
|
|
40
40
|
// 1. A TenantAdmin sets a secret over HTTP → DB holds only an envelope.
|
|
41
41
|
// 2. list handler returns a redacted preview, never plaintext.
|
|
42
|
-
// 3. Feature code (ctx.secrets.get) decrypts through the audited wrapper.
|
|
42
|
+
// 3. Feature code (ctx.services.secrets.get) decrypts through the audited wrapper.
|
|
43
43
|
// Every read writes a tenantSecretRead event to the events-table.
|
|
44
44
|
// 4. The response-guard catches accidental Secret<> leaks: a handler
|
|
45
45
|
// that tries to return the branded value triggers a 500 at the
|
|
@@ -129,7 +129,7 @@ beforeAll(async () => {
|
|
|
129
129
|
features: [createJobsFeature(), createSecretsFeature(), createBillingFeature(), leakyFeature],
|
|
130
130
|
// Typed masterKeyProvider option: lands in AppContext as a typed field,
|
|
131
131
|
// no Record<string, unknown>-via-extraContext. The rotation job reads
|
|
132
|
-
// it from ctx.masterKeyProvider directly.
|
|
132
|
+
// it from ctx.services.masterKeyProvider directly.
|
|
133
133
|
masterKeyProvider: providerRef,
|
|
134
134
|
extraContext: ({ db, registry }) => ({
|
|
135
135
|
// SecretsContext sees the mutable ref — any replace() flips what
|
|
@@ -299,7 +299,7 @@ describe("5. KEK rotation via the core job + real BullMQ dispatch", () => {
|
|
|
299
299
|
|
|
300
300
|
test("subsequent ctx.secrets.get after rotation still returns the original plaintext", async () => {
|
|
301
301
|
// Goes through the whole real stack: HTTP → dispatcher → billing
|
|
302
|
-
// handler → ctx.secrets.get → cached DEK-unwrap with V2 → decrypt.
|
|
302
|
+
// handler → ctx.services.secrets.get → cached DEK-unwrap with V2 → decrypt.
|
|
303
303
|
// If rotation broke anything, fingerprint would differ or the call
|
|
304
304
|
// would throw.
|
|
305
305
|
const result = await stack.http.writeOk<{ keyFingerprint: string }>(
|
|
@@ -328,7 +328,7 @@ describe("5. KEK rotation via the core job + real BullMQ dispatch", () => {
|
|
|
328
328
|
### src/feature.ts
|
|
329
329
|
|
|
330
330
|
```ts
|
|
331
|
-
// A miniature "billing" feature that reads a Stripe API key from ctx.secrets
|
|
331
|
+
// A miniature "billing" feature that reads a Stripe API key from ctx.services.secrets
|
|
332
332
|
// and simulates a charge. The point is to show how feature code uses the
|
|
333
333
|
// plaintext secret without ever exposing it to clients — the charge endpoint
|
|
334
334
|
// returns { chargeId } but never the apiKey.
|
|
@@ -357,7 +357,10 @@ const chargeWrite = defineWriteHandler({
|
|
|
357
357
|
}),
|
|
358
358
|
access: { roles: ["TenantAdmin", "User"] },
|
|
359
359
|
handler: async (event, ctx) => {
|
|
360
|
-
const secrets = requireSecretsContext(
|
|
360
|
+
const secrets = requireSecretsContext(
|
|
361
|
+
{ secrets: ctx.services.secrets, user: ctx.user },
|
|
362
|
+
"billing:write:charge",
|
|
363
|
+
);
|
|
361
364
|
// requireSecretsContext returned a wrapper that auto-fills the audit
|
|
362
365
|
// context (userId + "billing:write:charge") on every .get — the read
|
|
363
366
|
// lands in tenant_secret_reads without the handler having to remember.
|
|
@@ -510,7 +510,7 @@ export const INVOICE_EVENTS = {
|
|
|
510
510
|
// Qualifier used by the reducer to match events from the stream.
|
|
511
511
|
// `<const TShort>` preserves the literal-string at the call-site, so
|
|
512
512
|
// `eventName(INVOICE_EVENTS.sent)` carries `"billing:event:invoice-sent"`
|
|
513
|
-
// as a literal type. That literal is what `ctx.
|
|
513
|
+
// as a literal type. That literal is what `ctx.events.append({ type, ... })`
|
|
514
514
|
// strict-checks against the augmented `KumikoEventTypeMap`.
|
|
515
515
|
export function eventName<const TShort extends string>(
|
|
516
516
|
short: TShort,
|
|
@@ -927,7 +927,7 @@ export async function loadInvoiceState(
|
|
|
927
927
|
ctx: HandlerContext,
|
|
928
928
|
id: string,
|
|
929
929
|
): Promise<InvoiceState | null> {
|
|
930
|
-
const events = await ctx.
|
|
930
|
+
const events = await ctx.events.load(id);
|
|
931
931
|
if (events.length === 0) return null;
|
|
932
932
|
const state: InvoiceState = { ...initialInvoiceState };
|
|
933
933
|
for (const evt of events) reduceInvoice(state, evt);
|
|
@@ -158,7 +158,7 @@ beforeAll(async () => {
|
|
|
158
158
|
features: [createConfigFeature(), createTenantSettingsFeature(), invoiceFeature],
|
|
159
159
|
extraContext: ({ registry }) => ({
|
|
160
160
|
configResolver: resolver,
|
|
161
|
-
|
|
161
|
+
configAccessorFactory: createConfigAccessorFactory(registry, resolver),
|
|
162
162
|
}),
|
|
163
163
|
});
|
|
164
164
|
await unsafePushTables(stack.db, { configValuesTable });
|
|
@@ -173,7 +173,7 @@ import {
|
|
|
173
173
|
import { insertOne, selectMany } from "@cosmicdrift/kumiko-framework/db";
|
|
174
174
|
import { EXT_USER_DATA } from "@cosmicdrift/kumiko-framework/engine";
|
|
175
175
|
import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
|
|
176
|
-
import {
|
|
176
|
+
import { seedRowViaEventStore } from "@cosmicdrift/kumiko-testing/helpers";
|
|
177
177
|
import {
|
|
178
178
|
setupTestStack,
|
|
179
179
|
type TestStack,
|
|
@@ -183,8 +183,6 @@ import { noteEntity, notesFeature, notesTable } from "../feature";
|
|
|
183
183
|
|
|
184
184
|
let stack: TestStack;
|
|
185
185
|
|
|
186
|
-
const TENANT_SYSTEM = "00000000-0000-4000-8000-000000000001";
|
|
187
|
-
|
|
188
186
|
// Each test gets its own tenant and user, so rows from other tests never show up.
|
|
189
187
|
let testNumber = 0;
|
|
190
188
|
let TENANT_A = "";
|
|
@@ -231,9 +229,8 @@ function noteId(index: number): string {
|
|
|
231
229
|
}
|
|
232
230
|
|
|
233
231
|
async function seedAlice(opts: { gracePeriodEnd?: Instant; status?: string } = {}): Promise<void> {
|
|
234
|
-
await
|
|
232
|
+
await seedRowViaEventStore(stack.db, userTable, {
|
|
235
233
|
id: ALICE_ID,
|
|
236
|
-
tenantId: TENANT_SYSTEM,
|
|
237
234
|
email: ALICE_EMAIL,
|
|
238
235
|
passwordHash: "h",
|
|
239
236
|
displayName: "Alice",
|
|
@@ -243,7 +240,7 @@ async function seedAlice(opts: { gracePeriodEnd?: Instant; status?: string } = {
|
|
|
243
240
|
status: opts.status ?? USER_STATUS.Active,
|
|
244
241
|
gracePeriodEnd: opts.gracePeriodEnd ?? null,
|
|
245
242
|
});
|
|
246
|
-
await
|
|
243
|
+
await seedRowViaEventStore(stack.db, tenantMembershipsTable, {
|
|
247
244
|
tenantId: TENANT_A,
|
|
248
245
|
userId: ALICE_ID,
|
|
249
246
|
roles: '["Member"]',
|
|
@@ -325,7 +325,7 @@ describe("workflow-engine", () => {
|
|
|
325
325
|
});
|
|
326
326
|
|
|
327
327
|
it("webhook-delivery completes with exactly one dispatch request", async () => {
|
|
328
|
-
const ctx = {
|
|
328
|
+
const ctx = { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
|
|
329
329
|
|
|
330
330
|
const result = await startAndRunWorkflow({
|
|
331
331
|
runId: "wf-webhook-delivery-1",
|
|
@@ -339,7 +339,7 @@ describe("workflow-engine", () => {
|
|
|
339
339
|
});
|
|
340
340
|
|
|
341
341
|
expect(result.outcome).toBe("completed");
|
|
342
|
-
const dispatchRequests = ctx.
|
|
342
|
+
const dispatchRequests = ctx.events.unsafeAppend.mock.calls
|
|
343
343
|
.map(([event]) => event as { type: string; payload: Record<string, unknown> })
|
|
344
344
|
.filter((event) => event.type === STEP_DISPATCH_REQUESTED_TYPE);
|
|
345
345
|
expect(dispatchRequests).toHaveLength(1);
|
|
@@ -367,7 +367,7 @@ describe("workflow-engine", () => {
|
|
|
367
367
|
|
|
368
368
|
describe("workflow-runner", () => {
|
|
369
369
|
function makeAppendOnlyCtx() {
|
|
370
|
-
return {
|
|
370
|
+
return { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
|
|
371
371
|
}
|
|
372
372
|
|
|
373
373
|
it("startAndRunWorkflow writes run.started with Q7 snapshot fingerprint, then runs the pipeline to completion when no suspension", async () => {
|
|
@@ -386,15 +386,15 @@ describe("workflow-runner", () => {
|
|
|
386
386
|
});
|
|
387
387
|
|
|
388
388
|
expect(result.outcome).toBe("completed");
|
|
389
|
-
expect(ctx.
|
|
390
|
-
const started = ctx.
|
|
389
|
+
expect(ctx.events.unsafeAppend).toHaveBeenCalledTimes(2);
|
|
390
|
+
const started = ctx.events.unsafeAppend.mock.calls[0]![0] as {
|
|
391
391
|
type: string;
|
|
392
392
|
payload: Record<string, unknown>;
|
|
393
393
|
};
|
|
394
394
|
expect(started.type).toBe("kumiko:system:workflow.run-started");
|
|
395
395
|
expect(started.payload["definitionFingerprint"]).toBe(computeDefinitionFingerprint(workflow));
|
|
396
396
|
expect(started.payload["triggerEventType"]).toBe("demo.fired");
|
|
397
|
-
const completed = ctx.
|
|
397
|
+
const completed = ctx.events.unsafeAppend.mock.calls[1]![0] as { type: string };
|
|
398
398
|
expect(completed.type).toBe("kumiko:system:workflow.run-completed");
|
|
399
399
|
});
|
|
400
400
|
|
|
@@ -418,8 +418,8 @@ describe("workflow-runner", () => {
|
|
|
418
418
|
|
|
419
419
|
expect(result.outcome).toBe("suspended");
|
|
420
420
|
// run.started + workflow.step.waiting — no run-completed yet
|
|
421
|
-
expect(ctx.
|
|
422
|
-
const waiting = ctx.
|
|
421
|
+
expect(ctx.events.unsafeAppend).toHaveBeenCalledTimes(2);
|
|
422
|
+
const waiting = ctx.events.unsafeAppend.mock.calls[1]![0] as {
|
|
423
423
|
type: string;
|
|
424
424
|
payload: Record<string, unknown>;
|
|
425
425
|
};
|
|
@@ -444,14 +444,16 @@ describe("workflow-runner", () => {
|
|
|
444
444
|
handlerCtx: ctx as never,
|
|
445
445
|
});
|
|
446
446
|
|
|
447
|
-
const started = ctx.
|
|
447
|
+
const started = ctx.events.unsafeAppend.mock.calls[0]![0] as {
|
|
448
|
+
payload: Record<string, unknown>;
|
|
449
|
+
};
|
|
448
450
|
expect(started.payload["idempotencyKey"]).toBe("id:abc");
|
|
449
451
|
});
|
|
450
452
|
});
|
|
451
453
|
|
|
452
454
|
describe("userOnboardingWorkflow (end-to-end, in-memory)", () => {
|
|
453
455
|
it("suspends on the first wait, then resume-loop runs it through to completion", async () => {
|
|
454
|
-
const ctx = {
|
|
456
|
+
const ctx = { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
|
|
455
457
|
const trigger = {
|
|
456
458
|
aggregateId: "agg_user_42",
|
|
457
459
|
type: "user.signed-up",
|
|
@@ -469,16 +471,16 @@ describe("userOnboardingWorkflow (end-to-end, in-memory)", () => {
|
|
|
469
471
|
|
|
470
472
|
expect(result.outcome).toBe("suspended");
|
|
471
473
|
// Calls: run.started, mail.send dispatch-requested, workflow.step.waiting
|
|
472
|
-
expect(ctx.
|
|
473
|
-
const startedCall = ctx.
|
|
474
|
+
expect(ctx.events.unsafeAppend).toHaveBeenCalledTimes(3);
|
|
475
|
+
const startedCall = ctx.events.unsafeAppend.mock.calls[0]![0] as {
|
|
474
476
|
type: string;
|
|
475
477
|
payload: Record<string, unknown>;
|
|
476
478
|
};
|
|
477
|
-
const mailCall = ctx.
|
|
479
|
+
const mailCall = ctx.events.unsafeAppend.mock.calls[1]![0] as {
|
|
478
480
|
type: string;
|
|
479
481
|
payload: Record<string, unknown>;
|
|
480
482
|
};
|
|
481
|
-
const waitingCall = ctx.
|
|
483
|
+
const waitingCall = ctx.events.unsafeAppend.mock.calls[2]![0] as {
|
|
482
484
|
type: string;
|
|
483
485
|
payload: Record<string, unknown>;
|
|
484
486
|
};
|
|
@@ -514,7 +516,7 @@ describe("userOnboardingWorkflow (end-to-end, in-memory)", () => {
|
|
|
514
516
|
definitionFingerprint: waitingCall.payload["definitionFingerprint"] as string,
|
|
515
517
|
};
|
|
516
518
|
|
|
517
|
-
const resumeCtx = {
|
|
519
|
+
const resumeCtx = { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
|
|
518
520
|
const count = await runResumeLoop(
|
|
519
521
|
createInMemorySuspendedRunFetcher([suspendedRun]),
|
|
520
522
|
resumeCtx as never,
|
|
@@ -525,7 +527,7 @@ describe("userOnboardingWorkflow (end-to-end, in-memory)", () => {
|
|
|
525
527
|
// because userId starts with "active-"), second WAITING for P7D.
|
|
526
528
|
// The run is suspended again before the webhook, so no RUN_COMPLETED
|
|
527
529
|
// yet — this is one resume-cycle, not the whole workflow.
|
|
528
|
-
const resumeTypes = resumeCtx.
|
|
530
|
+
const resumeTypes = resumeCtx.events.unsafeAppend.mock.calls.map(
|
|
529
531
|
(c) => (c[0] as { type: string }).type,
|
|
530
532
|
);
|
|
531
533
|
expect(resumeTypes).toEqual([
|
|
@@ -533,14 +535,14 @@ describe("userOnboardingWorkflow (end-to-end, in-memory)", () => {
|
|
|
533
535
|
"kumiko:system:step.dispatch-requested",
|
|
534
536
|
"kumiko:system:workflow.step.waiting",
|
|
535
537
|
]);
|
|
536
|
-
const tipsMail = resumeCtx.
|
|
538
|
+
const tipsMail = resumeCtx.events.unsafeAppend.mock.calls[1]![0] as {
|
|
537
539
|
payload: { subject: string };
|
|
538
540
|
};
|
|
539
541
|
expect(tipsMail.payload.subject).toBe("Engagement tips");
|
|
540
542
|
});
|
|
541
543
|
|
|
542
544
|
it("not-engaged path picks the reminder branch", async () => {
|
|
543
|
-
const ctx = {
|
|
545
|
+
const ctx = { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
|
|
544
546
|
const trigger = {
|
|
545
547
|
aggregateId: "agg_user_cold",
|
|
546
548
|
type: "user.signed-up",
|
|
@@ -553,7 +555,9 @@ describe("userOnboardingWorkflow (end-to-end, in-memory)", () => {
|
|
|
553
555
|
triggerEventRef: { eventId: "2", aggregateId: trigger.aggregateId, version: 1 },
|
|
554
556
|
handlerCtx: ctx as never,
|
|
555
557
|
});
|
|
556
|
-
const waiting = ctx.
|
|
558
|
+
const waiting = ctx.events.unsafeAppend.mock.calls[2]![0] as {
|
|
559
|
+
payload: Record<string, unknown>;
|
|
560
|
+
};
|
|
557
561
|
const suspendedRun: SuspendableRun = {
|
|
558
562
|
runId: "wf-onboarding-cold-1",
|
|
559
563
|
workflowName: "user-onboarding",
|
|
@@ -564,10 +568,10 @@ describe("userOnboardingWorkflow (end-to-end, in-memory)", () => {
|
|
|
564
568
|
triggerEvent: trigger as never,
|
|
565
569
|
definitionFingerprint: waiting.payload["definitionFingerprint"] as string,
|
|
566
570
|
};
|
|
567
|
-
const resumeCtx = {
|
|
571
|
+
const resumeCtx = { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
|
|
568
572
|
await runResumeLoop(createInMemorySuspendedRunFetcher([suspendedRun]), resumeCtx as never);
|
|
569
573
|
|
|
570
|
-
const reminderMail = resumeCtx.
|
|
574
|
+
const reminderMail = resumeCtx.events.unsafeAppend.mock.calls[1]![0] as {
|
|
571
575
|
payload: { subject: string };
|
|
572
576
|
};
|
|
573
577
|
expect(reminderMail.payload.subject).toBe("Getting started");
|
|
@@ -696,7 +700,7 @@ describe("cron-scheduler", () => {
|
|
|
696
700
|
steps: stepsPipeline(({ r }) => [r.step.return({ isSuccess: true, data: undefined })]),
|
|
697
701
|
});
|
|
698
702
|
|
|
699
|
-
const handlerCtx = {
|
|
703
|
+
const handlerCtx = { events: { unsafeAppend: mock() } };
|
|
700
704
|
const lastRuns = new Map<string, Temporal.Instant>();
|
|
701
705
|
const now = Temporal.Instant.from("2025-06-01T08:00:00Z");
|
|
702
706
|
|
|
@@ -708,7 +712,7 @@ describe("cron-scheduler", () => {
|
|
|
708
712
|
);
|
|
709
713
|
|
|
710
714
|
expect(count).toBe(0);
|
|
711
|
-
expect(handlerCtx.
|
|
715
|
+
expect(handlerCtx.events.unsafeAppend).not.toHaveBeenCalled();
|
|
712
716
|
});
|
|
713
717
|
|
|
714
718
|
it("runDueCronWorkflows runs due workflows through the full start path", async () => {
|
|
@@ -718,7 +722,7 @@ describe("cron-scheduler", () => {
|
|
|
718
722
|
steps: stepsPipeline(({ r }) => [r.step.return({ isSuccess: true, data: undefined })]),
|
|
719
723
|
});
|
|
720
724
|
|
|
721
|
-
const handlerCtx = {
|
|
725
|
+
const handlerCtx = { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
|
|
722
726
|
const lastRuns = new Map<string, Temporal.Instant>();
|
|
723
727
|
const lastRun = Temporal.Instant.from("2025-05-31T08:00:00Z");
|
|
724
728
|
lastRuns.set("test-daily", lastRun);
|
|
@@ -733,10 +737,10 @@ describe("cron-scheduler", () => {
|
|
|
733
737
|
|
|
734
738
|
expect(count).toBe(1);
|
|
735
739
|
// run.started + run-completed (no suspension, pipeline returns immediately).
|
|
736
|
-
expect(handlerCtx.
|
|
737
|
-
const started = handlerCtx.
|
|
740
|
+
expect(handlerCtx.events.unsafeAppend).toHaveBeenCalledTimes(2);
|
|
741
|
+
const started = handlerCtx.events.unsafeAppend.mock.calls[0]![0] as Record<string, unknown>;
|
|
738
742
|
expect(started["type"]).toBe("kumiko:system:workflow.run-started");
|
|
739
|
-
const completed = handlerCtx.
|
|
743
|
+
const completed = handlerCtx.events.unsafeAppend.mock.calls[1]![0] as Record<string, unknown>;
|
|
740
744
|
expect(completed["type"]).toBe("kumiko:system:workflow.run-completed");
|
|
741
745
|
});
|
|
742
746
|
});
|
|
@@ -744,12 +748,12 @@ describe("cron-scheduler", () => {
|
|
|
744
748
|
describe("resume-loop", () => {
|
|
745
749
|
it("returns 0 when no suspended runs exist", async () => {
|
|
746
750
|
const fetchRuns = createInMemorySuspendedRunFetcher([]);
|
|
747
|
-
const handlerCtx = {
|
|
751
|
+
const handlerCtx = { events: { unsafeAppend: mock() } };
|
|
748
752
|
|
|
749
753
|
const count = await runResumeLoop(fetchRuns, handlerCtx as never);
|
|
750
754
|
|
|
751
755
|
expect(count).toBe(0);
|
|
752
|
-
expect(handlerCtx.
|
|
756
|
+
expect(handlerCtx.events.unsafeAppend).not.toHaveBeenCalled();
|
|
753
757
|
});
|
|
754
758
|
|
|
755
759
|
it("resumes a suspended run", async () => {
|
|
@@ -766,19 +770,19 @@ describe("resume-loop", () => {
|
|
|
766
770
|
};
|
|
767
771
|
|
|
768
772
|
const fetchRuns = createInMemorySuspendedRunFetcher([suspendedRun]);
|
|
769
|
-
const handlerCtx = {
|
|
773
|
+
const handlerCtx = { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
|
|
770
774
|
|
|
771
775
|
const count = await runResumeLoop(fetchRuns, handlerCtx as never);
|
|
772
776
|
|
|
773
777
|
expect(count).toBe(1);
|
|
774
|
-
expect(handlerCtx.
|
|
775
|
-
expect(handlerCtx.
|
|
778
|
+
expect(handlerCtx.events.unsafeAppend).toHaveBeenCalledTimes(2);
|
|
779
|
+
expect(handlerCtx.events.unsafeAppend).toHaveBeenNthCalledWith(1, {
|
|
776
780
|
aggregateId: "wf-test-run_123",
|
|
777
781
|
aggregateType: "workflow-run",
|
|
778
782
|
type: "kumiko:system:workflow.step.resumed",
|
|
779
783
|
payload: { stepIndex: 0, retryAttempt: undefined },
|
|
780
784
|
});
|
|
781
|
-
expect(handlerCtx.
|
|
785
|
+
expect(handlerCtx.events.unsafeAppend).toHaveBeenNthCalledWith(2, {
|
|
782
786
|
aggregateId: "wf-test-run_123",
|
|
783
787
|
aggregateType: "workflow-run",
|
|
784
788
|
type: "kumiko:system:workflow.run-completed",
|
|
@@ -800,13 +804,13 @@ describe("resume-loop", () => {
|
|
|
800
804
|
};
|
|
801
805
|
|
|
802
806
|
const fetchRuns = createInMemorySuspendedRunFetcher([suspendedRun]);
|
|
803
|
-
const handlerCtx = {
|
|
807
|
+
const handlerCtx = { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
|
|
804
808
|
|
|
805
809
|
const count = await runResumeLoop(fetchRuns, handlerCtx as never);
|
|
806
810
|
|
|
807
811
|
expect(count).toBe(0);
|
|
808
|
-
expect(handlerCtx.
|
|
809
|
-
const failed = handlerCtx.
|
|
812
|
+
expect(handlerCtx.events.unsafeAppend).toHaveBeenCalledTimes(1);
|
|
813
|
+
const failed = handlerCtx.events.unsafeAppend.mock.calls[0]![0] as {
|
|
810
814
|
type: string;
|
|
811
815
|
payload: Record<string, unknown>;
|
|
812
816
|
};
|
|
@@ -830,16 +834,18 @@ describe("resume-loop", () => {
|
|
|
830
834
|
|
|
831
835
|
const fetchRuns = createInMemorySuspendedRunFetcher([suspendedRun]);
|
|
832
836
|
const handlerCtx = {
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
837
|
+
events: {
|
|
838
|
+
unsafeAppend: mock()
|
|
839
|
+
.mockRejectedValueOnce(new VersionConflictError("wf-conflict-run", 1))
|
|
840
|
+
.mockResolvedValue(undefined),
|
|
841
|
+
},
|
|
836
842
|
};
|
|
837
843
|
|
|
838
844
|
const count = await runResumeLoop(fetchRuns, handlerCtx as never);
|
|
839
845
|
|
|
840
846
|
expect(count).toBe(0);
|
|
841
|
-
expect(handlerCtx.
|
|
842
|
-
expect((handlerCtx.
|
|
847
|
+
expect(handlerCtx.events.unsafeAppend).toHaveBeenCalledTimes(1);
|
|
848
|
+
expect((handlerCtx.events.unsafeAppend.mock.calls[0]![0] as { type: string }).type).toBe(
|
|
843
849
|
"kumiko:system:workflow.step.resumed",
|
|
844
850
|
);
|
|
845
851
|
});
|
|
@@ -1509,7 +1515,7 @@ export async function runResumeLoop(
|
|
|
1509
1515
|
if (run.definitionFingerprint !== undefined) {
|
|
1510
1516
|
const currentFingerprint = computeDefinitionFingerprint(run.workflow);
|
|
1511
1517
|
if (currentFingerprint !== run.definitionFingerprint) {
|
|
1512
|
-
await handlerCtx.
|
|
1518
|
+
await handlerCtx.events.unsafeAppend({
|
|
1513
1519
|
aggregateId: run.runId,
|
|
1514
1520
|
aggregateType: WORKFLOW_AGGREGATE_TYPE,
|
|
1515
1521
|
type: WORKFLOW_RUN_FAILED_TYPE,
|
|
@@ -1537,7 +1543,7 @@ export async function runResumeLoop(
|
|
|
1537
1543
|
// no FAILED-event. Stale WAITING-rows in the fetcher result also
|
|
1538
1544
|
// hit this branch on the second poll-tick.
|
|
1539
1545
|
try {
|
|
1540
|
-
await handlerCtx.
|
|
1546
|
+
await handlerCtx.events.unsafeAppend({
|
|
1541
1547
|
aggregateId: run.runId,
|
|
1542
1548
|
aggregateType: WORKFLOW_AGGREGATE_TYPE,
|
|
1543
1549
|
type: WORKFLOW_RESUMED_TYPE,
|
|
@@ -1589,7 +1595,7 @@ export async function runResumeLoop(
|
|
|
1589
1595
|
// returned. A second suspension (e.g. `wait` further down the
|
|
1590
1596
|
// pipeline) leaves the run pending for the next resume-loop tick.
|
|
1591
1597
|
if (outcome.kind !== "suspended") {
|
|
1592
|
-
await handlerCtx.
|
|
1598
|
+
await handlerCtx.events.unsafeAppend({
|
|
1593
1599
|
aggregateId: run.runId,
|
|
1594
1600
|
aggregateType: WORKFLOW_AGGREGATE_TYPE,
|
|
1595
1601
|
type: WORKFLOW_RUN_COMPLETED_TYPE,
|
|
@@ -1606,7 +1612,7 @@ export async function runResumeLoop(
|
|
|
1606
1612
|
stepIndex: run.stepIndex,
|
|
1607
1613
|
error: String(error),
|
|
1608
1614
|
});
|
|
1609
|
-
await handlerCtx.
|
|
1615
|
+
await handlerCtx.events.unsafeAppend({
|
|
1610
1616
|
aggregateId: run.runId,
|
|
1611
1617
|
aggregateType: WORKFLOW_AGGREGATE_TYPE,
|
|
1612
1618
|
type: WORKFLOW_RUN_FAILED_TYPE,
|
|
@@ -1697,7 +1703,7 @@ export async function startAndRunWorkflow(args: {
|
|
|
1697
1703
|
...(args.idempotencyKey && { idempotencyKey: args.idempotencyKey }),
|
|
1698
1704
|
};
|
|
1699
1705
|
|
|
1700
|
-
await args.handlerCtx.
|
|
1706
|
+
await args.handlerCtx.events.unsafeAppend({
|
|
1701
1707
|
aggregateId: args.runId,
|
|
1702
1708
|
aggregateType: WORKFLOW_AGGREGATE_TYPE,
|
|
1703
1709
|
type: WORKFLOW_RUN_STARTED_TYPE,
|
|
@@ -1724,7 +1730,7 @@ export async function startAndRunWorkflow(args: {
|
|
|
1724
1730
|
return { outcome: "suspended" };
|
|
1725
1731
|
}
|
|
1726
1732
|
|
|
1727
|
-
await args.handlerCtx.
|
|
1733
|
+
await args.handlerCtx.events.unsafeAppend({
|
|
1728
1734
|
aggregateId: args.runId,
|
|
1729
1735
|
aggregateType: WORKFLOW_AGGREGATE_TYPE,
|
|
1730
1736
|
type: WORKFLOW_RUN_COMPLETED_TYPE,
|
package/agents/examples.md
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
| `chat-channels` | Chat channels. Delivery notifications to Slack, minus the browser tab. | `examples/chat-channels.md` |
|
|
20
20
|
| `compliance-profiles-demo` | Two-tenant demo: EU + Swiss compliance profiles deliver different authority contacts, languages, and grace periods through the same App-code. | `examples/compliance-profiles-demo.md` |
|
|
21
21
|
| `compose-stacks` | compose*Stack helpers for auth, security, GDPR and SaaS billing, and the runProdApp check that names a stack whose boot option is missing. | `examples/compose-stacks.md` |
|
|
22
|
-
| `cross-feature-events` | Feature appends a typed domain event via ctx.
|
|
22
|
+
| `cross-feature-events` | Feature appends a typed domain event via ctx.events.append; a r.multiStreamProjection reacts asynchronously. | `examples/cross-feature-events.md` |
|
|
23
23
|
| `crypto-shredding-hr` | Crypto-shredding: PII fields encrypted per subject key; forgetting the subject erases the key and every field it protected. | `examples/crypto-shredding-hr.md` |
|
|
24
24
|
| `currencies-global` | Shared money fields across tenants. Commas still matter. | `examples/currencies-global.md` |
|
|
25
25
|
| `currencies-per-tenant` | Tenant-scoped money fields. Commas matter. | `examples/currencies-per-tenant.md` |
|
|
@@ -34,16 +34,16 @@
|
|
|
34
34
|
| `encrypted-tenant-config` | Per-tenant secrets via config-key encryption — Stripe-API-key pattern. | `examples/encrypted-tenant-config.md` |
|
|
35
35
|
| `env-composition` | Typed app env from the env blocks bundled features register, plus app-level blocks in extend. | `examples/env-composition.md` |
|
|
36
36
|
| `error-contract` | Typed errors on the wire. With snake_case reasons, because we care. | `examples/error-contract.md` |
|
|
37
|
-
| `event-sourcing` | Production-pattern ES sample: r.defineEvent (versioned + migrations) + ctx.
|
|
37
|
+
| `event-sourcing` | Production-pattern ES sample: r.defineEvent (versioned + migrations) + ctx.events.append + r.projection + r.multiStreamProjection + ctx.events.load (asOf) + ctx.events.archive + ctx.dispatch.queryProjection. | `examples/event-sourcing.md` |
|
|
38
38
|
| `feature-toggles` | Runtime feature-toggle flip — two toggleable features, one registers a cross-feature hook on the other; disabling either has the documented effect without reboot. | `examples/feature-toggles.md` |
|
|
39
39
|
| `field-access` | Field-level access control. When entity-level roles aren't granular enough. | `examples/field-access.md` |
|
|
40
|
-
| `files-post-processing` | The three ways to generate an image variant: declarative field variants, imperative ctx.derivatives.variant() with region-blur, and the public route behind a default-deny predicate. | `examples/files-post-processing.md` |
|
|
40
|
+
| `files-post-processing` | The three ways to generate an image variant: declarative field variants, imperative ctx.services.derivatives.variant() with region-blur, and the public route behind a default-deny predicate. | `examples/files-post-processing.md` |
|
|
41
41
|
| `golden-path` | The smallest complete feature: entity, write handler, event, projection, screen and an integration test. | `examples/golden-path.md` |
|
|
42
42
|
| `host-routing` | createHostRoutingFeature + createHostDispatch — tenant per subdomain, per-host HTML and CSP, locale redirect, shared by runProdApp and the dev server. | `examples/host-routing.md` |
|
|
43
43
|
| `i18n` | Feature-scoped translations. 'Hallo' and 'Hello' in the same app. | `examples/i18n.md` |
|
|
44
44
|
| `idempotency` | Same request, same result. Dedupes on request ID. | `examples/idempotency.md` |
|
|
45
45
|
| `inbound-mail-triage` | Inbound-mail consumer pattern: inbound-mail-foundation + in-memory provider, a worker-lane triage job attached to the ingest handler, verified end-to-end through createAllInOneEntrypoint. | `examples/inbound-mail-triage.md` |
|
|
46
|
-
| `lane-routing` | runIn lane-routing: r.job pinned to api/worker deploy-lanes, event-chain via ctx.
|
|
46
|
+
| `lane-routing` | runIn lane-routing: r.job pinned to api/worker deploy-lanes, event-chain via ctx.events.append, verified end-to-end through createAllInOneEntrypoint. | `examples/lane-routing.md` |
|
|
47
47
|
| `ledger-banking` | Bank accounts + transfers on the ledger primitive — balances are pure queries, never stored. | `examples/ledger-banking.md` |
|
|
48
48
|
| `ledger-invoicing` | Accrual invoicing on the ledger primitive — revenue at invoice time, VAT as a liability, receivable cleared on payment. | `examples/ledger-invoicing.md` |
|
|
49
49
|
| `legal-pages` | Auto-rendered Impressum + Datenschutzerklärung pages — template-resolver + legal-pages bundled features wired up with anonymousAccess for DACH-compliance. | `examples/legal-pages.md` |
|
package/agents/features.md
CHANGED
|
@@ -257,7 +257,7 @@ Category: operations
|
|
|
257
257
|
|
|
258
258
|
## file-derivatives
|
|
259
259
|
|
|
260
|
-
Declares the `derivativeRenderer` extension point. `ctx.derivatives.variant(fileRefId, spec, name)` derives a variant of a tracked FileRef the first time it's requested and reuses the stored result afterwards (derive-on-first-use, keyed by a hash of the spec). Mount at least one `derivatives-*` renderer feature alongside this one — without a registered renderer for the FileRef's MIME type, every `variant(...)` call throws. Also declares the `derivativePublicPredicate` extension point (`r.useExtension(EXT_DERIVATIVE_PUBLIC_PREDICATE, '<entityType>', { isPublic })`) and, when `createFileDerivativesFeature({resolveApexTenant})` is passed a host-resolver, mounts an anonymous `GET {basePath}/:fileRefId/:variant` route that serves any variant name the FileRef's field declared in its `variants` for a FileRef whose entityType has a registered predicate returning true — default-deny (404) otherwise, same as an unknown FileRef or an undeclared variant name. The route's only rate-limit (`per: "ip"`) depends on the server's `trustedProxyHops` matching the deployment's actual reverse-proxy count — at the default 0 it ignores `x-forwarded-for` entirely, so every caller shares one bucket until that's configured. `publicTenantResolution: "fileRef"` keeps resolveApexTenant as the host gate but reads the variant from the FileRef row's own tenant instead of the host's, so one shared platform host serves every tenant's public variants — each FileRef-tenant's own `isPublic` predicate still default-denies. Also declares the `derivativeOverlayResolver` extension point (`r.useExtension(EXT_DERIVATIVE_OVERLAY_RESOLVER, '<entityType>', { resolve })`), used to turn a variant's `overlays[].dataToken` into the actual QR payload for that FileRef's entityType before the variant is rendered — a variant declaring a `qr` overlay throws at request-time if no resolver is registered for the FileRef's entityType.
|
|
260
|
+
Declares the `derivativeRenderer` extension point. `ctx.services.derivatives.variant(fileRefId, spec, name)` derives a variant of a tracked FileRef the first time it's requested and reuses the stored result afterwards (derive-on-first-use, keyed by a hash of the spec). Mount at least one `derivatives-*` renderer feature alongside this one — without a registered renderer for the FileRef's MIME type, every `variant(...)` call throws. Also declares the `derivativePublicPredicate` extension point (`r.useExtension(EXT_DERIVATIVE_PUBLIC_PREDICATE, '<entityType>', { isPublic })`) and, when `createFileDerivativesFeature({resolveApexTenant})` is passed a host-resolver, mounts an anonymous `GET {basePath}/:fileRefId/:variant` route that serves any variant name the FileRef's field declared in its `variants` for a FileRef whose entityType has a registered predicate returning true — default-deny (404) otherwise, same as an unknown FileRef or an undeclared variant name. The route's only rate-limit (`per: "ip"`) depends on the server's `trustedProxyHops` matching the deployment's actual reverse-proxy count — at the default 0 it ignores `x-forwarded-for` entirely, so every caller shares one bucket until that's configured. `publicTenantResolution: "fileRef"` keeps resolveApexTenant as the host gate but reads the variant from the FileRef row's own tenant instead of the host's, so one shared platform host serves every tenant's public variants — each FileRef-tenant's own `isPublic` predicate still default-denies. Also declares the `derivativeOverlayResolver` extension point (`r.useExtension(EXT_DERIVATIVE_OVERLAY_RESOLVER, '<entityType>', { resolve })`), used to turn a variant's `overlays[].dataToken` into the actual QR payload for that FileRef's entityType before the variant is rendered — a variant declaring a `qr` overlay throws at request-time if no resolver is registered for the FileRef's entityType.
|
|
261
261
|
|
|
262
262
|
Category: storage
|
|
263
263
|
|
|
@@ -5,7 +5,7 @@ import { createAnonymousUser } from "../engine/system-user.js";
|
|
|
5
5
|
import { parseTenantId, SYSTEM_TENANT_ID } from "../engine/types/identifiers.js";
|
|
6
6
|
import { isSessionRequiredApiPath, TENANT_HEADER_NAME } from "./api-constants.js";
|
|
7
7
|
import { isForeignCookieOrigin } from "./origin-middleware.js";
|
|
8
|
-
import { setRequestIdentity } from "./request-context.js";
|
|
8
|
+
import { setRequestIdentity } from "./request-context-internals.js";
|
|
9
9
|
import { clearSessionCookies, getSessionCookies, hasDuplicateSessionCookie, } from "./session-cookies.js";
|
|
10
10
|
const USER_KEY = "pipelineUser";
|
|
11
11
|
const AUTH_TRANSPORT_KEY = "authTransport";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
2
|
import { createAnonymousUser } from "../engine/system-user.js";
|
|
3
3
|
import { SYSTEM_TENANT_ID } from "../engine/types/index.js";
|
|
4
|
-
import { toKumikoError
|
|
4
|
+
import { toKumikoError } from "../errors/to-kumiko-error.js";
|
|
5
|
+
import { toWriteErrorInfo } from "../errors/write-error-info.js";
|
|
5
6
|
import { Routes } from "./api-constants.js";
|
|
6
7
|
import { getUser } from "./auth-middleware.js";
|
|
7
8
|
import { pendingMfaStepResponse } from "./auth-routes-shared.js";
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
import type { AccessRule
|
|
1
|
+
import type { AccessRule } from "@cosmicdrift/kumiko-types/handlers";
|
|
2
|
+
import type { OwnershipMap } from "@cosmicdrift/kumiko-types/ownership";
|
|
3
|
+
import type { Registry } from "../engine/types/index.ts";
|
|
2
4
|
export declare function collectEntityReadAccess(registry: Registry): ReadonlyMap<string, readonly AccessRule[]>;
|
|
3
5
|
export declare function collectEntityRowReadMaps(registry: Registry): ReadonlyMap<string, OwnershipMap>;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type { EntityDefinition
|
|
1
|
+
import type { EntityDefinition } from "@cosmicdrift/kumiko-types/fields";
|
|
2
|
+
import type { ListColumnSpec } from "@cosmicdrift/kumiko-types/screen";
|
|
3
|
+
import type { SessionUser } from "../../engine/types/index.ts";
|
|
2
4
|
import type { ReferenceCellKind } from "./export-cells-reference.ts";
|
|
3
5
|
export type SimpleCellKind = "text" | "number" | "decimal" | "bigInt" | "money" | "date" | "timestamp" | "locatedTimestamp" | "boolean" | "auto";
|
|
4
6
|
export type ExportCellKind = {
|