@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
@@ -1,19 +1,19 @@
1
- // Self-Populating Settings-Hub (config-provisioning Phase 2).
1
+ // Self-Populating Settings Hub.
2
2
  //
3
- // Leitet aus den im Registry deklarierten Config-Keys automatisch die
4
- // Settings-UI ab: pro Audience (scope) einen Parent-Nav, pro (Feature ×
5
- // scope) einen configEdit-Screen + Child-Nav darunter. Kein manuelles
6
- // r.screen/r.nav am App-Author.
3
+ // Derives the Settings UI automatically from the config keys declared in the
4
+ // registry: one parent nav per audience (scope), and one configEdit screen plus
5
+ // child nav per (feature × scope). App authors do not need manual
6
+ // r.screen/r.nav declarations.
7
7
  //
8
- // Sichtbar wird nur ein Key MIT `mask` (siehe ConfigKeyDefinition): mask ist
9
- // die per-Key-Intent „user-facing Einstellung" und trägt zugleich das Label
10
- // (mask.title, ein i18n-Key). Keys ohne mask sind internes Plumbing
11
- // (ENV-provisioniert/computed) und erscheinen nicht.
8
+ // Only a key WITH `mask` is visible (see ConfigKeyDefinition): mask is the
9
+ // per-key intent for a “user-facing setting” and also supplies its label
10
+ // (mask.title, an i18n key). Keys without mask are internal plumbing
11
+ // (ENV-provisioned/computed) and are omitted.
12
12
  //
13
- // Die erzeugten Screens/Navs werden von buildAppSchema in die FeatureSchema
14
- // des config-Features (featureName "config") gemerged — der Renderer
15
- // qualifiziert die kurzen ids/refs mit "config". Daher hier durchweg KURZE
16
- // ids/parent/screen-Refs (buildNavRegistrySliceForApp qualifiziert selbst).
13
+ // buildAppSchema merges the generated screens/navs into the FeatureSchema of
14
+ // the config feature (featureName "config"). The renderer qualifies the short
15
+ // ids/refs with "config", so this code consistently uses SHORT ids/parent/screen
16
+ // refs (buildNavRegistrySliceForApp qualifies them itself).
17
17
  import { isOptionsQueryFieldRef } from "@cosmicdrift/kumiko-types/fields";
18
18
  import { CONFIG_EDIT_ENTITY, fieldLabelKey } from "../i18n/required-surface-keys.js";
19
19
  import { isEncryptedAtRest } from "./config-helpers.js";
@@ -22,14 +22,15 @@ import { createBooleanField, createNumberField, createSelectField, createTextFie
22
22
  import { isKebabSegment, toKebab } from "./qualified-name.js";
23
23
  import { isFieldsEditSection, sectionFieldSpecs, } from "./screen-helpers.js";
24
24
  import { isOpenToAllGranted } from "./types/handlers.js";
25
- // Namespace, unter dem buildAppSchema die generierten Screens/Navs einhängt
26
- // (find-or-create FeatureSchema). MUSS gleich CONFIG_FEATURE aus dem config
27
- // bundled-feature sein — framework kann das const nicht importieren (Richtung
28
- // bundled-features → framework), darum hier gepinnt + Pin-Test bundled-seitig.
25
+ // Namespace under which buildAppSchema attaches the generated screens/navs
26
+ // (find-or-create FeatureSchema). It MUST match CONFIG_FEATURE from the config
27
+ // bundled feature. The framework cannot import that constant because of the
28
+ // bundled-features → framework dependency direction, so it is pinned here and
29
+ // verified by a bundled-feature pin test.
29
30
  export const SETTINGS_HUB_FEATURE = "config";
30
- // Eigene Workspace nur für workspace-mode-Apps (siehe buildAppSchema): Settings
31
- // erscheinen als eigener Switcher-Eintrag, statt die kuratierten App-Workspaces
32
- // zu verschmutzen. Apps ohne Workspaces zeigen die Navs über den no-filter-Pfad.
31
+ // A dedicated workspace for workspace-mode apps (see buildAppSchema): Settings
32
+ // appear as their own switcher entry instead of cluttering the curated app
33
+ // workspaces. Apps without workspaces expose these navs through the no-filter path.
33
34
  export const SETTINGS_HUB_WORKSPACE = "settings";
34
35
  // Audience-Reihenfolge im Sidebar: Plattform vor Tenant vor Benutzer.
35
36
  const SCOPE_ORDER = { system: 10, tenant: 20, user: 30 };
@@ -54,21 +55,21 @@ const SECRETS_SECTION_DESCRIPTION_KEY = "config.secrets.description";
54
55
  const audienceNavShortId = (scope) => `audience-${scope}`;
55
56
  // Generated post-boot, never via r.nav() — the boot validator exempts exactly these QNs (an app references one to place the settings group inline).
56
57
  export const SETTINGS_HUB_AUDIENCE_NAV_QNS = SCOPES_BROAD_TO_DEEP.map((scope) => `${SETTINGS_HUB_FEATURE}:nav:${audienceNavShortId(scope)}`);
57
- // An einem Scope BREITER als der Home-Scope eines Keys darf nur eine für DIESE
58
- // Ebene privilegierte Rolle den (Cascade-)Default setzen — SystemAdmin auf
59
- // system, TenantAdmin/Admin auf tenant. Am Home-Scope gilt das volle write-Set
60
- // (unverändertes Verhalten). So liefert ein tenant-Home-Key wie SMTP zusätzlich
61
- // einen SystemAdmin-only Plattform-Screen; ein Key, dessen write-Set keine
62
- // dieser Rollen nennt, bekommt keinen breiteren Screen (write-Set = opt-in).
58
+ // At a scope broader than a key's home scope, only a role privileged for THAT
59
+ // level may set the cascade default—SystemAdmin at system, TenantAdmin/Admin at
60
+ // tenant. The home scope retains the full write set (unchanged behavior). Thus a
61
+ // tenant-home key such as SMTP also gets a SystemAdmin-only platform screen; a
62
+ // key whose write set names none of these roles gets no broader screen (the write
63
+ // set is the opt-in).
63
64
  const ELEVATED_ROLES = {
64
65
  system: ["SystemAdmin"],
65
66
  tenant: ["TenantAdmin", "Admin"],
66
67
  user: [],
67
68
  };
68
- // Der interne Maschinen-Akteur (access.system). Ein Key, den NUR diese Rolle
69
- // schreiben darf, ist provisioned-not-user-facing: er gehört nicht in den
70
- // menschlichen Hub (sonst rendert ein Feld, das der sichtbare Mensch nicht
71
- // speichern kann). `as const` für Literal-Verengung am Vergleich.
69
+ // The internal machine actor (access.system). A key writable ONLY by this role
70
+ // is provisioned-not-user-facing and must not enter the human hub; otherwise the
71
+ // UI would render a field that the visible user cannot save. `as const` narrows
72
+ // the literal for the comparison.
72
73
  const MACHINE_WRITE_ROLE = "system";
73
74
  const NO_SELECTOR_GATING = {
74
75
  pluginsByOwnerGroup: new Map(),
@@ -442,7 +443,7 @@ function buildScopeResult(scope, masked, secretsEnabled, secretsWriteHandler, de
442
443
  : NO_SELECTOR_GATING;
443
444
  const screens = [];
444
445
  const navs = [];
445
- // Audience-Parent: Gruppierungs-Knoten ohne Screen.
446
+ // Audience parent: grouping node without a screen.
446
447
  navs.push({
447
448
  id: audienceNavShortId(scope),
448
449
  label: `config.settings.${scope}`,
@@ -624,10 +625,10 @@ function effectiveWriteRoles(def, scope) {
624
625
  const elevated = ELEVATED_ROLES[scope];
625
626
  return def.access.write.filter((r) => elevated.includes(r));
626
627
  }
627
- // navMembers tragen die QUALIFIZIERTEN Nav-QNs (siehe build-app-schema.test:
628
- // admin.navMembers === ["orders:nav:list", ...]). Die generierten Navs leben
629
- // unter SETTINGS_HUB_FEATURE, also `config:nav:<shortId>`. Sortiert = stabile
630
- // Landing-Screen-Wahl (firstNavScreenId iteriert navMembers der Reihe nach).
628
+ // navMembers contain QUALIFIED nav QNs (see build-app-schema.test:
629
+ // admin.navMembers === ["orders:nav:list", ...]). The generated navs live under
630
+ // SETTINGS_HUB_FEATURE, namely `config:nav:<shortId>`. Sorting provides stable
631
+ // landing-screen selection (firstNavScreenId iterates navMembers in order).
631
632
  function buildSettingsWorkspace(navs) {
632
633
  const navMembers = navs.map((n) => `${SETTINGS_HUB_FEATURE}:nav:${n.id}`).sort();
633
634
  return {
@@ -636,11 +637,10 @@ function buildSettingsWorkspace(navs) {
636
637
  label: "config.settings.title",
637
638
  icon: "settings",
638
639
  order: 1000,
639
- // Union der Zugriffs-Regeln der bereits generierten (machine-gefilterten)
640
- // Hub-Navs — sonst sieht ein unprivilegierter User einen leeren
641
- // "Settings"-Switcher. Aus den Navs statt aus `masked`, damit die
642
- // machine-only "system"-Rolle (die in keinem Nav steht) nicht ins
643
- // Switcher-Gate leakt.
640
+ // Union of the access rules for the already generated (machine-filtered) Hub
641
+ // navs; otherwise an unprivileged user would see an empty "Settings"
642
+ // switcher. Use the navs rather than `masked` so the machine-only
643
+ // "system" role, which appears in no nav, cannot leak into the switcher gate.
644
644
  access: unionAccessRules(navs.map((n) => n.access)),
645
645
  },
646
646
  navMembers,
@@ -830,14 +830,14 @@ function maskOrder(k) {
830
830
  function minMaskOrder(keys) {
831
831
  return Math.min(...keys.map(maskOrder));
832
832
  }
833
- // Der Hub ist zum Editieren — wer mindestens einen Key der Gruppe SCHREIBEN
834
- // darf, sieht den Settings-Eintrag (write, nicht read). Das hält system-scope
835
- // (write default `["system"]`) human-hidden bis der Autor write: SystemAdmin
836
- // opt-int, und zeigt user-scope (write `all`) jedem. `all` lässt sich in
837
- // AccessRule nur als openToAll ausdrücken; der Write bleibt server-seitig
838
- // per Key gegated.
839
- // Union der Navs-Access-Regeln: ein openToAll-Nav öffnet das ganze Gate, sonst
840
- // die Vereinigung der Rollen. undefined-access-Navs tragen nichts bei.
833
+ // The hub is for editing: anyone allowed to WRITE at least one key in the group
834
+ // sees the Settings entry (write, not read). This keeps system-scope (write
835
+ // default `["system"]`) hidden from humans until the author opts in with
836
+ // write: SystemAdmin, while user-scope (write `all`) is shown to everyone.
837
+ // `all` can only be represented as openToAll in AccessRule; writes remain
838
+ // gated per key on the server.
839
+ // Access rules for navs are unioned: an openToAll nav opens the whole gate;
840
+ // otherwise roles are combined. Navs without access rules contribute nothing.
841
841
  function unionAccessRules(rules) {
842
842
  const roles = [];
843
843
  for (const rule of rules) {
@@ -852,8 +852,8 @@ function unionAccessRules(rules) {
852
852
  }
853
853
  return rolesToAccess(roles);
854
854
  }
855
- // `all` lässt sich in AccessRule nur als openToAll ausdrücken; der Write bleibt
856
- // server-seitig per Key gegated.
855
+ // `all` can only be represented as openToAll in AccessRule; writes remain gated
856
+ // per key on the server.
857
857
  function rolesToAccess(roles) {
858
858
  if (roles.includes("all"))
859
859
  return {
@@ -1,33 +1,30 @@
1
- // buildTarget — typed Builder für TargetRef.
1
+ // buildTarget — typed builder for TargetRef.
2
2
  //
3
- // **Was er macht.** Erzeugt einen TargetRef, dessen action + args
4
- // compile-time gegen die treeActions-Map des Ziel-Features validiert
5
- // sind. Magic-String-URIs werden nirgends hand-getippt; das ist die
6
- // Single-Source-of-Truth für Cross-Feature-Linking im Visual-Tree.
3
+ // **What it does.** Creates a TargetRef whose action and args are
4
+ // validated at compile time against the target feature's treeActions map.
5
+ // Magic-string URIs are never typed by hand; this is the single source
6
+ // of truth for cross-feature linking in the visual tree.
7
7
  //
8
- // **Wie er typed.** Function-Overloads splitten Actions ohne args
9
- // (NoArgsAction) und Actions mit args (WithArgsAction). TS validiert:
10
- // - action ist string-literal aus den Keys von treeActions
11
- // - bei WithArgsAction sind args required und matchen
8
+ // **How it is typed.** Function overloads separate actions without args
9
+ // (NoArgsAction) from actions with args (WithArgsAction). TypeScript validates:
10
+ // - action is a string literal from the keys of treeActions
11
+ // - for WithArgsAction, args is required and matches
12
12
  // treeActions[action]["args"]
13
- // - bei NoArgsAction ist args nicht erlaubt
13
+ // - for NoArgsAction, args is not allowed
14
14
  //
15
- // **Phase 0.** Das Feature-Handle ist hier eine generische Constraint
16
- // (FeatureWithTreeActions). In Schicht 2 wird treeActions ein
17
- // Pattern-Type im Feature-AST und defineFeature exposed eine
18
- // treeActions-Slot mit gleichem Shape — dann passen real Features
19
- // drauf, ohne Builder-Änderung.
20
- //
21
- // Siehe docs/plans/architecture/visual-tree.md A5.
22
- // TypeGuard für args: Overloads garantieren ein Plain-Object, aber die
23
- // Implementation-Signature sieht args als unknown (TArgs ist erased zur
24
- // Laufzeit). Der Guard validiert die Plain-Object-Convention runtime
25
- // statt einen `as`-Cast zu setzen — siehe coding-standards.md.
15
+ // **Feature handle.** It is currently a generic constraint
16
+ // (FeatureWithTreeActions). Once treeActions becomes a pattern type in the
17
+ // feature AST and defineFeature exposes a treeActions slot with the same
18
+ // shape, real features will fit without changing the builder.
19
+ // Type guard for args: overloads guarantee a plain object, but the
20
+ // implementation signature sees args as unknown (TArgs is erased at
21
+ // runtime). The guard validates the plain-object convention at runtime
22
+ // instead of using an `as` cast.
26
23
  function isArgsObject(v) {
27
24
  return typeof v === "object" && v !== null && !Array.isArray(v);
28
25
  }
29
- // Implementation — args ist `unknown` weil die Overloads-Generic-TArgs
30
- // zur Laufzeit erased ist. Plain-Object-Convention via TypeGuard.
26
+ // Implementation — args is `unknown` because the overloads' generic TArgs
27
+ // is erased at runtime. The plain-object convention is enforced via the type guard.
31
28
  export function buildTarget(spec) {
32
29
  if (!isArgsObject(spec.args)) {
33
30
  return Object.freeze({
@@ -1,9 +1,8 @@
1
- // biome-ignore-all lint/suspicious/noConsole: CLI tool — console.log is the output
2
1
  // biome-ignore-all lint/style/noNonNullAssertion: regex capture-group indexing — match-success implies non-null capture
3
2
  import { existsSync, readFileSync, writeFileSync } from "node:fs";
4
3
  import { join, relative } from "node:path";
5
4
  import { Glob } from "bun";
6
- import { Project, SyntaxKind } from "ts-morph";
5
+ import { Node, Project, SyntaxKind } from "ts-morph";
7
6
  export function analyzeHandlerArrow(arrowText) {
8
7
  const text = arrowText.trim();
9
8
  let handlerBodyText;
@@ -53,24 +52,30 @@ export function analyzeHandlerArrow(arrowText) {
53
52
  l.startsWith("for ") ||
54
53
  l.startsWith("while ") ||
55
54
  l.startsWith("} else"));
56
- const createMatch = handlerBodyText.match(/const\s+(\w+)\s*=\s*await\s+(\w+)\.create\s*\(/);
55
+ const [, createVar, createExecutor] = handlerBodyText.match(/const\s+(\w+)\s*=\s*await\s+(\w+)\.create\s*\(/) ?? [];
57
56
  const updateMatch = handlerBodyText.match(/const\s+(\w+)\s*=\s*await\s+(\w+)\.update\s*\(/);
58
57
  const hasSimpleReturn = /return\s*\{[^}]*isSuccess:\s*true/.test(handlerBodyText);
59
- if (createMatch && hasSimpleReturn && !hasConditionalLogic) {
58
+ if (createVar !== undefined &&
59
+ createExecutor !== undefined &&
60
+ hasSimpleReturn &&
61
+ !hasConditionalLogic) {
60
62
  isSimpleExecutorCreate = true;
61
- executorName = createMatch[2];
62
- executorCreateVar = createMatch[1];
63
- executorCreateArgs = extractArgs(handlerBodyText, createMatch[2], "create");
63
+ executorName = createExecutor;
64
+ executorCreateVar = createVar;
65
+ executorCreateArgs = extractArgs(handlerBodyText, createExecutor, "create");
64
66
  }
65
- else if (createMatch && hasSimpleReturn && hasConditionalLogic) {
67
+ else if (createVar !== undefined &&
68
+ createExecutor !== undefined &&
69
+ hasSimpleReturn &&
70
+ hasConditionalLogic) {
66
71
  // Try to match the guard pattern: if (!<var>.isSuccess) { return fail } return success
67
- const guard = extractGuardedPattern(handlerBodyText, createMatch[1]);
72
+ const guard = extractGuardedPattern(handlerBodyText, createVar);
68
73
  if (guard) {
69
74
  isGuardedCreate = true;
70
75
  guardConfig = guard;
71
- executorName = createMatch[2];
72
- executorCreateVar = createMatch[1];
73
- executorCreateArgs = extractArgs(handlerBodyText, createMatch[2], "create");
76
+ executorName = createExecutor;
77
+ executorCreateVar = createVar;
78
+ executorCreateArgs = extractArgs(handlerBodyText, createExecutor, "create");
74
79
  }
75
80
  }
76
81
  if (updateMatch &&
@@ -312,6 +317,8 @@ function inferSchemaType(objLiteral) {
312
317
  const schemaProp = objLiteral.getProperty("schema");
313
318
  if (!schemaProp)
314
319
  return "unknown";
320
+ if (!Node.isPropertyAssignment(schemaProp))
321
+ return "unknown";
315
322
  const init = schemaProp.getInitializer();
316
323
  if (!init)
317
324
  return "unknown";
@@ -431,7 +438,7 @@ function ensurePipelineImport(content) {
431
438
  const importRegex = /import\s*\{([^}]*)\}\s*from\s*["']@cosmicdrift\/kumiko-framework\/engine["']/;
432
439
  const match = content.match(importRegex);
433
440
  if (match) {
434
- const existingImports = match[1].trim();
441
+ const existingImports = (match[1] ?? "").trim();
435
442
  const newImports = existingImports ? `${existingImports}, stepsPipeline` : "stepsPipeline";
436
443
  return content.replace(importRegex, `import { ${newImports} } from "@cosmicdrift/kumiko-framework/engine"`);
437
444
  }
@@ -10,9 +10,9 @@ export function isEncryptedAtRest(def) {
10
10
  // --- Access Presets ---
11
11
  export const access = {
12
12
  all: ["all"], // @cast-boundary schema-walk
13
- // TenantAdmin zusätzlich: bundled-features vergeben "TenantAdmin",
14
- // App-Repos historisch "Admin" — das Preset deckt beide ab, sonst
15
- // driftet die writeRole-Spalte der Feature-Reference (Manifest 243/2).
13
+ // Bundled features use "TenantAdmin", while app repositories historically use
14
+ // "Admin"; including both prevents the feature reference's writeRole from
15
+ // drifting.
16
16
  admin: ["TenantAdmin", "Admin", "SystemAdmin"], // @cast-boundary schema-walk
17
17
  systemAdmin: ["SystemAdmin"], // @cast-boundary schema-walk
18
18
  system: ["system"], // @cast-boundary schema-walk
@@ -25,7 +25,7 @@ export const access = {
25
25
  // also set via ctx.systemWriteAs (roles = [SYSTEM_ROLE]). Stays human-writable
26
26
  // because checkWriteAccess only collapses to system-only when system is the
27
27
  // SOLE writer (humanWriters empty). Composes any preset, so apps with custom
28
- // roles get the same provisioning path (issue #396).
28
+ // roles get the same provisioning path.
29
29
  withSystem: (roles) => [SYSTEM_ROLE, ...roles],
30
30
  };
31
31
  // --- Scope Defaults ---
@@ -31,7 +31,7 @@ export const LifecycleHookTypes = {
31
31
  // --- Config Scopes ---
32
32
  // Value object satisfies the canonical ConfigScope union from kumiko-types —
33
33
  // a scope added here without a matching kumiko-types member is now a
34
- // compile error instead of silent drift (#1423/#1439).
34
+ // compile error instead of silent drift.
35
35
  export const ConfigScopes = {
36
36
  system: "system",
37
37
  tenant: "tenant",
@@ -65,7 +65,7 @@ void _concurrencyModeExhaustive;
65
65
  // --- Money Currency Sources ---
66
66
  // Canonical definition lives in kumiko-types/fields (client-safe, next to
67
67
  // MoneyCurrencySource) so renderer code can import it without pulling in
68
- // runtime-only engine code (fw#2937). Re-exported here for server callers
68
+ // runtime-only engine code. Re-exported here for server callers
69
69
  // already importing framework/engine (bundled-features/src/tenant-settings/
70
70
  // constants.ts TenantSettingsConfig.currency reuses this same constant, so
71
71
  // the two stay in sync by construction).
@@ -11,7 +11,7 @@ function inlineFormFieldMaps(screen) {
11
11
  return [];
12
12
  return screen.confirm !== undefined ? [screen.fields, screen.confirm.fields] : [screen.fields];
13
13
  }
14
- // `currency: { kind: "literal", code }` (fw#2839) is only meaningful for a
14
+ // `currency: { kind: "literal", code }` is only meaningful for a
15
15
  // code the app knows — a typo would otherwise render and submit amounts in a
16
16
  // currency no formatter or rate table covers.
17
17
  function validateLiteralCurrencyCode(where, field, currencies) {
@@ -106,7 +106,7 @@ export function createApp(config) {
106
106
  }
107
107
  }
108
108
  // A money field on an entity-less form screen names its own currency
109
- // source (fw#2839) — a literal code has to be one the app actually knows,
109
+ // source — a literal code has to be one the app actually knows,
110
110
  // same rule the entity `defaultCurrency` check above applies.
111
111
  for (const [screenId, screen] of Object.entries(feature.screens ?? {})) {
112
112
  const inlineFields = inlineFormFieldMaps(screen);
@@ -48,17 +48,25 @@ export function defineFeature(name, setup, settings) {
48
48
  },
49
49
  requires: (() => {
50
50
  const fn = (...args) => {
51
- if (!args.every(isObjectArgument))
51
+ const [first, ...rest] = args;
52
+ if (rest.length > 0 || !isObjectArgument(first)) {
52
53
  throwObjectArgumentRequired(name, "requires");
53
- state.requires.push(...resolveFeatureNamesArgs(args));
54
+ }
55
+ // Untyped callers can pass `{ feature: [...] }`; without this the object would be
56
+ // registered as a dependency name.
57
+ if (!Array.isArray(first.features) || !first.features.every((f) => typeof f === "string")) {
58
+ throw new Error(`[Feature ${name}] r.requires() needs { features: string[] }`);
59
+ }
60
+ state.requires.push(...first.features);
54
61
  };
55
- fn.projection = (tableName) => {
56
- state.requiredProjections.add(tableName);
57
- };
58
- fn.step = (stepKind) => {
59
- state.requiredSteps.add(stepKind);
60
- };
61
- return fn;
62
+ return Object.assign(fn, {
63
+ projection: (tableName) => {
64
+ state.requiredProjections.add(tableName);
65
+ },
66
+ step: (stepKind) => {
67
+ state.requiredSteps.add(stepKind);
68
+ },
69
+ });
62
70
  })(),
63
71
  optionalRequires(...args) {
64
72
  state.optionalRequires.push(...resolveFeatureNamesArgs(args));
@@ -106,10 +114,10 @@ export function defineFeature(name, setup, settings) {
106
114
  postDelete: state.phasedLifecycleHooks.postDelete,
107
115
  preQuery: state.lifecycleHooks["preQuery"] ?? {},
108
116
  postQuery: state.lifecycleHooks["postQuery"] ?? {},
109
- // @cast-boundary engine-bridge — die Hook-Registrierung erased die
110
- // per-Slot-Signaturen zu LifecycleHookFn (Union, s. Cast in
111
- // addLifecycleHook); die Branches dort sind die einzigen Producer und
112
- // schreiben pro Slot typrichtig.
117
+ // @cast-boundary engine-bridge — hook registration erases the per-slot
118
+ // signatures to LifecycleHookFn (a union; see the cast in
119
+ // addLifecycleHook). The branches there are the only producers and write
120
+ // the correct type for each slot.
113
121
  },
114
122
  entityHooks: {
115
123
  postSave: state.entityPostSave,
@@ -7,6 +7,10 @@ function pickPreTransactionPhases(def) {
7
7
  ...(def.beforeTransaction && { beforeTransaction: def.beforeTransaction }),
8
8
  };
9
9
  }
10
+ // `in` keeps both branches of the discriminated union readable regardless of narrowing.
11
+ function hasHandlerAndPerform(def) {
12
+ return ("handler" in def && def.handler !== undefined && "perform" in def && def.perform !== undefined);
13
+ }
10
14
  export function defineWriteHandler(def,
11
15
  // R6: a phantom rest-param. When the inferred response `TData` carries a
12
16
  // Secret<> anywhere, ContainsSecret<TData> is `true` and this resolves to a
@@ -32,13 +36,10 @@ export function defineWriteHandler(def,
32
36
  // The discriminated-union type-error
33
37
  // "Type 'PipelineDef<...>' is not assignable to type 'undefined'."
34
38
  // is functional but cryptic for less TS-experienced users; this throws
35
- // a name-and-explanation error message instead. Followup #3.
36
- // The cast is necessary because the discriminated union narrows
37
- // `handler` away once `perform` is present (and vice-versa) — at this
38
- // boundary we want to read both regardless of the narrowing.
39
- const probe = def;
40
- if (probe.handler !== undefined && probe.perform !== undefined) {
41
- throw new Error(`defineWriteHandler("${def.name}"): both \`handler\` and \`perform\` are set. ` +
39
+ // a name-and-explanation error message instead.
40
+ const handlerName = def.name;
41
+ if (hasHandlerAndPerform(def)) {
42
+ throw new Error(`defineWriteHandler("${handlerName}"): both \`handler\` and \`perform\` are set. ` +
42
43
  `Pick one — \`handler\` for the free-form async function, ` +
43
44
  `\`perform: stepsPipeline(...)\` for the step-pipeline form. ` +
44
45
  `(See step-vocabulary.md for which form fits.)`);
@@ -56,6 +57,7 @@ export function defineWriteHandler(def,
56
57
  ...(def.unsafeSkipTransitionGuard && { unsafeSkipTransitionGuard: true }),
57
58
  ...(def.rateLimit && { rateLimit: def.rateLimit }),
58
59
  ...(def.additionalRateLimits && { additionalRateLimits: def.additionalRateLimits }),
60
+ ...(def.rateLimitCost && { rateLimitCost: def.rateLimitCost }),
59
61
  ...(def.escapeHatch && { escapeHatch: def.escapeHatch }),
60
62
  ...pickPreTransactionPhases(def),
61
63
  ...(def.tenantlessAnonymous && { tenantlessAnonymous: true }),
@@ -103,10 +105,10 @@ export function isEntityConventionQueryHandler(def) {
103
105
  }
104
106
  // A projectionList screen's query must resolve to { rows, nextCursor, total? }
105
107
  // (CursorResult<T>) — the renderer used to read rowsQuery.data?.rows and
106
- // silently show an empty list otherwise (fw#2216: session-list); the
107
- // renderer now guards against a malformed shape at runtime instead. Use this
108
- // instead of defineQueryHandler for any query wired to a projectionList
109
- // screen's `query` so the contract is documented at the definition site.
108
+ // silently show an empty list otherwise; the renderer now guards against a
109
+ // malformed shape at runtime instead. Use this instead of defineQueryHandler
110
+ // for any query wired to a projectionList screen's `query` so the contract is
111
+ // documented at the definition site.
110
112
  //
111
113
  // Deliberately does NOT merge cursor/limit/sort/search into the input
112
114
  // schema — that would change sortable/paginated derivation for existing
@@ -4,7 +4,7 @@
4
4
  // (run-pipeline.ts) looks them up by `kind` to dispatch run-calls.
5
5
  //
6
6
  // The registry is process-global; Tier-2 step opt-in via
7
- // `r.requires.step("…")` (Q9 in step-vocabulary.md) is a future pass.
7
+ // `r.requires.step("…")` is a future pass.
8
8
  const stepRegistry = new Map();
9
9
  export function defineStep(def) {
10
10
  const existing = stepRegistry.get(def.kind);
@@ -22,9 +22,9 @@ export type WorkflowDefinition<TPayload = unknown, TData = unknown, TAwaits exte
22
22
  readonly name: string;
23
23
  readonly trigger: WorkflowTrigger;
24
24
  /**
25
- * Declared expected events (D4, workflow-resume-loop.md) — the sole route
25
+ * Declared expected events (workflow-resume-loop.md) — the sole route
26
26
  * a waitForEvent step can reach an event type. Read at registration time
27
- * to build the static apply-map (Phase 3b); values are plain event-type
27
+ * to build the static apply-map; values are plain event-type
28
28
  * strings, not the branded AwaitedEventType the pipeline closure sees.
29
29
  */
30
30
  readonly awaits?: TAwaits;
@@ -70,17 +70,17 @@ export type WorkflowInput<TPayload = unknown, TData = unknown, TAwaits extends R
70
70
  */
71
71
  export declare function defineWorkflow<TPayload = unknown, TData = unknown, const TAwaits extends Record<string, string> = Record<string, string>>(input: WorkflowInput<TPayload, TData, TAwaits>): WorkflowDefinition<TPayload, TData, TAwaits>;
72
72
  /**
73
- * Q7 Snapshot-at-Start fingerprint. SHA-256 over the workflow's stable
73
+ * Snapshot-at-Start fingerprint. SHA-256 over the workflow's stable
74
74
  * identity (name + trigger + serialized pipeline-closure source). Persisted
75
75
  * in `workflow.run.started` and re-checked at every resume so a library-
76
76
  * upgrade that changes the closure source surfaces as a loud
77
77
  * `workflow-definition-changed` failure on in-flight runs instead of a
78
78
  * silent semantic drift.
79
79
  *
80
- * Limitations (will be tightened in M.5 with the Designer/AST layer):
80
+ * Limitations (will be tightened with the Designer/AST layer):
81
81
  * - `build.toString()` captures the closure source but not bindings —
82
82
  * two definitions that import different external helpers with the
83
- * same source bytes would collide. Acceptable for M.4 because the
83
+ * same source bytes would collide. Acceptable because the
84
84
  * fingerprint is a *change-detector*, not a deep semantic identity.
85
85
  * - Minifiers / source-maps will produce different fingerprints across
86
86
  * environments. Run-the-fingerprint-in-the-same-environment is the
@@ -1,7 +1,7 @@
1
1
  // defineWorkflow — define a persistent, suspendable workflow.
2
2
  // Tier-3 / Workflow-only mount-point. See step-vocabulary.md Sample 2 for
3
3
  // the full lifecycle (run.started → wait → resume → run.completed) and
4
- // Q7 (Snapshot-at-Start) for the in-flight upgrade story.
4
+ // Snapshot-at-Start for the in-flight upgrade story.
5
5
  import { createHash } from "node:crypto";
6
6
  /**
7
7
  * Define a suspendable workflow.
@@ -39,27 +39,27 @@ export function defineWorkflow(input) {
39
39
  };
40
40
  }
41
41
  /**
42
- * Q7 Snapshot-at-Start fingerprint. SHA-256 over the workflow's stable
42
+ * Snapshot-at-Start fingerprint. SHA-256 over the workflow's stable
43
43
  * identity (name + trigger + serialized pipeline-closure source). Persisted
44
44
  * in `workflow.run.started` and re-checked at every resume so a library-
45
45
  * upgrade that changes the closure source surfaces as a loud
46
46
  * `workflow-definition-changed` failure on in-flight runs instead of a
47
47
  * silent semantic drift.
48
48
  *
49
- * Limitations (will be tightened in M.5 with the Designer/AST layer):
49
+ * Limitations (will be tightened with the Designer/AST layer):
50
50
  * - `build.toString()` captures the closure source but not bindings —
51
51
  * two definitions that import different external helpers with the
52
- * same source bytes would collide. Acceptable for M.4 because the
52
+ * same source bytes would collide. Acceptable because the
53
53
  * fingerprint is a *change-detector*, not a deep semantic identity.
54
54
  * - Minifiers / source-maps will produce different fingerprints across
55
55
  * environments. Run-the-fingerprint-in-the-same-environment is the
56
56
  * contract; cross-env replay is out of scope.
57
57
  */
58
58
  export function computeDefinitionFingerprint(workflow) {
59
- // `awaits` is part of the routing contract (D4, workflow-resume-loop.md):
59
+ // `awaits` is part of the routing contract (workflow-resume-loop.md):
60
60
  // changing which events a run waits on changes the run's behavior just
61
61
  // like changing the step source does, so a changed declaration must flip
62
- // the fingerprint and trip the Q7 stale-definition check on resume.
62
+ // the fingerprint and trip the stale-definition check on resume.
63
63
  const material = JSON.stringify({
64
64
  name: workflow.name,
65
65
  trigger: workflow.trigger,
@@ -44,6 +44,19 @@ export declare const entityListSchema: z.ZodObject<{
44
44
  }>;
45
45
  value: z.ZodUnknown;
46
46
  }, z.core.$strip>>>;
47
+ aggregate: z.ZodOptional<z.ZodObject<{
48
+ groupBy: z.ZodOptional<z.ZodString>;
49
+ measures: z.ZodDefault<z.ZodArray<z.ZodObject<{
50
+ field: z.ZodString;
51
+ kind: z.ZodEnum<{
52
+ avg: "avg";
53
+ count: "count";
54
+ max: "max";
55
+ min: "min";
56
+ sum: "sum";
57
+ }>;
58
+ }, z.core.$strip>>>;
59
+ }, z.core.$strip>>;
47
60
  }, z.core.$strip>;
48
61
  export declare function defineEntityWriteHandler(name: string, entity: EntityDefinition, options: EntityWriteHandlerOptions): WriteHandlerDef;
49
62
  export declare function defineEntityQueryHandler(name: string, entity: EntityDefinition, options: EntityQueryHandlerOptions): QueryHandlerDef;