@cosmicdrift/kumiko-framework 0.369.0 → 0.370.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.
Files changed (449) hide show
  1. package/AGENTS.md +14 -1
  2. package/agents/examples/apex-surface-auth.md +2 -1
  3. package/agents/examples/app-config.md +98 -0
  4. package/agents/examples/auth-mfa.md +72 -0
  5. package/agents/examples/compose-stacks.md +188 -0
  6. package/agents/examples/env-composition.md +268 -0
  7. package/agents/examples/host-routing.md +181 -0
  8. package/agents/examples/legal-pages.md +52 -3
  9. package/agents/examples/managed-config.md +1 -0
  10. package/agents/examples/managed-pages.md +1 -0
  11. package/agents/examples/prod-boot-options.md +180 -0
  12. package/agents/examples/relations.md +4 -0
  13. package/agents/examples/secrets-demo.md +4 -2
  14. package/agents/examples/security-baseline.md +20 -17
  15. package/agents/examples.md +6 -1
  16. package/agents/features.md +14 -2
  17. package/dist/api/anonymous-cookie.d.ts +1 -1
  18. package/dist/api/anonymous-live-entities.d.ts +1 -1
  19. package/dist/api/auth-middleware.d.ts +2 -2
  20. package/dist/api/auth-routes.d.ts +7 -7
  21. package/dist/api/extra-route.d.ts +2 -2
  22. package/dist/api/index.d.ts +37 -37
  23. package/dist/api/jwt.d.ts +1 -1
  24. package/dist/api/observability-middleware.d.ts +1 -1
  25. package/dist/api/readiness.d.ts +1 -1
  26. package/dist/api/redis-sse-broker.d.ts +2 -2
  27. package/dist/api/request-context.d.ts +1 -1
  28. package/dist/api/request-id-middleware.d.ts +3 -3
  29. package/dist/api/route-registrars.d.ts +4 -4
  30. package/dist/api/routes.d.ts +1 -1
  31. package/dist/api/server.d.ts +16 -16
  32. package/dist/api/sse-broker.d.ts +1 -1
  33. package/dist/api/sse-route.d.ts +1 -1
  34. package/dist/api/websocket-route.d.ts +3 -3
  35. package/dist/auth/index.d.ts +2 -2
  36. package/dist/compliance/duration-spec.d.ts +2 -2
  37. package/dist/compliance/index.d.ts +6 -6
  38. package/dist/compliance/profiles.d.ts +1 -1
  39. package/dist/config/index.d.ts +44 -0
  40. package/dist/config/index.js +61 -0
  41. package/dist/crypto/blind-index.d.ts +1 -1
  42. package/dist/crypto/event-pii.d.ts +1 -1
  43. package/dist/crypto/in-memory-kms-adapter.d.ts +1 -1
  44. package/dist/crypto/index.d.ts +11 -11
  45. package/dist/crypto/is-self-pii-field.d.ts +1 -1
  46. package/dist/crypto/kms-wiring.d.ts +2 -2
  47. package/dist/crypto/owner-transition-rekey.d.ts +1 -1
  48. package/dist/crypto/pg-kms-adapter.d.ts +1 -1
  49. package/dist/crypto/pii-field-encryption.d.ts +4 -4
  50. package/dist/crypto/request-kms-cache.d.ts +1 -1
  51. package/dist/crypto/subject-resolver.d.ts +3 -3
  52. package/dist/db/apply-entity-event.d.ts +4 -4
  53. package/dist/db/assert-exists-in.d.ts +4 -4
  54. package/dist/db/blind-index-cleanup.d.ts +2 -2
  55. package/dist/db/collect-table-metas.d.ts +2 -2
  56. package/dist/db/compound-types.d.ts +1 -1
  57. package/dist/db/config-seed.d.ts +5 -5
  58. package/dist/db/connection.d.ts +1 -6
  59. package/dist/db/connection.js +15 -4
  60. package/dist/db/dialect.d.ts +1 -1
  61. package/dist/db/eagerload.d.ts +3 -3
  62. package/dist/db/entity-field-encryption.d.ts +3 -3
  63. package/dist/db/entity-field-encryption.js +3 -1
  64. package/dist/db/entity-table-from-registry.d.ts +3 -3
  65. package/dist/db/entity-table-meta.d.ts +3 -3
  66. package/dist/db/event-store-executor-context.d.ts +9 -9
  67. package/dist/db/event-store-executor-read.d.ts +2 -2
  68. package/dist/db/event-store-executor-write.d.ts +2 -2
  69. package/dist/db/event-store-executor.d.ts +8 -8
  70. package/dist/db/feature-table-sources.d.ts +1 -1
  71. package/dist/db/index.d.ts +39 -39
  72. package/dist/db/located-timestamp.d.ts +1 -1
  73. package/dist/db/lock-guard.d.ts +2 -2
  74. package/dist/db/migrate-generator.d.ts +2 -2
  75. package/dist/db/migrate-runner.d.ts +1 -1
  76. package/dist/db/money.d.ts +1 -1
  77. package/dist/db/parent-ref-clause.d.ts +4 -4
  78. package/dist/db/projection-registry-binding.d.ts +1 -1
  79. package/dist/db/queries/advisory-lock.d.ts +1 -1
  80. package/dist/db/queries/backfill-pii.d.ts +2 -2
  81. package/dist/db/queries/ddl.d.ts +1 -1
  82. package/dist/db/queries/entity-read.d.ts +1 -1
  83. package/dist/db/queries/es-ops.d.ts +1 -1
  84. package/dist/db/queries/event-consumer.d.ts +2 -2
  85. package/dist/db/queries/event-store-admin.d.ts +1 -1
  86. package/dist/db/queries/event-store-transfer.d.ts +1 -1
  87. package/dist/db/queries/event-store.d.ts +1 -1
  88. package/dist/db/queries/pii-backfill-state.d.ts +1 -1
  89. package/dist/db/queries/projection-rebuild.d.ts +1 -1
  90. package/dist/db/queries/raw-sql.d.ts +1 -1
  91. package/dist/db/queries/seed-context.d.ts +2 -2
  92. package/dist/db/queries/shadow-swap.d.ts +3 -3
  93. package/dist/db/queries/table-ops.d.ts +1 -1
  94. package/dist/db/queries/test-stack.d.ts +2 -2
  95. package/dist/db/query.d.ts +3 -3
  96. package/dist/db/rebuild-marker.d.ts +1 -1
  97. package/dist/db/reference-data.d.ts +3 -3
  98. package/dist/db/render-ddl.d.ts +1 -1
  99. package/dist/db/replay-migration-sql.d.ts +1 -1
  100. package/dist/db/retired-framework-tables.d.ts +1 -1
  101. package/dist/db/schema-inspection.d.ts +1 -1
  102. package/dist/db/table-builder.d.ts +4 -4
  103. package/dist/db/table-push.d.ts +3 -3
  104. package/dist/db/tenant-db-runner.d.ts +2 -2
  105. package/dist/db/tenant-db.d.ts +7 -9
  106. package/dist/db/tenant-db.js +2 -12
  107. package/dist/derivatives/derivatives-context.d.ts +3 -3
  108. package/dist/derivatives/field-variants.d.ts +1 -1
  109. package/dist/derivatives/index.d.ts +6 -6
  110. package/dist/engine/access.d.ts +1 -1
  111. package/dist/engine/active-membership.d.ts +2 -2
  112. package/dist/engine/boot-validator/access-declarations.d.ts +1 -1
  113. package/dist/engine/boot-validator/access-roles.d.ts +1 -1
  114. package/dist/engine/boot-validator/action-wiring.d.ts +1 -1
  115. package/dist/engine/boot-validator/api-ext.d.ts +1 -1
  116. package/dist/engine/boot-validator/boot-check.d.ts +1 -1
  117. package/dist/engine/boot-validator/card-meta-overflow.d.ts +1 -1
  118. package/dist/engine/boot-validator/config-deps.d.ts +1 -1
  119. package/dist/engine/boot-validator/detail-screens.d.ts +2 -2
  120. package/dist/engine/boot-validator/entity-handler.d.ts +1 -1
  121. package/dist/engine/boot-validator/entity-list-screens.d.ts +1 -1
  122. package/dist/engine/boot-validator/gdpr-storage.d.ts +1 -1
  123. package/dist/engine/boot-validator/global-tenancy.d.ts +1 -1
  124. package/dist/engine/boot-validator/handler-field-references.d.ts +1 -1
  125. package/dist/engine/boot-validator/i18n-keys.d.ts +1 -1
  126. package/dist/engine/boot-validator/index.d.ts +7 -7
  127. package/dist/engine/boot-validator/nav.d.ts +1 -1
  128. package/dist/engine/boot-validator/ownership.d.ts +2 -2
  129. package/dist/engine/boot-validator/parent-ref.d.ts +1 -1
  130. package/dist/engine/boot-validator/pii-retention.d.ts +2 -2
  131. package/dist/engine/boot-validator/projection-list-screens.d.ts +1 -1
  132. package/dist/engine/boot-validator/query-output-columns.d.ts +1 -1
  133. package/dist/engine/boot-validator/query-refs.d.ts +1 -1
  134. package/dist/engine/boot-validator/record-owned.d.ts +1 -1
  135. package/dist/engine/boot-validator/screens.d.ts +2 -2
  136. package/dist/engine/boot-validator/security-baseline.d.ts +1 -1
  137. package/dist/engine/boot-validator/selector-owner-panels.d.ts +1 -1
  138. package/dist/engine/boot-validator/transfer-graph.d.ts +2 -2
  139. package/dist/engine/boot-validator/url-prefill-fields.d.ts +1 -1
  140. package/dist/engine/boot-validator/workspaces.d.ts +1 -1
  141. package/dist/engine/boot-validator.d.ts +1 -1
  142. package/dist/engine/bridge-stub.d.ts +1 -1
  143. package/dist/engine/build-app-schema.d.ts +2 -2
  144. package/dist/engine/build-config-feature-schema.d.ts +5 -5
  145. package/dist/engine/build-target.d.ts +2 -2
  146. package/dist/engine/changeset-changes.d.ts +1 -1
  147. package/dist/engine/codemod/index.d.ts +2 -2
  148. package/dist/engine/config-helpers.d.ts +1 -1
  149. package/dist/engine/constants.d.ts +1 -1
  150. package/dist/engine/create-app.d.ts +2 -2
  151. package/dist/engine/cross-tenant.d.ts +2 -2
  152. package/dist/engine/dedupe-features.d.ts +1 -1
  153. package/dist/engine/define-feature.d.ts +1 -1
  154. package/dist/engine/define-feature.js +2 -2
  155. package/dist/engine/define-handler.d.ts +4 -4
  156. package/dist/engine/define-step.d.ts +1 -1
  157. package/dist/engine/define-workflow.d.ts +2 -2
  158. package/dist/engine/effective-features.d.ts +1 -1
  159. package/dist/engine/embedded-derived.d.ts +1 -1
  160. package/dist/engine/entity-handlers.d.ts +6 -5
  161. package/dist/engine/entity-handlers.js +6 -3
  162. package/dist/engine/event-def.d.ts +15 -0
  163. package/dist/engine/event-def.js +123 -0
  164. package/dist/engine/event-helpers.d.ts +1 -1
  165. package/dist/engine/extension-names.d.ts +8 -8
  166. package/dist/engine/extension-selector-plugins.d.ts +2 -2
  167. package/dist/engine/extensions/escape-hatch-usage.d.ts +1 -1
  168. package/dist/engine/extensions/storage-provider.d.ts +1 -1
  169. package/dist/engine/extensions/tenant-data.d.ts +3 -3
  170. package/dist/engine/extensions/tenant-resource.d.ts +2 -2
  171. package/dist/engine/extensions/user-data.d.ts +2 -2
  172. package/dist/engine/factories.d.ts +1 -1
  173. package/dist/engine/feature-ast/extractors/ai-steps.d.ts +2 -2
  174. package/dist/engine/feature-ast/extractors/events.d.ts +2 -2
  175. package/dist/engine/feature-ast/extractors/handlers.d.ts +4 -4
  176. package/dist/engine/feature-ast/extractors/hooks.d.ts +5 -5
  177. package/dist/engine/feature-ast/extractors/index.d.ts +14 -14
  178. package/dist/engine/feature-ast/extractors/jobs-routes.d.ts +3 -3
  179. package/dist/engine/feature-ast/extractors/projections-screens.d.ts +3 -3
  180. package/dist/engine/feature-ast/extractors/round1.d.ts +2 -2
  181. package/dist/engine/feature-ast/extractors/round2.d.ts +2 -2
  182. package/dist/engine/feature-ast/extractors/round3.d.ts +4 -4
  183. package/dist/engine/feature-ast/extractors/round5.d.ts +2 -2
  184. package/dist/engine/feature-ast/extractors/round6.d.ts +2 -2
  185. package/dist/engine/feature-ast/extractors/shared.d.ts +2 -2
  186. package/dist/engine/feature-ast/index.d.ts +16 -16
  187. package/dist/engine/feature-ast/parse.d.ts +2 -2
  188. package/dist/engine/feature-ast/patch.d.ts +1 -1
  189. package/dist/engine/feature-ast/patcher.d.ts +15 -15
  190. package/dist/engine/feature-ast/pattern-change-schema.d.ts +10 -10
  191. package/dist/engine/feature-ast/patterns.d.ts +15 -15
  192. package/dist/engine/feature-ast/render.d.ts +1 -1
  193. package/dist/engine/feature-builder-state.d.ts +5 -5
  194. package/dist/engine/feature-config-events-jobs.d.ts +3 -3
  195. package/dist/engine/feature-config-events-jobs.js +8 -130
  196. package/dist/engine/feature-entity-handlers.d.ts +4 -4
  197. package/dist/engine/feature-entity-handlers.js +11 -5
  198. package/dist/engine/feature-manifest.d.ts +1 -1
  199. package/dist/engine/feature-ui-extensions.d.ts +7 -7
  200. package/dist/engine/feature-ui-extensions.js +2 -2
  201. package/dist/engine/field-access.d.ts +1 -1
  202. package/dist/engine/field-helpers.d.ts +1 -1
  203. package/dist/engine/handler-helpers.d.ts +1 -1
  204. package/dist/engine/index.d.ts +89 -88
  205. package/dist/engine/index.js +1 -0
  206. package/dist/engine/instruction-fields.d.ts +1 -1
  207. package/dist/engine/object-form.d.ts +1 -1
  208. package/dist/engine/object-form.js +5 -6
  209. package/dist/engine/ownership.d.ts +3 -3
  210. package/dist/engine/pattern-library/index.d.ts +2 -2
  211. package/dist/engine/pattern-library/library.d.ts +2 -2
  212. package/dist/engine/pattern-library/mixed-schemas.d.ts +1 -1
  213. package/dist/engine/pattern-library/opaque-schemas.d.ts +1 -1
  214. package/dist/engine/pattern-library/shared-fields.d.ts +1 -1
  215. package/dist/engine/pattern-library/static-schemas.d.ts +1 -1
  216. package/dist/engine/pattern-library/types.d.ts +1 -1
  217. package/dist/engine/personal-data-fields.d.ts +2 -2
  218. package/dist/engine/pipeline.d.ts +2 -2
  219. package/dist/engine/project-app-schema-for-roles.d.ts +1 -1
  220. package/dist/engine/projection-helpers.d.ts +4 -4
  221. package/dist/engine/read-claim.d.ts +1 -1
  222. package/dist/engine/registry-facade.d.ts +2 -2
  223. package/dist/engine/registry-ingest.d.ts +2 -2
  224. package/dist/engine/registry-state.d.ts +2 -2
  225. package/dist/engine/registry-validate.d.ts +3 -3
  226. package/dist/engine/registry.d.ts +1 -1
  227. package/dist/engine/resolve-config-or-param.d.ts +2 -2
  228. package/dist/engine/role-assignment.d.ts +1 -1
  229. package/dist/engine/run-in.d.ts +1 -1
  230. package/dist/engine/run-pipeline.d.ts +3 -3
  231. package/dist/engine/schema-builder.d.ts +1 -1
  232. package/dist/engine/screen-filter-ops.d.ts +1 -1
  233. package/dist/engine/screen-helpers.d.ts +2 -2
  234. package/dist/engine/soft-delete-cleanup.d.ts +2 -2
  235. package/dist/engine/steps/_event-match.d.ts +1 -1
  236. package/dist/engine/steps/_no-return-guard.d.ts +1 -1
  237. package/dist/engine/steps/_read-source.d.ts +4 -4
  238. package/dist/engine/steps/_resolver-utils.d.ts +1 -1
  239. package/dist/engine/steps/aggregate-append-event.d.ts +1 -1
  240. package/dist/engine/steps/aggregate-create.d.ts +2 -2
  241. package/dist/engine/steps/aggregate-update.d.ts +3 -3
  242. package/dist/engine/steps/branch.d.ts +1 -1
  243. package/dist/engine/steps/call-feature.d.ts +2 -2
  244. package/dist/engine/steps/compute.d.ts +1 -1
  245. package/dist/engine/steps/for-each.d.ts +1 -1
  246. package/dist/engine/steps/mail-send.d.ts +1 -1
  247. package/dist/engine/steps/read-find-many.d.ts +2 -2
  248. package/dist/engine/steps/read-find-one.d.ts +2 -2
  249. package/dist/engine/steps/retry.d.ts +1 -1
  250. package/dist/engine/steps/return.d.ts +2 -2
  251. package/dist/engine/steps/unsafe-projection-delete.d.ts +2 -2
  252. package/dist/engine/steps/unsafe-projection-upsert.d.ts +1 -1
  253. package/dist/engine/steps/wait-for-event.d.ts +1 -1
  254. package/dist/engine/steps/wait.d.ts +1 -1
  255. package/dist/engine/steps/webhook-send.d.ts +1 -1
  256. package/dist/engine/strip-disabled-features-from-app-schema.d.ts +4 -4
  257. package/dist/engine/system-user.d.ts +2 -2
  258. package/dist/engine/template-variables.d.ts +1 -1
  259. package/dist/engine/tier-resolver-extension.d.ts +4 -4
  260. package/dist/engine/transfer-adjacency.d.ts +1 -1
  261. package/dist/engine/types/index.d.ts +6 -6
  262. package/dist/engine/validate-projection-allowlist.d.ts +1 -1
  263. package/dist/engine/validation.d.ts +1 -1
  264. package/dist/entrypoint/index.d.ts +12 -12
  265. package/dist/env/dry-run.d.ts +14 -1
  266. package/dist/env/dry-run.js +50 -0
  267. package/dist/env/index.d.ts +54 -16
  268. package/dist/env/index.js +60 -6
  269. package/dist/errors/classes.d.ts +3 -3
  270. package/dist/errors/docs-url.d.ts +1 -1
  271. package/dist/errors/index.d.ts +18 -18
  272. package/dist/errors/member-resolution.d.ts +1 -1
  273. package/dist/errors/serialize.d.ts +2 -2
  274. package/dist/errors/subject-erased.d.ts +1 -1
  275. package/dist/errors/to-kumiko-error.d.ts +1 -1
  276. package/dist/errors/write-error-info.d.ts +1 -1
  277. package/dist/errors/zod-bridge.d.ts +1 -1
  278. package/dist/es-ops/context.d.ts +4 -4
  279. package/dist/es-ops/index.d.ts +4 -4
  280. package/dist/es-ops/operations-schema.d.ts +1 -1
  281. package/dist/es-ops/runner.d.ts +3 -3
  282. package/dist/es-ops/runner.js +9 -1
  283. package/dist/es-ops/types.d.ts +2 -2
  284. package/dist/event-store/admin-api.d.ts +3 -3
  285. package/dist/event-store/archive.d.ts +2 -2
  286. package/dist/event-store/event-store.d.ts +2 -2
  287. package/dist/event-store/events-schema.d.ts +1 -1
  288. package/dist/event-store/index.d.ts +15 -15
  289. package/dist/event-store/provenance-append.d.ts +3 -3
  290. package/dist/event-store/rebuild-dead-letter.d.ts +2 -2
  291. package/dist/event-store/row-to-stored-event.d.ts +2 -2
  292. package/dist/event-store/snapshot.d.ts +2 -2
  293. package/dist/event-store/tenant-db-append.d.ts +2 -2
  294. package/dist/event-store/transfer.d.ts +3 -3
  295. package/dist/event-store/upcaster-dead-letter.d.ts +2 -2
  296. package/dist/event-store/upcaster.d.ts +3 -3
  297. package/dist/files/assert-file-refs-belong-to-tenant.d.ts +2 -2
  298. package/dist/files/bind-pending-file-refs.d.ts +3 -3
  299. package/dist/files/create-file-ref-from-bytes.d.ts +4 -4
  300. package/dist/files/create-file-ref.d.ts +3 -3
  301. package/dist/files/dispose-removed-file-refs.d.ts +2 -2
  302. package/dist/files/feature.d.ts +3 -3
  303. package/dist/files/file-handle.d.ts +1 -1
  304. package/dist/files/file-ref-entity.d.ts +1 -1
  305. package/dist/files/file-ref-table.d.ts +1 -1
  306. package/dist/files/file-routes.d.ts +5 -5
  307. package/dist/files/in-memory-provider.d.ts +1 -1
  308. package/dist/files/index.d.ts +20 -20
  309. package/dist/files/load-save-file-refs.d.ts +2 -2
  310. package/dist/files/local-provider.d.ts +1 -1
  311. package/dist/files/provider-resolver.d.ts +5 -5
  312. package/dist/files/purge-expired-file-ref-bytes.d.ts +2 -2
  313. package/dist/files/record-read-check.d.ts +1 -1
  314. package/dist/files/record-write-check.d.ts +3 -3
  315. package/dist/files/storage-tracking.d.ts +2 -2
  316. package/dist/files/types.d.ts +1 -1
  317. package/dist/files/zip-stream.d.ts +1 -1
  318. package/dist/i18n/index.d.ts +4 -4
  319. package/dist/i18n/mail-registry.d.ts +1 -1
  320. package/dist/i18n/required-surface-keys.d.ts +1 -1
  321. package/dist/i18n/settings-hub-keys.d.ts +1 -1
  322. package/dist/internal/stack-support.d.ts +12 -12
  323. package/dist/internal/testing.d.ts +4 -4
  324. package/dist/jobs/index.d.ts +2 -2
  325. package/dist/jobs/job-runner.d.ts +1 -1
  326. package/dist/jobs/max-per-tenant.d.ts +1 -1
  327. package/dist/lifecycle/index.d.ts +2 -2
  328. package/dist/lifecycle/lifecycle.d.ts +1 -1
  329. package/dist/lifecycle/signal-handlers.d.ts +1 -1
  330. package/dist/logging/index.d.ts +4 -4
  331. package/dist/logging/pino-logger.d.ts +1 -1
  332. package/dist/logging/utils.d.ts +1 -1
  333. package/dist/migrations/index.d.ts +4 -4
  334. package/dist/migrations/kumiko-drift.d.ts +1 -1
  335. package/dist/migrations/pending-rebuilds.d.ts +5 -5
  336. package/dist/migrations/pii-event-backfill.d.ts +4 -4
  337. package/dist/migrations/projection-table-index.d.ts +1 -1
  338. package/dist/observability/console-provider.d.ts +1 -1
  339. package/dist/observability/context.d.ts +1 -1
  340. package/dist/observability/escape-hatch-report.d.ts +3 -3
  341. package/dist/observability/fallback.d.ts +1 -1
  342. package/dist/observability/index.d.ts +16 -16
  343. package/dist/observability/metric-validator.d.ts +1 -1
  344. package/dist/observability/metrics-handle.d.ts +1 -1
  345. package/dist/observability/metrics-wiring.d.ts +2 -2
  346. package/dist/observability/noop-provider.d.ts +1 -1
  347. package/dist/observability/prometheus-meter.d.ts +1 -1
  348. package/dist/observability/recording-meter.d.ts +1 -1
  349. package/dist/observability/recording-tracer.d.ts +1 -1
  350. package/dist/observability/redis-wrapper.d.ts +1 -1
  351. package/dist/observability/sensitive-filter.d.ts +1 -1
  352. package/dist/observability/standard-metrics.d.ts +1 -1
  353. package/dist/pipeline/active-membership.d.ts +4 -4
  354. package/dist/pipeline/append-event-core.d.ts +3 -3
  355. package/dist/pipeline/auth-claims-resolver.d.ts +2 -2
  356. package/dist/pipeline/cascade-handler.d.ts +3 -3
  357. package/dist/pipeline/dispatch-batch.d.ts +2 -2
  358. package/dist/pipeline/dispatch-query.d.ts +4 -4
  359. package/dist/pipeline/dispatch-shared.d.ts +17 -17
  360. package/dist/pipeline/dispatch-stream.d.ts +2 -2
  361. package/dist/pipeline/dispatch-write.d.ts +4 -4
  362. package/dist/pipeline/dispatcher-utils.d.ts +2 -2
  363. package/dist/pipeline/dispatcher.d.ts +12 -12
  364. package/dist/pipeline/event-consumer-state.d.ts +1 -1
  365. package/dist/pipeline/event-dispatcher-admin.d.ts +1 -1
  366. package/dist/pipeline/event-dispatcher-delivery.d.ts +7 -7
  367. package/dist/pipeline/event-dispatcher.d.ts +7 -7
  368. package/dist/pipeline/event-retention.d.ts +1 -1
  369. package/dist/pipeline/handler-access-error.d.ts +2 -2
  370. package/dist/pipeline/index.d.ts +42 -42
  371. package/dist/pipeline/irreversible-operation-gate.d.ts +1 -1
  372. package/dist/pipeline/lifecycle-pipeline.d.ts +2 -2
  373. package/dist/pipeline/member-read-only-transaction.d.ts +2 -2
  374. package/dist/pipeline/member-reader.d.ts +5 -5
  375. package/dist/pipeline/msp-rebuild.d.ts +4 -4
  376. package/dist/pipeline/multi-stream-apply-context.d.ts +3 -3
  377. package/dist/pipeline/notify-scope.d.ts +3 -3
  378. package/dist/pipeline/pending-gap-ranges.d.ts +2 -2
  379. package/dist/pipeline/pre-handler-gates.d.ts +3 -3
  380. package/dist/pipeline/pre-transaction-reservations.d.ts +4 -4
  381. package/dist/pipeline/projection-rebuild.d.ts +3 -3
  382. package/dist/pipeline/projection-state.d.ts +1 -1
  383. package/dist/pipeline/projections-runner.d.ts +3 -3
  384. package/dist/pipeline/projections-runner.js +3 -4
  385. package/dist/pipeline/system-hooks.d.ts +4 -4
  386. package/dist/pipeline/system-identity-switch.d.ts +3 -3
  387. package/dist/pipeline/tenant-timezone-cache.d.ts +1 -1
  388. package/dist/pipeline/write-origin.d.ts +3 -3
  389. package/dist/pipeline/write-result-masking.d.ts +2 -2
  390. package/dist/random/index.d.ts +2 -2
  391. package/dist/rate-limit/bucket.d.ts +1 -1
  392. package/dist/rate-limit/index.d.ts +3 -3
  393. package/dist/rate-limit/middleware.d.ts +3 -3
  394. package/dist/redis/cache-sync-bus.d.ts +2 -2
  395. package/dist/redis/cache-sync-topics.d.ts +1 -1
  396. package/dist/redis/index.d.ts +8 -8
  397. package/dist/redis/pubsub-signal.d.ts +1 -1
  398. package/dist/schema-cli.d.ts +1 -1
  399. package/dist/schema-cli.js +9 -1
  400. package/dist/search/derive-search-adapter-config.d.ts +2 -2
  401. package/dist/search/in-memory-adapter.d.ts +1 -1
  402. package/dist/search/index.d.ts +6 -6
  403. package/dist/search/meilisearch-adapter.d.ts +2 -2
  404. package/dist/search/purge-subject.d.ts +4 -4
  405. package/dist/search/reindex-entity.d.ts +3 -3
  406. package/dist/secrets/dek-cache.d.ts +1 -1
  407. package/dist/secrets/env-master-key-provider.d.ts +1 -1
  408. package/dist/secrets/env-master-key-provider.js +26 -11
  409. package/dist/secrets/envelope-cipher.d.ts +2 -2
  410. package/dist/secrets/envelope.d.ts +1 -1
  411. package/dist/secrets/index.d.ts +9 -9
  412. package/dist/secrets/rotation.d.ts +1 -1
  413. package/dist/secrets/stored-envelope.d.ts +1 -1
  414. package/dist/seeding/entity-seed.d.ts +1 -1
  415. package/dist/seeding/index.d.ts +3 -3
  416. package/dist/seeding/seed-users.d.ts +1 -1
  417. package/dist/time/index.d.ts +6 -6
  418. package/dist/ui-types/app-schema.d.ts +5 -5
  419. package/dist/ui-types/index.d.ts +23 -23
  420. package/dist/upgrade-cli.js +13 -3
  421. package/dist/utils/index.d.ts +9 -9
  422. package/package.json +19 -66
  423. package/presets/biome-app.json +80 -0
  424. package/presets/tsconfig.app.json +19 -0
  425. package/src/changes.json +78 -2
  426. package/src/scripts/codemod/README.md +18 -0
  427. package/src/scripts/codemod/codemod-support.ts +1 -1
  428. package/src/scripts/codemod/db-factory.ts +1 -1
  429. package/src/scripts/codemod/feature-factory.ts +1 -1
  430. package/src/scripts/codemod/import-extensions.ts +118 -0
  431. package/src/scripts/codemod/migrate-cross-tenant.ts +2 -2
  432. package/src/scripts/codemod/migrate-db-raw.ts +1 -1
  433. package/src/scripts/codemod/migrate-open-to-all.ts +1 -1
  434. package/src/scripts/codemod/object-form.ts +1 -1
  435. package/src/scripts/codemod/s3-imports.ts +1 -1
  436. package/src/scripts/codemod/tenant-db-options.ts +1 -1
  437. package/src/scripts/codemod/testing-move.ts +2 -2
  438. package/dist/db/bun-db-deprecated.d.ts +0 -10
  439. package/dist/db/bun-db-deprecated.js +0 -5
  440. package/dist/stack/index.d.ts +0 -10
  441. package/dist/stack/index.js +0 -11
  442. package/dist/testing/e2e-generator.d.ts +0 -5
  443. package/dist/testing/e2e-generator.js +0 -5
  444. package/dist/testing/handler-context.d.ts +0 -5
  445. package/dist/testing/handler-context.js +0 -5
  446. package/dist/testing/index.d.ts +0 -10
  447. package/dist/testing/index.js +0 -10
  448. package/dist/testing/real-providers.d.ts +0 -5
  449. package/dist/testing/real-providers.js +0 -5
package/AGENTS.md CHANGED
@@ -135,6 +135,7 @@ The scaffold (`bun create kumiko-app <name>`) produces this layout. Keep it.
135
135
 
136
136
  | Path | Content |
137
137
  | --- | --- |
138
+ | `kumiko.config.ts` | `defineAppConfig({ features, prodFeatures?, client, ports })`: the one list the tooling reads |
138
139
  | `src/run-config.ts` | `APP_FEATURES`, the mounted feature list |
139
140
  | `src/features/<name>/feature.ts` | `defineFeature(...)` with entities, handlers, screens, navs |
140
141
  | `src/features/<name>/index.ts` | Public exports of the feature |
@@ -143,7 +144,17 @@ The scaffold (`bun create kumiko-app <name>`) produces this layout. Keep it.
143
144
  | `src/__tests__/*.test.ts` | Unit tests, no services |
144
145
  | `src/__tests__/*.integration.test.ts` | Integration tests against Postgres and Redis |
145
146
  | `e2e/*.spec.ts` | Playwright tests against a booted app |
146
- | `kumiko/schema.ts`, `kumiko/migrations/` | Database schema and generated migrations |
147
+ | `kumiko/schema.ts`, `kumiko/migrations/` | Generated schema shim over `kumiko.config.ts`, and the migrations |
148
+ | `bin/server.ts`, `bin/main.ts`, `bin/env-schema.ts` | Dev server, production boot, env contract |
149
+ | `e2e/_helpers/`, `src/__tests__/_setup.ts` | Shared e2e helpers and the shared integration stack setup |
150
+
151
+ Files whose first line reads `kumiko-managed` (deploy/, `.github/workflows/`,
152
+ `.husky/pre-push`, the bunfigs, `kumiko/schema.ts`) belong to the framework.
153
+ `bun run check` reports drift against the installed version and
154
+ `bunx kumiko sync-managed --write` restores them. Keep a deliberate change with
155
+ `# kumiko-managed: local <reason>` on line 2. `biome.json` and `tsconfig.json`
156
+ extend `@cosmicdrift/kumiko-framework/biome` and `.../tsconfig.app.json`; put
157
+ app overrides next to `extends`. Full list: `docs/reference/app-skeleton.md`.
147
158
 
148
159
  The scaffolded `src/features/tasks/feature.ts` and
149
160
  `src/__tests__/tasks.integration.test.ts` are the smallest complete pair of
@@ -155,6 +166,8 @@ feature and test. Start from them.
155
166
  | --- | --- |
156
167
  | Run the app with demo data | `bun dev` |
157
168
  | Boot validation without serving | `bun run boot` |
169
+ | Boot, guards, managed files and script standard | `bun run check` |
170
+ | Restore framework-owned files | `bunx kumiko sync-managed --write` |
158
171
  | Types | `bun run typecheck` |
159
172
  | Lint | `bun run lint` |
160
173
  | Unit tests | `bun run test` |
@@ -81,6 +81,7 @@ anonymous **email-verified** deletion flow from `user-data-rights`:
81
81
 
82
82
  ```ts illustration
83
83
  runProdApp({
84
+ envSchema, // composeEnvSchema({ core: frameworkCoreEnvSchema, features })
84
85
  features: composeApexAccountApp({
85
86
  deletionTokenSecret: process.env.DELETION_TOKEN_SECRET!,
86
87
  deletionVerifyUrl: "https://app.example.com/delete-account/confirm",
@@ -299,7 +300,7 @@ describe("apex-surface-auth recipe", () => {
299
300
  // SERVER-WIRING: die App aktiviert `anonymousAccess` (defaultTenantId = der
300
301
  // Apex-Host-Tenant), damit /api/write die anonymen Deletion-Handler erreicht:
301
302
  //
302
- // runProdApp({ features: composeApexAccountApp({...}),
303
+ // runProdApp({ features: composeApexAccountApp({...}), envSchema,
303
304
  // anonymousAccess: { defaultTenantId: APEX_TENANT_ID } })
304
305
 
305
306
  import { createAuthEmailPasswordFeature } from "@cosmicdrift/kumiko-bundled-features/auth-email-password";
@@ -0,0 +1,98 @@
1
+ <!-- Generated by `bun run gen:agent-docs` from samples/recipes/app-config. Do not edit. -->
2
+
3
+ # app-config
4
+
5
+ kumiko.config.ts with defineAppConfig: the one feature list, client entries and ports the tooling reads.
6
+
7
+ ## README
8
+
9
+ # App config
10
+
11
+ `kumiko.config.ts` is the one place an app names its features, client entries
12
+ and ports. `kumiko/schema.ts`, `kumiko agent lint`, `kumiko check` and
13
+ `kumiko ports` all read it.
14
+
15
+ ## What it shows
16
+
17
+ - **`defineAppConfig`** from `@cosmicdrift/kumiko-framework/config` validates the
18
+ config when the file loads: ports in range and unique within the app, client
19
+ entries relative and inside the app.
20
+ - **`prodFeatures`** are mounted only in production (provider features such as
21
+ S3 or SMTP). `allAppFeatures(config)` returns `features` plus `prodFeatures`;
22
+ that is the list migrations and agent lint check.
23
+ - **`ports`** with `dev`, `e2e` and optional `infra` (`postgres`, `redis`,
24
+ `meilisearch`, `s3`). Keep them number literals: `kumiko ports` reads them
25
+ statically across all apps of a workspace and reports collisions.
26
+
27
+ ## Files
28
+
29
+ ```
30
+ kumiko.config.ts defineAppConfig with features, prodFeatures, client, ports
31
+ src/feature.ts two placeholder features
32
+ src/__tests__/app-config.test.ts feature list, port list, validation errors
33
+ ```
34
+
35
+ See [`docs/reference/app-skeleton.md`](../../../docs/reference/app-skeleton.md)
36
+ for the files around it.
37
+
38
+ ## Source files
39
+
40
+ ### src/__tests__/app-config.test.ts
41
+
42
+ ```ts
43
+ import { describe, expect, test } from "bun:test";
44
+ import {
45
+ allAppFeatures,
46
+ defineAppConfig,
47
+ findAppPortProblems,
48
+ listAppPorts,
49
+ } from "@cosmicdrift/kumiko-framework/config";
50
+ import appConfig from "../../kumiko.config";
51
+ import { notesFeature } from "../feature";
52
+
53
+ describe("kumiko.config.ts", () => {
54
+ test("schema, agent lint and boot see features plus prodFeatures", () => {
55
+ expect(allAppFeatures(appConfig).map((feature) => feature.name)).toEqual([
56
+ "notes",
57
+ "audit-export",
58
+ ]);
59
+ });
60
+
61
+ test("ports list every claim, infrastructure included", () => {
62
+ expect(listAppPorts(appConfig.ports)).toEqual([
63
+ { role: "dev", port: 4510 },
64
+ { role: "e2e", port: 4511 },
65
+ { role: "postgres", port: 15510 },
66
+ ]);
67
+ });
68
+
69
+ test("defineAppConfig rejects a port claimed twice inside the app", () => {
70
+ const ports = { dev: 4510, e2e: 4510 };
71
+ expect(findAppPortProblems(ports)).not.toEqual([]);
72
+ expect(() =>
73
+ defineAppConfig({ features: [notesFeature], client: { entries: ["src/client.tsx"] }, ports }),
74
+ ).toThrow();
75
+ });
76
+
77
+ test("client entries must stay inside the app", () => {
78
+ expect(() =>
79
+ defineAppConfig({
80
+ features: [notesFeature],
81
+ client: { entries: ["../other-app/src/client.tsx"] },
82
+ ports: { dev: 4510, e2e: 4511 },
83
+ }),
84
+ ).toThrow();
85
+ });
86
+ });
87
+ ```
88
+
89
+ ### src/feature.ts
90
+
91
+ ```ts
92
+ import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
93
+
94
+ export const notesFeature = defineFeature("notes", () => {});
95
+
96
+ // Stands in for a provider feature that only production mounts (S3, SMTP).
97
+ export const auditExportFeature = defineFeature("audit-export", () => {});
98
+ ```
@@ -61,6 +61,19 @@ const server = buildServer({
61
61
 
62
62
  Apps built via `runDevApp`/`runProdApp` (the dev-server bootstrap used by `create-kumiko-app`) get all of this automatically — just add `createAuthMfaFeature(...)` to `APP_FEATURES`. `composeFeatures` threads the status-checker and the bootstrap wires the session-revoke bind and the verify route for you. This sample shows the raw contract those helpers implement.
63
63
 
64
+ ## Self-service screen
65
+
66
+ `createAccountSecurityFeature({ nav?, access? })` adds one screen,
67
+ `account-security:screen:account-security`, that embeds the MFA enable,
68
+ regenerate and disable screens plus the own-sessions list. It owns no handlers
69
+ and needs no `composeAuthStack`: mount it next to `auth-mfa` and `sessions`.
70
+ Without `nav` the screen stays dormant (reachable by its route, no sidebar
71
+ entry); `access` defaults to every signed-in user.
72
+
73
+ ```ts illustration
74
+ features: [..., createSessionsFeature(), mfaFeature, createAccountSecurityFeature({ nav: { order: 90 } })]
75
+ ```
76
+
64
77
  ## Design rules
65
78
 
66
79
  1. **Enrollment is stateless until confirmed.** `enable-start` returns a signed setup token (QR + secret + 8 recovery codes) — nothing is persisted until `enable-confirm` proves the user scanned it with a valid TOTP code.
@@ -74,9 +87,61 @@ Apps built via `runDevApp`/`runProdApp` (the dev-server bootstrap used by `creat
74
87
 
75
88
  - **Baseline:** a user without MFA enrolled still gets a JWT straight from `/auth/login`.
76
89
  - **End-to-end:** enroll via `enable-start`/`enable-confirm`, log in (gets a challenge, no JWT), complete via `/auth/mfa/verify` (gets a JWT) — copies the `buildServer({ auth: ... })` block from the sample comment verbatim.
90
+ - **Account security:** the composed screen boot-validates next to `auth-mfa` and `sessions` and shows a sidebar entry once `nav` is set.
77
91
 
78
92
  ## Source files
79
93
 
94
+ ### src/__tests__/account-security.test.ts
95
+
96
+ ```ts
97
+ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
98
+ import { createAuthFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/auth-foundation";
99
+ import { createConfigFeature } from "@cosmicdrift/kumiko-bundled-features/config";
100
+ import { createPersonalAccessTokensFeature } from "@cosmicdrift/kumiko-bundled-features/personal-access-tokens";
101
+ import { createSessionsFeature } from "@cosmicdrift/kumiko-bundled-features/sessions";
102
+ import { createTenantFeature } from "@cosmicdrift/kumiko-bundled-features/tenant";
103
+ import { createUserFeature } from "@cosmicdrift/kumiko-bundled-features/user";
104
+ import { configureEntityFieldEncryption } from "@cosmicdrift/kumiko-framework/db";
105
+ import { validateBoot } from "@cosmicdrift/kumiko-framework/engine";
106
+ import { createTestEnvelopeCipher } from "@cosmicdrift/kumiko-testing/helpers";
107
+ import {
108
+ ACCOUNT_SECURITY_SCREEN_QN,
109
+ createAccountSecurityFeature,
110
+ createAuthMfaFeature,
111
+ } from "../feature";
112
+
113
+ const mfaFeature = createAuthMfaFeature({
114
+ setupTokenSecret: "sample-setup-token-secret-not-for-prod",
115
+ challengeTokenSecret: "sample-mfa-challenge-secret-at-least-32-bytes",
116
+ issuer: "Kumiko Sample",
117
+ });
118
+
119
+ describe("account-security next to auth-mfa", () => {
120
+ // user-mfa has encrypted fields, so boot validation needs a cipher.
121
+ beforeAll(() => configureEntityFieldEncryption(createTestEnvelopeCipher()));
122
+ afterAll(() => configureEntityFieldEncryption(undefined));
123
+
124
+ test("boot-validates without composeAuthStack and adds a sidebar entry with nav", () => {
125
+ const accountSecurity = createAccountSecurityFeature({ nav: { order: 90 } });
126
+ expect(() =>
127
+ validateBoot([
128
+ createConfigFeature(),
129
+ createUserFeature(),
130
+ createTenantFeature(),
131
+ createAuthFoundationFeature(),
132
+ createPersonalAccessTokensFeature({ scopes: {} }),
133
+ createSessionsFeature(),
134
+ mfaFeature,
135
+ accountSecurity,
136
+ ]),
137
+ ).not.toThrow();
138
+ expect(Object.values(accountSecurity.navs).map((nav) => nav.screen)).toEqual([
139
+ ACCOUNT_SECURITY_SCREEN_QN,
140
+ ]);
141
+ });
142
+ });
143
+ ```
144
+
80
145
  ### src/__tests__/feature.integration.test.ts
81
146
 
82
147
  ```ts
@@ -306,6 +371,13 @@ describe("auth-mfa sample wiring", () => {
306
371
  // complete exactly one login challenge, then it's burned.
307
372
  // 4. Every MFA state change signs out every OTHER live session (stolen-
308
373
  // session defense) — but never the session that made the change.
374
+
375
+ // One self-service screen for MFA and own sessions. Dormant until `nav` is
376
+ // set, so apps that mount it only for deep links get no sidebar entry.
377
+ export {
378
+ ACCOUNT_SECURITY_SCREEN_QN,
379
+ createAccountSecurityFeature,
380
+ } from "@cosmicdrift/kumiko-bundled-features/account-security";
309
381
  export {
310
382
  AuthMfaHandlers,
311
383
  base32Decode,
@@ -0,0 +1,188 @@
1
+ <!-- Generated by `bun run gen:agent-docs` from samples/recipes/compose-stacks. Do not edit. -->
2
+
3
+ # compose-stacks
4
+
5
+ compose*Stack helpers for auth, security, GDPR and SaaS billing, and the runProdApp check that names a stack whose boot option is missing.
6
+
7
+ ## README
8
+
9
+ # Compose stacks
10
+
11
+ Mount the auth, security, GDPR and SaaS features through the `compose*Stack`
12
+ helpers from `@cosmicdrift/kumiko-dev-server/compose-stacks` instead of
13
+ listing each feature and its require order by hand. A stack that depends on a
14
+ `runProdApp` option marks that on its features (`bootRequires`), and
15
+ `runProdApp` refuses to boot when the option is missing, naming the stack and
16
+ the option.
17
+
18
+ ## What it shows
19
+
20
+ - **`composeAuthStack({ mfa, sessions })`**: `auth-foundation`, `sessions`,
21
+ and with `mfa` also `auth-mfa` plus `account-security`. The password login
22
+ itself still comes from the `auth` option or `composeFeatures`.
23
+ - **`composeSecurityStack({ includeSessions })`**: `sessions`,
24
+ `crypto-shredding`, `rate-limiting` and `audit`. Needs a KMS decision
25
+ (`kmsMode`) and fails with `rateLimit: false`. Replaces
26
+ `securityBaselineFeatures()`.
27
+ - **`composeGdprStack({ tenantLifecycle, selfService })`**: `data-retention`
28
+ and `compliance-profiles`, optionally `tenant-lifecycle`. `selfService` adds
29
+ `sessions`, `user-data-rights` and `user-profile` (needs `mail`) and
30
+ replaces `dsgvoSelfServiceFeatures()`.
31
+ - **`composeSaasStack({ billing, tiers, caps, waitlist })`**:
32
+ `billing-foundation` and `tier-engine`, plus `cap-counter`/`cap-overview`
33
+ and `waitlist` when configured. `billing: "stripe"` leaves
34
+ `subscription-stripe` to the `billing` boot option, which also mounts the
35
+ tier-sync webhook route; `billing: "mollie"` mounts `subscription-mollie`
36
+ itself.
37
+
38
+ ## Boot requirements
39
+
40
+ | Stack | Boot option | Also satisfied by |
41
+ | --- | --- | --- |
42
+ | `composeMailStack` | `mail` | a mounted `channel-email` |
43
+ | `composeFileStack` without providers | `fileStorage` | a mounted file provider |
44
+ | `composeGdprStack` | `kmsMode` | `kms` or `allowPlaintextPii` |
45
+ | `composeGdprStack({ selfService })`, `composeUserDataRightsStack` | `mail` | a mounted `channel-email` |
46
+ | `composeSecurityStack` | `kmsMode`, `rateLimit` not `false` | `kms` or `allowPlaintextPii` |
47
+ | `composeSaasStack({ billing: "stripe" })` | `billing` | a mounted subscription provider |
48
+
49
+ A missing option fails the boot with:
50
+
51
+ ```
52
+ [runProdApp] stacks in `features` need boot options that are not set:
53
+ - composeSaasStack needs the boot option `billing`: set billing: { stripe: { priceToTier }, defaultTier }
54
+ ```
55
+
56
+ ## Flow
57
+
58
+ 1. `src/app.ts` lists the stacks and the boot options they need.
59
+ 2. The test boots with `KUMIKO_DRY_RUN_ENV=boot`, which runs the whole
60
+ validation and stops before any DB or Redis connection: with the options
61
+ the boot passes, without `billing` or `kmsMode` it fails and names the
62
+ stacks.
63
+
64
+ ## Tests
65
+
66
+ ```bash
67
+ bun test samples/recipes/compose-stacks
68
+ ```
69
+
70
+ ## Source files
71
+
72
+ ### src/__tests__/app.test.ts
73
+
74
+ ```ts
75
+ // KUMIKO_DRY_RUN_ENV=boot runs the full wiring check and stops before any
76
+ // DB/Redis connection, so the stack requirements are checked without infra.
77
+
78
+ import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test";
79
+ import { randomBytes } from "node:crypto";
80
+ import { composeEnvSchema } from "@cosmicdrift/kumiko-framework/env";
81
+ import { type RunProdAppOptions, runProdApp } from "@cosmicdrift/kumiko-server-runtime";
82
+ import { appFeatures, bootOptions } from "../app";
83
+
84
+ const PRODUCTION_BOOT_ENV: Readonly<Record<string, string>> = {
85
+ DATABASE_URL: "postgres://recipe:recipe@127.0.0.1:1/recipe",
86
+ REDIS_URL: "redis://127.0.0.1:1",
87
+ JWT_SECRET: "r".repeat(32),
88
+ KUMIKO_DRY_RUN_ENV: "boot",
89
+ NODE_ENV: "production",
90
+ PLATFORM_KEK: randomBytes(32).toString("base64"),
91
+ SUBJECT_KEYS_DATABASE_URL: "postgres://kms:kms@127.0.0.1:1/subject_keys",
92
+ KUMIKO_BLIND_INDEX_KEY: randomBytes(32).toString("base64"),
93
+ };
94
+
95
+ async function bootValidate(options: Pick<RunProdAppOptions, "kmsMode" | "billing">) {
96
+ const handle = await runProdApp({
97
+ features: appFeatures(),
98
+ envSchema: composeEnvSchema({ features: [] }),
99
+ autoListen: false,
100
+ migrations: false,
101
+ envSource: { ...PRODUCTION_BOOT_ENV },
102
+ ...options,
103
+ });
104
+ await handle.stop();
105
+ }
106
+
107
+ describe("compose stacks recipe", () => {
108
+ let logSpy: ReturnType<typeof spyOn>;
109
+ let warnSpy: ReturnType<typeof spyOn>;
110
+ beforeEach(() => {
111
+ logSpy = spyOn(console, "log").mockImplementation(() => {});
112
+ warnSpy = spyOn(console, "warn").mockImplementation(() => {});
113
+ });
114
+ afterEach(() => {
115
+ logSpy.mockRestore();
116
+ warnSpy.mockRestore();
117
+ });
118
+
119
+ test("the stacks with their boot options pass boot validation", async () => {
120
+ await bootValidate(bootOptions());
121
+ const lines = logSpy.mock.calls.map((call: unknown[]) => String(call[0]));
122
+ expect(lines.some((line: string) => line.includes("boot validation OK"))).toBe(true);
123
+ });
124
+
125
+ test("a missing billing option names composeSaasStack and the option", async () => {
126
+ const { billing: _billing, ...withoutBilling } = bootOptions();
127
+ await expect(bootValidate(withoutBilling)).rejects.toThrow(
128
+ "composeSaasStack needs the boot option `billing`",
129
+ );
130
+ });
131
+
132
+ test("a missing KMS decision names every stack that needs it", async () => {
133
+ const { kmsMode: _kmsMode, ...withoutKms } = bootOptions();
134
+ const failure = bootValidate(withoutKms);
135
+ await expect(failure).rejects.toThrow("composeSecurityStack needs the boot option `kmsMode`");
136
+ await expect(failure).rejects.toThrow("composeGdprStack needs the boot option `kmsMode`");
137
+ });
138
+ });
139
+ ```
140
+
141
+ ### src/app.ts
142
+
143
+ ```ts
144
+ import { createConfigFeature } from "@cosmicdrift/kumiko-bundled-features/config";
145
+ import { createSecretsFeature } from "@cosmicdrift/kumiko-bundled-features/secrets";
146
+ import { createTenantFeature } from "@cosmicdrift/kumiko-bundled-features/tenant";
147
+ import { createUserFeature } from "@cosmicdrift/kumiko-bundled-features/user";
148
+ import {
149
+ composeAuthStack,
150
+ composeGdprStack,
151
+ composeSaasStack,
152
+ composeSecurityStack,
153
+ } from "@cosmicdrift/kumiko-dev-server/compose-stacks";
154
+ import type { RunProdAppOptions } from "@cosmicdrift/kumiko-server-runtime";
155
+
156
+ export const PRO_PRICE_ID = "price_pro_monthly";
157
+
158
+ export function appFeatures(): RunProdAppOptions["features"] {
159
+ return [
160
+ createConfigFeature(),
161
+ createSecretsFeature(),
162
+ createUserFeature(),
163
+ createTenantFeature(),
164
+ ...composeAuthStack(),
165
+ ...composeSecurityStack(),
166
+ ...composeGdprStack({ tenantLifecycle: true }),
167
+ ...composeSaasStack({
168
+ billing: "stripe",
169
+ tiers: {
170
+ defaultTier: "free",
171
+ tierMap: {
172
+ free: { features: [], caps: { seats: 1 } },
173
+ pro: { features: [], caps: { seats: 25 } },
174
+ },
175
+ },
176
+ }),
177
+ ];
178
+ }
179
+
180
+ type StackBootOptions = Pick<RunProdAppOptions, "kmsMode" | "billing">;
181
+
182
+ export function bootOptions(): StackBootOptions {
183
+ return {
184
+ kmsMode: "required",
185
+ billing: { stripe: { priceToTier: { [PRO_PRICE_ID]: "pro" } }, defaultTier: "free" },
186
+ };
187
+ }
188
+ ```