@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
@@ -6,8 +6,10 @@ import { selectEventsHeadId, selectPendingAndNewEventRows, } from "../db/queries
6
6
  import { coerceRow } from "../db/query.js";
7
7
  import { extractTableInfo } from "../db/table-info.js";
8
8
  import { qnScope } from "../engine/qualified-name.js";
9
- import { eventsTable, toStoredEvent as rowToStoredEvent, } from "../event-store/index.js";
10
- import { emitDispatcherError, emitEventConsumerLag, emitEventConsumerPendingGaps, getFallbackMeter, } from "../observability/index.js";
9
+ import { eventsTable } from "../event-store/index.js";
10
+ import { toStoredEvent as rowToStoredEvent } from "../event-store/row-to-stored-event.js";
11
+ import { getFallbackMeter } from "../observability/fallback.js";
12
+ import { emitDispatcherError, emitEventConsumerLag, emitEventConsumerPendingGaps, } from "../observability/standard-metrics.js";
11
13
  import { ConsumerStatuses, eventConsumerStateTable, SHARED_INSTANCE_SENTINEL, } from "./event-consumer-state.js";
12
14
  import { parseWriteOrigin } from "./write-origin.js";
13
15
  // Fails closed without throwing: a throw would poison the event for every consumer.
@@ -212,9 +214,11 @@ export async function deliverEvents(consumer, events, context, maxAttempts, stat
212
214
  resolve(row.id);
213
215
  continue;
214
216
  }
215
- attempts += 1;
216
217
  lastError = errMessage;
217
218
  failedEventId = row.id;
219
+ if (consumer.errorPolicy?.isTransientError?.(e))
220
+ break;
221
+ attempts += 1;
218
222
  if (attempts >= effectiveMaxAttempts)
219
223
  deadLettered = true;
220
224
  break;
@@ -1,12 +1,13 @@
1
+ import type { Meter, Tracer } from "@cosmicdrift/kumiko-types/observability";
1
2
  import type { PgListenClient } from "../db/connection.ts";
2
3
  import type { AppContext } from "../engine/types/index.ts";
3
- import { type StoredEvent } from "../event-store/index.ts";
4
- import { type Meter, type Tracer } from "../observability/index.ts";
4
+ import type { StoredEvent } from "../event-store/index.ts";
5
5
  export type EventConsumerHandler = (event: StoredEvent, ctx: AppContext) => Promise<void>;
6
6
  export type EventConsumerBatchHandler = (events: readonly StoredEvent[], ctx: AppContext) => Promise<void>;
7
7
  export type EventConsumerErrorPolicy = {
8
8
  readonly skipApplyErrors?: boolean;
9
9
  readonly maxAttempts?: number;
10
+ readonly isTransientError?: (error: unknown) => boolean;
10
11
  };
11
12
  export type EventConsumer = {
12
13
  readonly name: string;
@@ -1,9 +1,11 @@
1
1
  import { extractPgError } from "../db/pg-error.js";
2
2
  import { recordConsumerPassFailure, selectSnapshotXmax, selectSnapshotXmin, } from "../db/queries/event-consumer.js";
3
+ import { assertNoActiveRowLevelSecurityScope, runInSystemRowLevelSecurityScope, } from "../db/row-level-security-scope.js";
3
4
  import { SYSTEM_TENANT_ID } from "../engine/types/identifiers.js";
4
- import { EVENTS_PUBSUB_CHANNEL } from "../event-store/index.js";
5
+ import { EVENTS_PUBSUB_CHANNEL } from "../event-store/event-store.js";
5
6
  import { createFallbackLogger } from "../logging/utils.js";
6
- import { emitEventConsumerPassOutcome, emitEventConsumerPassSkipped, emitEventConsumerRearmExhausted, emitEventDispatcherListenConnected, getFallbackMeter, getFallbackTracer, } from "../observability/index.js";
7
+ import { getFallbackMeter, getFallbackTracer } from "../observability/fallback.js";
8
+ import { emitEventConsumerPassOutcome, emitEventConsumerPassSkipped, emitEventConsumerRearmExhausted, emitEventDispatcherListenConnected, } from "../observability/standard-metrics.js";
7
9
  import { SHARED_INSTANCE_SENTINEL } from "./event-consumer-state.js";
8
10
  import { acquireConsumerState, consumerInstanceId, deliverEvents, emitLagFromTx, fetchPendingEvents, markProcessing, persistConsumerOutcome, preRegisterConsumers, selectIdleConsumerKeys, } from "./event-dispatcher-delivery.js";
9
11
  import { mergeContiguousGapRanges, partitionBurntGaps, splitRangeExcludingIds, toIdRanges, } from "./pending-gap-ranges.js";
@@ -16,12 +18,10 @@ const PENDING_GAPS_WARN_THRESHOLD = 1000;
16
18
  // Only these say the database socket itself is gone; timeouts, schema or pool errors do not
17
19
  // imply the dedicated LISTEN connection dropped.
18
20
  const CONNECTION_LOSS_CODES = new Set([
19
- "CONNECTION_CLOSED",
20
- "CONNECTION_DESTROYED",
21
- "CONNECTION_ENDED",
22
- "CONNECT_TIMEOUT",
23
- "ECONNREFUSED",
24
- "ECONNRESET",
21
+ "ERR_POSTGRES_CONNECTION_CLOSED",
22
+ "ERR_POSTGRES_CONNECTION_REFUSED",
23
+ "ERR_POSTGRES_CONNECTION_TIMEOUT",
24
+ "ERR_POSTGRES_CONNECTION_FAILED",
25
25
  "57P01",
26
26
  ]);
27
27
  function isConnectionLossError(e) {
@@ -111,7 +111,7 @@ export function createEventDispatcher(options) {
111
111
  let pgSubscription = null;
112
112
  // Bounds how many consumer turns hold a DB transaction at once. Each turn's
113
113
  // db.begin() checks out one pool connection, plus any writes the handler
114
- // itself makes via context.db — the app db pool defaults to postgres-js's
114
+ // itself makes via context.db — the app db pool defaults to Bun.SQL's
115
115
  // max=10 (db/connection.ts, no DATABASE_POOL_MAX override) and is shared
116
116
  // with HTTP request handlers, so turns can't be allowed to claim it all.
117
117
  // A pool no larger than this limit can deadlock: every connection held by
@@ -223,7 +223,8 @@ export function createEventDispatcher(options) {
223
223
  if (!preRegistered) {
224
224
  throw new Error("EventDispatcher.runOnce() called before start() — consumer state rows are not registered. Call start() first (production) or ensureRegistered() (tests after truncating kumiko_event_consumers).");
225
225
  }
226
- const pass = doPass();
226
+ // Per pass, never around start(): the poll loop itself must stay outside any scope.
227
+ const pass = runInSystemRowLevelSecurityScope("event dispatcher pass runs consumers for every tenant", doPass);
227
228
  inFlightPasses.add(pass);
228
229
  try {
229
230
  return await pass;
@@ -459,6 +460,7 @@ export function createEventDispatcher(options) {
459
460
  return {
460
461
  consumers,
461
462
  async start() {
463
+ assertNoActiveRowLevelSecurityScope("EventDispatcher");
462
464
  // skip: already running, idempotent
463
465
  if (running)
464
466
  return;
@@ -493,8 +495,7 @@ export function createEventDispatcher(options) {
493
495
  const sub = await options.pgClient.listen(EVENTS_PUBSUB_CHANNEL, runBackgroundPass, () => {
494
496
  // Fires on initial connect and again when the driver's own
495
497
  // re-LISTEN lands after a drop; during an outage that re-LISTEN
496
- // waits in its connection backoff (postgres-js: measured 10-30s
497
- // after the DB returns), polling covers
498
+ // waits in the driver's reconnect backoff, polling covers
498
499
  // delivery meanwhile. Never unlisten()
499
500
  // + listen() by hand: that leaves duplicate listeners.
500
501
  // ponytail: no own LISTEN reconnect, the backoff gap is polled;
@@ -1,6 +1,7 @@
1
1
  /// <reference types="temporal-polyfill/global" preserve="true" />
2
2
  import { lockEventConsumersShareMode } from "../db/queries/event-consumer.js";
3
3
  import { deleteMany, selectMany, transaction } from "../db/query.js";
4
+ import { runInSystemRowLevelSecurityScope } from "../db/row-level-security-scope.js";
4
5
  import { eventsTable } from "../event-store/index.js";
5
6
  import { eventConsumerStateTable } from "./event-consumer-state.js";
6
7
  export class ConsumerLagError extends Error {
@@ -27,64 +28,66 @@ function resolveCutoff(opts) {
27
28
  return Temporal.Now.instant().subtract({ hours: days * 24 });
28
29
  }
29
30
  export async function pruneEvents(db, options) {
30
- const cutoff = resolveCutoff(options);
31
- if (!options.aggregateTypes || options.aggregateTypes.length === 0) {
32
- throw new Error("pruneEvents: aggregateTypes is required and must be non-empty. Pruning the event log is destructive — name the aggregate types to delete explicitly.");
33
- }
34
- if (options.aggregateIds !== undefined && options.aggregateIds.length === 0) {
35
- throw new Error("pruneEvents: aggregateIds must be non-empty when set.");
36
- }
37
- if (options.batchSize !== undefined &&
38
- (!Number.isInteger(options.batchSize) || options.batchSize < 1)) {
39
- throw new Error("pruneEvents: batchSize must be a positive integer.");
40
- }
41
- const aggregateTypes = options.aggregateTypes;
42
- const aggregateIds = options.aggregateIds;
43
- const dryRun = options.dryRun === true;
44
- return transaction(db, async (tx) => {
45
- // Serialise against consumer-bootstrap INSERTs. Without this, the race
46
- // is: prune reads consumers (snapshot misses a consumer bootstrapping
47
- // in a parallel tx) → consumer commits its row with
48
- // lastProcessedEventId=0 → prune deletes events below its new cursor
49
- // → first pass of the new consumer silently skips the deleted events.
50
- //
51
- // SHARE is the lightest table-mode that conflicts with ROW EXCLUSIVE
52
- // (the mode INSERT/UPDATE/DELETE take). Concurrent INSERTs on the
53
- // consumer table queue until this TX commits; concurrent UPDATEs
54
- // (cursor advances) do too, but prune is measured in milliseconds and
55
- // pausing cursor advances for that window is cheap insurance against
56
- // a silent data-loss bug.
57
- await lockEventConsumersShareMode(tx);
58
- // Step 1 — collect candidate event ids.
59
- const candidates = await selectMany(tx, eventsTable, {
60
- aggregateType: [...aggregateTypes],
61
- ...(aggregateIds ? { aggregateId: [...aggregateIds] } : {}),
62
- createdAt: { lt: cutoff },
63
- }, options.batchSize === undefined
64
- ? undefined
65
- : { orderBy: { col: "id", direction: "asc" }, limit: options.batchSize });
66
- if (candidates.length === 0) {
67
- return { deletedCount: 0, cutoff, aggregateTypes, dryRun };
31
+ return runInSystemRowLevelSecurityScope("event retention pruning deletes expired events of all tenants", async () => {
32
+ const cutoff = resolveCutoff(options);
33
+ if (!options.aggregateTypes || options.aggregateTypes.length === 0) {
34
+ throw new Error("pruneEvents: aggregateTypes is required and must be non-empty. Pruning the event log is destructive — name the aggregate types to delete explicitly.");
68
35
  }
69
- const maxCandidateId = candidates.reduce((acc, row) => (row.id > acc ? row.id : acc), candidates[0]?.id ?? 0n);
70
- // Step 2 — safety guard: check every ACTIVE consumer has moved past
71
- // the candidate set. Disabled consumers are intentionally excluded —
72
- // ops disables them precisely to park them while pruning happens.
73
- // The SHARE lock above guarantees this SELECT sees a complete view:
74
- // no new consumer can INSERT a fresh-cursor row between here and the
75
- // DELETE below.
76
- const activeConsumers = await selectMany(tx, eventConsumerStateTable, { status: { ne: "disabled" } });
77
- for (const consumer of activeConsumers) {
78
- if (consumer.lastProcessedEventId < maxCandidateId) {
79
- throw new ConsumerLagError(consumer.name, consumer.lastProcessedEventId, maxCandidateId);
80
- }
36
+ if (options.aggregateIds !== undefined && options.aggregateIds.length === 0) {
37
+ throw new Error("pruneEvents: aggregateIds must be non-empty when set.");
81
38
  }
82
- if (dryRun) {
83
- return { deletedCount: candidates.length, cutoff, aggregateTypes, dryRun: true };
39
+ if (options.batchSize !== undefined &&
40
+ (!Number.isInteger(options.batchSize) || options.batchSize < 1)) {
41
+ throw new Error("pruneEvents: batchSize must be a positive integer.");
84
42
  }
85
- // Step 3 — actual delete, bounded to the candidate set.
86
- const candidateIds = candidates.map((c) => c.id);
87
- await deleteMany(tx, eventsTable, { id: candidateIds });
88
- return { deletedCount: candidateIds.length, cutoff, aggregateTypes, dryRun: false };
43
+ const aggregateTypes = options.aggregateTypes;
44
+ const aggregateIds = options.aggregateIds;
45
+ const dryRun = options.dryRun === true;
46
+ return transaction(db, async (tx) => {
47
+ // Serialise against consumer-bootstrap INSERTs. Without this, the race
48
+ // is: prune reads consumers (snapshot misses a consumer bootstrapping
49
+ // in a parallel tx) → consumer commits its row with
50
+ // lastProcessedEventId=0 → prune deletes events below its new cursor
51
+ // → first pass of the new consumer silently skips the deleted events.
52
+ //
53
+ // SHARE is the lightest table-mode that conflicts with ROW EXCLUSIVE
54
+ // (the mode INSERT/UPDATE/DELETE take). Concurrent INSERTs on the
55
+ // consumer table queue until this TX commits; concurrent UPDATEs
56
+ // (cursor advances) do too, but prune is measured in milliseconds and
57
+ // pausing cursor advances for that window is cheap insurance against
58
+ // a silent data-loss bug.
59
+ await lockEventConsumersShareMode(tx);
60
+ // Step 1 — collect candidate event ids.
61
+ const candidates = await selectMany(tx, eventsTable, {
62
+ aggregateType: [...aggregateTypes],
63
+ ...(aggregateIds ? { aggregateId: [...aggregateIds] } : {}),
64
+ createdAt: { lt: cutoff },
65
+ }, options.batchSize === undefined
66
+ ? undefined
67
+ : { orderBy: { col: "id", direction: "asc" }, limit: options.batchSize });
68
+ if (candidates.length === 0) {
69
+ return { deletedCount: 0, cutoff, aggregateTypes, dryRun };
70
+ }
71
+ const maxCandidateId = candidates.reduce((acc, row) => (row.id > acc ? row.id : acc), candidates[0]?.id ?? 0n);
72
+ // Step 2 — safety guard: check every ACTIVE consumer has moved past
73
+ // the candidate set. Disabled consumers are intentionally excluded —
74
+ // ops disables them precisely to park them while pruning happens.
75
+ // The SHARE lock above guarantees this SELECT sees a complete view:
76
+ // no new consumer can INSERT a fresh-cursor row between here and the
77
+ // DELETE below.
78
+ const activeConsumers = await selectMany(tx, eventConsumerStateTable, { status: { ne: "disabled" } });
79
+ for (const consumer of activeConsumers) {
80
+ if (consumer.lastProcessedEventId < maxCandidateId) {
81
+ throw new ConsumerLagError(consumer.name, consumer.lastProcessedEventId, maxCandidateId);
82
+ }
83
+ }
84
+ if (dryRun) {
85
+ return { deletedCount: candidates.length, cutoff, aggregateTypes, dryRun: true };
86
+ }
87
+ // Step 3 — actual delete, bounded to the candidate set.
88
+ const candidateIds = candidates.map((c) => c.id);
89
+ await deleteMany(tx, eventsTable, { id: candidateIds });
90
+ return { deletedCount: candidateIds.length, cutoff, aggregateTypes, dryRun: false };
91
+ });
89
92
  });
90
93
  }
@@ -1,5 +1,6 @@
1
1
  import { isAnonymousSessionUser } from "../engine/system-user.js";
2
- import { AccessDeniedError, UnauthenticatedError } from "../errors/index.js";
2
+ import { UnauthenticatedError } from "../errors/classes.js";
3
+ import { AccessDeniedError } from "../errors/index.js";
3
4
  // Anonymous callers get 401 so a client whose session lapsed (browser dropped
4
5
  // the expired auth cookie) can tell "sign in again" apart from "signed in but
5
6
  // not allowed", which stays 403.
@@ -1,9 +1,8 @@
1
- import type { TenantId } from "../engine/types/identifiers.ts";
2
- import type { MemberReader, SessionUser } from "../engine/types/index.ts";
1
+ import type { MemberReader } from "@cosmicdrift/kumiko-types/handlers";
2
+ import type { HandlerAuth } from "../engine/types/index.ts";
3
3
  import type { HandlerContextScope } from "./handler-context-scope.ts";
4
4
  export declare function buildAuthFacet(scope: HandlerContextScope): {
5
- resolveAuthClaims: (claimsUser: SessionUser) => Promise<Record<string, unknown>>;
6
- resolveActiveMembership: (userId: string, tenantId: TenantId) => Promise<import("@cosmicdrift/kumiko-types/handlers").ActiveMembershipResult>;
7
- queryAsMember: MemberReader;
8
- hasFeature: (featureName: string) => Promise<boolean>;
5
+ readonly auth: HandlerAuth;
6
+ readonly queryAsMember: MemberReader;
7
+ readonly hasFeature: (featureName: string) => Promise<boolean>;
9
8
  };
@@ -12,13 +12,13 @@ export function buildAuthFacet(scope) {
12
12
  ungatedMemberReader ??= createMemberReaderFn(ctx, user.tenantId, tx);
13
13
  return ungatedMemberReader(userId, qn, payload);
14
14
  }, { ...identitySwitchAudit, tenantId: user.tenantId });
15
- return {
15
+ const auth = {
16
16
  // Thin pass-through: one resolve impl lives on the dispatcher, the
17
17
  // handler surface just forwards the call so both entry points (login
18
- // handler via ctx.resolveAuthClaims, switch-tenant route via
18
+ // handler via ctx.auth.resolveClaims, switch-tenant route via
19
19
  // dispatcher.resolveAuthClaims) cannot drift.
20
- resolveAuthClaims: (claimsUser) => resolveAuthClaimsFn(ctx, claimsUser), // @wrapper-known semantic-alias
21
- // Thin pass-through, same reasoning as resolveAuthClaims above — one
20
+ resolveClaims: (claimsUser) => resolveAuthClaimsFn(ctx, claimsUser), // @wrapper-known semantic-alias
21
+ // Thin pass-through, same reasoning as resolveClaims above — one
22
22
  // resolve impl lives on the dispatcher so callers can't drift apart.
23
23
  // Internally queries memberships as SYSTEM, so it needs the same grant
24
24
  // as a SYSTEM queryAs/writeAs (r.systemScope() or escapeHatch).
@@ -27,6 +27,9 @@ export function buildAuthFacet(scope) {
27
27
  throw systemIdentitySwitchDenied(`handler "${type}"`);
28
28
  return resolveActiveMembershipFn(ctx, userId, tenantId, INTERACTIVE_SIGN_IN_POLICY); // @wrapper-known semantic-alias
29
29
  },
30
+ };
31
+ return {
32
+ auth,
30
33
  // Needs the same grant as a SYSTEM queryAs.
31
34
  queryAsMember,
32
35
  // Feature-effective check for in-handler opt-in logic. Scope:
@@ -1,14 +1,11 @@
1
+ import type { ConfigAccessor } from "@cosmicdrift/kumiko-types/config";
1
2
  import { type TenantDb } from "../db/tenant-db.ts";
2
3
  import type { TenantId } from "../engine/types/identifiers.ts";
3
- import type { ConfigAccessor } from "../engine/types/index.ts";
4
4
  import { createTzContext } from "../time/index.ts";
5
5
  import type { HandlerContextScope } from "./handler-context-scope.ts";
6
6
  export declare function buildConfigFacet(scope: HandlerContextScope, db: TenantDb | undefined): {
7
7
  config: ConfigAccessor | undefined;
8
- fragment: {
9
- config?: ConfigAccessor | undefined;
10
- configFor?: ((targetTenantId: TenantId) => ConfigAccessor) | undefined;
11
- };
8
+ configFor: ((targetTenantId: TenantId) => ConfigAccessor) | undefined;
12
9
  };
13
10
  export declare function resolveHandlerTz(scope: HandlerContextScope, config: ConfigAccessor | undefined): Promise<ReturnType<typeof createTzContext>>;
14
11
  export declare function resolveHandlerLocale(scope: HandlerContextScope): string;
@@ -18,7 +18,7 @@ function buildConfigFor(scope, configFactory, config) {
18
18
  return config;
19
19
  if (!isSystemIdentity(user) && !user.roles.includes("SystemAdmin")) {
20
20
  throw new AccessDeniedError({
21
- message: "ctx.configFor(otherTenant) requires the system role or SystemAdmin",
21
+ message: "ctx.tenants.config(otherTenant) requires the system role or SystemAdmin",
22
22
  details: { reason: "config_for_requires_system_admin" },
23
23
  });
24
24
  }
@@ -50,7 +50,7 @@ export function buildConfigFacet(scope, db) {
50
50
  })
51
51
  : undefined;
52
52
  const configFor = buildConfigFor(scope, configFactory, config);
53
- return { config, fragment: { ...(config && { config }), ...(configFor && { configFor }) } };
53
+ return { config, configFor };
54
54
  }
55
55
  async function readTenantTimezone(scope, config) {
56
56
  const { ctx, user, tx } = scope;
@@ -1,23 +1,48 @@
1
+ import type { TenantWriteTarget } from "@cosmicdrift/kumiko-types/handlers";
1
2
  import type { DbConnection, DbTx } from "../db/connection.ts";
2
3
  import { type TenantDb } from "../db/tenant-db.ts";
3
4
  import type { TenantId } from "../engine/types/identifiers.ts";
4
- import type { TenantWriteTarget } from "../engine/types/index.ts";
5
5
  import type { HandlerContextScope } from "./handler-context-scope.ts";
6
6
  export declare function buildTenantScopedDb(scope: HandlerContextScope, source: DbConnection | DbTx, signal: AbortSignal | undefined, foreignTenantId?: TenantId, denyWrites?: boolean): TenantDb;
7
7
  export declare function buildHandlerDbFacet(scope: HandlerContextScope): {
8
8
  db: TenantDb | undefined;
9
- exposedDb: TenantDb | undefined;
9
+ exposedDb: ({
10
+ readonly tenantId: TenantId;
11
+ readonly mode: import("@cosmicdrift/kumiko-types/tenant-db-types").TenantDbMode;
12
+ unsafeRaw(): import("@cosmicdrift/kumiko-types/db-connection").DbRunner;
13
+ global<TTable extends (import("@cosmicdrift/kumiko-types/schema-table-types").SchemaTable | import("@cosmicdrift/kumiko-types/entity-table-meta-types").EntityTableMeta) & import("@cosmicdrift/kumiko-types/tenancy-brand").TenancyBrand<"global">>(table: TTable): import("@cosmicdrift/kumiko-types/tenant-db-types").GlobalTableDb<TTable>;
14
+ selectMany<T = Record<string, unknown>>(table: import("@cosmicdrift/kumiko-types/schema-table-types").SchemaTable | import("@cosmicdrift/kumiko-types/entity-table-meta-types").EntityTableMeta, where?: import("@cosmicdrift/kumiko-types/where-clause-types").WhereObject, options?: import("@cosmicdrift/kumiko-types/where-clause-types").SelectOptions): Promise<readonly T[]>;
15
+ fetchOne<T = Record<string, unknown>>(table: import("@cosmicdrift/kumiko-types/schema-table-types").SchemaTable | import("@cosmicdrift/kumiko-types/entity-table-meta-types").EntityTableMeta, where: import("@cosmicdrift/kumiko-types/where-clause-types").WhereObject): Promise<T | undefined>;
16
+ count(table: import("@cosmicdrift/kumiko-types/schema-table-types").SchemaTable | import("@cosmicdrift/kumiko-types/entity-table-meta-types").EntityTableMeta, where?: import("@cosmicdrift/kumiko-types/where-clause-types").WhereObject): Promise<number>;
17
+ advisoryXactLock(namespace: number, key: string): Promise<void>;
18
+ databaseNow(): Promise<Date>;
19
+ aggregate(table: import("@cosmicdrift/kumiko-types/schema-table-types").SchemaTable | import("@cosmicdrift/kumiko-types/entity-table-meta-types").EntityTableMeta, spec: import("@cosmicdrift/kumiko-types/aggregate-types").AggregateSpec, where?: import("@cosmicdrift/kumiko-types/where-clause-types").WhereObject): Promise<readonly import("@cosmicdrift/kumiko-types/aggregate-types").AggregateRow[]>;
20
+ upsert<T = Record<string, unknown>>(table: import("@cosmicdrift/kumiko-types/executor-brand").WritableTable, values: Record<string, unknown>, options: import("@cosmicdrift/kumiko-types/tenant-db-types").TenantDbUpsertOptions): Promise<T | undefined>;
21
+ } & import("@cosmicdrift/kumiko-types/tenant-db-types").TenantDbWrites<import("@cosmicdrift/kumiko-types/executor-brand").WritableTable> & {
22
+ readonly outsideTransaction: TenantDb | undefined;
23
+ }) | undefined;
10
24
  outsideTxSource: DbConnection | undefined;
11
25
  fragment: {
12
- db: TenantDb | undefined;
13
- dbOutsideTransaction: TenantDb | undefined;
26
+ db: ({
27
+ readonly tenantId: TenantId;
28
+ readonly mode: import("@cosmicdrift/kumiko-types/tenant-db-types").TenantDbMode;
29
+ unsafeRaw(): import("@cosmicdrift/kumiko-types/db-connection").DbRunner;
30
+ global<TTable extends (import("@cosmicdrift/kumiko-types/schema-table-types").SchemaTable | import("@cosmicdrift/kumiko-types/entity-table-meta-types").EntityTableMeta) & import("@cosmicdrift/kumiko-types/tenancy-brand").TenancyBrand<"global">>(table: TTable): import("@cosmicdrift/kumiko-types/tenant-db-types").GlobalTableDb<TTable>;
31
+ selectMany<T = Record<string, unknown>>(table: import("@cosmicdrift/kumiko-types/schema-table-types").SchemaTable | import("@cosmicdrift/kumiko-types/entity-table-meta-types").EntityTableMeta, where?: import("@cosmicdrift/kumiko-types/where-clause-types").WhereObject, options?: import("@cosmicdrift/kumiko-types/where-clause-types").SelectOptions): Promise<readonly T[]>;
32
+ fetchOne<T = Record<string, unknown>>(table: import("@cosmicdrift/kumiko-types/schema-table-types").SchemaTable | import("@cosmicdrift/kumiko-types/entity-table-meta-types").EntityTableMeta, where: import("@cosmicdrift/kumiko-types/where-clause-types").WhereObject): Promise<T | undefined>;
33
+ count(table: import("@cosmicdrift/kumiko-types/schema-table-types").SchemaTable | import("@cosmicdrift/kumiko-types/entity-table-meta-types").EntityTableMeta, where?: import("@cosmicdrift/kumiko-types/where-clause-types").WhereObject): Promise<number>;
34
+ advisoryXactLock(namespace: number, key: string): Promise<void>;
35
+ databaseNow(): Promise<Date>;
36
+ aggregate(table: import("@cosmicdrift/kumiko-types/schema-table-types").SchemaTable | import("@cosmicdrift/kumiko-types/entity-table-meta-types").EntityTableMeta, spec: import("@cosmicdrift/kumiko-types/aggregate-types").AggregateSpec, where?: import("@cosmicdrift/kumiko-types/where-clause-types").WhereObject): Promise<readonly import("@cosmicdrift/kumiko-types/aggregate-types").AggregateRow[]>;
37
+ upsert<T = Record<string, unknown>>(table: import("@cosmicdrift/kumiko-types/executor-brand").WritableTable, values: Record<string, unknown>, options: import("@cosmicdrift/kumiko-types/tenant-db-types").TenantDbUpsertOptions): Promise<T | undefined>;
38
+ } & import("@cosmicdrift/kumiko-types/tenant-db-types").TenantDbWrites<import("@cosmicdrift/kumiko-types/executor-brand").WritableTable> & {
39
+ readonly outsideTransaction: TenantDb | undefined;
40
+ }) | undefined;
14
41
  systemDb?: import("@cosmicdrift/kumiko-types/tenant-db-types").UncheckedSystemDb | undefined;
15
42
  crossTenantReads?: import("@cosmicdrift/kumiko-types/tenant-db-types").CrossTenantReads | undefined;
16
43
  };
17
44
  };
18
- export declare function buildForTenantFragment(scope: HandlerContextScope, exposedDb: TenantDb | undefined, readOnlyForTenant: boolean): {
19
- forTenant?: ((targetTenantId: TenantId) => TenantWriteTarget) | undefined;
20
- };
45
+ export declare function buildWriteTarget(scope: HandlerContextScope, exposedDb: TenantDb | undefined, readOnlyForTenant: boolean): ((targetTenantId: TenantId) => TenantWriteTarget) | undefined;
21
46
  export declare function buildFileFragment(scope: HandlerContextScope, db: TenantDb | undefined): {
22
47
  files?: import("@cosmicdrift/kumiko-types/file-handle-types").FileContext | undefined;
23
48
  derivatives?: import("@cosmicdrift/kumiko-types/derivatives-types").DerivativesContext | undefined;
@@ -1,19 +1,19 @@
1
1
  import { crossTenantReadsGrantFor, escapeHatchFor } from "@cosmicdrift/kumiko-types/handlers";
2
- import { isAgentToolCallScope } from "../api/request-context.js";
2
+ import { isAgentToolCallScope } from "../api/request-context-scopes.js";
3
3
  import { createHandlerCrossTenantReads } from "../db/cross-tenant-reads.js";
4
4
  import { createTenantDb, createUncheckedSystemDb } from "../db/tenant-db.js";
5
5
  import { createDerivativesContext } from "../derivatives/derivatives-context.js";
6
6
  import { mayOverrideTenant } from "../engine/cross-tenant.js";
7
7
  import { AccessDeniedError, FrameworkReasons } from "../errors/index.js";
8
8
  import { createTenantFileContext } from "../files/file-handle.js";
9
+ import { attachOutsideTransaction } from "./attach-outside-transaction.js";
9
10
  import { createSystemScopedDbGuard, isMemberResolutionPrincipal, resolveAppPoolDb, } from "./dispatch-shared.js";
10
11
  import { buildPersonalDataGate } from "./write-origin.js";
11
12
  export function buildTenantScopedDb(scope, source, signal, foreignTenantId, denyWrites = false) {
12
13
  const { user, context, registry, origin, isSystem, writeEscapeHatch, handlerEscapeHatch } = scope;
13
- return createTenantDb({
14
+ const options = {
14
15
  db: source,
15
16
  tenantId: foreignTenantId ?? user.tenantId,
16
- mode: isSystem && foreignTenantId === undefined ? "system" : "tenant",
17
17
  tracer: context.tracer,
18
18
  meter: context.meter,
19
19
  signal,
@@ -28,7 +28,14 @@ export function buildTenantScopedDb(scope, source, signal, foreignTenantId, deny
28
28
  projectionRegistry: registry,
29
29
  ...(denyWrites && { writesDeniedReason: "without an open transaction" }),
30
30
  },
31
- });
31
+ };
32
+ return isSystem && foreignTenantId === undefined
33
+ ? createTenantDb({
34
+ ...options,
35
+ mode: "system",
36
+ reason: "system-scope handler dispatch reads and writes across tenants by design",
37
+ })
38
+ : createTenantDb(options);
32
39
  }
33
40
  function buildHandlerCrossTenantReads(scope) {
34
41
  const { user, context, registry, origin, dbSource, reqCtx, handlerEscapeHatch } = scope;
@@ -77,26 +84,28 @@ export function buildHandlerDbFacet(scope) {
77
84
  ? createUncheckedSystemDb(db, rawDbOutsideTransaction, scope.reportEscapeHatch)
78
85
  : undefined;
79
86
  const crossTenantReads = buildHandlerCrossTenantReads(scope);
87
+ // Same fail-closed treatment as `exposedDb` — a system handler reaching
88
+ // ctx.db.outsideTransaction directly would be a second, unguarded door to
89
+ // the same cross-tenant access ctx.db closes off.
90
+ const dbOutsideTransaction = isSystem && rawDbOutsideTransaction
91
+ ? createSystemScopedDbGuard(type, "db.outsideTransaction", "ctx.systemDb.outsideTransaction.assertTenantMatch(...) or " +
92
+ "ctx.systemDb.outsideTransaction.acknowledgeCrossTenant(...)")
93
+ : rawDbOutsideTransaction;
80
94
  // Exposed as ctx.db below — the internal `db` above stays the real,
81
95
  // working TenantDb for config/derivatives accessors and systemDb
82
96
  // construction.
83
- const exposedDb = isSystem && db
97
+ const unattachedExposedDb = isSystem && db
84
98
  ? createSystemScopedDbGuard(type, "db", "ctx.systemDb.assertTenantMatch(...) or ctx.systemDb.acknowledgeCrossTenant(...)")
85
99
  : db;
86
- // Same fail-closed treatment as `exposedDb` — a system handler reaching
87
- // ctx.dbOutsideTransaction directly would be a second, unguarded door to
88
- // the same cross-tenant access ctx.db closes off above.
89
- const dbOutsideTransaction = isSystem && rawDbOutsideTransaction
90
- ? createSystemScopedDbGuard(type, "dbOutsideTransaction", "ctx.systemDb.outsideTransaction.assertTenantMatch(...) or " +
91
- "ctx.systemDb.outsideTransaction.acknowledgeCrossTenant(...)")
92
- : rawDbOutsideTransaction;
100
+ const exposedDb = unattachedExposedDb
101
+ ? attachOutsideTransaction(unattachedExposedDb, dbOutsideTransaction)
102
+ : undefined;
93
103
  return {
94
104
  db,
95
105
  exposedDb,
96
106
  outsideTxSource,
97
107
  fragment: {
98
108
  db: exposedDb,
99
- dbOutsideTransaction,
100
109
  ...(systemDb && { systemDb }),
101
110
  ...(crossTenantReads && { crossTenantReads }),
102
111
  },
@@ -106,7 +115,7 @@ export function buildHandlerDbFacet(scope) {
106
115
  // dispatcher's tenantIdOverride predicate, so no caller reaches more than it could via
107
116
  // tenantIdOverride. The foreign db carries no unsafeRaw/globalWrites grant and is tenant mode
108
117
  // bound to the target; the executor accepts streamTenantId only on a db bound to that tenant.
109
- export function buildForTenantFragment(scope, exposedDb, readOnlyForTenant) {
118
+ export function buildWriteTarget(scope, exposedDb, readOnlyForTenant) {
110
119
  const { user, isSystem, dbSource, isWriteHandler, reqCtx, denyDbWrites, isPerCommand } = scope;
111
120
  const forTenant = !isSystem && dbSource && isWriteHandler
112
121
  ? (targetTenantId) => {
@@ -128,9 +137,9 @@ export function buildForTenantFragment(scope, exposedDb, readOnlyForTenant) {
128
137
  };
129
138
  }
130
139
  : undefined;
131
- return { ...(forTenant && { forTenant }) };
140
+ return forTenant;
132
141
  }
133
- // ctx.files resolved per-tenant through file-foundation (lazy — the
142
+ // ctx.services.files resolved per-tenant through file-foundation (lazy — the
134
143
  // provider is only resolved when a handle actually does I/O). Boot wires
135
144
  // _fileProviderResolver when a file-provider plugin is mounted; falls back
136
145
  // to a statically-injected context.files (tests).
@@ -138,7 +147,7 @@ export function buildFileFragment(scope, db) {
138
147
  const { context, registry, user } = scope;
139
148
  const fileResolver = context._fileProviderResolver;
140
149
  const files = fileResolver ? createTenantFileContext(fileResolver, user.tenantId) : context.files;
141
- // ctx.derivatives builds on ctx.files (needs a FileContext to read the
150
+ // ctx.services.derivatives builds on ctx.services.files (needs a FileContext to read the
142
151
  // original + write the variant) plus db (to look up the FileRef row) — so
143
152
  // it can only be constructed exactly when files+db both resolved; falls
144
153
  // back to a statically-injected context.derivatives otherwise (tests).
@@ -1,5 +1,7 @@
1
- import type { WriteResult } from "../engine/types/index.ts";
2
- import { type HandlerTransactionScope } from "./dispatch-shared.ts";
1
+ import type { WriteResult } from "@cosmicdrift/kumiko-types/handlers";
2
+ import type { HandlerDispatch } from "../engine/types/index.ts";
3
+ import { type AfterRollbackHook } from "./after-rollback-sink.ts";
4
+ import type { HandlerTransactionScope } from "./dispatch-shared.ts";
3
5
  import { type AfterCommitHook } from "./dispatcher-utils.ts";
4
6
  import type { HandlerContextScope } from "./handler-context-scope.ts";
5
7
  export type CommitSinks = {
@@ -8,14 +10,20 @@ export type CommitSinks = {
8
10
  readonly notifyCommitSink: AfterCommitHook[] | undefined;
9
11
  };
10
12
  export declare function createCommitSinks(afterCommitHooks: AfterCommitHook[] | undefined, transactionScope: HandlerTransactionScope, outerNotifySink: AfterCommitHook[] | undefined): CommitSinks;
11
- export declare function buildDispatchFacet(scope: HandlerContextScope, sinks: CommitSinks): {
12
- bridge: {
13
+ export type DispatchFacetInput = Pick<HandlerDispatch, "queryAsMember" | "queryProjection">;
14
+ export declare function buildDispatchFacet(scope: HandlerContextScope, sinks: CommitSinks, readers: DispatchFacetInput): {
15
+ dispatch: {
16
+ queryAsMember: import("@cosmicdrift/kumiko-types/handlers").MemberReader;
17
+ queryProjection: <T = Record<string, unknown>>(qualifiedName: string, options?: {
18
+ readonly unsafeAllTenants?: boolean;
19
+ }) => Promise<readonly T[]>;
13
20
  query: (targetType: string, payload: unknown) => Promise<unknown>;
14
21
  queryAs: import("./system-identity-switch.ts").QueryAsFn;
15
22
  write: (targetType: string, payload: unknown) => Promise<WriteResult>;
16
23
  writeAs: import("./system-identity-switch.ts").WriteAsFn;
17
24
  };
18
- scheduleFragment: {
19
- scheduleAfterCommit?: ((hook: AfterCommitHook) => void) | undefined;
25
+ commitHooks: {
26
+ afterCommit?: ((hook: AfterCommitHook) => void) | undefined;
27
+ afterRollback?: ((hook: AfterRollbackHook) => void) | undefined;
20
28
  };
21
29
  };
@@ -1,13 +1,15 @@
1
+ import { runWithWriteOrigin } from "../api/request-context-scopes.js";
1
2
  import { runInSavepoint } from "../db/query.js";
2
3
  import { writeFailure } from "../errors/index.js";
4
+ import { afterRollbackHooksOf, carrySavepointRollbackHooks, } from "./after-rollback-sink.js";
3
5
  import { runBatch, unwrapSingle } from "./dispatch-batch.js";
4
6
  import { executeQuery } from "./dispatch-query.js";
5
- import { perCommandNestedDenied } from "./dispatch-shared.js";
6
7
  import { executeWrite } from "./dispatch-write.js";
7
8
  import { isFailedWriteResult, NestedWriteRollback, } from "./dispatcher-utils.js";
9
+ import { perCommandNestedDenied } from "./handler-context-phase-denials.js";
8
10
  import { createGatedIdentitySwitch } from "./system-identity-switch.js";
9
11
  export function createCommitSinks(afterCommitHooks, transactionScope, outerNotifySink) {
10
- // Cross-feature bridge: ctx.query/write share the current tx + afterCommitHooks sink.
12
+ // Cross-feature bridge: ctx.dispatch.query/write share the current tx + afterCommitHooks sink.
11
13
  // queryAs/writeAs to anyone but the caller itself needs r.systemScope() or { escapeHatch } (system-identity-switch.ts).
12
14
  const bridgeSink = afterCommitHooks ?? [];
13
15
  // Query bridges and post-commit contexts get a throwaway sink: hooks pushed there never run.
@@ -40,9 +42,11 @@ async function runNestedWriteInSavepoint(scope, sinks, asUser, targetType, paylo
40
42
  return innerResult;
41
43
  });
42
44
  bridgeSink.push(...innerAfterCommitHooks);
45
+ carrySavepointRollbackHooks(innerAfterCommitHooks, bridgeSink, false);
43
46
  return result;
44
47
  }
45
48
  catch (e) {
49
+ carrySavepointRollbackHooks(innerAfterCommitHooks, bridgeSink, true);
46
50
  if (e instanceof NestedWriteRollback)
47
51
  return e.failure;
48
52
  throw e;
@@ -59,11 +63,14 @@ function createSerializedNestedWriter(scope, sinks) {
59
63
  return run;
60
64
  };
61
65
  }
62
- export function buildDispatchFacet(scope, sinks) {
66
+ export function buildDispatchFacet(scope, sinks, readers) {
63
67
  const { ctx, type, user, origin, tx, transactionScope, hasIdentitySwitchGrant, identitySwitchAudit, } = scope;
64
68
  const scheduleAfterCommit = (hook) => {
65
69
  sinks.bridgeSink.push(hook);
66
70
  };
71
+ const scheduleAfterRollback = (hook) => {
72
+ afterRollbackHooksOf(sinks.bridgeSink).push(() => runWithWriteOrigin(origin, hook));
73
+ };
67
74
  const executeNestedWriteInSavepoint = createSerializedNestedWriter(scope, sinks);
68
75
  // Without an open transaction (post-commit hooks, stream/query handlers, perCommand handlers) a bare
69
76
  // executeWrite would auto-commit event append, projections and inTransaction hooks separately and its
@@ -78,12 +85,18 @@ export function buildDispatchFacet(scope, sinks) {
78
85
  writeAs: writeAsUser,
79
86
  }, identitySwitchAudit);
80
87
  return {
81
- bridge: {
88
+ dispatch: {
89
+ ...readers,
82
90
  query: (targetType, payload) => executeQuery(ctx, targetType, payload, user, origin, tx, sinks.notifyCommitSink), // @wrapper-known semantic-alias
83
91
  queryAs: identitySwitch.queryAs,
84
92
  write: (targetType, payload) => writeAsUser(user, targetType, payload),
85
93
  writeAs: identitySwitch.writeAs,
86
94
  },
87
- scheduleFragment: { ...(sinks.hasLiveCommitSink && { scheduleAfterCommit }) },
95
+ commitHooks: {
96
+ ...(sinks.hasLiveCommitSink && { afterCommit: scheduleAfterCommit }),
97
+ // perCommand and no-tx paths have earlier commands already committed: nothing to compensate on rollback.
98
+ ...(sinks.hasLiveCommitSink &&
99
+ transactionScope === "inTransaction" && { afterRollback: scheduleAfterRollback }),
100
+ },
88
101
  };
89
102
  }