@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
@@ -48,10 +48,10 @@ export type ManifestFeature = {
48
48
  readonly extensionsUsed: readonly ManifestExtension[];
49
49
  readonly configKeys: readonly ManifestConfigKey[];
50
50
  readonly secrets: readonly ManifestSecret[];
51
- /** Alle registrierten Write-Handler-QNs dieses Features
52
- * (z.B. "user:write:user:create", "auth-email-password:write:login").
53
- * Von `collectWriteHandlerQns` abgeleitet — dient als Source-of-Truth
54
- * für den Client-seitigen Typcheck von `dispatcher.write`-Calls. */
51
+ /** All registered write-handler QNs for this feature
52
+ * (e.g. "user:write:user:create", "auth-email-password:write:login").
53
+ * Derived from `collectWriteHandlerQns` and used as the source of truth
54
+ * for client-side type checking of `dispatcher.write` calls. */
55
55
  readonly writeHandlers: readonly string[];
56
56
  /** Picker/scaffolder UI metadata declared via r.uiHints(). Optional —
57
57
  * absent for features that haven't been annotated yet (the picker falls
@@ -68,13 +68,13 @@ export type FeatureManifest = {
68
68
  readonly tier?: string;
69
69
  };
70
70
  export type BuildManifestOptions = {
71
- /** Herkunfts-Beschreibung fürs Manifest (landet 1:1 im JSON). */
71
+ /** Description of the manifest's origin, included unchanged in the JSON. */
72
72
  readonly source: string;
73
- /** Nur diese Features emittieren (z.B. die 16 enterprise-Features einer
74
- * Registry, die auch deren bundled-requires gemountet hat). Default:
75
- * alle Features der Registry. */
73
+ /** Emit only these features (e.g. the 16 enterprise features from a
74
+ * Registry that also mounted their bundled requirements). Default:
75
+ * all features in the Registry. */
76
76
  readonly featureNames?: ReadonlySet<string>;
77
- /** Taggt jedes Feature + das Manifest top-level (z.B. "enterprise"). */
77
+ /** Tags each feature and the top-level manifest (e.g. "enterprise"). */
78
78
  readonly tier?: string;
79
79
  };
80
80
  export declare function buildManifestFromRegistry(registry: Registry, options: BuildManifestOptions): FeatureManifest;
@@ -1,10 +1,9 @@
1
- // Runtime-introspected feature-manifest — die geteilte Extraktionslogik
2
- // hinter `gen-feature-manifest.ts` (use-all-bundled) und dem enterprise-
3
- // Generator. Vorher waren das zwei fast wortgleiche Forks mit divergentem
4
- // Schema (enterprise#95): erweitert das Framework die Introspektion, driftete
5
- // die Kopie still. Quelle der Wahrheit ist die GEBOOTETE Registry — der
6
- // AST-Parser kann die imperativen Factory-Helper der bundled features nicht
7
- // lesen.
1
+ // Runtime-introspected feature manifest — shared extraction logic for
2
+ // `gen-feature-manifest.ts` (use-all-bundled) and the enterprise generator.
3
+ // These were previously two nearly identical forks with diverging schemas:
4
+ // when framework introspection was extended, the copy silently drifted. The
5
+ // booted Registry is authoritative because the AST parser cannot read the
6
+ // imperative factory helpers of bundled features.
8
7
  import { SYSTEM_EVENT_PREFIX } from "../crypto/system-event-pii.js";
9
8
  import { compareByCodepoint } from "../utils/index.js";
10
9
  import { isEncryptedAtRest } from "./config-helpers.js";
@@ -38,9 +38,9 @@ export declare function buildUiExtensionsMethods<TName extends string>(state: Fe
38
38
  */
39
39
  exposesApi(apiName: string): void;
40
40
  /**
41
- * Declares that this feature calls a cross-feature API. Boot-Validator
42
- * checkt dass irgendein anderes Feature `r.exposesApi(name)` macht und
43
- * dass dieses Feature `r.requires` darauf hat.
41
+ * Declares that this feature calls a cross-feature API. The boot validator
42
+ * checks that another feature calls `r.exposesApi(name)` and that this
43
+ * feature declares a corresponding `r.requires` dependency.
44
44
  */
45
45
  usesApi(apiName: string): void;
46
46
  bootCheck(fn: BootCheckFn): void;
@@ -6,7 +6,7 @@ import { bindHookEscapeHatchGrant } from "../pipeline/system-identity-switch.js"
6
6
  import { LifecycleHookTypes } from "./constants.js";
7
7
  import { reasonProblem } from "./escape-hatch-reason.js";
8
8
  import { resolveName } from "./handler-helpers.js";
9
- import { isObjectArgument, throwObjectArgumentRequired } from "./object-form.js";
9
+ import { isObjectArgument, requireArgument, throwObjectArgumentRequired } from "./object-form.js";
10
10
  import { isKebabSegment, isValidQn, qualifyEntityName, toKebab } from "./qualified-name.js";
11
11
  import { HookPhases } from "./types/index.js";
12
12
  // Builds hooks/extensions/projections/screens/nav/workspace/tables/tree-actions
@@ -159,7 +159,7 @@ export function buildUiExtensionsMethods(state, name) {
159
159
  }
160
160
  const targets = Array.isArray(target) ? target : [target];
161
161
  const names = targets.map(resolveName);
162
- // Hook-fn casts unten alle: @cast-boundary engine-bridge
162
+ // All hook-function casts below: @cast-boundary engine-bridge
163
163
  // — typed Dev-API (LifecycleHookFn|ValidationHookFn) → erased Map<name, fn>.
164
164
  if (type === "validation") {
165
165
  for (const n of names) {
@@ -211,7 +211,11 @@ export function buildUiExtensionsMethods(state, name) {
211
211
  },
212
212
  useExtension(extensionNameOrDefinition, entityRef, options) {
213
213
  const [extensionName, resolvedEntityRef, resolvedOptions] = typeof extensionNameOrDefinition === "string"
214
- ? [extensionNameOrDefinition, entityRef, options]
214
+ ? [
215
+ extensionNameOrDefinition,
216
+ requireArgument(entityRef, name, "useExtension", "entity"),
217
+ options,
218
+ ]
215
219
  : (() => {
216
220
  const { name, entity, ...rest } = extensionNameOrDefinition;
217
221
  return [name, entity, rest];
@@ -219,13 +223,14 @@ export function buildUiExtensionsMethods(state, name) {
219
223
  const resolvedEntityName = resolveName(resolvedEntityRef);
220
224
  // @cast-boundary engine-bridge — typed per-extension options → erased registration bag
221
225
  const optionsBag = resolvedOptions;
222
- // fw#2914 — cross-cutting escapeHatch convention for hook-context db
226
+ // Cross-cutting escapeHatch convention for hook-context db
223
227
  // access (mirrors r.hook's validation above). Validated the same way
224
228
  // for every extension regardless of its typed hook shape.
225
229
  const escapeHatch = optionsBag?.["escapeHatch"];
226
230
  if (escapeHatch !== undefined) {
227
- const reason = isPlainObject(escapeHatch) ? escapeHatch["reason"] : undefined;
228
- if (typeof reason !== "string") {
231
+ const escapeHatchObject = isPlainObject(escapeHatch) ? escapeHatch : undefined;
232
+ const reason = escapeHatchObject?.["reason"];
233
+ if (escapeHatchObject === undefined || typeof reason !== "string") {
229
234
  throw new Error(`[Feature ${name}] r.useExtension("${extensionName}", "${resolvedEntityName}", ...) declares an invalid { escapeHatch } — ` +
230
235
  `must be { reason: "<explanation>" } explaining why this usage needs unfiltered db access.`);
231
236
  }
@@ -233,7 +238,7 @@ export function buildUiExtensionsMethods(state, name) {
233
238
  if (extReasonProblem !== undefined) {
234
239
  throw new Error(`[Feature ${name}] r.useExtension("${extensionName}", "${resolvedEntityName}", ...) declares an invalid { escapeHatch } — ${extReasonProblem}`);
235
240
  }
236
- const extGrantsProblem = escapeHatchGrantsProblem(escapeHatch);
241
+ const extGrantsProblem = escapeHatchGrantsProblem(escapeHatchObject);
237
242
  if (extGrantsProblem) {
238
243
  throw new Error(`[Feature ${name}] r.useExtension("${extensionName}", "${resolvedEntityName}", ...) declares an invalid { escapeHatch } — ${extGrantsProblem}`);
239
244
  }
@@ -282,9 +287,9 @@ export function buildUiExtensionsMethods(state, name) {
282
287
  state.exposedApis.add(apiName);
283
288
  },
284
289
  /**
285
- * Declares that this feature calls a cross-feature API. Boot-Validator
286
- * checkt dass irgendein anderes Feature `r.exposesApi(name)` macht und
287
- * dass dieses Feature `r.requires` darauf hat.
290
+ * Declares that this feature calls a cross-feature API. The boot validator
291
+ * checks that another feature calls `r.exposesApi(name)` and that this
292
+ * feature declares a corresponding `r.requires` dependency.
288
293
  */
289
294
  usesApi(apiName) {
290
295
  state.usedApis.add(apiName);
@@ -344,7 +349,11 @@ export function buildUiExtensionsMethods(state, name) {
344
349
  entityRefOrDefinition.data,
345
350
  entityRefOrDefinition.upsertKey,
346
351
  ]
347
- : [entityRefOrDefinition, data, options?.upsertKey];
352
+ : [
353
+ entityRefOrDefinition,
354
+ requireArgument(data, name, "referenceData", "data"),
355
+ options?.upsertKey,
356
+ ];
348
357
  state.referenceData.push({
349
358
  entityName: resolveName(entityRef),
350
359
  data: resolvedData,
@@ -424,10 +433,9 @@ export function buildUiExtensionsMethods(state, name) {
424
433
  state.workspaces[definition.id] = definition;
425
434
  },
426
435
  httpRoute(definition) {
427
- // Path-Validation: muss mit "/" beginnen, keine /api/-Routes (die
428
- // sind dem Dispatcher reserviert; eine HTTP-Route die /api/foo
429
- // belegt, würde die Auth-Middleware umgehen ohne dass der Author
430
- // das ausgesprochen hat — bewusster Block).
436
+ // Path validation: must start with "/"; /api/ routes are reserved for the
437
+ // dispatcher. An HTTP route occupying /api/foo could bypass the auth
438
+ // middleware without the author explicitly intending it, so block it.
431
439
  if (!definition.path.startsWith("/")) {
432
440
  throw new Error(`[Feature ${name}] httpRoute path "${definition.path}" must start with "/". ` +
433
441
  `Got "${definition.path}".`);
@@ -505,7 +513,7 @@ export function buildUiExtensionsMethods(state, name) {
505
513
  }
506
514
  // `read_` is reserved for r.entity()/r.projection() (managed,
507
515
  // event-sourced, rebuildable). storeTable is the unmanaged
508
- // direct-write escape hatch — the prefix must say so (#1220).
516
+ // direct-write escape hatch — the prefix must say so.
509
517
  if (tableName.startsWith("read_")) {
510
518
  throw new Error(`[Feature ${name}] r.storeTable("${tableName}"): the "read_" prefix is reserved ` +
511
519
  `for managed r.entity()/r.projection() tables. Pick an unprefixed name or a ` +
@@ -514,7 +522,7 @@ export function buildUiExtensionsMethods(state, name) {
514
522
  // meta.source must agree with the r.storeTable() escape hatch, or the
515
523
  // migrate-generator treats schema drift on this table as safe to
516
524
  // DROP+rebuild-from-events — wiping direct-write data with no events
517
- // to replay it from (#1209).
525
+ // to replay it from.
518
526
  if (meta.source !== "unmanaged") {
519
527
  throw new Error(`[Feature ${name}] r.storeTable("${tableName}") was given an EntityTableMeta with ` +
520
528
  `source: "${meta.source}". r.storeTable() requires source: "unmanaged" (via ` +
@@ -538,16 +546,16 @@ export function buildUiExtensionsMethods(state, name) {
538
546
  };
539
547
  },
540
548
  treeActions(actions) {
541
- // Only-once-guard: zweiter Aufruf ist Author-Bug, soll am
542
- // Feature-File aufschlagen (gleicher Stil wie r.toggleable).
549
+ // Only-once guard: a second call is an authoring error that should surface in
550
+ // the feature file (matching the behavior of r.toggleable).
543
551
  if (state.treeActions !== undefined) {
544
552
  throw new Error(`[Feature ${name}] r.treeActions() already called. ` +
545
553
  `Each feature may declare a single tree-actions schema.`);
546
554
  }
547
555
  state.treeActions = actions;
548
- // Return typed handle für setup-export. Frozen damit Caller die
549
- // Map nicht nachträglich mutieren (würde Pattern-AST + Runtime-
550
- // Lookup divergieren lassen).
556
+ // Return a typed handle for the setup export. Freeze it so callers cannot
557
+ // mutate the map afterward, which would make the pattern AST and runtime
558
+ // lookup diverge.
551
559
  return Object.freeze({
552
560
  id: name,
553
561
  treeActions: actions,
@@ -119,18 +119,17 @@ export function checkWriteFieldRoles(entity, changes, user) {
119
119
  // row. For creates, pass oldRow = undefined; the check degenerates to a
120
120
  // newRow-only evaluation.
121
121
  //
122
- // `submittedChanges` and `rowContext` are deliberately separate (fw#1685):
122
+ // `submittedChanges` and `rowContext` are deliberately separate:
123
123
  // - `submittedChanges` drives WHICH fields get checked — only what the user
124
124
  // actually wrote in the request. A preSave-hook-derived field the user
125
125
  // never touched (e.g. a system hook setting `assignedTo`) must not be
126
126
  // field-ownership-checked against the user at all.
127
127
  // - `rowContext` drives what a checked field's rule is evaluated AGAINST —
128
128
  // this needs the full post-hook row, because an ownership rule can
129
- // reference a DIFFERENT column that only a hook populates (kumiko-
130
- // framework#1672: a hook derives `authorId`, a user-submitted `secretNote`
131
- // field's rule is `from("user:id", "authorId")` — the check needs the
132
- // hook-derived `authorId` in scope even though the user only wrote
133
- // `secretNote`). Defaults to `submittedChanges` when omitted.
129
+ // reference a DIFFERENT column that only a hook populates (a hook derives
130
+ // `authorId`, a user-submitted `secretNote` field's rule is `from("user:id", "authorId")`
131
+ // — the check needs the hook-derived `authorId` in scope even though the
132
+ // user only wrote `secretNote`). Defaults to `submittedChanges` when omitted.
134
133
  //
135
134
  // Returns the denied field name for the caller to wrap into an
136
135
  // `ownership_denied` error with scope: "field", or null if all fields pass.
@@ -101,17 +101,30 @@ function sumListCell(rows, listField, cell) {
101
101
  return sum;
102
102
  }
103
103
  function targetCurrency(field, current, sourceCurrency) {
104
+ // The client value is last: it must never override what the field or its sources dictate.
105
+ if (field.type === "money" && field.currency.kind === "literal")
106
+ return field.currency.code;
107
+ if (sourceCurrency !== undefined)
108
+ return sourceCurrency;
104
109
  if (isPlainObject(current) &&
105
110
  typeof current["currency"] === "string" &&
106
111
  current["currency"] !== "") {
107
112
  return current["currency"];
108
113
  }
109
- if (sourceCurrency !== undefined)
110
- return sourceCurrency;
111
- if (field.type === "money" && field.currency.kind === "literal")
112
- return field.currency.code;
113
114
  return undefined;
114
115
  }
116
+ function computeOrdinary(derivation, values, fields) {
117
+ const operands = derivation.from.map((name) => readOperand(values, fields, name));
118
+ const currencies = new Set(operands.flatMap((operand) => operand.currency ?? []));
119
+ const sourceCurrency = currencies.values().next().value;
120
+ // Operands in different currencies have no meaningful sum.
121
+ if (currencies.size > 1)
122
+ return { computed: undefined, sourceCurrency };
123
+ return {
124
+ computed: computeDerivedCellValue(derivation.op, operands.map((operand) => operand.value)),
125
+ sourceCurrency,
126
+ };
127
+ }
115
128
  /** Recomputes every derived head field of an action form from its inputs.
116
129
  * Pure and client-safe: the renderer runs it live, the server runs it
117
130
  * again (`withFormDerivations`) and overwrites whatever the client sent.
@@ -148,9 +161,7 @@ export function applyFormDerivations(values, screen) {
148
161
  ordinary = derivation;
149
162
  }
150
163
  if (ordinary !== undefined) {
151
- const operands = ordinary.from.map((name) => readOperand(result, screen.fields, name));
152
- sourceCurrency = operands.find((operand) => operand.currency !== undefined)?.currency;
153
- computed = computeDerivedCellValue(ordinary.op, operands.map((operand) => operand.value));
164
+ ({ computed, sourceCurrency } = computeOrdinary(ordinary, result, screen.fields));
154
165
  }
155
166
  if (computed === undefined) {
156
167
  delete result[target];
@@ -5,7 +5,7 @@ const MAX_WRAPPER_DEPTH = 8;
5
5
  const MAX_NESTING_DEPTH = 8;
6
6
  const referenceMetaSchema = z.union([
7
7
  z.string().min(1),
8
- z.object({ entity: z.string().min(1), by: z.string().min(1).optional() }),
8
+ z.strictObject({ entity: z.string().min(1), by: z.string().min(1).optional() }),
9
9
  ]);
10
10
  function rawReferenceMeta(field) {
11
11
  const meta = zodMeta(field);
@@ -91,4 +91,5 @@ export type { AccessRule, ActionFormScreenDefinition, ActiveMembership, ActiveMe
91
91
  export { DEFAULT_CURRENCIES, DEFAULT_LOCALES, DELIVERY_FAILURE_CODES, DELIVERY_SKIP_REASONS, HookPhases, HTTP_ERROR_CODE_PATTERN, isAgentVisibleScreen, isDeliveryErrorCode, isOpenToAllGranted, resolveAgentExposure, } from "./types/index.ts";
92
92
  export type { AwaitedEventType, PipelineBuildCtx, PipelineCtx, PipelineDef, StepBuilder, StepDef, StepFailureStrategy, StepInstance, StepKind, StepNamespace, StepResolver, } from "./types/step.ts";
93
93
  export { runValidation } from "./validation.ts";
94
+ export { walkStepInstances } from "./walk-step-instances.ts";
94
95
  export { formDerivationsOfSchema, withFormDerivations } from "./with-form-derivations.ts";
@@ -22,10 +22,9 @@ export { defineStep, getStep, listStepKinds } from "./define-step.js";
22
22
  export { computeDefinitionFingerprint, defineWorkflow } from "./define-workflow.js";
23
23
  export { computeEffectiveFeatures, isToggleableFeature } from "./effective-features.js";
24
24
  export { createEntityExecutor, defineEntityCreateHandler, defineEntityDeleteHandler, defineEntityDetailHandler, defineEntityListHandler,
25
- // Legacy single-fn-with-verb-string API. Backwards-compat — neue
26
- // Apps nehmen die verb-spezifischen Wrapper oben. Existierende
27
- // Caller (Integration-Tests, alte bundled-features) bleiben so
28
- // unverändert lauffähig.
25
+ // Legacy single-fn-with-verb-string API. Backwards compatibility — new
26
+ // apps use the verb-specific wrappers above. Existing callers (integration
27
+ // tests, old bundled-features) remain runnable without changes.
29
28
  defineEntityQueryHandler, defineEntityRestoreHandler, defineEntityUpdateHandler, defineEntityWriteHandler, defineProjectionQueryHandler, entityListSchema, MAX_LIST_LIMIT, } from "./entity-handlers.js";
30
29
  export { declareEscapeHatch } from "./escape-hatch-declaration.js";
31
30
  export { createEventDef } from "./event-def.js";
@@ -81,4 +80,5 @@ export { findOverDeepTransferChain, resolveTransferAdjacency as resolveEntityTra
81
80
  export { isSystemTenant, isUuid, parseTenantId, SYSTEM_TENANT_ID } from "./types/identifiers.js";
82
81
  export { DEFAULT_CURRENCIES, DEFAULT_LOCALES, DELIVERY_FAILURE_CODES, DELIVERY_SKIP_REASONS, HookPhases, HTTP_ERROR_CODE_PATTERN, isAgentVisibleScreen, isDeliveryErrorCode, isOpenToAllGranted, resolveAgentExposure, } from "./types/index.js";
83
82
  export { runValidation } from "./validation.js";
83
+ export { walkStepInstances } from "./walk-step-instances.js";
84
84
  export { formDerivationsOfSchema, withFormDerivations } from "./with-form-derivations.js";
@@ -1,6 +1,7 @@
1
1
  export declare function splitNamedDefinition<T extends {
2
2
  readonly name: string;
3
3
  }>(definition: T): [string, Omit<T, "name">];
4
+ export declare function requireArgument<T>(value: T | undefined, featureName: string, method: string, argument: string): T;
4
5
  export declare function unwrapArrayForm<K extends string>(args: readonly [Record<K, readonly string[]>] | readonly string[], key: K): readonly string[];
5
6
  export declare function isObjectArgument(value: unknown): boolean;
6
7
  export declare function throwObjectArgumentRequired(featureName: string, method: string): never;
@@ -4,14 +4,24 @@ export function splitNamedDefinition(definition) {
4
4
  const { name, ...rest } = definition;
5
5
  return [name, rest];
6
6
  }
7
+ // The `(name, options)` overloads make `options` required for typed callers;
8
+ // the implementation signature has to stay optional, so untyped callers are caught here.
9
+ export function requireArgument(value, featureName, method, argument) {
10
+ if (value === undefined) {
11
+ throw new Error(`[Feature ${featureName}] r.${method}() needs its ${argument} argument`);
12
+ }
13
+ return value;
14
+ }
15
+ function isStringList(args) {
16
+ return args.every((arg) => typeof arg === "string");
17
+ }
7
18
  // `optionalRequires` and `readConfig` still accept variadic strings next to a
8
19
  // single object wrapping the same string array under `key`.
9
20
  export function unwrapArrayForm(args, key) {
21
+ if (isStringList(args))
22
+ return args;
10
23
  const [first] = args;
11
- if (typeof first === "object" && first !== null && key in first) {
12
- return first[key];
13
- }
14
- return args;
24
+ return first[key];
15
25
  }
16
26
  export function isObjectArgument(value) {
17
27
  return typeof value === "object" && value !== null;
@@ -72,7 +72,7 @@ export function matchesRule(rule, user, row) {
72
72
  // `where` rules produce SQL for the DB-side filter and have no in-memory
73
73
  // evaluator — the feature author owns the semantics. Only the read path
74
74
  // reaches SQL (buildOwnershipClause); on write maps the boot-validator
75
- // rejects them outright (fw#2626), and the in-memory write helpers below
75
+ // rejects them outright, and the in-memory write helpers below
76
76
  // fail closed rather than calling in here.
77
77
  throw new Error("where-rules can only be evaluated at the SQL layer (buildOwnershipClause); they are rejected on access.write at boot.");
78
78
  }
@@ -219,7 +219,7 @@ export function shiftParams(fragment, shift) {
219
219
  // is a boot-time misconfiguration; at request time we treat it as empty
220
220
  // (safe default) rather than passing silently.
221
221
  //
222
- // Caller obligations (fw#1700) — this function returns ONLY the ownership
222
+ // Caller obligations — this function returns ONLY the ownership
223
223
  // fragment, not the full row-access contract. A raw-SQL caller (not going
224
224
  // through `ctx.db`, which already applies all three) must additionally:
225
225
  // 1. Pass `paramStart` as `params.length + 1` for its own already-bound
@@ -309,7 +309,7 @@ function ruleToFragment(rule, user, table, paramStart) {
309
309
  });
310
310
  // Runtime backstop for the boot-time probe (boot-validator/ownership.ts):
311
311
  // an unqualified column in a correlated subquery silently turns into a
312
- // fail-open tautology (fw#2639) — throw instead of shipping it.
312
+ // fail-open tautology — throw instead of shipping it.
313
313
  assertQualifiedWhereFragment(frag.sqlText, cachedTableColumnSqlNames(table), `ownership where-rule on "${tableNameOf(table)}"`);
314
314
  return { kind: "sql", sqlText: frag.sqlText, params: frag.params };
315
315
  }
@@ -1,12 +1,10 @@
1
- // Tier 2.7e Cross-Feature: ReferenceFieldDef.entity-String-Parser.
2
- //
3
- // Akzeptiert beide Formen:
1
+ // Parser for the ReferenceFieldDef.entity string. Accepts both forms:
4
2
  // - "user" → same-feature ref (featureName = currentFeature)
5
- // - "users:user" → cross-feature ref (qualifiziert)
3
+ // - "users:user" → cross-feature ref (qualified)
6
4
  //
7
- // Lebt im framework-Package damit Server-Validator + Renderer (über
8
- // Re-Export aus @cosmicdrift/kumiko-renderer/headless) denselben Parser nutzen — die
9
- // Convention darf nicht zweimal implementiert werden.
5
+ // Kept in the framework package so the server validator and renderer (via
6
+ // re-export from @cosmicdrift/kumiko-renderer/headless) use the same parser;
7
+ // the convention must not be implemented twice.
10
8
  export function parseRefTarget(raw, currentFeature) {
11
9
  const idx = raw.indexOf(":");
12
10
  if (idx < 0) {
@@ -1,3 +1,3 @@
1
- // Public API of the pattern-library — Designer (C5/C6), AI-Builder (L2),
2
- // MCP-Server (L9) consume from here.
1
+ // Public API of the pattern-library — Designer, AI-Builder,
2
+ // MCP-Server consume from here.
3
3
  export { getPatternSchema, groupByCategory, PATTERN_LIBRARY } from "./library.js";
@@ -1,6 +1,6 @@
1
1
  // Pattern-Library — concrete FormSchema entries for every FeaturePattern
2
- // kind. Centralised here so the Designer (C5/C6), the AI-Builder (L2),
3
- // and the MCP-Server (L9) share one source-of-truth for "how does this
2
+ // kind. Centralised here so the Designer, the AI-Builder,
3
+ // and the MCP-Server share one source-of-truth for "how does this
4
4
  // pattern look as a form?".
5
5
  //
6
6
  // **Updating contract:** when a new pattern-kind gets a parser/renderer
@@ -1,7 +1,7 @@
1
1
  // Forms-Schema metadata — describes how a FeaturePattern is rendered as
2
2
  // a Designer form, fed to an LLM as a JSON-Schema, or surfaced in the
3
3
  // MCP-Server tool list. One schema, three consumers — that's the whole
4
- // point of factoring this out of the hand-rolled C5 skeleton.
4
+ // point of factoring this out of the hand-rolled skeleton.
5
5
  //
6
6
  // **NOT a DSL.** The Source-of-Truth for a feature stays
7
7
  // `defineFeature.ts` — the AST-visitor (feature-ast/parse.ts) reads it
@@ -10,7 +10,7 @@
10
10
  // already-parsed FeaturePattern in a form. No alternative parser, no
11
11
  // alternative syntax, no second canonical representation.
12
12
  //
13
- // **Vokabular** (12 input-types):
13
+ // **Vocabulary** (12 input-types):
14
14
  //
15
15
  // text — single-line string (name / label / id)
16
16
  // textarea — multi-line string (description / SQL / readme)
@@ -31,6 +31,6 @@
31
31
  // FeaturePattern object using dot-separated keys (`definition.fields`,
32
32
  // `access.roles`, `templates.email`). Numeric indices use the bracket
33
33
  // form (`columns.0`). The Designer/LLM uses paths for read & write —
34
- // the patcher (C2) consumes pattern-level updates only, so paths are
34
+ // the patcher consumes pattern-level updates only, so paths are
35
35
  // purely a UI concern at this stage.
36
36
  export {};
@@ -8,7 +8,7 @@
8
8
  // the resolver-side PipelineCtx (run-pipeline.ts). Resolvers that need
9
9
  // prior step results destructure them from the resolver's ctx.
10
10
  //
11
- // Renamed from `pipeline()` (Followup #1) — it shared its name with the
11
+ // Renamed from `pipeline()` — it shared its name with the
12
12
  // internal `packages/framework/src/pipeline/` directory (dispatcher,
13
13
  // lifecycle, outbox-poller), which made repo-wide grep for `pipeline`
14
14
  // return mixed results.
@@ -76,7 +76,7 @@ export function stepsPipeline(closure) {
76
76
  // awaits map wired into the closure. The cast below is the one place a
77
77
  // workflow's raw declared event-type strings become AwaitedEventType — safe
78
78
  // because pipelineDef.awaits only ever holds what defineWorkflow's `awaits`
79
- // carried in (D4, workflow-resume-loop.md), never an unchecked external
79
+ // carried in (workflow-resume-loop.md), never an unchecked external
80
80
  // value.
81
81
  export function buildPipelineSteps(pipelineDef, event) {
82
82
  const steps = pipelineDef.build({
@@ -1,2 +1,4 @@
1
1
  import type { AppSchema } from "../ui-types/app-schema.ts";
2
+ import type { NavDefinition } from "./types/nav.ts";
2
3
  export declare function projectAppSchemaForRoles(schema: AppSchema, roles: readonly string[]): AppSchema;
4
+ export declare function isPureGroupingNav(nav: Pick<NavDefinition, "screen" | "target" | "provider">): boolean;
@@ -1,4 +1,4 @@
1
- // Per-role projection of a fully-built AppSchema (fw#3314). GET /api/schema
1
+ // Per-role projection of a fully-built AppSchema. GET /api/schema
2
2
  // used to ship the same full schema — screens, navs, workspaces, content
3
3
  // collections — to every authenticated user regardless of role, relying on
4
4
  // client-side UI checks (isUiAccessGranted) alone to hide what a role
@@ -27,7 +27,7 @@
27
27
  // @cosmicdrift/kumiko-types/handlers) — an unset `access` here means every
28
28
  // signed-in user may see the entry, the opposite stance from `hasAccess`.
29
29
  //
30
- // Reference-site coverage (every place boot-validator/screens.ts resolves a
30
+ // Reference-site coverage (every place boot-validator/screens*.ts resolves a
31
31
  // screen target is a site this file also projects):
32
32
  // - nav.screen / nav.parent (author-registered AND settings-hub-generated
33
33
  // navs — the latter use short ids relative to the synthetic "config"
@@ -204,16 +204,18 @@ function isNavDeniedOrDead(ctx, screenAccessByQn, keptScreenQns, roles) {
204
204
  const effectiveAccess = ctx.nav.access ?? screenAccessByQn.get(ctx.resolvedScreenQn);
205
205
  return !isUiAccessGranted(effectiveAccess, roles);
206
206
  }
207
+ export function isPureGroupingNav(nav) {
208
+ return nav.screen === undefined && nav.target === undefined && nav.provider !== true;
209
+ }
207
210
  function isDroppedByPropagation(ctx, dropped, childrenByParent) {
208
211
  if (ctx.resolvedParentQn !== undefined && dropped.has(ctx.resolvedParentQn))
209
212
  return true;
210
- const isPureGroupingNode = ctx.nav.screen === undefined && ctx.nav.target === undefined && ctx.nav.provider !== true;
211
- if (!isPureGroupingNode)
213
+ if (!isPureGroupingNav(ctx.nav))
212
214
  return false;
213
215
  const children = childrenByParent.get(ctx.qn) ?? [];
214
216
  return children.length > 0 && children.every((child) => dropped.has(child.qn));
215
217
  }
216
- // --- screen-target resolution helpers (mirror boot-validator/screens.ts) ---
218
+ // --- screen-target resolution helpers (mirror boot-validator/screens*.ts) ---
217
219
  function isScreenTargetKept(featureName, target, keptScreenQns) {
218
220
  return keptScreenQns.has(resolveScreenTargetQn(featureName, target));
219
221
  }
@@ -1,27 +1,27 @@
1
1
  import { updateMany } from "../db/query.js";
2
- // Typed-Apply-Helper für r.projection.apply: erlaubt per-event-type
3
- // typed event.payload-Access ohne SingleStreamApplyFn-Generic durch die
4
- // ganze ProjectionDefinition propagieren zu müssen.
2
+ // Typed apply helper for r.projection.apply: enables typed event.payload
3
+ // access per event type without propagating a SingleStreamApplyFn generic
4
+ // through the entire ProjectionDefinition.
5
5
  //
6
- // Der Helper ist ein purer Type-Vehikel — zur Laufzeit identitäts-fn:
6
+ // The helper is purely a type vehicle — an identity function at runtime:
7
7
  //
8
8
  // apply: {
9
9
  // "user.created": defineApply<UserCreatedPayload>(async (event, tx, table) => {
10
- // // event.payload ist UserCreatedPayload, nicht Record<string, unknown>.
10
+ // // event.payload is UserCreatedPayload, not Record<string, unknown>.
11
11
  // // Write through the passed `table` (ES-blessed inside apply), not a
12
12
  // // closed-over branded constant.
13
13
  // await insertOne(tx, table, { id: event.aggregateId, ...event.payload });
14
14
  // }),
15
15
  // }
16
16
  //
17
- // Default-Generic = Record<string, unknown> behält rückwärtskompatibles
18
- // Verhalten für Apply-Handler die ohne Type-Argument geschrieben sind. Der
19
- // `table`-Param ist optional zu nutzen — 2-arg-Applies bleiben gültig.
17
+ // The default generic, Record<string, unknown>, preserves backward-compatible
18
+ // behavior for apply handlers written without a type argument. The `table`
19
+ // parameter is optional to use, so 2-argument applies remain valid.
20
20
  export function defineApply(fn) {
21
21
  // @cast-boundary engine-bridge — typed user-fn → erased internal storage
22
22
  return fn;
23
23
  }
24
- // Pendant für r.multiStreamProjection.apply — bekommt zusätzlich ctx.
24
+ // Counterpart for r.multiStreamProjection.apply — also receives ctx.
25
25
  export function defineMspApply(fn) {
26
26
  // @cast-boundary engine-bridge — typed user-fn → erased internal storage
27
27
  return fn;
@@ -32,7 +32,7 @@ function validateSegment(value, label, context) {
32
32
  }
33
33
  // registry-ingest.ts also qualifies handlers/projections with these two —
34
34
  // not in the public QnTypes enum, but reachable as a type segment the same
35
- // way (#1991).
35
+ // way.
36
36
  const NON_ENUM_QN_TYPES = ["stream", "projection", "workspace"];
37
37
  // Every segment word that a fully-qualified QN can carry as its type.
38
38
  const RESERVED_QN_SEGMENTS = new Set([
@@ -44,7 +44,7 @@ const RESERVED_QN_SEGMENTS = new Set([
44
44
  // the trailing part. Both signals must hold together: the scope alone
45
45
  // repeating (e.g. entity "user:create" on feature "user") or a reserved word
46
46
  // alone appearing (e.g. "compliance:query:for-tenant") are both common,
47
- // legitimate sub-structure on their own (#1991).
47
+ // legitimate sub-structure on their own.
48
48
  function isDoubleQualified(scope, segments) {
49
49
  const [first, second] = segments;
50
50
  return first === scope && second !== undefined && RESERVED_QN_SEGMENTS.has(second);
@@ -85,7 +85,7 @@ export function buildRegistryFacade(state) {
85
85
  getEntityPostQueryHooks(entityName, effectiveFeatures) {
86
86
  return filterOwned(state.entityPostQueryHooks.get(entityName), effectiveFeatures);
87
87
  },
88
- // F3 — Search-Payload-Extension contributors for an entity. Used by
88
+ // Search-Payload-Extension contributors for an entity. Used by
89
89
  // `buildSearchDocument` in system-hooks.ts to enrich the indexed payload.
90
90
  // `effectiveFeatures` filters out contributors owned by feature-toggle-
91
91
  // disabled features (parallel to getEntityPostQueryHooks etc.).