@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.
Files changed (468) hide show
  1. package/AGENTS.md +6 -1
  2. package/LICENSE +21 -57
  3. package/README.md +2 -2
  4. package/agents/examples/anonymous-access.md +1 -1
  5. package/agents/examples/apex-landing.md +204 -0
  6. package/agents/examples/api-worker-split.md +64 -0
  7. package/agents/examples/app-config.md +14 -0
  8. package/agents/examples/auth-mfa.md +115 -0
  9. package/agents/examples/env-composition.md +28 -1
  10. package/agents/examples/legal-pages.md +1 -1
  11. package/agents/examples/prod-boot-options.md +16 -0
  12. package/agents/examples/rate-limiting.md +48 -0
  13. package/agents/examples/record-detail-layout.md +692 -0
  14. package/agents/examples/seed-migration.md +212 -0
  15. package/agents/examples/wizard-form.md +941 -0
  16. package/agents/examples/writeform-section.md +548 -0
  17. package/agents/features.md +19 -2
  18. package/agents/widgets.md +40 -39
  19. package/dist/api/api-constants.js +2 -2
  20. package/dist/api/auth-middleware.js +7 -7
  21. package/dist/api/auth-rate-limiters.js +7 -3
  22. package/dist/api/auth-routes-mfa.js +1 -1
  23. package/dist/api/auth-routes-session.js +1 -1
  24. package/dist/api/auth-routes-shared.js +7 -3
  25. package/dist/api/auth-routes-signup.js +1 -1
  26. package/dist/api/client-error-route.js +8 -2
  27. package/dist/api/client-ip.js +3 -1
  28. package/dist/api/extra-route.js +1 -1
  29. package/dist/api/index.d.ts +3 -1
  30. package/dist/api/index.js +3 -1
  31. package/dist/api/pii-leak-guard.js +4 -2
  32. package/dist/api/readiness.js +5 -5
  33. package/dist/api/redis-sse-broker.js +8 -6
  34. package/dist/api/request-context.d.ts +1 -1
  35. package/dist/api/request-context.js +1 -1
  36. package/dist/api/routes.js +2 -2
  37. package/dist/api/server-boot-checks.d.ts +10 -0
  38. package/dist/api/server-boot-checks.js +157 -0
  39. package/dist/api/server-event-dispatcher.d.ts +26 -0
  40. package/dist/api/server-event-dispatcher.js +208 -0
  41. package/dist/api/server-extra-routes.d.ts +11 -0
  42. package/dist/api/server-extra-routes.js +203 -0
  43. package/dist/api/server-middleware.d.ts +20 -0
  44. package/dist/api/server-middleware.js +211 -0
  45. package/dist/api/server-routes.d.ts +19 -0
  46. package/dist/api/server-routes.js +293 -0
  47. package/dist/api/server-websocket-routes.d.ts +4 -0
  48. package/dist/api/server-websocket-routes.js +108 -0
  49. package/dist/api/server-wiring.d.ts +32 -0
  50. package/dist/api/server-wiring.js +236 -0
  51. package/dist/api/server.d.ts +10 -15
  52. package/dist/api/server.js +48 -1250
  53. package/dist/api/session-cookies.js +4 -4
  54. package/dist/api/sse-broker.js +1 -1
  55. package/dist/api/sse-route.d.ts +13 -13
  56. package/dist/api/sse-route.js +31 -27
  57. package/dist/auth/index.js +4 -4
  58. package/dist/auth/roles.d.ts +4 -4
  59. package/dist/auth/roles.js +24 -24
  60. package/dist/compliance/duration-spec.js +18 -20
  61. package/dist/compliance/index.js +2 -3
  62. package/dist/compliance/override-schema.d.ts +4 -4
  63. package/dist/compliance/override-schema.js +19 -22
  64. package/dist/compliance/profiles.d.ts +26 -29
  65. package/dist/compliance/profiles.js +62 -69
  66. package/dist/compliance/sub-processors.d.ts +28 -30
  67. package/dist/compliance/sub-processors.js +17 -21
  68. package/dist/consumer-cli.js +4 -4
  69. package/dist/crypto/blind-index.js +18 -17
  70. package/dist/crypto/ciphertext-pattern.js +1 -1
  71. package/dist/crypto/event-pii.js +3 -3
  72. package/dist/crypto/kek-source.d.ts +1 -1
  73. package/dist/crypto/kek-source.js +3 -2
  74. package/dist/crypto/kms-adapter.d.ts +1 -1
  75. package/dist/crypto/kms-adapter.js +4 -6
  76. package/dist/crypto/kms-wiring.d.ts +1 -2
  77. package/dist/crypto/kms-wiring.js +2 -2
  78. package/dist/crypto/owner-transition-rekey.d.ts +5 -1
  79. package/dist/crypto/owner-transition-rekey.js +1 -1
  80. package/dist/crypto/pg-kms-adapter.js +2 -6
  81. package/dist/crypto/pii-field-encryption.d.ts +5 -1
  82. package/dist/crypto/pii-field-encryption.js +7 -5
  83. package/dist/crypto/subject-resolver.d.ts +1 -1
  84. package/dist/crypto/subject-resolver.js +2 -2
  85. package/dist/db/aggregate-sql.d.ts +21 -0
  86. package/dist/db/aggregate-sql.js +155 -0
  87. package/dist/db/apply-entity-event.d.ts +6 -6
  88. package/dist/db/apply-entity-event.js +55 -55
  89. package/dist/db/blind-index-cleanup.js +7 -7
  90. package/dist/db/closed-connection.d.ts +9 -0
  91. package/dist/db/closed-connection.js +95 -0
  92. package/dist/db/collect-table-metas.js +10 -11
  93. package/dist/db/compound-types.d.ts +1 -1
  94. package/dist/db/compound-types.js +12 -12
  95. package/dist/db/cursor.js +3 -4
  96. package/dist/db/dialect.d.ts +2 -2
  97. package/dist/db/dialect.js +3 -3
  98. package/dist/db/distinct-on.d.ts +1 -1
  99. package/dist/db/driver-row-coercion.d.ts +2 -0
  100. package/dist/db/driver-row-coercion.js +186 -0
  101. package/dist/db/driver-value-preparation.d.ts +16 -0
  102. package/dist/db/driver-value-preparation.js +99 -0
  103. package/dist/db/eagerload.d.ts +3 -3
  104. package/dist/db/eagerload.js +21 -12
  105. package/dist/db/entity-field-encryption.d.ts +1 -0
  106. package/dist/db/entity-field-encryption.js +1 -1
  107. package/dist/db/entity-table-meta.d.ts +2 -2
  108. package/dist/db/entity-table-meta.js +105 -112
  109. package/dist/db/event-store-executor-context.d.ts +3 -2
  110. package/dist/db/event-store-executor-context.js +13 -13
  111. package/dist/db/event-store-executor-read-aggregate.d.ts +8 -0
  112. package/dist/db/event-store-executor-read-aggregate.js +112 -0
  113. package/dist/db/event-store-executor-read-filter.d.ts +31 -0
  114. package/dist/db/event-store-executor-read-filter.js +203 -0
  115. package/dist/db/event-store-executor-read-paging.d.ts +14 -0
  116. package/dist/db/event-store-executor-read-paging.js +99 -0
  117. package/dist/db/event-store-executor-read-rows.d.ts +6 -0
  118. package/dist/db/event-store-executor-read-rows.js +32 -0
  119. package/dist/db/event-store-executor-read-search.d.ts +28 -0
  120. package/dist/db/event-store-executor-read-search.js +221 -0
  121. package/dist/db/event-store-executor-read-sort.d.ts +41 -0
  122. package/dist/db/event-store-executor-read-sort.js +130 -0
  123. package/dist/db/event-store-executor-read-where.d.ts +24 -0
  124. package/dist/db/event-store-executor-read-where.js +81 -0
  125. package/dist/db/event-store-executor-read.d.ts +2 -9
  126. package/dist/db/event-store-executor-read.js +50 -704
  127. package/dist/db/event-store-executor-write-steps.d.ts +20 -0
  128. package/dist/db/event-store-executor-write-steps.js +100 -0
  129. package/dist/db/event-store-executor-write.js +401 -510
  130. package/dist/db/index.d.ts +6 -2
  131. package/dist/db/index.js +5 -1
  132. package/dist/db/list-aggregate-labels.d.ts +14 -0
  133. package/dist/db/list-aggregate-labels.js +26 -0
  134. package/dist/db/located-timestamp.d.ts +11 -11
  135. package/dist/db/located-timestamp.js +29 -30
  136. package/dist/db/migrate-generator.d.ts +1 -1
  137. package/dist/db/migrate-generator.js +97 -105
  138. package/dist/db/migrate-runner.js +29 -26
  139. package/dist/db/money.d.ts +6 -6
  140. package/dist/db/money.js +29 -27
  141. package/dist/db/queries/backfill-pii.js +5 -5
  142. package/dist/db/queries/ddl.js +1 -1
  143. package/dist/db/queries/es-ops.d.ts +1 -1
  144. package/dist/db/queries/es-ops.js +1 -1
  145. package/dist/db/queries/event-consumer.js +3 -3
  146. package/dist/db/queries/event-store.js +4 -2
  147. package/dist/db/queries/projection-rebuild.js +3 -3
  148. package/dist/db/queries/raw-sql.d.ts +2 -2
  149. package/dist/db/queries/raw-sql.js +2 -2
  150. package/dist/db/queries/shadow-swap.js +19 -19
  151. package/dist/db/query.d.ts +3 -16
  152. package/dist/db/query.js +8 -761
  153. package/dist/db/rebuild-marker.js +20 -21
  154. package/dist/db/reference-data.js +6 -1
  155. package/dist/db/replay-migration-sql.js +2 -2
  156. package/dist/db/schema-inspection.js +4 -5
  157. package/dist/db/table-builder.d.ts +1 -2
  158. package/dist/db/table-builder.js +137 -190
  159. package/dist/db/table-info.d.ts +10 -0
  160. package/dist/db/table-info.js +45 -0
  161. package/dist/db/temporal-value-guards.d.ts +6 -0
  162. package/dist/db/temporal-value-guards.js +15 -0
  163. package/dist/db/tenant-db-runner.d.ts +1 -0
  164. package/dist/db/tenant-db-runner.js +3 -0
  165. package/dist/db/tenant-db.d.ts +2 -2
  166. package/dist/db/tenant-db.js +48 -11
  167. package/dist/db/where-clause.d.ts +6 -0
  168. package/dist/db/where-clause.js +236 -0
  169. package/dist/derivatives/delete-stored-file.js +6 -2
  170. package/dist/derivatives/derivatives-context.js +1 -1
  171. package/dist/engine/boot-validator/access-roles.js +4 -3
  172. package/dist/engine/boot-validator/api-ext.js +14 -14
  173. package/dist/engine/boot-validator/boot-check.js +1 -1
  174. package/dist/engine/boot-validator/config-deps.js +7 -6
  175. package/dist/engine/boot-validator/detail-screens.js +4 -4
  176. package/dist/engine/boot-validator/entity-handler.d.ts +1 -0
  177. package/dist/engine/boot-validator/entity-handler.js +77 -61
  178. package/dist/engine/boot-validator/form-derivations.js +35 -1
  179. package/dist/engine/boot-validator/gdpr-storage.js +4 -4
  180. package/dist/engine/boot-validator/i18n-keys.js +6 -4
  181. package/dist/engine/boot-validator/index.d.ts +2 -2
  182. package/dist/engine/boot-validator/index.js +22 -20
  183. package/dist/engine/boot-validator/nav.js +5 -5
  184. package/dist/engine/boot-validator/ownership.js +12 -9
  185. package/dist/engine/boot-validator/parent-ref.js +1 -1
  186. package/dist/engine/boot-validator/pii-retention.js +258 -187
  187. package/dist/engine/boot-validator/projection-list-screens.js +7 -7
  188. package/dist/engine/boot-validator/query-refs.js +1 -1
  189. package/dist/engine/boot-validator/screens-actions.d.ts +1 -0
  190. package/dist/engine/boot-validator/screens-actions.js +23 -17
  191. package/dist/engine/boot-validator/screens-dashboard.js +2 -5
  192. package/dist/engine/boot-validator/screens-forms.js +12 -17
  193. package/dist/engine/boot-validator/screens-kind-config-edit.d.ts +3 -0
  194. package/dist/engine/boot-validator/screens-kind-config-edit.js +88 -0
  195. package/dist/engine/boot-validator/screens-kind-entity-edit.d.ts +3 -0
  196. package/dist/engine/boot-validator/screens-kind-entity-edit.js +55 -0
  197. package/dist/engine/boot-validator/screens-kind-entity-list.d.ts +3 -0
  198. package/dist/engine/boot-validator/screens-kind-entity-list.js +228 -0
  199. package/dist/engine/boot-validator/screens-kind-projection-detail.d.ts +3 -0
  200. package/dist/engine/boot-validator/screens-kind-projection-detail.js +235 -0
  201. package/dist/engine/boot-validator/screens-kind-projection-list.d.ts +3 -0
  202. package/dist/engine/boot-validator/screens-kind-projection-list.js +52 -0
  203. package/dist/engine/boot-validator/screens-kind-secret-mint.d.ts +3 -0
  204. package/dist/engine/boot-validator/screens-kind-secret-mint.js +28 -0
  205. package/dist/engine/boot-validator/screens-kind-shared.d.ts +37 -0
  206. package/dist/engine/boot-validator/screens-kind-shared.js +142 -0
  207. package/dist/engine/boot-validator/screens-lists.d.ts +2 -1
  208. package/dist/engine/boot-validator/screens-lists.js +26 -24
  209. package/dist/engine/boot-validator/screens.d.ts +0 -2
  210. package/dist/engine/boot-validator/screens.js +102 -869
  211. package/dist/engine/boot-validator/security-baseline.js +3 -2
  212. package/dist/engine/boot-validator/transfer-graph.js +2 -2
  213. package/dist/engine/boot-validator/workspaces.js +3 -3
  214. package/dist/engine/bridge-stub.js +3 -4
  215. package/dist/engine/build-app-schema.js +130 -170
  216. package/dist/engine/build-config-feature-schema.js +50 -50
  217. package/dist/engine/build-target.js +20 -23
  218. package/dist/engine/codemod/pipeline-codemod.js +20 -13
  219. package/dist/engine/config-helpers.js +4 -4
  220. package/dist/engine/constants.js +2 -2
  221. package/dist/engine/create-app.js +2 -2
  222. package/dist/engine/define-feature.js +21 -13
  223. package/dist/engine/define-handler.js +13 -11
  224. package/dist/engine/define-step.js +1 -1
  225. package/dist/engine/define-workflow.d.ts +5 -5
  226. package/dist/engine/define-workflow.js +6 -6
  227. package/dist/engine/entity-handlers.d.ts +13 -0
  228. package/dist/engine/entity-handlers.js +22 -34
  229. package/dist/engine/entity-list-runtime-options.d.ts +8 -0
  230. package/dist/engine/entity-list-runtime-options.js +18 -0
  231. package/dist/engine/event-def.js +2 -2
  232. package/dist/engine/extension-names.d.ts +16 -17
  233. package/dist/engine/extension-names.js +37 -38
  234. package/dist/engine/extensions/escape-hatch-usage.js +1 -1
  235. package/dist/engine/extensions/tenant-data.js +2 -2
  236. package/dist/engine/extensions/user-data.d.ts +23 -24
  237. package/dist/engine/factories.d.ts +14 -13
  238. package/dist/engine/factories.js +38 -37
  239. package/dist/engine/feature-ast/entity-field-types.js +1 -1
  240. package/dist/engine/feature-ast/extractors/handlers.js +2 -1
  241. package/dist/engine/feature-ast/extractors/hooks.js +1 -1
  242. package/dist/engine/feature-ast/extractors/round2.js +25 -6
  243. package/dist/engine/feature-ast/extractors/shared.d.ts +2 -3
  244. package/dist/engine/feature-ast/extractors/shared.js +2 -3
  245. package/dist/engine/feature-ast/parse.js +13 -13
  246. package/dist/engine/feature-ast/patch.js +4 -182
  247. package/dist/engine/feature-ast/pattern-change-schema.d.ts +3 -0
  248. package/dist/engine/feature-ast/pattern-change-schema.js +2 -1
  249. package/dist/engine/feature-ast/pattern-id-matchers.d.ts +7 -0
  250. package/dist/engine/feature-ast/pattern-id-matchers.js +210 -0
  251. package/dist/engine/feature-ast/patterns.d.ts +11 -2
  252. package/dist/engine/feature-ast/patterns.js +43 -51
  253. package/dist/engine/feature-ast/render.js +50 -89
  254. package/dist/engine/feature-config-events-jobs.js +15 -12
  255. package/dist/engine/feature-entity-handlers.js +12 -5
  256. package/dist/engine/feature-manifest.d.ts +9 -9
  257. package/dist/engine/feature-manifest.js +6 -7
  258. package/dist/engine/feature-ui-extensions.d.ts +3 -3
  259. package/dist/engine/feature-ui-extensions.js +30 -22
  260. package/dist/engine/field-access.js +5 -6
  261. package/dist/engine/form-derivations.js +18 -7
  262. package/dist/engine/handler-field-references.js +1 -1
  263. package/dist/engine/index.d.ts +1 -0
  264. package/dist/engine/index.js +4 -4
  265. package/dist/engine/object-form.d.ts +1 -0
  266. package/dist/engine/object-form.js +14 -4
  267. package/dist/engine/ownership.js +3 -3
  268. package/dist/engine/parse-ref-target.js +5 -7
  269. package/dist/engine/pattern-library/index.js +2 -2
  270. package/dist/engine/pattern-library/library.js +2 -2
  271. package/dist/engine/pattern-library/types.js +3 -3
  272. package/dist/engine/pipeline.js +2 -2
  273. package/dist/engine/project-app-schema-for-roles.d.ts +2 -0
  274. package/dist/engine/project-app-schema-for-roles.js +7 -5
  275. package/dist/engine/projection-helpers.js +9 -9
  276. package/dist/engine/qualified-name.js +2 -2
  277. package/dist/engine/registry-facade.js +1 -1
  278. package/dist/engine/registry-ingest.js +13 -13
  279. package/dist/engine/registry-state.js +17 -19
  280. package/dist/engine/registry-validate.js +12 -12
  281. package/dist/engine/run-in.js +2 -2
  282. package/dist/engine/run-pipeline.js +7 -0
  283. package/dist/engine/schema-builder.js +251 -233
  284. package/dist/engine/screen-filter-ops.js +17 -20
  285. package/dist/engine/screen-helpers.js +4 -3
  286. package/dist/engine/screen-kind.d.ts +7 -0
  287. package/dist/engine/screen-kind.js +1 -0
  288. package/dist/engine/state-machine.d.ts +12 -12
  289. package/dist/engine/state-machine.js +7 -7
  290. package/dist/engine/steps/_resolver-utils.js +4 -3
  291. package/dist/engine/steps/for-each.js +4 -4
  292. package/dist/engine/steps/unsafe-projection-delete.js +1 -1
  293. package/dist/engine/steps/unsafe-projection-upsert.js +4 -4
  294. package/dist/engine/steps/wait-for-event.js +4 -4
  295. package/dist/engine/steps/workflow-system-events.js +3 -3
  296. package/dist/engine/strip-disabled-features-from-app-schema.js +51 -14
  297. package/dist/engine/tier-resolver-extension.d.ts +29 -27
  298. package/dist/engine/tier-resolver-extension.js +26 -26
  299. package/dist/engine/transfer-adjacency.js +2 -2
  300. package/dist/engine/validate-projection-allowlist.js +9 -28
  301. package/dist/engine/walk-step-instances.d.ts +2 -0
  302. package/dist/engine/walk-step-instances.js +38 -0
  303. package/dist/engine/where-rule-lint.js +1 -1
  304. package/dist/engine/write-handler-qn-extract.js +1 -1
  305. package/dist/entrypoint/index.d.ts +4 -1
  306. package/dist/entrypoint/index.js +10 -4
  307. package/dist/env/index.d.ts +7 -6
  308. package/dist/env/index.js +10 -9
  309. package/dist/errors/docs-url.d.ts +1 -1
  310. package/dist/errors/docs-url.js +22 -2
  311. package/dist/errors/transition-details.js +7 -7
  312. package/dist/errors/write-error-info.d.ts +6 -6
  313. package/dist/errors/write-error-info.js +6 -6
  314. package/dist/es-ops/context.d.ts +9 -9
  315. package/dist/es-ops/context.js +29 -29
  316. package/dist/es-ops/index.js +7 -9
  317. package/dist/es-ops/operations-schema.js +4 -10
  318. package/dist/es-ops/runner.d.ts +11 -11
  319. package/dist/es-ops/runner.js +49 -53
  320. package/dist/es-ops/types.d.ts +55 -55
  321. package/dist/es-ops/types.js +11 -11
  322. package/dist/event-store/admin-api.js +7 -8
  323. package/dist/event-store/errors.js +1 -1
  324. package/dist/event-store/event-store.js +12 -6
  325. package/dist/event-store/rebuild-dead-letter.js +1 -1
  326. package/dist/files/bind-pending-file-refs.js +3 -3
  327. package/dist/files/create-file-ref-from-bytes.js +4 -1
  328. package/dist/files/feature.js +9 -10
  329. package/dist/files/file-handle.js +7 -9
  330. package/dist/files/file-ref-entity.js +15 -15
  331. package/dist/files/file-ref-table.js +7 -8
  332. package/dist/files/file-routes.d.ts +7 -0
  333. package/dist/files/file-routes.js +22 -13
  334. package/dist/files/in-memory-provider.js +8 -9
  335. package/dist/files/local-provider.js +18 -25
  336. package/dist/files/provider-resolver.d.ts +7 -7
  337. package/dist/files/resolve-content-type.js +43 -0
  338. package/dist/files/storage-tracking.js +2 -2
  339. package/dist/files/upload-ledger.js +7 -0
  340. package/dist/files/zip-stream.d.ts +12 -19
  341. package/dist/files/zip-stream.js +44 -63
  342. package/dist/i18n/required-surface-keys.d.ts +1 -1
  343. package/dist/i18n/required-surface-keys.js +188 -212
  344. package/dist/internal/stack-support.d.ts +2 -1
  345. package/dist/internal/stack-support.js +1 -1
  346. package/dist/jobs/job-runner-context.d.ts +32 -0
  347. package/dist/jobs/job-runner-context.js +305 -0
  348. package/dist/jobs/job-runner-execution.d.ts +7 -0
  349. package/dist/jobs/job-runner-execution.js +160 -0
  350. package/dist/jobs/job-runner-gates.d.ts +19 -0
  351. package/dist/jobs/job-runner-gates.js +198 -0
  352. package/dist/jobs/job-runner-helpers.d.ts +17 -3
  353. package/dist/jobs/job-runner-helpers.js +69 -4
  354. package/dist/jobs/job-runner-schedulers.d.ts +1 -1
  355. package/dist/jobs/job-runner-schedulers.js +3 -4
  356. package/dist/jobs/job-runner-scope.d.ts +44 -0
  357. package/dist/jobs/job-runner-scope.js +102 -0
  358. package/dist/jobs/job-runner-types.d.ts +12 -0
  359. package/dist/jobs/job-runner.d.ts +0 -1
  360. package/dist/jobs/job-runner.js +57 -669
  361. package/dist/lifecycle/lifecycle.js +3 -5
  362. package/dist/lifecycle/signal-handlers.js +5 -4
  363. package/dist/logging/utils.d.ts +2 -1
  364. package/dist/logging/utils.js +38 -10
  365. package/dist/migrations/index.js +1 -1
  366. package/dist/migrations/kumiko-drift.js +14 -13
  367. package/dist/migrations/pending-rebuilds.d.ts +21 -20
  368. package/dist/migrations/pending-rebuilds.js +27 -27
  369. package/dist/migrations/projection-table-index.d.ts +3 -3
  370. package/dist/migrations/projection-table-index.js +8 -8
  371. package/dist/observability/escape-hatch-report.d.ts +3 -0
  372. package/dist/observability/escape-hatch-report.js +12 -1
  373. package/dist/observability/metric-validator.js +1 -1
  374. package/dist/observability/metrics-handle.js +3 -3
  375. package/dist/pipeline/append-event-core.js +11 -2
  376. package/dist/pipeline/cascade-handler.d.ts +1 -1
  377. package/dist/pipeline/cascade-handler.js +165 -138
  378. package/dist/pipeline/dispatch-batch.js +2 -2
  379. package/dist/pipeline/dispatch-query.js +20 -13
  380. package/dist/pipeline/dispatch-shared.d.ts +14 -3
  381. package/dist/pipeline/dispatch-shared.js +67 -721
  382. package/dist/pipeline/dispatch-stream.js +1 -1
  383. package/dist/pipeline/dispatch-write.js +297 -190
  384. package/dist/pipeline/dispatcher-utils.d.ts +1 -1
  385. package/dist/pipeline/dispatcher-utils.js +1 -1
  386. package/dist/pipeline/event-consumer-state.js +2 -2
  387. package/dist/pipeline/event-dispatcher-admin.js +2 -1
  388. package/dist/pipeline/event-dispatcher-delivery.js +4 -6
  389. package/dist/pipeline/event-dispatcher.js +17 -28
  390. package/dist/pipeline/handler-context-auth.d.ts +9 -0
  391. package/dist/pipeline/handler-context-auth.js +54 -0
  392. package/dist/pipeline/handler-context-config.d.ts +14 -0
  393. package/dist/pipeline/handler-context-config.js +113 -0
  394. package/dist/pipeline/handler-context-db.d.ts +24 -0
  395. package/dist/pipeline/handler-context-db.js +149 -0
  396. package/dist/pipeline/handler-context-dispatch.d.ts +21 -0
  397. package/dist/pipeline/handler-context-dispatch.js +89 -0
  398. package/dist/pipeline/handler-context-events.d.ts +43 -0
  399. package/dist/pipeline/handler-context-events.js +237 -0
  400. package/dist/pipeline/handler-context-notify.d.ts +12 -0
  401. package/dist/pipeline/handler-context-notify.js +55 -0
  402. package/dist/pipeline/handler-context-observability.d.ts +7 -0
  403. package/dist/pipeline/handler-context-observability.js +21 -0
  404. package/dist/pipeline/handler-context-scope.d.ts +48 -0
  405. package/dist/pipeline/handler-context-scope.js +88 -0
  406. package/dist/pipeline/irreversible-operation-gate.js +1 -1
  407. package/dist/pipeline/lifecycle-pipeline.js +9 -9
  408. package/dist/pipeline/member-read-only-transaction.js +1 -3
  409. package/dist/pipeline/msp-rebuild.js +1 -1
  410. package/dist/pipeline/notify-scope.js +12 -1
  411. package/dist/pipeline/pre-handler-gates.js +20 -4
  412. package/dist/pipeline/pre-transaction-reservations.d.ts +1 -0
  413. package/dist/pipeline/pre-transaction-reservations.js +9 -3
  414. package/dist/pipeline/projection-rebuild.js +15 -13
  415. package/dist/pipeline/system-hooks.js +39 -41
  416. package/dist/pipeline/system-identity-switch.js +1 -3
  417. package/dist/pipeline/tenant-timezone-cache.js +1 -1
  418. package/dist/random/generate.d.ts +29 -29
  419. package/dist/random/generate.js +30 -30
  420. package/dist/random/words.js +20 -20
  421. package/dist/rate-limit/middleware.js +9 -5
  422. package/dist/redis/client.js +2 -2
  423. package/dist/redis/pubsub-signal.js +14 -17
  424. package/dist/schema-cli/apply-command.d.ts +2 -0
  425. package/dist/schema-cli/apply-command.js +97 -0
  426. package/dist/schema-cli/baseline-command.d.ts +2 -0
  427. package/dist/schema-cli/baseline-command.js +33 -0
  428. package/dist/schema-cli/generate-command.d.ts +2 -0
  429. package/dist/schema-cli/generate-command.js +90 -0
  430. package/dist/schema-cli/shared.d.ts +39 -0
  431. package/dist/schema-cli/shared.js +95 -0
  432. package/dist/schema-cli/status-command.d.ts +2 -0
  433. package/dist/schema-cli/status-command.js +73 -0
  434. package/dist/schema-cli/validate-boot-input.d.ts +5 -0
  435. package/dist/schema-cli/validate-boot-input.js +130 -0
  436. package/dist/schema-cli/validate-command.d.ts +2 -0
  437. package/dist/schema-cli/validate-command.js +130 -0
  438. package/dist/schema-cli.d.ts +2 -18
  439. package/dist/schema-cli.js +47 -510
  440. package/dist/search/index.js +4 -4
  441. package/dist/search/meilisearch-adapter.js +2 -1
  442. package/dist/search/purge-subject.js +4 -5
  443. package/dist/search/reindex-entity.js +6 -9
  444. package/dist/time/boot-tz-warning.d.ts +2 -2
  445. package/dist/time/boot-tz-warning.js +8 -8
  446. package/dist/time/iana.js +10 -10
  447. package/dist/time/index.js +9 -9
  448. package/dist/time/legacy-date.d.ts +2 -2
  449. package/dist/time/legacy-date.js +6 -8
  450. package/dist/time/polyfill.js +1 -1
  451. package/dist/time/tz-context.d.ts +1 -1
  452. package/dist/time/tz-context.js +1 -1
  453. package/dist/ui-types/app-schema.js +7 -7
  454. package/dist/ui-types/list-row-meta.js +4 -4
  455. package/dist/upgrade-cli.js +159 -130
  456. package/dist/utils/compare.js +1 -1
  457. package/package.json +5 -5
  458. package/src/changes.json +358 -0
  459. package/src/scripts/codemod/crypto-shredding-testing-move.ts +2 -2
  460. package/src/scripts/codemod/feature-layout.ts +10 -2
  461. package/src/scripts/codemod/migrate-cross-tenant.ts +1 -1
  462. package/src/scripts/codemod/migrate-open-to-all.ts +1 -1
  463. package/src/scripts/codemod/object-form.ts +41 -4
  464. package/src/scripts/codemod/package-merge.ts +58 -8
  465. package/src/scripts/codemod/pii-personal-migration.ts +192 -153
  466. package/src/scripts/codemod/testing-injection.ts +122 -42
  467. package/src/scripts/codemod/testing-move.ts +29 -7
  468. package/src/scripts/codemod/unprocessable-error-details-reason.ts +2 -2
@@ -10,7 +10,7 @@ import type { Lifecycle } from "../lifecycle/index.ts";
10
10
  import type { ObservabilityProvider } from "../observability/index.ts";
11
11
  import type { Dispatcher, DispatcherOptions } from "../pipeline/dispatcher.ts";
12
12
  import type { EventDedup, EventDispatcher } from "../pipeline/index.ts";
13
- import type { SystemHooks } from "../pipeline/lifecycle-pipeline.ts";
13
+ import type { LifecycleHooks, SystemHooks } from "../pipeline/lifecycle-pipeline.ts";
14
14
  export type BaseEntrypointOptions = {
15
15
  readonly registry: Registry;
16
16
  readonly context: AppContext;
@@ -21,6 +21,7 @@ export type BaseEntrypointOptions = {
21
21
  readonly systemHooks?: SystemHooks;
22
22
  readonly eventDedup?: EventDedup;
23
23
  readonly lifecycle?: Lifecycle;
24
+ readonly instanceId?: ServerOptions["instanceId"];
24
25
  };
25
26
  type JobsBlock = {
26
27
  readonly redisUrl: string;
@@ -49,6 +50,7 @@ export type ApiEntrypointOptions = BaseEntrypointOptions & {
49
50
  readonly runLocal?: boolean;
50
51
  };
51
52
  readonly trustedProxyHops?: ServerOptions["trustedProxyHops"];
53
+ readonly errorDocs?: ServerOptions["errorDocs"];
52
54
  };
53
55
  export type WorkerEntrypointOptions = BaseEntrypointOptions & JobsBlock & {
54
56
  readonly eventDispatcher?: ServerOptions["eventDispatcher"];
@@ -61,6 +63,7 @@ export type ApiEntrypoint = {
61
63
  readonly lifecycle: Lifecycle;
62
64
  readonly observability: ObservabilityProvider;
63
65
  readonly dispatcher: Dispatcher;
66
+ readonly lifecycleHooks: LifecycleHooks;
64
67
  readonly eventDispatcher?: EventDispatcher;
65
68
  readonly mode: "api";
66
69
  start(): Promise<void>;
@@ -36,11 +36,12 @@
36
36
  //
37
37
  // SSE fanout across processes (split api/worker deploy, replicas > 1):
38
38
  // buildServer's default sseBroker is Redis-backed whenever REDIS_URL is
39
- // set (fw#2625) — a push on the worker's dispatcher reaches clients
39
+ // set — a push on the worker's dispatcher reaches clients
40
40
  // connected to any API instance via Redis Pub/Sub, no per-instance
41
41
  // cursor needed. Without REDIS_URL, the in-memory broker still only
42
42
  // reaches clients on the same process.
43
- import { buildServer, withFileProviderResolver } from "../api/server.js";
43
+ import { buildServer } from "../api/server.js";
44
+ import { withFileProviderResolver } from "../api/server-wiring.js";
44
45
  import { createJobRunner } from "../jobs/job-runner.js";
45
46
  import { createLifecycle } from "../lifecycle/index.js";
46
47
  import { createNoopProvider } from "../observability/index.js";
@@ -55,7 +56,7 @@ import { resolveCacheSyncBus } from "../redis/cache-sync-bus.js";
55
56
  // so the command-dispatcher fires handleEvent as an afterCommit-hook for
56
57
  // event-triggered jobs (dispatcher.ts:997). Without this plumbing,
57
58
  // `r.job({ trigger: { on: … } })` silently drops on every write — that
58
- // was the hidden Welle-2.5 gap.
59
+ // was the hidden gap.
59
60
  //
60
61
  // Caller-supplied `dispatcherOptions.jobRunner` wins (tests sometimes
61
62
  // inject a mock runner directly).
@@ -119,6 +120,8 @@ function buildApiServer(opts, lifecycle, dispatcherOverride, jobRunner, processL
119
120
  jwtIssuer: opts.jwtIssuer,
120
121
  auth: opts.auth,
121
122
  trustedProxyHops: opts.trustedProxyHops,
123
+ errorDocs: opts.errorDocs,
124
+ instanceId: opts.instanceId,
122
125
  anonymousAccess: opts.anonymousAccess,
123
126
  sseBroker: opts.sseBroker,
124
127
  rateLimit: opts.rateLimit,
@@ -145,6 +148,7 @@ function buildWorkerServer(opts, lifecycle, jobRunner) {
145
148
  jwtSecret: opts.jwtSecret,
146
149
  lifecycle,
147
150
  processLane: "worker",
151
+ instanceId: opts.instanceId,
148
152
  observability: opts.observability,
149
153
  dispatcherOptions,
150
154
  systemHooks: opts.systemHooks,
@@ -198,7 +202,7 @@ export function createApiEntrypoint(options) {
198
202
  const lifecycle = options.lifecycle ?? createLifecycle({ startReady: true });
199
203
  const observability = resolveObservability(options.observability);
200
204
  const { options: busOptions, context } = resolveEntrypointCacheSync(options, lifecycle);
201
- // Boot-validation (Welle 2.6.c) — fail loud before traffic arrives:
205
+ // Boot-validation — fail loud before traffic arrives:
202
206
  // (a) Any jobs declared + no jobs-block → command-dispatcher would
203
207
  // silently drop every event-triggered enqueue. Fix: add jobs:
204
208
  // { redisUrl } so the API holds lane-queue-clients.
@@ -240,6 +244,7 @@ export function createApiEntrypoint(options) {
240
244
  lifecycle,
241
245
  observability: server.observability,
242
246
  dispatcher: server.dispatcher,
247
+ lifecycleHooks: server.lifecycleHooks,
243
248
  ...(server.eventDispatcher && { eventDispatcher: server.eventDispatcher }),
244
249
  mode: "api",
245
250
  async start() {
@@ -319,6 +324,7 @@ export function createAllInOneEntrypoint(options) {
319
324
  jobRunner: workerJobRunner,
320
325
  observability: server.observability,
321
326
  dispatcher: server.dispatcher,
327
+ lifecycleHooks: server.lifecycleHooks,
322
328
  mode: "all-in-one",
323
329
  async start() {
324
330
  await eventDispatcher.start();
@@ -116,12 +116,13 @@ export type ParseEnvOptions = {
116
116
  * is `undefined` in the result despite its `string` type — it is only set once
117
117
  * the boot-time decrypt (resolvePlatformKeks) has run. */
118
118
  export declare function parseEnv<S extends z.ZodObject<z.ZodRawShape>>(schema: S, env: Record<string, string | undefined>, options?: ParseEnvOptions): z.infer<S>;
119
- /** Dry-Run-Gegenstück zu parseEnv (KUMIKO_DRY_RUN_ENV-Pfad): parst jedes
120
- * Feld einzeln und liefert ein ehrliches Partial — vorhandene Werte kommen
121
- * typisiert (gecoerct) durch, fehlende/invalide fehlen einfach. Wirft nie:
122
- * der Dry-Run soll das Inventory rendern, nicht an required-Feldern
123
- * scheitern. Ersetzt das `({} as Shape)`-Muster, bei dem JEDER Zugriff
124
- * silent undefined war und das Compile-Level nichts davon wusste. */
119
+ /** Dry-run counterpart to parseEnv (KUMIKO_DRY_RUN_ENV path): parses each
120
+ * field individually and returns an honest Partial — present values pass
121
+ * through with their types (coerced), while missing or invalid values are
122
+ * simply omitted. Never throws: the dry run renders the inventory instead
123
+ * of failing on required fields. Replaces the `({} as Shape)` pattern, where
124
+ * every access silently returned undefined and the compiler could not detect
125
+ * it. */
125
126
  export declare function parseEnvDryRun<S extends z.ZodObject<z.ZodRawShape>>(schema: S, env: Record<string, string | undefined>): Partial<z.infer<S>>;
126
127
  export type EnvFieldStatus = "set" | "unset" | "missing" | "invalid";
127
128
  export type EnvFieldInspection = {
package/dist/env/index.js CHANGED
@@ -209,7 +209,7 @@ export function composeEnvSchema(options) {
209
209
  // rather than silently overwriting a deploy-critical default. The
210
210
  // conflict-detection makes the order safe in both directions — both
211
211
  // throw — but downstream tools that consume `sources` (e.g. the
212
- // upcoming Phase-5 lint-guard) may rely on this insertion order.
212
+ // upcoming lint-guard) may rely on this insertion order.
213
213
  if (options.core) {
214
214
  for (const [key, field] of Object.entries(zodShape(options.core))) {
215
215
  merged[key] = field;
@@ -356,12 +356,13 @@ export function parseEnv(schema, env, options = {}) {
356
356
  function ucfirst(s) {
357
357
  return s.length === 0 ? s : s.charAt(0).toUpperCase() + s.slice(1);
358
358
  }
359
- /** Dry-Run-Gegenstück zu parseEnv (KUMIKO_DRY_RUN_ENV-Pfad): parst jedes
360
- * Feld einzeln und liefert ein ehrliches Partial — vorhandene Werte kommen
361
- * typisiert (gecoerct) durch, fehlende/invalide fehlen einfach. Wirft nie:
362
- * der Dry-Run soll das Inventory rendern, nicht an required-Feldern
363
- * scheitern. Ersetzt das `({} as Shape)`-Muster, bei dem JEDER Zugriff
364
- * silent undefined war und das Compile-Level nichts davon wusste. */
359
+ /** Dry-run counterpart to parseEnv (KUMIKO_DRY_RUN_ENV path): parses each
360
+ * field individually and returns an honest Partial — present values pass
361
+ * through with their types (coerced), while missing or invalid values are
362
+ * simply omitted. Never throws: the dry run renders the inventory instead
363
+ * of failing on required fields. Replaces the `({} as Shape)` pattern, where
364
+ * every access silently returned undefined and the compiler could not detect
365
+ * it. */
365
366
  export function parseEnvDryRun(schema, env) {
366
367
  const out = {};
367
368
  for (const [name, field] of Object.entries(zodShape(schema))) {
@@ -372,8 +373,8 @@ export function parseEnvDryRun(schema, env) {
372
373
  if (result.success)
373
374
  out[name] = result.data;
374
375
  }
375
- // @cast-boundary schema-walk — Partial<z.infer<S>> erasure über den
376
- // per-Feld-safeParse; jeder enthaltene Wert hat seinen Feld-Parse bestanden.
376
+ // @cast-boundary schema-walk — Partial<z.infer<S>> erasure through the
377
+ // per-field safeParse; every included value passed its field-level parse.
377
378
  return out;
378
379
  }
379
380
  /** Checks every field of `schema` on its own against `env`, for the boot dry
@@ -1,5 +1,5 @@
1
1
  import type { KumikoError } from "./kumiko-error.ts";
2
- /** Links an app's own error reasons to its own docs; without it only framework reasons carry a docsUrl. */
2
+ /** Links an app's own error reasons to its own docs; uncovered reasons fall back to the framework page of the error code. */
3
3
  export type ErrorDocsConfig = {
4
4
  readonly baseUrl: string;
5
5
  readonly reasons?: readonly string[] | "all";
@@ -5,6 +5,26 @@ const frameworkReasons = new Set([
5
5
  ...Object.values(FrameworkReasons),
6
6
  ...Object.values(AgentReasons),
7
7
  ]);
8
+ // Codes of the built-in error classes: only these have a framework docs page.
9
+ const frameworkErrorCodes = new Set([
10
+ "validation_error",
11
+ "feature_disabled",
12
+ "access_denied",
13
+ "unauthenticated",
14
+ "not_found",
15
+ "conflict",
16
+ "version_conflict",
17
+ "precondition_failed",
18
+ "record_locked",
19
+ "idempotent_replay",
20
+ "unique_violation",
21
+ "unprocessable",
22
+ "unconfigured",
23
+ "internal_error",
24
+ "member_read_timeout",
25
+ "rate_limited",
26
+ "rate_limit_unavailable",
27
+ ]);
8
28
  function reasonOf(err) {
9
29
  if (!err.details || typeof err.details !== "object")
10
30
  return undefined;
@@ -22,7 +42,7 @@ function errorsUrl(baseUrl, slug) {
22
42
  }
23
43
  // A reason the framework documents (or no reason, or the code itself) links to the framework docs, overridable via
24
44
  // KUMIKO_DOCS_URL. An app's own reason links to the app docs where `errorDocs` covers it; every
25
- // other reason falls back to the framework page of the error code, which exists for each code.
45
+ // other reason falls back to the framework page of the error code, unless an app subclass overrode the code.
26
46
  export function resolveErrorDocsUrl(err, errorDocs) {
27
47
  const reason = reasonOf(err);
28
48
  const frameworkBaseUrl = process.env["KUMIKO_DOCS_URL"] ?? DEFAULT_DOCS_BASE_URL;
@@ -32,5 +52,5 @@ export function resolveErrorDocsUrl(err, errorDocs) {
32
52
  if (errorDocs && isCoveredByConfig(reason, errorDocs)) {
33
53
  return errorsUrl(errorDocs.baseUrl, reason);
34
54
  }
35
- return errorsUrl(frameworkBaseUrl, err.code);
55
+ return frameworkErrorCodes.has(err.code) ? errorsUrl(frameworkBaseUrl, err.code) : undefined;
36
56
  }
@@ -1,11 +1,11 @@
1
- // Gemeinsame Detail-Shape für invalid_transition-Errors. Beide Pfade
2
- // (state-machine.assertTransition + failTransition) müssen identisch
3
- // strukturierte Details liefern, sonst können HTTP-Clients den 422-Body
4
- // nicht uniform parsen — `from`/`to`/`allowed` sind die strukturierten
5
- // Felder, `message` ist die menschen-lesbare Form.
1
+ // Shared detail shape for invalid_transition errors. Both paths
2
+ // (`state-machine.assertTransition` and `failTransition`) must provide
3
+ // identically structured details so HTTP clients can parse the 422 body uniformly:
4
+ // `from`/`to`/`allowed` are the structured fields, while `message` is the
5
+ // human-readable form.
6
6
  //
7
- // Kein Re-Export von "validTargets" (CSV-string) mehr — wer CSV will
8
- // baut's via `allowed.join(", ")`. Eine Shape, ein Vertrag.
7
+ // `validTargets` is not re-exported as a CSV string; callers that need CSV can use
8
+ // `allowed.join(", ")`. One shape defines the contract.
9
9
  export function buildInvalidTransitionDetails(from, to, allowed) {
10
10
  return {
11
11
  from,
@@ -7,13 +7,13 @@ export declare function failUnprocessable(reason: string, details?: Readonly<Rec
7
7
  readonly reason?: never;
8
8
  }): WriteFailure;
9
9
  /**
10
- * Convenience für State-Transition-Rejects: produces a WriteFailure mit
11
- * reason="invalid_transition" + strukturiertem `from`/`to`/`allowed`-
12
- * Detail-Block + lesbarer message. Pattern hat sich in publicstatus-
13
- * Maintenance + bestehenden state-machine-Helpers wiederholt — Helper
14
- * sammelt das in einem Aufruf statt drei manuelle Detail-Felder.
10
+ * Convenience for state-transition rejects: produces a WriteFailure with
11
+ * reason="invalid_transition", a structured `from`/`to`/`allowed` detail
12
+ * block, and a readable message. This pattern recurs in publicstatus
13
+ * maintenance and existing state-machine helpers, so the helper collects it
14
+ * in one call instead of requiring three manual detail fields.
15
15
  *
16
- * `allowed` ist typisch `MAINTENANCE_TRANSITIONS.allowedFrom(from)`.
16
+ * `allowed` is typically `MAINTENANCE_TRANSITIONS.allowedFrom(from)`.
17
17
  */
18
18
  export declare function failTransition(from: string, to: string, allowed: readonly string[]): WriteFailure;
19
19
  export declare function toWriteErrorInfo(err: KumikoError): WriteErrorInfo;
@@ -24,13 +24,13 @@ export function failUnprocessable(reason, details) {
24
24
  return writeFailure(new UnprocessableError(reason, details ? { details } : undefined));
25
25
  }
26
26
  /**
27
- * Convenience für State-Transition-Rejects: produces a WriteFailure mit
28
- * reason="invalid_transition" + strukturiertem `from`/`to`/`allowed`-
29
- * Detail-Block + lesbarer message. Pattern hat sich in publicstatus-
30
- * Maintenance + bestehenden state-machine-Helpers wiederholt — Helper
31
- * sammelt das in einem Aufruf statt drei manuelle Detail-Felder.
27
+ * Convenience for state-transition rejects: produces a WriteFailure with
28
+ * reason="invalid_transition", a structured `from`/`to`/`allowed` detail
29
+ * block, and a readable message. This pattern recurs in publicstatus
30
+ * maintenance and existing state-machine helpers, so the helper collects it
31
+ * in one call instead of requiring three manual detail fields.
32
32
  *
33
- * `allowed` ist typisch `MAINTENANCE_TRANSITIONS.allowedFrom(from)`.
33
+ * `allowed` is typically `MAINTENANCE_TRANSITIONS.allowedFrom(from)`.
34
34
  */
35
35
  export function failTransition(from, to, allowed) {
36
36
  return writeFailure(new UnprocessableError(FrameworkReasons.invalidTransition, {
@@ -5,15 +5,15 @@ export type CreateSeedMigrationContextArgs = {
5
5
  readonly dispatcher: Dispatcher;
6
6
  readonly dbRunner: DbRunner;
7
7
  };
8
- /** Builder: gibt eine factory-function zurück die der Runner pro-Migration
9
- * aufruft. Der dbRunner kann eine Top-Connection oder eine Tx sein —
10
- * Read-Helpers nutzen ihn direkt, systemWriteAs delegiert an dispatcher.
8
+ /** Builder that returns a factory function called by the runner for each
9
+ * migration. dbRunner may be a top-level connection or a transaction—read
10
+ * helpers use it directly, while systemWriteAs delegates to the dispatcher.
11
11
  *
12
- * Hinweis: dispatcher.write bekommt den Runner-tx NICHT durchgereicht —
13
- * runBatch öffnet eine eigene Transaktion auf context.db (eigene Pool-
14
- * Connection). Die Writes committen daher unabhängig: ein Runner-Failure
15
- * rollt NUR den Marker-Insert + dbRunner-reads zurück, die dispatcher-Writes
16
- * bleiben committed. Seeds MÜSSEN deshalb idempotent sein (verifiziert in
17
- * runner.integration.test.ts „dispatcher-writes vor throw bleiben committed"). */
12
+ * dispatcher.write does not receive the runner transaction: runBatch opens
13
+ * a separate transaction on context.db (using a separate pool connection).
14
+ * Writes therefore commit independently: a runner failure rolls back only
15
+ * the marker insert and dbRunner reads; dispatcher writes remain committed.
16
+ * Seeds must therefore be idempotent (verified in
17
+ * runner.integration.test.ts “dispatcher-writes vor throw bleiben committed”). */
18
18
  export declare function createSeedMigrationContext(args: CreateSeedMigrationContextArgs): SeedMigrationContext;
19
19
  export type { SeedMigrationContext } from "./types.ts";
@@ -1,49 +1,49 @@
1
- // SeedMigrationContext-Builder. Caller (runProdApp/CLI) übergibt einen
2
- // schon-konfigurierten Dispatcher; der Builder produziert pro-Migration
3
- // einen tx-scoped Context der via dispatcher.write den existierenden
4
- // Handler-Pfad nutzt — gleiches Pattern wie ein User-UI-Click.
1
+ // SeedMigrationContext builder. The caller (runProdApp/CLI) supplies a
2
+ // preconfigured dispatcher; the builder creates a transaction-scoped context
3
+ // for each migration that uses the existing handler path through
4
+ // dispatcher.write—the same pattern as a user UI click.
5
5
  //
6
- // SystemUser bypassed Access-Checks (Standard-Seed-Pattern, siehe
7
- // config-seed.ts:40). Events haben createdBy = SYSTEM_TENANT_ID-User
8
- // → audit-fähig.
6
+ // The system user bypasses access checks (the standard seed pattern; see
7
+ // config-seed.ts:40). Events have createdBy = SYSTEM_TENANT_ID user,
8
+ // making them auditable.
9
9
  import { configuredPiiSubjectKms, decryptPiiFieldValues } from "../crypto/index.js";
10
10
  import { selectAllTenants, selectMembershipsOfUser, selectTemplateResources, selectUserByEmail, } from "../db/queries/seed-context.js";
11
11
  import { createSystemUser, SYSTEM_TENANT_ID } from "../engine/index.js";
12
12
  import { parseStringArrayJson } from "../utils/parse-string-array-json.js";
13
- /** Builder: gibt eine factory-function zurück die der Runner pro-Migration
14
- * aufruft. Der dbRunner kann eine Top-Connection oder eine Tx sein —
15
- * Read-Helpers nutzen ihn direkt, systemWriteAs delegiert an dispatcher.
13
+ /** Builder that returns a factory function called by the runner for each
14
+ * migration. dbRunner may be a top-level connection or a transaction—read
15
+ * helpers use it directly, while systemWriteAs delegates to the dispatcher.
16
16
  *
17
- * Hinweis: dispatcher.write bekommt den Runner-tx NICHT durchgereicht —
18
- * runBatch öffnet eine eigene Transaktion auf context.db (eigene Pool-
19
- * Connection). Die Writes committen daher unabhängig: ein Runner-Failure
20
- * rollt NUR den Marker-Insert + dbRunner-reads zurück, die dispatcher-Writes
21
- * bleiben committed. Seeds MÜSSEN deshalb idempotent sein (verifiziert in
22
- * runner.integration.test.ts „dispatcher-writes vor throw bleiben committed"). */
17
+ * dispatcher.write does not receive the runner transaction: runBatch opens
18
+ * a separate transaction on context.db (using a separate pool connection).
19
+ * Writes therefore commit independently: a runner failure rolls back only
20
+ * the marker insert and dbRunner reads; dispatcher writes remain committed.
21
+ * Seeds must therefore be idempotent (verified in
22
+ * runner.integration.test.ts “dispatcher-writes vor throw bleiben committed”). */
23
23
  export function createSeedMigrationContext(args) {
24
- // Default-Executor für System-scope-Aggregates (config-values, system
25
- // text-content, etc.). Bei Tenant-scope-Aggregates muss der Caller
26
- // explizit `tenantIdOverride` übergeben — siehe types.ts Doku.
24
+ // Default executor for system-scope aggregates (config-values, system
25
+ // text-content, etc.). For tenant-scope aggregates, the caller must
26
+ // explicitly provide `tenantIdOverride`—see the documentation in types.ts.
27
27
  const defaultSystemUser = createSystemUser(SYSTEM_TENANT_ID);
28
28
  return {
29
29
  systemWriteAs: async (handlerQualifiedName, payload, tenantIdOverride, extraRoles) => {
30
- // tenantIdOverride: baut einen System-User mit der Stream-tenantId
31
- // damit der Event-Store-Executor das Aggregate im richtigen Stream
32
- // findet. Verhindert die version_conflict-Falle (siehe Memory
33
- // feedback_event_store_tenant_consistency.md).
30
+ // tenantIdOverride creates a system user with the stream tenant ID so that
31
+ // the event-store executor finds the aggregate in the correct stream.
32
+ // This prevents the version_conflict failure.
34
33
  const executor = tenantIdOverride !== undefined || (extraRoles && extraRoles.length > 0)
35
34
  ? createSystemUser(tenantIdOverride ?? SYSTEM_TENANT_ID, extraRoles)
36
35
  : defaultSystemUser;
37
36
  const result = await args.dispatcher.write(handlerQualifiedName, payload, executor);
38
- // Critical: WriteResult{isSuccess: false} würde sonst silent durchlaufen
39
- // → Marker landet trotz failed-Write → Migration falsch als "applied"
40
- // markiert. Hier throw damit der Runner's outer-tx rollback macht und
41
- // Marker NICHT geschrieben wird. Seed-Author kann via try/catch eigene
42
- // Fehler-Behandlung machen wenn ein soft-failure erwartet ist.
37
+ // Without this check, WriteResult{isSuccess: false} would pass silently,
38
+ // causing the marker to be written despite the failed write and the
39
+ // migration to be incorrectly marked as "applied". Throw so the
40
+ // runner's outer transaction rolls back and the marker is not written.
41
+ // Seed authors can use try/catch for custom handling when a soft failure
42
+ // is expected.
43
43
  if (!result.isSuccess) {
44
44
  const code = result.error?.code ?? "unknown";
45
45
  const message = result.error?.message ?? "(no message)";
46
- throw new Error(`[es-ops/seed-migration] systemWriteAs("${handlerQualifiedName}") failed: ${code} — ${message}`);
46
+ throw new Error(`systemWriteAs("${handlerQualifiedName}") failed: ${code} — ${message}`);
47
47
  }
48
48
  return result;
49
49
  },
@@ -1,14 +1,12 @@
1
- // es-ops — ES-Operations-Pattern für Kumiko-Apps.
1
+ // es-ops — ES operations pattern for Kumiko apps.
2
2
  //
3
- // Phase 1: seed-migrations. Phase 2+ docken an dieselbe Infra an
4
- // (kumiko_es_operations-Table mit operation_type-Discriminator).
3
+ // Seed migrations use the same infrastructure as later operation types
4
+ // (the `kumiko_es_operations` table with an `operation_type` discriminator).
5
5
  //
6
- // App-Author-API:
7
- // - SeedMigration: default-export-Typ einer seed-file
8
- // - runProdApp({ seedsDir }): Framework runs pending bei Boot
9
- // - bunx kumiko ops seed:new|status|apply (CLI)
10
- //
11
- // Plan-Doc: kumiko-platform/docs/plans/features/es-ops.md
6
+ // App author API:
7
+ // - `SeedMigration`: default export type of a seed file
8
+ // - `runProdApp({ seedsDir })`: the framework runs pending migrations at boot
9
+ // - `bunx kumiko ops seed:new|status|apply` (CLI)
12
10
  export { createSeedMigrationContext, } from "./context.js";
13
11
  export { createEsOperationsTable, esOperationsTable, } from "./operations-schema.js";
14
12
  export { runPendingSeedMigrations, } from "./runner.js";
@@ -1,12 +1,6 @@
1
- // Tracking-Table für ES-Operations (Phase 1: seed-migrations; Phase 2+:
2
- // projection-rebuild, event-replay, stream-migration, ... — siehe
3
- // kumiko-platform/docs/plans/features/es-ops.md).
4
- //
5
- // File-ID-Tracking analog drizzle-kit: filename ist die ID, applied-set
6
- // liegt in dieser Tabelle. Pending = files-on-disk MINUS applied-set.
7
- //
8
- // operation_type-Discriminator lässt Phase 2+ dieselbe Tabelle nutzen,
9
- // kein Schema-Sprawl. CLI-Status filtert per type:
1
+ // Tracks ES operations. The filename is the ID, so pending operations are files on disk minus the
2
+ // applied set. The operation_type discriminator lets different operation types share one table
3
+ // without schema sprawl; CLI status commands filter by type:
10
4
  // bunx kumiko ops seed:status → operation_type = "seed-migration"
11
5
  // bunx kumiko ops projection:status → operation_type = "projection-rebuild"
12
6
  import { index, integer, table as pgTable, sql, text, timestamp } from "../db/dialect.js";
@@ -24,7 +18,7 @@ export const esOperationsTable = pgTable("kumiko_es_operations", {
24
18
  .default(sql `now()`),
25
19
  durationMs: integer("duration_ms").notNull(),
26
20
  // Trace: came from boot-time auto-apply, explicit CLI, or CI step.
27
- // Helps when forensics ask "wer hat das wann angestoßen".
21
+ // Supports forensic questions about who initiated the operation and when.
28
22
  appliedBy: text("applied_by").notNull().$type(),
29
23
  // Optional human-readable annotation — surfaced in `ops <op>:status`.
30
24
  notes: text("notes"),
@@ -3,23 +3,23 @@ import type { Registry } from "../engine/index.ts";
3
3
  import type { EsOperationAppliedBy, SeedMigrationContext } from "./types.ts";
4
4
  export type RunPendingSeedMigrationsArgs = {
5
5
  readonly db: DbConnection;
6
- /** Absoluter Pfad zum seeds-Directory (typically <appRoot>/seeds). */
6
+ /** Absolute path to the seeds directory (typically <appRoot>/seeds). */
7
7
  readonly seedsDir: string;
8
- /** Factory die den Context für jede einzelne seed-Migration erzeugt.
9
- * Caller bekommt einen DbRunner (Connection ODER aktive Tx) — Runner
10
- * ruft das pro-migration im tx-Scope auf. */
8
+ /** Factory that creates the context for each seed migration.
9
+ * The caller receives a DbRunner (connection OR active transaction); the
10
+ * runner invokes this once per migration within the transaction scope. */
11
11
  readonly createContext: (dbRunner: DbRunner) => SeedMigrationContext;
12
12
  /** Trace-marker: boot | cli | ci-pipeline. Landet in applied_by. */
13
13
  readonly appliedBy: EsOperationAppliedBy;
14
- /** Optional registry für Dry-Run-Validation: parsed jeden seed-file und
15
- * checkt dass alle referenzierten handler-QNs in der Registry existieren
16
- * BEVOR die Migration läuft. Catched camelCase-typos + andere QN-Drift
17
- * zur Boot-Zeit statt mitten im write-cycle (Phase 1.5 / A2).
14
+ /** Optional registry for dry-run validation: parses each seed file and
15
+ * checks that all referenced handler QNs exist in the registry
16
+ * BEFORE the migration runs. This catches camelCase typos and other QN
17
+ * drift at boot rather than in the middle of a write cycle.
18
18
  *
19
- * Wenn weggelassen → kein Dry-Run (backward-compat für tests die ohne
20
- * Registry arbeiten). runProdApp reicht den richtigen Registry rein. */
19
+ * If omitted, no dry run is performed (backward compatibility for tests
20
+ * that do not provide a registry). runProdApp supplies the correct one. */
21
21
  readonly registry?: Registry;
22
- /** Optional log-prefix override, default "[es-ops/seed-migration]". */
22
+ /** Optional line sink; the default logs under the "es-ops/seed-migration" namespace. */
23
23
  readonly logger?: (line: string) => void;
24
24
  };
25
25
  export type RunPendingSeedMigrationsResult = {