@cosmicdrift/kumiko-framework 0.389.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 (616) hide show
  1. package/AGENTS.md +9 -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/inbound-mail-triage.md +1 -0
  13. package/agents/examples/lane-routing.md +2 -1
  14. package/agents/examples/legal-pages.md +2 -2
  15. package/agents/examples/lifecycle-hooks.md +3 -3
  16. package/agents/examples/managed-config.md +4 -4
  17. package/agents/examples/managed-pages.md +1 -1
  18. package/agents/examples/relations.md +19 -4
  19. package/agents/examples/search.md +4 -4
  20. package/agents/examples/secrets-demo.md +9 -6
  21. package/agents/examples/state-machine.md +2 -2
  22. package/agents/examples/tenant-settings.md +1 -1
  23. package/agents/examples/user-data-rights.md +3 -6
  24. package/agents/examples/workflow-engine.md +53 -47
  25. package/agents/examples.md +4 -4
  26. package/agents/features.md +1 -1
  27. package/dist/api/auth-middleware.js +1 -1
  28. package/dist/api/auth-routes-invite.js +2 -1
  29. package/dist/api/entity-read-access.d.ts +3 -1
  30. package/dist/api/export/export-columns.d.ts +3 -1
  31. package/dist/api/export/export-route.js +3 -2
  32. package/dist/api/export/export-screen.d.ts +2 -1
  33. package/dist/api/extra-route.d.ts +3 -1
  34. package/dist/api/index.d.ts +23 -27
  35. package/dist/api/index.js +13 -15
  36. package/dist/api/jwt.js +1 -1
  37. package/dist/api/observability-middleware.d.ts +1 -1
  38. package/dist/api/observability-middleware.js +2 -1
  39. package/dist/api/request-context-internals.d.ts +31 -0
  40. package/dist/api/request-context-internals.js +11 -0
  41. package/dist/api/request-context-scopes.d.ts +14 -0
  42. package/dist/api/request-context-scopes.js +69 -0
  43. package/dist/api/request-context.d.ts +1 -40
  44. package/dist/api/request-context.js +22 -51
  45. package/dist/api/request-id-middleware.d.ts +1 -1
  46. package/dist/api/route-registrars.d.ts +2 -1
  47. package/dist/api/route-registrars.js +1 -1
  48. package/dist/api/routes.js +7 -3
  49. package/dist/api/server-boot-checks.d.ts +1 -1
  50. package/dist/api/server-boot-checks.js +2 -2
  51. package/dist/api/server-event-dispatcher.d.ts +6 -1
  52. package/dist/api/server-event-dispatcher.js +3 -4
  53. package/dist/api/server-extra-routes.d.ts +1 -1
  54. package/dist/api/server-extra-routes.js +2 -1
  55. package/dist/api/server-middleware.js +3 -1
  56. package/dist/api/server-routes.d.ts +2 -1
  57. package/dist/api/server-wiring.js +6 -4
  58. package/dist/api/server.d.ts +2 -1
  59. package/dist/api/sse-route.d.ts +2 -1
  60. package/dist/api/tenant-scoped-secrets.d.ts +2 -0
  61. package/dist/api/tenant-scoped-secrets.js +13 -0
  62. package/dist/api/websocket-route.d.ts +1 -1
  63. package/dist/auth/index.d.ts +0 -1
  64. package/dist/auth/roles.d.ts +0 -5
  65. package/dist/compliance/duration-spec.d.ts +0 -1
  66. package/dist/compliance/duration-spec.js +0 -5
  67. package/dist/compliance/index.d.ts +4 -4
  68. package/dist/compliance/index.js +2 -2
  69. package/dist/compliance/profiles.d.ts +0 -15
  70. package/dist/compliance/profiles.js +0 -23
  71. package/dist/config/index.d.ts +10 -10
  72. package/dist/config/index.js +13 -1
  73. package/dist/config/internals.d.ts +9 -0
  74. package/dist/config/internals.js +1 -0
  75. package/dist/consumer-cli-internals.d.ts +4 -0
  76. package/dist/consumer-cli-internals.js +1 -0
  77. package/dist/consumer-cli.d.ts +1 -4
  78. package/dist/consumer-cli.js +5 -1
  79. package/dist/crypto/event-pii.js +1 -1
  80. package/dist/crypto/index.d.ts +8 -9
  81. package/dist/crypto/index.js +7 -8
  82. package/dist/crypto/pg-kms-adapter.js +6 -1
  83. package/dist/db/apply-entity-event.d.ts +1 -1
  84. package/dist/db/apply-entity-event.js +15 -47
  85. package/dist/db/blind-index-cleanup.js +91 -77
  86. package/dist/db/collect-table-metas.js +1 -1
  87. package/dist/db/compound-types.d.ts +1 -1
  88. package/dist/db/compound-types.js +0 -7
  89. package/dist/db/config-seed.d.ts +2 -1
  90. package/dist/db/config-seed.js +6 -1
  91. package/dist/db/connection.d.ts +3 -1
  92. package/dist/db/connection.js +15 -5
  93. package/dist/db/cross-tenant-reads.d.ts +1 -1
  94. package/dist/db/cross-tenant-reads.js +1 -1
  95. package/dist/db/dialect.d.ts +0 -5
  96. package/dist/db/dialect.js +0 -3
  97. package/dist/db/eagerload.d.ts +2 -1
  98. package/dist/db/entity-field-encryption.d.ts +1 -1
  99. package/dist/db/entity-table-meta.d.ts +1 -1
  100. package/dist/db/event-store-executor-context.d.ts +3 -1
  101. package/dist/db/event-store-executor-context.js +4 -3
  102. package/dist/db/event-store-executor-read-filter.d.ts +1 -1
  103. package/dist/db/event-store-executor-read-rows.d.ts +2 -1
  104. package/dist/db/event-store-executor-read-search.d.ts +2 -1
  105. package/dist/db/event-store-executor-read-sort.d.ts +2 -1
  106. package/dist/db/event-store-executor-read.js +2 -2
  107. package/dist/db/event-store-executor-write-atomic.js +8 -7
  108. package/dist/db/event-store-executor-write-steps.d.ts +3 -2
  109. package/dist/db/event-store-executor-write.js +7 -4
  110. package/dist/db/event-store-executor.d.ts +1 -1
  111. package/dist/db/executor-managed-tables.d.ts +7 -1
  112. package/dist/db/executor-managed-tables.js +11 -2
  113. package/dist/db/index.d.ts +29 -28
  114. package/dist/db/index.js +22 -20
  115. package/dist/db/known-table-names.d.ts +6 -0
  116. package/dist/db/known-table-names.js +21 -0
  117. package/dist/db/list-aggregate-labels.d.ts +1 -1
  118. package/dist/db/located-timestamp.d.ts +1 -1
  119. package/dist/db/located-timestamp.js +0 -5
  120. package/dist/db/migrate-generator.d.ts +17 -1
  121. package/dist/db/migrate-generator.js +50 -20
  122. package/dist/db/migrate-primary-key.d.ts +12 -0
  123. package/dist/db/migrate-primary-key.js +45 -0
  124. package/dist/db/migrate-rls-diff.d.ts +20 -0
  125. package/dist/db/migrate-rls-diff.js +61 -0
  126. package/dist/db/migrate-runner.js +4 -0
  127. package/dist/db/money.d.ts +1 -1
  128. package/dist/db/money.js +1 -1
  129. package/dist/db/parent-ref-clause.d.ts +2 -1
  130. package/dist/db/pg-error.d.ts +2 -0
  131. package/dist/db/pg-error.js +11 -0
  132. package/dist/db/queries/ddl.d.ts +3 -0
  133. package/dist/db/queries/ddl.js +34 -1
  134. package/dist/db/queries/event-store.js +4 -2
  135. package/dist/db/queries/event-tenants.d.ts +2 -0
  136. package/dist/db/queries/event-tenants.js +17 -0
  137. package/dist/db/queries/rebuild-rls-guard.d.ts +2 -0
  138. package/dist/db/queries/rebuild-rls-guard.js +29 -0
  139. package/dist/db/queries/rls-boot-catalog.d.ts +16 -0
  140. package/dist/db/queries/rls-boot-catalog.js +39 -0
  141. package/dist/db/queries/rls-catalog.d.ts +6 -0
  142. package/dist/db/queries/rls-catalog.js +82 -0
  143. package/dist/db/queries/rls-scope.d.ts +3 -0
  144. package/dist/db/queries/rls-scope.js +17 -0
  145. package/dist/db/queries/rls-shape.d.ts +10 -0
  146. package/dist/db/queries/rls-shape.js +42 -0
  147. package/dist/db/queries/session-advisory-lock.d.ts +2 -0
  148. package/dist/db/queries/session-advisory-lock.js +23 -0
  149. package/dist/db/queries/shadow-swap.d.ts +1 -2
  150. package/dist/db/queries/shadow-swap.js +9 -25
  151. package/dist/db/queries/test-stack.d.ts +4 -1
  152. package/dist/db/queries/test-stack.js +83 -2
  153. package/dist/db/query.js +11 -7
  154. package/dist/db/reference-data.d.ts +1 -1
  155. package/dist/db/reference-data.js +6 -1
  156. package/dist/db/render-ddl.d.ts +6 -2
  157. package/dist/db/render-ddl.js +7 -7
  158. package/dist/db/render-rls-ddl.d.ts +35 -0
  159. package/dist/db/render-rls-ddl.js +127 -0
  160. package/dist/db/replay-migration-sql.d.ts +3 -1
  161. package/dist/db/replay-migration-sql.js +22 -5
  162. package/dist/db/replay-rls.d.ts +25 -0
  163. package/dist/db/replay-rls.js +156 -0
  164. package/dist/db/row-level-security-boot-check.d.ts +5 -0
  165. package/dist/db/row-level-security-boot-check.js +85 -0
  166. package/dist/db/row-level-security-connection.d.ts +3 -0
  167. package/dist/db/row-level-security-connection.js +213 -0
  168. package/dist/db/row-level-security-scope.d.ts +33 -0
  169. package/dist/db/row-level-security-scope.js +127 -0
  170. package/dist/db/scope-tenant-db-to-tenant.d.ts +3 -0
  171. package/dist/db/scope-tenant-db-to-tenant.js +14 -0
  172. package/dist/db/sql-identifier.d.ts +1 -0
  173. package/dist/db/sql-identifier.js +3 -0
  174. package/dist/db/table-builder.d.ts +2 -1
  175. package/dist/db/table-builder.js +1 -1
  176. package/dist/db/table-info.js +1 -1
  177. package/dist/db/table-push.d.ts +11 -2
  178. package/dist/db/table-push.js +15 -2
  179. package/dist/db/tenant-db-runner.d.ts +3 -1
  180. package/dist/db/tenant-db-runner.js +4 -3
  181. package/dist/db/tenant-db-scoped-rebind.d.ts +10 -0
  182. package/dist/db/tenant-db-scoped-rebind.js +33 -0
  183. package/dist/db/tenant-db-statement-runner.d.ts +13 -0
  184. package/dist/db/tenant-db-statement-runner.js +48 -0
  185. package/dist/db/tenant-db.d.ts +17 -12
  186. package/dist/db/tenant-db.js +49 -120
  187. package/dist/db/tenant-id-filter.d.ts +3 -0
  188. package/dist/db/tenant-id-filter.js +30 -0
  189. package/dist/db/transaction-serialization.d.ts +6 -0
  190. package/dist/db/transaction-serialization.js +60 -0
  191. package/dist/derivatives/delete-stored-file.js +1 -1
  192. package/dist/derivatives/index.d.ts +2 -5
  193. package/dist/derivatives/index.js +2 -3
  194. package/dist/engine/access.d.ts +2 -1
  195. package/dist/engine/access.js +1 -1
  196. package/dist/engine/boot-validator/entity-handler.d.ts +2 -1
  197. package/dist/engine/boot-validator/entity-handler.js +1 -1
  198. package/dist/engine/boot-validator/entity-list-aggregate-options.d.ts +1 -1
  199. package/dist/engine/boot-validator/list-table-aggregate-options.d.ts +1 -1
  200. package/dist/engine/boot-validator/list-table-aggregate-query.d.ts +2 -1
  201. package/dist/engine/boot-validator/nav.d.ts +3 -1
  202. package/dist/engine/boot-validator/nav.js +1 -1
  203. package/dist/engine/boot-validator/ownership.d.ts +2 -1
  204. package/dist/engine/boot-validator/parent-ref.d.ts +2 -1
  205. package/dist/engine/boot-validator/projection-list-screens.d.ts +2 -1
  206. package/dist/engine/boot-validator/query-refs.d.ts +2 -1
  207. package/dist/engine/boot-validator/screens-forms.d.ts +2 -1
  208. package/dist/engine/boot-validator/screens-kind-shared.d.ts +3 -1
  209. package/dist/engine/boot-validator/screens.d.ts +2 -1
  210. package/dist/engine/boot-validator/workspaces.d.ts +3 -1
  211. package/dist/engine/bridge-stub.d.ts +5 -2
  212. package/dist/engine/bridge-stub.js +39 -24
  213. package/dist/engine/config-helpers.d.ts +2 -2
  214. package/dist/engine/config-helpers.js +0 -9
  215. package/dist/engine/constants.d.ts +0 -10
  216. package/dist/engine/constants.js +0 -8
  217. package/dist/engine/create-app.js +1 -1
  218. package/dist/engine/define-feature.d.ts +2 -1
  219. package/dist/engine/define-feature.js +1 -2
  220. package/dist/engine/define-handler.d.ts +1 -1
  221. package/dist/engine/define-step.d.ts +0 -1
  222. package/dist/engine/define-step.js +0 -3
  223. package/dist/engine/embedded-derived.d.ts +1 -1
  224. package/dist/engine/entity-handlers.d.ts +2 -1
  225. package/dist/engine/entity-handlers.js +7 -7
  226. package/dist/engine/entity-list-runtime-options.js +3 -1
  227. package/dist/engine/entity-list-searchability.d.ts +2 -1
  228. package/dist/engine/event-def.d.ts +2 -1
  229. package/dist/engine/event-helpers.d.ts +3 -1
  230. package/dist/engine/event-helpers.js +3 -3
  231. package/dist/engine/extension-names.d.ts +2 -8
  232. package/dist/engine/extension-names.js +2 -2
  233. package/dist/engine/extension-selector-plugins.d.ts +1 -1
  234. package/dist/engine/extensions/storage-provider.d.ts +1 -2
  235. package/dist/engine/extensions/user-data.d.ts +0 -8
  236. package/dist/engine/factories.d.ts +2 -1
  237. package/dist/engine/feature-builder-state.d.ts +8 -1
  238. package/dist/engine/feature-changelog.d.ts +1 -1
  239. package/dist/engine/feature-config-events-jobs.d.ts +4 -1
  240. package/dist/engine/feature-entity-handlers.d.ts +5 -1
  241. package/dist/engine/feature-manifest.js +1 -1
  242. package/dist/engine/feature-ui-extensions.d.ts +7 -1
  243. package/dist/engine/feature-ui-extensions.js +6 -4
  244. package/dist/engine/field-access.d.ts +2 -1
  245. package/dist/engine/handler-field-references.d.ts +0 -4
  246. package/dist/engine/index.d.ts +57 -54
  247. package/dist/engine/index.js +22 -27
  248. package/dist/engine/instruction-fields.d.ts +1 -1
  249. package/dist/engine/personal-data-fields.d.ts +1 -1
  250. package/dist/engine/qualified-name.d.ts +0 -1
  251. package/dist/engine/read-claim.d.ts +2 -1
  252. package/dist/engine/registry-facade.js +0 -3
  253. package/dist/engine/registry-ingest.d.ts +2 -1
  254. package/dist/engine/registry-ingest.js +1 -2
  255. package/dist/engine/registry-state.d.ts +12 -2
  256. package/dist/engine/registry-state.js +2 -3
  257. package/dist/engine/registry-validate.d.ts +3 -1
  258. package/dist/engine/registry-validate.js +7 -7
  259. package/dist/engine/run-in.d.ts +1 -1
  260. package/dist/engine/run-in.js +0 -1
  261. package/dist/engine/schema-builder.d.ts +1 -1
  262. package/dist/engine/schema-builder.js +1 -1
  263. package/dist/engine/screen-filter-ops.d.ts +2 -1
  264. package/dist/engine/screen-filter-ops.js +0 -5
  265. package/dist/engine/soft-delete-cleanup.d.ts +1 -1
  266. package/dist/engine/soft-delete-cleanup.js +4 -4
  267. package/dist/engine/state-machine.js +2 -1
  268. package/dist/engine/steps/_read-source.js +1 -1
  269. package/dist/engine/steps/aggregate-append-event.js +2 -2
  270. package/dist/engine/steps/call-feature.js +2 -2
  271. package/dist/engine/steps/mail-send.js +1 -1
  272. package/dist/engine/steps/retry.js +1 -1
  273. package/dist/engine/steps/wait-for-event.js +1 -1
  274. package/dist/engine/steps/wait.js +1 -1
  275. package/dist/engine/steps/webhook-send.js +1 -1
  276. package/dist/engine/template-variables.d.ts +2 -1
  277. package/dist/engine/transfer-adjacency.d.ts +1 -1
  278. package/dist/engine/types/index.d.ts +8 -31
  279. package/dist/engine/types/index.js +2 -10
  280. package/dist/engine/validation.d.ts +2 -1
  281. package/dist/entrypoint/index.d.ts +7 -35
  282. package/dist/entrypoint/index.js +7 -1
  283. package/dist/entrypoint/internals.d.ts +40 -0
  284. package/dist/entrypoint/internals.js +1 -0
  285. package/dist/entrypoint/row-level-security-mode-check.d.ts +3 -0
  286. package/dist/entrypoint/row-level-security-mode-check.js +19 -0
  287. package/dist/env/dry-run-internals.d.ts +10 -0
  288. package/dist/env/dry-run-internals.js +1 -0
  289. package/dist/env/dry-run.d.ts +1 -10
  290. package/dist/env/dry-run.js +2 -1
  291. package/dist/env/index.d.ts +1 -85
  292. package/dist/env/index.js +6 -50
  293. package/dist/env/internals.d.ts +87 -0
  294. package/dist/env/internals.js +53 -0
  295. package/dist/errors/classes.js +2 -2
  296. package/dist/errors/index.d.ts +5 -14
  297. package/dist/errors/index.js +4 -9
  298. package/dist/errors/member-resolution.js +1 -1
  299. package/dist/errors/reasons.d.ts +0 -1
  300. package/dist/errors/reasons.js +7 -7
  301. package/dist/errors/serialize.d.ts +0 -18
  302. package/dist/errors/serialize.js +0 -27
  303. package/dist/es-ops/index.d.ts +4 -4
  304. package/dist/es-ops/index.js +2 -2
  305. package/dist/es-ops/operations-schema.d.ts +1 -1
  306. package/dist/es-ops/types.d.ts +4 -5
  307. package/dist/event-store/admin-api-internals.d.ts +14 -0
  308. package/dist/event-store/admin-api-internals.js +1 -0
  309. package/dist/event-store/admin-api.d.ts +1 -14
  310. package/dist/event-store/admin-api.js +11 -6
  311. package/dist/event-store/archive.js +4 -2
  312. package/dist/event-store/errors.js +2 -2
  313. package/dist/event-store/event-store.js +41 -34
  314. package/dist/event-store/events-schema.js +4 -1
  315. package/dist/event-store/index.d.ts +11 -13
  316. package/dist/event-store/index.js +7 -9
  317. package/dist/event-store/rebuild-dead-letter.js +4 -2
  318. package/dist/event-store/snapshot.js +4 -3
  319. package/dist/event-store/stream-scope.d.ts +2 -0
  320. package/dist/event-store/stream-scope.js +6 -0
  321. package/dist/event-store/upcaster-dead-letter.js +4 -2
  322. package/dist/event-store/upcaster.d.ts +2 -1
  323. package/dist/files/action-form-upload.d.ts +2 -1
  324. package/dist/files/action-form-upload.js +1 -1
  325. package/dist/files/assert-file-refs-belong-to-tenant.d.ts +2 -1
  326. package/dist/files/assert-file-refs-belong-to-tenant.js +1 -1
  327. package/dist/files/bind-pending-file-refs.d.ts +2 -1
  328. package/dist/files/bind-pending-file-refs.js +2 -1
  329. package/dist/files/bind-referenced-files.write.js +1 -1
  330. package/dist/files/create-file-ref-from-bytes.d.ts +6 -3
  331. package/dist/files/create-file-ref-from-bytes.js +3 -3
  332. package/dist/files/create-file-ref.d.ts +3 -2
  333. package/dist/files/create-file-ref.js +2 -2
  334. package/dist/files/dispose-removed-file-refs.d.ts +2 -1
  335. package/dist/files/dispose-removed-file-refs.js +1 -1
  336. package/dist/files/feature.js +2 -2
  337. package/dist/files/file-handle.js +1 -1
  338. package/dist/files/file-routes.d.ts +1 -1
  339. package/dist/files/file-routes.js +12 -2
  340. package/dist/files/index.d.ts +11 -13
  341. package/dist/files/index.js +5 -7
  342. package/dist/files/load-save-file-refs.d.ts +2 -1
  343. package/dist/files/load-save-file-refs.js +1 -1
  344. package/dist/files/provider-resolver.d.ts +5 -4
  345. package/dist/files/provider-resolver.js +4 -4
  346. package/dist/files/storage-tracking.js +4 -2
  347. package/dist/files/sweep-orphaned-uploads.d.ts +1 -1
  348. package/dist/files/sweep-orphaned-uploads.js +1 -1
  349. package/dist/i18n/index.d.ts +2 -8
  350. package/dist/i18n/index.js +1 -1
  351. package/dist/i18n/internals.d.ts +7 -0
  352. package/dist/i18n/internals.js +1 -0
  353. package/dist/i18n/required-surface-keys.d.ts +4 -1
  354. package/dist/internal/row-level-security.d.ts +3 -0
  355. package/dist/internal/row-level-security.js +3 -0
  356. package/dist/internal/stack-support.d.ts +1 -1
  357. package/dist/internal/stack-support.js +1 -1
  358. package/dist/internal/testing.d.ts +1 -0
  359. package/dist/internal/testing.js +9 -5
  360. package/dist/jobs/index.d.ts +1 -1
  361. package/dist/jobs/job-append-event.d.ts +12 -0
  362. package/dist/jobs/job-append-event.js +30 -0
  363. package/dist/jobs/job-runner-context.d.ts +2 -2
  364. package/dist/jobs/job-runner-context.js +46 -16
  365. package/dist/jobs/job-runner-execution.d.ts +1 -1
  366. package/dist/jobs/job-runner-execution.js +6 -4
  367. package/dist/jobs/job-runner-gates.d.ts +1 -1
  368. package/dist/jobs/job-runner-gates.js +0 -1
  369. package/dist/jobs/job-runner-helpers.d.ts +11 -4
  370. package/dist/jobs/job-runner-helpers.js +10 -1
  371. package/dist/jobs/job-runner-scope.d.ts +5 -2
  372. package/dist/jobs/job-runner-types.d.ts +2 -1
  373. package/dist/jobs/job-runner.js +19 -6
  374. package/dist/jobs/max-per-tenant.d.ts +1 -1
  375. package/dist/logging/index.d.ts +1 -2
  376. package/dist/logging/index.js +1 -1
  377. package/dist/logging/pino-logger.js +1 -1
  378. package/dist/logging/utils.d.ts +1 -0
  379. package/dist/logging/utils.js +6 -0
  380. package/dist/migrations/index.d.ts +3 -3
  381. package/dist/migrations/index.js +3 -3
  382. package/dist/migrations/pending-rebuilds.d.ts +1 -1
  383. package/dist/migrations/pending-rebuilds.js +1 -1
  384. package/dist/migrations/pii-event-backfill.js +4 -1
  385. package/dist/observability/escape-hatch-report.d.ts +2 -1
  386. package/dist/observability/index.d.ts +7 -15
  387. package/dist/observability/index.js +4 -12
  388. package/dist/observability/metric-validator.js +1 -1
  389. package/dist/observability/metrics-handle.d.ts +0 -1
  390. package/dist/observability/metrics-handle.js +2 -15
  391. package/dist/observability/recording-tracer.d.ts +1 -2
  392. package/dist/observability/recording-tracer.js +0 -6
  393. package/dist/observability/sensitive-filter.d.ts +0 -2
  394. package/dist/observability/sensitive-filter.js +0 -29
  395. package/dist/pipeline/active-membership.d.ts +2 -1
  396. package/dist/pipeline/active-membership.js +6 -2
  397. package/dist/pipeline/append-event-core.d.ts +2 -1
  398. package/dist/pipeline/append-event-core.js +2 -2
  399. package/dist/pipeline/attach-outside-transaction.d.ts +3 -0
  400. package/dist/pipeline/attach-outside-transaction.js +13 -0
  401. package/dist/pipeline/auth-claims-resolver.d.ts +2 -1
  402. package/dist/pipeline/cascade-handler.d.ts +2 -1
  403. package/dist/pipeline/cascade-handler.js +3 -2
  404. package/dist/pipeline/config-accessor-factory.d.ts +1 -1
  405. package/dist/pipeline/config-accessor-factory.js +1 -1
  406. package/dist/pipeline/context-services.d.ts +56 -0
  407. package/dist/pipeline/context-services.js +73 -0
  408. package/dist/pipeline/dispatch-batch.d.ts +2 -1
  409. package/dist/pipeline/dispatch-batch.js +31 -18
  410. package/dist/pipeline/dispatch-query.js +5 -4
  411. package/dist/pipeline/dispatch-scope.d.ts +6 -0
  412. package/dist/pipeline/dispatch-scope.js +27 -0
  413. package/dist/pipeline/dispatch-shared.d.ts +13 -9
  414. package/dist/pipeline/dispatch-shared.js +75 -198
  415. package/dist/pipeline/dispatch-stream.js +8 -4
  416. package/dist/pipeline/dispatch-write.d.ts +2 -1
  417. package/dist/pipeline/dispatch-write.js +10 -8
  418. package/dist/pipeline/dispatcher-utils.d.ts +3 -1
  419. package/dist/pipeline/dispatcher-utils.js +8 -2
  420. package/dist/pipeline/dispatcher.d.ts +3 -2
  421. package/dist/pipeline/dispatcher.js +4 -3
  422. package/dist/pipeline/event-consumer-state.d.ts +0 -1
  423. package/dist/pipeline/event-dispatcher-delivery.d.ts +1 -1
  424. package/dist/pipeline/event-dispatcher-delivery.js +4 -2
  425. package/dist/pipeline/event-dispatcher.d.ts +2 -2
  426. package/dist/pipeline/event-dispatcher.js +7 -3
  427. package/dist/pipeline/event-retention.js +59 -56
  428. package/dist/pipeline/handler-access-error.js +2 -1
  429. package/dist/pipeline/handler-context-auth.d.ts +5 -6
  430. package/dist/pipeline/handler-context-auth.js +7 -4
  431. package/dist/pipeline/handler-context-config.d.ts +2 -5
  432. package/dist/pipeline/handler-context-config.js +2 -2
  433. package/dist/pipeline/handler-context-db.d.ts +32 -7
  434. package/dist/pipeline/handler-context-db.js +26 -17
  435. package/dist/pipeline/handler-context-dispatch.d.ts +13 -7
  436. package/dist/pipeline/handler-context-dispatch.js +9 -8
  437. package/dist/pipeline/handler-context-events.d.ts +22 -36
  438. package/dist/pipeline/handler-context-events.js +36 -31
  439. package/dist/pipeline/handler-context-member-resolution.d.ts +2 -0
  440. package/dist/pipeline/handler-context-member-resolution.js +110 -0
  441. package/dist/pipeline/handler-context-notify.d.ts +3 -2
  442. package/dist/pipeline/handler-context-notify.js +1 -1
  443. package/dist/pipeline/handler-context-observability.d.ts +2 -4
  444. package/dist/pipeline/handler-context-observability.js +7 -5
  445. package/dist/pipeline/handler-context-phase-denials.d.ts +11 -0
  446. package/dist/pipeline/handler-context-phase-denials.js +98 -0
  447. package/dist/pipeline/handler-context-scope.d.ts +7 -10
  448. package/dist/pipeline/handler-context-scope.js +18 -20
  449. package/dist/pipeline/index.d.ts +9 -21
  450. package/dist/pipeline/index.js +5 -7
  451. package/dist/pipeline/irreversible-operation-gate.d.ts +1 -1
  452. package/dist/pipeline/irreversible-operation-gate.js +2 -2
  453. package/dist/pipeline/lifecycle-pipeline.d.ts +8 -7
  454. package/dist/pipeline/lifecycle-pipeline.js +9 -15
  455. package/dist/pipeline/member-read-only-transaction.js +11 -3
  456. package/dist/pipeline/member-reader.d.ts +1 -1
  457. package/dist/pipeline/member-reader.js +2 -2
  458. package/dist/pipeline/msp-rebuild.js +5 -3
  459. package/dist/pipeline/multi-stream-apply-context.js +3 -2
  460. package/dist/pipeline/notify-scope.d.ts +2 -1
  461. package/dist/pipeline/pre-handler-gates.d.ts +2 -1
  462. package/dist/pipeline/pre-transaction-reservations.d.ts +3 -3
  463. package/dist/pipeline/pre-transaction-reservations.js +9 -7
  464. package/dist/pipeline/projection-rebuild.js +12 -5
  465. package/dist/pipeline/projection-state.d.ts +0 -6
  466. package/dist/pipeline/projection-state.js +0 -5
  467. package/dist/pipeline/projections-runner.d.ts +2 -1
  468. package/dist/pipeline/projections-runner.js +10 -6
  469. package/dist/pipeline/system-hooks.d.ts +3 -1
  470. package/dist/pipeline/system-hooks.js +6 -4
  471. package/dist/pipeline/system-identity-switch.d.ts +4 -2
  472. package/dist/pipeline/system-identity-switch.js +51 -36
  473. package/dist/pipeline/typed-append-event.d.ts +2 -0
  474. package/dist/pipeline/typed-append-event.js +4 -0
  475. package/dist/pipeline/write-origin.js +2 -2
  476. package/dist/pipeline/write-result-masking.d.ts +1 -1
  477. package/dist/random/index.d.ts +1 -2
  478. package/dist/random/index.js +1 -2
  479. package/dist/rate-limit/bucket.d.ts +2 -1
  480. package/dist/rate-limit/middleware.js +2 -1
  481. package/dist/redis/index.d.ts +3 -4
  482. package/dist/redis/index.js +2 -2
  483. package/dist/schema-cli/apply-command.js +5 -2
  484. package/dist/schema-cli/baseline-command.js +7 -2
  485. package/dist/schema-cli/generate-command.js +7 -9
  486. package/dist/schema-cli/shared.d.ts +4 -0
  487. package/dist/schema-cli/shared.js +21 -2
  488. package/dist/schema-cli/status-command.js +8 -2
  489. package/dist/schema-cli/validate-command.js +52 -4
  490. package/dist/schema-cli.d.ts +0 -1
  491. package/dist/search/configure-tenant-index.d.ts +1 -3
  492. package/dist/search/configure-tenant-index.js +0 -4
  493. package/dist/search/index.d.ts +1 -4
  494. package/dist/search/index.js +0 -2
  495. package/dist/search/meilisearch-adapter-internals.d.ts +8 -0
  496. package/dist/search/meilisearch-adapter-internals.js +9 -0
  497. package/dist/search/meilisearch-adapter.d.ts +1 -8
  498. package/dist/search/meilisearch-adapter.js +6 -7
  499. package/dist/search/meilisearch-peer.d.ts +2 -0
  500. package/dist/search/meilisearch-peer.js +5 -0
  501. package/dist/search/reindex-entity.js +93 -87
  502. package/dist/secrets/index.d.ts +3 -4
  503. package/dist/secrets/index.js +2 -3
  504. package/dist/seeding/index.d.ts +2 -2
  505. package/dist/seeding/index.js +1 -2
  506. package/dist/time/index.d.ts +2 -2
  507. package/dist/time/index.js +1 -1
  508. package/dist/time/tz-context.d.ts +0 -5
  509. package/dist/time/tz-context.js +0 -9
  510. package/dist/ui-types/index.d.ts +8 -11
  511. package/dist/ui-types/index.js +3 -3
  512. package/dist/upgrade-changelog.d.ts +3 -2
  513. package/dist/upgrade-changelog.js +12 -8
  514. package/dist/upgrade-cli-internals.d.ts +8 -0
  515. package/dist/upgrade-cli-internals.js +63 -0
  516. package/dist/upgrade-cli.d.ts +1 -9
  517. package/dist/upgrade-cli.js +10 -64
  518. package/dist/utils/import-optional-peer.d.ts +6 -0
  519. package/dist/utils/import-optional-peer.js +19 -0
  520. package/dist/utils/index.d.ts +1 -4
  521. package/dist/utils/index.js +1 -4
  522. package/package.json +22 -18
  523. package/src/changes.json +206 -0
  524. package/dist/crypto/request-kms-cache.d.ts +0 -8
  525. package/dist/crypto/request-kms-cache.js +0 -21
  526. package/dist/engine/codemod/index.d.ts +0 -2
  527. package/dist/engine/codemod/index.js +0 -1
  528. package/dist/engine/codemod/pipeline-codemod.d.ts +0 -50
  529. package/dist/engine/codemod/pipeline-codemod.js +0 -536
  530. package/dist/engine/feature-ast/entity-field-types.d.ts +0 -13
  531. package/dist/engine/feature-ast/entity-field-types.js +0 -35
  532. package/dist/engine/feature-ast/extractors/ai-steps.d.ts +0 -6
  533. package/dist/engine/feature-ast/extractors/ai-steps.js +0 -254
  534. package/dist/engine/feature-ast/extractors/events.d.ts +0 -5
  535. package/dist/engine/feature-ast/extractors/events.js +0 -275
  536. package/dist/engine/feature-ast/extractors/handlers.d.ts +0 -24
  537. package/dist/engine/feature-ast/extractors/handlers.js +0 -358
  538. package/dist/engine/feature-ast/extractors/hooks.d.ts +0 -24
  539. package/dist/engine/feature-ast/extractors/hooks.js +0 -248
  540. package/dist/engine/feature-ast/extractors/index.d.ts +0 -14
  541. package/dist/engine/feature-ast/extractors/index.js +0 -13
  542. package/dist/engine/feature-ast/extractors/jobs-routes.d.ts +0 -7
  543. package/dist/engine/feature-ast/extractors/jobs-routes.js +0 -145
  544. package/dist/engine/feature-ast/extractors/projections-screens.d.ts +0 -10
  545. package/dist/engine/feature-ast/extractors/projections-screens.js +0 -195
  546. package/dist/engine/feature-ast/extractors/resolve-import.d.ts +0 -21
  547. package/dist/engine/feature-ast/extractors/resolve-import.js +0 -180
  548. package/dist/engine/feature-ast/extractors/round1.d.ts +0 -11
  549. package/dist/engine/feature-ast/extractors/round1.js +0 -87
  550. package/dist/engine/feature-ast/extractors/round2.d.ts +0 -7
  551. package/dist/engine/feature-ast/extractors/round2.js +0 -191
  552. package/dist/engine/feature-ast/extractors/round3.d.ts +0 -23
  553. package/dist/engine/feature-ast/extractors/round3.js +0 -292
  554. package/dist/engine/feature-ast/extractors/round5.d.ts +0 -9
  555. package/dist/engine/feature-ast/extractors/round5.js +0 -68
  556. package/dist/engine/feature-ast/extractors/round6.d.ts +0 -4
  557. package/dist/engine/feature-ast/extractors/round6.js +0 -17
  558. package/dist/engine/feature-ast/extractors/shared.d.ts +0 -94
  559. package/dist/engine/feature-ast/extractors/shared.js +0 -343
  560. package/dist/engine/feature-ast/index.d.ts +0 -16
  561. package/dist/engine/feature-ast/index.js +0 -10
  562. package/dist/engine/feature-ast/parse.d.ts +0 -31
  563. package/dist/engine/feature-ast/parse.js +0 -485
  564. package/dist/engine/feature-ast/patch.d.ts +0 -212
  565. package/dist/engine/feature-ast/patch.js +0 -611
  566. package/dist/engine/feature-ast/patcher.d.ts +0 -217
  567. package/dist/engine/feature-ast/patcher.js +0 -281
  568. package/dist/engine/feature-ast/pattern-change-schema.d.ts +0 -1238
  569. package/dist/engine/feature-ast/pattern-change-schema.js +0 -1072
  570. package/dist/engine/feature-ast/pattern-id-matchers.d.ts +0 -7
  571. package/dist/engine/feature-ast/pattern-id-matchers.js +0 -211
  572. package/dist/engine/feature-ast/pattern-id-schema.d.ts +0 -251
  573. package/dist/engine/feature-ast/pattern-id-schema.js +0 -166
  574. package/dist/engine/feature-ast/patterns.d.ts +0 -322
  575. package/dist/engine/feature-ast/patterns.js +0 -107
  576. package/dist/engine/feature-ast/render.d.ts +0 -47
  577. package/dist/engine/feature-ast/render.js +0 -666
  578. package/dist/engine/feature-ast/source-location.d.ts +0 -17
  579. package/dist/engine/feature-ast/source-location.js +0 -27
  580. package/dist/engine/pattern-library/index.d.ts +0 -2
  581. package/dist/engine/pattern-library/index.js +0 -3
  582. package/dist/engine/pattern-library/library.d.ts +0 -14
  583. package/dist/engine/pattern-library/library.js +0 -94
  584. package/dist/engine/pattern-library/mixed-schemas.d.ts +0 -16
  585. package/dist/engine/pattern-library/mixed-schemas.js +0 -559
  586. package/dist/engine/pattern-library/opaque-schemas.d.ts +0 -7
  587. package/dist/engine/pattern-library/opaque-schemas.js +0 -115
  588. package/dist/engine/pattern-library/shared-fields.d.ts +0 -122
  589. package/dist/engine/pattern-library/shared-fields.js +0 -88
  590. package/dist/engine/pattern-library/static-schemas.d.ts +0 -21
  591. package/dist/engine/pattern-library/static-schemas.js +0 -487
  592. package/dist/engine/pattern-library/types.d.ts +0 -158
  593. package/dist/engine/pattern-library/types.js +0 -36
  594. package/dist/engine/resolve-config-or-param.d.ts +0 -18
  595. package/dist/engine/resolve-config-or-param.js +0 -76
  596. package/src/scripts/codemod/README.md +0 -187
  597. package/src/scripts/codemod/codemod-support.ts +0 -334
  598. package/src/scripts/codemod/collect-source-files.ts +0 -48
  599. package/src/scripts/codemod/crypto-shredding-testing-move.ts +0 -119
  600. package/src/scripts/codemod/db-factory.ts +0 -810
  601. package/src/scripts/codemod/feature-factory.ts +0 -429
  602. package/src/scripts/codemod/feature-layout.ts +0 -424
  603. package/src/scripts/codemod/import-extensions.ts +0 -118
  604. package/src/scripts/codemod/migrate-cross-tenant.ts +0 -328
  605. package/src/scripts/codemod/migrate-db-raw.ts +0 -401
  606. package/src/scripts/codemod/migrate-open-to-all.ts +0 -235
  607. package/src/scripts/codemod/object-form.ts +0 -746
  608. package/src/scripts/codemod/package-merge.ts +0 -299
  609. package/src/scripts/codemod/pii-personal-migration.ts +0 -816
  610. package/src/scripts/codemod/remove-engine-payload-casts.ts +0 -318
  611. package/src/scripts/codemod/s3-imports.ts +0 -236
  612. package/src/scripts/codemod/tenant-db-options.ts +0 -454
  613. package/src/scripts/codemod/testing-injection.ts +0 -215
  614. package/src/scripts/codemod/testing-move-targets.ts +0 -161
  615. package/src/scripts/codemod/testing-move.ts +0 -542
  616. package/src/scripts/codemod/unprocessable-error-details-reason.ts +0 -411
@@ -17,41 +17,47 @@ import { toSnakeCase } from "../utils/case.js";
17
17
  import { resolveTableName } from "./entity-table-meta.js";
18
18
  import { toPostgresArrayLiteral } from "./queries/postgres-array-literal.js";
19
19
  import { executeRawQuery, executeRawQueryRead } from "./queries/raw-sql.js";
20
+ import { runInSystemRowLevelSecurityScope } from "./row-level-security-scope.js";
20
21
  import { columnNamesOf, tableExists } from "./schema-inspection.js";
21
22
  export async function nullBlindIndexesForSubject(db, features, subjectKey) {
22
- const likePattern = subjectCiphertextLikePattern(subjectKey);
23
- const candidates = [];
24
- for (const feature of features.values()) {
25
- for (const [entityName, entity] of Object.entries(feature.entities ?? {})) {
26
- const lookupable = collectLookupableFields(entity);
27
- if (lookupable.length === 0)
28
- continue;
29
- // No featureName prefix — the dispatcher builds entity tables without
30
- // one (buildEntityTable with no featureName option), the sweep has to
31
- // hit the same names.
32
- candidates.push({ tableName: resolveTableName(entityName, entity, undefined), lookupable });
23
+ return runInSystemRowLevelSecurityScope("blind index nulling for a forgotten subject spans tenants", async () => {
24
+ const likePattern = subjectCiphertextLikePattern(subjectKey);
25
+ const candidates = [];
26
+ for (const feature of features.values()) {
27
+ for (const [entityName, entity] of Object.entries(feature.entities ?? {})) {
28
+ const lookupable = collectLookupableFields(entity);
29
+ if (lookupable.length === 0)
30
+ continue;
31
+ // No featureName prefix — the dispatcher builds entity tables without
32
+ // one (buildEntityTable with no featureName option), the sweep has to
33
+ // hit the same names.
34
+ candidates.push({
35
+ tableName: resolveTableName(entityName, entity, undefined),
36
+ lookupable,
37
+ });
38
+ }
33
39
  }
34
- }
35
- // Skip entities whose projection was never migrated — same class as
36
- // subjectRowExistsInTenant. A throw here runs AFTER eraseKey
37
- // in forget-subject and would leave deterministic bidx columns still
38
- // linkable. One batched existence query instead of one
39
- // roundtrip per entity.
40
- const existing = await existingTableNames(db, candidates.map((c) => c.tableName));
41
- for (const { tableName, lookupable } of candidates) {
42
- if (!existing.has(tableName))
43
- continue;
44
- // Same hazard for a migrated table that predates a later-added
45
- // lookupable field: skip fields whose columns are missing instead of
46
- // aborting the sweep for the remaining ones.
47
- const columns = await columnNamesOf(db, tableName);
48
- for (const fieldName of lookupable) {
49
- const snake = toSnakeCase(fieldName);
50
- if (!columns.has(snake) || !columns.has(`${snake}_bidx`))
40
+ // Skip entities whose projection was never migrated — same class as
41
+ // subjectRowExistsInTenant. A throw here runs AFTER eraseKey
42
+ // in forget-subject and would leave deterministic bidx columns still
43
+ // linkable. One batched existence query instead of one
44
+ // roundtrip per entity.
45
+ const existing = await existingTableNames(db, candidates.map((c) => c.tableName));
46
+ for (const { tableName, lookupable } of candidates) {
47
+ if (!existing.has(tableName))
51
48
  continue;
52
- await executeRawQuery(db, `UPDATE ${quoteIdent(tableName)} SET ${quoteIdent(`${snake}_bidx`)} = NULL WHERE ${quoteIdent(snake)} LIKE $1`, [likePattern]);
49
+ // Same hazard for a migrated table that predates a later-added
50
+ // lookupable field: skip fields whose columns are missing instead of
51
+ // aborting the sweep for the remaining ones.
52
+ const columns = await columnNamesOf(db, tableName);
53
+ for (const fieldName of lookupable) {
54
+ const snake = toSnakeCase(fieldName);
55
+ if (!columns.has(snake) || !columns.has(`${snake}_bidx`))
56
+ continue;
57
+ await executeRawQuery(db, `UPDATE ${quoteIdent(tableName)} SET ${quoteIdent(`${snake}_bidx`)} = NULL WHERE ${quoteIdent(snake)} LIKE $1`, [likePattern]);
58
+ }
53
59
  }
54
- }
60
+ });
55
61
  }
56
62
  async function existingTableNames(db, tableNames) {
57
63
  if (tableNames.length === 0)
@@ -75,37 +81,39 @@ async function existingTableNames(db, tableNames) {
75
81
  // (`aggregate_id = subjectId` under the actor tenant) when apps need
76
82
  // client-supplied ids.
77
83
  export async function subjectRowExistsInTenant(db, features, subjectId, tenantId) {
78
- // Prefetch which self-PII projection tables actually exist — probing a
79
- // missing relation used to throw (and get swallowed), which both hid
80
- // real schema bugs and risked poisoning the driver connection for the
81
- // rest of the forget TX.
82
- const candidateTables = [];
83
- for (const feature of features.values()) {
84
- for (const [entityName, entity] of Object.entries(feature.entities ?? {})) {
85
- const hasSelfPiiField = Object.values(entity.fields).some(isSelfPiiField);
86
- if (!hasSelfPiiField)
87
- continue;
88
- // Subject ids are uuids; comparing one to a serial id column makes
89
- // postgres throw (invalid input syntax for integer) mid forget-TX.
90
- if (entity.idType === "serial")
84
+ return runInSystemRowLevelSecurityScope("subject existence check spans tenants", async () => {
85
+ // Prefetch which self-PII projection tables actually exist — probing a
86
+ // missing relation used to throw (and get swallowed), which both hid
87
+ // real schema bugs and risked poisoning the driver connection for the
88
+ // rest of the forget TX.
89
+ const candidateTables = [];
90
+ for (const feature of features.values()) {
91
+ for (const [entityName, entity] of Object.entries(feature.entities ?? {})) {
92
+ const hasSelfPiiField = Object.values(entity.fields).some(isSelfPiiField);
93
+ if (!hasSelfPiiField)
94
+ continue;
95
+ // Subject ids are uuids; comparing one to a serial id column makes
96
+ // postgres throw (invalid input syntax for integer) mid forget-TX.
97
+ if (entity.idType === "serial")
98
+ continue;
99
+ candidateTables.push(resolveTableName(entityName, entity, undefined));
100
+ }
101
+ }
102
+ const existing = new Set();
103
+ for (const tableName of candidateTables) {
104
+ const rows = await executeRawQueryRead(db, `SELECT to_regclass(quote_ident($1)) IS NOT NULL AS exists`, [tableName]);
105
+ if (rows[0]?.exists === true)
106
+ existing.add(tableName);
107
+ }
108
+ for (const tableName of candidateTables) {
109
+ if (!existing.has(tableName))
91
110
  continue;
92
- candidateTables.push(resolveTableName(entityName, entity, undefined));
111
+ const rows = await executeRawQueryRead(db, `SELECT 1 FROM ${quoteIdent(tableName)} WHERE id = $1 AND tenant_id = $2 LIMIT 1`, [subjectId, tenantId]);
112
+ if (rows.length > 0)
113
+ return true;
93
114
  }
94
- }
95
- const existing = new Set();
96
- for (const tableName of candidateTables) {
97
- const rows = await executeRawQueryRead(db, `SELECT to_regclass(quote_ident($1)) IS NOT NULL AS exists`, [tableName]);
98
- if (rows[0]?.exists === true)
99
- existing.add(tableName);
100
- }
101
- for (const tableName of candidateTables) {
102
- if (!existing.has(tableName))
103
- continue;
104
- const rows = await executeRawQueryRead(db, `SELECT 1 FROM ${quoteIdent(tableName)} WHERE id = $1 AND tenant_id = $2 LIMIT 1`, [subjectId, tenantId]);
105
- if (rows.length > 0)
106
- return true;
107
- }
108
- return false;
115
+ return false;
116
+ });
109
117
  }
110
118
  function findEntityByExactName(features, entityName) {
111
119
  for (const feature of features.values()) {
@@ -123,14 +131,16 @@ function findEntityByExactName(features, entityName) {
123
131
  // table (globally unique, unspoofable via a client-supplied explicitId
124
132
  // at create) — a composite PK or shared table would break this.
125
133
  export async function recordRowExistsInTenant(db, features, entityName, recordId, tenantId) {
126
- const entity = findEntityByExactName(features, entityName);
127
- if (!entity)
128
- return false;
129
- const tableName = resolveTableName(entityName, entity, undefined);
130
- if (!(await tableExists(db, tableName)))
131
- return false;
132
- const rows = await executeRawQueryRead(db, `SELECT 1 FROM ${quoteIdent(tableName)} WHERE id = $1 AND tenant_id = $2 LIMIT 1`, [recordId, tenantId]);
133
- return rows.length > 0;
134
+ return runInSystemRowLevelSecurityScope("record existence check spans tenants", async () => {
135
+ const entity = findEntityByExactName(features, entityName);
136
+ if (!entity)
137
+ return false;
138
+ const tableName = resolveTableName(entityName, entity, undefined);
139
+ if (!(await tableExists(db, tableName)))
140
+ return false;
141
+ const rows = await executeRawQueryRead(db, `SELECT 1 FROM ${quoteIdent(tableName)} WHERE id = $1 AND tenant_id = $2 LIMIT 1`, [recordId, tenantId]);
142
+ return rows.length > 0;
143
+ });
134
144
  }
135
145
  // Provenance fallback for record subjects whose projection row is gone (hard
136
146
  // delete) or that have no registered entity at all (custom aggregates): the
@@ -138,20 +148,24 @@ export async function recordRowExistsInTenant(db, features, entityName, recordId
138
148
  // and the subject key is global, so another tenant could open a stream under
139
149
  // the same aggregate id; any foreign event voids the proof.
140
150
  export async function recordEventsOwnedExclusivelyByTenant(db, aggregateType, aggregateId, tenantId) {
141
- const rows = await executeRawQueryRead(db, `SELECT 1 FROM "kumiko_events" WHERE aggregate_type = $1 AND aggregate_id = $2::uuid AND tenant_id = $3::uuid
151
+ return runInSystemRowLevelSecurityScope("record event ownership check spans tenants", async () => {
152
+ const rows = await executeRawQueryRead(db, `SELECT 1 FROM "kumiko_events" WHERE aggregate_type = $1 AND aggregate_id = $2::uuid AND tenant_id = $3::uuid
142
153
  AND NOT EXISTS (SELECT 1 FROM "kumiko_events" WHERE aggregate_type = $1 AND aggregate_id = $2::uuid AND tenant_id <> $3::uuid)
143
154
  LIMIT 1`, [aggregateType, aggregateId, tenantId]);
144
- return rows.length > 0;
155
+ return rows.length > 0;
156
+ });
145
157
  }
146
158
  // Owning tenant of a record subject's row, for callers that must evaluate
147
159
  // tenant-scoped policy for the row's real owner (not the acting user's tenant).
148
160
  export async function recordRowOwningTenantId(db, features, entityName, recordId) {
149
- const entity = findEntityByExactName(features, entityName);
150
- if (!entity)
151
- return undefined;
152
- const tableName = resolveTableName(entityName, entity, undefined);
153
- if (!(await tableExists(db, tableName)))
154
- return undefined;
155
- const rows = await executeRawQueryRead(db, `SELECT tenant_id FROM ${quoteIdent(tableName)} WHERE id = $1 LIMIT 1`, [recordId]);
156
- return rows[0]?.tenant_id;
161
+ return runInSystemRowLevelSecurityScope("record owner lookup spans tenants", async () => {
162
+ const entity = findEntityByExactName(features, entityName);
163
+ if (!entity)
164
+ return undefined;
165
+ const tableName = resolveTableName(entityName, entity, undefined);
166
+ if (!(await tableExists(db, tableName)))
167
+ return undefined;
168
+ const rows = await executeRawQueryRead(db, `SELECT tenant_id FROM ${quoteIdent(tableName)} WHERE id = $1 LIMIT 1`, [recordId]);
169
+ return rows[0]?.tenant_id;
170
+ });
157
171
  }
@@ -1,7 +1,7 @@
1
1
  // Canonical table source for both `kumiko schema generate` and setupTestStack
2
2
  // (entities, storeTables, projections, multiStreamProjections). One shared
3
3
  // source so the test-DB push and migrations cannot drift apart again.
4
- import { compareByCodepoint } from "../utils/index.js";
4
+ import { compareByCodepoint } from "../utils/compare.js";
5
5
  import { assertBackingTableSuperset, deriveEntityTableMeta, } from "./entity-table-meta.js";
6
6
  import { enumerateFeatureTableSources } from "./feature-table-sources.js";
7
7
  import { asEntityTableMeta } from "./query.js";
@@ -1,4 +1,4 @@
1
- import type { EntityDefinition } from "../engine/types/index.ts";
1
+ import type { EntityDefinition } from "@cosmicdrift/kumiko-types/fields";
2
2
  /**
3
3
  * API-Form (combined) → DB-Form (flat). Wird vor jedem Insert/Update aufgerufen.
4
4
  */
@@ -1,10 +1,3 @@
1
- // Compound-type pipeline for the executor.
2
- //
3
- // A compound type is a field represented by ONE API object and MULTIPLE
4
- // DB columns. Examples:
5
- // - locatedTimestamp: { at, tz, utc } ↔ <name>Utc + <name>Tz
6
- // - money: { amount, currency } ↔ <name> + <name>Currency
7
- // - (upcoming) address: { street, zip, city } ↔ <name>Street + <name>Zip + <name>City
8
1
  //
9
2
  // Instead of nesting every helper in the executor at four different points,
10
3
  // this function pipelines all compound-type conversions in one pass. Adding
@@ -1,5 +1,6 @@
1
+ import type { ConfigSeedDef } from "@cosmicdrift/kumiko-types/config";
1
2
  import type { EntityDefinition } from "../engine/index.ts";
2
- import type { ConfigSeedDef, Registry } from "../engine/types/index.ts";
3
+ import type { Registry } from "../engine/types/index.ts";
3
4
  import type { EnvelopeCipher } from "../secrets/envelope-cipher.ts";
4
5
  import type { DbConnection } from "./connection.ts";
5
6
  import type { EntityTable } from "./table-builder.ts";
@@ -24,7 +24,12 @@ export async function seedConfigValues(seeds, table, entity, registry, db, ciphe
24
24
  return { created, skipped };
25
25
  const systemUser = createSystemUser(SYSTEM_TENANT_ID);
26
26
  const executor = createEventStoreExecutor(table, entity, { entityName: "config-value" });
27
- const tdb = createTenantDb({ db, tenantId: SYSTEM_TENANT_ID, mode: "system" });
27
+ const tdb = createTenantDb({
28
+ db,
29
+ tenantId: SYSTEM_TENANT_ID,
30
+ mode: "system",
31
+ reason: "config seeds are system-tenant defaults",
32
+ });
28
33
  for (const seed of seeds) {
29
34
  const keyDef = registry.getConfigKey(seed.key);
30
35
  if (!keyDef) {
@@ -1,4 +1,5 @@
1
1
  import type { DbConnection, PgClient, PgListenClient } from "@cosmicdrift/kumiko-types/db-connection";
2
+ import { type RowLevelSecurityMode } from "./render-rls-ddl.ts";
2
3
  export type * from "@cosmicdrift/kumiko-types/db-connection";
3
4
  type BunSqlOptions = Bun.SQL.PostgresOrMySQLOptions;
4
5
  export type DbConnectionOptions = {
@@ -13,6 +14,7 @@ export type DbConnectionOptions = {
13
14
  };
14
15
  export type CreateDbConnectionOptions = DbConnectionOptions & {
15
16
  readonly url: string;
17
+ readonly rowLevelSecurity?: RowLevelSecurityMode;
16
18
  };
17
19
  export type DbConnectionHandle = {
18
20
  db: DbConnection;
@@ -26,7 +28,7 @@ export type UnboundedSiblingPool = {
26
28
  readonly close: (timeoutSeconds: number) => Promise<void>;
27
29
  };
28
30
  export declare function openUnboundedSiblingPool(db: unknown): UnboundedSiblingPool | undefined;
29
- export declare function createDbConnection({ url, ...options }: CreateDbConnectionOptions): DbConnectionHandle;
31
+ export declare function createDbConnection({ url, rowLevelSecurity, ...options }: CreateDbConnectionOptions): DbConnectionHandle;
30
32
  export declare function dbConnectionOptionsFromEnv(env?: Readonly<Record<string, string | undefined>>): DbConnectionOptions;
31
33
  export declare const DEFAULT_SERVER_STATEMENT_TIMEOUT_MS = 60000;
32
34
  export declare const DEFAULT_SERVER_IDLE_IN_TRANSACTION_TIMEOUT_MS = 300000;
@@ -1,4 +1,6 @@
1
1
  import { readPositiveIntEnv } from "../utils/env-parse.js";
2
+ import { DEFAULT_ROW_LEVEL_SECURITY_MODE } from "./render-rls-ddl.js";
3
+ import { enforceRowLevelSecurity } from "./row-level-security-connection.js";
2
4
  // A DB outage can leave an in-flight query referenced on a dead connection,
3
5
  // so a plain close() (no timeout = wait for queries to finish) hangs forever —
4
6
  // close() must always bound how long shutdown waits.
@@ -20,7 +22,7 @@ function verifiedTls(ssl) {
20
22
  }
21
23
  return ssl;
22
24
  }
23
- export function createDbConnection({ url, ...options }) {
25
+ export function createDbConnection({ url, rowLevelSecurity = DEFAULT_ROW_LEVEL_SECURITY_MODE, ...options }) {
24
26
  const sqlOptions = {};
25
27
  if (options.maxConnections !== undefined)
26
28
  sqlOptions.max = options.maxConnections;
@@ -45,11 +47,18 @@ export function createDbConnection({ url, ...options }) {
45
47
  if (Object.keys(serverParameters).length > 0)
46
48
  sqlOptions.connection = serverParameters;
47
49
  // Bun.SQL opens all `max` connections on the first query, so a pool always costs `max` backends.
48
- const client = new Bun.SQL(url, sqlOptions);
50
+ const rawClient = new Bun.SQL(url, sqlOptions);
51
+ const enforced = rowLevelSecurity === "on";
52
+ const client = enforced ? enforceRowLevelSecurity(rawClient) : rawClient;
49
53
  // A run that never settles (a caller gave up on it via its own timeout) never reaches the
50
54
  // sibling's own close; close() ends it so shutdown and DROP DATABASE are not blocked by it.
51
55
  const openSiblings = new Set();
52
- unboundedSiblingFactories.set(client, () => {
56
+ const registerFactory = (factory) => {
57
+ unboundedSiblingFactories.set(rawClient, factory);
58
+ if (client !== rawClient)
59
+ unboundedSiblingFactories.set(client, factory);
60
+ };
61
+ registerFactory(() => {
53
62
  // Two connections are enough for lock-in-tx plus DDL; the cap keeps parallel rebuilds from exhausting max_connections.
54
63
  const sibling = new Bun.SQL(url, {
55
64
  ...sqlOptions,
@@ -58,7 +67,7 @@ export function createDbConnection({ url, ...options }) {
58
67
  });
59
68
  openSiblings.add(sibling);
60
69
  return {
61
- client: sibling,
70
+ client: enforced ? enforceRowLevelSecurity(sibling) : sibling,
62
71
  close: async (timeoutSeconds) => {
63
72
  openSiblings.delete(sibling);
64
73
  await sibling.close({ timeout: timeoutSeconds });
@@ -71,8 +80,9 @@ export function createDbConnection({ url, ...options }) {
71
80
  listenClient: client,
72
81
  close: async () => {
73
82
  const timeout = options.closeTimeoutSeconds ?? DEFAULT_DB_CLOSE_TIMEOUT_SECONDS;
83
+ unboundedSiblingFactories.delete(rawClient);
74
84
  unboundedSiblingFactories.delete(client);
75
- const pools = [client, ...openSiblings];
85
+ const pools = [rawClient, ...openSiblings];
76
86
  openSiblings.clear();
77
87
  const results = await Promise.allSettled(pools.map((pool) => pool.close({ timeout })));
78
88
  const failure = results.find((result) => result.status === "rejected");
@@ -1,5 +1,5 @@
1
+ import type { EscapeHatchReporter } from "@cosmicdrift/kumiko-types/handlers";
1
2
  import type { CrossTenantReads } from "@cosmicdrift/kumiko-types/tenant-db-types";
2
- import type { EscapeHatchReporter } from "../engine/types/index.ts";
3
3
  import { type CreateTenantDbOptions, type TenantDb } from "./tenant-db.ts";
4
4
  export declare function createCrossTenantReads(systemModeDb: TenantDb, reason: string, report: EscapeHatchReporter): CrossTenantReads;
5
5
  export declare function createHandlerCrossTenantReads(options: Omit<CreateTenantDbOptions, "mode"> & {
@@ -18,6 +18,6 @@ export function createCrossTenantReads(systemModeDb, reason, report) {
18
18
  // Own system-mode TenantDb without unsafeRaw/globalWrites: the handler gets the read surface only.
19
19
  export function createHandlerCrossTenantReads(options) {
20
20
  const { reason, report, ...dbOptions } = options;
21
- const systemModeDb = createTenantDb({ ...dbOptions, mode: "system" });
21
+ const systemModeDb = createTenantDb({ ...dbOptions, mode: "system", reason });
22
22
  return createCrossTenantReads(systemModeDb, reason, report);
23
23
  }
@@ -4,7 +4,6 @@ import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
4
4
  import type { PgType } from "./entity-table-meta.ts";
5
5
  export type { ColumnHandle, SchemaTable } from "@cosmicdrift/kumiko-types/schema-table-types";
6
6
  export type TableColumns<_T = unknown> = SchemaTable;
7
- export type SelectQuery = unknown;
8
7
  export declare function pgTypeToSqlType(pgType: PgType): string;
9
8
  type ColumnFinal = {
10
9
  readonly sqlName: string;
@@ -46,10 +45,6 @@ export declare function timestamp(name: string, _opts?: {
46
45
  withTimezone?: boolean;
47
46
  mode?: "string" | "date";
48
47
  }): ColumnBuilder<Temporal.Instant | string>;
49
- export declare function numeric(name: string, _opts?: {
50
- precision?: number;
51
- scale?: number;
52
- }): ColumnBuilder<string>;
53
48
  export declare function instant(name: string, opts?: {
54
49
  precision?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
55
50
  }): ColumnBuilder<Temporal.Instant>;
@@ -180,9 +180,6 @@ export function timestamp(name, _opts) {
180
180
  }
181
181
  // numeric → text (we don't currently use Decimal); kept for compat with
182
182
  // legacy schema imports that won't actually instantiate at runtime.
183
- export function numeric(name, _opts) {
184
- return buildColumn(name, "text");
185
- }
186
183
  export function instant(name, opts) {
187
184
  const pgType = opts?.precision === 3 ? "timestamptz(3)" : "timestamptz";
188
185
  return buildColumn(name, pgType);
@@ -1,4 +1,5 @@
1
- import type { EntityDefinition, SessionUser } from "../engine/types/index.ts";
1
+ import type { EntityDefinition } from "@cosmicdrift/kumiko-types/fields";
2
+ import type { SessionUser } from "../engine/types/index.ts";
2
3
  import { type ParentVisibilityOption } from "./parent-ref-clause.ts";
3
4
  import type { TenantDb } from "./tenant-db.ts";
4
5
  export type EagerLoadEntityResolver = (entityName: string) => EntityDefinition | undefined;
@@ -1,4 +1,4 @@
1
- import type { EntityDefinition } from "../engine/types/index.ts";
1
+ import type { EntityDefinition } from "@cosmicdrift/kumiko-types/fields";
2
2
  import { type Logger } from "../logging/index.ts";
3
3
  import type { EnvelopeCipher } from "../secrets/envelope-cipher.ts";
4
4
  export declare function collectEncryptedFieldNames(entity: EntityDefinition): ReadonlySet<string>;
@@ -1,6 +1,6 @@
1
1
  import type { Writable } from "@cosmicdrift/kumiko-types/executor-brand";
2
+ import type { EntityDefinition } from "@cosmicdrift/kumiko-types/fields";
2
3
  import type { EntityTenancy, TenancyBrand } from "@cosmicdrift/kumiko-types/tenancy-brand";
3
- import type { EntityDefinition } from "../engine/types/index.ts";
4
4
  import type { BuildEntityTableMetaOptions, EntityTableMeta, UnmanagedTableInput } from "./entity-table-meta-types.ts";
5
5
  export type { BuildEntityTableMetaOptions, ColumnMeta, CompositePrimaryKeyMeta, EntityTableMeta, IndexMeta, PgType, UnmanagedTableInput, } from "./entity-table-meta-types.ts";
6
6
  export declare function resolveTableName(entityName: string, entity: EntityDefinition, featureName: string | undefined): string;
@@ -1,6 +1,8 @@
1
+ import type { EntityDefinition } from "@cosmicdrift/kumiko-types/fields";
2
+ import type { EntityId } from "@cosmicdrift/kumiko-types/identifiers";
1
3
  import type { ErasedSubjectHandling } from "../crypto/pii-field-encryption.ts";
2
4
  import type { WhereObject } from "../db/query.ts";
3
- import type { EntityDefinition, EntityId, SessionUser, TenantId } from "../engine/types/index.ts";
5
+ import type { SessionUser, TenantId } from "../engine/types/index.ts";
4
6
  import { type WriteFailure } from "../errors/index.ts";
5
7
  import { type EventMetadata } from "../event-store/index.ts";
6
8
  import type { EntityCache } from "../pipeline/entity-cache.ts";
@@ -5,7 +5,8 @@ import { executeRawQueryRead } from "../db/queries/raw-sql.js";
5
5
  import { shiftParams } from "../engine/ownership.js";
6
6
  import { SYSTEM_TENANT_ID } from "../engine/types/identifiers.js";
7
7
  import { AccessDeniedError, InternalError, subjectErasedConflict, UniqueViolationError, writeFailure, } from "../errors/index.js";
8
- import { ArchivedStreamError, isStreamArchived } from "../event-store/index.js";
8
+ import { ArchivedStreamError } from "../event-store/errors.js";
9
+ import { isStreamArchived } from "../event-store/index.js";
9
10
  import { assertUnreachable } from "../utils/index.js";
10
11
  import { rehydrateCompoundTypes } from "./compound-types.js";
11
12
  import { collectEncryptedFieldNames, decryptEntityFieldValues, encryptEntityFieldValues, logUndecryptableField, resolveEntityFieldEncryption, } from "./entity-field-encryption.js";
@@ -120,7 +121,7 @@ export function buildExecutorContext(table, entity, options) {
120
121
  // old hardcoded user.tenantId). Single source of truth for the stream key.
121
122
  const streamTenantFor = (user, requestedStreamTenantId) => entity.systemStream ? SYSTEM_TENANT_ID : (requestedStreamTenantId ?? user.tenantId);
122
123
  // Only a system-mode db (r.systemScope() / acknowledged cross-tenant) or a tenant-mode db bound
123
- // to exactly that stream tenant (ctx.forTenant) may address another tenant's stream, and only
124
+ // to exactly that stream tenant (ctx.tenants.writeTarget) may address another tenant's stream, and only
124
125
  // the tenant of the row it just loaded.
125
126
  const streamTenantOverrideFailure = (db, row, requestedStreamTenantId) => {
126
127
  if (requestedStreamTenantId === undefined)
@@ -293,7 +294,7 @@ export function buildExecutorContext(table, entity, options) {
293
294
  return await decryptForRead(rehydrateCompoundTypes(row, entity));
294
295
  }
295
296
  // Archive guard for the CRUD write paths. Archived streams are read-only —
296
- // ctx.appendEvent (append-event-core) already enforces this, but the
297
+ // ctx.events.append (append-event-core) already enforces this, but the
297
298
  // executor appends directly via append() and getStreamVersion() ignores
298
299
  // the archive flag, so without this check a PATCH/DELETE on an archived
299
300
  // entity would silently land an event and break the read-only contract
@@ -1,5 +1,5 @@
1
+ import type { EntityDefinition } from "@cosmicdrift/kumiko-types/fields";
1
2
  import { type OwnershipClause } from "../engine/ownership.ts";
2
- import type { EntityDefinition } from "../engine/types/index.ts";
3
3
  import { type Table } from "./event-store-executor-context.ts";
4
4
  export type ListWhere = {
5
5
  readonly whereSql: string[];
@@ -1,4 +1,5 @@
1
- import type { EntityDefinition, TenantId } from "../engine/types/index.ts";
1
+ import type { EntityDefinition } from "@cosmicdrift/kumiko-types/fields";
2
+ import type { TenantId } from "../engine/types/index.ts";
2
3
  import type { TableInfo } from "./table-info.ts";
3
4
  export declare function withStreamVersion(row: Record<string, unknown>, streamVersion: number): Record<string, unknown>;
4
5
  export declare function coerceAndRehydrateRow(raw: Record<string, unknown>, tableInfo: TableInfo, entity: EntityDefinition): Record<string, unknown>;
@@ -1,5 +1,6 @@
1
+ import type { EntityDefinition } from "@cosmicdrift/kumiko-types/fields";
1
2
  import { type OwnershipClause } from "../engine/ownership.ts";
2
- import type { EntityDefinition, SessionUser, TenantId } from "../engine/types/index.ts";
3
+ import type { SessionUser, TenantId } from "../engine/types/index.ts";
3
4
  import type { SearchAdapter } from "../search/types.ts";
4
5
  import type { EventStoreExecutor } from "./event-store-executor.ts";
5
6
  import type { Table } from "./event-store-executor-context.ts";
@@ -1,5 +1,6 @@
1
+ import type { EntityDefinition } from "@cosmicdrift/kumiko-types/fields";
1
2
  import { type OwnershipClause } from "../engine/ownership.ts";
2
- import type { EntityDefinition, SessionUser } from "../engine/types/index.ts";
3
+ import type { SessionUser } from "../engine/types/index.ts";
3
4
  import type { EventStoreExecutor } from "./event-store-executor.ts";
4
5
  import type { Table } from "./event-store-executor-context.ts";
5
6
  import type { ListWhere } from "./event-store-executor-read-filter.ts";
@@ -59,7 +59,7 @@ export function createReadVerbs(ctx) {
59
59
  const tableInfo = extractTableInfo(table);
60
60
  const encryptedRows = rawRows.map((r) => coerceAndRehydrateRow(r, tableInfo, entity));
61
61
  const decryptedRows = await Promise.all(encryptedRows.map((r) => decryptForRead(r, { degradeUndecryptable: () => { } })));
62
- // Stream version is authoritative (see detail()): ctx.appendEvent bumps the
62
+ // Stream version is authoritative (see detail()): ctx.events.append bumps the
63
63
  // stream without touching row.version, so the raw row version would hand
64
64
  // clients a stale optimistic-lock base. Rows without events keep theirs.
65
65
  const rows = decryptedRows.map((r, i) => withStreamVersion(r, streamVersions[i] ?? 0));
@@ -101,7 +101,7 @@ export function createReadVerbs(ctx) {
101
101
  return null;
102
102
  const idWhere = idFilter(payload.id);
103
103
  // Stream-version authoritative (same policy as update/Block 0):
104
- // ctx.appendEvent (lifecycle-writes like incident:post-update) bumps
104
+ // ctx.events.append (lifecycle-writes like incident:post-update) bumps
105
105
  // the stream WITHOUT touching row.version — a detail-read that hands
106
106
  // out the stale row.version dooms the next CRUD update built on it
107
107
  // (entityEdit loads detail.version as its optimistic-lock base) to a
@@ -1,21 +1,22 @@
1
1
  import { runnerCanBeginTransaction } from "./query.js";
2
- import { runInOwnTransaction } from "./tenant-db.js";
3
2
  import { isBoundTenantDb, tenantDbRunner, tenantDbWritesDeniedReason } from "./tenant-db-runner.js";
3
+ import { runInOwnSavepoint, runInOwnTransaction } from "./tenant-db-scoped-rebind.js";
4
4
  // Aborts the surrounding transaction when a verb returns a failure instead of throwing.
5
5
  class RollbackOnFailure extends Error {
6
6
  }
7
- // Pool runners have no savepoint, so append, projection and hooks would otherwise commit as
8
- // separate autocommit statements. Tx and savepoint runners already provide atomicity.
7
+ // Append, projection and hooks commit or roll back together, also when a handler swallows a failed
8
+ // verb inside its transaction. Savepoints on one tx are serialized, so parallel verbs cannot interleave.
9
9
  async function runVerbAtomically(db, run) {
10
10
  // Unbound and denied handles keep their original error, a fresh transaction would reword it.
11
- if (!isBoundTenantDb(db) ||
12
- tenantDbWritesDeniedReason(db) !== undefined ||
13
- !runnerCanBeginTransaction(tenantDbRunner(db))) {
11
+ if (!isBoundTenantDb(db) || tenantDbWritesDeniedReason(db) !== undefined) {
14
12
  return run(db);
15
13
  }
14
+ const runInOwnScope = runnerCanBeginTransaction(tenantDbRunner(db))
15
+ ? runInOwnTransaction
16
+ : runInOwnSavepoint;
16
17
  let failure;
17
18
  try {
18
- return await runInOwnTransaction(db, async (txDb) => {
19
+ return await runInOwnScope(db, async (txDb) => {
19
20
  const result = await run(txDb);
20
21
  if (!result.isSuccess) {
21
22
  failure = result;
@@ -1,8 +1,9 @@
1
+ import type { EntityId } from "@cosmicdrift/kumiko-types/identifiers";
1
2
  import type { TenantDb } from "@cosmicdrift/kumiko-types/tenant-db-types";
2
3
  import type { ZodType } from "zod";
3
4
  import type { UnavailableSelectOption } from "../engine/screen-helpers.ts";
4
- import type { EntityId } from "../engine/types/index.ts";
5
- import { type UnprocessableOpts, type WriteFailure, writeFailure } from "../errors/index.ts";
5
+ import type { UnprocessableOpts } from "../errors/classes.ts";
6
+ import { type WriteFailure, writeFailure } from "../errors/index.ts";
6
7
  import type { StoredEvent } from "../event-store/index.ts";
7
8
  import type { DbRow, DbRunner } from "./connection.ts";
8
9
  export declare function projectEntityEvent(db: TenantDb, runner: DbRunner, event: StoredEvent): Promise<void>;
@@ -4,8 +4,11 @@ import { instructionFieldNames } from "../engine/instruction-fields.js";
4
4
  import { userCanCreateFieldRow, userCanWriteFieldRow } from "../engine/ownership.js";
5
5
  import { buildInsertSchema, buildUpdateSchema } from "../engine/schema-builder.js";
6
6
  import { findUnavailableSelectOptions, isRecordLocked, isUnchangedValue, } from "../engine/screen-helpers.js";
7
- import { AccessDeniedError, VersionConflictError as FrameworkVersionConflict, IdempotentReplayError, InternalError, isSubjectErasedConflict, NotFoundError, PreconditionFailedError, RecordLockedError, UnprocessableError, writeFailure, } from "../errors/index.js";
8
- import { append, IdempotentAppendConflictError as EventStoreIdempotentAppendConflict, VersionConflictError as EventStoreVersionConflict, getStreamVersion, } from "../event-store/index.js";
7
+ import { IdempotentReplayError, PreconditionFailedError, RecordLockedError, } from "../errors/classes.js";
8
+ import { AccessDeniedError, VersionConflictError as FrameworkVersionConflict, InternalError, NotFoundError, UnprocessableError, writeFailure, } from "../errors/index.js";
9
+ import { isSubjectErasedConflict } from "../errors/subject-erased.js";
10
+ import { IdempotentAppendConflictError as EventStoreIdempotentAppendConflict } from "../event-store/errors.js";
11
+ import { append, VersionConflictError as EventStoreVersionConflict, getStreamVersion, } from "../event-store/index.js";
9
12
  import { assertInstructionFieldWriteAllowed, assertIrreversibleOperationAllowed, isIrreversibleEntityVerb, } from "../pipeline/irreversible-operation-gate.js";
10
13
  import { generateId } from "../utils/index.js";
11
14
  import { applyEntityEvent } from "./apply-entity-event.js";
@@ -131,7 +134,7 @@ export function createWriteVerbs(ctx) {
131
134
  }
132
135
  throw error;
133
136
  }
134
- // Stream-version is authoritative, not row.version. `ctx.appendEvent`
137
+ // Stream-version is authoritative, not row.version. `ctx.events.append`
135
138
  // can bump the stream between CRUD writes (domain event on the same
136
139
  // aggregate); a stale row.version here would make the next CRUD write
137
140
  // trip `events_aggregate_version_uq` (tenant_id, aggregate_id, version)
@@ -251,7 +254,7 @@ export function createWriteVerbs(ctx) {
251
254
  // internal_error at commit time instead of the version_conflict this
252
255
  // catch classifies. runInSavepointIfSupported confines the failed
253
256
  // INSERT to a nested scope that rolls back on its own (same pattern as
254
- // ctx.tryAppendEvent), and falls back to a plain call when the runner
257
+ // ctx.events.tryAppend), and falls back to a plain call when the runner
255
258
  // is a bare pool connection with no active transaction to poison
256
259
  // (seeds/tests calling the executor directly).
257
260
  const event = await runInSavepointIfSupported(runner, async (sp) => append(sp, {
@@ -1,6 +1,6 @@
1
1
  import type { EventStoreExecutor } from "@cosmicdrift/kumiko-types/event-store-executor-types";
2
+ import type { EntityDefinition } from "@cosmicdrift/kumiko-types/fields";
2
3
  import type { LocalKeyKmsAdapter } from "../crypto/index.ts";
3
- import type { EntityDefinition } from "../engine/types/index.ts";
4
4
  import type { EntityCache } from "../pipeline/entity-cache.ts";
5
5
  import type { SearchAdapter } from "../search/types.ts";
6
6
  import type { EnvelopeCipher } from "../secrets/envelope-cipher.ts";
@@ -1,6 +1,12 @@
1
1
  import type { ExecutorManagedWriteCapability, Writable } from "@cosmicdrift/kumiko-types/executor-brand";
2
+ import type { EntityDefinition } from "@cosmicdrift/kumiko-types/fields";
2
3
  import { AccessDeniedError } from "../errors/index.ts";
3
- export declare function markExecutorManagedTable(table: object): void;
4
+ export type ExecutorManagedEntitySource = {
5
+ readonly entityName: string;
6
+ readonly entity: EntityDefinition;
7
+ };
8
+ export declare function markExecutorManagedTable(table: object, entitySource?: ExecutorManagedEntitySource): void;
9
+ export declare function executorManagedEntitySourceOf(table: unknown): ExecutorManagedEntitySource | undefined;
4
10
  export declare function isExecutorManagedTable(table: unknown): boolean;
5
11
  export declare function registerExecutorManagedWriteRunner(runner: object): void;
6
12
  export declare function hasExecutorManagedWriteCapability(runner: unknown): runner is ExecutorManagedWriteCapability;