@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
@@ -12,6 +12,7 @@ import { IdempotentAppendConflictError, SeedTimeOrderError, VersionConflictError
12
12
  import { eventsTable } from "./events-schema.js";
13
13
  import { toStoredEvent } from "./row-to-stored-event.js";
14
14
  import { currentSeedCreatedAt } from "./seed-clock.js";
15
+ import { inEventStreamScope } from "./stream-scope.js";
15
16
  // Append one event atomically. Two guarantees combined:
16
17
  //
17
18
  // 1. UNIQUE (tenant_id, aggregate_id, version) serializes concurrent writers
@@ -51,7 +52,7 @@ export async function append(db, event) {
51
52
  const newVersion = toStore.expectedVersion + 1;
52
53
  const eventVersion = toStore.eventVersion ?? 1;
53
54
  try {
54
- const row = await runAtomicEventWrite(db, async (runner) => {
55
+ const row = await inEventStreamScope(toStore.tenantId, () => runAtomicEventWrite(db, async (runner) => {
55
56
  await claimXactId(runner);
56
57
  // Inside the write transaction so a concurrent live append cannot slip
57
58
  // between the check and the insert.
@@ -65,7 +66,7 @@ export async function append(db, event) {
65
66
  // commit, so the dispatcher cannot wake before the row is visible.
66
67
  await notifyPgChannel(runner, EVENTS_PUBSUB_CHANNEL);
67
68
  return inserted;
68
- });
69
+ }));
69
70
  return buildStoredEvent(toStore, newVersion, eventVersion, row);
70
71
  }
71
72
  catch (e) {
@@ -208,15 +209,20 @@ export async function loadAggregate(db, aggregateId, tenantId, options) {
208
209
  if (options?.aggregateType === "") {
209
210
  throw new Error("loadAggregate: aggregateType must be a non-empty string when provided");
210
211
  }
211
- if (!options?.includeArchived) {
212
- const archived = await isStreamArchived(db, tenantId, aggregateId);
213
- if (archived)
214
- return [];
215
- }
216
- const rows = await selectMany(db, eventsTable, options?.aggregateType !== undefined
217
- ? { aggregateId, tenantId, aggregateType: options.aggregateType }
218
- : { aggregateId, tenantId }, { orderBy: { col: "version", direction: "asc" } });
219
- return rows.map(toStoredEvent);
212
+ return inEventStreamScope(tenantId, async () => {
213
+ if (!options?.includeArchived) {
214
+ const archived = await isStreamArchived(db, tenantId, aggregateId);
215
+ if (archived)
216
+ return [];
217
+ }
218
+ const rows = await selectMany(db, eventsTable, {
219
+ aggregateId,
220
+ tenantId,
221
+ ...(options?.aggregateType !== undefined && { aggregateType: options.aggregateType }),
222
+ ...(options?.atVersion !== undefined && { version: options.atVersion }),
223
+ }, { orderBy: { col: "version", direction: "asc" } });
224
+ return rows.map(toStoredEvent);
225
+ });
220
226
  }
221
227
  // Events and the stream's latest version from ONE read, so both come from the same
222
228
  // snapshot: a commit landing between two separate statements would leave the caller
@@ -227,40 +233,44 @@ export async function loadAggregateForWriting(db, aggregateId, tenantId, options
227
233
  if (options.aggregateType === "") {
228
234
  throw new Error("loadAggregateForWriting: aggregateType must be a non-empty string");
229
235
  }
230
- if (await isStreamArchived(db, tenantId, aggregateId)) {
231
- return { events: [], streamVersion: await getStreamVersion(db, aggregateId, tenantId) };
232
- }
233
- const rows = await selectMany(db, eventsTable, { aggregateId, tenantId }, { orderBy: { col: "version", direction: "asc" } });
234
- const all = rows.map(toStoredEvent);
235
- return {
236
- events: all.filter((e) => e.aggregateType === options.aggregateType),
237
- streamVersion: all.at(-1)?.version ?? 0,
238
- };
236
+ return inEventStreamScope(tenantId, async () => {
237
+ if (await isStreamArchived(db, tenantId, aggregateId)) {
238
+ return { events: [], streamVersion: await getStreamVersion(db, aggregateId, tenantId) };
239
+ }
240
+ const rows = await selectMany(db, eventsTable, { aggregateId, tenantId }, { orderBy: { col: "version", direction: "asc" } });
241
+ const all = rows.map(toStoredEvent);
242
+ return {
243
+ events: all.filter((e) => e.aggregateType === options.aggregateType),
244
+ streamVersion: all.at(-1)?.version ?? 0,
245
+ };
246
+ });
239
247
  }
240
248
  // Load events up to a point in time. Used for asOf queries that reconstruct
241
249
  // historical state. Includes events whose created_at is <= asOf. Same
242
250
  // archive semantics as loadAggregate.
243
251
  export async function loadAggregateAsOf(db, aggregateId, tenantId, asOf, options) {
244
- if (!options?.includeArchived) {
245
- const archived = await isStreamArchived(db, tenantId, aggregateId);
246
- if (archived)
247
- return [];
248
- }
249
- const rows = await selectMany(db, eventsTable, { aggregateId, tenantId, createdAt: { lte: asOf } }, { orderBy: { col: "version", direction: "asc" } });
250
- return rows.map(toStoredEvent);
252
+ return inEventStreamScope(tenantId, async () => {
253
+ if (!options?.includeArchived) {
254
+ const archived = await isStreamArchived(db, tenantId, aggregateId);
255
+ if (archived)
256
+ return [];
257
+ }
258
+ const rows = await selectMany(db, eventsTable, { aggregateId, tenantId, createdAt: { lte: asOf } }, { orderBy: { col: "version", direction: "asc" } });
259
+ return rows.map(toStoredEvent);
260
+ });
251
261
  }
252
262
  // Cheapest possible read of "what's the latest version on this stream?". The
253
263
  // CRUD executor uses this as expectedVersion for its append, so a domain
254
- // event appended via ctx.appendEvent between two CRUD writes doesn't cause
264
+ // event appended via ctx.events.append between two CRUD writes doesn't cause
255
265
  // the next CRUD write to fail with version_conflict. Indexed lookup on the
256
266
  // existing (aggregate_id, version) unique index. Returns 0 for empty/unknown
257
267
  // streams (matches create()'s expectedVersion=0 convention).
258
268
  // @wrapper-known semantic-alias
259
269
  export async function getStreamVersion(db, aggregateId, tenantId) {
260
- return selectStreamMaxVersion(db, aggregateId, tenantId);
270
+ return inEventStreamScope(tenantId, () => selectStreamMaxVersion(db, aggregateId, tenantId));
261
271
  }
262
272
  export async function getStreamVersions(db, aggregateIds, tenantId) {
263
- return selectStreamMaxVersions(db, aggregateIds, tenantId);
273
+ return inEventStreamScope(tenantId, () => selectStreamMaxVersions(db, aggregateIds, tenantId));
264
274
  }
265
275
  /** MAX(version) for one aggregate — no tenant filter. SECURITY: existence-oracle,
266
276
  * a caller can probe whether an aggregateId has any events regardless of tenant
@@ -307,11 +317,11 @@ export async function loadEventsAfterVersion(db, aggregateId, tenantId, afterVer
307
317
  // The caller may pause / do async work between yields; the next batch is
308
318
  // only fetched when consumed.
309
319
  //
310
- // Cancellation: pass `signal` (typically `ctx.signal` from a handler) to
320
+ // Cancellation: pass `signal` (typically `ctx.lifecycle.signal` from a handler) to
311
321
  // abort iteration. Checked both at batch boundaries (before the next
312
322
  // fetch) AND between yields (so abort lands within one event regardless
313
323
  // of batch size). Throws AbortError on the first check after abort;
314
- // in-flight queries are not actively cancelled (postgres-js connection-
324
+ // in-flight queries are not actively cancelled (connection
315
325
  // cancel is a separate, riskier concern handled per-query at the TenantDb
316
326
  // boundary).
317
327
  export async function* streamAllEventsByType(db, aggregateType, batchSize = 1000, signal) {
@@ -2,7 +2,7 @@
2
2
  import { bigserial, index, instant, integer, jsonb, table as pgTable, sql, text, uniqueIndex, uuid, } from "../db/dialect.js";
3
3
  import { tableExists } from "../db/index.js";
4
4
  import { ensureIdempotencyKeyIndex, ensureMembershipPayloadTenantIndex, } from "../db/queries/event-store.js";
5
- import { unsafePushTables } from "../db/table-push.js";
5
+ import { ensureTableRowLevelSecurity, unsafePushTables } from "../db/table-push.js";
6
6
  import { createArchivedStreamsTable } from "./archive.js";
7
7
  import { createSnapshotsTable } from "./snapshot.js";
8
8
  // Event-store schema as a Drizzle table. The typed select/insert path handles
@@ -57,6 +57,9 @@ export async function createEventsTable(db) {
57
57
  if (!(await tableExists(db, "public.kumiko_events"))) {
58
58
  await unsafePushTables(db, { kumikoEvents: eventsTable });
59
59
  }
60
+ else {
61
+ await ensureTableRowLevelSecurity(db, eventsTable);
62
+ }
60
63
  // Runs unconditionally (both fresh + already-existing table) so installs
61
64
  // that predate the idempotency-key index get healed the same way
62
65
  // ensureSnapshotVersionColumn heals kumiko_snapshots.
@@ -1,16 +1,14 @@
1
1
  export { APP_INSTANCE_STREAM_TYPE, APP_STARTED_EVENT_TYPE } from "../crypto/system-event-pii.ts";
2
- export { backfillEventPiiEncryption, backfillEventPiiEncryptionBatch, type PiiBackfillBatchOptions, type PiiBackfillBatchResult, type PiiBackfillFailure, type PiiBackfillOptions, type PiiBackfillResult, type PiiBackfillScanCache, } from "../db/queries/backfill-pii.ts";
3
- export { type DeleteRowsWithoutReplayableStreamArgs, deleteRowsWithoutReplayableStream, } from "../db/queries/event-store-orphan-rows.ts";
4
- export { type ArchiveStreamArgs, archivedStreamsTable, archiveStream, createArchivedStreamsTable, isStreamArchived, restoreStream, } from "./archive.ts";
5
- export { ArchivedStreamError, IdempotentAppendConflictError, SeedTimeOrderError, VersionConflictError, } from "./errors.ts";
6
- export { append, EVENTS_PUBSUB_CHANNEL, type EventMetadata, type EventToAppend, getEventsHighWaterMark, getStreamVersion, getStreamVersions, getUnscopedAggregateStreamMaxVersion, getUnscopedStreamMaxVersionForSeed, loadAggregate, loadAggregateAsOf, loadEventsAfterVersion, type StoredEvent, streamAllEventsByType, } from "./event-store.ts";
2
+ export { backfillEventPiiEncryption, backfillEventPiiEncryptionBatch, } from "../db/queries/backfill-pii.ts";
3
+ export { deleteRowsWithoutReplayableStream } from "../db/queries/event-store-orphan-rows.ts";
4
+ export { archivedStreamsTable, archiveStream, createArchivedStreamsTable, isStreamArchived, } from "./archive.ts";
5
+ export { SeedTimeOrderError, VersionConflictError, } from "./errors.ts";
6
+ export { append, type EventMetadata, getEventsHighWaterMark, getStreamVersion, getStreamVersions, getUnscopedAggregateStreamMaxVersion, getUnscopedStreamMaxVersionForSeed, loadAggregate, type StoredEvent, streamAllEventsByType, } from "./event-store.ts";
7
7
  export { createEventsTable, eventsTable } from "./events-schema.ts";
8
- export { appendProvenanceEvent, type ProvenanceEventInput } from "./provenance-append.ts";
9
- export { createRebuildDeadLetterTable, listRebuildDeadLetters, type RebuildDeadLetterRow, rebuildDeadLetterTable, recordRebuildDeadLetters, type SkippedApply, } from "./rebuild-dead-letter.ts";
10
- export { toStoredEvent } from "./row-to-stored-event.ts";
8
+ export { appendProvenanceEvent } from "./provenance-append.ts";
11
9
  export { assertSeedModeNotInProduction, isSeedModeEnabled, runSeedWritesAt, SEED_MODE_ENV, SeedModeDisabledError, } from "./seed-clock.ts";
12
- export { createSnapshotsTable, type LoadAggregateWithSnapshotOptions, type LoadAggregateWithSnapshotResult, loadAggregateWithSnapshot, loadLatestSnapshot, type SaveSnapshotArgs, type Snapshot, type SnapshotReducer, saveSnapshot, snapshotsTable, } from "./snapshot.ts";
13
- export { type AppendEventInTenantDbOptions, appendEventInTenantDb, getStreamVersionInTenantDb, } from "./tenant-db-append.ts";
14
- export { AGGREGATE_TRANSFER_STREAM_TYPE, AGGREGATE_TRANSFERRED_EVENT_TYPE, type TransferAggregateStreamsArgs, transferAggregateStreams, } from "./transfer.ts";
15
- export { type EventUpcasters, makeUpcastCtx, type UpcasterErrorPolicy, type UpcastOptions, upcastStoredEvent, upcastStoredEvents, } from "./upcaster.ts";
16
- export { createUpcasterDeadLetterTable, type DeadLetterRow, listDeadLetters, recordUpcasterDeadLetter, upcasterDeadLetterTable, } from "./upcaster-dead-letter.ts";
10
+ export { snapshotsTable } from "./snapshot.ts";
11
+ export { appendEventInTenantDb, getStreamVersionInTenantDb, } from "./tenant-db-append.ts";
12
+ export { AGGREGATE_TRANSFER_STREAM_TYPE, AGGREGATE_TRANSFERRED_EVENT_TYPE, transferAggregateStreams, } from "./transfer.ts";
13
+ export { makeUpcastCtx, upcastStoredEvent, } from "./upcaster.ts";
14
+ export { upcasterDeadLetterTable } from "./upcaster-dead-letter.ts";
@@ -1,16 +1,14 @@
1
1
  export { APP_INSTANCE_STREAM_TYPE, APP_STARTED_EVENT_TYPE } from "../crypto/system-event-pii.js";
2
2
  export { backfillEventPiiEncryption, backfillEventPiiEncryptionBatch, } from "../db/queries/backfill-pii.js";
3
- export { deleteRowsWithoutReplayableStream, } from "../db/queries/event-store-orphan-rows.js";
4
- export { archivedStreamsTable, archiveStream, createArchivedStreamsTable, isStreamArchived, restoreStream, } from "./archive.js";
5
- export { ArchivedStreamError, IdempotentAppendConflictError, SeedTimeOrderError, VersionConflictError, } from "./errors.js";
6
- export { append, EVENTS_PUBSUB_CHANNEL, getEventsHighWaterMark, getStreamVersion, getStreamVersions, getUnscopedAggregateStreamMaxVersion, getUnscopedStreamMaxVersionForSeed, loadAggregate, loadAggregateAsOf, loadEventsAfterVersion, streamAllEventsByType, } from "./event-store.js";
3
+ export { deleteRowsWithoutReplayableStream } from "../db/queries/event-store-orphan-rows.js";
4
+ export { archivedStreamsTable, archiveStream, createArchivedStreamsTable, isStreamArchived, } from "./archive.js";
5
+ export { SeedTimeOrderError, VersionConflictError, } from "./errors.js";
6
+ export { append, getEventsHighWaterMark, getStreamVersion, getStreamVersions, getUnscopedAggregateStreamMaxVersion, getUnscopedStreamMaxVersionForSeed, loadAggregate, streamAllEventsByType, } from "./event-store.js";
7
7
  export { createEventsTable, eventsTable } from "./events-schema.js";
8
8
  export { appendProvenanceEvent } from "./provenance-append.js";
9
- export { createRebuildDeadLetterTable, listRebuildDeadLetters, rebuildDeadLetterTable, recordRebuildDeadLetters, } from "./rebuild-dead-letter.js";
10
- export { toStoredEvent } from "./row-to-stored-event.js";
11
9
  export { assertSeedModeNotInProduction, isSeedModeEnabled, runSeedWritesAt, SEED_MODE_ENV, SeedModeDisabledError, } from "./seed-clock.js";
12
- export { createSnapshotsTable, loadAggregateWithSnapshot, loadLatestSnapshot, saveSnapshot, snapshotsTable, } from "./snapshot.js";
10
+ export { snapshotsTable } from "./snapshot.js";
13
11
  export { appendEventInTenantDb, getStreamVersionInTenantDb, } from "./tenant-db-append.js";
14
12
  export { AGGREGATE_TRANSFER_STREAM_TYPE, AGGREGATE_TRANSFERRED_EVENT_TYPE, transferAggregateStreams, } from "./transfer.js";
15
- export { makeUpcastCtx, upcastStoredEvent, upcastStoredEvents, } from "./upcaster.js";
16
- export { createUpcasterDeadLetterTable, listDeadLetters, recordUpcasterDeadLetter, upcasterDeadLetterTable, } from "./upcaster-dead-letter.js";
13
+ export { makeUpcastCtx, upcastStoredEvent, } from "./upcaster.js";
14
+ export { upcasterDeadLetterTable } from "./upcaster-dead-letter.js";
@@ -32,7 +32,7 @@ export async function appendProvenanceEvent(db, event) {
32
32
  message: `appendProvenanceEvent: event tenant "${event.tenantId}" does not match the TenantDb's tenant "${db.tenantId}".`,
33
33
  });
34
34
  }
35
- // postgres-js aborts the whole surrounding begin() on a statement
35
+ // Postgres aborts the whole surrounding transaction on a statement
36
36
  // error (25P02) even when the caller's catch swallows it — the savepoint
37
37
  // confines that to this scope. Pool connections have no ambient tx to poison.
38
38
  await runInSavepointIfSupported(runner, async (sp) => {
@@ -14,7 +14,7 @@
14
14
  // is a separate ops step — same stance as the upcaster dead-letter.
15
15
  import { bigint, index, jsonb, table as pgTable, text, timestamp, uuid } from "../db/dialect.js";
16
16
  import { tableExists } from "../db/schema-inspection.js";
17
- import { unsafePushTables } from "../db/table-push.js";
17
+ import { ensureTableRowLevelSecurity, unsafePushTables } from "../db/table-push.js";
18
18
  export const rebuildDeadLetterTable = pgTable("kumiko_rebuild_dead_letters", {
19
19
  // Surrogate PK — the same event can land here across multiple rebuild
20
20
  // attempts before the fix ships, without unique-violation noise.
@@ -39,8 +39,10 @@ export const rebuildDeadLetterTable = pgTable("kumiko_rebuild_dead_letters", {
39
39
  // provisioned before this table existed.
40
40
  export async function createRebuildDeadLetterTable(db) {
41
41
  // skip: table already exists — bootstrap called from multiple paths
42
- if (await tableExists(db, "public.kumiko_rebuild_dead_letters"))
42
+ if (await tableExists(db, "public.kumiko_rebuild_dead_letters")) {
43
+ await ensureTableRowLevelSecurity(db, rebuildDeadLetterTable);
43
44
  return;
45
+ }
44
46
  await unsafePushTables(db, { kumikoRebuildDeadLetters: rebuildDeadLetterTable });
45
47
  }
46
48
  // Bulk-write, called ONCE at the end of a quarantining rebuild (inside its
@@ -4,7 +4,7 @@ import { index, instant, integer, jsonb, table as pgTable, primaryKey, sql, text
4
4
  import { ensureSnapshotVersionColumn, upsertSnapshot } from "../db/queries/event-store.js";
5
5
  import { selectMany } from "../db/query.js";
6
6
  import { tableExists } from "../db/schema-inspection.js";
7
- import { unsafePushTables } from "../db/table-push.js";
7
+ import { ensureTableRowLevelSecurity, unsafePushTables } from "../db/table-push.js";
8
8
  import { createFallbackLogger, scrubLogText } from "../logging/index.js";
9
9
  import { isStreamArchived } from "./archive.js";
10
10
  import { loadEventsAfterVersion } from "./event-store.js";
@@ -18,7 +18,7 @@ import { loadEventsAfterVersion } from "./event-store.js";
18
18
  // 3. loadEventsAfterVersion(aggregate, N) → only the delta
19
19
  // 4. reducer(snapshot, delta) → current state
20
20
  //
21
- // Write path: manual via ctx.snapshotAggregate, or automatic via the
21
+ // Write path: manual via ctx.events.snapshot, or automatic via the
22
22
  // { snapshotEvery: N } load option — the read path persists a fresh
23
23
  // snapshot whenever it folded at least N delta events.
24
24
  //
@@ -32,7 +32,7 @@ import { loadEventsAfterVersion } from "./event-store.js";
32
32
  //
33
33
  // Upcaster interaction: the raw API (loadAggregateWithSnapshot below) does
34
34
  // NOT apply the upcaster chain on delta events — same layering as raw
35
- // loadAggregate. The Dispatcher wraps this into ctx.loadAggregateWithSnapshot
35
+ // loadAggregate. The Dispatcher wraps this into ctx.events.loadWithSnapshot
36
36
  // and runs upcastStoredEvents on the delta before calling the reducer, so
37
37
  // feature authors always see current-version payloads.
38
38
  export const snapshotsTable = pgTable("kumiko_snapshots", {
@@ -64,6 +64,7 @@ export async function createSnapshotsTable(db) {
64
64
  // Installs that predate snapshot_version get healed by the same
65
65
  // idempotent ensure that `kumiko schema apply` / test-setup already runs.
66
66
  await ensureSnapshotVersionColumn(db);
67
+ await ensureTableRowLevelSecurity(db, snapshotsTable);
67
68
  // skip: table already ensured — only the column heal above was needed
68
69
  return;
69
70
  }
@@ -0,0 +1,2 @@
1
+ import type { TenantId } from "../engine/types/index.ts";
2
+ export declare function inEventStreamScope<T>(streamTenantId: TenantId, work: () => Promise<T>): Promise<T>;
@@ -0,0 +1,6 @@
1
+ import { runInRowLevelSecurityScope, tenantRowLevelSecurityScope, } from "../db/row-level-security-scope.js";
2
+ // A stream belongs to exactly one tenant; its rows are only writable and reliably readable in
3
+ // that tenant's scope, which differs from the caller's for systemStream entities and ctx.tenants.writeTarget.
4
+ export function inEventStreamScope(streamTenantId, work) {
5
+ return runInRowLevelSecurityScope(tenantRowLevelSecurityScope(streamTenantId), work);
6
+ }
@@ -13,7 +13,7 @@
13
13
  // separate CLI step — not implemented here, tracked as follow-up.
14
14
  import { bigint, index, integer, jsonb, table as pgTable, text, timestamp, uuid, } from "../db/dialect.js";
15
15
  import { tableExists } from "../db/schema-inspection.js";
16
- import { unsafePushTables } from "../db/table-push.js";
16
+ import { ensureTableRowLevelSecurity, unsafePushTables } from "../db/table-push.js";
17
17
  export const upcasterDeadLetterTable = pgTable("kumiko_upcaster_dead_letters", {
18
18
  // Surrogate PK. We don't reuse eventId so a single event can land
19
19
  // here multiple times (retry attempts across deploys before the fix
@@ -40,8 +40,10 @@ export const upcasterDeadLetterTable = pgTable("kumiko_upcaster_dead_letters", {
40
40
  // exercise the quarantine path; production boot uses drizzle-kit push.
41
41
  export async function createUpcasterDeadLetterTable(db) {
42
42
  // skip: table already exists — bootstrap called from multiple paths
43
- if (await tableExists(db, "public.kumiko_upcaster_dead_letters"))
43
+ if (await tableExists(db, "public.kumiko_upcaster_dead_letters")) {
44
+ await ensureTableRowLevelSecurity(db, upcasterDeadLetterTable);
44
45
  return;
46
+ }
45
47
  await unsafePushTables(db, { kumikoUpcasterDeadLetters: upcasterDeadLetterTable });
46
48
  }
47
49
  // Writes a dead-letter row. Called by upcastStoredEvent when errorPolicy
@@ -1,5 +1,6 @@
1
+ import type { EventUpcastCtx, EventUpcastFn } from "@cosmicdrift/kumiko-types/handlers";
1
2
  import type { DbRunner } from "../db/index.ts";
2
- import type { EventUpcastCtx, EventUpcastFn, TenantId } from "../engine/types/index.ts";
3
+ import type { TenantId } from "../engine/types/index.ts";
3
4
  import type { StoredEvent } from "./event-store.ts";
4
5
  export type UpcasterErrorPolicy = "throw" | "quarantine";
5
6
  export type UpcastOptions = {
@@ -1,4 +1,5 @@
1
- import { type AnyFileFieldDef, type Registry, type SessionUser } from "../engine/types/index.ts";
1
+ import type { AnyFileFieldDef } from "@cosmicdrift/kumiko-types/fields";
2
+ import type { Registry, SessionUser } from "../engine/types/index.ts";
2
3
  export declare function isActionFormScreenQn(value: string): boolean;
3
4
  /** The files/images field `fieldName` of the registered actionForm screen `screenQn`, if any. */
4
5
  export declare function resolveActionFormFileField(registry: Pick<Registry, "getScreen"> | undefined, screenQn: string, fieldName: string): AnyFileFieldDef | undefined;
@@ -1,5 +1,5 @@
1
1
  import { hasAccess } from "../engine/access.js";
2
- import { isFileField, } from "../engine/types/index.js";
2
+ import { isFileField } from "../engine/field-helpers.js";
3
3
  // Same character set as the other upload identifiers: the screen QN is stored as the pending
4
4
  // upload's entityType and compared by exact match, never interpolated into a storage key.
5
5
  const ACTION_FORM_SCREEN_QN = /^[A-Za-z0-9_-]+:screen:[A-Za-z0-9_-]+$/;
@@ -1,4 +1,5 @@
1
- import { type Registry, type SaveContext } from "../engine/types/index.ts";
1
+ import type { SaveContext } from "@cosmicdrift/kumiko-types/hooks";
2
+ import type { Registry } from "../engine/types/index.ts";
2
3
  import type { FileRefRows } from "./load-save-file-refs.ts";
3
4
  export declare function assertFileRefsBelongToTenant(args: {
4
5
  readonly registry: Registry;
@@ -1,4 +1,4 @@
1
- import { isFileField } from "../engine/types/index.js";
1
+ import { isFileField } from "../engine/field-helpers.js";
2
2
  import { ValidationError } from "../errors/index.js";
3
3
  import { fileRefIdsOf } from "./bind-pending-file-refs.js";
4
4
  import { FILE_REF_ENTITY_NAME } from "./file-ref-entity.js";
@@ -1,5 +1,6 @@
1
+ import type { SaveContext } from "@cosmicdrift/kumiko-types/hooks";
1
2
  import type { TenantDb } from "../db/tenant-db.ts";
2
- import { type Registry, type SaveContext, type SessionUser } from "../engine/types/index.ts";
3
+ import type { Registry, SessionUser } from "../engine/types/index.ts";
3
4
  import { type FileRefRows } from "./load-save-file-refs.ts";
4
5
  export declare function fileRefIdsOf(value: unknown): readonly string[];
5
6
  type FileRefRow = Readonly<Record<string, unknown>>;
@@ -1,5 +1,6 @@
1
+ import { isUuid } from "@cosmicdrift/kumiko-types/identifiers";
2
+ import { isFileField } from "../engine/field-helpers.js";
1
3
  import { isAnonymousSessionUser } from "../engine/system-user.js";
2
- import { isFileField, isUuid, } from "../engine/types/index.js";
3
4
  import { FrameworkReasons, InternalError, reraiseAsKumikoError, UnprocessableError, } from "../errors/index.js";
4
5
  import { getFileRefExecutor, resolveAttachedField } from "./create-file-ref.js";
5
6
  import { FILE_REF_ENTITY_NAME } from "./file-ref-entity.js";
@@ -1,6 +1,6 @@
1
1
  import * as z from "zod";
2
+ import { isFileField } from "../engine/field-helpers.js";
2
3
  import { defineWriteHandler, SYSTEM_ROLE, SYSTEM_USER_ID } from "../engine/index.js";
3
- import { isFileField } from "../engine/types/index.js";
4
4
  import { ValidationError } from "../errors/index.js";
5
5
  import { fileRefIdsOf } from "./bind-pending-file-refs.js";
6
6
  import { getFileRefExecutor } from "./create-file-ref.js";
@@ -1,11 +1,14 @@
1
+ import type { BeforeTransactionResult, WriteResult } from "@cosmicdrift/kumiko-types/handlers";
1
2
  import type { TenantDb } from "../db/tenant-db.ts";
2
- import type { BeforeTransactionResult, Registry, SessionUser, WriteResult } from "../engine/types/index.ts";
3
+ import type { Registry, SessionUser } from "../engine/types/index.ts";
3
4
  import { type CreatedFileRef, type UploadedFileBytes } from "./create-file-ref.ts";
4
5
  import type { FileContext } from "./file-handle.ts";
5
6
  export type { CreatedFileRef, UploadedFileBytes };
6
7
  export type CreateFileRefContext = {
7
8
  readonly db: TenantDb;
8
- readonly files?: FileContext | undefined;
9
+ readonly services: {
10
+ readonly files?: FileContext | undefined;
11
+ };
9
12
  readonly registry: Registry;
10
13
  readonly user: SessionUser;
11
14
  };
@@ -21,6 +24,6 @@ export type CreateFileRefInput = {
21
24
  };
22
25
  export declare function filesUnavailableMessage(caller: string): string;
23
26
  export declare function createFileRefFromBytes(ctx: CreateFileRefContext, input: CreateFileRefInput): Promise<WriteResult<CreatedFileRef>>;
24
- export type UploadFileBytesContext = Pick<CreateFileRefContext, "db" | "files" | "registry" | "user">;
27
+ export type UploadFileBytesContext = Pick<CreateFileRefContext, "db" | "services" | "registry" | "user">;
25
28
  export declare function uploadFileBytesBeforeTransaction(ctx: UploadFileBytesContext, input: CreateFileRefInput): Promise<BeforeTransactionResult<UploadedFileBytes>>;
26
29
  export declare function createFileRefFromUploadedBytes(ctx: Pick<CreateFileRefContext, "db" | "user">, uploaded: UploadedFileBytes): Promise<WriteResult<CreatedFileRef>>;
@@ -8,13 +8,13 @@ import { assertSafeStorageKey } from "./types.js";
8
8
  // The handler context has no HTTP/job/seed marker to name, so the message states the actual
9
9
  // cause: the dispatcher's AppContext carries no file-provider resolver.
10
10
  export function filesUnavailableMessage(caller) {
11
- return `${caller}: ctx.files is unavailable because no file-provider resolver is wired on this dispatcher context. Mount a file-provider-* feature and build the dispatcher context with withFileProviderResolver (HTTP, job and seed dispatchers each need it)`;
11
+ return `${caller}: ctx.services.files is unavailable because no file-provider resolver is wired on this dispatcher context. Mount a file-provider-* feature and build the dispatcher context with withFileProviderResolver (HTTP, job and seed dispatchers each need it)`;
12
12
  }
13
13
  // Server-side counterpart of POST /files for handlers/jobs that produce bytes
14
14
  // themselves (generated PDFs, exports). Same validation, storage layout and
15
15
  // fileRef.created event as an upload; the tenant is always ctx.user.tenantId.
16
16
  export async function createFileRefFromBytes(ctx, input) {
17
- const { files } = ctx;
17
+ const { files } = ctx.services;
18
18
  if (!files) {
19
19
  return writeFailure(new InternalError({
20
20
  message: filesUnavailableMessage("createFileRefFromBytes"),
@@ -46,6 +46,9 @@ export async function createFileRefFromBytes(ctx, input) {
46
46
  return fileRejectedFailure(outcome.error);
47
47
  case "failed":
48
48
  return outcome.failure;
49
+ case "target-locked":
50
+ // Only the HTTP route supplies the lock re-check, so this path cannot produce it.
51
+ return writeFailure(new InternalError({ message: "createFileRefFromBytes: unexpected target-locked outcome" }));
49
52
  }
50
53
  }
51
54
  function fileRejectedFailure(error) {
@@ -56,7 +59,7 @@ function fileRejectedFailure(error) {
56
59
  // A crash between this phase and the commit leaves the bytes in storage; the upload ledger sweep
57
60
  // removes them after its grace period.
58
61
  export async function uploadFileBytesBeforeTransaction(ctx, input) {
59
- const { files } = ctx;
62
+ const { files } = ctx.services;
60
63
  if (!files) {
61
64
  return writeFailure(new InternalError({
62
65
  message: filesUnavailableMessage("uploadFileBytesBeforeTransaction"),
@@ -1,5 +1,6 @@
1
- import { type TenantDb } from "../db/tenant-db.ts";
2
- import { type AnyFileFieldDef, type Registry, type SessionUser } from "../engine/types/index.ts";
1
+ import type { AnyFileFieldDef } from "@cosmicdrift/kumiko-types/fields";
2
+ import type { TenantDb } from "../db/tenant-db.ts";
3
+ import type { Registry, SessionUser } from "../engine/types/index.ts";
3
4
  import { type WriteFailure } from "../errors/index.ts";
4
5
  export declare const DEFAULT_MAX_UPLOAD_SIZE = "10mb";
5
6
  declare function buildFileRefExecutor(): import("@cosmicdrift/kumiko-types/event-store-executor-types").EventStoreExecutor<{
@@ -50,6 +51,7 @@ export type StoreFileDeps = {
50
51
  readonly defaultMaxUploadSize: string;
51
52
  readonly writeBytes: (storageKey: string, data: Uint8Array, mimeType: string) => Promise<void>;
52
53
  readonly deleteBytes: (storageKey: string) => Promise<void>;
54
+ readonly isAttachTargetLocked?: (rowDb: TenantDb) => Promise<boolean>;
53
55
  };
54
56
  export type CreatedFileRef = {
55
57
  readonly id: string;
@@ -80,6 +82,8 @@ export type StoreFileOutcome = {
80
82
  } | {
81
83
  readonly kind: "rejected";
82
84
  readonly error: string;
85
+ } | {
86
+ readonly kind: "target-locked";
83
87
  } | {
84
88
  readonly kind: "failed";
85
89
  readonly failure: WriteFailure;
@@ -1,6 +1,6 @@
1
1
  import { createEventStoreExecutor } from "../db/event-store-executor.js";
2
- import { runInOwnTransaction } from "../db/tenant-db.js";
3
- import { isFileField, } from "../engine/types/index.js";
2
+ import { runInOwnTransaction } from "../db/tenant-db-scoped-rebind.js";
3
+ import { isFileField } from "../engine/field-helpers.js";
4
4
  import { InternalError } from "../errors/index.js";
5
5
  import { generateId } from "../utils/index.js";
6
6
  import { isActionFormScreenQn, resolveActionFormFileField } from "./action-form-upload.js";
@@ -41,6 +41,8 @@ export function resolveAttachedField(registry, entityType, fieldName) {
41
41
  return { kind: "unresolvable" };
42
42
  return { kind: "resolved", fieldDef };
43
43
  }
44
+ class AttachTargetLockedError extends Error {
45
+ }
44
46
  function resolveUploadField(registry, input) {
45
47
  const { entityType, entityId, fieldName, actionForm } = input;
46
48
  if (actionForm === undefined)
@@ -196,14 +198,21 @@ export async function storeFileAsFileRef(deps, input) {
196
198
  // skip: the create failure is the error worth reporting; the leftover bytes stay in storage.
197
199
  }
198
200
  };
201
+ const createRow = async (rowDb) => {
202
+ if (await deps.isAttachTargetLocked?.(rowDb))
203
+ throw new AttachTargetLockedError();
204
+ return createFileRefRow({ user: deps.user, tenantDb: rowDb }, upload.uploaded);
205
+ };
199
206
  let row;
200
207
  try {
201
208
  row = deps.rowInOwnTransaction
202
- ? await runInOwnTransaction(deps.tenantDb, (txDb) => createFileRefRow({ user: deps.user, tenantDb: txDb }, upload.uploaded))
203
- : await createFileRefRow(deps, upload.uploaded);
209
+ ? await runInOwnTransaction(deps.tenantDb, createRow)
210
+ : await createRow(deps.tenantDb);
204
211
  }
205
212
  catch (e) {
206
213
  await deleteUploadedBytes();
214
+ if (e instanceof AttachTargetLockedError)
215
+ return { kind: "target-locked" };
207
216
  throw e;
208
217
  }
209
218
  if ("failure" in row) {
@@ -1,5 +1,6 @@
1
+ import type { SaveContext } from "@cosmicdrift/kumiko-types/hooks";
1
2
  import type { TenantDb } from "../db/tenant-db.ts";
2
- import { type Registry, type SaveContext, type SessionUser } from "../engine/types/index.ts";
3
+ import type { Registry, SessionUser } from "../engine/types/index.ts";
3
4
  export declare function disposeRemovedFileRefs(args: {
4
5
  readonly registry: Registry;
5
6
  readonly result: SaveContext;
@@ -1,4 +1,4 @@
1
- import { isFileField, } from "../engine/types/index.js";
1
+ import { isFileField } from "../engine/field-helpers.js";
2
2
  import { reraiseAsKumikoError } from "../errors/index.js";
3
3
  import { fileRefIdsOf } from "./bind-pending-file-refs.js";
4
4
  import { getFileRefExecutor } from "./create-file-ref.js";
@@ -41,10 +41,10 @@ export function createFilesFeature(options = {}) {
41
41
  handler: async (_payload, ctx) => {
42
42
  await sweepOrphanedUploads({
43
43
  db: ctx.db,
44
- files: ctx.files,
44
+ files: ctx.services.files,
45
45
  now: ctx.tz.now(),
46
46
  graceHours: uploadSweepGraceHours,
47
- log: ctx.log,
47
+ log: ctx.obs.log,
48
48
  });
49
49
  },
50
50
  });
@@ -3,7 +3,7 @@
3
3
  // The contract the framework exposes to hook/handler code: a FileHandle lets
4
4
  // you read/write/delete the binary behind a storage key without ever passing
5
5
  // the binary through event payloads, job queues, or hook signatures. Events
6
- // carry the key, hooks reach for `ctx.files.ref(key)` when they actually need
6
+ // carry the key, hooks reach for `ctx.services.files.ref(key)` when they actually need
7
7
  // the bytes, and big files stay in the storage layer where they belong.
8
8
  //
9
9
  // `derive(suffix)` is the primitive for thumbnail/variant keys: it inserts a
@@ -1,7 +1,8 @@
1
+ import type { RateLimitResolver } from "@cosmicdrift/kumiko-types/rate-limit-types";
1
2
  import type { WriteErrorInfo } from "@cosmicdrift/kumiko-types/write-error-info-types";
2
3
  import { Hono } from "hono";
3
4
  import type { DbConnection } from "../db/connection.ts";
4
- import { type Registry, type SessionUser, type TenantId } from "../engine/types/index.ts";
5
+ import type { Registry, SessionUser, TenantId } from "../engine/types/index.ts";
5
6
  import type { FileProviderResolver } from "./provider-resolver.ts";
6
7
  import type { RecordReadCheck } from "./record-read-check.ts";
7
8
  import { type RecordWriteCheck } from "./record-write-check.ts";
@@ -30,6 +31,7 @@ export type FileAccessGuard = (args: {
30
31
  }) => FileAccessDecision | Promise<FileAccessDecision>;
31
32
  export type FileRoutesOptions = {
32
33
  readonly db: DbConnection;
34
+ readonly metaBatchRateLimitResolver?: RateLimitResolver;
33
35
  readonly resolveProvider: FileProviderResolver;
34
36
  readonly registry?: Registry;
35
37
  readonly maxUploadSize?: string;