@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
@@ -35,6 +35,10 @@ back.
35
35
  - **`r.hook({ type: "postDelete", target: { allOf: entityRef }, handler })`** — fires after commit.
36
36
  External side effects (logs, notifications) belong here because
37
37
  failures cannot roll the delete back.
38
+ - **`ctx.lifecycle.afterRollback(fn)`** — the counterpart of `ctx.lifecycle.afterCommit`: runs `fn` when
39
+ the handler transaction (or the enclosing savepoint of a nested `ctx.dispatch.write`) does not commit.
40
+ Use it to give back something reserved outside the transaction, like the slot in
41
+ `article:reserve-slot`. A failed COMMIT triggers it too, so write the callback idempotent.
38
42
 
39
43
  ## When to reach for it
40
44
 
@@ -71,7 +75,7 @@ import {
71
75
  type TestStack,
72
76
  unsafeCreateEntityTable,
73
77
  } from "@cosmicdrift/kumiko-testing/stack";
74
- import { articleEntity, articlesFeature, hookLog } from "../feature";
78
+ import { articleEntity, articlesFeature, hookLog, reservedSlots } from "../feature";
75
79
 
76
80
  let stack: TestStack;
77
81
 
@@ -90,6 +94,7 @@ afterAll(async () => {
90
94
  beforeEach(() => {
91
95
  stack.events.reset();
92
96
  hookLog.length = 0;
97
+ reservedSlots.clear();
93
98
  });
94
99
 
95
100
  describe("validation hook: single handler", () => {
@@ -256,6 +261,29 @@ describe("preDelete + postDelete entity hooks", () => {
256
261
  expect(hookLog.map((e) => e.type)).toEqual(["deleted"]);
257
262
  });
258
263
  });
264
+
265
+ describe("scheduleAfterRollback", () => {
266
+ test("keeps the outside-transaction reservation when the write commits", async () => {
267
+ await stack.http.writeOk(
268
+ "blog:write:article:reserve-slot",
269
+ { slot: "kept", reject: false },
270
+ editor,
271
+ );
272
+
273
+ expect(reservedSlots.has("kept")).toBe(true);
274
+ });
275
+
276
+ test("gives the reservation back when the write rolls back", async () => {
277
+ const error = await stack.http.writeErr(
278
+ "blog:write:article:reserve-slot",
279
+ { slot: "released", reject: true },
280
+ editor,
281
+ );
282
+
283
+ expectErrorIncludes(error, "slot_rejected");
284
+ expect(reservedSlots.has("released")).toBe(false);
285
+ });
286
+ });
259
287
  ```
260
288
 
261
289
  ### src/feature.ts
@@ -276,7 +304,12 @@ import {
276
304
  defineFeature,
277
305
  type SaveContext,
278
306
  } from "@cosmicdrift/kumiko-framework/engine";
279
- import { ConflictError } from "@cosmicdrift/kumiko-framework/errors";
307
+ import {
308
+ ConflictError,
309
+ UnprocessableError,
310
+ writeFailure,
311
+ } from "@cosmicdrift/kumiko-framework/errors";
312
+ import * as z from "zod";
280
313
 
281
314
  export const articleEntity = createEntity({
282
315
  table: "read_sample_articles",
@@ -298,6 +331,9 @@ export const articleEntity = createEntity({
298
331
  // Collect hook events for testing
299
332
  export const hookLog: { type: string; data: Record<string, unknown> }[] = [];
300
333
 
334
+ // Stands in for a quota held in an external system, outside the handler transaction.
335
+ export const reservedSlots = new Set<string>();
336
+
301
337
  const editorWrite = { access: { roles: ["Admin", "Editor"] } } as const;
302
338
 
303
339
  export const articlesFeature = defineFeature("blog", (r) => {
@@ -311,6 +347,23 @@ export const articlesFeature = defineFeature("blog", (r) => {
311
347
  );
312
348
  r.writeHandler(defineEntityDeleteHandler("article", articleEntity, editorWrite));
313
349
 
350
+ // --- scheduleAfterRollback: give back a reservation made outside the transaction when it does
351
+ // not commit. The callback must be idempotent: a failed COMMIT also triggers it.
352
+ r.writeHandler({
353
+ name: "article:reserve-slot",
354
+ schema: z.object({ slot: z.string(), reject: z.boolean() }),
355
+ access: editorWrite.access,
356
+ handler: async (event, ctx) => {
357
+ const { slot, reject } = event.payload;
358
+ reservedSlots.add(slot);
359
+ ctx.lifecycle.afterRollback?.(async () => {
360
+ reservedSlots.delete(slot);
361
+ });
362
+ if (reject) return writeFailure(new UnprocessableError("slot_rejected"));
363
+ return { isSuccess: true as const, data: {} };
364
+ },
365
+ });
366
+
314
367
  // --- Validation hook on create: reject banned words + length ---
315
368
  r.hook({
316
369
  type: "validation",
@@ -0,0 +1,466 @@
1
+ <!-- Generated by `bun run gen:agent-docs` from samples/recipes/list-table-options. Do not edit. -->
2
+
3
+ # list-table-options
4
+
5
+ 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.
6
+
7
+ ## README
8
+
9
+ # List table options
10
+
11
+ Opt-in table behaviour for entity, projection and related lists. A list without
12
+ the `table` block renders and behaves as before.
13
+
14
+ ## What it shows
15
+
16
+ - `table.rememberState`: search, sort, page size, facets and date range survive
17
+ leaving and re-entering the list within the browser session.
18
+ - `table.resetAll`: one button resets everything that differs from the defaults.
19
+ - `table.columnPicker`: the view menu lets the user hide and reorder columns;
20
+ `hidden: true` on a column starts it hidden.
21
+ - `table.density`: row density default and an optional user choice.
22
+ - `table.pinning`: the user pins columns left or right in the view menu;
23
+ `pinned: "left"` on a column starts it pinned.
24
+ - `table.resizing`: columns can be resized (table-layout fixed); `width` and
25
+ `minWidth` on a column are start values in px.
26
+ - `table.keyboardNavigation`: rows are one tab stop, arrow keys move between rows,
27
+ Space selects the focused row.
28
+ - `table.export`: an Export button downloads the whole filtered list as an XLSX
29
+ file; `maxRows` lowers the default limit of 10000 rows.
30
+ Reference columns export their label and timestamps use the browser time zone.
31
+ - `bulkActions`: row checkboxes and a selection bar. "Delete" runs the delete
32
+ row action once per selected row; done tasks are skipped.
33
+ - `table.grouping`: the server groups the list by status; each header shows the
34
+ group's count and estimate sum, "done" starts collapsed and the view menu
35
+ offers grouping by priority or none.
36
+ - `table.totals`: a footer row with the estimate sum over the filtered list.
37
+ - `facets.estimateHours: { display: "range" }`: from/to inputs for a number field.
38
+ - The same block on a `projectionList`, and `task:workload`, a hand-written list
39
+ query that keeps grouping and totals by accepting `aggregate`
40
+ (`entityListSchema`) and answering it with `answerListAggregate`.
41
+
42
+ ## Source
43
+
44
+ Feature entry point: `src/feature.ts`.
45
+
46
+ ## Tests
47
+
48
+ ```bash
49
+ cd samples/recipes/list-table-options
50
+ bun test
51
+ ```
52
+
53
+ The test boots the feature through the boot validator and checks that a
54
+ misspelled key, a hidden column without the picker, an unknown density, a pinned column
55
+ without `pinning`, a width without `resizing` and a bulk action on a navigate
56
+ row action are rejected.
57
+ `workload.integration.test.ts` runs the hand-written query over HTTP and checks
58
+ the grouped sums and the filtered total.
59
+
60
+ ## Source files
61
+
62
+ ### src/__tests__/feature.test.ts
63
+
64
+ ```ts
65
+ import { describe, expect, test } from "bun:test";
66
+ import {
67
+ createRegistry,
68
+ defineFeature,
69
+ validateBoot as validateBootRaw,
70
+ } from "@cosmicdrift/kumiko-framework/engine";
71
+ import type { ListTableOptions } from "@cosmicdrift/kumiko-framework/ui-types";
72
+ import { withBootValidatorFixture } from "@cosmicdrift/kumiko-testing/helpers";
73
+ import { createTaskBoardFeature, openAccess, taskEntity } from "../feature";
74
+
75
+ // The boot validator is the net for blocks the type system never sees (JS, generated features).
76
+ function featureWithBlock(block: object) {
77
+ return createTaskBoardFeature(block as ListTableOptions);
78
+ }
79
+
80
+ function validateBoot(features: Parameters<typeof validateBootRaw>[0]): void {
81
+ validateBootRaw(withBootValidatorFixture(features));
82
+ }
83
+
84
+ describe("list-table-options recipe", () => {
85
+ test("the full table block boots and reaches the registered screen", () => {
86
+ const feature = createTaskBoardFeature();
87
+ expect(() => validateBoot([feature])).not.toThrow();
88
+ const screen = createRegistry([feature]).getScreen("task-board:screen:task-list");
89
+ expect(screen?.type === "entityList" ? screen.table : undefined).toEqual({
90
+ rememberState: true,
91
+ resetAll: true,
92
+ columnPicker: true,
93
+ density: { default: "comfortable", userChoice: true },
94
+ pinning: true,
95
+ resizing: true,
96
+ keyboardNavigation: true,
97
+ export: { xlsx: true, maxRows: 5000 },
98
+ grouping: { field: "status", collapsedWhen: "done", userChoice: true, fields: ["priority"] },
99
+ totals: [{ field: "estimateHours", kind: "sum" }],
100
+ });
101
+ });
102
+
103
+ test("the bulk action resolves to the delete row action", () => {
104
+ const screen = createRegistry([createTaskBoardFeature()]).getScreen(
105
+ "task-board:screen:task-list",
106
+ );
107
+ expect(screen?.type === "entityList" ? screen.bulkActions : undefined).toEqual([
108
+ { id: "delete", rowAction: "delete" },
109
+ ]);
110
+ });
111
+
112
+ test("a bulk action that points at a navigate row action is rejected", () => {
113
+ const feature = defineFeature("bulk-on-navigate", (r) => {
114
+ r.crud("task", taskEntity, { write: openAccess, read: openAccess });
115
+ r.screen({
116
+ id: "task-list",
117
+ type: "entityList",
118
+ entity: "task",
119
+ columns: ["title"],
120
+ rowActions: [{ kind: "navigate", id: "open", label: "Open", screen: "task-list" }],
121
+ bulkActions: [{ id: "open", rowAction: "open" }],
122
+ access: openAccess.access,
123
+ });
124
+ });
125
+ expect(() => validateBoot([feature])).toThrow(
126
+ /bulk action "open" points at rowAction "open" of kind "navigate"/,
127
+ );
128
+ });
129
+
130
+ test("a pinned column needs table.pinning", () => {
131
+ expect(() => validateBoot([featureWithBlock({ columnPicker: true, resizing: true })])).toThrow(
132
+ /column "title" is pinned but table\.pinning is not enabled/,
133
+ );
134
+ });
135
+
136
+ test("width and minWidth need table.resizing", () => {
137
+ expect(() => validateBoot([featureWithBlock({ columnPicker: true, pinning: true })])).toThrow(
138
+ /column "title" sets width but table\.resizing is not enabled/,
139
+ );
140
+ });
141
+
142
+ test("a misspelled table key is rejected with the allowed keys", () => {
143
+ expect(() => validateBoot([featureWithBlock({ rememberStatee: true })])).toThrow(
144
+ /unknown key\(s\) "rememberStatee"\. Allowed keys: rememberState, resetAll, columnPicker, density, pinning, resizing, keyboardNavigation, export/,
145
+ );
146
+ });
147
+
148
+ test("a hidden column needs the column picker", () => {
149
+ expect(() => validateBoot([featureWithBlock({ rememberState: true, resetAll: true })])).toThrow(
150
+ /column "estimateHours" is hidden but table\.columnPicker is not enabled/,
151
+ );
152
+ });
153
+
154
+ test("a density outside the union is rejected", () => {
155
+ expect(() =>
156
+ validateBoot([featureWithBlock({ columnPicker: true, density: { default: "tight" } })]),
157
+ ).toThrow(/table\.density\.default is "tight"/);
158
+ });
159
+
160
+ test("an export row limit above the hard cap is rejected", () => {
161
+ expect(() =>
162
+ validateBoot([
163
+ featureWithBlock({ columnPicker: true, export: { xlsx: true, maxRows: 100001 } }),
164
+ ]),
165
+ ).toThrow(/table\.export\.maxRows is 100001 .* at most 100000/);
166
+ });
167
+ });
168
+ ```
169
+
170
+ ### src/__tests__/workload.integration.test.ts
171
+
172
+ ```ts
173
+ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
174
+ import { createTestUser, testTenantId } from "@cosmicdrift/kumiko-framework/seeding";
175
+ import { setupTestStack, type TestStack } from "@cosmicdrift/kumiko-testing/stack";
176
+ import { createTaskBoardFeature } from "../feature";
177
+
178
+ type ListAggregateResult = {
179
+ readonly groups: readonly { key: unknown; count: number; measures: readonly unknown[] }[];
180
+ };
181
+
182
+ let stack: TestStack;
183
+ const user = createTestUser({ roles: ["User"], tenantId: testTenantId(1) });
184
+
185
+ const TASKS = [
186
+ { title: "Quarterly VAT filing", assignee: "Ines", estimateHours: 6 },
187
+ { title: "Prepare audit", assignee: "Ines", estimateHours: 24 },
188
+ { title: "Plan offsite", assignee: "Mara", estimateHours: 7 },
189
+ ] as const;
190
+
191
+ beforeAll(async () => {
192
+ stack = await setupTestStack({ features: [createTaskBoardFeature()], systemHooks: [] });
193
+ for (const task of TASKS) {
194
+ await stack.http.writeOk("task-board:write:task:create", task, user);
195
+ }
196
+ });
197
+
198
+ afterAll(async () => {
199
+ await stack.cleanup();
200
+ });
201
+
202
+ describe("hand-written list query with aggregate", () => {
203
+ test("groups by assignee with the server count and estimate sum", async () => {
204
+ const result = await stack.http.queryOk<ListAggregateResult>(
205
+ "task-board:query:task:workload",
206
+ { aggregate: { groupBy: "assignee", measures: [{ field: "estimateHours", kind: "sum" }] } },
207
+ user,
208
+ );
209
+ expect(result.groups.map(({ key, count, measures }) => ({ key, count, measures }))).toEqual([
210
+ { key: "Ines", count: 2, measures: [30] },
211
+ { key: "Mara", count: 1, measures: [7] },
212
+ ]);
213
+ });
214
+
215
+ test("the totals answer follows the list filter", async () => {
216
+ const result = await stack.http.queryOk<ListAggregateResult>(
217
+ "task-board:query:task:workload",
218
+ {
219
+ filters: [{ field: "estimateHours", op: "lte", value: 7 }],
220
+ aggregate: { measures: [{ field: "estimateHours", kind: "sum" }] },
221
+ },
222
+ user,
223
+ );
224
+ expect(result.groups.map((group) => group.measures)).toEqual([[13]]);
225
+ });
226
+
227
+ test("without aggregate the same query lists rows", async () => {
228
+ const list = await stack.http.queryOk<{ rows: { title: string }[] }>(
229
+ "task-board:query:task:workload",
230
+ { sort: "title" },
231
+ user,
232
+ );
233
+ expect(list.rows.map((row) => row.title)).toEqual([
234
+ "Plan offsite",
235
+ "Prepare audit",
236
+ "Quarterly VAT filing",
237
+ ]);
238
+ });
239
+ });
240
+ ```
241
+
242
+ ### src/feature.ts
243
+
244
+ ```ts
245
+ import {
246
+ answerListAggregate,
247
+ buildEntityTable,
248
+ createEventStoreExecutor,
249
+ } from "@cosmicdrift/kumiko-framework/db";
250
+ import {
251
+ createDateField,
252
+ createEntity,
253
+ createNumberField,
254
+ createSelectField,
255
+ createTextField,
256
+ defineFeature,
257
+ entityListSchema,
258
+ type FeatureDefinition,
259
+ } from "@cosmicdrift/kumiko-framework/engine";
260
+ import type { ListTableOptions } from "@cosmicdrift/kumiko-framework/ui-types";
261
+ import { z } from "zod";
262
+
263
+ export const taskEntity = createEntity({
264
+ table: "read_list_table_tasks",
265
+ fields: {
266
+ title: createTextField({
267
+ personal: false,
268
+ reason: "is_business_data",
269
+ required: true,
270
+ searchable: true,
271
+ sortable: true,
272
+ }),
273
+ status: createSelectField({
274
+ options: ["open", "inProgress", "blocked", "done"] as const,
275
+ default: "open",
276
+ sortable: true,
277
+ filterable: true,
278
+ }),
279
+ priority: createSelectField({
280
+ options: ["low", "medium", "high"] as const,
281
+ default: "medium",
282
+ sortable: true,
283
+ filterable: true,
284
+ }),
285
+ dueDate: createDateField({ sortable: true }),
286
+ assignee: createTextField({ personal: false, reason: "is_business_data", sortable: true }),
287
+ estimateHours: createNumberField({ sortable: true, filterable: true }),
288
+ },
289
+ });
290
+
291
+ export const openAccess = {
292
+ access: {
293
+ openToAll: { reason: "recipe: any signed-in user manages the tasks; no per-user ownership" },
294
+ },
295
+ } as const;
296
+
297
+ // Overridable so a test can feed the boot validator a block that must be rejected.
298
+ export function createTaskBoardFeature(
299
+ taskTable: ListTableOptions = {
300
+ rememberState: true,
301
+ resetAll: true,
302
+ columnPicker: true,
303
+ density: { default: "comfortable", userChoice: true },
304
+ pinning: true,
305
+ resizing: true,
306
+ keyboardNavigation: true,
307
+ export: { xlsx: true, maxRows: 5000 },
308
+ grouping: { field: "status", collapsedWhen: "done", userChoice: true, fields: ["priority"] },
309
+ totals: [{ field: "estimateHours", kind: "sum" }],
310
+ },
311
+ ): FeatureDefinition {
312
+ return defineFeature("task-board", (r) => {
313
+ r.crud("task", taskEntity, { write: openAccess, read: openAccess });
314
+
315
+ r.screen({
316
+ id: "task-list",
317
+ type: "entityList",
318
+ entity: "task",
319
+ columns: [
320
+ // Starts pinned left; width and minWidth are start values for resizing.
321
+ { field: "title", pinned: "left", width: 280, minWidth: 160 },
322
+ "status",
323
+ "priority",
324
+ { field: "dueDate", hideOnNarrow: true },
325
+ { field: "assignee", hideOnNarrow: true },
326
+ // Starts hidden; the user can add it back in the view menu.
327
+ { field: "estimateHours", hidden: true, hideOnNarrow: true },
328
+ ],
329
+ facets: { status: { display: "chips" }, priority: {}, estimateHours: { display: "range" } },
330
+ defaultSort: { field: "dueDate", dir: "asc" },
331
+ searchable: true,
332
+ table: taskTable,
333
+ rowActions: [
334
+ { kind: "navigate", id: "open", label: "Open", screen: "task-edit", rowClick: true },
335
+ {
336
+ kind: "writeHandler",
337
+ id: "delete",
338
+ label: "Delete",
339
+ handler: "task-board:write:task:delete",
340
+ style: "danger",
341
+ // Done tasks are skipped by the bulk run and counted as skipped.
342
+ visible: { field: "status", ne: "done" },
343
+ },
344
+ ],
345
+ // Row checkboxes and a selection bar; each selected row gets its own delete write.
346
+ bulkActions: [{ id: "delete", rowAction: "delete" }],
347
+ access: openAccess.access,
348
+ });
349
+
350
+ r.screen({
351
+ id: "task-edit",
352
+ type: "entityEdit",
353
+ entity: "task",
354
+ dormant: true,
355
+ listScreenId: "task-list",
356
+ layout: {
357
+ sections: [
358
+ {
359
+ columns: 2,
360
+ fields: ["title", "assignee", "status", "priority", "dueDate", "estimateHours"],
361
+ },
362
+ ],
363
+ },
364
+ });
365
+
366
+ // The same block works on a list over any query.
367
+ r.queryHandler({
368
+ name: "task:overdue",
369
+ schema: z.object({}),
370
+ handler: async () => ({
371
+ rows: [{ id: "t1", title: "Quarterly VAT filing", assignee: "Ines", daysLate: 3 }],
372
+ nextCursor: null,
373
+ }),
374
+ access: openAccess.access,
375
+ outputSchema: z.object({
376
+ rows: z.array(
377
+ z.object({
378
+ id: z.string(),
379
+ title: z.string(),
380
+ assignee: z.string(),
381
+ daysLate: z.number(),
382
+ }),
383
+ ),
384
+ nextCursor: z.string().nullable(),
385
+ }),
386
+ });
387
+
388
+ r.screen({
389
+ id: "task-overdue",
390
+ type: "projectionList",
391
+ query: "task-board:query:task:overdue",
392
+ columns: ["title", "assignee", "daysLate"],
393
+ table: { rememberState: true, density: { userChoice: true } },
394
+ });
395
+
396
+ // A hand-written list query keeps grouping and totals when it accepts
397
+ // `aggregate` (entityListSchema carries it) and answers it on the server.
398
+ const taskExecutor = createEventStoreExecutor(
399
+ buildEntityTable("task", taskEntity),
400
+ taskEntity,
401
+ {
402
+ entityName: "task",
403
+ },
404
+ );
405
+ r.queryHandler({
406
+ name: "task:workload",
407
+ schema: entityListSchema,
408
+ handler: async (query, ctx) => {
409
+ const parentVisibility = { entities: ctx.registry.getAllEntities() };
410
+ const listPayload = query.payload;
411
+ if (listPayload.aggregate !== undefined) {
412
+ return answerListAggregate(
413
+ taskExecutor,
414
+ { ...listPayload, aggregate: listPayload.aggregate },
415
+ query.user,
416
+ ctx.db,
417
+ { parentVisibility },
418
+ {
419
+ entity: taskEntity,
420
+ resolveEntity: (name) => ctx.registry.getEntity(name),
421
+ viewer: { user: query.user, parentVisibility },
422
+ },
423
+ );
424
+ }
425
+ return taskExecutor.list(listPayload, query.user, ctx.db, { parentVisibility });
426
+ },
427
+ access: openAccess.access,
428
+ });
429
+
430
+ r.screen({
431
+ id: "task-workload",
432
+ type: "projectionList",
433
+ query: "task-board:query:task:workload",
434
+ columns: ["title", "assignee", "status", "estimateHours"],
435
+ defaultSort: { field: "title", dir: "asc" },
436
+ table: {
437
+ grouping: { field: "assignee" },
438
+ totals: [{ field: "estimateHours", kind: "sum" }],
439
+ },
440
+ });
441
+
442
+ r.nav({ id: "tasks", label: "task-board:nav.tasks", icon: "list", order: 10 });
443
+ r.nav({
444
+ id: "task-list",
445
+ label: "task-board:nav.list",
446
+ parent: "task-board:nav:tasks",
447
+ screen: "task-board:screen:task-list",
448
+ order: 10,
449
+ });
450
+ r.nav({
451
+ id: "task-overdue",
452
+ label: "task-board:nav.overdue",
453
+ parent: "task-board:nav:tasks",
454
+ screen: "task-board:screen:task-overdue",
455
+ order: 20,
456
+ });
457
+ r.nav({
458
+ id: "task-workload",
459
+ label: "task-board:nav.workload",
460
+ parent: "task-board:nav:tasks",
461
+ screen: "task-board:screen:task-workload",
462
+ order: 30,
463
+ });
464
+ });
465
+ }
466
+ ```
@@ -51,7 +51,7 @@ r.config({
51
51
 
52
52
  - **`backing: "secrets"`** — the value lives in the secrets store (envelope
53
53
  encryption, KEK rotation, audit-on-read) instead of `config_values`. Set/read/
54
- reset dispatch through `ctx.secrets`; the query handlers mask the value while
54
+ reset dispatch through `ctx.services.secrets`; the query handlers mask the value while
55
55
  the owning feature still reads the revealed plaintext via `ctx.config`. Only
56
56
  valid for `scope: "system"` — secrets are flat per `(tenant, key)` with no
57
57
  cascade, so a tenant override would be incoherent and is rejected at boot.
@@ -80,7 +80,7 @@ await runProdApp({
80
80
  envSchema, // composeEnvSchema({ core: frameworkCoreEnvSchema, features })
81
81
  extraContext: ({ db, registry }) => ({
82
82
  configResolver: resolver,
83
- _configAccessorFactory: createConfigAccessorFactory(registry, resolver),
83
+ configAccessorFactory: createConfigAccessorFactory(registry, resolver),
84
84
  // Required whenever a key declares backing:"secrets" — without it the set
85
85
  // and read paths fail loud, never silently miss.
86
86
  secrets: createSecretsContext({ db, masterKeyProvider, registry }),
@@ -90,7 +90,7 @@ await runProdApp({
90
90
  ```
91
91
 
92
92
  Register the `secrets` feature too so its `tenant_secrets` table is migrated;
93
- the config backing only needs the `ctx.secrets` context shown above.
93
+ the config backing only needs the `ctx.services.secrets` context shown above.
94
94
 
95
95
  ## Vs. the neighbouring recipes
96
96
 
@@ -211,7 +211,7 @@ beforeAll(async () => {
211
211
  const resolver = createConfigResolver();
212
212
  return {
213
213
  configResolver: resolver,
214
- _configAccessorFactory: createConfigAccessorFactory(registry, resolver),
214
+ configAccessorFactory: createConfigAccessorFactory(registry, resolver),
215
215
  secrets: createSecretsContext({ db, masterKeyProvider, registry }),
216
216
  };
217
217
  },
@@ -212,7 +212,7 @@ beforeAll(async () => {
212
212
  // Wire ctx.config() so the branding query resolves the tenant's cascade.
213
213
  extraContext: ({ registry }) => ({
214
214
  configResolver: resolver,
215
- _configAccessorFactory: createConfigAccessorFactory(registry, resolver),
215
+ configAccessorFactory: createConfigAccessorFactory(registry, resolver),
216
216
  }),
217
217
  });
218
218
  await unsafeCreateEntityTable(stack.db, pageEntity);
@@ -42,6 +42,7 @@ bun test
42
42
  // and its text contains exactly the inspections of the requested period.
43
43
 
44
44
  import { afterAll, beforeAll, describe, expect, test } from "bun:test";
45
+ import { MAX_LIST_LIMIT } from "@cosmicdrift/kumiko-framework/engine";
45
46
  import {
46
47
  createFilesFeature,
47
48
  createInMemoryFileProvider,
@@ -150,7 +151,7 @@ describe("export-audit", () => {
150
151
 
151
152
  test("a period with more inspections than the export holds is rejected instead of cut off", async () => {
152
153
  const assetName = "Großanlage";
153
- for (let day = 0; day < 101; day += 1) {
154
+ for (let day = 0; day < MAX_LIST_LIMIT; day += 1) {
154
155
  const inspectedOn = new Date(Date.UTC(2025, 0, 1 + day)).toISOString().slice(0, 10);
155
156
  await addInspection(inspectedOn, "ok", `Prüfer-${day}`, assetName);
156
157
  }
@@ -185,6 +186,7 @@ import {
185
186
  createTextField,
186
187
  defineFeature,
187
188
  defineWriteHandler,
189
+ MAX_LIST_LIMIT,
188
190
  } from "@cosmicdrift/kumiko-framework/engine";
189
191
  import { UnprocessableError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
190
192
  import {
@@ -221,7 +223,7 @@ function toFileNameSegment(text: string): string {
221
223
  }
222
224
 
223
225
  // One row above the limit tells "exactly full" from "cut off"; entity lists cap at 200 rows.
224
- const AUDIT_ROW_LIMIT = 100;
226
+ const AUDIT_ROW_LIMIT = MAX_LIST_LIMIT - 1;
225
227
 
226
228
  const access = { access: { roles: ["Admin", "User"] } } as const;
227
229