@cosmicdrift/kumiko-framework 0.388.0 → 0.390.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 (711) hide show
  1. package/AGENTS.md +12 -4
  2. package/README.md +1 -1
  3. package/agents/examples/apex-surface-auth.md +2 -3
  4. package/agents/examples/api-worker-split.md +9 -2
  5. package/agents/examples/auth-claims.md +1 -1
  6. package/agents/examples/cross-feature-events.md +12 -12
  7. package/agents/examples/crypto-shredding-hr.md +2 -2
  8. package/agents/examples/encrypted-tenant-config.md +1 -1
  9. package/agents/examples/error-contract.md +12 -7
  10. package/agents/examples/event-sourcing.md +29 -29
  11. package/agents/examples/files-post-processing.md +10 -8
  12. package/agents/examples/golden-path.md +13 -1
  13. package/agents/examples/inbound-mail-triage.md +1 -0
  14. package/agents/examples/lane-routing.md +2 -1
  15. package/agents/examples/legal-pages.md +2 -2
  16. package/agents/examples/lifecycle-hooks.md +55 -2
  17. package/agents/examples/list-table-options.md +466 -0
  18. package/agents/examples/managed-config.md +4 -4
  19. package/agents/examples/managed-pages.md +1 -1
  20. package/agents/examples/pdf-audit-export.md +4 -2
  21. package/agents/examples/relations.md +19 -4
  22. package/agents/examples/search.md +4 -4
  23. package/agents/examples/secrets-demo.md +9 -6
  24. package/agents/examples/state-machine.md +5 -4
  25. package/agents/examples/tenant-isolation.md +73 -1
  26. package/agents/examples/tenant-settings.md +1 -1
  27. package/agents/examples/user-data-rights.md +3 -6
  28. package/agents/examples/workflow-engine.md +53 -47
  29. package/agents/examples.md +5 -4
  30. package/agents/features.md +1 -1
  31. package/agents/widgets.md +1 -0
  32. package/dist/api/api-constants.d.ts +1 -0
  33. package/dist/api/api-constants.js +2 -0
  34. package/dist/api/auth-middleware.js +1 -1
  35. package/dist/api/auth-routes-invite.js +2 -1
  36. package/dist/api/auth-routes-shared.d.ts +2 -0
  37. package/dist/api/auth-routes-shared.js +5 -0
  38. package/dist/api/client-error-route.js +2 -3
  39. package/dist/api/entity-read-access.d.ts +4 -1
  40. package/dist/api/entity-read-access.js +14 -0
  41. package/dist/api/export/export-cells-reference.d.ts +9 -0
  42. package/dist/api/export/export-cells-reference.js +21 -0
  43. package/dist/api/export/export-cells.d.ts +11 -0
  44. package/dist/api/export/export-cells.js +136 -0
  45. package/dist/api/export/export-ciphertext-guard.d.ts +2 -0
  46. package/dist/api/export/export-ciphertext-guard.js +27 -0
  47. package/dist/api/export/export-columns.d.ts +31 -0
  48. package/dist/api/export/export-columns.js +85 -0
  49. package/dist/api/export/export-errors.d.ts +4 -0
  50. package/dist/api/export/export-errors.js +14 -0
  51. package/dist/api/export/export-route.d.ts +4 -0
  52. package/dist/api/export/export-route.js +75 -0
  53. package/dist/api/export/export-rows.d.ts +13 -0
  54. package/dist/api/export/export-rows.js +62 -0
  55. package/dist/api/export/export-screen.d.ts +13 -0
  56. package/dist/api/export/export-screen.js +47 -0
  57. package/dist/api/export/export-xlsx-writer.d.ts +4 -0
  58. package/dist/api/export/export-xlsx-writer.js +21 -0
  59. package/dist/api/extra-route.d.ts +7 -1
  60. package/dist/api/index.d.ts +23 -27
  61. package/dist/api/index.js +13 -15
  62. package/dist/api/jwt.js +1 -1
  63. package/dist/api/observability-middleware.d.ts +1 -1
  64. package/dist/api/observability-middleware.js +2 -1
  65. package/dist/api/pii-leak-guard.d.ts +3 -0
  66. package/dist/api/pii-leak-guard.js +3 -2
  67. package/dist/api/request-context-internals.d.ts +31 -0
  68. package/dist/api/request-context-internals.js +11 -0
  69. package/dist/api/request-context-scopes.d.ts +14 -0
  70. package/dist/api/request-context-scopes.js +69 -0
  71. package/dist/api/request-context.d.ts +1 -40
  72. package/dist/api/request-context.js +22 -51
  73. package/dist/api/request-id-middleware.d.ts +1 -1
  74. package/dist/api/route-registrars.d.ts +2 -1
  75. package/dist/api/route-registrars.js +1 -1
  76. package/dist/api/routes.d.ts +16 -0
  77. package/dist/api/routes.js +9 -5
  78. package/dist/api/server-boot-checks.d.ts +1 -1
  79. package/dist/api/server-boot-checks.js +2 -2
  80. package/dist/api/server-event-dispatcher.d.ts +6 -1
  81. package/dist/api/server-event-dispatcher.js +3 -4
  82. package/dist/api/server-extra-routes.d.ts +1 -1
  83. package/dist/api/server-extra-routes.js +5 -1
  84. package/dist/api/server-middleware.js +3 -1
  85. package/dist/api/server-routes.d.ts +3 -2
  86. package/dist/api/server-routes.js +8 -2
  87. package/dist/api/server-wiring.js +8 -4
  88. package/dist/api/server.d.ts +2 -1
  89. package/dist/api/sse-route.d.ts +3 -1
  90. package/dist/api/sse-route.js +11 -1
  91. package/dist/api/tenant-scoped-secrets.d.ts +2 -0
  92. package/dist/api/tenant-scoped-secrets.js +13 -0
  93. package/dist/api/websocket-route.d.ts +1 -1
  94. package/dist/auth/index.d.ts +0 -1
  95. package/dist/auth/roles.d.ts +0 -5
  96. package/dist/compliance/duration-spec.d.ts +0 -1
  97. package/dist/compliance/duration-spec.js +0 -5
  98. package/dist/compliance/index.d.ts +4 -4
  99. package/dist/compliance/index.js +2 -2
  100. package/dist/compliance/profiles.d.ts +0 -15
  101. package/dist/compliance/profiles.js +0 -23
  102. package/dist/config/index.d.ts +11 -9
  103. package/dist/config/index.js +13 -1
  104. package/dist/config/internals.d.ts +9 -0
  105. package/dist/config/internals.js +1 -0
  106. package/dist/consumer-cli-internals.d.ts +4 -0
  107. package/dist/consumer-cli-internals.js +1 -0
  108. package/dist/consumer-cli.d.ts +1 -4
  109. package/dist/consumer-cli.js +5 -1
  110. package/dist/crypto/event-pii.js +1 -1
  111. package/dist/crypto/index.d.ts +8 -9
  112. package/dist/crypto/index.js +7 -8
  113. package/dist/crypto/pg-kms-adapter.d.ts +1 -0
  114. package/dist/crypto/pg-kms-adapter.js +17 -18
  115. package/dist/db/aggregate-sql.d.ts +2 -0
  116. package/dist/db/aggregate-sql.js +10 -0
  117. package/dist/db/apply-entity-event.d.ts +1 -1
  118. package/dist/db/apply-entity-event.js +15 -47
  119. package/dist/db/blind-index-cleanup.js +91 -77
  120. package/dist/db/closed-connection.js +12 -19
  121. package/dist/db/collect-table-metas.js +1 -1
  122. package/dist/db/compound-types.d.ts +1 -1
  123. package/dist/db/compound-types.js +0 -7
  124. package/dist/db/config-seed.d.ts +2 -1
  125. package/dist/db/config-seed.js +6 -1
  126. package/dist/db/connection.d.ts +7 -6
  127. package/dist/db/connection.js +43 -24
  128. package/dist/db/cross-tenant-reads.d.ts +1 -1
  129. package/dist/db/cross-tenant-reads.js +1 -1
  130. package/dist/db/dialect.d.ts +0 -5
  131. package/dist/db/dialect.js +0 -3
  132. package/dist/db/driver-row-coercion.js +4 -4
  133. package/dist/db/driver-value-preparation.js +6 -4
  134. package/dist/db/eagerload.d.ts +2 -1
  135. package/dist/db/entity-field-encryption.d.ts +1 -1
  136. package/dist/db/entity-table-meta.d.ts +1 -1
  137. package/dist/db/event-store-executor-context.d.ts +3 -1
  138. package/dist/db/event-store-executor-context.js +4 -3
  139. package/dist/db/event-store-executor-read-aggregate-currencies.d.ts +17 -0
  140. package/dist/db/event-store-executor-read-aggregate-currencies.js +40 -0
  141. package/dist/db/event-store-executor-read-aggregate.js +36 -5
  142. package/dist/db/event-store-executor-read-filter.d.ts +1 -1
  143. package/dist/db/event-store-executor-read-filter.js +6 -3
  144. package/dist/db/event-store-executor-read-rows.d.ts +2 -1
  145. package/dist/db/event-store-executor-read-search.d.ts +2 -1
  146. package/dist/db/event-store-executor-read-sort.d.ts +2 -1
  147. package/dist/db/event-store-executor-read.js +2 -2
  148. package/dist/db/event-store-executor-write-atomic.d.ts +4 -0
  149. package/dist/db/event-store-executor-write-atomic.js +42 -0
  150. package/dist/db/event-store-executor-write-steps.d.ts +3 -5
  151. package/dist/db/event-store-executor-write-steps.js +0 -5
  152. package/dist/db/event-store-executor-write.js +22 -19
  153. package/dist/db/event-store-executor.d.ts +1 -1
  154. package/dist/db/event-store-executor.js +2 -1
  155. package/dist/db/executor-managed-tables.d.ts +7 -1
  156. package/dist/db/executor-managed-tables.js +12 -3
  157. package/dist/db/index.d.ts +29 -28
  158. package/dist/db/index.js +22 -20
  159. package/dist/db/known-table-names.d.ts +6 -0
  160. package/dist/db/known-table-names.js +21 -0
  161. package/dist/db/list-aggregate-labels.d.ts +1 -1
  162. package/dist/db/located-timestamp.d.ts +1 -1
  163. package/dist/db/located-timestamp.js +0 -5
  164. package/dist/db/migrate-generator.d.ts +17 -1
  165. package/dist/db/migrate-generator.js +50 -20
  166. package/dist/db/migrate-primary-key.d.ts +12 -0
  167. package/dist/db/migrate-primary-key.js +45 -0
  168. package/dist/db/migrate-rls-diff.d.ts +20 -0
  169. package/dist/db/migrate-rls-diff.js +61 -0
  170. package/dist/db/migrate-runner.js +7 -3
  171. package/dist/db/money.d.ts +1 -1
  172. package/dist/db/money.js +1 -1
  173. package/dist/db/parent-ref-clause.d.ts +2 -1
  174. package/dist/db/pg-error.d.ts +2 -0
  175. package/dist/db/pg-error.js +37 -21
  176. package/dist/db/queries/backfill-pii.js +3 -6
  177. package/dist/db/queries/database-now.js +2 -1
  178. package/dist/db/queries/ddl.d.ts +3 -0
  179. package/dist/db/queries/ddl.js +34 -1
  180. package/dist/db/queries/event-store.js +4 -2
  181. package/dist/db/queries/event-tenants.d.ts +2 -0
  182. package/dist/db/queries/event-tenants.js +17 -0
  183. package/dist/db/queries/rebuild-rls-guard.d.ts +2 -0
  184. package/dist/db/queries/rebuild-rls-guard.js +29 -0
  185. package/dist/db/queries/rls-boot-catalog.d.ts +16 -0
  186. package/dist/db/queries/rls-boot-catalog.js +39 -0
  187. package/dist/db/queries/rls-catalog.d.ts +6 -0
  188. package/dist/db/queries/rls-catalog.js +82 -0
  189. package/dist/db/queries/rls-scope.d.ts +3 -0
  190. package/dist/db/queries/rls-scope.js +17 -0
  191. package/dist/db/queries/rls-shape.d.ts +10 -0
  192. package/dist/db/queries/rls-shape.js +42 -0
  193. package/dist/db/queries/session-advisory-lock.d.ts +2 -0
  194. package/dist/db/queries/session-advisory-lock.js +23 -0
  195. package/dist/db/queries/shadow-swap.d.ts +1 -2
  196. package/dist/db/queries/shadow-swap.js +11 -28
  197. package/dist/db/queries/test-stack.d.ts +4 -1
  198. package/dist/db/queries/test-stack.js +83 -2
  199. package/dist/db/query.d.ts +14 -0
  200. package/dist/db/query.js +77 -48
  201. package/dist/db/reference-data.d.ts +1 -1
  202. package/dist/db/reference-data.js +20 -3
  203. package/dist/db/render-ddl.d.ts +6 -2
  204. package/dist/db/render-ddl.js +7 -7
  205. package/dist/db/render-rls-ddl.d.ts +35 -0
  206. package/dist/db/render-rls-ddl.js +127 -0
  207. package/dist/db/replay-migration-sql.d.ts +3 -1
  208. package/dist/db/replay-migration-sql.js +22 -5
  209. package/dist/db/replay-rls.d.ts +25 -0
  210. package/dist/db/replay-rls.js +156 -0
  211. package/dist/db/row-level-security-boot-check.d.ts +5 -0
  212. package/dist/db/row-level-security-boot-check.js +85 -0
  213. package/dist/db/row-level-security-connection.d.ts +3 -0
  214. package/dist/db/row-level-security-connection.js +213 -0
  215. package/dist/db/row-level-security-scope.d.ts +33 -0
  216. package/dist/db/row-level-security-scope.js +127 -0
  217. package/dist/db/scope-tenant-db-to-tenant.d.ts +3 -0
  218. package/dist/db/scope-tenant-db-to-tenant.js +14 -0
  219. package/dist/db/sql-identifier.d.ts +1 -0
  220. package/dist/db/sql-identifier.js +3 -0
  221. package/dist/db/statement-timeout.js +2 -1
  222. package/dist/db/table-builder.d.ts +2 -1
  223. package/dist/db/table-builder.js +1 -1
  224. package/dist/db/table-info.js +1 -1
  225. package/dist/db/table-push.d.ts +11 -2
  226. package/dist/db/table-push.js +15 -2
  227. package/dist/db/tenant-db-runner.d.ts +3 -1
  228. package/dist/db/tenant-db-runner.js +4 -3
  229. package/dist/db/tenant-db-scoped-rebind.d.ts +10 -0
  230. package/dist/db/tenant-db-scoped-rebind.js +33 -0
  231. package/dist/db/tenant-db-statement-runner.d.ts +13 -0
  232. package/dist/db/tenant-db-statement-runner.js +48 -0
  233. package/dist/db/tenant-db-upsert.d.ts +5 -0
  234. package/dist/db/tenant-db-upsert.js +91 -0
  235. package/dist/db/tenant-db.d.ts +17 -12
  236. package/dist/db/tenant-db.js +60 -121
  237. package/dist/db/tenant-id-filter.d.ts +3 -0
  238. package/dist/db/tenant-id-filter.js +30 -0
  239. package/dist/db/transaction-serialization.d.ts +6 -0
  240. package/dist/db/transaction-serialization.js +60 -0
  241. package/dist/derivatives/delete-stored-file.js +1 -1
  242. package/dist/derivatives/index.d.ts +2 -5
  243. package/dist/derivatives/index.js +2 -3
  244. package/dist/engine/access.d.ts +2 -1
  245. package/dist/engine/access.js +1 -1
  246. package/dist/engine/boot-validator/bundled-lists-table.d.ts +2 -0
  247. package/dist/engine/boot-validator/bundled-lists-table.js +36 -0
  248. package/dist/engine/boot-validator/entity-handler.d.ts +2 -1
  249. package/dist/engine/boot-validator/entity-handler.js +1 -1
  250. package/dist/engine/boot-validator/entity-list-aggregate-options.d.ts +3 -0
  251. package/dist/engine/boot-validator/entity-list-aggregate-options.js +23 -0
  252. package/dist/engine/boot-validator/list-bulk-actions.d.ts +3 -0
  253. package/dist/engine/boot-validator/list-bulk-actions.js +49 -0
  254. package/dist/engine/boot-validator/list-column-layout.d.ts +8 -0
  255. package/dist/engine/boot-validator/list-column-layout.js +41 -0
  256. package/dist/engine/boot-validator/list-table-aggregate-options.d.ts +24 -0
  257. package/dist/engine/boot-validator/list-table-aggregate-options.js +145 -0
  258. package/dist/engine/boot-validator/list-table-aggregate-query.d.ts +11 -0
  259. package/dist/engine/boot-validator/list-table-aggregate-query.js +31 -0
  260. package/dist/engine/boot-validator/list-table-export-options.d.ts +1 -0
  261. package/dist/engine/boot-validator/list-table-export-options.js +27 -0
  262. package/dist/engine/boot-validator/list-table-options.d.ts +3 -0
  263. package/dist/engine/boot-validator/list-table-options.js +77 -0
  264. package/dist/engine/boot-validator/list-table-reject-unknown-keys.d.ts +1 -0
  265. package/dist/engine/boot-validator/list-table-reject-unknown-keys.js +7 -0
  266. package/dist/engine/boot-validator/nav.d.ts +3 -1
  267. package/dist/engine/boot-validator/nav.js +1 -1
  268. package/dist/engine/boot-validator/ownership.d.ts +2 -1
  269. package/dist/engine/boot-validator/parent-ref.d.ts +2 -1
  270. package/dist/engine/boot-validator/projection-list-screens.d.ts +2 -1
  271. package/dist/engine/boot-validator/projection-list-screens.js +3 -13
  272. package/dist/engine/boot-validator/query-refs.d.ts +2 -1
  273. package/dist/engine/boot-validator/related-list-table-rules.d.ts +4 -0
  274. package/dist/engine/boot-validator/related-list-table-rules.js +42 -0
  275. package/dist/engine/boot-validator/screens-forms.d.ts +2 -1
  276. package/dist/engine/boot-validator/screens-kind-entity-list.js +7 -0
  277. package/dist/engine/boot-validator/screens-kind-projection-list.js +4 -0
  278. package/dist/engine/boot-validator/screens-kind-shared.d.ts +3 -1
  279. package/dist/engine/boot-validator/screens-lists.js +12 -2
  280. package/dist/engine/boot-validator/screens.d.ts +2 -1
  281. package/dist/engine/boot-validator/workspaces.d.ts +3 -1
  282. package/dist/engine/bridge-stub.d.ts +5 -2
  283. package/dist/engine/bridge-stub.js +39 -24
  284. package/dist/engine/build-app-schema.d.ts +2 -1
  285. package/dist/engine/build-app-schema.js +9 -1
  286. package/dist/engine/build-config-feature-schema.js +6 -1
  287. package/dist/engine/config-helpers.d.ts +2 -2
  288. package/dist/engine/config-helpers.js +0 -9
  289. package/dist/engine/constants.d.ts +0 -10
  290. package/dist/engine/constants.js +0 -8
  291. package/dist/engine/create-app.js +1 -1
  292. package/dist/engine/define-feature.d.ts +2 -1
  293. package/dist/engine/define-feature.js +5 -2
  294. package/dist/engine/define-handler.d.ts +1 -1
  295. package/dist/engine/define-step.d.ts +0 -1
  296. package/dist/engine/define-step.js +0 -3
  297. package/dist/engine/embedded-derived.d.ts +1 -1
  298. package/dist/engine/entity-handlers.d.ts +2 -1
  299. package/dist/engine/entity-handlers.js +7 -7
  300. package/dist/engine/entity-list-runtime-options.js +3 -1
  301. package/dist/engine/entity-list-searchability.d.ts +2 -1
  302. package/dist/engine/event-def.d.ts +2 -1
  303. package/dist/engine/event-helpers.d.ts +3 -1
  304. package/dist/engine/event-helpers.js +3 -3
  305. package/dist/engine/extension-names.d.ts +2 -8
  306. package/dist/engine/extension-names.js +2 -2
  307. package/dist/engine/extension-selector-plugins.d.ts +1 -1
  308. package/dist/engine/extensions/storage-provider.d.ts +1 -2
  309. package/dist/engine/extensions/user-data.d.ts +0 -8
  310. package/dist/engine/factories.d.ts +2 -1
  311. package/dist/engine/feature-builder-state.d.ts +9 -1
  312. package/dist/engine/feature-builder-state.js +1 -0
  313. package/dist/engine/feature-changelog.d.ts +1 -1
  314. package/dist/engine/feature-config-events-jobs.d.ts +4 -1
  315. package/dist/engine/feature-entity-handlers.d.ts +5 -1
  316. package/dist/engine/feature-manifest.d.ts +1 -0
  317. package/dist/engine/feature-manifest.js +2 -1
  318. package/dist/engine/feature-ui-extensions.d.ts +7 -1
  319. package/dist/engine/feature-ui-extensions.js +6 -4
  320. package/dist/engine/field-access.d.ts +3 -1
  321. package/dist/engine/field-access.js +12 -0
  322. package/dist/engine/handler-field-references.d.ts +0 -4
  323. package/dist/engine/index.d.ts +58 -55
  324. package/dist/engine/index.js +23 -28
  325. package/dist/engine/instruction-fields.d.ts +1 -1
  326. package/dist/engine/personal-data-fields.d.ts +1 -1
  327. package/dist/engine/qualified-name.d.ts +0 -1
  328. package/dist/engine/read-claim.d.ts +2 -1
  329. package/dist/engine/registry-facade.js +0 -3
  330. package/dist/engine/registry-ingest.d.ts +2 -1
  331. package/dist/engine/registry-ingest.js +1 -2
  332. package/dist/engine/registry-state.d.ts +12 -2
  333. package/dist/engine/registry-state.js +2 -3
  334. package/dist/engine/registry-validate.d.ts +3 -1
  335. package/dist/engine/registry-validate.js +7 -7
  336. package/dist/engine/run-in.d.ts +1 -1
  337. package/dist/engine/run-in.js +0 -1
  338. package/dist/engine/schema-builder.d.ts +1 -1
  339. package/dist/engine/schema-builder.js +1 -1
  340. package/dist/engine/screen-filter-ops.d.ts +2 -1
  341. package/dist/engine/screen-filter-ops.js +2 -5
  342. package/dist/engine/soft-delete-cleanup.d.ts +1 -1
  343. package/dist/engine/soft-delete-cleanup.js +4 -4
  344. package/dist/engine/state-machine.js +2 -1
  345. package/dist/engine/steps/_read-source.js +1 -1
  346. package/dist/engine/steps/aggregate-append-event.js +2 -2
  347. package/dist/engine/steps/call-feature.js +2 -2
  348. package/dist/engine/steps/mail-send.js +1 -1
  349. package/dist/engine/steps/retry.js +1 -1
  350. package/dist/engine/steps/wait-for-event.js +1 -1
  351. package/dist/engine/steps/wait.js +1 -1
  352. package/dist/engine/steps/webhook-send.js +1 -1
  353. package/dist/engine/strip-disabled-features-from-app-schema.js +7 -3
  354. package/dist/engine/template-variables.d.ts +2 -1
  355. package/dist/engine/transfer-adjacency.d.ts +1 -1
  356. package/dist/engine/types/feature.d.ts +1 -0
  357. package/dist/engine/types/index.d.ts +8 -30
  358. package/dist/engine/types/index.js +2 -10
  359. package/dist/engine/types/screen.d.ts +1 -1
  360. package/dist/engine/types/screen.js +1 -1
  361. package/dist/engine/validation.d.ts +2 -1
  362. package/dist/entrypoint/index.d.ts +9 -35
  363. package/dist/entrypoint/index.js +10 -1
  364. package/dist/entrypoint/internals.d.ts +40 -0
  365. package/dist/entrypoint/internals.js +1 -0
  366. package/dist/entrypoint/row-level-security-mode-check.d.ts +3 -0
  367. package/dist/entrypoint/row-level-security-mode-check.js +19 -0
  368. package/dist/env/dry-run-internals.d.ts +10 -0
  369. package/dist/env/dry-run-internals.js +1 -0
  370. package/dist/env/dry-run.d.ts +1 -10
  371. package/dist/env/dry-run.js +2 -1
  372. package/dist/env/index.d.ts +1 -85
  373. package/dist/env/index.js +6 -50
  374. package/dist/env/internals.d.ts +87 -0
  375. package/dist/env/internals.js +53 -0
  376. package/dist/errors/classes.js +2 -2
  377. package/dist/errors/index.d.ts +5 -14
  378. package/dist/errors/index.js +4 -9
  379. package/dist/errors/member-resolution.js +1 -1
  380. package/dist/errors/reasons.d.ts +0 -1
  381. package/dist/errors/reasons.js +7 -7
  382. package/dist/errors/serialize.d.ts +0 -18
  383. package/dist/errors/serialize.js +0 -27
  384. package/dist/es-ops/index.d.ts +4 -4
  385. package/dist/es-ops/index.js +2 -2
  386. package/dist/es-ops/operations-schema.d.ts +1 -1
  387. package/dist/es-ops/types.d.ts +4 -5
  388. package/dist/event-store/admin-api-internals.d.ts +14 -0
  389. package/dist/event-store/admin-api-internals.js +1 -0
  390. package/dist/event-store/admin-api.d.ts +1 -14
  391. package/dist/event-store/admin-api.js +11 -6
  392. package/dist/event-store/archive.js +4 -2
  393. package/dist/event-store/errors.js +2 -2
  394. package/dist/event-store/event-store.d.ts +1 -0
  395. package/dist/event-store/event-store.js +42 -32
  396. package/dist/event-store/events-schema.js +4 -1
  397. package/dist/event-store/index.d.ts +11 -13
  398. package/dist/event-store/index.js +7 -9
  399. package/dist/event-store/provenance-append.js +1 -1
  400. package/dist/event-store/rebuild-dead-letter.js +4 -2
  401. package/dist/event-store/snapshot.js +4 -3
  402. package/dist/event-store/stream-scope.d.ts +2 -0
  403. package/dist/event-store/stream-scope.js +6 -0
  404. package/dist/event-store/upcaster-dead-letter.js +4 -2
  405. package/dist/event-store/upcaster.d.ts +2 -1
  406. package/dist/files/action-form-upload.d.ts +2 -1
  407. package/dist/files/action-form-upload.js +1 -1
  408. package/dist/files/assert-file-refs-belong-to-tenant.d.ts +2 -1
  409. package/dist/files/assert-file-refs-belong-to-tenant.js +1 -1
  410. package/dist/files/bind-pending-file-refs.d.ts +2 -1
  411. package/dist/files/bind-pending-file-refs.js +2 -1
  412. package/dist/files/bind-referenced-files.write.js +1 -1
  413. package/dist/files/create-file-ref-from-bytes.d.ts +6 -3
  414. package/dist/files/create-file-ref-from-bytes.js +6 -3
  415. package/dist/files/create-file-ref.d.ts +6 -2
  416. package/dist/files/create-file-ref.js +13 -4
  417. package/dist/files/dispose-removed-file-refs.d.ts +2 -1
  418. package/dist/files/dispose-removed-file-refs.js +1 -1
  419. package/dist/files/feature.js +2 -2
  420. package/dist/files/file-handle.js +1 -1
  421. package/dist/files/file-routes.d.ts +3 -1
  422. package/dist/files/file-routes.js +41 -4
  423. package/dist/files/index.d.ts +11 -13
  424. package/dist/files/index.js +5 -7
  425. package/dist/files/load-save-file-refs.d.ts +2 -1
  426. package/dist/files/load-save-file-refs.js +1 -1
  427. package/dist/files/provider-resolver.d.ts +6 -4
  428. package/dist/files/provider-resolver.js +5 -5
  429. package/dist/files/record-write-check.d.ts +6 -0
  430. package/dist/files/record-write-check.js +13 -0
  431. package/dist/files/storage-tracking.js +4 -2
  432. package/dist/files/sweep-orphaned-uploads.d.ts +1 -1
  433. package/dist/files/sweep-orphaned-uploads.js +1 -1
  434. package/dist/files/upload-ledger.d.ts +2 -2
  435. package/dist/files/upload-ledger.js +4 -4
  436. package/dist/i18n/index.d.ts +2 -8
  437. package/dist/i18n/index.js +1 -1
  438. package/dist/i18n/internals.d.ts +7 -0
  439. package/dist/i18n/internals.js +1 -0
  440. package/dist/i18n/required-surface-keys.d.ts +4 -1
  441. package/dist/i18n/required-surface-keys.js +7 -2
  442. package/dist/internal/row-level-security.d.ts +3 -0
  443. package/dist/internal/row-level-security.js +3 -0
  444. package/dist/internal/stack-support.d.ts +1 -1
  445. package/dist/internal/stack-support.js +1 -1
  446. package/dist/internal/testing.d.ts +1 -0
  447. package/dist/internal/testing.js +10 -6
  448. package/dist/jobs/index.d.ts +1 -1
  449. package/dist/jobs/job-append-event.d.ts +12 -0
  450. package/dist/jobs/job-append-event.js +30 -0
  451. package/dist/jobs/job-runner-context.d.ts +2 -2
  452. package/dist/jobs/job-runner-context.js +46 -16
  453. package/dist/jobs/job-runner-execution.d.ts +1 -1
  454. package/dist/jobs/job-runner-execution.js +6 -4
  455. package/dist/jobs/job-runner-gates.d.ts +1 -1
  456. package/dist/jobs/job-runner-gates.js +0 -1
  457. package/dist/jobs/job-runner-helpers.d.ts +11 -4
  458. package/dist/jobs/job-runner-helpers.js +10 -1
  459. package/dist/jobs/job-runner-scope.d.ts +5 -2
  460. package/dist/jobs/job-runner-scope.js +6 -6
  461. package/dist/jobs/job-runner-types.d.ts +2 -1
  462. package/dist/jobs/job-runner.js +22 -6
  463. package/dist/jobs/max-per-tenant.d.ts +1 -1
  464. package/dist/logging/index.d.ts +1 -2
  465. package/dist/logging/index.js +1 -1
  466. package/dist/logging/pino-logger.js +1 -1
  467. package/dist/logging/utils.d.ts +1 -0
  468. package/dist/logging/utils.js +6 -0
  469. package/dist/migrations/index.d.ts +3 -3
  470. package/dist/migrations/index.js +3 -3
  471. package/dist/migrations/pending-rebuilds.d.ts +1 -1
  472. package/dist/migrations/pending-rebuilds.js +1 -1
  473. package/dist/migrations/pii-event-backfill.js +4 -1
  474. package/dist/observability/escape-hatch-report.d.ts +2 -1
  475. package/dist/observability/escape-hatch-report.js +9 -2
  476. package/dist/observability/index.d.ts +7 -15
  477. package/dist/observability/index.js +4 -12
  478. package/dist/observability/metric-validator.js +1 -1
  479. package/dist/observability/metrics-handle.d.ts +0 -1
  480. package/dist/observability/metrics-handle.js +2 -15
  481. package/dist/observability/recording-tracer.d.ts +1 -2
  482. package/dist/observability/recording-tracer.js +0 -6
  483. package/dist/observability/sensitive-filter.d.ts +0 -2
  484. package/dist/observability/sensitive-filter.js +0 -29
  485. package/dist/pipeline/active-membership.d.ts +2 -1
  486. package/dist/pipeline/active-membership.js +6 -2
  487. package/dist/pipeline/after-rollback-sink.d.ts +6 -0
  488. package/dist/pipeline/after-rollback-sink.js +32 -0
  489. package/dist/pipeline/append-event-core.d.ts +2 -1
  490. package/dist/pipeline/append-event-core.js +2 -2
  491. package/dist/pipeline/attach-outside-transaction.d.ts +3 -0
  492. package/dist/pipeline/attach-outside-transaction.js +13 -0
  493. package/dist/pipeline/auth-claims-resolver.d.ts +2 -1
  494. package/dist/pipeline/cascade-handler.d.ts +2 -1
  495. package/dist/pipeline/cascade-handler.js +3 -2
  496. package/dist/pipeline/config-accessor-factory.d.ts +1 -1
  497. package/dist/pipeline/config-accessor-factory.js +1 -1
  498. package/dist/pipeline/context-services.d.ts +56 -0
  499. package/dist/pipeline/context-services.js +73 -0
  500. package/dist/pipeline/dispatch-batch.d.ts +2 -1
  501. package/dist/pipeline/dispatch-batch.js +39 -19
  502. package/dist/pipeline/dispatch-query.js +5 -4
  503. package/dist/pipeline/dispatch-scope.d.ts +6 -0
  504. package/dist/pipeline/dispatch-scope.js +27 -0
  505. package/dist/pipeline/dispatch-shared.d.ts +13 -9
  506. package/dist/pipeline/dispatch-shared.js +75 -194
  507. package/dist/pipeline/dispatch-stream.js +8 -4
  508. package/dist/pipeline/dispatch-write.d.ts +2 -1
  509. package/dist/pipeline/dispatch-write.js +10 -8
  510. package/dist/pipeline/dispatcher-utils.d.ts +3 -1
  511. package/dist/pipeline/dispatcher-utils.js +8 -2
  512. package/dist/pipeline/dispatcher.d.ts +3 -2
  513. package/dist/pipeline/dispatcher.js +4 -3
  514. package/dist/pipeline/event-consumer-state.d.ts +0 -1
  515. package/dist/pipeline/event-dispatcher-delivery.d.ts +1 -1
  516. package/dist/pipeline/event-dispatcher-delivery.js +7 -3
  517. package/dist/pipeline/event-dispatcher.d.ts +3 -2
  518. package/dist/pipeline/event-dispatcher.js +13 -12
  519. package/dist/pipeline/event-retention.js +59 -56
  520. package/dist/pipeline/handler-access-error.js +2 -1
  521. package/dist/pipeline/handler-context-auth.d.ts +5 -6
  522. package/dist/pipeline/handler-context-auth.js +7 -4
  523. package/dist/pipeline/handler-context-config.d.ts +2 -5
  524. package/dist/pipeline/handler-context-config.js +2 -2
  525. package/dist/pipeline/handler-context-db.d.ts +32 -7
  526. package/dist/pipeline/handler-context-db.js +26 -17
  527. package/dist/pipeline/handler-context-dispatch.d.ts +14 -6
  528. package/dist/pipeline/handler-context-dispatch.js +18 -5
  529. package/dist/pipeline/handler-context-events.d.ts +22 -38
  530. package/dist/pipeline/handler-context-events.js +42 -35
  531. package/dist/pipeline/handler-context-member-resolution.d.ts +2 -0
  532. package/dist/pipeline/handler-context-member-resolution.js +110 -0
  533. package/dist/pipeline/handler-context-notify.d.ts +3 -2
  534. package/dist/pipeline/handler-context-notify.js +1 -1
  535. package/dist/pipeline/handler-context-observability.d.ts +2 -4
  536. package/dist/pipeline/handler-context-observability.js +7 -5
  537. package/dist/pipeline/handler-context-phase-denials.d.ts +11 -0
  538. package/dist/pipeline/handler-context-phase-denials.js +98 -0
  539. package/dist/pipeline/handler-context-scope.d.ts +7 -10
  540. package/dist/pipeline/handler-context-scope.js +18 -20
  541. package/dist/pipeline/index.d.ts +9 -21
  542. package/dist/pipeline/index.js +5 -7
  543. package/dist/pipeline/irreversible-operation-gate.d.ts +1 -1
  544. package/dist/pipeline/irreversible-operation-gate.js +2 -2
  545. package/dist/pipeline/lifecycle-pipeline.d.ts +8 -7
  546. package/dist/pipeline/lifecycle-pipeline.js +9 -15
  547. package/dist/pipeline/member-read-only-transaction.js +11 -3
  548. package/dist/pipeline/member-reader.d.ts +1 -1
  549. package/dist/pipeline/member-reader.js +2 -2
  550. package/dist/pipeline/msp-rebuild.js +5 -3
  551. package/dist/pipeline/multi-stream-apply-context.js +3 -2
  552. package/dist/pipeline/notify-scope.d.ts +2 -1
  553. package/dist/pipeline/pre-handler-gates.d.ts +2 -1
  554. package/dist/pipeline/pre-transaction-reservations.d.ts +3 -3
  555. package/dist/pipeline/pre-transaction-reservations.js +9 -7
  556. package/dist/pipeline/projection-rebuild.js +12 -5
  557. package/dist/pipeline/projection-state.d.ts +0 -6
  558. package/dist/pipeline/projection-state.js +0 -5
  559. package/dist/pipeline/projections-runner.d.ts +2 -1
  560. package/dist/pipeline/projections-runner.js +10 -6
  561. package/dist/pipeline/system-hooks.d.ts +6 -2
  562. package/dist/pipeline/system-hooks.js +61 -10
  563. package/dist/pipeline/system-identity-switch.d.ts +4 -2
  564. package/dist/pipeline/system-identity-switch.js +51 -36
  565. package/dist/pipeline/typed-append-event.d.ts +2 -0
  566. package/dist/pipeline/typed-append-event.js +4 -0
  567. package/dist/pipeline/write-origin.js +2 -2
  568. package/dist/pipeline/write-result-masking.d.ts +1 -1
  569. package/dist/pipeline/write-result-masking.js +13 -10
  570. package/dist/random/index.d.ts +1 -2
  571. package/dist/random/index.js +1 -2
  572. package/dist/rate-limit/bucket.d.ts +2 -1
  573. package/dist/rate-limit/middleware.js +2 -1
  574. package/dist/redis/index.d.ts +3 -4
  575. package/dist/redis/index.js +2 -2
  576. package/dist/schema-cli/apply-command.js +5 -2
  577. package/dist/schema-cli/baseline-command.js +7 -2
  578. package/dist/schema-cli/generate-command.js +7 -9
  579. package/dist/schema-cli/shared.d.ts +4 -0
  580. package/dist/schema-cli/shared.js +21 -2
  581. package/dist/schema-cli/status-command.js +8 -2
  582. package/dist/schema-cli/validate-command.js +52 -4
  583. package/dist/schema-cli.d.ts +0 -1
  584. package/dist/search/configure-tenant-index.d.ts +1 -3
  585. package/dist/search/configure-tenant-index.js +0 -4
  586. package/dist/search/index.d.ts +1 -4
  587. package/dist/search/index.js +0 -2
  588. package/dist/search/meilisearch-adapter-internals.d.ts +8 -0
  589. package/dist/search/meilisearch-adapter-internals.js +9 -0
  590. package/dist/search/meilisearch-adapter.d.ts +1 -8
  591. package/dist/search/meilisearch-adapter.js +6 -7
  592. package/dist/search/meilisearch-peer.d.ts +2 -0
  593. package/dist/search/meilisearch-peer.js +5 -0
  594. package/dist/search/reindex-entity.js +107 -91
  595. package/dist/secrets/index.d.ts +3 -4
  596. package/dist/secrets/index.js +2 -3
  597. package/dist/seeding/index.d.ts +2 -2
  598. package/dist/seeding/index.js +1 -2
  599. package/dist/time/index.d.ts +2 -2
  600. package/dist/time/index.js +1 -1
  601. package/dist/time/tz-context.d.ts +0 -5
  602. package/dist/time/tz-context.js +0 -9
  603. package/dist/ui-types/index.d.ts +8 -11
  604. package/dist/ui-types/index.js +3 -3
  605. package/dist/upgrade-changelog.d.ts +3 -0
  606. package/dist/upgrade-changelog.js +18 -0
  607. package/dist/upgrade-cli-internals.d.ts +8 -0
  608. package/dist/upgrade-cli-internals.js +63 -0
  609. package/dist/upgrade-cli.d.ts +1 -18
  610. package/dist/upgrade-cli.js +29 -137
  611. package/dist/upgrade-marker-parse.d.ts +32 -0
  612. package/dist/upgrade-marker-parse.js +73 -0
  613. package/dist/utils/import-optional-peer.d.ts +6 -0
  614. package/dist/utils/import-optional-peer.js +19 -0
  615. package/dist/utils/index.d.ts +1 -4
  616. package/dist/utils/index.js +1 -4
  617. package/package.json +27 -20
  618. package/src/changes.json +451 -0
  619. package/dist/crypto/request-kms-cache.d.ts +0 -8
  620. package/dist/crypto/request-kms-cache.js +0 -21
  621. package/dist/engine/codemod/index.d.ts +0 -2
  622. package/dist/engine/codemod/index.js +0 -1
  623. package/dist/engine/codemod/pipeline-codemod.d.ts +0 -50
  624. package/dist/engine/codemod/pipeline-codemod.js +0 -536
  625. package/dist/engine/feature-ast/entity-field-types.d.ts +0 -13
  626. package/dist/engine/feature-ast/entity-field-types.js +0 -35
  627. package/dist/engine/feature-ast/extractors/ai-steps.d.ts +0 -6
  628. package/dist/engine/feature-ast/extractors/ai-steps.js +0 -254
  629. package/dist/engine/feature-ast/extractors/events.d.ts +0 -5
  630. package/dist/engine/feature-ast/extractors/events.js +0 -275
  631. package/dist/engine/feature-ast/extractors/handlers.d.ts +0 -24
  632. package/dist/engine/feature-ast/extractors/handlers.js +0 -358
  633. package/dist/engine/feature-ast/extractors/hooks.d.ts +0 -24
  634. package/dist/engine/feature-ast/extractors/hooks.js +0 -248
  635. package/dist/engine/feature-ast/extractors/index.d.ts +0 -14
  636. package/dist/engine/feature-ast/extractors/index.js +0 -13
  637. package/dist/engine/feature-ast/extractors/jobs-routes.d.ts +0 -7
  638. package/dist/engine/feature-ast/extractors/jobs-routes.js +0 -145
  639. package/dist/engine/feature-ast/extractors/projections-screens.d.ts +0 -10
  640. package/dist/engine/feature-ast/extractors/projections-screens.js +0 -195
  641. package/dist/engine/feature-ast/extractors/resolve-import.d.ts +0 -21
  642. package/dist/engine/feature-ast/extractors/resolve-import.js +0 -180
  643. package/dist/engine/feature-ast/extractors/round1.d.ts +0 -10
  644. package/dist/engine/feature-ast/extractors/round1.js +0 -81
  645. package/dist/engine/feature-ast/extractors/round2.d.ts +0 -7
  646. package/dist/engine/feature-ast/extractors/round2.js +0 -191
  647. package/dist/engine/feature-ast/extractors/round3.d.ts +0 -23
  648. package/dist/engine/feature-ast/extractors/round3.js +0 -292
  649. package/dist/engine/feature-ast/extractors/round5.d.ts +0 -9
  650. package/dist/engine/feature-ast/extractors/round5.js +0 -68
  651. package/dist/engine/feature-ast/extractors/round6.d.ts +0 -4
  652. package/dist/engine/feature-ast/extractors/round6.js +0 -17
  653. package/dist/engine/feature-ast/extractors/shared.d.ts +0 -94
  654. package/dist/engine/feature-ast/extractors/shared.js +0 -343
  655. package/dist/engine/feature-ast/index.d.ts +0 -16
  656. package/dist/engine/feature-ast/index.js +0 -10
  657. package/dist/engine/feature-ast/parse.d.ts +0 -31
  658. package/dist/engine/feature-ast/parse.js +0 -483
  659. package/dist/engine/feature-ast/patch.d.ts +0 -210
  660. package/dist/engine/feature-ast/patch.js +0 -610
  661. package/dist/engine/feature-ast/patcher.d.ts +0 -217
  662. package/dist/engine/feature-ast/patcher.js +0 -281
  663. package/dist/engine/feature-ast/pattern-change-schema.d.ts +0 -1476
  664. package/dist/engine/feature-ast/pattern-change-schema.js +0 -1226
  665. package/dist/engine/feature-ast/pattern-id-matchers.d.ts +0 -7
  666. package/dist/engine/feature-ast/pattern-id-matchers.js +0 -210
  667. package/dist/engine/feature-ast/patterns.d.ts +0 -318
  668. package/dist/engine/feature-ast/patterns.js +0 -106
  669. package/dist/engine/feature-ast/render.d.ts +0 -47
  670. package/dist/engine/feature-ast/render.js +0 -662
  671. package/dist/engine/feature-ast/source-location.d.ts +0 -17
  672. package/dist/engine/feature-ast/source-location.js +0 -27
  673. package/dist/engine/pattern-library/index.d.ts +0 -2
  674. package/dist/engine/pattern-library/index.js +0 -3
  675. package/dist/engine/pattern-library/library.d.ts +0 -14
  676. package/dist/engine/pattern-library/library.js +0 -93
  677. package/dist/engine/pattern-library/mixed-schemas.d.ts +0 -16
  678. package/dist/engine/pattern-library/mixed-schemas.js +0 -559
  679. package/dist/engine/pattern-library/opaque-schemas.d.ts +0 -7
  680. package/dist/engine/pattern-library/opaque-schemas.js +0 -115
  681. package/dist/engine/pattern-library/shared-fields.d.ts +0 -122
  682. package/dist/engine/pattern-library/shared-fields.js +0 -88
  683. package/dist/engine/pattern-library/static-schemas.d.ts +0 -20
  684. package/dist/engine/pattern-library/static-schemas.js +0 -478
  685. package/dist/engine/pattern-library/types.d.ts +0 -158
  686. package/dist/engine/pattern-library/types.js +0 -36
  687. package/dist/engine/provider-plugin-context.d.ts +0 -3
  688. package/dist/engine/provider-plugin-context.js +0 -28
  689. package/dist/engine/resolve-config-or-param.d.ts +0 -18
  690. package/dist/engine/resolve-config-or-param.js +0 -76
  691. package/src/scripts/codemod/README.md +0 -187
  692. package/src/scripts/codemod/codemod-support.ts +0 -334
  693. package/src/scripts/codemod/collect-source-files.ts +0 -48
  694. package/src/scripts/codemod/crypto-shredding-testing-move.ts +0 -119
  695. package/src/scripts/codemod/db-factory.ts +0 -810
  696. package/src/scripts/codemod/feature-factory.ts +0 -429
  697. package/src/scripts/codemod/feature-layout.ts +0 -424
  698. package/src/scripts/codemod/import-extensions.ts +0 -118
  699. package/src/scripts/codemod/migrate-cross-tenant.ts +0 -328
  700. package/src/scripts/codemod/migrate-db-raw.ts +0 -401
  701. package/src/scripts/codemod/migrate-open-to-all.ts +0 -235
  702. package/src/scripts/codemod/object-form.ts +0 -746
  703. package/src/scripts/codemod/package-merge.ts +0 -299
  704. package/src/scripts/codemod/pii-personal-migration.ts +0 -816
  705. package/src/scripts/codemod/remove-engine-payload-casts.ts +0 -318
  706. package/src/scripts/codemod/s3-imports.ts +0 -236
  707. package/src/scripts/codemod/tenant-db-options.ts +0 -454
  708. package/src/scripts/codemod/testing-injection.ts +0 -215
  709. package/src/scripts/codemod/testing-move-targets.ts +0 -161
  710. package/src/scripts/codemod/testing-move.ts +0 -542
  711. package/src/scripts/codemod/unprocessable-error-details-reason.ts +0 -411
@@ -325,7 +325,7 @@ describe("workflow-engine", () => {
325
325
  });
326
326
 
327
327
  it("webhook-delivery completes with exactly one dispatch request", async () => {
328
- const ctx = { unsafeAppendEvent: mock().mockResolvedValue(undefined) };
328
+ const ctx = { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
329
329
 
330
330
  const result = await startAndRunWorkflow({
331
331
  runId: "wf-webhook-delivery-1",
@@ -339,7 +339,7 @@ describe("workflow-engine", () => {
339
339
  });
340
340
 
341
341
  expect(result.outcome).toBe("completed");
342
- const dispatchRequests = ctx.unsafeAppendEvent.mock.calls
342
+ const dispatchRequests = ctx.events.unsafeAppend.mock.calls
343
343
  .map(([event]) => event as { type: string; payload: Record<string, unknown> })
344
344
  .filter((event) => event.type === STEP_DISPATCH_REQUESTED_TYPE);
345
345
  expect(dispatchRequests).toHaveLength(1);
@@ -367,7 +367,7 @@ describe("workflow-engine", () => {
367
367
 
368
368
  describe("workflow-runner", () => {
369
369
  function makeAppendOnlyCtx() {
370
- return { unsafeAppendEvent: mock().mockResolvedValue(undefined) };
370
+ return { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
371
371
  }
372
372
 
373
373
  it("startAndRunWorkflow writes run.started with Q7 snapshot fingerprint, then runs the pipeline to completion when no suspension", async () => {
@@ -386,15 +386,15 @@ describe("workflow-runner", () => {
386
386
  });
387
387
 
388
388
  expect(result.outcome).toBe("completed");
389
- expect(ctx.unsafeAppendEvent).toHaveBeenCalledTimes(2);
390
- const started = ctx.unsafeAppendEvent.mock.calls[0]![0] as {
389
+ expect(ctx.events.unsafeAppend).toHaveBeenCalledTimes(2);
390
+ const started = ctx.events.unsafeAppend.mock.calls[0]![0] as {
391
391
  type: string;
392
392
  payload: Record<string, unknown>;
393
393
  };
394
394
  expect(started.type).toBe("kumiko:system:workflow.run-started");
395
395
  expect(started.payload["definitionFingerprint"]).toBe(computeDefinitionFingerprint(workflow));
396
396
  expect(started.payload["triggerEventType"]).toBe("demo.fired");
397
- const completed = ctx.unsafeAppendEvent.mock.calls[1]![0] as { type: string };
397
+ const completed = ctx.events.unsafeAppend.mock.calls[1]![0] as { type: string };
398
398
  expect(completed.type).toBe("kumiko:system:workflow.run-completed");
399
399
  });
400
400
 
@@ -418,8 +418,8 @@ describe("workflow-runner", () => {
418
418
 
419
419
  expect(result.outcome).toBe("suspended");
420
420
  // run.started + workflow.step.waiting — no run-completed yet
421
- expect(ctx.unsafeAppendEvent).toHaveBeenCalledTimes(2);
422
- const waiting = ctx.unsafeAppendEvent.mock.calls[1]![0] as {
421
+ expect(ctx.events.unsafeAppend).toHaveBeenCalledTimes(2);
422
+ const waiting = ctx.events.unsafeAppend.mock.calls[1]![0] as {
423
423
  type: string;
424
424
  payload: Record<string, unknown>;
425
425
  };
@@ -444,14 +444,16 @@ describe("workflow-runner", () => {
444
444
  handlerCtx: ctx as never,
445
445
  });
446
446
 
447
- const started = ctx.unsafeAppendEvent.mock.calls[0]![0] as { payload: Record<string, unknown> };
447
+ const started = ctx.events.unsafeAppend.mock.calls[0]![0] as {
448
+ payload: Record<string, unknown>;
449
+ };
448
450
  expect(started.payload["idempotencyKey"]).toBe("id:abc");
449
451
  });
450
452
  });
451
453
 
452
454
  describe("userOnboardingWorkflow (end-to-end, in-memory)", () => {
453
455
  it("suspends on the first wait, then resume-loop runs it through to completion", async () => {
454
- const ctx = { unsafeAppendEvent: mock().mockResolvedValue(undefined) };
456
+ const ctx = { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
455
457
  const trigger = {
456
458
  aggregateId: "agg_user_42",
457
459
  type: "user.signed-up",
@@ -469,16 +471,16 @@ describe("userOnboardingWorkflow (end-to-end, in-memory)", () => {
469
471
 
470
472
  expect(result.outcome).toBe("suspended");
471
473
  // Calls: run.started, mail.send dispatch-requested, workflow.step.waiting
472
- expect(ctx.unsafeAppendEvent).toHaveBeenCalledTimes(3);
473
- const startedCall = ctx.unsafeAppendEvent.mock.calls[0]![0] as {
474
+ expect(ctx.events.unsafeAppend).toHaveBeenCalledTimes(3);
475
+ const startedCall = ctx.events.unsafeAppend.mock.calls[0]![0] as {
474
476
  type: string;
475
477
  payload: Record<string, unknown>;
476
478
  };
477
- const mailCall = ctx.unsafeAppendEvent.mock.calls[1]![0] as {
479
+ const mailCall = ctx.events.unsafeAppend.mock.calls[1]![0] as {
478
480
  type: string;
479
481
  payload: Record<string, unknown>;
480
482
  };
481
- const waitingCall = ctx.unsafeAppendEvent.mock.calls[2]![0] as {
483
+ const waitingCall = ctx.events.unsafeAppend.mock.calls[2]![0] as {
482
484
  type: string;
483
485
  payload: Record<string, unknown>;
484
486
  };
@@ -514,7 +516,7 @@ describe("userOnboardingWorkflow (end-to-end, in-memory)", () => {
514
516
  definitionFingerprint: waitingCall.payload["definitionFingerprint"] as string,
515
517
  };
516
518
 
517
- const resumeCtx = { unsafeAppendEvent: mock().mockResolvedValue(undefined) };
519
+ const resumeCtx = { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
518
520
  const count = await runResumeLoop(
519
521
  createInMemorySuspendedRunFetcher([suspendedRun]),
520
522
  resumeCtx as never,
@@ -525,7 +527,7 @@ describe("userOnboardingWorkflow (end-to-end, in-memory)", () => {
525
527
  // because userId starts with "active-"), second WAITING for P7D.
526
528
  // The run is suspended again before the webhook, so no RUN_COMPLETED
527
529
  // yet — this is one resume-cycle, not the whole workflow.
528
- const resumeTypes = resumeCtx.unsafeAppendEvent.mock.calls.map(
530
+ const resumeTypes = resumeCtx.events.unsafeAppend.mock.calls.map(
529
531
  (c) => (c[0] as { type: string }).type,
530
532
  );
531
533
  expect(resumeTypes).toEqual([
@@ -533,14 +535,14 @@ describe("userOnboardingWorkflow (end-to-end, in-memory)", () => {
533
535
  "kumiko:system:step.dispatch-requested",
534
536
  "kumiko:system:workflow.step.waiting",
535
537
  ]);
536
- const tipsMail = resumeCtx.unsafeAppendEvent.mock.calls[1]![0] as {
538
+ const tipsMail = resumeCtx.events.unsafeAppend.mock.calls[1]![0] as {
537
539
  payload: { subject: string };
538
540
  };
539
541
  expect(tipsMail.payload.subject).toBe("Engagement tips");
540
542
  });
541
543
 
542
544
  it("not-engaged path picks the reminder branch", async () => {
543
- const ctx = { unsafeAppendEvent: mock().mockResolvedValue(undefined) };
545
+ const ctx = { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
544
546
  const trigger = {
545
547
  aggregateId: "agg_user_cold",
546
548
  type: "user.signed-up",
@@ -553,7 +555,9 @@ describe("userOnboardingWorkflow (end-to-end, in-memory)", () => {
553
555
  triggerEventRef: { eventId: "2", aggregateId: trigger.aggregateId, version: 1 },
554
556
  handlerCtx: ctx as never,
555
557
  });
556
- const waiting = ctx.unsafeAppendEvent.mock.calls[2]![0] as { payload: Record<string, unknown> };
558
+ const waiting = ctx.events.unsafeAppend.mock.calls[2]![0] as {
559
+ payload: Record<string, unknown>;
560
+ };
557
561
  const suspendedRun: SuspendableRun = {
558
562
  runId: "wf-onboarding-cold-1",
559
563
  workflowName: "user-onboarding",
@@ -564,10 +568,10 @@ describe("userOnboardingWorkflow (end-to-end, in-memory)", () => {
564
568
  triggerEvent: trigger as never,
565
569
  definitionFingerprint: waiting.payload["definitionFingerprint"] as string,
566
570
  };
567
- const resumeCtx = { unsafeAppendEvent: mock().mockResolvedValue(undefined) };
571
+ const resumeCtx = { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
568
572
  await runResumeLoop(createInMemorySuspendedRunFetcher([suspendedRun]), resumeCtx as never);
569
573
 
570
- const reminderMail = resumeCtx.unsafeAppendEvent.mock.calls[1]![0] as {
574
+ const reminderMail = resumeCtx.events.unsafeAppend.mock.calls[1]![0] as {
571
575
  payload: { subject: string };
572
576
  };
573
577
  expect(reminderMail.payload.subject).toBe("Getting started");
@@ -696,7 +700,7 @@ describe("cron-scheduler", () => {
696
700
  steps: stepsPipeline(({ r }) => [r.step.return({ isSuccess: true, data: undefined })]),
697
701
  });
698
702
 
699
- const handlerCtx = { unsafeAppendEvent: mock() };
703
+ const handlerCtx = { events: { unsafeAppend: mock() } };
700
704
  const lastRuns = new Map<string, Temporal.Instant>();
701
705
  const now = Temporal.Instant.from("2025-06-01T08:00:00Z");
702
706
 
@@ -708,7 +712,7 @@ describe("cron-scheduler", () => {
708
712
  );
709
713
 
710
714
  expect(count).toBe(0);
711
- expect(handlerCtx.unsafeAppendEvent).not.toHaveBeenCalled();
715
+ expect(handlerCtx.events.unsafeAppend).not.toHaveBeenCalled();
712
716
  });
713
717
 
714
718
  it("runDueCronWorkflows runs due workflows through the full start path", async () => {
@@ -718,7 +722,7 @@ describe("cron-scheduler", () => {
718
722
  steps: stepsPipeline(({ r }) => [r.step.return({ isSuccess: true, data: undefined })]),
719
723
  });
720
724
 
721
- const handlerCtx = { unsafeAppendEvent: mock().mockResolvedValue(undefined) };
725
+ const handlerCtx = { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
722
726
  const lastRuns = new Map<string, Temporal.Instant>();
723
727
  const lastRun = Temporal.Instant.from("2025-05-31T08:00:00Z");
724
728
  lastRuns.set("test-daily", lastRun);
@@ -733,10 +737,10 @@ describe("cron-scheduler", () => {
733
737
 
734
738
  expect(count).toBe(1);
735
739
  // run.started + run-completed (no suspension, pipeline returns immediately).
736
- expect(handlerCtx.unsafeAppendEvent).toHaveBeenCalledTimes(2);
737
- const started = handlerCtx.unsafeAppendEvent.mock.calls[0]![0] as Record<string, unknown>;
740
+ expect(handlerCtx.events.unsafeAppend).toHaveBeenCalledTimes(2);
741
+ const started = handlerCtx.events.unsafeAppend.mock.calls[0]![0] as Record<string, unknown>;
738
742
  expect(started["type"]).toBe("kumiko:system:workflow.run-started");
739
- const completed = handlerCtx.unsafeAppendEvent.mock.calls[1]![0] as Record<string, unknown>;
743
+ const completed = handlerCtx.events.unsafeAppend.mock.calls[1]![0] as Record<string, unknown>;
740
744
  expect(completed["type"]).toBe("kumiko:system:workflow.run-completed");
741
745
  });
742
746
  });
@@ -744,12 +748,12 @@ describe("cron-scheduler", () => {
744
748
  describe("resume-loop", () => {
745
749
  it("returns 0 when no suspended runs exist", async () => {
746
750
  const fetchRuns = createInMemorySuspendedRunFetcher([]);
747
- const handlerCtx = { unsafeAppendEvent: mock() };
751
+ const handlerCtx = { events: { unsafeAppend: mock() } };
748
752
 
749
753
  const count = await runResumeLoop(fetchRuns, handlerCtx as never);
750
754
 
751
755
  expect(count).toBe(0);
752
- expect(handlerCtx.unsafeAppendEvent).not.toHaveBeenCalled();
756
+ expect(handlerCtx.events.unsafeAppend).not.toHaveBeenCalled();
753
757
  });
754
758
 
755
759
  it("resumes a suspended run", async () => {
@@ -766,19 +770,19 @@ describe("resume-loop", () => {
766
770
  };
767
771
 
768
772
  const fetchRuns = createInMemorySuspendedRunFetcher([suspendedRun]);
769
- const handlerCtx = { unsafeAppendEvent: mock().mockResolvedValue(undefined) };
773
+ const handlerCtx = { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
770
774
 
771
775
  const count = await runResumeLoop(fetchRuns, handlerCtx as never);
772
776
 
773
777
  expect(count).toBe(1);
774
- expect(handlerCtx.unsafeAppendEvent).toHaveBeenCalledTimes(2);
775
- expect(handlerCtx.unsafeAppendEvent).toHaveBeenNthCalledWith(1, {
778
+ expect(handlerCtx.events.unsafeAppend).toHaveBeenCalledTimes(2);
779
+ expect(handlerCtx.events.unsafeAppend).toHaveBeenNthCalledWith(1, {
776
780
  aggregateId: "wf-test-run_123",
777
781
  aggregateType: "workflow-run",
778
782
  type: "kumiko:system:workflow.step.resumed",
779
783
  payload: { stepIndex: 0, retryAttempt: undefined },
780
784
  });
781
- expect(handlerCtx.unsafeAppendEvent).toHaveBeenNthCalledWith(2, {
785
+ expect(handlerCtx.events.unsafeAppend).toHaveBeenNthCalledWith(2, {
782
786
  aggregateId: "wf-test-run_123",
783
787
  aggregateType: "workflow-run",
784
788
  type: "kumiko:system:workflow.run-completed",
@@ -800,13 +804,13 @@ describe("resume-loop", () => {
800
804
  };
801
805
 
802
806
  const fetchRuns = createInMemorySuspendedRunFetcher([suspendedRun]);
803
- const handlerCtx = { unsafeAppendEvent: mock().mockResolvedValue(undefined) };
807
+ const handlerCtx = { events: { unsafeAppend: mock().mockResolvedValue(undefined) } };
804
808
 
805
809
  const count = await runResumeLoop(fetchRuns, handlerCtx as never);
806
810
 
807
811
  expect(count).toBe(0);
808
- expect(handlerCtx.unsafeAppendEvent).toHaveBeenCalledTimes(1);
809
- const failed = handlerCtx.unsafeAppendEvent.mock.calls[0]![0] as {
812
+ expect(handlerCtx.events.unsafeAppend).toHaveBeenCalledTimes(1);
813
+ const failed = handlerCtx.events.unsafeAppend.mock.calls[0]![0] as {
810
814
  type: string;
811
815
  payload: Record<string, unknown>;
812
816
  };
@@ -830,16 +834,18 @@ describe("resume-loop", () => {
830
834
 
831
835
  const fetchRuns = createInMemorySuspendedRunFetcher([suspendedRun]);
832
836
  const handlerCtx = {
833
- unsafeAppendEvent: mock()
834
- .mockRejectedValueOnce(new VersionConflictError("wf-conflict-run", 1))
835
- .mockResolvedValue(undefined),
837
+ events: {
838
+ unsafeAppend: mock()
839
+ .mockRejectedValueOnce(new VersionConflictError("wf-conflict-run", 1))
840
+ .mockResolvedValue(undefined),
841
+ },
836
842
  };
837
843
 
838
844
  const count = await runResumeLoop(fetchRuns, handlerCtx as never);
839
845
 
840
846
  expect(count).toBe(0);
841
- expect(handlerCtx.unsafeAppendEvent).toHaveBeenCalledTimes(1);
842
- expect((handlerCtx.unsafeAppendEvent.mock.calls[0]![0] as { type: string }).type).toBe(
847
+ expect(handlerCtx.events.unsafeAppend).toHaveBeenCalledTimes(1);
848
+ expect((handlerCtx.events.unsafeAppend.mock.calls[0]![0] as { type: string }).type).toBe(
843
849
  "kumiko:system:workflow.step.resumed",
844
850
  );
845
851
  });
@@ -1509,7 +1515,7 @@ export async function runResumeLoop(
1509
1515
  if (run.definitionFingerprint !== undefined) {
1510
1516
  const currentFingerprint = computeDefinitionFingerprint(run.workflow);
1511
1517
  if (currentFingerprint !== run.definitionFingerprint) {
1512
- await handlerCtx.unsafeAppendEvent({
1518
+ await handlerCtx.events.unsafeAppend({
1513
1519
  aggregateId: run.runId,
1514
1520
  aggregateType: WORKFLOW_AGGREGATE_TYPE,
1515
1521
  type: WORKFLOW_RUN_FAILED_TYPE,
@@ -1537,7 +1543,7 @@ export async function runResumeLoop(
1537
1543
  // no FAILED-event. Stale WAITING-rows in the fetcher result also
1538
1544
  // hit this branch on the second poll-tick.
1539
1545
  try {
1540
- await handlerCtx.unsafeAppendEvent({
1546
+ await handlerCtx.events.unsafeAppend({
1541
1547
  aggregateId: run.runId,
1542
1548
  aggregateType: WORKFLOW_AGGREGATE_TYPE,
1543
1549
  type: WORKFLOW_RESUMED_TYPE,
@@ -1589,7 +1595,7 @@ export async function runResumeLoop(
1589
1595
  // returned. A second suspension (e.g. `wait` further down the
1590
1596
  // pipeline) leaves the run pending for the next resume-loop tick.
1591
1597
  if (outcome.kind !== "suspended") {
1592
- await handlerCtx.unsafeAppendEvent({
1598
+ await handlerCtx.events.unsafeAppend({
1593
1599
  aggregateId: run.runId,
1594
1600
  aggregateType: WORKFLOW_AGGREGATE_TYPE,
1595
1601
  type: WORKFLOW_RUN_COMPLETED_TYPE,
@@ -1606,7 +1612,7 @@ export async function runResumeLoop(
1606
1612
  stepIndex: run.stepIndex,
1607
1613
  error: String(error),
1608
1614
  });
1609
- await handlerCtx.unsafeAppendEvent({
1615
+ await handlerCtx.events.unsafeAppend({
1610
1616
  aggregateId: run.runId,
1611
1617
  aggregateType: WORKFLOW_AGGREGATE_TYPE,
1612
1618
  type: WORKFLOW_RUN_FAILED_TYPE,
@@ -1697,7 +1703,7 @@ export async function startAndRunWorkflow(args: {
1697
1703
  ...(args.idempotencyKey && { idempotencyKey: args.idempotencyKey }),
1698
1704
  };
1699
1705
 
1700
- await args.handlerCtx.unsafeAppendEvent({
1706
+ await args.handlerCtx.events.unsafeAppend({
1701
1707
  aggregateId: args.runId,
1702
1708
  aggregateType: WORKFLOW_AGGREGATE_TYPE,
1703
1709
  type: WORKFLOW_RUN_STARTED_TYPE,
@@ -1724,7 +1730,7 @@ export async function startAndRunWorkflow(args: {
1724
1730
  return { outcome: "suspended" };
1725
1731
  }
1726
1732
 
1727
- await args.handlerCtx.unsafeAppendEvent({
1733
+ await args.handlerCtx.events.unsafeAppend({
1728
1734
  aggregateId: args.runId,
1729
1735
  aggregateType: WORKFLOW_AGGREGATE_TYPE,
1730
1736
  type: WORKFLOW_RUN_COMPLETED_TYPE,
@@ -19,7 +19,7 @@
19
19
  | `chat-channels` | Chat channels. Delivery notifications to Slack, minus the browser tab. | `examples/chat-channels.md` |
20
20
  | `compliance-profiles-demo` | Two-tenant demo: EU + Swiss compliance profiles deliver different authority contacts, languages, and grace periods through the same App-code. | `examples/compliance-profiles-demo.md` |
21
21
  | `compose-stacks` | compose*Stack helpers for auth, security, GDPR and SaaS billing, and the runProdApp check that names a stack whose boot option is missing. | `examples/compose-stacks.md` |
22
- | `cross-feature-events` | Feature appends a typed domain event via ctx.appendEvent; a r.multiStreamProjection reacts asynchronously. | `examples/cross-feature-events.md` |
22
+ | `cross-feature-events` | Feature appends a typed domain event via ctx.events.append; a r.multiStreamProjection reacts asynchronously. | `examples/cross-feature-events.md` |
23
23
  | `crypto-shredding-hr` | Crypto-shredding: PII fields encrypted per subject key; forgetting the subject erases the key and every field it protected. | `examples/crypto-shredding-hr.md` |
24
24
  | `currencies-global` | Shared money fields across tenants. Commas still matter. | `examples/currencies-global.md` |
25
25
  | `currencies-per-tenant` | Tenant-scoped money fields. Commas matter. | `examples/currencies-per-tenant.md` |
@@ -34,20 +34,21 @@
34
34
  | `encrypted-tenant-config` | Per-tenant secrets via config-key encryption — Stripe-API-key pattern. | `examples/encrypted-tenant-config.md` |
35
35
  | `env-composition` | Typed app env from the env blocks bundled features register, plus app-level blocks in extend. | `examples/env-composition.md` |
36
36
  | `error-contract` | Typed errors on the wire. With snake_case reasons, because we care. | `examples/error-contract.md` |
37
- | `event-sourcing` | Production-pattern ES sample: r.defineEvent (versioned + migrations) + ctx.appendEvent + r.projection + r.multiStreamProjection + ctx.loadAggregate (asOf) + ctx.archiveStream + ctx.queryProjection. | `examples/event-sourcing.md` |
37
+ | `event-sourcing` | Production-pattern ES sample: r.defineEvent (versioned + migrations) + ctx.events.append + r.projection + r.multiStreamProjection + ctx.events.load (asOf) + ctx.events.archive + ctx.dispatch.queryProjection. | `examples/event-sourcing.md` |
38
38
  | `feature-toggles` | Runtime feature-toggle flip — two toggleable features, one registers a cross-feature hook on the other; disabling either has the documented effect without reboot. | `examples/feature-toggles.md` |
39
39
  | `field-access` | Field-level access control. When entity-level roles aren't granular enough. | `examples/field-access.md` |
40
- | `files-post-processing` | The three ways to generate an image variant: declarative field variants, imperative ctx.derivatives.variant() with region-blur, and the public route behind a default-deny predicate. | `examples/files-post-processing.md` |
40
+ | `files-post-processing` | The three ways to generate an image variant: declarative field variants, imperative ctx.services.derivatives.variant() with region-blur, and the public route behind a default-deny predicate. | `examples/files-post-processing.md` |
41
41
  | `golden-path` | The smallest complete feature: entity, write handler, event, projection, screen and an integration test. | `examples/golden-path.md` |
42
42
  | `host-routing` | createHostRoutingFeature + createHostDispatch — tenant per subdomain, per-host HTML and CSP, locale redirect, shared by runProdApp and the dev server. | `examples/host-routing.md` |
43
43
  | `i18n` | Feature-scoped translations. 'Hallo' and 'Hello' in the same app. | `examples/i18n.md` |
44
44
  | `idempotency` | Same request, same result. Dedupes on request ID. | `examples/idempotency.md` |
45
45
  | `inbound-mail-triage` | Inbound-mail consumer pattern: inbound-mail-foundation + in-memory provider, a worker-lane triage job attached to the ingest handler, verified end-to-end through createAllInOneEntrypoint. | `examples/inbound-mail-triage.md` |
46
- | `lane-routing` | runIn lane-routing: r.job pinned to api/worker deploy-lanes, event-chain via ctx.appendEvent, verified end-to-end through createAllInOneEntrypoint. | `examples/lane-routing.md` |
46
+ | `lane-routing` | runIn lane-routing: r.job pinned to api/worker deploy-lanes, event-chain via ctx.events.append, verified end-to-end through createAllInOneEntrypoint. | `examples/lane-routing.md` |
47
47
  | `ledger-banking` | Bank accounts + transfers on the ledger primitive — balances are pure queries, never stored. | `examples/ledger-banking.md` |
48
48
  | `ledger-invoicing` | Accrual invoicing on the ledger primitive — revenue at invoice time, VAT as a liability, receivable cleared on payment. | `examples/ledger-invoicing.md` |
49
49
  | `legal-pages` | Auto-rendered Impressum + Datenschutzerklärung pages — template-resolver + legal-pages bundled features wired up with anonymousAccess for DACH-compliance. | `examples/legal-pages.md` |
50
50
  | `lifecycle-hooks` | preSave, postSave, and the rest. Your logic, our plumbing. | `examples/lifecycle-hooks.md` |
51
+ | `list-table-options` | Opt-in table behaviour of a list: remembered search/sort/filters, one reset button, column picker with hidden columns, row density, server-side groups with sums, a totals row and a number range facet. | `examples/list-table-options.md` |
51
52
  | `managed-config` | Managed config: one declaration provisions storage + masking + settings-hub, across backings (secrets vs config) and scopes (system vs tenant). | `examples/managed-config.md` |
52
53
  | `managed-pages` | Tenant-editable, server-rendered public pages with per-tenant branding + tier-gated sanitized custom CSS — managed-pages wired up with config + anonymousAccess. | `examples/managed-pages.md` |
53
54
  | `notes-history-basic` | Append-only note history — who wrote what, when — attached to any entity without changing it. | `examples/notes-history-basic.md` |
@@ -257,7 +257,7 @@ Category: operations
257
257
 
258
258
  ## file-derivatives
259
259
 
260
- Declares the `derivativeRenderer` extension point. `ctx.derivatives.variant(fileRefId, spec, name)` derives a variant of a tracked FileRef the first time it's requested and reuses the stored result afterwards (derive-on-first-use, keyed by a hash of the spec). Mount at least one `derivatives-*` renderer feature alongside this one — without a registered renderer for the FileRef's MIME type, every `variant(...)` call throws. Also declares the `derivativePublicPredicate` extension point (`r.useExtension(EXT_DERIVATIVE_PUBLIC_PREDICATE, '<entityType>', { isPublic })`) and, when `createFileDerivativesFeature({resolveApexTenant})` is passed a host-resolver, mounts an anonymous `GET {basePath}/:fileRefId/:variant` route that serves any variant name the FileRef's field declared in its `variants` for a FileRef whose entityType has a registered predicate returning true — default-deny (404) otherwise, same as an unknown FileRef or an undeclared variant name. The route's only rate-limit (`per: "ip"`) depends on the server's `trustedProxyHops` matching the deployment's actual reverse-proxy count — at the default 0 it ignores `x-forwarded-for` entirely, so every caller shares one bucket until that's configured. `publicTenantResolution: "fileRef"` keeps resolveApexTenant as the host gate but reads the variant from the FileRef row's own tenant instead of the host's, so one shared platform host serves every tenant's public variants — each FileRef-tenant's own `isPublic` predicate still default-denies. Also declares the `derivativeOverlayResolver` extension point (`r.useExtension(EXT_DERIVATIVE_OVERLAY_RESOLVER, '<entityType>', { resolve })`), used to turn a variant's `overlays[].dataToken` into the actual QR payload for that FileRef's entityType before the variant is rendered — a variant declaring a `qr` overlay throws at request-time if no resolver is registered for the FileRef's entityType.
260
+ Declares the `derivativeRenderer` extension point. `ctx.services.derivatives.variant(fileRefId, spec, name)` derives a variant of a tracked FileRef the first time it's requested and reuses the stored result afterwards (derive-on-first-use, keyed by a hash of the spec). Mount at least one `derivatives-*` renderer feature alongside this one — without a registered renderer for the FileRef's MIME type, every `variant(...)` call throws. Also declares the `derivativePublicPredicate` extension point (`r.useExtension(EXT_DERIVATIVE_PUBLIC_PREDICATE, '<entityType>', { isPublic })`) and, when `createFileDerivativesFeature({resolveApexTenant})` is passed a host-resolver, mounts an anonymous `GET {basePath}/:fileRefId/:variant` route that serves any variant name the FileRef's field declared in its `variants` for a FileRef whose entityType has a registered predicate returning true — default-deny (404) otherwise, same as an unknown FileRef or an undeclared variant name. The route's only rate-limit (`per: "ip"`) depends on the server's `trustedProxyHops` matching the deployment's actual reverse-proxy count — at the default 0 it ignores `x-forwarded-for` entirely, so every caller shares one bucket until that's configured. `publicTenantResolution: "fileRef"` keeps resolveApexTenant as the host gate but reads the variant from the FileRef row's own tenant instead of the host's, so one shared platform host serves every tenant's public variants — each FileRef-tenant's own `isPublic` predicate still default-denies. Also declares the `derivativeOverlayResolver` extension point (`r.useExtension(EXT_DERIVATIVE_OVERLAY_RESOLVER, '<entityType>', { resolve })`), used to turn a variant's `overlays[].dataToken` into the actual QR payload for that FileRef's entityType before the variant is rendered — a variant declaring a `qr` overlay throws at request-time if no resolver is registered for the FileRef's entityType.
261
261
 
262
262
  Category: storage
263
263
 
package/agents/widgets.md CHANGED
@@ -143,6 +143,7 @@ Value exports of `@cosmicdrift/kumiko-renderer/web`.
143
143
  | `buildFileUploadFormData` | |
144
144
  | `buildNavRegistrySlice` | |
145
145
  | `buildNavRegistrySliceForApp` | |
146
+ | `clearRememberedListState` | Forgets all remembered list state and the identity marker. |
146
147
  | `cn` | Standard shadcn helper: `clsx` combines conditional classes, while `tailwind-merge` resolves conflicts (for example, `px-2 px-4` → `px-4`). |
147
148
  | `createBrowserDraftStorage` | Default DraftStorage when createKumikoApp boots without one. |
148
149
  | `createBrowserLocaleResolver` | Default resolver when createKumikoApp is booted without a `locale` option. |
@@ -8,6 +8,7 @@ export declare const Routes: {
8
8
  readonly command: "/command";
9
9
  readonly sse: "/sse";
10
10
  readonly stream: "/stream";
11
+ readonly exportXlsx: "/export/xlsx";
11
12
  readonly auth: "/auth";
12
13
  readonly authLogin: "/auth/login";
13
14
  readonly authMfaVerify: "/auth/mfa/verify";
@@ -10,6 +10,7 @@ export const Routes = {
10
10
  command: "/command",
11
11
  sse: "/sse",
12
12
  stream: "/stream",
13
+ exportXlsx: "/export/xlsx",
13
14
  auth: "/auth",
14
15
  authLogin: "/auth/login",
15
16
  authMfaVerify: "/auth/mfa/verify",
@@ -76,6 +77,7 @@ export const NON_PUBLIC_API_PATHS = new Set([
76
77
  `/api${Routes.command}`,
77
78
  `/api${Routes.sse}`,
78
79
  `/api${Routes.stream}`,
80
+ `/api${Routes.exportXlsx}`,
79
81
  // Namespace prefix used only for body-limit registration
80
82
  // (`/api/auth/*` in route-registrars.ts) — never dispatched as its own
81
83
  // route, so it carries no auth bypass either way. Classified non-public
@@ -5,7 +5,7 @@ import { createAnonymousUser } from "../engine/system-user.js";
5
5
  import { parseTenantId, SYSTEM_TENANT_ID } from "../engine/types/identifiers.js";
6
6
  import { isSessionRequiredApiPath, TENANT_HEADER_NAME } from "./api-constants.js";
7
7
  import { isForeignCookieOrigin } from "./origin-middleware.js";
8
- import { setRequestIdentity } from "./request-context.js";
8
+ import { setRequestIdentity } from "./request-context-internals.js";
9
9
  import { clearSessionCookies, getSessionCookies, hasDuplicateSessionCookie, } from "./session-cookies.js";
10
10
  const USER_KEY = "pipelineUser";
11
11
  const AUTH_TRANSPORT_KEY = "authTransport";
@@ -1,7 +1,8 @@
1
1
  import * as z from "zod";
2
2
  import { createAnonymousUser } from "../engine/system-user.js";
3
3
  import { SYSTEM_TENANT_ID } from "../engine/types/index.js";
4
- import { toKumikoError, toWriteErrorInfo } from "../errors/index.js";
4
+ import { toKumikoError } from "../errors/to-kumiko-error.js";
5
+ import { toWriteErrorInfo } from "../errors/write-error-info.js";
5
6
  import { Routes } from "./api-constants.js";
6
7
  import { getUser } from "./auth-middleware.js";
7
8
  import { pendingMfaStepResponse } from "./auth-routes-shared.js";
@@ -8,6 +8,7 @@ export declare const SignupRequestBody: z.ZodObject<{
8
8
  entityType: z.ZodString;
9
9
  token: z.ZodString;
10
10
  }, z.core.$strip>>;
11
+ returnTo: z.ZodCatch<z.ZodOptional<z.ZodString>>;
11
12
  }, z.core.$strip>;
12
13
  export declare function isUnknownHandlerError(e: unknown): boolean;
13
14
  export type PendingMfaStep = {
@@ -29,5 +30,6 @@ export declare function registerTokenRequestRoute(opts: {
29
30
  }): void;
30
31
  declare const RequestTokenBody: z.ZodObject<{
31
32
  email: z.ZodEmail;
33
+ returnTo: z.ZodCatch<z.ZodOptional<z.ZodString>>;
32
34
  }, z.core.$strip>;
33
35
  export {};
@@ -4,6 +4,9 @@ import { SYSTEM_TENANT_ID } from "../engine/types/index.js";
4
4
  import { NotFoundError } from "../errors/index.js";
5
5
  import { createFallbackLogger } from "../logging/utils.js";
6
6
  const log = createFallbackLogger("kumiko");
7
+ // Content is checked where the mail link is built (bundled-features knows the path rules); a bad
8
+ // value must never void the whole body, or the request would silently send no mail.
9
+ const returnToField = z.string().max(2048).optional().catch(undefined);
7
10
  // Cross-device try-first handover: an optional tenant-handover grant the signup-request
8
11
  // route forwards to the handler for server-side verification and binding —
9
12
  // the grant itself never appears anywhere else (URL, mail, log, response).
@@ -15,6 +18,7 @@ export const SignupRequestBody = z.object({
15
18
  token: z.string().min(1).max(4096),
16
19
  })
17
20
  .optional(),
21
+ returnTo: returnToField,
18
22
  });
19
23
  // Shape guard for "handler not registered" — the only legitimate reason to
20
24
  // fall back to a single-tenant reply on /auth/tenants or /auth/switch-tenant.
@@ -82,4 +86,5 @@ export function registerTokenRequestRoute(opts) {
82
86
  // gains optional fields (locale, deviceId, …).
83
87
  const RequestTokenBody = z.object({
84
88
  email: z.email(),
89
+ returnTo: returnToField,
85
90
  });
@@ -73,6 +73,8 @@ export function createClientErrorRoute(options) {
73
73
  const app = new Hono();
74
74
  const logger = createFallbackLogger("client-errors");
75
75
  const routePath = `/api${Routes.clientErrors}`;
76
+ // Always on: the shared limiter fails open when Redis is down, this per-process window is the floor.
77
+ app.post(Routes.clientErrors, inMemoryIpRateLimit(options.clientIpResolver, options.now ?? Date.now));
76
78
  if (options.resolver) {
77
79
  app.post(Routes.clientErrors, httpRouteRateLimit({
78
80
  resolver: options.resolver,
@@ -82,9 +84,6 @@ export function createClientErrorRoute(options) {
82
84
  ...(options.meter && { meter: options.meter }),
83
85
  }));
84
86
  }
85
- else {
86
- app.post(Routes.clientErrors, inMemoryIpRateLimit(options.clientIpResolver, options.now ?? Date.now));
87
- }
88
87
  app.post(Routes.clientErrors, bodyLimit({
89
88
  maxSize: MAX_BODY_BYTES,
90
89
  onError: (c) => c.json({ error: { code: "payload_too_large" } }, 413),
@@ -1,2 +1,5 @@
1
- import type { AccessRule, Registry } from "../engine/types/index.ts";
1
+ import type { AccessRule } from "@cosmicdrift/kumiko-types/handlers";
2
+ import type { OwnershipMap } from "@cosmicdrift/kumiko-types/ownership";
3
+ import type { Registry } from "../engine/types/index.ts";
2
4
  export declare function collectEntityReadAccess(registry: Registry): ReadonlyMap<string, readonly AccessRule[]>;
5
+ export declare function collectEntityRowReadMaps(registry: Registry): ReadonlyMap<string, OwnershipMap>;
@@ -25,3 +25,17 @@ export function collectEntityReadAccess(registry) {
25
25
  }
26
26
  return rulesByEntity;
27
27
  }
28
+ // Entities whose own access.read narrows rows per role (e.g. Driver sees only assigned rows).
29
+ // A signal for such an entity must not name ids to a role that does not read every row.
30
+ export function collectEntityRowReadMaps(registry) {
31
+ const mapsByEntity = new Map();
32
+ for (const [entityName, entity] of registry.getAllEntities()) {
33
+ const readMap = entity.access?.read;
34
+ if (readMap === undefined || Object.keys(readMap).length === 0)
35
+ continue;
36
+ for (const aggregateType of new Set([entityName, toKebabCase(entityName)])) {
37
+ mapsByEntity.set(aggregateType, readMap);
38
+ }
39
+ }
40
+ return mapsByEntity;
41
+ }
@@ -0,0 +1,9 @@
1
+ import type { Cell } from "write-excel-file/node";
2
+ import type { ExportRow } from "./export-rows.ts";
3
+ export type ReferenceCellKind = {
4
+ readonly kind: "reference";
5
+ readonly labelField: string;
6
+ readonly multiple: boolean;
7
+ };
8
+ /** Labels come from the list row's eager-loaded `_refs`; a missing target shows its raw id. */
9
+ export declare function referenceCell(cell: ReferenceCellKind, field: string, row: ExportRow): Cell;
@@ -0,0 +1,21 @@
1
+ import { isPlainObject } from "../../utils/is-plain-object.js";
2
+ function labelOf(ref, labelField) {
3
+ if (!isPlainObject(ref))
4
+ return undefined;
5
+ const label = ref[labelField];
6
+ return typeof label === "string" ? label : undefined;
7
+ }
8
+ function refsOf(row, field) {
9
+ const refs = row["_refs"];
10
+ return isPlainObject(refs) ? refs[field] : undefined;
11
+ }
12
+ /** Labels come from the list row's eager-loaded `_refs`; a missing target shows its raw id. */
13
+ export function referenceCell(cell, field, row) {
14
+ const ids = cell.multiple && Array.isArray(row[field]) ? row[field] : [row[field]];
15
+ const ref = refsOf(row, field);
16
+ const labels = ids.map((id) => {
17
+ const target = Array.isArray(ref) ? ref.find((r) => isPlainObject(r) && r["id"] === id) : ref;
18
+ return labelOf(target, cell.labelField) ?? String(id);
19
+ });
20
+ return { value: labels.join(", "), type: String };
21
+ }
@@ -0,0 +1,11 @@
1
+ import type { Cell } from "write-excel-file/node";
2
+ import type { ExportColumn } from "./export-columns.ts";
3
+ import type { ExportRow } from "./export-rows.ts";
4
+ export type Translate = (key: string) => string;
5
+ export type ExportCellContext = {
6
+ readonly row: ExportRow;
7
+ readonly translate: Translate;
8
+ readonly timeZone: string;
9
+ };
10
+ /** Never emits a formula cell and never reinterprets strings: text always stays text. */
11
+ export declare function toExportCell(column: ExportColumn, context: ExportCellContext): Cell;