@cosmicdrift/kumiko-framework 0.389.0 → 0.390.1

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 (617) 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/driver-value-preparation.js +23 -2
  98. package/dist/db/eagerload.d.ts +2 -1
  99. package/dist/db/entity-field-encryption.d.ts +1 -1
  100. package/dist/db/entity-table-meta.d.ts +1 -1
  101. package/dist/db/event-store-executor-context.d.ts +3 -1
  102. package/dist/db/event-store-executor-context.js +4 -3
  103. package/dist/db/event-store-executor-read-filter.d.ts +1 -1
  104. package/dist/db/event-store-executor-read-rows.d.ts +2 -1
  105. package/dist/db/event-store-executor-read-search.d.ts +2 -1
  106. package/dist/db/event-store-executor-read-sort.d.ts +2 -1
  107. package/dist/db/event-store-executor-read.js +2 -2
  108. package/dist/db/event-store-executor-write-atomic.js +8 -7
  109. package/dist/db/event-store-executor-write-steps.d.ts +3 -2
  110. package/dist/db/event-store-executor-write.js +7 -4
  111. package/dist/db/event-store-executor.d.ts +1 -1
  112. package/dist/db/executor-managed-tables.d.ts +7 -1
  113. package/dist/db/executor-managed-tables.js +11 -2
  114. package/dist/db/index.d.ts +29 -28
  115. package/dist/db/index.js +22 -20
  116. package/dist/db/known-table-names.d.ts +6 -0
  117. package/dist/db/known-table-names.js +21 -0
  118. package/dist/db/list-aggregate-labels.d.ts +1 -1
  119. package/dist/db/located-timestamp.d.ts +1 -1
  120. package/dist/db/located-timestamp.js +0 -5
  121. package/dist/db/migrate-generator.d.ts +17 -1
  122. package/dist/db/migrate-generator.js +50 -20
  123. package/dist/db/migrate-primary-key.d.ts +12 -0
  124. package/dist/db/migrate-primary-key.js +45 -0
  125. package/dist/db/migrate-rls-diff.d.ts +20 -0
  126. package/dist/db/migrate-rls-diff.js +61 -0
  127. package/dist/db/migrate-runner.js +4 -0
  128. package/dist/db/money.d.ts +1 -1
  129. package/dist/db/money.js +1 -1
  130. package/dist/db/parent-ref-clause.d.ts +2 -1
  131. package/dist/db/pg-error.d.ts +2 -0
  132. package/dist/db/pg-error.js +11 -0
  133. package/dist/db/queries/ddl.d.ts +3 -0
  134. package/dist/db/queries/ddl.js +34 -1
  135. package/dist/db/queries/event-store.js +4 -2
  136. package/dist/db/queries/event-tenants.d.ts +2 -0
  137. package/dist/db/queries/event-tenants.js +17 -0
  138. package/dist/db/queries/rebuild-rls-guard.d.ts +2 -0
  139. package/dist/db/queries/rebuild-rls-guard.js +29 -0
  140. package/dist/db/queries/rls-boot-catalog.d.ts +16 -0
  141. package/dist/db/queries/rls-boot-catalog.js +39 -0
  142. package/dist/db/queries/rls-catalog.d.ts +6 -0
  143. package/dist/db/queries/rls-catalog.js +82 -0
  144. package/dist/db/queries/rls-scope.d.ts +3 -0
  145. package/dist/db/queries/rls-scope.js +17 -0
  146. package/dist/db/queries/rls-shape.d.ts +10 -0
  147. package/dist/db/queries/rls-shape.js +42 -0
  148. package/dist/db/queries/session-advisory-lock.d.ts +2 -0
  149. package/dist/db/queries/session-advisory-lock.js +23 -0
  150. package/dist/db/queries/shadow-swap.d.ts +1 -2
  151. package/dist/db/queries/shadow-swap.js +9 -25
  152. package/dist/db/queries/test-stack.d.ts +4 -1
  153. package/dist/db/queries/test-stack.js +84 -2
  154. package/dist/db/query.js +11 -7
  155. package/dist/db/reference-data.d.ts +1 -1
  156. package/dist/db/reference-data.js +6 -1
  157. package/dist/db/render-ddl.d.ts +6 -2
  158. package/dist/db/render-ddl.js +7 -7
  159. package/dist/db/render-rls-ddl.d.ts +35 -0
  160. package/dist/db/render-rls-ddl.js +127 -0
  161. package/dist/db/replay-migration-sql.d.ts +3 -1
  162. package/dist/db/replay-migration-sql.js +22 -5
  163. package/dist/db/replay-rls.d.ts +25 -0
  164. package/dist/db/replay-rls.js +156 -0
  165. package/dist/db/row-level-security-boot-check.d.ts +6 -0
  166. package/dist/db/row-level-security-boot-check.js +86 -0
  167. package/dist/db/row-level-security-connection.d.ts +3 -0
  168. package/dist/db/row-level-security-connection.js +213 -0
  169. package/dist/db/row-level-security-scope.d.ts +33 -0
  170. package/dist/db/row-level-security-scope.js +127 -0
  171. package/dist/db/scope-tenant-db-to-tenant.d.ts +3 -0
  172. package/dist/db/scope-tenant-db-to-tenant.js +14 -0
  173. package/dist/db/sql-identifier.d.ts +1 -0
  174. package/dist/db/sql-identifier.js +3 -0
  175. package/dist/db/table-builder.d.ts +2 -1
  176. package/dist/db/table-builder.js +1 -1
  177. package/dist/db/table-info.js +1 -1
  178. package/dist/db/table-push.d.ts +11 -2
  179. package/dist/db/table-push.js +15 -2
  180. package/dist/db/tenant-db-runner.d.ts +3 -1
  181. package/dist/db/tenant-db-runner.js +4 -3
  182. package/dist/db/tenant-db-scoped-rebind.d.ts +10 -0
  183. package/dist/db/tenant-db-scoped-rebind.js +33 -0
  184. package/dist/db/tenant-db-statement-runner.d.ts +13 -0
  185. package/dist/db/tenant-db-statement-runner.js +48 -0
  186. package/dist/db/tenant-db.d.ts +17 -12
  187. package/dist/db/tenant-db.js +49 -120
  188. package/dist/db/tenant-id-filter.d.ts +3 -0
  189. package/dist/db/tenant-id-filter.js +30 -0
  190. package/dist/db/transaction-serialization.d.ts +6 -0
  191. package/dist/db/transaction-serialization.js +60 -0
  192. package/dist/derivatives/delete-stored-file.js +1 -1
  193. package/dist/derivatives/index.d.ts +2 -5
  194. package/dist/derivatives/index.js +2 -3
  195. package/dist/engine/access.d.ts +2 -1
  196. package/dist/engine/access.js +1 -1
  197. package/dist/engine/boot-validator/entity-handler.d.ts +2 -1
  198. package/dist/engine/boot-validator/entity-handler.js +1 -1
  199. package/dist/engine/boot-validator/entity-list-aggregate-options.d.ts +1 -1
  200. package/dist/engine/boot-validator/list-table-aggregate-options.d.ts +1 -1
  201. package/dist/engine/boot-validator/list-table-aggregate-query.d.ts +2 -1
  202. package/dist/engine/boot-validator/nav.d.ts +3 -1
  203. package/dist/engine/boot-validator/nav.js +1 -1
  204. package/dist/engine/boot-validator/ownership.d.ts +2 -1
  205. package/dist/engine/boot-validator/parent-ref.d.ts +2 -1
  206. package/dist/engine/boot-validator/projection-list-screens.d.ts +2 -1
  207. package/dist/engine/boot-validator/query-refs.d.ts +2 -1
  208. package/dist/engine/boot-validator/screens-forms.d.ts +2 -1
  209. package/dist/engine/boot-validator/screens-kind-shared.d.ts +3 -1
  210. package/dist/engine/boot-validator/screens.d.ts +2 -1
  211. package/dist/engine/boot-validator/workspaces.d.ts +3 -1
  212. package/dist/engine/bridge-stub.d.ts +5 -2
  213. package/dist/engine/bridge-stub.js +39 -24
  214. package/dist/engine/config-helpers.d.ts +2 -2
  215. package/dist/engine/config-helpers.js +0 -9
  216. package/dist/engine/constants.d.ts +0 -10
  217. package/dist/engine/constants.js +0 -8
  218. package/dist/engine/create-app.js +1 -1
  219. package/dist/engine/define-feature.d.ts +2 -1
  220. package/dist/engine/define-feature.js +1 -2
  221. package/dist/engine/define-handler.d.ts +1 -1
  222. package/dist/engine/define-step.d.ts +0 -1
  223. package/dist/engine/define-step.js +0 -3
  224. package/dist/engine/embedded-derived.d.ts +1 -1
  225. package/dist/engine/entity-handlers.d.ts +2 -1
  226. package/dist/engine/entity-handlers.js +7 -7
  227. package/dist/engine/entity-list-runtime-options.js +3 -1
  228. package/dist/engine/entity-list-searchability.d.ts +2 -1
  229. package/dist/engine/event-def.d.ts +2 -1
  230. package/dist/engine/event-helpers.d.ts +3 -1
  231. package/dist/engine/event-helpers.js +3 -3
  232. package/dist/engine/extension-names.d.ts +2 -8
  233. package/dist/engine/extension-names.js +2 -2
  234. package/dist/engine/extension-selector-plugins.d.ts +1 -1
  235. package/dist/engine/extensions/storage-provider.d.ts +1 -2
  236. package/dist/engine/extensions/user-data.d.ts +0 -8
  237. package/dist/engine/factories.d.ts +2 -1
  238. package/dist/engine/feature-builder-state.d.ts +8 -1
  239. package/dist/engine/feature-changelog.d.ts +1 -1
  240. package/dist/engine/feature-config-events-jobs.d.ts +4 -1
  241. package/dist/engine/feature-entity-handlers.d.ts +5 -1
  242. package/dist/engine/feature-manifest.js +1 -1
  243. package/dist/engine/feature-ui-extensions.d.ts +7 -1
  244. package/dist/engine/feature-ui-extensions.js +6 -4
  245. package/dist/engine/field-access.d.ts +2 -1
  246. package/dist/engine/handler-field-references.d.ts +0 -4
  247. package/dist/engine/index.d.ts +57 -54
  248. package/dist/engine/index.js +22 -27
  249. package/dist/engine/instruction-fields.d.ts +1 -1
  250. package/dist/engine/personal-data-fields.d.ts +1 -1
  251. package/dist/engine/qualified-name.d.ts +0 -1
  252. package/dist/engine/read-claim.d.ts +2 -1
  253. package/dist/engine/registry-facade.js +0 -3
  254. package/dist/engine/registry-ingest.d.ts +2 -1
  255. package/dist/engine/registry-ingest.js +1 -2
  256. package/dist/engine/registry-state.d.ts +12 -2
  257. package/dist/engine/registry-state.js +2 -3
  258. package/dist/engine/registry-validate.d.ts +3 -1
  259. package/dist/engine/registry-validate.js +7 -7
  260. package/dist/engine/run-in.d.ts +1 -1
  261. package/dist/engine/run-in.js +0 -1
  262. package/dist/engine/schema-builder.d.ts +1 -1
  263. package/dist/engine/schema-builder.js +1 -1
  264. package/dist/engine/screen-filter-ops.d.ts +2 -1
  265. package/dist/engine/screen-filter-ops.js +0 -5
  266. package/dist/engine/soft-delete-cleanup.d.ts +1 -1
  267. package/dist/engine/soft-delete-cleanup.js +4 -4
  268. package/dist/engine/state-machine.js +2 -1
  269. package/dist/engine/steps/_read-source.js +1 -1
  270. package/dist/engine/steps/aggregate-append-event.js +2 -2
  271. package/dist/engine/steps/call-feature.js +2 -2
  272. package/dist/engine/steps/mail-send.js +1 -1
  273. package/dist/engine/steps/retry.js +1 -1
  274. package/dist/engine/steps/wait-for-event.js +1 -1
  275. package/dist/engine/steps/wait.js +1 -1
  276. package/dist/engine/steps/webhook-send.js +1 -1
  277. package/dist/engine/template-variables.d.ts +2 -1
  278. package/dist/engine/transfer-adjacency.d.ts +1 -1
  279. package/dist/engine/types/index.d.ts +8 -31
  280. package/dist/engine/types/index.js +2 -10
  281. package/dist/engine/validation.d.ts +2 -1
  282. package/dist/entrypoint/index.d.ts +7 -35
  283. package/dist/entrypoint/index.js +7 -1
  284. package/dist/entrypoint/internals.d.ts +40 -0
  285. package/dist/entrypoint/internals.js +1 -0
  286. package/dist/entrypoint/row-level-security-mode-check.d.ts +3 -0
  287. package/dist/entrypoint/row-level-security-mode-check.js +19 -0
  288. package/dist/env/dry-run-internals.d.ts +10 -0
  289. package/dist/env/dry-run-internals.js +1 -0
  290. package/dist/env/dry-run.d.ts +1 -10
  291. package/dist/env/dry-run.js +2 -1
  292. package/dist/env/index.d.ts +1 -85
  293. package/dist/env/index.js +6 -50
  294. package/dist/env/internals.d.ts +87 -0
  295. package/dist/env/internals.js +53 -0
  296. package/dist/errors/classes.js +2 -2
  297. package/dist/errors/index.d.ts +5 -14
  298. package/dist/errors/index.js +4 -9
  299. package/dist/errors/member-resolution.js +1 -1
  300. package/dist/errors/reasons.d.ts +0 -1
  301. package/dist/errors/reasons.js +7 -7
  302. package/dist/errors/serialize.d.ts +0 -18
  303. package/dist/errors/serialize.js +0 -27
  304. package/dist/es-ops/index.d.ts +4 -4
  305. package/dist/es-ops/index.js +2 -2
  306. package/dist/es-ops/operations-schema.d.ts +1 -1
  307. package/dist/es-ops/types.d.ts +4 -5
  308. package/dist/event-store/admin-api-internals.d.ts +14 -0
  309. package/dist/event-store/admin-api-internals.js +1 -0
  310. package/dist/event-store/admin-api.d.ts +1 -14
  311. package/dist/event-store/admin-api.js +11 -6
  312. package/dist/event-store/archive.js +4 -2
  313. package/dist/event-store/errors.js +2 -2
  314. package/dist/event-store/event-store.js +41 -34
  315. package/dist/event-store/events-schema.js +4 -1
  316. package/dist/event-store/index.d.ts +11 -13
  317. package/dist/event-store/index.js +7 -9
  318. package/dist/event-store/rebuild-dead-letter.js +4 -2
  319. package/dist/event-store/snapshot.js +4 -3
  320. package/dist/event-store/stream-scope.d.ts +2 -0
  321. package/dist/event-store/stream-scope.js +6 -0
  322. package/dist/event-store/upcaster-dead-letter.js +4 -2
  323. package/dist/event-store/upcaster.d.ts +2 -1
  324. package/dist/files/action-form-upload.d.ts +2 -1
  325. package/dist/files/action-form-upload.js +1 -1
  326. package/dist/files/assert-file-refs-belong-to-tenant.d.ts +2 -1
  327. package/dist/files/assert-file-refs-belong-to-tenant.js +1 -1
  328. package/dist/files/bind-pending-file-refs.d.ts +2 -1
  329. package/dist/files/bind-pending-file-refs.js +2 -1
  330. package/dist/files/bind-referenced-files.write.js +1 -1
  331. package/dist/files/create-file-ref-from-bytes.d.ts +6 -3
  332. package/dist/files/create-file-ref-from-bytes.js +3 -3
  333. package/dist/files/create-file-ref.d.ts +3 -2
  334. package/dist/files/create-file-ref.js +2 -2
  335. package/dist/files/dispose-removed-file-refs.d.ts +2 -1
  336. package/dist/files/dispose-removed-file-refs.js +1 -1
  337. package/dist/files/feature.js +2 -2
  338. package/dist/files/file-handle.js +1 -1
  339. package/dist/files/file-routes.d.ts +1 -1
  340. package/dist/files/file-routes.js +12 -2
  341. package/dist/files/index.d.ts +11 -13
  342. package/dist/files/index.js +5 -7
  343. package/dist/files/load-save-file-refs.d.ts +2 -1
  344. package/dist/files/load-save-file-refs.js +1 -1
  345. package/dist/files/provider-resolver.d.ts +5 -4
  346. package/dist/files/provider-resolver.js +4 -4
  347. package/dist/files/storage-tracking.js +4 -2
  348. package/dist/files/sweep-orphaned-uploads.d.ts +1 -1
  349. package/dist/files/sweep-orphaned-uploads.js +1 -1
  350. package/dist/i18n/index.d.ts +2 -8
  351. package/dist/i18n/index.js +1 -1
  352. package/dist/i18n/internals.d.ts +7 -0
  353. package/dist/i18n/internals.js +1 -0
  354. package/dist/i18n/required-surface-keys.d.ts +4 -1
  355. package/dist/internal/row-level-security.d.ts +3 -0
  356. package/dist/internal/row-level-security.js +3 -0
  357. package/dist/internal/stack-support.d.ts +1 -1
  358. package/dist/internal/stack-support.js +1 -1
  359. package/dist/internal/testing.d.ts +1 -0
  360. package/dist/internal/testing.js +9 -5
  361. package/dist/jobs/index.d.ts +1 -1
  362. package/dist/jobs/job-append-event.d.ts +12 -0
  363. package/dist/jobs/job-append-event.js +30 -0
  364. package/dist/jobs/job-runner-context.d.ts +2 -2
  365. package/dist/jobs/job-runner-context.js +46 -16
  366. package/dist/jobs/job-runner-execution.d.ts +1 -1
  367. package/dist/jobs/job-runner-execution.js +6 -4
  368. package/dist/jobs/job-runner-gates.d.ts +1 -1
  369. package/dist/jobs/job-runner-gates.js +0 -1
  370. package/dist/jobs/job-runner-helpers.d.ts +11 -4
  371. package/dist/jobs/job-runner-helpers.js +10 -1
  372. package/dist/jobs/job-runner-scope.d.ts +5 -2
  373. package/dist/jobs/job-runner-types.d.ts +2 -1
  374. package/dist/jobs/job-runner.js +19 -6
  375. package/dist/jobs/max-per-tenant.d.ts +1 -1
  376. package/dist/logging/index.d.ts +1 -2
  377. package/dist/logging/index.js +1 -1
  378. package/dist/logging/pino-logger.js +1 -1
  379. package/dist/logging/utils.d.ts +1 -0
  380. package/dist/logging/utils.js +6 -0
  381. package/dist/migrations/index.d.ts +3 -3
  382. package/dist/migrations/index.js +3 -3
  383. package/dist/migrations/pending-rebuilds.d.ts +1 -1
  384. package/dist/migrations/pending-rebuilds.js +1 -1
  385. package/dist/migrations/pii-event-backfill.js +4 -1
  386. package/dist/observability/escape-hatch-report.d.ts +2 -1
  387. package/dist/observability/index.d.ts +7 -15
  388. package/dist/observability/index.js +4 -12
  389. package/dist/observability/metric-validator.js +1 -1
  390. package/dist/observability/metrics-handle.d.ts +0 -1
  391. package/dist/observability/metrics-handle.js +2 -15
  392. package/dist/observability/recording-tracer.d.ts +1 -2
  393. package/dist/observability/recording-tracer.js +0 -6
  394. package/dist/observability/sensitive-filter.d.ts +0 -2
  395. package/dist/observability/sensitive-filter.js +0 -29
  396. package/dist/pipeline/active-membership.d.ts +2 -1
  397. package/dist/pipeline/active-membership.js +6 -2
  398. package/dist/pipeline/append-event-core.d.ts +2 -1
  399. package/dist/pipeline/append-event-core.js +2 -2
  400. package/dist/pipeline/attach-outside-transaction.d.ts +3 -0
  401. package/dist/pipeline/attach-outside-transaction.js +13 -0
  402. package/dist/pipeline/auth-claims-resolver.d.ts +2 -1
  403. package/dist/pipeline/cascade-handler.d.ts +2 -1
  404. package/dist/pipeline/cascade-handler.js +3 -2
  405. package/dist/pipeline/config-accessor-factory.d.ts +1 -1
  406. package/dist/pipeline/config-accessor-factory.js +1 -1
  407. package/dist/pipeline/context-services.d.ts +56 -0
  408. package/dist/pipeline/context-services.js +73 -0
  409. package/dist/pipeline/dispatch-batch.d.ts +2 -1
  410. package/dist/pipeline/dispatch-batch.js +31 -18
  411. package/dist/pipeline/dispatch-query.js +5 -4
  412. package/dist/pipeline/dispatch-scope.d.ts +6 -0
  413. package/dist/pipeline/dispatch-scope.js +27 -0
  414. package/dist/pipeline/dispatch-shared.d.ts +13 -9
  415. package/dist/pipeline/dispatch-shared.js +75 -198
  416. package/dist/pipeline/dispatch-stream.js +8 -4
  417. package/dist/pipeline/dispatch-write.d.ts +2 -1
  418. package/dist/pipeline/dispatch-write.js +10 -8
  419. package/dist/pipeline/dispatcher-utils.d.ts +3 -1
  420. package/dist/pipeline/dispatcher-utils.js +8 -2
  421. package/dist/pipeline/dispatcher.d.ts +3 -2
  422. package/dist/pipeline/dispatcher.js +4 -3
  423. package/dist/pipeline/event-consumer-state.d.ts +0 -1
  424. package/dist/pipeline/event-dispatcher-delivery.d.ts +1 -1
  425. package/dist/pipeline/event-dispatcher-delivery.js +4 -2
  426. package/dist/pipeline/event-dispatcher.d.ts +2 -2
  427. package/dist/pipeline/event-dispatcher.js +7 -3
  428. package/dist/pipeline/event-retention.js +59 -56
  429. package/dist/pipeline/handler-access-error.js +2 -1
  430. package/dist/pipeline/handler-context-auth.d.ts +5 -6
  431. package/dist/pipeline/handler-context-auth.js +7 -4
  432. package/dist/pipeline/handler-context-config.d.ts +2 -5
  433. package/dist/pipeline/handler-context-config.js +2 -2
  434. package/dist/pipeline/handler-context-db.d.ts +32 -7
  435. package/dist/pipeline/handler-context-db.js +26 -17
  436. package/dist/pipeline/handler-context-dispatch.d.ts +13 -7
  437. package/dist/pipeline/handler-context-dispatch.js +9 -8
  438. package/dist/pipeline/handler-context-events.d.ts +22 -36
  439. package/dist/pipeline/handler-context-events.js +36 -31
  440. package/dist/pipeline/handler-context-member-resolution.d.ts +2 -0
  441. package/dist/pipeline/handler-context-member-resolution.js +110 -0
  442. package/dist/pipeline/handler-context-notify.d.ts +3 -2
  443. package/dist/pipeline/handler-context-notify.js +1 -1
  444. package/dist/pipeline/handler-context-observability.d.ts +2 -4
  445. package/dist/pipeline/handler-context-observability.js +7 -5
  446. package/dist/pipeline/handler-context-phase-denials.d.ts +11 -0
  447. package/dist/pipeline/handler-context-phase-denials.js +98 -0
  448. package/dist/pipeline/handler-context-scope.d.ts +7 -10
  449. package/dist/pipeline/handler-context-scope.js +18 -20
  450. package/dist/pipeline/index.d.ts +9 -21
  451. package/dist/pipeline/index.js +5 -7
  452. package/dist/pipeline/irreversible-operation-gate.d.ts +1 -1
  453. package/dist/pipeline/irreversible-operation-gate.js +2 -2
  454. package/dist/pipeline/lifecycle-pipeline.d.ts +8 -7
  455. package/dist/pipeline/lifecycle-pipeline.js +9 -15
  456. package/dist/pipeline/member-read-only-transaction.js +11 -3
  457. package/dist/pipeline/member-reader.d.ts +1 -1
  458. package/dist/pipeline/member-reader.js +2 -2
  459. package/dist/pipeline/msp-rebuild.js +5 -3
  460. package/dist/pipeline/multi-stream-apply-context.js +3 -2
  461. package/dist/pipeline/notify-scope.d.ts +2 -1
  462. package/dist/pipeline/pre-handler-gates.d.ts +2 -1
  463. package/dist/pipeline/pre-transaction-reservations.d.ts +3 -3
  464. package/dist/pipeline/pre-transaction-reservations.js +9 -7
  465. package/dist/pipeline/projection-rebuild.js +12 -5
  466. package/dist/pipeline/projection-state.d.ts +0 -6
  467. package/dist/pipeline/projection-state.js +0 -5
  468. package/dist/pipeline/projections-runner.d.ts +2 -1
  469. package/dist/pipeline/projections-runner.js +10 -6
  470. package/dist/pipeline/system-hooks.d.ts +3 -1
  471. package/dist/pipeline/system-hooks.js +6 -4
  472. package/dist/pipeline/system-identity-switch.d.ts +4 -2
  473. package/dist/pipeline/system-identity-switch.js +51 -36
  474. package/dist/pipeline/typed-append-event.d.ts +2 -0
  475. package/dist/pipeline/typed-append-event.js +4 -0
  476. package/dist/pipeline/write-origin.js +2 -2
  477. package/dist/pipeline/write-result-masking.d.ts +1 -1
  478. package/dist/random/index.d.ts +1 -2
  479. package/dist/random/index.js +1 -2
  480. package/dist/rate-limit/bucket.d.ts +2 -1
  481. package/dist/rate-limit/middleware.js +2 -1
  482. package/dist/redis/index.d.ts +3 -4
  483. package/dist/redis/index.js +2 -2
  484. package/dist/schema-cli/apply-command.js +5 -2
  485. package/dist/schema-cli/baseline-command.js +7 -2
  486. package/dist/schema-cli/generate-command.js +7 -9
  487. package/dist/schema-cli/shared.d.ts +12 -2
  488. package/dist/schema-cli/shared.js +24 -2
  489. package/dist/schema-cli/status-command.js +8 -2
  490. package/dist/schema-cli/validate-command.js +48 -4
  491. package/dist/schema-cli.d.ts +0 -1
  492. package/dist/search/configure-tenant-index.d.ts +1 -3
  493. package/dist/search/configure-tenant-index.js +0 -4
  494. package/dist/search/index.d.ts +1 -4
  495. package/dist/search/index.js +0 -2
  496. package/dist/search/meilisearch-adapter-internals.d.ts +8 -0
  497. package/dist/search/meilisearch-adapter-internals.js +9 -0
  498. package/dist/search/meilisearch-adapter.d.ts +1 -8
  499. package/dist/search/meilisearch-adapter.js +6 -7
  500. package/dist/search/meilisearch-peer.d.ts +2 -0
  501. package/dist/search/meilisearch-peer.js +5 -0
  502. package/dist/search/reindex-entity.js +93 -87
  503. package/dist/secrets/index.d.ts +3 -4
  504. package/dist/secrets/index.js +2 -3
  505. package/dist/seeding/index.d.ts +2 -2
  506. package/dist/seeding/index.js +1 -2
  507. package/dist/time/index.d.ts +2 -2
  508. package/dist/time/index.js +1 -1
  509. package/dist/time/tz-context.d.ts +0 -5
  510. package/dist/time/tz-context.js +0 -9
  511. package/dist/ui-types/index.d.ts +8 -11
  512. package/dist/ui-types/index.js +3 -3
  513. package/dist/upgrade-changelog.d.ts +3 -2
  514. package/dist/upgrade-changelog.js +12 -8
  515. package/dist/upgrade-cli-internals.d.ts +8 -0
  516. package/dist/upgrade-cli-internals.js +63 -0
  517. package/dist/upgrade-cli.d.ts +2 -9
  518. package/dist/upgrade-cli.js +28 -70
  519. package/dist/utils/import-optional-peer.d.ts +6 -0
  520. package/dist/utils/import-optional-peer.js +19 -0
  521. package/dist/utils/index.d.ts +1 -4
  522. package/dist/utils/index.js +1 -4
  523. package/package.json +23 -19
  524. package/src/changes.json +236 -0
  525. package/dist/crypto/request-kms-cache.d.ts +0 -8
  526. package/dist/crypto/request-kms-cache.js +0 -21
  527. package/dist/engine/codemod/index.d.ts +0 -2
  528. package/dist/engine/codemod/index.js +0 -1
  529. package/dist/engine/codemod/pipeline-codemod.d.ts +0 -50
  530. package/dist/engine/codemod/pipeline-codemod.js +0 -536
  531. package/dist/engine/feature-ast/entity-field-types.d.ts +0 -13
  532. package/dist/engine/feature-ast/entity-field-types.js +0 -35
  533. package/dist/engine/feature-ast/extractors/ai-steps.d.ts +0 -6
  534. package/dist/engine/feature-ast/extractors/ai-steps.js +0 -254
  535. package/dist/engine/feature-ast/extractors/events.d.ts +0 -5
  536. package/dist/engine/feature-ast/extractors/events.js +0 -275
  537. package/dist/engine/feature-ast/extractors/handlers.d.ts +0 -24
  538. package/dist/engine/feature-ast/extractors/handlers.js +0 -358
  539. package/dist/engine/feature-ast/extractors/hooks.d.ts +0 -24
  540. package/dist/engine/feature-ast/extractors/hooks.js +0 -248
  541. package/dist/engine/feature-ast/extractors/index.d.ts +0 -14
  542. package/dist/engine/feature-ast/extractors/index.js +0 -13
  543. package/dist/engine/feature-ast/extractors/jobs-routes.d.ts +0 -7
  544. package/dist/engine/feature-ast/extractors/jobs-routes.js +0 -145
  545. package/dist/engine/feature-ast/extractors/projections-screens.d.ts +0 -10
  546. package/dist/engine/feature-ast/extractors/projections-screens.js +0 -195
  547. package/dist/engine/feature-ast/extractors/resolve-import.d.ts +0 -21
  548. package/dist/engine/feature-ast/extractors/resolve-import.js +0 -180
  549. package/dist/engine/feature-ast/extractors/round1.d.ts +0 -11
  550. package/dist/engine/feature-ast/extractors/round1.js +0 -87
  551. package/dist/engine/feature-ast/extractors/round2.d.ts +0 -7
  552. package/dist/engine/feature-ast/extractors/round2.js +0 -191
  553. package/dist/engine/feature-ast/extractors/round3.d.ts +0 -23
  554. package/dist/engine/feature-ast/extractors/round3.js +0 -292
  555. package/dist/engine/feature-ast/extractors/round5.d.ts +0 -9
  556. package/dist/engine/feature-ast/extractors/round5.js +0 -68
  557. package/dist/engine/feature-ast/extractors/round6.d.ts +0 -4
  558. package/dist/engine/feature-ast/extractors/round6.js +0 -17
  559. package/dist/engine/feature-ast/extractors/shared.d.ts +0 -94
  560. package/dist/engine/feature-ast/extractors/shared.js +0 -343
  561. package/dist/engine/feature-ast/index.d.ts +0 -16
  562. package/dist/engine/feature-ast/index.js +0 -10
  563. package/dist/engine/feature-ast/parse.d.ts +0 -31
  564. package/dist/engine/feature-ast/parse.js +0 -485
  565. package/dist/engine/feature-ast/patch.d.ts +0 -212
  566. package/dist/engine/feature-ast/patch.js +0 -611
  567. package/dist/engine/feature-ast/patcher.d.ts +0 -217
  568. package/dist/engine/feature-ast/patcher.js +0 -281
  569. package/dist/engine/feature-ast/pattern-change-schema.d.ts +0 -1238
  570. package/dist/engine/feature-ast/pattern-change-schema.js +0 -1072
  571. package/dist/engine/feature-ast/pattern-id-matchers.d.ts +0 -7
  572. package/dist/engine/feature-ast/pattern-id-matchers.js +0 -211
  573. package/dist/engine/feature-ast/pattern-id-schema.d.ts +0 -251
  574. package/dist/engine/feature-ast/pattern-id-schema.js +0 -166
  575. package/dist/engine/feature-ast/patterns.d.ts +0 -322
  576. package/dist/engine/feature-ast/patterns.js +0 -107
  577. package/dist/engine/feature-ast/render.d.ts +0 -47
  578. package/dist/engine/feature-ast/render.js +0 -666
  579. package/dist/engine/feature-ast/source-location.d.ts +0 -17
  580. package/dist/engine/feature-ast/source-location.js +0 -27
  581. package/dist/engine/pattern-library/index.d.ts +0 -2
  582. package/dist/engine/pattern-library/index.js +0 -3
  583. package/dist/engine/pattern-library/library.d.ts +0 -14
  584. package/dist/engine/pattern-library/library.js +0 -94
  585. package/dist/engine/pattern-library/mixed-schemas.d.ts +0 -16
  586. package/dist/engine/pattern-library/mixed-schemas.js +0 -559
  587. package/dist/engine/pattern-library/opaque-schemas.d.ts +0 -7
  588. package/dist/engine/pattern-library/opaque-schemas.js +0 -115
  589. package/dist/engine/pattern-library/shared-fields.d.ts +0 -122
  590. package/dist/engine/pattern-library/shared-fields.js +0 -88
  591. package/dist/engine/pattern-library/static-schemas.d.ts +0 -21
  592. package/dist/engine/pattern-library/static-schemas.js +0 -487
  593. package/dist/engine/pattern-library/types.d.ts +0 -158
  594. package/dist/engine/pattern-library/types.js +0 -36
  595. package/dist/engine/resolve-config-or-param.d.ts +0 -18
  596. package/dist/engine/resolve-config-or-param.js +0 -76
  597. package/src/scripts/codemod/README.md +0 -187
  598. package/src/scripts/codemod/codemod-support.ts +0 -334
  599. package/src/scripts/codemod/collect-source-files.ts +0 -48
  600. package/src/scripts/codemod/crypto-shredding-testing-move.ts +0 -119
  601. package/src/scripts/codemod/db-factory.ts +0 -810
  602. package/src/scripts/codemod/feature-factory.ts +0 -429
  603. package/src/scripts/codemod/feature-layout.ts +0 -424
  604. package/src/scripts/codemod/import-extensions.ts +0 -118
  605. package/src/scripts/codemod/migrate-cross-tenant.ts +0 -328
  606. package/src/scripts/codemod/migrate-db-raw.ts +0 -401
  607. package/src/scripts/codemod/migrate-open-to-all.ts +0 -235
  608. package/src/scripts/codemod/object-form.ts +0 -746
  609. package/src/scripts/codemod/package-merge.ts +0 -299
  610. package/src/scripts/codemod/pii-personal-migration.ts +0 -816
  611. package/src/scripts/codemod/remove-engine-payload-casts.ts +0 -318
  612. package/src/scripts/codemod/s3-imports.ts +0 -236
  613. package/src/scripts/codemod/tenant-db-options.ts +0 -454
  614. package/src/scripts/codemod/testing-injection.ts +0 -215
  615. package/src/scripts/codemod/testing-move-targets.ts +0 -161
  616. package/src/scripts/codemod/testing-move.ts +0 -542
  617. package/src/scripts/codemod/unprocessable-error-details-reason.ts +0 -411
@@ -368,6 +368,6 @@ export function buildEntityTable(entityName, entity, options) {
368
368
  return indexes;
369
369
  });
370
370
  stampEntityTableMeta(built, entity);
371
- markExecutorManagedTable(built);
371
+ markExecutorManagedTable(built, { entityName, entity });
372
372
  return built;
373
373
  }
@@ -1,4 +1,4 @@
1
- import { camelCase as envCamelCase } from "../env/index.js";
1
+ import { camelCase as envCamelCase } from "../env/internals.js";
2
2
  import { toSnakeCase } from "./table-builder.js";
3
3
  import { asEntityTableMeta } from "./table-introspection.js";
4
4
  // Idempotent snake_case → camelCase. `env.camelCase` always lowercases first
@@ -1,6 +1,7 @@
1
- import type { EntityDefinition } from "../engine/types/index.ts";
1
+ import type { EntityDefinition } from "@cosmicdrift/kumiko-types/fields";
2
2
  import type { DbConnection } from "./connection.ts";
3
3
  import type { ColumnMeta, EntityTableMeta, IndexMeta } from "./entity-table-meta.ts";
4
+ import type { RowLevelSecurityMode } from "./render-rls-ddl.ts";
4
5
  /**
5
6
  * Bypass: creates an entity-table directly without going through the
6
7
  * full registry. Reserved for framework-internal meta-tables and
@@ -13,6 +14,12 @@ export declare function tableToMeta(table: unknown): EntityTableMeta;
13
14
  export declare function addMissingColumns(db: DbConnection, tableName: string, columns: readonly ColumnMeta[]): Promise<void>;
14
15
  /** CREATE [UNIQUE] INDEX IF NOT EXISTS for exactly the given indexes. */
15
16
  export declare function addMissingIndexes(db: DbConnection, tableName: string, indexes: readonly IndexMeta[]): Promise<void>;
17
+ /**
18
+ * Re-applies the row-level security DDL on a table that already exists. The create functions of
19
+ * framework tables skip the push for existing tables, so databases created before row-level
20
+ * security was switched on would never get the policies. Idempotent; no-op unless the mode is "on".
21
+ */
22
+ export declare function ensureTableRowLevelSecurity(db: DbConnection, table: unknown): Promise<void>;
16
23
  /**
17
24
  * Bypass: pushes table definitions to the database directly. Produces
18
25
  * CREATE TABLE IF NOT EXISTS + CREATE INDEX statements via renderTableDdl
@@ -21,4 +28,6 @@ export declare function addMissingIndexes(db: DbConnection, tableName: string, i
21
28
  * Reserved for framework-internal meta-tables + test setup. App-defined
22
29
  * entities go through `kumiko schema apply` (committed SQL files).
23
30
  */
24
- export declare function unsafePushTables(db: DbConnection, tables: Record<string, unknown>, prevTables?: Record<string, unknown>): Promise<void>;
31
+ export declare function unsafePushTables(db: DbConnection, tables: Record<string, unknown>, prevTables?: Record<string, unknown>, options?: {
32
+ readonly rowLevelSecurity?: RowLevelSecurityMode;
33
+ }): Promise<void>;
@@ -1,6 +1,7 @@
1
1
  import { pgTypeToSqlType } from "./dialect.js";
2
- import { alterTableAddColumn, createIndexIfNotExists, executeDdlStatement } from "./queries/ddl.js";
2
+ import { alterTableAddColumn, applyTableRowLevelSecurity, createIndexIfNotExists, executeDdlStatement, } from "./queries/ddl.js";
3
3
  import { renderTableDdl } from "./render-ddl.js";
4
+ import { rowLevelSecurityModeOf } from "./row-level-security-connection.js";
4
5
  import { tableExists } from "./schema-inspection.js";
5
6
  import { buildEntityTable, toTableName } from "./table-builder.js";
6
7
  import { asEntityTableMeta } from "./table-introspection.js";
@@ -46,6 +47,15 @@ export async function addMissingIndexes(db, tableName, indexes) {
46
47
  await createIndexIfNotExists(db, kind, idx.name, tableName, colList, idx.whereSql);
47
48
  }
48
49
  }
50
+ /**
51
+ * Re-applies the row-level security DDL on a table that already exists. The create functions of
52
+ * framework tables skip the push for existing tables, so databases created before row-level
53
+ * security was switched on would never get the policies. Idempotent; no-op unless the mode is "on".
54
+ */
55
+ export async function ensureTableRowLevelSecurity(db, table) {
56
+ if (rowLevelSecurityModeOf(db) === "on")
57
+ await applyTableRowLevelSecurity(db, tableToMeta(table));
58
+ }
49
59
  /**
50
60
  * Bypass: pushes table definitions to the database directly. Produces
51
61
  * CREATE TABLE IF NOT EXISTS + CREATE INDEX statements via renderTableDdl
@@ -54,7 +64,8 @@ export async function addMissingIndexes(db, tableName, indexes) {
54
64
  * Reserved for framework-internal meta-tables + test setup. App-defined
55
65
  * entities go through `kumiko schema apply` (committed SQL files).
56
66
  */
57
- export async function unsafePushTables(db, tables, prevTables) {
67
+ export async function unsafePushTables(db, tables, prevTables, options = {}) {
68
+ const rowLevelSecurity = options.rowLevelSecurity ?? rowLevelSecurityModeOf(db);
58
69
  const prevMetas = new Map();
59
70
  if (prevTables) {
60
71
  for (const [key, table] of Object.entries(prevTables)) {
@@ -78,6 +89,8 @@ export async function unsafePushTables(db, tables, prevTables) {
78
89
  await executeDdlStatement(db, stmt);
79
90
  }
80
91
  }
92
+ if (rowLevelSecurity === "on")
93
+ await applyTableRowLevelSecurity(db, meta);
81
94
  }
82
95
  }
83
96
  // @wrapper-known semantic-alias
@@ -1,9 +1,11 @@
1
1
  import type { TenantDb } from "@cosmicdrift/kumiko-types/tenant-db-types";
2
+ import type { TenantId } from "../engine/types/identifiers.ts";
2
3
  import { InternalError } from "../errors/index.ts";
3
4
  import type { DbRunner } from "./connection.ts";
5
+ import { type TenantDbModeOptions } from "./row-level-security-scope.ts";
4
6
  export declare function isBoundTenantDb(value: unknown): value is TenantDb;
5
7
  export declare function isDbRunner(value: unknown): value is DbRunner;
6
- export declare function bindTenantDbRunner(tenantDb: TenantDb, runner: DbRunner): void;
8
+ export declare function bindTenantDbRunner(tenantDb: TenantDb, runner: DbRunner, modeOptions: TenantDbModeOptions, tenantId: TenantId): void;
7
9
  export declare function tenantDbRunner(tenantDb: TenantDb): DbRunner;
8
10
  export declare function denyTenantDbWrites(tenantDb: TenantDb, reason: string): void;
9
11
  export declare function tenantDbWritesDeniedReason(tenantDb: TenantDb): string | undefined;
@@ -1,5 +1,6 @@
1
1
  import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
2
2
  import { InternalError } from "../errors/index.js";
3
+ import { tenantDbRowLevelSecurityScope, withRowLevelSecurityScope, } from "./row-level-security-scope.js";
3
4
  const tenantDbRunners = new WeakMap();
4
5
  export function isBoundTenantDb(value) {
5
6
  return typeof value === "object" && value !== null && tenantDbRunners.has(value);
@@ -7,8 +8,8 @@ export function isBoundTenantDb(value) {
7
8
  export function isDbRunner(value) {
8
9
  return typeof propertyOf(value, "unsafe") === "function";
9
10
  }
10
- export function bindTenantDbRunner(tenantDb, runner) {
11
- tenantDbRunners.set(tenantDb, runner);
11
+ export function bindTenantDbRunner(tenantDb, runner, modeOptions, tenantId) {
12
+ tenantDbRunners.set(tenantDb, withRowLevelSecurityScope(runner, tenantDbRowLevelSecurityScope(modeOptions, tenantId)));
12
13
  }
13
14
  // WeakMap.get never reads a property off tenantDb — safe even when tenantDb is a
14
15
  // throwing systemScope guard Proxy that rejects every property access.
@@ -31,7 +32,7 @@ export function tenantDbWritesDeniedReason(tenantDb) {
31
32
  }
32
33
  export function tenantDbWritesDeniedError(operation, reason) {
33
34
  return new InternalError({
34
- message: `${operation}: writes are not available ${reason}; run the write through ctx.write so it gets its own transaction`,
35
+ message: `${operation}: writes are not available ${reason}; run the write through ctx.dispatch.write so it gets its own transaction`,
35
36
  });
36
37
  }
37
38
  // For framework code that writes through the raw runner (executor verbs, event appends, projection steps):
@@ -0,0 +1,10 @@
1
+ import type { TenantDb } from "@cosmicdrift/kumiko-types/tenant-db-types";
2
+ import type { DbRunner } from "./connection.ts";
3
+ type ScopedRebinder = {
4
+ readonly memberReadOnly: boolean;
5
+ readonly rebind: (runner: DbRunner) => TenantDb;
6
+ };
7
+ export declare function registerScopedRebinder(tenantDb: TenantDb, scoped: ScopedRebinder): void;
8
+ export declare function runInOwnTransaction<T>(tenantDb: TenantDb, fn: (txDb: TenantDb) => Promise<T>): Promise<T>;
9
+ export declare function runInOwnSavepoint<T>(tenantDb: TenantDb, fn: (savepointDb: TenantDb) => Promise<T>): Promise<T>;
10
+ export {};
@@ -0,0 +1,33 @@
1
+ import { InternalError } from "../errors/index.js";
2
+ import { runInNewTransaction, runInSavepointIfSupported } from "./query.js";
3
+ import { tenantDbRunner } from "./tenant-db-runner.js";
4
+ const scopedRebinders = new WeakMap();
5
+ export function registerScopedRebinder(tenantDb, scoped) {
6
+ scopedRebinders.set(tenantDb, scoped);
7
+ }
8
+ function requireScopedRebinder(tenantDb, caller) {
9
+ const scoped = scopedRebinders.get(tenantDb);
10
+ if (!scoped) {
11
+ throw new InternalError({
12
+ message: `${caller} received a TenantDb without a transaction rebinder: either it was not ` +
13
+ "built by createTenantDb, or it is the fail-closed ctx.db/ctx.db.outsideTransaction of an " +
14
+ "r.systemScope() handler (use ctx.systemDb.outsideTransaction there).",
15
+ });
16
+ }
17
+ return scoped;
18
+ }
19
+ export async function runInOwnTransaction(tenantDb, fn) {
20
+ const scoped = requireScopedRebinder(tenantDb, "runInOwnTransaction");
21
+ if (scoped.memberReadOnly) {
22
+ throw new InternalError({
23
+ message: "runInOwnTransaction: memberReadOnly TenantDb — a fresh transaction would escape " +
24
+ "the enforced read-only scope.",
25
+ });
26
+ }
27
+ return runInNewTransaction(tenantDbRunner(tenantDb), (tx) => fn(scoped.rebind(tx)));
28
+ }
29
+ // A throw inside fn rolls back only fn's statements; the caller's transaction stays usable.
30
+ export async function runInOwnSavepoint(tenantDb, fn) {
31
+ const scoped = requireScopedRebinder(tenantDb, "runInOwnSavepoint");
32
+ return runInSavepointIfSupported(tenantDbRunner(tenantDb), (sp) => fn(scoped.rebind(sp)));
33
+ }
@@ -0,0 +1,13 @@
1
+ import type { EntityTableMeta } from "@cosmicdrift/kumiko-types/entity-table-meta-types";
2
+ import type { Meter, Tracer } from "@cosmicdrift/kumiko-types/observability";
3
+ import type { SchemaTable } from "@cosmicdrift/kumiko-types/schema-table-types";
4
+ import type { TenantId } from "../engine/types/identifiers.ts";
5
+ import { type TenantDbModeOptions } from "./row-level-security-scope.ts";
6
+ export type TenantDbStatementRunnerOptions = {
7
+ readonly tracer?: Tracer | undefined;
8
+ readonly meter?: Meter | undefined;
9
+ readonly signal?: AbortSignal | undefined;
10
+ readonly tenantId: TenantId;
11
+ } & TenantDbModeOptions;
12
+ export type TenantDbOperation = "select" | "insert" | "update" | "delete";
13
+ export declare function createTenantDbStatementRunner({ tracer, meter, signal, mode, reason, tenantId, }: TenantDbStatementRunnerOptions): <T>(operation: TenantDbOperation, table: SchemaTable | EntityTableMeta, runner: () => Promise<T>) => Promise<T>;
@@ -0,0 +1,48 @@
1
+ import { emitDbQuery } from "../observability/standard-metrics.js";
2
+ import { runInRowLevelSecurityScope, tenantDbRowLevelSecurityScope, } from "./row-level-security-scope.js";
3
+ import { tableNameOf } from "./table-introspection.js";
4
+ export function createTenantDbStatementRunner({ tracer, meter, signal, mode, reason, tenantId, }) {
5
+ return function withDbSpan(operation, table, runner) {
6
+ signal?.throwIfAborted();
7
+ const scope = tenantDbRowLevelSecurityScope(mode === "system" ? { mode, reason } : { mode }, tenantId, table);
8
+ const scopedRunner = () => runInRowLevelSecurityScope(scope, runner);
9
+ if (!tracer && !meter)
10
+ return scopedRunner();
11
+ const tableName = tableNameOf(table);
12
+ const start = performance.now();
13
+ const emitMetric = () => {
14
+ if (meter) {
15
+ emitDbQuery(meter, { operation, table: tableName }, (performance.now() - start) / 1000);
16
+ }
17
+ };
18
+ if (!tracer) {
19
+ return (async () => {
20
+ try {
21
+ return await scopedRunner();
22
+ }
23
+ finally {
24
+ emitMetric();
25
+ }
26
+ })();
27
+ }
28
+ return tracer.withSpan("db.query", {
29
+ kind: "client",
30
+ attributes: {
31
+ "db.system": "postgresql",
32
+ "db.operation": operation,
33
+ "db.table": tableName,
34
+ },
35
+ }, async (span) => {
36
+ try {
37
+ const result = await scopedRunner();
38
+ if (Array.isArray(result)) {
39
+ span.setAttribute("db.row_count", result.length);
40
+ }
41
+ return result;
42
+ }
43
+ finally {
44
+ emitMetric();
45
+ }
46
+ });
47
+ };
48
+ }
@@ -1,13 +1,13 @@
1
1
  import type { EntityTableMeta } from "@cosmicdrift/kumiko-types/entity-table-meta-types";
2
2
  import type { ExecutorManagedRunner } from "@cosmicdrift/kumiko-types/executor-brand";
3
- import type { EscapeHatchDeclaration, EscapeHatchReporter, EscapeHatchTarget } from "@cosmicdrift/kumiko-types/handlers";
3
+ import type { EscapeHatchDeclaration, EscapeHatchReporter, EscapeHatchTarget, HandlerDb } from "@cosmicdrift/kumiko-types/handlers";
4
+ import type { Meter, Tracer } from "@cosmicdrift/kumiko-types/observability";
4
5
  import type { SchemaTable } from "@cosmicdrift/kumiko-types/schema-table-types";
5
- import { type ExecutorManagedTenantDb, type TenantDb, type TenantDbMode, type UncheckedSystemDb } from "@cosmicdrift/kumiko-types/tenant-db-types";
6
+ import { type ExecutorManagedTenantDb, type TenantDb, type UncheckedSystemDb } from "@cosmicdrift/kumiko-types/tenant-db-types";
6
7
  import { asRawClient } from "../db/query.ts";
7
8
  import type { EntityDefinition } from "../engine/types/fields.ts";
8
9
  import { type TenantId } from "../engine/types/identifiers.ts";
9
10
  import type { Registry } from "../engine/types/index.ts";
10
- import { type Meter, type Tracer } from "../observability/index.ts";
11
11
  import type { DbRunner } from "./connection.ts";
12
12
  import { tableNameOf } from "./table-introspection.ts";
13
13
  type Table = SchemaTable;
@@ -19,10 +19,9 @@ export declare function unsafeRawForDeclaredStep(holder: TenantDb | UncheckedSys
19
19
  export declare function withSystemDbUnsafeRawGrant<T extends object>(systemDb: T, grant: EscapeHatchDeclaration | undefined, deniedCallerLabel: string): T | UncheckedSystemDb;
20
20
  export declare function createUncheckedSystemDb(db: TenantDb, dbOutsideTransaction?: TenantDb, report?: EscapeHatchReporter): UncheckedSystemDb;
21
21
  export declare function createSystemDbView(db: TenantDb, dbOutsideTransaction?: TenantDb, report?: EscapeHatchReporter): UncheckedSystemDb;
22
- export declare function scopeTenantDbToTenant(db: TenantDb, tenantId: TenantId): TenantDb;
23
22
  export declare function castTenantRows<T>(rows: readonly Record<string, unknown>[]): readonly T[];
23
+ export { requestedTenantIds } from "./tenant-id-filter.ts";
24
24
  export { tableNameOf };
25
- export declare function requestedTenantIds(requested: unknown): readonly unknown[] | undefined;
26
25
  export declare function hasTenantColumn(table: Table | EntityTableMeta): boolean;
27
26
  export type TenantDbGrants = {
28
27
  readonly globalWrites?: EscapeHatchDeclaration;
@@ -40,26 +39,32 @@ export declare function acknowledgeConventionCrossTenant(tenantDb: TenantDb, rea
40
39
  }): TenantDb;
41
40
  export declare function reportConventionCrossTenantUse(acknowledged: TenantDb, target?: EscapeHatchTarget): void;
42
41
  export type OutsideTransactionContext = {
43
- readonly dbOutsideTransaction: TenantDb | undefined;
42
+ readonly db: Pick<HandlerDb, "outsideTransaction">;
44
43
  };
45
- export declare function hasOutsideTransactionDb(ctx: OutsideTransactionContext): ctx is OutsideTransactionContext & {
46
- readonly dbOutsideTransaction: TenantDb;
44
+ export declare function hasOutsideTransactionDb(ctx: OutsideTransactionContext): ctx is {
45
+ readonly db: {
46
+ readonly outsideTransaction: TenantDb;
47
+ };
47
48
  };
48
49
  export declare function requireOutsideTransactionDb(ctx: OutsideTransactionContext): TenantDb;
49
- export declare function runInOwnTransaction<T>(tenantDb: TenantDb, fn: (txDb: TenantDb) => Promise<T>): Promise<T>;
50
50
  export type CreateTenantDbOptions = {
51
51
  readonly db: DbRunner;
52
52
  readonly tenantId: TenantId;
53
- readonly mode?: TenantDbMode;
54
53
  readonly tracer?: Tracer;
55
54
  readonly meter?: Meter;
56
55
  readonly signal?: AbortSignal;
57
56
  readonly grants?: TenantDbGrants;
58
- };
57
+ } & ({
58
+ readonly mode?: "tenant";
59
+ readonly reason?: undefined;
60
+ } | {
61
+ readonly mode: "system";
62
+ readonly reason: string;
63
+ });
59
64
  export declare function createTenantDb(options: CreateTenantDbOptions & {
60
65
  readonly db: ExecutorManagedRunner;
61
66
  }): ExecutorManagedTenantDb;
62
67
  export declare function createTenantDb(options: CreateTenantDbOptions): TenantDb;
63
- export declare function createTenantDataDestroyDb(options: Omit<CreateTenantDbOptions, "mode">): ExecutorManagedTenantDb;
68
+ export declare function createTenantDataDestroyDb(options: Omit<CreateTenantDbOptions, "mode" | "reason">): ExecutorManagedTenantDb;
64
69
  export declare function createProjectingTenantDb(db: DbRunner, tenantId: TenantId, projectionRegistry: Registry | undefined): TenantDb;
65
70
  export { asRawClient };
@@ -1,17 +1,23 @@
1
1
  import { SYSTEM_SCOPE_CHECK_BRAND, } from "@cosmicdrift/kumiko-types/tenant-db-types";
2
- import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
3
- import { asEntityTableMeta, asRawClient, aggregateWhere as bunAggregateWhere, countWhere as bunCountWhere, deleteMany as bunDeleteMany, fetchOne as bunFetchOne, insertOne as bunInsertOne, selectMany as bunSelectMany, updateMany as bunUpdateMany, runInNewTransaction, } from "../db/query.js";
2
+ import { asEntityTableMeta, asRawClient, aggregateWhere as bunAggregateWhere, countWhere as bunCountWhere, deleteMany as bunDeleteMany, fetchOne as bunFetchOne, insertOne as bunInsertOne, selectMany as bunSelectMany, updateMany as bunUpdateMany, } from "../db/query.js";
4
3
  import { assertReason } from "../engine/escape-hatch-reason.js";
5
4
  import { SYSTEM_TENANT_ID } from "../engine/types/identifiers.js";
6
- import { AccessDeniedError, InternalError, memberResolutionReadOnlyDenied, } from "../errors/index.js";
7
- import { emitDbQuery, fallbackEscapeHatchReporter, registerStandardMetrics, } from "../observability/index.js";
5
+ import { AccessDeniedError, InternalError } from "../errors/index.js";
6
+ import { memberResolutionReadOnlyDenied } from "../errors/member-resolution.js";
7
+ import { fallbackEscapeHatchReporter } from "../observability/escape-hatch-report.js";
8
+ import { registerStandardMetrics } from "../observability/standard-metrics.js";
8
9
  import { assertWritableTable, executorManagedWriteDenied, hasExecutorManagedWriteCapability, registerExecutorManagedWriteRunner, } from "./executor-managed-tables.js";
9
10
  import { bindProjectionRegistry, projectionRegistryOf } from "./projection-registry-binding.js";
10
11
  import { acquireNamespacedAdvisoryLock } from "./queries/advisory-lock.js";
11
12
  import { queryDatabaseNow } from "./queries/database-now.js";
13
+ import { systemModeOptions, unsafeRawScopedRunner, unscopedRunnerOf, } from "./row-level-security-scope.js";
12
14
  import { hasFieldProperty, tableNameOf } from "./table-introspection.js";
13
- import { bindTenantDbRunner, denyTenantDbWrites, tenantDbRunner, tenantDbWritesDeniedError, tenantDbWritesDeniedReason, } from "./tenant-db-runner.js";
15
+ import { bindTenantDbRunner, denyTenantDbWrites, tenantDbRunner, tenantDbWritesDeniedError, } from "./tenant-db-runner.js";
16
+ import { registerScopedRebinder } from "./tenant-db-scoped-rebind.js";
17
+ import { createTenantDbStatementRunner } from "./tenant-db-statement-runner.js";
14
18
  import { upsertTableDenied, upsertTenantRow } from "./tenant-db-upsert.js";
19
+ import { isForeignTenantId, requestedTenantIds, tenantIdsAfterExclusion, } from "./tenant-id-filter.js";
20
+ import { registerRunnerProxyTarget } from "./transaction-serialization.js";
15
21
  export { SYSTEM_SCOPE_CHECK_BRAND, } from "@cosmicdrift/kumiko-types/tenant-db-types";
16
22
  const declaredUnsafeRawRunners = new WeakMap();
17
23
  // The CRUD executor writes through tenantDbRunner, not insertOne, so it asks the
@@ -67,6 +73,7 @@ function boundRunner(runner, gate, projectionRegistry, executorManagedWrites) {
67
73
  return value.bind(target);
68
74
  },
69
75
  });
76
+ registerRunnerProxyTarget(proxy, runner);
70
77
  if (gate)
71
78
  runnerPersonalDataGates.set(proxy, gate);
72
79
  if (projectionRegistry)
@@ -166,9 +173,10 @@ function buildUncheckedSystemDb(db, dbOutsideTransaction, report, gate) {
166
173
  `${gate.deniedCallerLabel} to allow unsafeRaw.`,
167
174
  });
168
175
  }
176
+ // A granted unsafeRaw is a declared, audited bypass of the TenantDb filter, so row-level security does not narrow it either.
169
177
  // Engine-forwarded steps carry their own declared reason; a caller-supplied one never reaches the audit trail.
170
178
  report("unsafe-raw", forwardedDeclaredStep ? reason : (gate?.grant?.reason ?? reason));
171
- const runner = withoutExecutorManagedWrites(tenantDbRunner(db));
179
+ const runner = unsafeRawScopedRunner(withoutExecutorManagedWrites(tenantDbRunner(db)));
172
180
  return boundRunner(runner, personalDataGates.get(db), projectionRegistryOf(db), false);
173
181
  }
174
182
  const uncheckedSystemDb = {
@@ -234,10 +242,9 @@ function buildUncheckedSystemDb(db, dbOutsideTransaction, report, gate) {
234
242
  // own tenantId, never a foreign one.
235
243
  //
236
244
  // dbOutsideTransaction is optional so every existing single-arg call site
237
- // (jobs/job-runner.ts, tests) keeps compiling — those callers have no
238
- // outside-tx source to hand in and never needed one. Only
239
- // buildHandlerContext passes it, which is also the only place `.outsideTransaction`
240
- // is reachable through `ctx.systemDb`.
245
+ // (jobs/job-runner.ts, tests) keeps compiling — those callers have no outside-tx
246
+ // source to hand in. Only buildHandlerContext passes it, which is also the only
247
+ // place `.outsideTransaction` is reachable through `ctx.systemDb`.
241
248
  //
242
249
  // Ungated here (the handler's own systemScope() is the grant); a hook's own
243
250
  // escapeHatch is layered on afterwards via withSystemDbUnsafeRawGrant. Public
@@ -252,55 +259,16 @@ export function createUncheckedSystemDb(db, dbOutsideTransaction, report = fallb
252
259
  export function createSystemDbView(db, dbOutsideTransaction, report = fallbackEscapeHatchReporter(db.tenantId)) {
253
260
  return buildUncheckedSystemDb(db, dbOutsideTransaction, report, { kind: "source-tenant-db" });
254
261
  }
255
- // Narrows a (possibly "system"-mode) TenantDb to a "tenant"-mode handle for one tenant on the
256
- // same connection/transaction. For code that must run caller-supplied callbacks (e.g. config
257
- // validators) without handing them a cross-tenant view.
258
- export function scopeTenantDbToTenant(db, tenantId) {
259
- const writesDeniedReason = tenantDbWritesDeniedReason(db);
260
- return createTenantDb({
261
- db: tenantDbRunner(db),
262
- tenantId,
263
- mode: "tenant",
264
- ...(writesDeniedReason !== undefined && { grants: { writesDeniedReason } }),
265
- });
266
- }
267
262
  // @cast-boundary tenant-db-row
268
263
  export function castTenantRows(rows) {
269
264
  return rows;
270
265
  }
266
+ export { requestedTenantIds } from "./tenant-id-filter.js";
271
267
  export { tableNameOf };
272
268
  // A grant is only real when its reason is non-empty — `{ reason: "" }` must not silently unlock it.
273
269
  function hasGrant(decl) {
274
270
  return decl !== undefined && decl.reason.trim().length > 0;
275
271
  }
276
- // Tenant ids left over when the caller excludes some via ne/notIn; undefined for other operator forms.
277
- function tenantIdsAfterExclusion(requested, allowed) {
278
- if (!isPlainObject(requested))
279
- return undefined;
280
- if ("ne" in requested)
281
- return allowed.filter((t) => t !== requested["ne"]);
282
- if (Array.isArray(requested["notIn"])) {
283
- const excluded = requested["notIn"];
284
- return allowed.filter((t) => !excluded.includes(t));
285
- }
286
- return undefined;
287
- }
288
- // Tenant ids a where.tenantId filter asks for; undefined for operator forms
289
- // that cannot narrow to a tenant list (ne, like, ...).
290
- export function requestedTenantIds(requested) {
291
- if (Array.isArray(requested))
292
- return requested;
293
- if (!isPlainObject(requested))
294
- return [requested];
295
- if (Array.isArray(requested["in"]))
296
- return requested["in"];
297
- if ("eq" in requested)
298
- return [requested["eq"]];
299
- return undefined;
300
- }
301
- function isForeignTenantId(tenantIdValue) {
302
- return tenantIdValue !== undefined && tenantIdValue !== SYSTEM_TENANT_ID;
303
- }
304
272
  // Checks the canonical EntityTableMeta (branded EntityTable's KUMIKO_META_SYMBOL
305
273
  // or a plain deriveEntityTableMeta/defineUnmanagedTable result), not a direct
306
274
  // `table.tenantId` property read — the latter only exists on branded EntityTables
@@ -347,28 +315,16 @@ export function reportConventionCrossTenantUse(acknowledged, target) {
347
315
  }
348
316
  reporter(target);
349
317
  }
350
- const ownTransactionRebinders = new WeakMap();
351
318
  export function hasOutsideTransactionDb(ctx) {
352
- return ctx.dbOutsideTransaction !== undefined;
319
+ return ctx.db.outsideTransaction !== undefined;
353
320
  }
354
321
  export function requireOutsideTransactionDb(ctx) {
355
322
  if (!hasOutsideTransactionDb(ctx)) {
356
323
  throw new InternalError({
357
- message: "ctx.dbOutsideTransaction is not available in this dispatch phase (member-resolution, before-transaction denial) or metering tenant mode.",
358
- });
359
- }
360
- return ctx.dbOutsideTransaction;
361
- }
362
- export async function runInOwnTransaction(tenantDb, fn) {
363
- const rebind = ownTransactionRebinders.get(tenantDb);
364
- if (!rebind) {
365
- throw new InternalError({
366
- message: "runInOwnTransaction received a TenantDb without a transaction rebinder: either it was not " +
367
- "built by createTenantDb, or it is the fail-closed ctx.db/ctx.dbOutsideTransaction of an " +
368
- "r.systemScope() handler (use ctx.systemDb.outsideTransaction there).",
324
+ message: "ctx.db.outsideTransaction is not available in this dispatch phase (member-resolution, before-transaction denial) or metering tenant mode.",
369
325
  });
370
326
  }
371
- return rebind(fn);
327
+ return ctx.db.outsideTransaction;
372
328
  }
373
329
  export function createTenantDb(options) {
374
330
  return buildTenantDb(options);
@@ -380,7 +336,9 @@ export function createTenantDataDestroyDb(options) {
380
336
  // Untyped JS callers or an `as` cast can still hand in undefined; a scoped handle
381
337
  // without a tenant would bind `tenant_id = NULL` instead of failing loudly.
382
338
  function buildTenantDb(options) {
383
- const { db, tenantId, mode = "tenant", tracer, meter, signal, grants } = options;
339
+ const { db: givenDb, tenantId, mode = "tenant", reason: systemReason, tracer, meter, signal, grants, } = options;
340
+ const modeOptions = mode === "system" ? systemModeOptions(systemReason) : { mode: "tenant" };
341
+ const db = mode === "system" ? givenDb : unscopedRunnerOf(givenDb);
384
342
  if (tenantId === undefined) {
385
343
  throw new InternalError({ message: "createTenantDb: tenantId is required" });
386
344
  }
@@ -393,47 +351,13 @@ function buildTenantDb(options) {
393
351
  const rebindGrants = projectionRegistry && grants?.projectionRegistry === undefined
394
352
  ? { ...grants, projectionRegistry }
395
353
  : grants;
396
- function withDbSpan(operation, table, runner) {
397
- signal?.throwIfAborted();
398
- if (!tracer && !meter)
399
- return runner();
400
- const tableName = tableNameOf(table);
401
- const start = performance.now();
402
- const emitMetric = () => {
403
- if (meter) {
404
- emitDbQuery(meter, { operation, table: tableName }, (performance.now() - start) / 1000);
405
- }
406
- };
407
- if (!tracer) {
408
- return (async () => {
409
- try {
410
- return await runner();
411
- }
412
- finally {
413
- emitMetric();
414
- }
415
- })();
416
- }
417
- return tracer.withSpan("db.query", {
418
- kind: "client",
419
- attributes: {
420
- "db.system": "postgresql",
421
- "db.operation": operation,
422
- "db.table": tableName,
423
- },
424
- }, async (span) => {
425
- try {
426
- const result = await runner();
427
- if (Array.isArray(result)) {
428
- span.setAttribute("db.row_count", result.length);
429
- }
430
- return result;
431
- }
432
- finally {
433
- emitMetric();
434
- }
435
- });
436
- }
354
+ const withDbSpan = createTenantDbStatementRunner({
355
+ tracer,
356
+ meter,
357
+ signal,
358
+ ...modeOptions,
359
+ tenantId,
360
+ });
437
361
  // Reads see own-tenant rows + reference data (tenantId === SYSTEM_TENANT_ID).
438
362
  // Writes never touch reference rows — those are system-mode only.
439
363
  // A caller-supplied `where.tenantId` may only NARROW the enforced scope
@@ -613,7 +537,7 @@ function buildTenantDb(options) {
613
537
  }
614
538
  // Engine-forwarded steps carry their own declared reason; otherwise the grant's reason is audited.
615
539
  report("unsafe-raw", declaredStepReason ?? grants?.unsafeRaw?.reason ?? "");
616
- return boundRunner(withoutExecutorManagedWrites(db), personalDataGate, projectionRegistry, false);
540
+ return boundRunner(unsafeRawScopedRunner(withoutExecutorManagedWrites(db)), personalDataGate, projectionRegistry, false);
617
541
  }
618
542
  const tenantDb = {
619
543
  tenantId,
@@ -712,7 +636,7 @@ function buildTenantDb(options) {
712
636
  unsafeRawRebinders.set(tenantDb, (grant) => createTenantDb({
713
637
  db,
714
638
  tenantId,
715
- mode,
639
+ ...modeOptions,
716
640
  tracer,
717
641
  meter,
718
642
  signal,
@@ -730,6 +654,7 @@ function buildTenantDb(options) {
730
654
  db,
731
655
  tenantId,
732
656
  mode: "system",
657
+ reason,
733
658
  tracer,
734
659
  meter,
735
660
  signal,
@@ -738,18 +663,22 @@ function buildTenantDb(options) {
738
663
  crossTenantUseReporters.set(acknowledged, (target) => report("acknowledge-cross-tenant", reason, target));
739
664
  return acknowledged;
740
665
  });
741
- ownTransactionRebinders.set(tenantDb, async (fn) => {
742
- if (grants?.memberReadOnly) {
743
- throw new InternalError({
744
- message: "runInOwnTransaction: memberReadOnly TenantDb — a fresh transaction would escape " +
745
- "the enforced read-only scope.",
746
- });
747
- }
748
- // Carries a runner-bound gate (grants.personalDataGate unset, resolved via the fallback above) forward explicitly, since the fresh tx-handle isn't itself registered in runnerPersonalDataGates.
749
- const txGrants = personalDataGate ? { ...rebindGrants, personalDataGate } : rebindGrants;
750
- return runInNewTransaction(db, (tx) => fn(createTenantDb({ db: tx, tenantId, mode, tracer, meter, signal, grants: txGrants })));
666
+ // Carries a runner-bound gate (grants.personalDataGate unset, resolved via the fallback above) forward explicitly, since a fresh tx-handle isn't itself registered in runnerPersonalDataGates.
667
+ const scopedGrants = personalDataGate ? { ...rebindGrants, personalDataGate } : rebindGrants;
668
+ registerScopedRebinder(tenantDb, {
669
+ memberReadOnly: grants?.memberReadOnly === true,
670
+ rebind: (runner) => createTenantDb({
671
+ db: runner,
672
+ tenantId,
673
+ ...modeOptions,
674
+ tracer,
675
+ meter,
676
+ signal,
677
+ grants: scopedGrants,
678
+ }),
751
679
  });
752
- bindTenantDbRunner(tenantDb, db);
680
+ // Framework code reading through the raw runner (executor list/detail) must follow the db's own mode, not the ambient scope.
681
+ bindTenantDbRunner(tenantDb, db, modeOptions, tenantId);
753
682
  if (grants?.writesDeniedReason !== undefined) {
754
683
  denyTenantDbWrites(tenantDb, grants.writesDeniedReason);
755
684
  }
@@ -0,0 +1,3 @@
1
+ export declare function tenantIdsAfterExclusion(requested: unknown, allowed: readonly unknown[]): readonly unknown[] | undefined;
2
+ export declare function requestedTenantIds(requested: unknown): readonly unknown[] | undefined;
3
+ export declare function isForeignTenantId(tenantIdValue: unknown): boolean;
@@ -0,0 +1,30 @@
1
+ import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
2
+ import { SYSTEM_TENANT_ID } from "../engine/types/identifiers.js";
3
+ // Tenant ids left over when the caller excludes some via ne/notIn; undefined for other operator forms.
4
+ export function tenantIdsAfterExclusion(requested, allowed) {
5
+ if (!isPlainObject(requested))
6
+ return undefined;
7
+ if ("ne" in requested)
8
+ return allowed.filter((t) => t !== requested["ne"]);
9
+ if (Array.isArray(requested["notIn"])) {
10
+ const excluded = requested["notIn"];
11
+ return allowed.filter((t) => !excluded.includes(t));
12
+ }
13
+ return undefined;
14
+ }
15
+ // Tenant ids a where.tenantId filter asks for; undefined for operator forms
16
+ // that cannot narrow to a tenant list (ne, like, ...).
17
+ export function requestedTenantIds(requested) {
18
+ if (Array.isArray(requested))
19
+ return requested;
20
+ if (!isPlainObject(requested))
21
+ return [requested];
22
+ if (Array.isArray(requested["in"]))
23
+ return requested["in"];
24
+ if ("eq" in requested)
25
+ return [requested["eq"]];
26
+ return undefined;
27
+ }
28
+ export function isForeignTenantId(tenantIdValue) {
29
+ return tenantIdValue !== undefined && tenantIdValue !== SYSTEM_TENANT_ID;
30
+ }
@@ -0,0 +1,6 @@
1
+ type HandleKey = object;
2
+ export declare function registerRunnerProxyTarget(proxy: HandleKey, target: HandleKey): void;
3
+ export declare function openSerializedSavepoint<T>(transactionHandle: HandleKey & {
4
+ savepoint: <R>(fn: (sp: unknown) => Promise<R>) => Promise<R>;
5
+ }, fn: (sp: unknown) => Promise<T>): Promise<T>;
6
+ export {};