@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
@@ -0,0 +1,210 @@
1
+ import { SyntaxKind } from "ts-morph";
2
+ import { readNameLiteral, readNameOrRef, resolveSameFileObjectLiteral, } from "./extractors/shared.js";
3
+ const PATTERN_ID_MATCHERS = {
4
+ requires: matchSingletonCall,
5
+ optionalRequires: matchSingletonCall,
6
+ readsConfig: matchSingletonCall,
7
+ systemScope: matchSingletonCall,
8
+ toggleable: matchSingletonCall,
9
+ describe: matchSingletonCall,
10
+ uiHints: matchSingletonCall,
11
+ config: matchSingletonCall,
12
+ translations: matchSingletonCall,
13
+ authClaims: matchSingletonCall,
14
+ treeActions: matchSingletonCall,
15
+ entity: matchEntityCall,
16
+ relation: matchRelationCall,
17
+ nav: matchIdPropertyCall,
18
+ workspace: matchIdPropertyCall,
19
+ screen: matchIdPropertyCall,
20
+ writeHandler: matchHandlerCall,
21
+ queryHandler: matchHandlerCall,
22
+ streamHandler: matchHandlerCall,
23
+ hook: matchHookCall,
24
+ metric: matchShortNameCall,
25
+ secret: matchShortNameCall,
26
+ secretNamespace: matchShortNameCall,
27
+ claimKey: matchShortNameCall,
28
+ referenceData: matchReferenceDataCall,
29
+ useExtension: matchUseExtensionCall,
30
+ job: matchJobCall,
31
+ notification: matchNotificationCall,
32
+ httpRoute: matchHttpRouteCall,
33
+ projection: matchProjectionCall,
34
+ multiStreamProjection: matchProjectionCall,
35
+ defineEvent: matchDefineEventCall,
36
+ extendsRegistrar: matchExtendsRegistrarCall,
37
+ "ai.generate": matchAiStepCall,
38
+ "ai.extract": matchAiStepCall,
39
+ "ai.classify": matchAiStepCall,
40
+ };
41
+ export function callMatchesId(call, kind, id) {
42
+ return PATTERN_ID_MATCHERS[kind](call, id);
43
+ }
44
+ // Singletons: kind alone identifies the call.
45
+ function matchSingletonCall() {
46
+ return true;
47
+ }
48
+ function matchEntityCall(call, id) {
49
+ return (matchFirstArgString(call, id.entityName) || matchObjectProperty(call, "name", id.entityName));
50
+ }
51
+ // Positional: r.relation(entity, name, def) | Object: { entity, name, ... }
52
+ function matchRelationCall(call, id) {
53
+ if (matchFirstArgString(call, id.entityName)) {
54
+ return matchArgString(call, 1, id.relationName);
55
+ }
56
+ return (matchObjectProperty(call, "entity", id.entityName) &&
57
+ matchObjectProperty(call, "name", id.relationName));
58
+ }
59
+ function matchIdPropertyCall(call, id) {
60
+ return matchObjectProperty(call, "id", id.id);
61
+ }
62
+ function matchHandlerCall(call, id) {
63
+ return (matchFirstArgString(call, id.handlerName) || matchObjectProperty(call, "name", id.handlerName));
64
+ }
65
+ // Positional: r.hook(type, target, fn) | Object: { type, target }
66
+ function matchHookCall(call, id) {
67
+ if (typeof id.target === "object") {
68
+ return matchHookAllOfCall(call, id.hookType, id.target.allOf);
69
+ }
70
+ if (matchFirstArgString(call, id.hookType)) {
71
+ return matchArgNameOrRef(call, 1, id.target);
72
+ }
73
+ return (matchObjectProperty(call, "type", id.hookType) && matchObjectProperty(call, "target", id.target));
74
+ }
75
+ // Entity-wide { allOf } target — only ever appears as the object
76
+ // literal { allOf: entity } (positional or nested in the object
77
+ // form), never as a bare string, so check both call shapes.
78
+ function matchHookAllOfCall(call, hookType, allOfEntity) {
79
+ if (matchFirstArgString(call, hookType)) {
80
+ return matchAllOfArg(call.getArguments()[1], allOfEntity);
81
+ }
82
+ return (matchObjectProperty(call, "type", hookType) &&
83
+ matchObjectAllOfProperty(call, "target", allOfEntity));
84
+ }
85
+ function matchShortNameCall(call, id) {
86
+ return matchFirstArgString(call, id.shortName) || matchObjectProperty(call, "name", id.shortName);
87
+ }
88
+ function matchReferenceDataCall(call, id) {
89
+ return (matchFirstArgString(call, id.entityName) || matchObjectProperty(call, "entity", id.entityName));
90
+ }
91
+ // Positional: r.useExtension(name, entity) | Object: { name, entity }
92
+ function matchUseExtensionCall(call, id) {
93
+ if (matchFirstArgString(call, id.extensionName)) {
94
+ return matchArgNameOrRef(call, 1, id.entityName);
95
+ }
96
+ return (matchObjectProperty(call, "name", id.extensionName) &&
97
+ matchObjectProperty(call, "entity", id.entityName));
98
+ }
99
+ function matchJobCall(call, id) {
100
+ return matchFirstArgString(call, id.jobName) || matchObjectProperty(call, "name", id.jobName);
101
+ }
102
+ function matchNotificationCall(call, id) {
103
+ return (matchFirstArgString(call, id.notificationName) ||
104
+ matchObjectProperty(call, "name", id.notificationName));
105
+ }
106
+ // Object form only; positional doesn't apply.
107
+ function matchHttpRouteCall(call, id) {
108
+ return (matchObjectProperty(call, "method", id.method) && matchObjectProperty(call, "path", id.path));
109
+ }
110
+ function matchProjectionCall(call, id) {
111
+ return matchObjectProperty(call, "name", id.name);
112
+ }
113
+ function matchDefineEventCall(call, id) {
114
+ return matchFirstArgString(call, id.eventName) || matchObjectProperty(call, "name", id.eventName);
115
+ }
116
+ function matchExtendsRegistrarCall(call, id) {
117
+ return matchFirstArgString(call, id.extensionName);
118
+ }
119
+ function matchAiStepCall(call, id) {
120
+ return readAiStepKey(call) === id.stepKey;
121
+ }
122
+ function readAiStepKey(call) {
123
+ const arg = call.getArguments()[0];
124
+ if (!arg)
125
+ return undefined;
126
+ const obj = resolveSameFileObjectLiteral(arg);
127
+ if (!obj)
128
+ return undefined;
129
+ const prop = obj.getProperty("stepKey");
130
+ if (!prop)
131
+ return undefined;
132
+ const assign = prop.asKind(SyntaxKind.PropertyAssignment);
133
+ if (assign) {
134
+ const init = assign.getInitializer();
135
+ if (!init)
136
+ return undefined;
137
+ return readNameLiteral(init);
138
+ }
139
+ const shorthand = prop.asKind(SyntaxKind.ShorthandPropertyAssignment);
140
+ if (shorthand)
141
+ return readNameLiteral(shorthand.getNameNode());
142
+ return undefined;
143
+ }
144
+ // Resolves an argument the same way the extractors do (readNameLiteral):
145
+ // a string literal directly, or a bare identifier following its
146
+ // declaration (same-file or imported) to a string-literal initializer —
147
+ // the dominant naming style in the framework's own bundled-features
148
+ // (`r.entity(ENTITY, ...)`, `r.useExtension(EXT_X, ...)`).
149
+ //
150
+ // Narrow on purpose: every kind's arg-0 (and relation's arg-1) is parsed
151
+ // via readNameLiteral, never readNameOrRef (see round2.ts/round3.ts) —
152
+ // widening this shared helper to readNameOrRef would let an object-form
153
+ // call's first argument (an ObjectLiteralExpression) match here too,
154
+ // short-circuiting the object-form branch in callMatchesId. Positions
155
+ // where the parser itself accepts an inline `{ name: "..." }` ref use
156
+ // `matchArgNameOrRef` below instead.
157
+ function matchArgString(call, index, expected) {
158
+ const arg = call.getArguments()[index];
159
+ if (!arg)
160
+ return false;
161
+ return readNameLiteral(arg) === expected;
162
+ }
163
+ // @wrapper-known semantic-alias
164
+ function matchFirstArgString(call, expected) {
165
+ return matchArgString(call, 0, expected);
166
+ }
167
+ // Like matchArgString, but via readNameOrRef — for the specific positional
168
+ // slots where the parser accepts an inline `{ name: "..." }` object ref in
169
+ // addition to a literal/identifier (useExtension's entity arg, hook's
170
+ // target arg; see round3.ts:445 / hooks.ts:75). Not a drop-in replacement
171
+ // for matchArgString: applying it to an arg-0 position would match an
172
+ // object-form call's first (and only) argument, see the comment above.
173
+ function matchArgNameOrRef(call, index, expected) {
174
+ const arg = call.getArguments()[index];
175
+ if (!arg)
176
+ return false;
177
+ return readNameOrRef(arg) === expected;
178
+ }
179
+ // Object-form property values are resolved via readNameOrRef, not the
180
+ // narrower readNameLiteral — some properties (useExtension's `entity`,
181
+ // hook's `target`/`allOf`) accept an inline `{ name: "..." }` ref in the
182
+ // parser (see extractors/round3.ts, extractors/hooks.ts), not just a
183
+ // literal or identifier. readNameOrRef is a superset of readNameLiteral,
184
+ // so this is safe for every other property too.
185
+ function matchObjectProperty(call, propName, expected) {
186
+ const obj = call.getArguments()[0]?.asKind(SyntaxKind.ObjectLiteralExpression);
187
+ if (!obj)
188
+ return false;
189
+ const init = obj.getProperty(propName)?.asKind(SyntaxKind.PropertyAssignment)?.getInitializer();
190
+ if (!init)
191
+ return false;
192
+ return readNameOrRef(init) === expected;
193
+ }
194
+ // Matches an r.hook `{ allOf: entity }` target — as the arg node directly
195
+ // (positional call form) or as a nested object property (object call form).
196
+ function matchAllOfArg(node, expectedEntity) {
197
+ const obj = node?.asKind(SyntaxKind.ObjectLiteralExpression);
198
+ const init = obj?.getProperty("allOf")?.asKind(SyntaxKind.PropertyAssignment)?.getInitializer();
199
+ if (!init)
200
+ return false;
201
+ return readNameOrRef(init) === expectedEntity;
202
+ }
203
+ function matchObjectAllOfProperty(call, propName, expectedEntity) {
204
+ const obj = call.getArguments()[0]?.asKind(SyntaxKind.ObjectLiteralExpression);
205
+ const propInit = obj
206
+ ?.getProperty(propName)
207
+ ?.asKind(SyntaxKind.PropertyAssignment)
208
+ ?.getInitializer();
209
+ return matchAllOfArg(propInit, expectedEntity);
210
+ }
@@ -18,6 +18,7 @@ export type EntityPattern = {
18
18
  readonly source: SourceLocation;
19
19
  readonly entityName: string;
20
20
  readonly definition: EntityDefinition;
21
+ readonly backingTable?: RawRefSentinel;
21
22
  };
22
23
  export type RelationPattern = {
23
24
  readonly kind: "relation";
@@ -258,14 +259,14 @@ export type EnvSchemaPattern = {
258
259
  readonly source: SourceLocation;
259
260
  readonly schemaBody: SourceLocation;
260
261
  };
261
- /** Live-editable policy defaults for an AI pipeline step instance (#256). */
262
+ /** Live-editable policy defaults for an AI pipeline step instance. */
262
263
  export type AiStepPolicy = {
263
264
  readonly enabled: boolean;
264
265
  readonly providerId?: string;
265
266
  readonly model?: string;
266
267
  readonly params: Record<string, unknown>;
267
268
  };
268
- /** Preserves an unresolvable argument reference across parse → render (#998). */
269
+ /** Preserves an unresolvable argument reference across parse → render. */
269
270
  export type AiStepOpaqueArgs = {
270
271
  readonly __raw: string;
271
272
  };
@@ -304,6 +305,14 @@ export type UnknownPattern = {
304
305
  };
305
306
  export type FeaturePattern = EntityPattern | RelationPattern | NavPattern | WorkspacePattern | ConfigPattern | TranslationsPattern | RequiresPattern | OptionalRequiresPattern | SystemScopePattern | ToggleablePattern | DescribePattern | UiHintsPattern | MetricPattern | SecretPattern | SecretNamespacePattern | ClaimKeyPattern | ReferenceDataPattern | ReadsConfigPattern | UseExtensionPattern | UsesApiPattern | ExposesApiPattern | TreeActionsPattern | ScreenPattern | WriteHandlerPattern | QueryHandlerPattern | StreamHandlerPattern | HookPattern | JobPattern | NotificationPattern | AuthClaimsPattern | HttpRoutePattern | ProjectionPattern | MultiStreamProjectionPattern | DefineEventPattern | ExtendsRegistrarPattern | EnvSchemaPattern | AiGeneratePattern | AiExtractPattern | AiClassifyPattern | UnknownPattern;
306
307
  export type FeaturePatternKind = FeaturePattern["kind"];
308
+ export type MembersByKind<U extends {
309
+ readonly kind: string;
310
+ }> = {
311
+ readonly [K in U["kind"]]: Extract<U, {
312
+ readonly kind: K;
313
+ }>;
314
+ };
315
+ export type FeaturePatternOfKind = MembersByKind<FeaturePattern>;
307
316
  export type Editability = "static" | "mixed" | "opaque";
308
317
  export declare function getEditability(pattern: FeaturePattern): Editability;
309
318
  export {};
@@ -59,56 +59,48 @@
59
59
  // against this constant to decide "form vs read-only span" — the actual
60
60
  // SourceLocation lives at the matching path in `opaqueProps`.
61
61
  export const SCREEN_OPAQUE_MARKER = "$opaque";
62
+ const EDITABILITY_BY_KIND = {
63
+ entity: "static",
64
+ relation: "static",
65
+ nav: "static",
66
+ workspace: "static",
67
+ config: "static",
68
+ translations: "static",
69
+ requires: "static",
70
+ optionalRequires: "static",
71
+ systemScope: "static",
72
+ toggleable: "static",
73
+ describe: "static",
74
+ metric: "static",
75
+ secret: "static",
76
+ secretNamespace: "static",
77
+ claimKey: "static",
78
+ referenceData: "static",
79
+ readsConfig: "static",
80
+ useExtension: "static",
81
+ usesApi: "static",
82
+ exposesApi: "static",
83
+ treeActions: "static",
84
+ screen: "mixed",
85
+ writeHandler: "mixed",
86
+ queryHandler: "mixed",
87
+ streamHandler: "mixed",
88
+ hook: "mixed",
89
+ job: "mixed",
90
+ notification: "mixed",
91
+ httpRoute: "mixed",
92
+ projection: "mixed",
93
+ multiStreamProjection: "mixed",
94
+ defineEvent: "mixed",
95
+ "ai.generate": "mixed",
96
+ "ai.extract": "mixed",
97
+ "ai.classify": "mixed",
98
+ authClaims: "opaque",
99
+ extendsRegistrar: "opaque",
100
+ envSchema: "opaque",
101
+ uiHints: "opaque",
102
+ unknown: "opaque",
103
+ };
62
104
  export function getEditability(pattern) {
63
- switch (pattern.kind) {
64
- case "entity":
65
- case "relation":
66
- case "nav":
67
- case "workspace":
68
- case "config":
69
- case "translations":
70
- case "requires":
71
- case "optionalRequires":
72
- case "systemScope":
73
- case "toggleable":
74
- case "describe":
75
- case "metric":
76
- case "secret":
77
- case "secretNamespace":
78
- case "claimKey":
79
- case "referenceData":
80
- case "readsConfig":
81
- case "useExtension":
82
- case "usesApi":
83
- case "exposesApi":
84
- case "treeActions":
85
- return "static";
86
- case "screen":
87
- case "writeHandler":
88
- case "queryHandler":
89
- case "streamHandler":
90
- case "hook":
91
- case "job":
92
- case "notification":
93
- case "httpRoute":
94
- case "projection":
95
- case "multiStreamProjection":
96
- case "defineEvent":
97
- case "ai.generate":
98
- case "ai.extract":
99
- case "ai.classify":
100
- return "mixed";
101
- case "authClaims":
102
- case "extendsRegistrar":
103
- case "envSchema":
104
- case "uiHints":
105
- case "unknown":
106
- return "opaque";
107
- default: {
108
- // Exhaustiveness guard — adding a new pattern kind without
109
- // updating this switch produces a compile error here.
110
- const _exhaustive = pattern;
111
- return _exhaustive;
112
- }
113
- }
105
+ return EDITABILITY_BY_KIND[pattern.kind];
114
106
  }
@@ -30,92 +30,52 @@ export const VERSION_HEADER = `// kumiko-feature-version: ${FEATURE_FILE_VERSION
30
30
  * trailing newline; callers compose statements with their own joiner.
31
31
  */
32
32
  export function renderPattern(pattern) {
33
- switch (pattern.kind) {
34
- case "requires":
35
- return renderRequires(pattern);
36
- case "optionalRequires":
37
- return renderOptionalRequires(pattern);
38
- case "readsConfig":
39
- return renderReadsConfig(pattern);
40
- case "systemScope":
41
- return renderSystemScope(pattern);
42
- case "toggleable":
43
- return renderToggleable(pattern);
44
- case "describe":
45
- return renderDescribe(pattern);
46
- case "uiHints":
47
- return renderUiHints(pattern);
48
- case "entity":
49
- return renderEntity(pattern);
50
- case "relation":
51
- return renderRelation(pattern);
52
- case "nav":
53
- return renderNav(pattern);
54
- case "workspace":
55
- return renderWorkspace(pattern);
56
- case "config":
57
- return renderConfig(pattern);
58
- case "translations":
59
- return renderTranslations(pattern);
60
- case "metric":
61
- return renderMetric(pattern);
62
- case "secret":
63
- return renderSecret(pattern);
64
- case "secretNamespace":
65
- return renderSecretNamespace(pattern);
66
- case "claimKey":
67
- return renderClaimKey(pattern);
68
- case "referenceData":
69
- return renderReferenceData(pattern);
70
- case "useExtension":
71
- return renderUseExtension(pattern);
72
- case "screen":
73
- return renderScreen(pattern);
74
- case "writeHandler":
75
- return renderWriteHandler(pattern);
76
- case "queryHandler":
77
- return renderQueryHandler(pattern);
78
- case "streamHandler":
79
- return renderStreamHandler(pattern);
80
- case "hook":
81
- return renderHook(pattern);
82
- case "job":
83
- return renderJob(pattern);
84
- case "notification":
85
- return renderNotification(pattern);
86
- case "authClaims":
87
- return renderAuthClaims(pattern);
88
- case "httpRoute":
89
- return renderHttpRoute(pattern);
90
- case "projection":
91
- return renderProjection(pattern);
92
- case "multiStreamProjection":
93
- return renderMultiStreamProjection(pattern);
94
- case "defineEvent":
95
- return renderDefineEvent(pattern);
96
- case "extendsRegistrar":
97
- return renderExtendsRegistrar(pattern);
98
- case "usesApi":
99
- return renderUsesApi(pattern);
100
- case "exposesApi":
101
- return renderExposesApi(pattern);
102
- case "treeActions":
103
- return renderTreeActions(pattern);
104
- case "envSchema":
105
- return renderEnvSchema(pattern);
106
- case "ai.generate":
107
- return renderAiGenerate(pattern);
108
- case "ai.extract":
109
- return renderAiExtract(pattern);
110
- case "ai.classify":
111
- return renderAiClassify(pattern);
112
- case "unknown":
113
- return renderUnknown(pattern);
114
- default: {
115
- const _exhaustive = pattern;
116
- return _exhaustive;
117
- }
118
- }
33
+ return renderPatternOfKind(pattern.kind, pattern);
34
+ }
35
+ const PATTERN_RENDERERS = {
36
+ requires: renderRequires,
37
+ optionalRequires: renderOptionalRequires,
38
+ readsConfig: renderReadsConfig,
39
+ systemScope: renderSystemScope,
40
+ toggleable: renderToggleable,
41
+ describe: renderDescribe,
42
+ uiHints: renderUiHints,
43
+ entity: renderEntity,
44
+ relation: renderRelation,
45
+ nav: renderNav,
46
+ workspace: renderWorkspace,
47
+ config: renderConfig,
48
+ translations: renderTranslations,
49
+ metric: renderMetric,
50
+ secret: renderSecret,
51
+ secretNamespace: renderSecretNamespace,
52
+ claimKey: renderClaimKey,
53
+ referenceData: renderReferenceData,
54
+ useExtension: renderUseExtension,
55
+ screen: renderScreen,
56
+ writeHandler: renderWriteHandler,
57
+ queryHandler: renderQueryHandler,
58
+ streamHandler: renderStreamHandler,
59
+ hook: renderHook,
60
+ job: renderJob,
61
+ notification: renderNotification,
62
+ authClaims: renderAuthClaims,
63
+ httpRoute: renderHttpRoute,
64
+ projection: renderProjection,
65
+ multiStreamProjection: renderMultiStreamProjection,
66
+ defineEvent: renderDefineEvent,
67
+ extendsRegistrar: renderExtendsRegistrar,
68
+ usesApi: renderUsesApi,
69
+ exposesApi: renderExposesApi,
70
+ treeActions: renderTreeActions,
71
+ envSchema: renderEnvSchema,
72
+ "ai.generate": renderAiGenerate,
73
+ "ai.extract": renderAiExtract,
74
+ "ai.classify": renderAiClassify,
75
+ unknown: renderUnknown,
76
+ };
77
+ function renderPatternOfKind(kind, pattern) {
78
+ return PATTERN_RENDERERS[kind](pattern);
119
79
  }
120
80
  // =============================================================================
121
81
  // JSON-Like Value Renderer — emits TypeScript-source-compatible literals.
@@ -206,7 +166,8 @@ function renderEntity(p) {
206
166
  // losing `name` to the sentinel shortcut — spread the reference verbatim
207
167
  // next to the name instead.
208
168
  if (isRawRefSentinel(p.definition)) {
209
- return `r.entity({ name: ${JSON.stringify(p.entityName)}, ...${p.definition.__raw} });`;
169
+ const backingTable = p.backingTable ? `, backingTable: ${p.backingTable.__raw}` : "";
170
+ return `r.entity({ name: ${JSON.stringify(p.entityName)}, ...${p.definition.__raw}${backingTable} });`;
210
171
  }
211
172
  const merged = { name: p.entityName, ...p.definition };
212
173
  return `r.entity(${renderValue(merged)});`;
@@ -278,7 +239,7 @@ function renderUseExtension(p) {
278
239
  if (p.extensionNameRaw !== undefined) {
279
240
  // A raw-ref name can't be spread into the merged Object-Form without
280
241
  // losing it to renderValue's plain-string serialization — fall back
281
- // to positional form, which keeps the reference verbatim (#2111).
242
+ // to positional form, which keeps the reference verbatim.
282
243
  const optionsArg = p.options !== undefined ? `, ${renderValue(p.options)}` : "";
283
244
  return `r.useExtension(${nameLiteral}, ${JSON.stringify(p.entityName)}${optionsArg});`;
284
245
  }
@@ -568,7 +529,7 @@ function renderMultiStreamProjection(p) {
568
529
  function renderDefineEvent(p) {
569
530
  const nameLiteral = p.eventNameRaw ?? JSON.stringify(p.eventName);
570
531
  const migrationEntries = p.migrations !== undefined ? Object.entries(p.migrations) : [];
571
- // piiFields is a mandatory option (fw#2558) — the options object is
532
+ // piiFields is a mandatory option — the options object is
572
533
  // always rendered, unlike the old version/migrations-only shortcut.
573
534
  const lines = [`r.defineEvent(${nameLiteral}, ${p.schemaSource.raw}, {`];
574
535
  lines.push(` piiFields: ${p.piiFields.raw},`);
@@ -4,7 +4,7 @@ import { isValidIanaTimeZone } from "../time/iana.js";
4
4
  import { reasonProblem } from "./escape-hatch-reason.js";
5
5
  import { createEventDef } from "./event-def.js";
6
6
  import { resolveName } from "./handler-helpers.js";
7
- import { splitNamedDefinition, unwrapArrayForm } from "./object-form.js";
7
+ import { requireArgument, splitNamedDefinition, unwrapArrayForm } from "./object-form.js";
8
8
  import { QnTypes, qn, toKebab } from "./qualified-name.js";
9
9
  // Builds config/secrets/claims/events/jobs/notifications registrar methods.
10
10
  export function buildConfigEventsJobsMethods(state, name) {
@@ -49,7 +49,7 @@ export function buildConfigEventsJobsMethods(state, name) {
49
49
  }
50
50
  // Shared by defineEvent's `migrations` option — each entry registers a
51
51
  // single upcast step, same validation/dedup as the old standalone
52
- // r.eventMigration() call (folded into defineEvent, #1082 step 8).
52
+ // r.eventMigration() call (folded into defineEvent).
53
53
  function registerEventMigration(eventName, fromVersion, toVersion, transform) {
54
54
  if (toVersion !== fromVersion + 1) {
55
55
  throw new Error(`[Feature ${name}] defineEvent("${eventName}") migrations: only single-step migrations are allowed — toVersion must be fromVersion + 1 (got ${fromVersion} -> ${toVersion}). ` +
@@ -73,8 +73,8 @@ export function buildConfigEventsJobsMethods(state, name) {
73
73
  const [jobName, jobOptions, jobHandler] = typeof jobNameOrDefinition === "string"
74
74
  ? [
75
75
  jobNameOrDefinition,
76
- options,
77
- handler,
76
+ requireArgument(options, name, "job", "options"),
77
+ requireArgument(handler, name, "job", "handler"),
78
78
  ]
79
79
  : (() => {
80
80
  const { name: definedJobName, handler: h, ...rest } = jobNameOrDefinition;
@@ -97,9 +97,9 @@ export function buildConfigEventsJobsMethods(state, name) {
97
97
  'tz must be an IANA time zone name such as "Europe/Berlin".');
98
98
  }
99
99
  }
100
- // Resolve NameOrRef(s) in trigger.on. Multi-Trigger-Form: Array
101
- // wird zu Array von resolved strings, Single bleibt single string —
102
- // job-runner unterscheidet anhand Array.isArray.
100
+ // Resolve NameOrRef(s) in trigger.on. For the multi-trigger form, arrays
101
+ // become arrays of resolved strings while a single value remains a string;
102
+ // the job runner distinguishes them with Array.isArray.
103
103
  const trigger = "on" in jobOptions.trigger
104
104
  ? {
105
105
  on: Array.isArray(jobOptions.trigger.on)
@@ -114,7 +114,10 @@ export function buildConfigEventsJobsMethods(state, name) {
114
114
  },
115
115
  notification(notificationNameOrDefinition, definition) {
116
116
  const [notificationName, resolvedDefinition] = typeof notificationNameOrDefinition === "string"
117
- ? [notificationNameOrDefinition, definition]
117
+ ? [
118
+ notificationNameOrDefinition,
119
+ requireArgument(definition, name, "notification", "definition"),
120
+ ]
118
121
  : splitNamedDefinition(notificationNameOrDefinition);
119
122
  state.notifications[notificationName] = {
120
123
  name: notificationName,
@@ -167,7 +170,7 @@ export function buildConfigEventsJobsMethods(state, name) {
167
170
  },
168
171
  metric(shortNameOrDefinition, options) {
169
172
  const [shortName, metricOptions] = typeof shortNameOrDefinition === "string"
170
- ? [shortNameOrDefinition, options]
173
+ ? [shortNameOrDefinition, requireArgument(options, name, "metric", "options")]
171
174
  : splitNamedDefinition(shortNameOrDefinition);
172
175
  if (state.metrics[shortName]) {
173
176
  throw new Error(`[Feature ${name}] Metric "${shortName}" already registered. ` +
@@ -183,7 +186,7 @@ export function buildConfigEventsJobsMethods(state, name) {
183
186
  },
184
187
  secret(shortNameOrDefinition, options) {
185
188
  const [shortName, secretOptions] = typeof shortNameOrDefinition === "string"
186
- ? [shortNameOrDefinition, options]
189
+ ? [shortNameOrDefinition, requireArgument(options, name, "secret", "options")]
187
190
  : splitNamedDefinition(shortNameOrDefinition);
188
191
  if (state.secretKeys[shortName]) {
189
192
  throw new Error(`[Feature ${name}] Secret "${shortName}" already registered. ` +
@@ -208,7 +211,7 @@ export function buildConfigEventsJobsMethods(state, name) {
208
211
  },
209
212
  secretNamespace(shortNameOrDefinition, options) {
210
213
  const [shortName, namespaceOptions] = typeof shortNameOrDefinition === "string"
211
- ? [shortNameOrDefinition, options]
214
+ ? [shortNameOrDefinition, requireArgument(options, name, "secretNamespace", "options")]
212
215
  : splitNamedDefinition(shortNameOrDefinition);
213
216
  if (state.secretNamespaces[shortName]) {
214
217
  throw new Error(`[Feature ${name}] Secret namespace "${shortName}" already registered. ` +
@@ -227,7 +230,7 @@ export function buildConfigEventsJobsMethods(state, name) {
227
230
  ? shortNameOrDefinition
228
231
  : shortNameOrDefinition.name;
229
232
  const claimType = typeof shortNameOrDefinition === "string"
230
- ? options.type
233
+ ? requireArgument(options, name, "claimKey", "options").type
231
234
  : shortNameOrDefinition.type;
232
235
  if (state.claimKeys[shortName]) {
233
236
  throw new Error(`[Feature ${name}] Claim key "${shortName}" already declared. ` +
@@ -3,7 +3,7 @@ import { toTableName } from "../db/table-builder.js";
3
3
  import { isEntityConventionQueryHandler, isPagedQueryHandler, PAGED_QUERY_HANDLER_BRAND, } from "./define-handler.js";
4
4
  import { assertEscapeHatchAccessIsSystemAdminOnly, registerCrudHandlers, } from "./entity-handlers.js";
5
5
  import { resolveName } from "./handler-helpers.js";
6
- import { isObjectArgument, throwObjectArgumentRequired } from "./object-form.js";
6
+ import { isObjectArgument, requireArgument, throwObjectArgumentRequired } from "./object-form.js";
7
7
  const CRUD_VERBS = new Set(["create", "update", "delete"]);
8
8
  const CRUD_REGISTERED_VERBS = new Set([...CRUD_VERBS, "restore", "list", "detail"]);
9
9
  // A silent overwrite would drop framework behaviour that rides on the r.crud
@@ -42,9 +42,9 @@ function tryMapEntity(state, name, handlerName) {
42
42
  // skip: feature-name entity match is the preferred mapping
43
43
  return;
44
44
  }
45
- const entityKeys = Object.keys(state.entities);
46
- if (entityKeys.length === 1) {
47
- state.handlerEntityMappings[handlerName] = entityKeys[0];
45
+ const [onlyEntityName, ...otherEntityNames] = Object.keys(state.entities);
46
+ if (onlyEntityName !== undefined && otherEntityNames.length === 0) {
47
+ state.handlerEntityMappings[handlerName] = onlyEntityName;
48
48
  }
49
49
  }
50
50
  }
@@ -97,7 +97,11 @@ export function buildEntityHandlerMethods(state, name) {
97
97
  const { entity, name: innerName, ...rest } = entityRefOrDefinition;
98
98
  return [entity, innerName, rest];
99
99
  })()
100
- : [entityRefOrDefinition, relationName, definition];
100
+ : [
101
+ entityRefOrDefinition,
102
+ requireArgument(relationName, name, "relation", "relation name"),
103
+ requireArgument(definition, name, "relation", "definition"),
104
+ ];
101
105
  const entityName = resolveName(entityRef);
102
106
  if (!state.relations[entityName])
103
107
  state.relations[entityName] = {};
@@ -126,6 +130,9 @@ export function buildEntityHandlerMethods(state, name) {
126
130
  ...(def.unsafeSkipTransitionGuard && { unsafeSkipTransitionGuard: true }),
127
131
  ...(def.rateLimit && { rateLimit: def.rateLimit }),
128
132
  ...(def.additionalRateLimits && { additionalRateLimits: def.additionalRateLimits }),
133
+ ...(def.rateLimitCost && {
134
+ rateLimitCost: def.rateLimitCost, // @cast-boundary engine-bridge
135
+ }),
129
136
  ...(def.escapeHatch && { escapeHatch: def.escapeHatch }),
130
137
  ...transactionPhaseSlots(def),
131
138
  ...(def.tenantlessAnonymous && { tenantlessAnonymous: true }),