@cosmicdrift/kumiko-framework 0.388.0 → 0.390.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (711) hide show
  1. package/AGENTS.md +12 -4
  2. package/README.md +1 -1
  3. package/agents/examples/apex-surface-auth.md +2 -3
  4. package/agents/examples/api-worker-split.md +9 -2
  5. package/agents/examples/auth-claims.md +1 -1
  6. package/agents/examples/cross-feature-events.md +12 -12
  7. package/agents/examples/crypto-shredding-hr.md +2 -2
  8. package/agents/examples/encrypted-tenant-config.md +1 -1
  9. package/agents/examples/error-contract.md +12 -7
  10. package/agents/examples/event-sourcing.md +29 -29
  11. package/agents/examples/files-post-processing.md +10 -8
  12. package/agents/examples/golden-path.md +13 -1
  13. package/agents/examples/inbound-mail-triage.md +1 -0
  14. package/agents/examples/lane-routing.md +2 -1
  15. package/agents/examples/legal-pages.md +2 -2
  16. package/agents/examples/lifecycle-hooks.md +55 -2
  17. package/agents/examples/list-table-options.md +466 -0
  18. package/agents/examples/managed-config.md +4 -4
  19. package/agents/examples/managed-pages.md +1 -1
  20. package/agents/examples/pdf-audit-export.md +4 -2
  21. package/agents/examples/relations.md +19 -4
  22. package/agents/examples/search.md +4 -4
  23. package/agents/examples/secrets-demo.md +9 -6
  24. package/agents/examples/state-machine.md +5 -4
  25. package/agents/examples/tenant-isolation.md +73 -1
  26. package/agents/examples/tenant-settings.md +1 -1
  27. package/agents/examples/user-data-rights.md +3 -6
  28. package/agents/examples/workflow-engine.md +53 -47
  29. package/agents/examples.md +5 -4
  30. package/agents/features.md +1 -1
  31. package/agents/widgets.md +1 -0
  32. package/dist/api/api-constants.d.ts +1 -0
  33. package/dist/api/api-constants.js +2 -0
  34. package/dist/api/auth-middleware.js +1 -1
  35. package/dist/api/auth-routes-invite.js +2 -1
  36. package/dist/api/auth-routes-shared.d.ts +2 -0
  37. package/dist/api/auth-routes-shared.js +5 -0
  38. package/dist/api/client-error-route.js +2 -3
  39. package/dist/api/entity-read-access.d.ts +4 -1
  40. package/dist/api/entity-read-access.js +14 -0
  41. package/dist/api/export/export-cells-reference.d.ts +9 -0
  42. package/dist/api/export/export-cells-reference.js +21 -0
  43. package/dist/api/export/export-cells.d.ts +11 -0
  44. package/dist/api/export/export-cells.js +136 -0
  45. package/dist/api/export/export-ciphertext-guard.d.ts +2 -0
  46. package/dist/api/export/export-ciphertext-guard.js +27 -0
  47. package/dist/api/export/export-columns.d.ts +31 -0
  48. package/dist/api/export/export-columns.js +85 -0
  49. package/dist/api/export/export-errors.d.ts +4 -0
  50. package/dist/api/export/export-errors.js +14 -0
  51. package/dist/api/export/export-route.d.ts +4 -0
  52. package/dist/api/export/export-route.js +75 -0
  53. package/dist/api/export/export-rows.d.ts +13 -0
  54. package/dist/api/export/export-rows.js +62 -0
  55. package/dist/api/export/export-screen.d.ts +13 -0
  56. package/dist/api/export/export-screen.js +47 -0
  57. package/dist/api/export/export-xlsx-writer.d.ts +4 -0
  58. package/dist/api/export/export-xlsx-writer.js +21 -0
  59. package/dist/api/extra-route.d.ts +7 -1
  60. package/dist/api/index.d.ts +23 -27
  61. package/dist/api/index.js +13 -15
  62. package/dist/api/jwt.js +1 -1
  63. package/dist/api/observability-middleware.d.ts +1 -1
  64. package/dist/api/observability-middleware.js +2 -1
  65. package/dist/api/pii-leak-guard.d.ts +3 -0
  66. package/dist/api/pii-leak-guard.js +3 -2
  67. package/dist/api/request-context-internals.d.ts +31 -0
  68. package/dist/api/request-context-internals.js +11 -0
  69. package/dist/api/request-context-scopes.d.ts +14 -0
  70. package/dist/api/request-context-scopes.js +69 -0
  71. package/dist/api/request-context.d.ts +1 -40
  72. package/dist/api/request-context.js +22 -51
  73. package/dist/api/request-id-middleware.d.ts +1 -1
  74. package/dist/api/route-registrars.d.ts +2 -1
  75. package/dist/api/route-registrars.js +1 -1
  76. package/dist/api/routes.d.ts +16 -0
  77. package/dist/api/routes.js +9 -5
  78. package/dist/api/server-boot-checks.d.ts +1 -1
  79. package/dist/api/server-boot-checks.js +2 -2
  80. package/dist/api/server-event-dispatcher.d.ts +6 -1
  81. package/dist/api/server-event-dispatcher.js +3 -4
  82. package/dist/api/server-extra-routes.d.ts +1 -1
  83. package/dist/api/server-extra-routes.js +5 -1
  84. package/dist/api/server-middleware.js +3 -1
  85. package/dist/api/server-routes.d.ts +3 -2
  86. package/dist/api/server-routes.js +8 -2
  87. package/dist/api/server-wiring.js +8 -4
  88. package/dist/api/server.d.ts +2 -1
  89. package/dist/api/sse-route.d.ts +3 -1
  90. package/dist/api/sse-route.js +11 -1
  91. package/dist/api/tenant-scoped-secrets.d.ts +2 -0
  92. package/dist/api/tenant-scoped-secrets.js +13 -0
  93. package/dist/api/websocket-route.d.ts +1 -1
  94. package/dist/auth/index.d.ts +0 -1
  95. package/dist/auth/roles.d.ts +0 -5
  96. package/dist/compliance/duration-spec.d.ts +0 -1
  97. package/dist/compliance/duration-spec.js +0 -5
  98. package/dist/compliance/index.d.ts +4 -4
  99. package/dist/compliance/index.js +2 -2
  100. package/dist/compliance/profiles.d.ts +0 -15
  101. package/dist/compliance/profiles.js +0 -23
  102. package/dist/config/index.d.ts +11 -9
  103. package/dist/config/index.js +13 -1
  104. package/dist/config/internals.d.ts +9 -0
  105. package/dist/config/internals.js +1 -0
  106. package/dist/consumer-cli-internals.d.ts +4 -0
  107. package/dist/consumer-cli-internals.js +1 -0
  108. package/dist/consumer-cli.d.ts +1 -4
  109. package/dist/consumer-cli.js +5 -1
  110. package/dist/crypto/event-pii.js +1 -1
  111. package/dist/crypto/index.d.ts +8 -9
  112. package/dist/crypto/index.js +7 -8
  113. package/dist/crypto/pg-kms-adapter.d.ts +1 -0
  114. package/dist/crypto/pg-kms-adapter.js +17 -18
  115. package/dist/db/aggregate-sql.d.ts +2 -0
  116. package/dist/db/aggregate-sql.js +10 -0
  117. package/dist/db/apply-entity-event.d.ts +1 -1
  118. package/dist/db/apply-entity-event.js +15 -47
  119. package/dist/db/blind-index-cleanup.js +91 -77
  120. package/dist/db/closed-connection.js +12 -19
  121. package/dist/db/collect-table-metas.js +1 -1
  122. package/dist/db/compound-types.d.ts +1 -1
  123. package/dist/db/compound-types.js +0 -7
  124. package/dist/db/config-seed.d.ts +2 -1
  125. package/dist/db/config-seed.js +6 -1
  126. package/dist/db/connection.d.ts +7 -6
  127. package/dist/db/connection.js +43 -24
  128. package/dist/db/cross-tenant-reads.d.ts +1 -1
  129. package/dist/db/cross-tenant-reads.js +1 -1
  130. package/dist/db/dialect.d.ts +0 -5
  131. package/dist/db/dialect.js +0 -3
  132. package/dist/db/driver-row-coercion.js +4 -4
  133. package/dist/db/driver-value-preparation.js +6 -4
  134. package/dist/db/eagerload.d.ts +2 -1
  135. package/dist/db/entity-field-encryption.d.ts +1 -1
  136. package/dist/db/entity-table-meta.d.ts +1 -1
  137. package/dist/db/event-store-executor-context.d.ts +3 -1
  138. package/dist/db/event-store-executor-context.js +4 -3
  139. package/dist/db/event-store-executor-read-aggregate-currencies.d.ts +17 -0
  140. package/dist/db/event-store-executor-read-aggregate-currencies.js +40 -0
  141. package/dist/db/event-store-executor-read-aggregate.js +36 -5
  142. package/dist/db/event-store-executor-read-filter.d.ts +1 -1
  143. package/dist/db/event-store-executor-read-filter.js +6 -3
  144. package/dist/db/event-store-executor-read-rows.d.ts +2 -1
  145. package/dist/db/event-store-executor-read-search.d.ts +2 -1
  146. package/dist/db/event-store-executor-read-sort.d.ts +2 -1
  147. package/dist/db/event-store-executor-read.js +2 -2
  148. package/dist/db/event-store-executor-write-atomic.d.ts +4 -0
  149. package/dist/db/event-store-executor-write-atomic.js +42 -0
  150. package/dist/db/event-store-executor-write-steps.d.ts +3 -5
  151. package/dist/db/event-store-executor-write-steps.js +0 -5
  152. package/dist/db/event-store-executor-write.js +22 -19
  153. package/dist/db/event-store-executor.d.ts +1 -1
  154. package/dist/db/event-store-executor.js +2 -1
  155. package/dist/db/executor-managed-tables.d.ts +7 -1
  156. package/dist/db/executor-managed-tables.js +12 -3
  157. package/dist/db/index.d.ts +29 -28
  158. package/dist/db/index.js +22 -20
  159. package/dist/db/known-table-names.d.ts +6 -0
  160. package/dist/db/known-table-names.js +21 -0
  161. package/dist/db/list-aggregate-labels.d.ts +1 -1
  162. package/dist/db/located-timestamp.d.ts +1 -1
  163. package/dist/db/located-timestamp.js +0 -5
  164. package/dist/db/migrate-generator.d.ts +17 -1
  165. package/dist/db/migrate-generator.js +50 -20
  166. package/dist/db/migrate-primary-key.d.ts +12 -0
  167. package/dist/db/migrate-primary-key.js +45 -0
  168. package/dist/db/migrate-rls-diff.d.ts +20 -0
  169. package/dist/db/migrate-rls-diff.js +61 -0
  170. package/dist/db/migrate-runner.js +7 -3
  171. package/dist/db/money.d.ts +1 -1
  172. package/dist/db/money.js +1 -1
  173. package/dist/db/parent-ref-clause.d.ts +2 -1
  174. package/dist/db/pg-error.d.ts +2 -0
  175. package/dist/db/pg-error.js +37 -21
  176. package/dist/db/queries/backfill-pii.js +3 -6
  177. package/dist/db/queries/database-now.js +2 -1
  178. package/dist/db/queries/ddl.d.ts +3 -0
  179. package/dist/db/queries/ddl.js +34 -1
  180. package/dist/db/queries/event-store.js +4 -2
  181. package/dist/db/queries/event-tenants.d.ts +2 -0
  182. package/dist/db/queries/event-tenants.js +17 -0
  183. package/dist/db/queries/rebuild-rls-guard.d.ts +2 -0
  184. package/dist/db/queries/rebuild-rls-guard.js +29 -0
  185. package/dist/db/queries/rls-boot-catalog.d.ts +16 -0
  186. package/dist/db/queries/rls-boot-catalog.js +39 -0
  187. package/dist/db/queries/rls-catalog.d.ts +6 -0
  188. package/dist/db/queries/rls-catalog.js +82 -0
  189. package/dist/db/queries/rls-scope.d.ts +3 -0
  190. package/dist/db/queries/rls-scope.js +17 -0
  191. package/dist/db/queries/rls-shape.d.ts +10 -0
  192. package/dist/db/queries/rls-shape.js +42 -0
  193. package/dist/db/queries/session-advisory-lock.d.ts +2 -0
  194. package/dist/db/queries/session-advisory-lock.js +23 -0
  195. package/dist/db/queries/shadow-swap.d.ts +1 -2
  196. package/dist/db/queries/shadow-swap.js +11 -28
  197. package/dist/db/queries/test-stack.d.ts +4 -1
  198. package/dist/db/queries/test-stack.js +83 -2
  199. package/dist/db/query.d.ts +14 -0
  200. package/dist/db/query.js +77 -48
  201. package/dist/db/reference-data.d.ts +1 -1
  202. package/dist/db/reference-data.js +20 -3
  203. package/dist/db/render-ddl.d.ts +6 -2
  204. package/dist/db/render-ddl.js +7 -7
  205. package/dist/db/render-rls-ddl.d.ts +35 -0
  206. package/dist/db/render-rls-ddl.js +127 -0
  207. package/dist/db/replay-migration-sql.d.ts +3 -1
  208. package/dist/db/replay-migration-sql.js +22 -5
  209. package/dist/db/replay-rls.d.ts +25 -0
  210. package/dist/db/replay-rls.js +156 -0
  211. package/dist/db/row-level-security-boot-check.d.ts +5 -0
  212. package/dist/db/row-level-security-boot-check.js +85 -0
  213. package/dist/db/row-level-security-connection.d.ts +3 -0
  214. package/dist/db/row-level-security-connection.js +213 -0
  215. package/dist/db/row-level-security-scope.d.ts +33 -0
  216. package/dist/db/row-level-security-scope.js +127 -0
  217. package/dist/db/scope-tenant-db-to-tenant.d.ts +3 -0
  218. package/dist/db/scope-tenant-db-to-tenant.js +14 -0
  219. package/dist/db/sql-identifier.d.ts +1 -0
  220. package/dist/db/sql-identifier.js +3 -0
  221. package/dist/db/statement-timeout.js +2 -1
  222. package/dist/db/table-builder.d.ts +2 -1
  223. package/dist/db/table-builder.js +1 -1
  224. package/dist/db/table-info.js +1 -1
  225. package/dist/db/table-push.d.ts +11 -2
  226. package/dist/db/table-push.js +15 -2
  227. package/dist/db/tenant-db-runner.d.ts +3 -1
  228. package/dist/db/tenant-db-runner.js +4 -3
  229. package/dist/db/tenant-db-scoped-rebind.d.ts +10 -0
  230. package/dist/db/tenant-db-scoped-rebind.js +33 -0
  231. package/dist/db/tenant-db-statement-runner.d.ts +13 -0
  232. package/dist/db/tenant-db-statement-runner.js +48 -0
  233. package/dist/db/tenant-db-upsert.d.ts +5 -0
  234. package/dist/db/tenant-db-upsert.js +91 -0
  235. package/dist/db/tenant-db.d.ts +17 -12
  236. package/dist/db/tenant-db.js +60 -121
  237. package/dist/db/tenant-id-filter.d.ts +3 -0
  238. package/dist/db/tenant-id-filter.js +30 -0
  239. package/dist/db/transaction-serialization.d.ts +6 -0
  240. package/dist/db/transaction-serialization.js +60 -0
  241. package/dist/derivatives/delete-stored-file.js +1 -1
  242. package/dist/derivatives/index.d.ts +2 -5
  243. package/dist/derivatives/index.js +2 -3
  244. package/dist/engine/access.d.ts +2 -1
  245. package/dist/engine/access.js +1 -1
  246. package/dist/engine/boot-validator/bundled-lists-table.d.ts +2 -0
  247. package/dist/engine/boot-validator/bundled-lists-table.js +36 -0
  248. package/dist/engine/boot-validator/entity-handler.d.ts +2 -1
  249. package/dist/engine/boot-validator/entity-handler.js +1 -1
  250. package/dist/engine/boot-validator/entity-list-aggregate-options.d.ts +3 -0
  251. package/dist/engine/boot-validator/entity-list-aggregate-options.js +23 -0
  252. package/dist/engine/boot-validator/list-bulk-actions.d.ts +3 -0
  253. package/dist/engine/boot-validator/list-bulk-actions.js +49 -0
  254. package/dist/engine/boot-validator/list-column-layout.d.ts +8 -0
  255. package/dist/engine/boot-validator/list-column-layout.js +41 -0
  256. package/dist/engine/boot-validator/list-table-aggregate-options.d.ts +24 -0
  257. package/dist/engine/boot-validator/list-table-aggregate-options.js +145 -0
  258. package/dist/engine/boot-validator/list-table-aggregate-query.d.ts +11 -0
  259. package/dist/engine/boot-validator/list-table-aggregate-query.js +31 -0
  260. package/dist/engine/boot-validator/list-table-export-options.d.ts +1 -0
  261. package/dist/engine/boot-validator/list-table-export-options.js +27 -0
  262. package/dist/engine/boot-validator/list-table-options.d.ts +3 -0
  263. package/dist/engine/boot-validator/list-table-options.js +77 -0
  264. package/dist/engine/boot-validator/list-table-reject-unknown-keys.d.ts +1 -0
  265. package/dist/engine/boot-validator/list-table-reject-unknown-keys.js +7 -0
  266. package/dist/engine/boot-validator/nav.d.ts +3 -1
  267. package/dist/engine/boot-validator/nav.js +1 -1
  268. package/dist/engine/boot-validator/ownership.d.ts +2 -1
  269. package/dist/engine/boot-validator/parent-ref.d.ts +2 -1
  270. package/dist/engine/boot-validator/projection-list-screens.d.ts +2 -1
  271. package/dist/engine/boot-validator/projection-list-screens.js +3 -13
  272. package/dist/engine/boot-validator/query-refs.d.ts +2 -1
  273. package/dist/engine/boot-validator/related-list-table-rules.d.ts +4 -0
  274. package/dist/engine/boot-validator/related-list-table-rules.js +42 -0
  275. package/dist/engine/boot-validator/screens-forms.d.ts +2 -1
  276. package/dist/engine/boot-validator/screens-kind-entity-list.js +7 -0
  277. package/dist/engine/boot-validator/screens-kind-projection-list.js +4 -0
  278. package/dist/engine/boot-validator/screens-kind-shared.d.ts +3 -1
  279. package/dist/engine/boot-validator/screens-lists.js +12 -2
  280. package/dist/engine/boot-validator/screens.d.ts +2 -1
  281. package/dist/engine/boot-validator/workspaces.d.ts +3 -1
  282. package/dist/engine/bridge-stub.d.ts +5 -2
  283. package/dist/engine/bridge-stub.js +39 -24
  284. package/dist/engine/build-app-schema.d.ts +2 -1
  285. package/dist/engine/build-app-schema.js +9 -1
  286. package/dist/engine/build-config-feature-schema.js +6 -1
  287. package/dist/engine/config-helpers.d.ts +2 -2
  288. package/dist/engine/config-helpers.js +0 -9
  289. package/dist/engine/constants.d.ts +0 -10
  290. package/dist/engine/constants.js +0 -8
  291. package/dist/engine/create-app.js +1 -1
  292. package/dist/engine/define-feature.d.ts +2 -1
  293. package/dist/engine/define-feature.js +5 -2
  294. package/dist/engine/define-handler.d.ts +1 -1
  295. package/dist/engine/define-step.d.ts +0 -1
  296. package/dist/engine/define-step.js +0 -3
  297. package/dist/engine/embedded-derived.d.ts +1 -1
  298. package/dist/engine/entity-handlers.d.ts +2 -1
  299. package/dist/engine/entity-handlers.js +7 -7
  300. package/dist/engine/entity-list-runtime-options.js +3 -1
  301. package/dist/engine/entity-list-searchability.d.ts +2 -1
  302. package/dist/engine/event-def.d.ts +2 -1
  303. package/dist/engine/event-helpers.d.ts +3 -1
  304. package/dist/engine/event-helpers.js +3 -3
  305. package/dist/engine/extension-names.d.ts +2 -8
  306. package/dist/engine/extension-names.js +2 -2
  307. package/dist/engine/extension-selector-plugins.d.ts +1 -1
  308. package/dist/engine/extensions/storage-provider.d.ts +1 -2
  309. package/dist/engine/extensions/user-data.d.ts +0 -8
  310. package/dist/engine/factories.d.ts +2 -1
  311. package/dist/engine/feature-builder-state.d.ts +9 -1
  312. package/dist/engine/feature-builder-state.js +1 -0
  313. package/dist/engine/feature-changelog.d.ts +1 -1
  314. package/dist/engine/feature-config-events-jobs.d.ts +4 -1
  315. package/dist/engine/feature-entity-handlers.d.ts +5 -1
  316. package/dist/engine/feature-manifest.d.ts +1 -0
  317. package/dist/engine/feature-manifest.js +2 -1
  318. package/dist/engine/feature-ui-extensions.d.ts +7 -1
  319. package/dist/engine/feature-ui-extensions.js +6 -4
  320. package/dist/engine/field-access.d.ts +3 -1
  321. package/dist/engine/field-access.js +12 -0
  322. package/dist/engine/handler-field-references.d.ts +0 -4
  323. package/dist/engine/index.d.ts +58 -55
  324. package/dist/engine/index.js +23 -28
  325. package/dist/engine/instruction-fields.d.ts +1 -1
  326. package/dist/engine/personal-data-fields.d.ts +1 -1
  327. package/dist/engine/qualified-name.d.ts +0 -1
  328. package/dist/engine/read-claim.d.ts +2 -1
  329. package/dist/engine/registry-facade.js +0 -3
  330. package/dist/engine/registry-ingest.d.ts +2 -1
  331. package/dist/engine/registry-ingest.js +1 -2
  332. package/dist/engine/registry-state.d.ts +12 -2
  333. package/dist/engine/registry-state.js +2 -3
  334. package/dist/engine/registry-validate.d.ts +3 -1
  335. package/dist/engine/registry-validate.js +7 -7
  336. package/dist/engine/run-in.d.ts +1 -1
  337. package/dist/engine/run-in.js +0 -1
  338. package/dist/engine/schema-builder.d.ts +1 -1
  339. package/dist/engine/schema-builder.js +1 -1
  340. package/dist/engine/screen-filter-ops.d.ts +2 -1
  341. package/dist/engine/screen-filter-ops.js +2 -5
  342. package/dist/engine/soft-delete-cleanup.d.ts +1 -1
  343. package/dist/engine/soft-delete-cleanup.js +4 -4
  344. package/dist/engine/state-machine.js +2 -1
  345. package/dist/engine/steps/_read-source.js +1 -1
  346. package/dist/engine/steps/aggregate-append-event.js +2 -2
  347. package/dist/engine/steps/call-feature.js +2 -2
  348. package/dist/engine/steps/mail-send.js +1 -1
  349. package/dist/engine/steps/retry.js +1 -1
  350. package/dist/engine/steps/wait-for-event.js +1 -1
  351. package/dist/engine/steps/wait.js +1 -1
  352. package/dist/engine/steps/webhook-send.js +1 -1
  353. package/dist/engine/strip-disabled-features-from-app-schema.js +7 -3
  354. package/dist/engine/template-variables.d.ts +2 -1
  355. package/dist/engine/transfer-adjacency.d.ts +1 -1
  356. package/dist/engine/types/feature.d.ts +1 -0
  357. package/dist/engine/types/index.d.ts +8 -30
  358. package/dist/engine/types/index.js +2 -10
  359. package/dist/engine/types/screen.d.ts +1 -1
  360. package/dist/engine/types/screen.js +1 -1
  361. package/dist/engine/validation.d.ts +2 -1
  362. package/dist/entrypoint/index.d.ts +9 -35
  363. package/dist/entrypoint/index.js +10 -1
  364. package/dist/entrypoint/internals.d.ts +40 -0
  365. package/dist/entrypoint/internals.js +1 -0
  366. package/dist/entrypoint/row-level-security-mode-check.d.ts +3 -0
  367. package/dist/entrypoint/row-level-security-mode-check.js +19 -0
  368. package/dist/env/dry-run-internals.d.ts +10 -0
  369. package/dist/env/dry-run-internals.js +1 -0
  370. package/dist/env/dry-run.d.ts +1 -10
  371. package/dist/env/dry-run.js +2 -1
  372. package/dist/env/index.d.ts +1 -85
  373. package/dist/env/index.js +6 -50
  374. package/dist/env/internals.d.ts +87 -0
  375. package/dist/env/internals.js +53 -0
  376. package/dist/errors/classes.js +2 -2
  377. package/dist/errors/index.d.ts +5 -14
  378. package/dist/errors/index.js +4 -9
  379. package/dist/errors/member-resolution.js +1 -1
  380. package/dist/errors/reasons.d.ts +0 -1
  381. package/dist/errors/reasons.js +7 -7
  382. package/dist/errors/serialize.d.ts +0 -18
  383. package/dist/errors/serialize.js +0 -27
  384. package/dist/es-ops/index.d.ts +4 -4
  385. package/dist/es-ops/index.js +2 -2
  386. package/dist/es-ops/operations-schema.d.ts +1 -1
  387. package/dist/es-ops/types.d.ts +4 -5
  388. package/dist/event-store/admin-api-internals.d.ts +14 -0
  389. package/dist/event-store/admin-api-internals.js +1 -0
  390. package/dist/event-store/admin-api.d.ts +1 -14
  391. package/dist/event-store/admin-api.js +11 -6
  392. package/dist/event-store/archive.js +4 -2
  393. package/dist/event-store/errors.js +2 -2
  394. package/dist/event-store/event-store.d.ts +1 -0
  395. package/dist/event-store/event-store.js +42 -32
  396. package/dist/event-store/events-schema.js +4 -1
  397. package/dist/event-store/index.d.ts +11 -13
  398. package/dist/event-store/index.js +7 -9
  399. package/dist/event-store/provenance-append.js +1 -1
  400. package/dist/event-store/rebuild-dead-letter.js +4 -2
  401. package/dist/event-store/snapshot.js +4 -3
  402. package/dist/event-store/stream-scope.d.ts +2 -0
  403. package/dist/event-store/stream-scope.js +6 -0
  404. package/dist/event-store/upcaster-dead-letter.js +4 -2
  405. package/dist/event-store/upcaster.d.ts +2 -1
  406. package/dist/files/action-form-upload.d.ts +2 -1
  407. package/dist/files/action-form-upload.js +1 -1
  408. package/dist/files/assert-file-refs-belong-to-tenant.d.ts +2 -1
  409. package/dist/files/assert-file-refs-belong-to-tenant.js +1 -1
  410. package/dist/files/bind-pending-file-refs.d.ts +2 -1
  411. package/dist/files/bind-pending-file-refs.js +2 -1
  412. package/dist/files/bind-referenced-files.write.js +1 -1
  413. package/dist/files/create-file-ref-from-bytes.d.ts +6 -3
  414. package/dist/files/create-file-ref-from-bytes.js +6 -3
  415. package/dist/files/create-file-ref.d.ts +6 -2
  416. package/dist/files/create-file-ref.js +13 -4
  417. package/dist/files/dispose-removed-file-refs.d.ts +2 -1
  418. package/dist/files/dispose-removed-file-refs.js +1 -1
  419. package/dist/files/feature.js +2 -2
  420. package/dist/files/file-handle.js +1 -1
  421. package/dist/files/file-routes.d.ts +3 -1
  422. package/dist/files/file-routes.js +41 -4
  423. package/dist/files/index.d.ts +11 -13
  424. package/dist/files/index.js +5 -7
  425. package/dist/files/load-save-file-refs.d.ts +2 -1
  426. package/dist/files/load-save-file-refs.js +1 -1
  427. package/dist/files/provider-resolver.d.ts +6 -4
  428. package/dist/files/provider-resolver.js +5 -5
  429. package/dist/files/record-write-check.d.ts +6 -0
  430. package/dist/files/record-write-check.js +13 -0
  431. package/dist/files/storage-tracking.js +4 -2
  432. package/dist/files/sweep-orphaned-uploads.d.ts +1 -1
  433. package/dist/files/sweep-orphaned-uploads.js +1 -1
  434. package/dist/files/upload-ledger.d.ts +2 -2
  435. package/dist/files/upload-ledger.js +4 -4
  436. package/dist/i18n/index.d.ts +2 -8
  437. package/dist/i18n/index.js +1 -1
  438. package/dist/i18n/internals.d.ts +7 -0
  439. package/dist/i18n/internals.js +1 -0
  440. package/dist/i18n/required-surface-keys.d.ts +4 -1
  441. package/dist/i18n/required-surface-keys.js +7 -2
  442. package/dist/internal/row-level-security.d.ts +3 -0
  443. package/dist/internal/row-level-security.js +3 -0
  444. package/dist/internal/stack-support.d.ts +1 -1
  445. package/dist/internal/stack-support.js +1 -1
  446. package/dist/internal/testing.d.ts +1 -0
  447. package/dist/internal/testing.js +10 -6
  448. package/dist/jobs/index.d.ts +1 -1
  449. package/dist/jobs/job-append-event.d.ts +12 -0
  450. package/dist/jobs/job-append-event.js +30 -0
  451. package/dist/jobs/job-runner-context.d.ts +2 -2
  452. package/dist/jobs/job-runner-context.js +46 -16
  453. package/dist/jobs/job-runner-execution.d.ts +1 -1
  454. package/dist/jobs/job-runner-execution.js +6 -4
  455. package/dist/jobs/job-runner-gates.d.ts +1 -1
  456. package/dist/jobs/job-runner-gates.js +0 -1
  457. package/dist/jobs/job-runner-helpers.d.ts +11 -4
  458. package/dist/jobs/job-runner-helpers.js +10 -1
  459. package/dist/jobs/job-runner-scope.d.ts +5 -2
  460. package/dist/jobs/job-runner-scope.js +6 -6
  461. package/dist/jobs/job-runner-types.d.ts +2 -1
  462. package/dist/jobs/job-runner.js +22 -6
  463. package/dist/jobs/max-per-tenant.d.ts +1 -1
  464. package/dist/logging/index.d.ts +1 -2
  465. package/dist/logging/index.js +1 -1
  466. package/dist/logging/pino-logger.js +1 -1
  467. package/dist/logging/utils.d.ts +1 -0
  468. package/dist/logging/utils.js +6 -0
  469. package/dist/migrations/index.d.ts +3 -3
  470. package/dist/migrations/index.js +3 -3
  471. package/dist/migrations/pending-rebuilds.d.ts +1 -1
  472. package/dist/migrations/pending-rebuilds.js +1 -1
  473. package/dist/migrations/pii-event-backfill.js +4 -1
  474. package/dist/observability/escape-hatch-report.d.ts +2 -1
  475. package/dist/observability/escape-hatch-report.js +9 -2
  476. package/dist/observability/index.d.ts +7 -15
  477. package/dist/observability/index.js +4 -12
  478. package/dist/observability/metric-validator.js +1 -1
  479. package/dist/observability/metrics-handle.d.ts +0 -1
  480. package/dist/observability/metrics-handle.js +2 -15
  481. package/dist/observability/recording-tracer.d.ts +1 -2
  482. package/dist/observability/recording-tracer.js +0 -6
  483. package/dist/observability/sensitive-filter.d.ts +0 -2
  484. package/dist/observability/sensitive-filter.js +0 -29
  485. package/dist/pipeline/active-membership.d.ts +2 -1
  486. package/dist/pipeline/active-membership.js +6 -2
  487. package/dist/pipeline/after-rollback-sink.d.ts +6 -0
  488. package/dist/pipeline/after-rollback-sink.js +32 -0
  489. package/dist/pipeline/append-event-core.d.ts +2 -1
  490. package/dist/pipeline/append-event-core.js +2 -2
  491. package/dist/pipeline/attach-outside-transaction.d.ts +3 -0
  492. package/dist/pipeline/attach-outside-transaction.js +13 -0
  493. package/dist/pipeline/auth-claims-resolver.d.ts +2 -1
  494. package/dist/pipeline/cascade-handler.d.ts +2 -1
  495. package/dist/pipeline/cascade-handler.js +3 -2
  496. package/dist/pipeline/config-accessor-factory.d.ts +1 -1
  497. package/dist/pipeline/config-accessor-factory.js +1 -1
  498. package/dist/pipeline/context-services.d.ts +56 -0
  499. package/dist/pipeline/context-services.js +73 -0
  500. package/dist/pipeline/dispatch-batch.d.ts +2 -1
  501. package/dist/pipeline/dispatch-batch.js +39 -19
  502. package/dist/pipeline/dispatch-query.js +5 -4
  503. package/dist/pipeline/dispatch-scope.d.ts +6 -0
  504. package/dist/pipeline/dispatch-scope.js +27 -0
  505. package/dist/pipeline/dispatch-shared.d.ts +13 -9
  506. package/dist/pipeline/dispatch-shared.js +75 -194
  507. package/dist/pipeline/dispatch-stream.js +8 -4
  508. package/dist/pipeline/dispatch-write.d.ts +2 -1
  509. package/dist/pipeline/dispatch-write.js +10 -8
  510. package/dist/pipeline/dispatcher-utils.d.ts +3 -1
  511. package/dist/pipeline/dispatcher-utils.js +8 -2
  512. package/dist/pipeline/dispatcher.d.ts +3 -2
  513. package/dist/pipeline/dispatcher.js +4 -3
  514. package/dist/pipeline/event-consumer-state.d.ts +0 -1
  515. package/dist/pipeline/event-dispatcher-delivery.d.ts +1 -1
  516. package/dist/pipeline/event-dispatcher-delivery.js +7 -3
  517. package/dist/pipeline/event-dispatcher.d.ts +3 -2
  518. package/dist/pipeline/event-dispatcher.js +13 -12
  519. package/dist/pipeline/event-retention.js +59 -56
  520. package/dist/pipeline/handler-access-error.js +2 -1
  521. package/dist/pipeline/handler-context-auth.d.ts +5 -6
  522. package/dist/pipeline/handler-context-auth.js +7 -4
  523. package/dist/pipeline/handler-context-config.d.ts +2 -5
  524. package/dist/pipeline/handler-context-config.js +2 -2
  525. package/dist/pipeline/handler-context-db.d.ts +32 -7
  526. package/dist/pipeline/handler-context-db.js +26 -17
  527. package/dist/pipeline/handler-context-dispatch.d.ts +14 -6
  528. package/dist/pipeline/handler-context-dispatch.js +18 -5
  529. package/dist/pipeline/handler-context-events.d.ts +22 -38
  530. package/dist/pipeline/handler-context-events.js +42 -35
  531. package/dist/pipeline/handler-context-member-resolution.d.ts +2 -0
  532. package/dist/pipeline/handler-context-member-resolution.js +110 -0
  533. package/dist/pipeline/handler-context-notify.d.ts +3 -2
  534. package/dist/pipeline/handler-context-notify.js +1 -1
  535. package/dist/pipeline/handler-context-observability.d.ts +2 -4
  536. package/dist/pipeline/handler-context-observability.js +7 -5
  537. package/dist/pipeline/handler-context-phase-denials.d.ts +11 -0
  538. package/dist/pipeline/handler-context-phase-denials.js +98 -0
  539. package/dist/pipeline/handler-context-scope.d.ts +7 -10
  540. package/dist/pipeline/handler-context-scope.js +18 -20
  541. package/dist/pipeline/index.d.ts +9 -21
  542. package/dist/pipeline/index.js +5 -7
  543. package/dist/pipeline/irreversible-operation-gate.d.ts +1 -1
  544. package/dist/pipeline/irreversible-operation-gate.js +2 -2
  545. package/dist/pipeline/lifecycle-pipeline.d.ts +8 -7
  546. package/dist/pipeline/lifecycle-pipeline.js +9 -15
  547. package/dist/pipeline/member-read-only-transaction.js +11 -3
  548. package/dist/pipeline/member-reader.d.ts +1 -1
  549. package/dist/pipeline/member-reader.js +2 -2
  550. package/dist/pipeline/msp-rebuild.js +5 -3
  551. package/dist/pipeline/multi-stream-apply-context.js +3 -2
  552. package/dist/pipeline/notify-scope.d.ts +2 -1
  553. package/dist/pipeline/pre-handler-gates.d.ts +2 -1
  554. package/dist/pipeline/pre-transaction-reservations.d.ts +3 -3
  555. package/dist/pipeline/pre-transaction-reservations.js +9 -7
  556. package/dist/pipeline/projection-rebuild.js +12 -5
  557. package/dist/pipeline/projection-state.d.ts +0 -6
  558. package/dist/pipeline/projection-state.js +0 -5
  559. package/dist/pipeline/projections-runner.d.ts +2 -1
  560. package/dist/pipeline/projections-runner.js +10 -6
  561. package/dist/pipeline/system-hooks.d.ts +6 -2
  562. package/dist/pipeline/system-hooks.js +61 -10
  563. package/dist/pipeline/system-identity-switch.d.ts +4 -2
  564. package/dist/pipeline/system-identity-switch.js +51 -36
  565. package/dist/pipeline/typed-append-event.d.ts +2 -0
  566. package/dist/pipeline/typed-append-event.js +4 -0
  567. package/dist/pipeline/write-origin.js +2 -2
  568. package/dist/pipeline/write-result-masking.d.ts +1 -1
  569. package/dist/pipeline/write-result-masking.js +13 -10
  570. package/dist/random/index.d.ts +1 -2
  571. package/dist/random/index.js +1 -2
  572. package/dist/rate-limit/bucket.d.ts +2 -1
  573. package/dist/rate-limit/middleware.js +2 -1
  574. package/dist/redis/index.d.ts +3 -4
  575. package/dist/redis/index.js +2 -2
  576. package/dist/schema-cli/apply-command.js +5 -2
  577. package/dist/schema-cli/baseline-command.js +7 -2
  578. package/dist/schema-cli/generate-command.js +7 -9
  579. package/dist/schema-cli/shared.d.ts +4 -0
  580. package/dist/schema-cli/shared.js +21 -2
  581. package/dist/schema-cli/status-command.js +8 -2
  582. package/dist/schema-cli/validate-command.js +52 -4
  583. package/dist/schema-cli.d.ts +0 -1
  584. package/dist/search/configure-tenant-index.d.ts +1 -3
  585. package/dist/search/configure-tenant-index.js +0 -4
  586. package/dist/search/index.d.ts +1 -4
  587. package/dist/search/index.js +0 -2
  588. package/dist/search/meilisearch-adapter-internals.d.ts +8 -0
  589. package/dist/search/meilisearch-adapter-internals.js +9 -0
  590. package/dist/search/meilisearch-adapter.d.ts +1 -8
  591. package/dist/search/meilisearch-adapter.js +6 -7
  592. package/dist/search/meilisearch-peer.d.ts +2 -0
  593. package/dist/search/meilisearch-peer.js +5 -0
  594. package/dist/search/reindex-entity.js +107 -91
  595. package/dist/secrets/index.d.ts +3 -4
  596. package/dist/secrets/index.js +2 -3
  597. package/dist/seeding/index.d.ts +2 -2
  598. package/dist/seeding/index.js +1 -2
  599. package/dist/time/index.d.ts +2 -2
  600. package/dist/time/index.js +1 -1
  601. package/dist/time/tz-context.d.ts +0 -5
  602. package/dist/time/tz-context.js +0 -9
  603. package/dist/ui-types/index.d.ts +8 -11
  604. package/dist/ui-types/index.js +3 -3
  605. package/dist/upgrade-changelog.d.ts +3 -0
  606. package/dist/upgrade-changelog.js +18 -0
  607. package/dist/upgrade-cli-internals.d.ts +8 -0
  608. package/dist/upgrade-cli-internals.js +63 -0
  609. package/dist/upgrade-cli.d.ts +1 -18
  610. package/dist/upgrade-cli.js +29 -137
  611. package/dist/upgrade-marker-parse.d.ts +32 -0
  612. package/dist/upgrade-marker-parse.js +73 -0
  613. package/dist/utils/import-optional-peer.d.ts +6 -0
  614. package/dist/utils/import-optional-peer.js +19 -0
  615. package/dist/utils/index.d.ts +1 -4
  616. package/dist/utils/index.js +1 -4
  617. package/package.json +27 -20
  618. package/src/changes.json +451 -0
  619. package/dist/crypto/request-kms-cache.d.ts +0 -8
  620. package/dist/crypto/request-kms-cache.js +0 -21
  621. package/dist/engine/codemod/index.d.ts +0 -2
  622. package/dist/engine/codemod/index.js +0 -1
  623. package/dist/engine/codemod/pipeline-codemod.d.ts +0 -50
  624. package/dist/engine/codemod/pipeline-codemod.js +0 -536
  625. package/dist/engine/feature-ast/entity-field-types.d.ts +0 -13
  626. package/dist/engine/feature-ast/entity-field-types.js +0 -35
  627. package/dist/engine/feature-ast/extractors/ai-steps.d.ts +0 -6
  628. package/dist/engine/feature-ast/extractors/ai-steps.js +0 -254
  629. package/dist/engine/feature-ast/extractors/events.d.ts +0 -5
  630. package/dist/engine/feature-ast/extractors/events.js +0 -275
  631. package/dist/engine/feature-ast/extractors/handlers.d.ts +0 -24
  632. package/dist/engine/feature-ast/extractors/handlers.js +0 -358
  633. package/dist/engine/feature-ast/extractors/hooks.d.ts +0 -24
  634. package/dist/engine/feature-ast/extractors/hooks.js +0 -248
  635. package/dist/engine/feature-ast/extractors/index.d.ts +0 -14
  636. package/dist/engine/feature-ast/extractors/index.js +0 -13
  637. package/dist/engine/feature-ast/extractors/jobs-routes.d.ts +0 -7
  638. package/dist/engine/feature-ast/extractors/jobs-routes.js +0 -145
  639. package/dist/engine/feature-ast/extractors/projections-screens.d.ts +0 -10
  640. package/dist/engine/feature-ast/extractors/projections-screens.js +0 -195
  641. package/dist/engine/feature-ast/extractors/resolve-import.d.ts +0 -21
  642. package/dist/engine/feature-ast/extractors/resolve-import.js +0 -180
  643. package/dist/engine/feature-ast/extractors/round1.d.ts +0 -10
  644. package/dist/engine/feature-ast/extractors/round1.js +0 -81
  645. package/dist/engine/feature-ast/extractors/round2.d.ts +0 -7
  646. package/dist/engine/feature-ast/extractors/round2.js +0 -191
  647. package/dist/engine/feature-ast/extractors/round3.d.ts +0 -23
  648. package/dist/engine/feature-ast/extractors/round3.js +0 -292
  649. package/dist/engine/feature-ast/extractors/round5.d.ts +0 -9
  650. package/dist/engine/feature-ast/extractors/round5.js +0 -68
  651. package/dist/engine/feature-ast/extractors/round6.d.ts +0 -4
  652. package/dist/engine/feature-ast/extractors/round6.js +0 -17
  653. package/dist/engine/feature-ast/extractors/shared.d.ts +0 -94
  654. package/dist/engine/feature-ast/extractors/shared.js +0 -343
  655. package/dist/engine/feature-ast/index.d.ts +0 -16
  656. package/dist/engine/feature-ast/index.js +0 -10
  657. package/dist/engine/feature-ast/parse.d.ts +0 -31
  658. package/dist/engine/feature-ast/parse.js +0 -483
  659. package/dist/engine/feature-ast/patch.d.ts +0 -210
  660. package/dist/engine/feature-ast/patch.js +0 -610
  661. package/dist/engine/feature-ast/patcher.d.ts +0 -217
  662. package/dist/engine/feature-ast/patcher.js +0 -281
  663. package/dist/engine/feature-ast/pattern-change-schema.d.ts +0 -1476
  664. package/dist/engine/feature-ast/pattern-change-schema.js +0 -1226
  665. package/dist/engine/feature-ast/pattern-id-matchers.d.ts +0 -7
  666. package/dist/engine/feature-ast/pattern-id-matchers.js +0 -210
  667. package/dist/engine/feature-ast/patterns.d.ts +0 -318
  668. package/dist/engine/feature-ast/patterns.js +0 -106
  669. package/dist/engine/feature-ast/render.d.ts +0 -47
  670. package/dist/engine/feature-ast/render.js +0 -662
  671. package/dist/engine/feature-ast/source-location.d.ts +0 -17
  672. package/dist/engine/feature-ast/source-location.js +0 -27
  673. package/dist/engine/pattern-library/index.d.ts +0 -2
  674. package/dist/engine/pattern-library/index.js +0 -3
  675. package/dist/engine/pattern-library/library.d.ts +0 -14
  676. package/dist/engine/pattern-library/library.js +0 -93
  677. package/dist/engine/pattern-library/mixed-schemas.d.ts +0 -16
  678. package/dist/engine/pattern-library/mixed-schemas.js +0 -559
  679. package/dist/engine/pattern-library/opaque-schemas.d.ts +0 -7
  680. package/dist/engine/pattern-library/opaque-schemas.js +0 -115
  681. package/dist/engine/pattern-library/shared-fields.d.ts +0 -122
  682. package/dist/engine/pattern-library/shared-fields.js +0 -88
  683. package/dist/engine/pattern-library/static-schemas.d.ts +0 -20
  684. package/dist/engine/pattern-library/static-schemas.js +0 -478
  685. package/dist/engine/pattern-library/types.d.ts +0 -158
  686. package/dist/engine/pattern-library/types.js +0 -36
  687. package/dist/engine/provider-plugin-context.d.ts +0 -3
  688. package/dist/engine/provider-plugin-context.js +0 -28
  689. package/dist/engine/resolve-config-or-param.d.ts +0 -18
  690. package/dist/engine/resolve-config-or-param.js +0 -76
  691. package/src/scripts/codemod/README.md +0 -187
  692. package/src/scripts/codemod/codemod-support.ts +0 -334
  693. package/src/scripts/codemod/collect-source-files.ts +0 -48
  694. package/src/scripts/codemod/crypto-shredding-testing-move.ts +0 -119
  695. package/src/scripts/codemod/db-factory.ts +0 -810
  696. package/src/scripts/codemod/feature-factory.ts +0 -429
  697. package/src/scripts/codemod/feature-layout.ts +0 -424
  698. package/src/scripts/codemod/import-extensions.ts +0 -118
  699. package/src/scripts/codemod/migrate-cross-tenant.ts +0 -328
  700. package/src/scripts/codemod/migrate-db-raw.ts +0 -401
  701. package/src/scripts/codemod/migrate-open-to-all.ts +0 -235
  702. package/src/scripts/codemod/object-form.ts +0 -746
  703. package/src/scripts/codemod/package-merge.ts +0 -299
  704. package/src/scripts/codemod/pii-personal-migration.ts +0 -816
  705. package/src/scripts/codemod/remove-engine-payload-casts.ts +0 -318
  706. package/src/scripts/codemod/s3-imports.ts +0 -236
  707. package/src/scripts/codemod/tenant-db-options.ts +0 -454
  708. package/src/scripts/codemod/testing-injection.ts +0 -215
  709. package/src/scripts/codemod/testing-move-targets.ts +0 -161
  710. package/src/scripts/codemod/testing-move.ts +0 -542
  711. package/src/scripts/codemod/unprocessable-error-details-reason.ts +0 -411
@@ -0,0 +1,127 @@
1
+ // Pure renderer for Postgres row level security: EntityTableMeta → policy DDL.
2
+ // Every table with a `tenant_id` column gets two policies; tables without one are untouched.
3
+ import { SYSTEM_TENANT_ID } from "@cosmicdrift/kumiko-types/identifiers";
4
+ import { isOneOf, isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
5
+ import { pgTypeToSqlType } from "./dialect.js";
6
+ import { quoteIdent } from "./sql-identifier.js";
7
+ export const ROW_LEVEL_SECURITY_MODES = ["off", "on"];
8
+ export const DEFAULT_ROW_LEVEL_SECURITY_MODE = "on";
9
+ export const TENANT_ISOLATION_POLICY = "kumiko_tenant_isolation";
10
+ export const SYSTEM_TENANT_READ_POLICY = "kumiko_system_tenant_read";
11
+ export const TENANT_ID_SETTING = "kumiko.tenant_id";
12
+ export const SCOPE_SETTING = "kumiko.scope";
13
+ export const SYSTEM_SCOPE = "system";
14
+ const TENANT_COLUMN = "tenant_id";
15
+ export const POLICY_COMMANDS = ["ALL", "SELECT", "INSERT", "UPDATE", "DELETE"];
16
+ export const POLICY_KINDS = ["PERMISSIVE", "RESTRICTIVE"];
17
+ export function tenantRowLevelSecurityFor(meta) {
18
+ const tenantColumn = meta.columns.find((col) => col.name === TENANT_COLUMN);
19
+ if (tenantColumn === undefined)
20
+ return undefined;
21
+ const sqlType = pgTypeToSqlType(tenantColumn.pgType);
22
+ const column = quoteIdent(TENANT_COLUMN);
23
+ // NULLIF: after a transaction-local set_config, current_setting returns '' instead of NULL.
24
+ const sessionTenant = `NULLIF(current_setting('${TENANT_ID_SETTING}', true), '')`;
25
+ const isolation = `${column} = ${sessionTenant}::${sqlType} OR current_setting('${SCOPE_SETTING}', true) = '${SYSTEM_SCOPE}'`;
26
+ return {
27
+ policies: [
28
+ {
29
+ name: TENANT_ISOLATION_POLICY,
30
+ command: "ALL",
31
+ kind: "PERMISSIVE",
32
+ rolesSql: "PUBLIC",
33
+ using: isolation,
34
+ withCheck: isolation,
35
+ },
36
+ {
37
+ name: SYSTEM_TENANT_READ_POLICY,
38
+ command: "SELECT",
39
+ kind: "PERMISSIVE",
40
+ rolesSql: "PUBLIC",
41
+ using: `${column} = '${SYSTEM_TENANT_ID}'::${sqlType} AND ${sessionTenant} IS NOT NULL`,
42
+ },
43
+ ],
44
+ };
45
+ }
46
+ export function rowLevelSecurityByTable(metas) {
47
+ const byTable = {};
48
+ for (const meta of metas) {
49
+ const spec = tenantRowLevelSecurityFor(meta);
50
+ if (spec !== undefined)
51
+ byTable[meta.tableName] = spec;
52
+ }
53
+ return byTable;
54
+ }
55
+ export function renderCreatePolicy(tableSql, policy) {
56
+ const using = policy.using !== undefined ? ` USING (${policy.using})` : "";
57
+ const withCheck = policy.withCheck !== undefined ? ` WITH CHECK (${policy.withCheck})` : "";
58
+ return `CREATE POLICY ${quoteIdent(policy.name)} ON ${tableSql} AS ${policy.kind} FOR ${policy.command} TO ${policy.rolesSql}${using}${withCheck};`;
59
+ }
60
+ function renderDropPolicy(tableSql, policyName) {
61
+ return `DROP POLICY IF EXISTS ${quoteIdent(policyName)} ON ${tableSql};`;
62
+ }
63
+ export function renderRowLevelSecurityFlags(tableSql, flags) {
64
+ return [
65
+ `ALTER TABLE ${tableSql} ${flags.enabled ? "ENABLE" : "DISABLE"} ROW LEVEL SECURITY;`,
66
+ `ALTER TABLE ${tableSql} ${flags.forced ? "FORCE" : "NO FORCE"} ROW LEVEL SECURITY;`,
67
+ ];
68
+ }
69
+ export function renderEnableRowLevelSecurity(tableSql, next, previous) {
70
+ const nextNames = new Set(next.policies.map((policy) => policy.name));
71
+ const vanished = (previous?.policies ?? []).filter((policy) => !nextNames.has(policy.name));
72
+ return [
73
+ ...vanished.map((policy) => renderDropPolicy(tableSql, policy.name)),
74
+ ...next.policies.flatMap((policy) => [
75
+ renderDropPolicy(tableSql, policy.name),
76
+ renderCreatePolicy(tableSql, policy),
77
+ ]),
78
+ ...renderRowLevelSecurityFlags(tableSql, { enabled: true, forced: true }),
79
+ ];
80
+ }
81
+ export function renderDisableRowLevelSecurity(tableSql, previous) {
82
+ return [
83
+ ...previous.policies.map((policy) => renderDropPolicy(tableSql, policy.name)),
84
+ ...renderRowLevelSecurityFlags(tableSql, { enabled: false, forced: false }).reverse(),
85
+ ];
86
+ }
87
+ export function renderTableRowLevelSecurityDdl(meta) {
88
+ const spec = tenantRowLevelSecurityFor(meta);
89
+ if (spec === undefined)
90
+ return [];
91
+ return renderEnableRowLevelSecurity(quoteIdent(meta.tableName), spec);
92
+ }
93
+ function isSamePolicy(a, b) {
94
+ return (a.name === b.name &&
95
+ a.command === b.command &&
96
+ a.kind === b.kind &&
97
+ a.rolesSql === b.rolesSql &&
98
+ a.using === b.using &&
99
+ a.withCheck === b.withCheck);
100
+ }
101
+ export function isSameTableRowLevelSecurity(a, b) {
102
+ return (a.policies.length === b.policies.length &&
103
+ a.policies.every((policy, index) => {
104
+ const other = b.policies[index];
105
+ return other !== undefined && isSamePolicy(policy, other);
106
+ }));
107
+ }
108
+ function isOptionalString(value) {
109
+ return value === undefined || typeof value === "string";
110
+ }
111
+ function isRowLevelSecurityPolicy(value) {
112
+ return (isPlainObject(value) &&
113
+ typeof value["name"] === "string" &&
114
+ typeof value["rolesSql"] === "string" &&
115
+ isOneOf(POLICY_COMMANDS, value["command"]) &&
116
+ isOneOf(POLICY_KINDS, value["kind"]) &&
117
+ isOptionalString(value["using"]) &&
118
+ isOptionalString(value["withCheck"]));
119
+ }
120
+ function isTableRowLevelSecurity(value) {
121
+ return (isPlainObject(value) &&
122
+ Array.isArray(value["policies"]) &&
123
+ value["policies"].every(isRowLevelSecurityPolicy));
124
+ }
125
+ export function isTableRowLevelSecurityRecord(value) {
126
+ return isPlainObject(value) && Object.values(value).every(isTableRowLevelSecurity);
127
+ }
@@ -1,13 +1,15 @@
1
1
  import type { Snapshot } from "./migrate-generator.ts";
2
+ import { type ReplayedRowLevelSecurity } from "./replay-rls.ts";
2
3
  export type ReplayedTable = {
3
4
  readonly columns: ReadonlySet<string>;
4
5
  readonly columnsUnknown?: boolean;
6
+ readonly rowLevelSecurity?: ReplayedRowLevelSecurity;
5
7
  };
6
8
  export type ReplayedSchema = ReadonlyMap<string, ReplayedTable>;
7
9
  export declare function replayMigrationsDir(migrationsDir: string): ReplayedSchema;
8
10
  export type ReplayMismatch = {
9
11
  readonly tableName: string;
10
- readonly kind: "missing-table" | "unexpected-table" | "column-drift";
12
+ readonly kind: "missing-table" | "unexpected-table" | "column-drift" | "row-level-security-drift";
11
13
  readonly detail: string;
12
14
  };
13
15
  export declare function diffReplayAgainstSnapshot(replayed: ReplayedSchema, snapshot: Snapshot): readonly ReplayMismatch[];
@@ -9,6 +9,7 @@
9
9
  // either. Reuses `loadMigrationsFromDir`'s statement-splitting so the replay
10
10
  // sees exactly what the real runner would execute.
11
11
  import { loadMigrationsFromDir } from "./migrate-runner.js";
12
+ import { applyRowLevelSecurityStatement, IDENT, replayedOnlyRowLevelSecurityDrift, rowLevelSecurityDrift, TABLE_REF, } from "./replay-rls.js";
12
13
  // Migration files comment out destructive ops (DROP TABLE/COLUMN) as
13
14
  // `-- DESTRUCTIVE: <stmt>; -- uncomment + ensure backup` so the real
14
15
  // migrate-runner never executes them unattended. For replay purposes the
@@ -48,10 +49,6 @@ function splitTopLevel(body) {
48
49
  parts.push(current);
49
50
  return parts;
50
51
  }
51
- // Identifiers in hand-written migrations aren't always quoted (the generator
52
- // always quotes, but the header explicitly invites hand-editing) — optional
53
- // quotes so `CREATE TABLE foo (...)` parses the same as `CREATE TABLE "foo" (...)`.
54
- const IDENT = `"?([^"\\s(;,.]+)"?`;
55
52
  function parseColumnNames(body) {
56
53
  const columns = new Set();
57
54
  for (const part of splitTopLevel(body)) {
@@ -197,7 +194,7 @@ function applyStatement(schema, statement, context) {
197
194
  // instead of matching only the first clause, in statement order so an
198
195
  // add-then-drop of the same column (unusual, but not impossible) resolves
199
196
  // correctly.
200
- const alterTable = statement.match(new RegExp(`^ALTER TABLE\\s+${IDENT}\\s+([\\s\\S]*?);?\\s*$`, "i"));
197
+ const alterTable = statement.match(new RegExp(`^ALTER TABLE\\s+(?:IF EXISTS\\s+)?(?:ONLY\\s+)?${TABLE_REF}\\s+([\\s\\S]*?);?\\s*$`, "i"));
201
198
  const alterTableName = alterTable?.[1];
202
199
  const alterBody = alterTable?.[2];
203
200
  if (alterTableName !== undefined && alterBody !== undefined) {
@@ -276,10 +273,29 @@ export function replayMigrationsDir(migrationsDir) {
276
273
  for (const migration of migrations) {
277
274
  for (const statement of migration.statements) {
278
275
  applyStatement(schema, statement, { file: migration.id });
276
+ applyRowLevelSecurityStatement(schema, statement, { file: migration.id });
279
277
  }
280
278
  }
281
279
  return schema;
282
280
  }
281
+ function rowLevelSecurityMismatches(replayed, snapshot) {
282
+ const mismatches = [];
283
+ const specs = snapshot.rowLevelSecurity ?? {};
284
+ for (const { tableName } of snapshot.tables) {
285
+ const table = replayed.get(tableName);
286
+ // skip: a missing table is already reported as missing-table
287
+ if (!table)
288
+ continue;
289
+ const spec = Object.hasOwn(specs, tableName) ? specs[tableName] : undefined;
290
+ const detail = spec === undefined
291
+ ? replayedOnlyRowLevelSecurityDrift(table.rowLevelSecurity)
292
+ : rowLevelSecurityDrift(table.rowLevelSecurity, tableName, spec);
293
+ if (detail !== undefined) {
294
+ mismatches.push({ tableName, kind: "row-level-security-drift", detail });
295
+ }
296
+ }
297
+ return mismatches;
298
+ }
283
299
  // Compares what the migration files actually produce (`replayed`) against
284
300
  // what `.snapshot.json` claims (`snapshot`) — the check that would have
285
301
  // caught kumiko-studio's 0016 misgeneration (snapshot correct, SQL wrong).
@@ -314,6 +330,7 @@ export function diffReplayAgainstSnapshot(replayed, snapshot) {
314
330
  });
315
331
  }
316
332
  }
333
+ mismatches.push(...rowLevelSecurityMismatches(replayed, snapshot));
317
334
  for (const tableName of replayed.keys()) {
318
335
  if (!snapshotTableNames.has(tableName)) {
319
336
  mismatches.push({
@@ -0,0 +1,25 @@
1
+ import { type TableRowLevelSecurity } from "./render-rls-ddl.ts";
2
+ export type ReplayedPolicies = ReadonlyMap<string, string | undefined>;
3
+ export type ReplayedRowLevelSecurity = {
4
+ readonly enabled: boolean;
5
+ readonly forced: boolean;
6
+ readonly policies: ReplayedPolicies;
7
+ };
8
+ export type MutableReplayedRowLevelSecurity = {
9
+ enabled: boolean;
10
+ forced: boolean;
11
+ policies: Map<string, string | undefined>;
12
+ };
13
+ type TableWithRowLevelSecurity = {
14
+ rowLevelSecurity?: MutableReplayedRowLevelSecurity;
15
+ };
16
+ export declare const IDENT = "\"?([^\"\\s(;,.]+)\"?";
17
+ export declare const TABLE_REF = "(?:\"?public\"?\\.)?\"?([^\"\\s(;,.]+)\"?";
18
+ type StatementContext = {
19
+ readonly file: string;
20
+ };
21
+ type ReplayTables = ReadonlyMap<string, TableWithRowLevelSecurity>;
22
+ export declare function applyRowLevelSecurityStatement(tables: ReplayTables, statement: string, context: StatementContext): void;
23
+ export declare function rowLevelSecurityDrift(replayed: ReplayedRowLevelSecurity | undefined, tableName: string, expected: TableRowLevelSecurity): string | undefined;
24
+ export declare function replayedOnlyRowLevelSecurityDrift(replayed: ReplayedRowLevelSecurity | undefined): string | undefined;
25
+ export {};
@@ -0,0 +1,156 @@
1
+ // Row level security part of the migration replay: tracks ENABLE/FORCE flags and
2
+ // policy definitions per table so they can be compared against the snapshot.
3
+ import { renderCreatePolicy } from "./render-rls-ddl.js";
4
+ import { quoteIdent } from "./sql-identifier.js";
5
+ // Identifiers in hand-written migrations aren't always quoted (the generator
6
+ // always quotes, but the header explicitly invites hand-editing) — optional
7
+ // quotes so `CREATE TABLE foo (...)` parses the same as `CREATE TABLE "foo" (...)`.
8
+ export const IDENT = `"?([^"\\s(;,.]+)"?`;
9
+ export const TABLE_REF = `(?:"?public"?\\.)?${IDENT}`;
10
+ const ALTER_TABLE_RE = new RegExp(`^ALTER\\s+TABLE\\s+(?:IF\\s+EXISTS\\s+)?(?:ONLY\\s+)?${TABLE_REF}\\s+([\\s\\S]*?);?\\s*$`, "i");
11
+ const FLAG_CLAUSE_RE = /\b(ENABLE|DISABLE|NO\s+FORCE|FORCE)\s+ROW\s+LEVEL\s+SECURITY\b/gi;
12
+ const CREATE_POLICY_RE = new RegExp(`^CREATE\\s+POLICY\\s+${IDENT}\\s+ON\\s+${TABLE_REF}(?=[\\s;]|$)([\\s\\S]*)$`, "i");
13
+ const DROP_POLICY_RE = new RegExp(`^DROP\\s+POLICY\\s+(IF\\s+EXISTS\\s+)?${IDENT}\\s+ON\\s+${TABLE_REF}(?=[\\s;]|$)`, "i");
14
+ const ALTER_POLICY_RE = new RegExp(`^ALTER\\s+POLICY\\s+${IDENT}\\s+ON\\s+${TABLE_REF}(?=[\\s;]|$)([\\s\\S]*)$`, "i");
15
+ const RENAME_POLICY_RE = new RegExp(`^\\s*RENAME\\s+TO\\s+${IDENT}\\s*;?\\s*$`, "i");
16
+ const POLICY_OR_RLS_RE = /\bPOLICY\b|ROW\s+LEVEL\s+SECURITY/i;
17
+ const ANY_POLICY_STATEMENT_RE = /^(CREATE|ALTER|DROP)\s+POLICY\b/i;
18
+ function stateOf(table) {
19
+ table.rowLevelSecurity ??= {
20
+ enabled: false,
21
+ forced: false,
22
+ policies: new Map(),
23
+ };
24
+ return table.rowLevelSecurity;
25
+ }
26
+ function applyFlagClauses(table, alterBody) {
27
+ for (const [, clause] of alterBody.matchAll(FLAG_CLAUSE_RE)) {
28
+ const state = stateOf(table);
29
+ switch (clause?.toUpperCase().replace(/\s+/g, " ")) {
30
+ case "ENABLE":
31
+ state.enabled = true;
32
+ break;
33
+ case "DISABLE":
34
+ state.enabled = false;
35
+ break;
36
+ case "FORCE":
37
+ state.forced = true;
38
+ break;
39
+ case "NO FORCE":
40
+ state.forced = false;
41
+ break;
42
+ }
43
+ }
44
+ }
45
+ function normalizePolicyDefinition(text) {
46
+ return text.replace(/\s+/g, " ").replace(/;\s*$/, "").trim();
47
+ }
48
+ function applyAlterPolicy(table, policyName, alterBody) {
49
+ const { policies } = stateOf(table);
50
+ const newName = alterBody.match(RENAME_POLICY_RE)?.[1];
51
+ if (newName === undefined) {
52
+ if (policies.has(policyName))
53
+ policies.set(policyName, undefined);
54
+ // skip: body is not a rename, the altered-flag above is all that is tracked
55
+ return;
56
+ }
57
+ // skip: policy not tracked, nothing to rename
58
+ if (!policies.has(policyName))
59
+ return;
60
+ policies.set(newName, policies.get(policyName));
61
+ policies.delete(policyName);
62
+ }
63
+ function failUnparsedPolicy(statement, file) {
64
+ const prefix = statement.slice(0, 200).replace(/\s+/g, " ").trim();
65
+ throw new Error(`replayMigrationsDir: unparsed policy statement in ${file} — expected CREATE POLICY <name> ON <table>, ` +
66
+ `DROP POLICY [IF EXISTS] <name> ON <table> or ALTER POLICY <name> ON <table>. Statement: ${prefix}${statement.length > 200 ? "…" : ""}`);
67
+ }
68
+ function tryApplyAlterTable(tables, statement) {
69
+ const alter = statement.match(ALTER_TABLE_RE);
70
+ if (alter?.[1] === undefined || alter[2] === undefined)
71
+ return false;
72
+ const table = tables.get(alter[1]);
73
+ if (table)
74
+ applyFlagClauses(table, alter[2]);
75
+ return true;
76
+ }
77
+ function tryApplyCreatePolicy(tables, statement) {
78
+ const created = statement.match(CREATE_POLICY_RE);
79
+ if (created?.[1] === undefined || created[2] === undefined)
80
+ return false;
81
+ const table = tables.get(created[2]);
82
+ if (table) {
83
+ stateOf(table).policies.set(created[1], normalizePolicyDefinition(created[3] ?? ""));
84
+ }
85
+ return true;
86
+ }
87
+ function tryApplyDropPolicy(tables, statement, context) {
88
+ const dropped = statement.match(DROP_POLICY_RE);
89
+ if (dropped?.[2] === undefined || dropped[3] === undefined)
90
+ return false;
91
+ const table = tables.get(dropped[3]);
92
+ if (!table)
93
+ return true;
94
+ const removed = stateOf(table).policies.delete(dropped[2]);
95
+ if (!removed && dropped[1] === undefined) {
96
+ throw new Error(`replayMigrationsDir: ${context.file} drops policy "${dropped[2]}" on "${dropped[3]}" which no earlier migration created`);
97
+ }
98
+ return true;
99
+ }
100
+ function tryApplyAlterPolicy(tables, statement) {
101
+ const altered = statement.match(ALTER_POLICY_RE);
102
+ if (altered?.[1] === undefined || altered[2] === undefined || altered[3] === undefined) {
103
+ return false;
104
+ }
105
+ const table = tables.get(altered[2]);
106
+ if (table)
107
+ applyAlterPolicy(table, altered[1], altered[3]);
108
+ return true;
109
+ }
110
+ export function applyRowLevelSecurityStatement(tables, statement, context) {
111
+ if (/^DO\b/i.test(statement) && POLICY_OR_RLS_RE.test(statement)) {
112
+ throw new Error(`replayMigrationsDir: ${context.file} changes policies or row level security inside a DO block, which the replay cannot evaluate — write the statements at top level`);
113
+ }
114
+ const handled = tryApplyAlterTable(tables, statement) ||
115
+ tryApplyCreatePolicy(tables, statement) ||
116
+ tryApplyDropPolicy(tables, statement, context) ||
117
+ tryApplyAlterPolicy(tables, statement);
118
+ if (!handled && ANY_POLICY_STATEMENT_RE.test(statement)) {
119
+ failUnparsedPolicy(statement, context.file);
120
+ }
121
+ }
122
+ function expectedPolicyDefinition(tableName, policy) {
123
+ const rendered = renderCreatePolicy(quoteIdent(tableName), policy);
124
+ const definition = rendered.match(CREATE_POLICY_RE)?.[3];
125
+ if (definition === undefined) {
126
+ throw new Error(`rendered policy "${policy.name}" is not a CREATE POLICY statement`);
127
+ }
128
+ return normalizePolicyDefinition(definition);
129
+ }
130
+ export function rowLevelSecurityDrift(replayed, tableName, expected) {
131
+ const parts = [];
132
+ if (replayed?.enabled !== true)
133
+ parts.push("ROW LEVEL SECURITY is not enabled");
134
+ if (replayed?.forced !== true)
135
+ parts.push("ROW LEVEL SECURITY is not forced");
136
+ const actual = replayed?.policies ?? new Map();
137
+ const expectedNames = new Set(expected.policies.map((policy) => policy.name));
138
+ for (const policy of expected.policies) {
139
+ if (!actual.has(policy.name)) {
140
+ parts.push(`missing policy: ${policy.name}`);
141
+ }
142
+ else if (actual.get(policy.name) !== expectedPolicyDefinition(tableName, policy)) {
143
+ parts.push(`policy ${policy.name} deviates from the generated definition (hand-edited or altered)`);
144
+ }
145
+ }
146
+ const unexpected = [...actual.keys()].filter((name) => !expectedNames.has(name));
147
+ if (unexpected.length > 0)
148
+ parts.push(`unexpected policies: ${unexpected.join(", ")}`);
149
+ return parts.length > 0 ? parts.join("; ") : undefined;
150
+ }
151
+ export function replayedOnlyRowLevelSecurityDrift(replayed) {
152
+ const hasRowLevelSecurity = replayed !== undefined && (replayed.enabled || replayed.forced || replayed.policies.size > 0);
153
+ return hasRowLevelSecurity
154
+ ? "migrations enable row level security or create policies but .snapshot.json has no row level security spec for this table"
155
+ : undefined;
156
+ }
@@ -0,0 +1,5 @@
1
+ import { type KnownTables } from "./known-table-names.ts";
2
+ import type { AnyDb } from "./query.ts";
3
+ import type { RowLevelSecurityMode } from "./render-rls-ddl.ts";
4
+ export declare function assertRowLevelSecurityTableState(db: AnyDb, mode: RowLevelSecurityMode, knownTables: KnownTables): Promise<void>;
5
+ export declare function assertRowLevelSecurityBootState(db: AnyDb, mode: RowLevelSecurityMode, knownTables: KnownTables): Promise<void>;
@@ -0,0 +1,85 @@
1
+ import { InternalError } from "../errors/index.js";
2
+ import { isLiveFrameworkTable } from "./known-table-names.js";
3
+ import { readConnectedRoleAttributes, readTablesWithRowLevelSecurityEnabled, readTenantTablesRowLevelSecurity, } from "./queries/rls-boot-catalog.js";
4
+ function missingPartsOf(table) {
5
+ return [
6
+ ...(table.enabled ? [] : ["ENABLE ROW LEVEL SECURITY"]),
7
+ ...(table.forced ? [] : ["FORCE ROW LEVEL SECURITY"]),
8
+ ...(table.hasIsolationPolicy ? [] : ["policy kumiko_tenant_isolation"]),
9
+ ...(table.hasSystemReadPolicy ? [] : ["policy kumiko_system_tenant_read"]),
10
+ ];
11
+ }
12
+ async function assertEnforcingRole(db) {
13
+ const role = await readConnectedRoleAttributes(db);
14
+ if (role === undefined) {
15
+ throw new InternalError({ message: "row-level security boot check: current role not found." });
16
+ }
17
+ const bypassing = [
18
+ ...(role.superuser ? ["SUPERUSER"] : []),
19
+ ...(role.bypassRowLevelSecurity ? ["BYPASSRLS"] : []),
20
+ ];
21
+ // skip: every role enforces row-level security
22
+ if (bypassing.length === 0)
23
+ return;
24
+ throw new InternalError({
25
+ message: `rowLevelSecurity is "on" but the database role "${role.roleName}" has ${bypassing.join(" and ")}, which makes Postgres skip every policy. Connect as a role with NOSUPERUSER NOBYPASSRLS.`,
26
+ });
27
+ }
28
+ function listingOf(entries) {
29
+ return entries.map((entry) => `${entry.table} (${entry.missing.join(", ")})`).join("; ");
30
+ }
31
+ async function assertAllTenantTablesProtected(db, knownTables) {
32
+ const incomplete = (await readTenantTablesRowLevelSecurity(db))
33
+ .map((table) => ({ table: table.tableName, missing: missingPartsOf(table) }))
34
+ .filter((entry) => entry.missing.length > 0);
35
+ // skip: every tenant table is protected
36
+ if (incomplete.length === 0)
37
+ return;
38
+ const frameworkTables = incomplete.filter((entry) => isLiveFrameworkTable(entry.table));
39
+ const known = incomplete.filter((entry) => !isLiveFrameworkTable(entry.table) && knownTables.has(entry.table));
40
+ const orphaned = incomplete.filter((entry) => !knownTables.has(entry.table));
41
+ const sections = [
42
+ ...(frameworkTables.length > 0
43
+ ? [
44
+ `framework tables without it: ${listingOf(frameworkTables)}. Run \`kumiko schema apply\`: it adds the missing policies to the framework tables (\`kumiko schema generate\` reports no changes for them).`,
45
+ ]
46
+ : []),
47
+ ...(known.length > 0
48
+ ? [
49
+ `tables of this app without it: ${listingOf(known)}. Run \`kumiko schema generate\` and apply the migration.`,
50
+ ]
51
+ : []),
52
+ ...(orphaned.length > 0
53
+ ? [
54
+ `tables no feature declares anymore: ${listingOf(orphaned)}. No feature declares them: add a migration with DROP TABLE (enable the commented \`-- DESTRUCTIVE\` DROP that \`kumiko schema generate\` emitted; see \`kumiko schema status\`).`,
55
+ ]
56
+ : []),
57
+ ];
58
+ throw new InternalError({
59
+ message: `rowLevelSecurity is "on" but tenant tables lack row-level security. ${sections.join(" ")}`,
60
+ });
61
+ }
62
+ async function assertNoLiveRowLevelSecurity(db) {
63
+ const tables = await readTablesWithRowLevelSecurityEnabled(db);
64
+ // skip: no live row-level security to disable
65
+ if (tables.length === 0)
66
+ return;
67
+ throw new InternalError({
68
+ message: `rowLevelSecurity is "off" but row-level security is still enabled on: ${tables.join(", ")}. Without a tenant scope every statement would see zero rows. Run \`kumiko schema generate\` with rowLevelSecurity off to produce the DISABLE ROW LEVEL SECURITY migration and apply it.`,
69
+ });
70
+ }
71
+ // Table state only, no role check: the role is a runtime property of the boot connection, so tools
72
+ // that connect with another role (CI, `schema validate`) use this one.
73
+ export async function assertRowLevelSecurityTableState(db, mode, knownTables) {
74
+ if (mode === "off") {
75
+ await assertNoLiveRowLevelSecurity(db);
76
+ // skip: off-mode check done
77
+ return;
78
+ }
79
+ await assertAllTenantTablesProtected(db, knownTables);
80
+ }
81
+ export async function assertRowLevelSecurityBootState(db, mode, knownTables) {
82
+ if (mode === "on")
83
+ await assertEnforcingRole(db);
84
+ await assertRowLevelSecurityTableState(db, mode, knownTables);
85
+ }
@@ -0,0 +1,3 @@
1
+ import type { RowLevelSecurityMode } from "./render-rls-ddl.ts";
2
+ export declare function rowLevelSecurityModeOf(db: unknown): RowLevelSecurityMode;
3
+ export declare function enforceRowLevelSecurity<T extends object>(pool: T): T;