@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
package/agents/widgets.md
CHANGED
|
@@ -16,11 +16,12 @@ Value exports of `@cosmicdrift/kumiko-renderer/web`.
|
|
|
16
16
|
| `BareFormProvider` | |
|
|
17
17
|
| `BooleanField` | Checkbox/Switch = Field(layout:"inline") + Input(kind:"boolean"). |
|
|
18
18
|
| `Card` | |
|
|
19
|
-
| `
|
|
20
|
-
| `
|
|
21
|
-
| `
|
|
19
|
+
| `ChoiceCards` | Card-styled radio group for mutually exclusive choices that need a description or price line. |
|
|
20
|
+
| `CollapsibleSection` | Collapsible section using native <details> with React-controlled state; otherwise the open attribute resets to its initial value on every parent re-render. |
|
|
21
|
+
| `ComparisonTable` | Transposed comparison table: row = metric, column = variant, with the best column optionally highlighted for each metric. |
|
|
22
|
+
| `DateField` | Date field = Field + Input(kind:"date"), ISO yyyy-mm-dd. |
|
|
22
23
|
| `DefaultAppShell` | |
|
|
23
|
-
| `DetailList` | Read-only
|
|
24
|
+
| `DetailList` | Read-only key-value list for detail views (dimmed label on the left, value on the right). |
|
|
24
25
|
| `DispatcherProvider` | |
|
|
25
26
|
| `Drawer` | Slide-in panel beside a list (e.g. mail reader next to the inbox) — thin wrapper over the Sheet primitive with header/body/footer slots so screens skip per-route Radix boilerplate. |
|
|
26
27
|
| `DropdownMenu` | |
|
|
@@ -32,10 +33,10 @@ Value exports of `@cosmicdrift/kumiko-renderer/web`.
|
|
|
32
33
|
| `DropdownMenuSeparator` | |
|
|
33
34
|
| `DropdownMenuTrigger` | |
|
|
34
35
|
| `EditorPanel` | |
|
|
35
|
-
| `EmptyState` |
|
|
36
|
-
| `ErrorState` |
|
|
37
|
-
| `FeedList` |
|
|
38
|
-
| `FileField` |
|
|
36
|
+
| `EmptyState` | Empty state with an optional icon and CTA, using the dashed-box style of entityList empty states as a standalone widget for custom screens. |
|
|
37
|
+
| `ErrorState` | Error state based on the Banner primitive, with a retry button. |
|
|
38
|
+
| `FeedList` | Non-tabular compact list (e.g. "upcoming appointments") — primary text plus an optional right-aligned trailing value for each row. |
|
|
39
|
+
| `FileField` | File upload = Field + Input(kind:"file"\|"image"), based on FileRef. |
|
|
39
40
|
| `FloatingPanel` | Non-modal panel floating above the page: draggable by its header, resizable from all edges and corners, clamped to the viewport, geometry optionally remembered. |
|
|
40
41
|
| `FormScreenShell` | |
|
|
41
42
|
| `HeaderActionGroup` | |
|
|
@@ -46,14 +47,14 @@ Value exports of `@cosmicdrift/kumiko-renderer/web`.
|
|
|
46
47
|
| `LanguageMenuItems` | Locale choices as dropdown entries, for a user menu that carries the shell controls. |
|
|
47
48
|
| `LanguageSwitcher` | |
|
|
48
49
|
| `LiveEventsProvider` | |
|
|
49
|
-
| `LoadingState` |
|
|
50
|
+
| `LoadingState` | Loading state with skeleton rows styled like cards; `rows` controls the height. |
|
|
50
51
|
| `LocaleProvider` | |
|
|
51
|
-
| `MiniStat` |
|
|
52
|
-
| `ModeSwitch` | Segmented
|
|
52
|
+
| `MiniStat` | Compact metric tile (without an icon) — for dense KPI grids. |
|
|
53
|
+
| `ModeSwitch` | Segmented control for mutually exclusive modes—the prominent alternative to the buried <select>. |
|
|
53
54
|
| `MoneyField` | |
|
|
54
55
|
| `NavProvider` | |
|
|
55
56
|
| `NavTree` | |
|
|
56
|
-
| `NumberField` |
|
|
57
|
+
| `NumberField` | Number field = Field + Input(kind:"number"); avoids repeating the id/name/value/onChange wiring at each screen. |
|
|
57
58
|
| `PageSection` | |
|
|
58
59
|
| `PdfPreview` | |
|
|
59
60
|
| `PercentField` | |
|
|
@@ -64,22 +65,22 @@ Value exports of `@cosmicdrift/kumiko-renderer/web`.
|
|
|
64
65
|
| `PrimitivesProvider` | |
|
|
65
66
|
| `ProfileMenu` | |
|
|
66
67
|
| `ProgressBar` | Progress bar, `value` 0..1 (clamped). |
|
|
67
|
-
| `ProgressList` |
|
|
68
|
+
| `ProgressList` | Label/value header and progress bar for each entry (for example, loan repayment progress). |
|
|
68
69
|
| `PublicShell` | One header and footer for anonymous pages; `focus` narrows to a task column, `card` centers a single card (sign-in). |
|
|
69
70
|
| `QueryTable` | |
|
|
70
|
-
| `RangeField` |
|
|
71
|
+
| `RangeField` | Slider = Field + Input(kind:"range"). |
|
|
71
72
|
| `RenderEdit` | |
|
|
72
73
|
| `RenderField` | |
|
|
73
74
|
| `RenderList` | |
|
|
74
75
|
| `ResizableHandle` | |
|
|
75
76
|
| `ResizablePanel` | |
|
|
76
77
|
| `ResizablePanelGroup` | |
|
|
77
|
-
| `ResultPanel` |
|
|
78
|
-
| `ResultTable` |
|
|
78
|
+
| `ResultPanel` | Result section for a calculator: SectionCard with an empty state (Banner) or a metric list (DetailList) plus optional extras (table, notes). |
|
|
79
|
+
| `ResultTable` | Static, prop-driven result table for calculated rows (tranches, scenarios). |
|
|
79
80
|
| `RichContentEditor` | |
|
|
80
81
|
| `ScreenWidthProvider` | |
|
|
81
|
-
| `SectionCard` |
|
|
82
|
-
| `SelectField` |
|
|
82
|
+
| `SectionCard` | Section with a title and optional action slot (range switcher, filter) — replaces repeated `<section className={CARD}>…<h2>` blocks in custom screens. |
|
|
83
|
+
| `SelectField` | Select field = Field + Input(kind:"select"). |
|
|
83
84
|
| `SideBySideTable` | Small read-only grid with real table semantics (`th scope`) whose cells are arbitrary React nodes — for side-by-side comparisons like "from the document" vs. |
|
|
84
85
|
| `Sidebar` | |
|
|
85
86
|
| `SidebarBrand` | |
|
|
@@ -91,15 +92,15 @@ Value exports of `@cosmicdrift/kumiko-renderer/web`.
|
|
|
91
92
|
| `SidebarUser` | |
|
|
92
93
|
| `Sparkline` | |
|
|
93
94
|
| `Stack` | |
|
|
94
|
-
| `StatCard` | Icon-
|
|
95
|
+
| `StatCard` | Icon-bearing metric tile with an optional delta chip, trend line, and sparkline. |
|
|
95
96
|
| `StatusBadge` | Pill badge with a status dot. |
|
|
96
97
|
| `StatusBarChart` | Status bar strip (e.g. 90-day uptime): variable-height bars with gradient fade + tick line on top; the last entry gets a "now" accent stripe. |
|
|
97
98
|
| `StepBar` | Wizard step overview — numbered chips with a connector line between them. |
|
|
98
|
-
| `TextField` |
|
|
99
|
-
| `TextareaField` |
|
|
99
|
+
| `TextField` | Text field = Field + Input(kind:"text"). |
|
|
100
|
+
| `TextareaField` | Multi-line text field = Field + Input(kind:"textarea"). |
|
|
100
101
|
| `ThemeMenuItem` | Theme toggle as a dropdown entry, for a user menu that carries the shell controls. |
|
|
101
102
|
| `ThemeToggle` | |
|
|
102
|
-
| `TimeseriesChart` |
|
|
103
|
+
| `TimeseriesChart` | Time-series line chart (smoothed line with area fill). |
|
|
103
104
|
| `ToastProvider` | |
|
|
104
105
|
| `TokensProvider` | |
|
|
105
106
|
| `Topbar` | |
|
|
@@ -112,16 +113,16 @@ Value exports of `@cosmicdrift/kumiko-renderer/web`.
|
|
|
112
113
|
|
|
113
114
|
| Name | Description |
|
|
114
115
|
| --- | --- |
|
|
115
|
-
| `useBrowserNavApi` | React
|
|
116
|
-
| `useBrowserTokensApi` |
|
|
116
|
+
| `useBrowserNavApi` | React hook that builds a NavApi from browser history. |
|
|
117
|
+
| `useBrowserTokensApi` | Builds a TokensApi for the browser. |
|
|
117
118
|
| `useDispatcher` | |
|
|
118
119
|
| `useDispatcherStatus` | |
|
|
119
|
-
| `useDraft` |
|
|
120
|
+
| `useDraft` | Form state for calculator screens: a draft object plus `patch` for partial updates, and `field(name)` that provides `{ id, name, value, onChange }` props ready for field widgets (NumberField/MoneyField/PercentField). |
|
|
120
121
|
| `useForm` | |
|
|
121
122
|
| `useIsNarrowViewport` | |
|
|
122
123
|
| `useIsViewportBelow` | |
|
|
123
|
-
| `useLiveEvents` | Hook
|
|
124
|
-
| `useLocale` |
|
|
124
|
+
| `useLiveEvents` | Hook for a useQuery-like consumer. |
|
|
125
|
+
| `useLocale` | Provides the current LocaleResolver and automatically subscribes to locale changes — the calling component re-renders when the language changes. |
|
|
125
126
|
| `useNav` | |
|
|
126
127
|
| `usePrimitives` | |
|
|
127
128
|
| `useQuery` | |
|
|
@@ -129,8 +130,8 @@ Value exports of `@cosmicdrift/kumiko-renderer/web`.
|
|
|
129
130
|
| `useStore` | |
|
|
130
131
|
| `useStoreSelector` | |
|
|
131
132
|
| `useToast` | |
|
|
132
|
-
| `useTokenController` |
|
|
133
|
-
| `useTokens` | Read-only
|
|
133
|
+
| `useTokenController` | Full API including theme toggling, for a dark/light switch button. |
|
|
134
|
+
| `useTokens` | Read-only tokens hook. |
|
|
134
135
|
| `useTranslation` | `t("key", params)` resolves in this order: 1. |
|
|
135
136
|
| `useUserRoles` | |
|
|
136
137
|
|
|
@@ -138,17 +139,17 @@ Value exports of `@cosmicdrift/kumiko-renderer/web`.
|
|
|
138
139
|
|
|
139
140
|
| Name | Description |
|
|
140
141
|
| --- | --- |
|
|
141
|
-
| `applyTokensToCssVars` |
|
|
142
|
+
| `applyTokensToCssVars` | Historically wrote tokens to :root as CSS variables. |
|
|
142
143
|
| `buildFileUploadFormData` | |
|
|
143
144
|
| `buildNavRegistrySlice` | |
|
|
144
145
|
| `buildNavRegistrySliceForApp` | |
|
|
145
|
-
| `cn` | shadcn
|
|
146
|
+
| `cn` | Standard shadcn helper: `clsx` combines conditional classes, while `tailwind-merge` resolves conflicts (for example, `px-2 px-4` → `px-4`). |
|
|
146
147
|
| `createBrowserDraftStorage` | Default DraftStorage when createKumikoApp boots without one. |
|
|
147
|
-
| `createBrowserLocaleResolver` | Default
|
|
148
|
-
| `createEventSourceLiveEvents` |
|
|
148
|
+
| `createBrowserLocaleResolver` | Default resolver when createKumikoApp is booted without a `locale` option. |
|
|
149
|
+
| `createEventSourceLiveEvents` | Returns an EventSource-backed `LiveEventSubscriber`. |
|
|
149
150
|
| `createKumikoApp` | |
|
|
150
151
|
| `createPublicSurface` | |
|
|
151
|
-
| `createStaticLocaleResolver` | Default
|
|
152
|
+
| `createStaticLocaleResolver` | Default resolver for apps without their own i18n layer. |
|
|
152
153
|
| `downloadFileRef` | |
|
|
153
154
|
| `fetchFileRefBlob` | |
|
|
154
155
|
| `fileNameFromContentDisposition` | |
|
|
@@ -157,16 +158,16 @@ Value exports of `@cosmicdrift/kumiko-renderer/web`.
|
|
|
157
158
|
| `formatMoney` | |
|
|
158
159
|
| `formatPath` | |
|
|
159
160
|
| `parsePath` | |
|
|
160
|
-
| `parseTargetFromSearchParams` |
|
|
161
|
+
| `parseTargetFromSearchParams` | Parses the current search parameters back into a TargetRef. |
|
|
161
162
|
| `postWithDownload` | |
|
|
162
163
|
| `qualifyScreenId` | |
|
|
163
164
|
| `readLoadedBuild` | |
|
|
164
165
|
| `reparentAppSchemaNavs` | |
|
|
165
166
|
| `resolveDefaultId` | |
|
|
166
167
|
| `saveBlobAsFile` | |
|
|
167
|
-
| `smoothPath` | Quadratic
|
|
168
|
-
| `synthesizeActionFormEntity` |
|
|
169
|
-
| `synthesizeActionFormScreen` |
|
|
168
|
+
| `smoothPath` | Quadratic midpoint technique: smooths the zigzag line without overshoot (~5 lines instead of a Catmull-Rom/Bezier fit). |
|
|
169
|
+
| `synthesizeActionFormEntity` | Builds a minimal EntityDefinition from the inline fields of an ActionForm or SecretMint screen. |
|
|
170
|
+
| `synthesizeActionFormScreen` | Converts an ActionFormScreenDefinition or SecretMintScreenDefinition to the EntityEditScreen shape expected by RenderEdit. |
|
|
170
171
|
| `uploadFileRef` | Posts one file to the stack's file endpoint (double-submit CSRF) and returns the new FileRef id. |
|
|
171
172
|
|
|
172
173
|
## Constants
|
|
@@ -177,7 +178,7 @@ Value exports of `@cosmicdrift/kumiko-renderer/web`.
|
|
|
177
178
|
| `STATUS_TONE_TEXT` | |
|
|
178
179
|
| `cssVarTokens` | Tokens with var-string values. |
|
|
179
180
|
| `defaultPrimitives` | |
|
|
180
|
-
| `defaultTokens` | Default
|
|
181
|
+
| `defaultTokens` | Default tokens—identical to `cssVarTokens` (variable-string references). |
|
|
181
182
|
| `lightTokens` | |
|
|
182
183
|
|
|
183
184
|
## Classes
|
|
@@ -137,8 +137,8 @@ export const TENANT_HEADER_NAME = "X-Tenant";
|
|
|
137
137
|
export const LOCALE_HEADER_NAME = "X-Locale";
|
|
138
138
|
// Internal-only signal set by buildServer's app.notFound() to mark "no
|
|
139
139
|
// route matched" 404s so tryHonoFirst (server-runtime) can tell them apart
|
|
140
|
-
// from a matched route's own deliberate 404 (e.g. default-deny reads)
|
|
141
|
-
//
|
|
140
|
+
// from a matched route's own deliberate 404 (e.g. default-deny reads).
|
|
141
|
+
// Never reaches a client: tryHonoFirst and every
|
|
142
142
|
// direct app.fetch() passthrough strip it before the response leaves the
|
|
143
143
|
// process, since its presence would otherwise let a caller distinguish
|
|
144
144
|
// "unregistered path" from "registered path, access denied" — a leak the
|
|
@@ -126,13 +126,13 @@ export function authMiddleware(jwt, options = {}) {
|
|
|
126
126
|
// No JWT → either fall through as anonymous (when the server opts in)
|
|
127
127
|
// or reject with 401 (preserving the pre-anonymous default).
|
|
128
128
|
//
|
|
129
|
-
//
|
|
130
|
-
// PUBLIC_API_PATHS
|
|
131
|
-
//
|
|
132
|
-
//
|
|
133
|
-
//
|
|
134
|
-
//
|
|
135
|
-
//
|
|
129
|
+
// Special case for auth routes: `/api/auth/*` paths that are NOT in
|
|
130
|
+
// PUBLIC_API_PATHS (tenants, switch-tenant, logout) require a JWT —
|
|
131
|
+
// but not tenant resolution. If they went through handleAnonymous,
|
|
132
|
+
// resolveTenant would throw 400 tenant_required when no tenant is
|
|
133
|
+
// declared. That would be the wrong diagnosis: the problem is missing
|
|
134
|
+
// authentication, not a missing tenant. Therefore, return 401 here
|
|
135
|
+
// without entering the anonymous-tenant flow.
|
|
136
136
|
if (anonymousAccess) {
|
|
137
137
|
if (isSessionRequiredApiPath(c.req.path)) {
|
|
138
138
|
return middlewareReject(c, {
|
|
@@ -93,10 +93,14 @@ export function createRedisLoginRateLimiter(redis, maxAttempts = 10, windowMs =
|
|
|
93
93
|
// shipped (PTTL returns -1 for "no expiry set, key exists") — without
|
|
94
94
|
// it, those pre-existing keys would grow forever with no way back to
|
|
95
95
|
// a normal window.
|
|
96
|
-
const count =
|
|
96
|
+
const count = await redis.eval(`local c = redis.call('INCR', KEYS[1])
|
|
97
97
|
if c == 1 or redis.call('PTTL', KEYS[1]) < 0 then redis.call('PEXPIRE', KEYS[1], ARGV[1]) end
|
|
98
|
-
return c`, 1, redisKey, windowMs)
|
|
99
|
-
|
|
98
|
+
return c`, 1, redisKey, windowMs);
|
|
99
|
+
const attempts = typeof count === "string" && /^\d+$/.test(count) ? Number(count) : count;
|
|
100
|
+
if (typeof attempts !== "number" || !Number.isInteger(attempts)) {
|
|
101
|
+
throw new TypeError(`redis INCR script returned ${String(count)}, expected an integer`);
|
|
102
|
+
}
|
|
103
|
+
return attempts <= maxAttempts;
|
|
100
104
|
},
|
|
101
105
|
async reset(key) {
|
|
102
106
|
await redis.del(`${prefix}${key}`);
|
|
@@ -130,7 +130,7 @@ export function registerMfaPreauthEnableStartRoute(ctx) {
|
|
|
130
130
|
// Second axis, independent of the IP-derived bucket above: the
|
|
131
131
|
// preauthSetupToken is minted by login.write.ts and not freely
|
|
132
132
|
// choosable, so this cap survives an attacker rotating
|
|
133
|
-
// x-forwarded-for to bypass the IP bucket
|
|
133
|
+
// x-forwarded-for to bypass the IP bucket.
|
|
134
134
|
const tokenAllowed = await rateLimiter.check(preauthTokenKeyOf(body.preauthSetupToken));
|
|
135
135
|
if (!tokenAllowed) {
|
|
136
136
|
return c.json({ isSuccess: false, error: "rate_limited" }, 429);
|
|
@@ -121,7 +121,7 @@ export function registerSessionRoutes(ctx) {
|
|
|
121
121
|
id: user.id,
|
|
122
122
|
tenantId: targetTenantId,
|
|
123
123
|
roles: sessionRoles,
|
|
124
|
-
// Tenant-independent prefs must survive the switch
|
|
124
|
+
// Tenant-independent prefs must survive the switch.
|
|
125
125
|
...tenantIndependentPrefs(user),
|
|
126
126
|
};
|
|
127
127
|
const claims = await dispatcher.resolveAuthClaims(targetSession);
|
|
@@ -2,8 +2,9 @@ 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
4
|
import { NotFoundError } from "../errors/index.js";
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import { createFallbackLogger } from "../logging/utils.js";
|
|
6
|
+
const log = createFallbackLogger("kumiko");
|
|
7
|
+
// Cross-device try-first handover: an optional tenant-handover grant the signup-request
|
|
7
8
|
// route forwards to the handler for server-side verification and binding —
|
|
8
9
|
// the grant itself never appears anywhere else (URL, mail, log, response).
|
|
9
10
|
export const SignupRequestBody = z.object({
|
|
@@ -68,7 +69,10 @@ export function registerTokenRequestRoute(opts) {
|
|
|
68
69
|
// rate_limited is an expected, attacker-triggerable outcome; logging it
|
|
69
70
|
// would flood the sink and bury real misconfiguration errors.
|
|
70
71
|
if (!result.isSuccess && result.error.code !== "rate_limited") {
|
|
71
|
-
|
|
72
|
+
log.error("token request handler failed", {
|
|
73
|
+
handler: opts.requestHandler,
|
|
74
|
+
code: result.error.code,
|
|
75
|
+
});
|
|
72
76
|
}
|
|
73
77
|
return c.json({ isSuccess: true });
|
|
74
78
|
});
|
|
@@ -63,7 +63,7 @@ export function registerSignupRoutes(ctx) {
|
|
|
63
63
|
// switcher), signup knows exactly ONE membership — the frontend UI uses
|
|
64
64
|
// it directly as the redirect target.
|
|
65
65
|
tenantKey: data.tenantKey,
|
|
66
|
-
// Cross-device try-first handover
|
|
66
|
+
// Cross-device try-first handover:
|
|
67
67
|
// present only when signup-confirm actually claimed a bound grant —
|
|
68
68
|
// absent, not null, so a client that doesn't know the field sees
|
|
69
69
|
// nothing unusual.
|
|
@@ -37,8 +37,13 @@ function inMemoryIpRateLimit(clientIpResolver, now) {
|
|
|
37
37
|
windows.delete(ip);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
// Map keeps insertion order and touched IPs are re-inserted, so the front is the least recently
|
|
41
|
+
// seen; clear() would let an attacker rotating addresses reset every other IP's window.
|
|
42
|
+
for (const ip of windows.keys()) {
|
|
43
|
+
if (windows.size <= MAX_TRACKED_IPS)
|
|
44
|
+
break;
|
|
45
|
+
windows.delete(ip);
|
|
46
|
+
}
|
|
42
47
|
}
|
|
43
48
|
return async (c, next) => {
|
|
44
49
|
const ip = clientIpResolver.resolve(clientIpSourceFromHonoContext(c));
|
|
@@ -47,6 +52,7 @@ function inMemoryIpRateLimit(clientIpResolver, now) {
|
|
|
47
52
|
const existing = windows.get(ip);
|
|
48
53
|
const window = existing && nowMs - existing.startedAt < windowMs ? existing : { count: 0, startedAt: nowMs };
|
|
49
54
|
window.count += 1;
|
|
55
|
+
windows.delete(ip);
|
|
50
56
|
windows.set(ip, window);
|
|
51
57
|
if (window.count > REPORTS_PER_WINDOW) {
|
|
52
58
|
const resetAtMs = window.startedAt + windowMs;
|
package/dist/api/client-ip.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createFallbackLogger } from "../logging/utils.js";
|
|
2
|
+
const log = createFallbackLogger("kumiko");
|
|
1
3
|
// Single source for client-IP extraction, shared by every IP-keyed rate
|
|
2
4
|
// limit and audit field. Deriving the caller IP independently per call site
|
|
3
5
|
// makes it easy for one to silently trust the first XFF entry, which is
|
|
@@ -70,7 +72,7 @@ export function createClientIpResolver(trustedProxyHops, context = "resolveClien
|
|
|
70
72
|
if (trustedProxyHops === 0) {
|
|
71
73
|
if (xff !== undefined && xff.trim().length > 0 && !warnedUnexpectedForwardedFor) {
|
|
72
74
|
warnedUnexpectedForwardedFor = true;
|
|
73
|
-
|
|
75
|
+
log.warn("received X-Forwarded-For but trustedProxyHops is 0 (no proxy trusted) — " +
|
|
74
76
|
"ignoring it. Running behind a proxy? Set trustedProxyHops, otherwise all clients " +
|
|
75
77
|
"share one rate-limit bucket.");
|
|
76
78
|
}
|
package/dist/api/extra-route.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// ExtraRoute — declarative replacement for the old `extraRoutes: (app, deps)
|
|
2
|
-
// => void` closure
|
|
2
|
+
// => void` closure. Every entry declares its access
|
|
3
3
|
// tier (`entry`) up front; buildServer wires the matching guard + deps
|
|
4
4
|
// instead of handing every route a raw db/redis escape hatch.
|
|
5
5
|
export const ExtraRouteEntries = {
|
package/dist/api/index.d.ts
CHANGED
|
@@ -27,7 +27,9 @@ export type { MetricsRouteOptions } from "./route-registrars.ts";
|
|
|
27
27
|
export { createMetricsApp, DEFAULT_MAX_REQUEST_BYTES, isPrometheusMeter, } from "./route-registrars.ts";
|
|
28
28
|
export { createApiRoutes } from "./routes.ts";
|
|
29
29
|
export type { KumikoServer, ServerOptions } from "./server.ts";
|
|
30
|
-
export { buildServer
|
|
30
|
+
export { buildServer } from "./server.ts";
|
|
31
|
+
export { makeDispatchSystemQuery, makeDispatchSystemWrite, makeDispatchWriteAs, } from "./server-extra-routes.ts";
|
|
32
|
+
export { withFileProviderResolver } from "./server-wiring.ts";
|
|
31
33
|
export type { ResolvedSessionCookies, SessionCookieBase, SessionCookieNames, } from "./session-cookies.ts";
|
|
32
34
|
export { AUTH_COOKIE_BASE, CSRF_COOKIE_BASE, getSessionCookies, HOST_COOKIE_PREFIX, isHostPrefixedCookieName, resolveSessionCookieNames, resolveSessionCookies, sessionCookieName, sessionCookiesMiddleware, TENANT_COOKIE_BASE, } from "./session-cookies.ts";
|
|
33
35
|
export type { SseBroker, SseClient, SseEvent } from "./sse-broker.ts";
|
package/dist/api/index.js
CHANGED
|
@@ -16,7 +16,9 @@ export { readonlyRequestContext as requestContext, } from "./request-context.js"
|
|
|
16
16
|
export { buildRequestContextDataFromRequest, requestIdMiddleware, } from "./request-id-middleware.js";
|
|
17
17
|
export { createMetricsApp, DEFAULT_MAX_REQUEST_BYTES, isPrometheusMeter, } from "./route-registrars.js";
|
|
18
18
|
export { createApiRoutes } from "./routes.js";
|
|
19
|
-
export { buildServer
|
|
19
|
+
export { buildServer } from "./server.js";
|
|
20
|
+
export { makeDispatchSystemQuery, makeDispatchSystemWrite, makeDispatchWriteAs, } from "./server-extra-routes.js";
|
|
21
|
+
export { withFileProviderResolver } from "./server-wiring.js";
|
|
20
22
|
export { AUTH_COOKIE_BASE, CSRF_COOKIE_BASE, getSessionCookies, HOST_COOKIE_PREFIX, isHostPrefixedCookieName, resolveSessionCookieNames, resolveSessionCookies, sessionCookieName, sessionCookiesMiddleware, TENANT_COOKIE_BASE, } from "./session-cookies.js";
|
|
21
23
|
export { createSseBroker } from "./sse-broker.js";
|
|
22
24
|
export { createSseRoute, SSE_HEARTBEAT_INTERVAL_MS } from "./sse-route.js";
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { PII_CIPHERTEXT_PREFIX } from "../crypto/index.js";
|
|
2
|
+
import { createFallbackLogger } from "../logging/utils.js";
|
|
2
3
|
import { resolveRouteLabel } from "./route-label.js";
|
|
4
|
+
const log = createFallbackLogger("kumiko:pii-leak-guard");
|
|
3
5
|
const isProductionEnv = () => process.env["NODE_ENV"] === "production";
|
|
4
6
|
// Version-agnostic: catches both the current PII_CIPHERTEXT_PREFIX and any
|
|
5
7
|
// older/decrypt-only format version still present in unmigrated rows.
|
|
@@ -28,7 +30,7 @@ export function piiCiphertextResponseGuard() {
|
|
|
28
30
|
// skip: clean response — the common case
|
|
29
31
|
if (!CIPHERTEXT_RE.test(text))
|
|
30
32
|
return;
|
|
31
|
-
const detail = `
|
|
33
|
+
const detail = `JSON response for ${c.req.method} ${resolveRouteLabel(c)} contains a PII ciphertext ` +
|
|
32
34
|
`("${PII_CIPHERTEXT_PREFIX}…") — a raw DB read leaked to the API surface. ` +
|
|
33
35
|
`Decrypt before returning (decryptStoredPii / executor read path).`;
|
|
34
36
|
if (!isProductionEnv()) {
|
|
@@ -36,7 +38,7 @@ export function piiCiphertextResponseGuard() {
|
|
|
36
38
|
// skip: response replaced with the loud 500 above — nothing left to do
|
|
37
39
|
return;
|
|
38
40
|
}
|
|
39
|
-
|
|
41
|
+
log.error(detail);
|
|
40
42
|
const headers = new Headers(c.res.headers);
|
|
41
43
|
headers.delete("content-length");
|
|
42
44
|
c.res = new Response(text.replace(CIPHERTEXT_REDACT_RE, "[pii-redacted]"), {
|
package/dist/api/readiness.js
CHANGED
|
@@ -74,11 +74,11 @@ export function redisPingCheck(redis) {
|
|
|
74
74
|
},
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
|
-
// Lag
|
|
78
|
-
//
|
|
79
|
-
// (bigint),
|
|
80
|
-
//
|
|
81
|
-
//
|
|
77
|
+
// Lag check for the asynchronous event dispatcher. Reads the HWM and consumer cursor from
|
|
78
|
+
// the database, without relying on extra Redis or runtime state. The failure threshold is
|
|
79
|
+
// measured in event IDs (`bigint`), the natural unit because events have monotonically
|
|
80
|
+
// increasing IDs. For example, `maxLagEvents = 1_000` stops routing new traffic when the
|
|
81
|
+
// projection falls more than 1,000 events behind the HWM.
|
|
82
82
|
export function dispatcherLagCheck(db, consumerNames, maxLagEvents) {
|
|
83
83
|
return {
|
|
84
84
|
name: "dispatcher_lag",
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
|
|
2
|
+
import { createFallbackLogger } from "../logging/utils.js";
|
|
2
3
|
import { redisChannelPrefixFromEnv, redisClientOptionsFromEnv, } from "../redis/client.js";
|
|
3
4
|
import { createRedisPubSubSignal } from "../redis/pubsub-signal.js";
|
|
4
5
|
import { createSseBroker, readNonEmptyStringArray, } from "./sse-broker.js";
|
|
5
|
-
|
|
6
|
+
const log = createFallbackLogger("kumiko:sse-broker");
|
|
7
|
+
// Channel namespace for cross-replica fanout. Every pod publishes
|
|
6
8
|
// here and every pod's psubscribe listens here, so a push on one instance
|
|
7
9
|
// reaches SSE clients connected to any other instance without a shared
|
|
8
10
|
// cursor — Pub/Sub for connected-client fanout, the event-store's shared
|
|
@@ -21,9 +23,9 @@ export function isRedisSseBroker(broker) {
|
|
|
21
23
|
// runProdApp must funnel through this rather than each deciding on their
|
|
22
24
|
// own — runProdApp doing exactly that (building an in-memory broker
|
|
23
25
|
// unconditionally, then passing it in as ServerOptions.sseBroker) is why
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
26
|
+
// the fanout fix shipped without ever taking effect in production: an
|
|
27
|
+
// explicit ServerOptions.sseBroker always wins in buildServer, so its own
|
|
28
|
+
// REDIS_URL-based default never ran.
|
|
27
29
|
export function createDefaultSseBroker(env = process.env) {
|
|
28
30
|
const redisUrl = env["REDIS_URL"];
|
|
29
31
|
const ownedRedisSseBroker = redisUrl
|
|
@@ -109,7 +111,7 @@ export function createRedisSseBroker(opts) {
|
|
|
109
111
|
signal.onMessage((channel, payload) => {
|
|
110
112
|
if (channel.startsWith(channelPrefix)) {
|
|
111
113
|
if (!isSseEvent(payload)) {
|
|
112
|
-
|
|
114
|
+
log.error(`dropping malformed event on "${channel}"`);
|
|
113
115
|
// skip: malformed payload already logged above, nothing to deliver
|
|
114
116
|
return;
|
|
115
117
|
}
|
|
@@ -132,7 +134,7 @@ export function createRedisSseBroker(opts) {
|
|
|
132
134
|
pushToChannel(channel, event) {
|
|
133
135
|
return signal.publishConfirmed(`${channelPrefix}${channel}`, event);
|
|
134
136
|
},
|
|
135
|
-
//
|
|
137
|
+
// This is the security-critical call — a revoked session's
|
|
136
138
|
// stream must close on every replica, not just the one that observed
|
|
137
139
|
// the revocation event. Publishing (rather than calling inner directly,
|
|
138
140
|
// like the in-memory broker does) is what makes that true here.
|
|
@@ -41,6 +41,6 @@ export declare function runWithOrigin<T>(origin: {
|
|
|
41
41
|
readonly risk: AgentRisk;
|
|
42
42
|
};
|
|
43
43
|
}, fn: () => T): T;
|
|
44
|
-
export declare function
|
|
44
|
+
export declare function runAsAgentToolCallEntry<T>(fn: () => T): T;
|
|
45
45
|
export declare function isAgentToolCallScope(): boolean;
|
|
46
46
|
export declare function runWithWriteOrigin<T>(origin: WriteOrigin, fn: () => T): T;
|
|
@@ -53,7 +53,7 @@ export function runWithOrigin(origin, fn) {
|
|
|
53
53
|
// surrounding turn/approve handler. Reserved for dispatchToolCall, so it also marks
|
|
54
54
|
// the scope as an agent tool call; it always mints a scope, because an agent loop
|
|
55
55
|
// running outside any request must still carry that marker.
|
|
56
|
-
export function
|
|
56
|
+
export function runAsAgentToolCallEntry(fn) {
|
|
57
57
|
const current = requestContext.get();
|
|
58
58
|
const requestId = current?.requestId ?? requestContext.generateId();
|
|
59
59
|
const { entryHandler: _entryHandler, ...rest } = current ?? {};
|
package/dist/api/routes.js
CHANGED
|
@@ -129,7 +129,7 @@ export function createApiRoutes(dispatcher, options = {}) {
|
|
|
129
129
|
// dispatch gates (feature/rate-limit/access/validation) plus the handler's
|
|
130
130
|
// first yield — is raced against a heartbeat timeout BEFORE streamSSE, so
|
|
131
131
|
// a gate failure that settles in time maps to its real HTTP status via
|
|
132
|
-
// queryErrorResponse instead of a flushed-200 error frame
|
|
132
|
+
// queryErrorResponse instead of a flushed-200 error frame.
|
|
133
133
|
api.post(Routes.stream, async (c) => {
|
|
134
134
|
const user = getUser(c);
|
|
135
135
|
const body = await readDispatchBody(c);
|
|
@@ -149,7 +149,7 @@ export function createApiRoutes(dispatcher, options = {}) {
|
|
|
149
149
|
// Hook the raw request signal directly so a client disconnect during the
|
|
150
150
|
// pre-pull still reclaims the generator instead of leaking a Redis
|
|
151
151
|
// subscription/DB cursor held open inside its still-unresolved first
|
|
152
|
-
// `.next()
|
|
152
|
+
// `.next()`.
|
|
153
153
|
const signal = c.req.raw.signal;
|
|
154
154
|
const onPrePullAbort = () => void generator.return(undefined);
|
|
155
155
|
signal.addEventListener("abort", onPrePullAbort);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type AppContext, type Registry } from "../engine/types/index.ts";
|
|
2
|
+
import type { createFallbackLogger } from "../logging/index.ts";
|
|
3
|
+
import type { AuthRoutesConfig } from "./auth-routes.ts";
|
|
4
|
+
export type BootLogger = ReturnType<typeof createFallbackLogger>;
|
|
5
|
+
export declare function assertNoPayloadRateLimitsWithoutResolver(registry: Registry): void;
|
|
6
|
+
export declare function assertFileStorageProviderForFileFields(registry: Registry, context: AppContext): void;
|
|
7
|
+
export declare function warnSearchableScreensWithoutSearchAdapter(registry: Registry, context: AppContext, bootLog: BootLogger): void;
|
|
8
|
+
export declare function resolveServerInstanceId(explicitInstanceId: string | undefined, bootLog: BootLogger): string;
|
|
9
|
+
export declare function warnUnlimitedSystemScopeFeatures(registry: Registry, bootLog: BootLogger): void;
|
|
10
|
+
export declare function assertSinglePrincipalStatusProvider(registry: Registry, auth: AuthRoutesConfig): void;
|