@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
@@ -2,6 +2,7 @@ import { escapeHatchFor } from "@cosmicdrift/kumiko-types/handlers";
2
2
  import { withSystemDbUnsafeRawGrant, withUnsafeRawGrant } from "../db/tenant-db.js";
3
3
  import { SYSTEM_ROLE, SYSTEM_USER_ID } from "../engine/system-user.js";
4
4
  import { AccessDeniedError, FrameworkReasons, InternalError } from "../errors/index.js";
5
+ import { attachOutsideTransaction } from "./attach-outside-transaction.js";
5
6
  export function isSystemIdentity(user) {
6
7
  return user.id === SYSTEM_USER_ID || user.roles.includes(SYSTEM_ROLE);
7
8
  }
@@ -49,14 +50,14 @@ export function identitySwitchDenied(callerLabel, asUser) {
49
50
  }
50
51
  export function unsafeAllTenantsDenied(callerLabel) {
51
52
  return new AccessDeniedError({
52
- message: `${callerLabel} may not call ctx.queryProjection(..., { unsafeAllTenants: true }) — declare ` +
53
+ message: `${callerLabel} may not call ctx.dispatch.queryProjection(..., { unsafeAllTenants: true }) — declare ` +
53
54
  "r.systemScope() or escapeHatch: { reason } on it",
54
55
  details: { reason: FrameworkReasons.unsafeAllTenantsDenied },
55
56
  });
56
57
  }
57
58
  // Reverse-lookup so withHookEscapeHatchGrant can re-gate the SAME ungated pair (and caller) under a narrower grant.
58
59
  const sourceByGated = new WeakMap();
59
- // Same idea, for ctx.queryAsMember — a single function rather than a pair.
60
+ // Same idea, for ctx.dispatch.queryAsMember — a single function rather than a pair.
60
61
  const ungatedMemberReaderByGated = new WeakMap();
61
62
  function reportGrantedSwitch(caller, asUser, hasGrant, audit) {
62
63
  // skip: no audit wired, switch wasn't grant-gated, or grant carries no reason to report
@@ -88,7 +89,7 @@ export function createGatedIdentitySwitch(callerLabel, caller, hasGrant, ungated
88
89
  sourceByGated.set(writeAs, source);
89
90
  return gated;
90
91
  }
91
- // ctx.queryAsMember's gate: the caller never names the target identity up
92
+ // ctx.dispatch.queryAsMember's gate: the caller never names the target identity up
92
93
  // front (it's resolved internally), so this is a flat allow/deny.
93
94
  export function createGatedMemberReader(callerLabel, allowSystemIdentity, ungated, audit) {
94
95
  const gated = async (userId, qn, payload) => {
@@ -102,9 +103,9 @@ export function createGatedMemberReader(callerLabel, allowSystemIdentity, ungate
102
103
  ungatedMemberReaderByGated.set(gated, { ungated, audit });
103
104
  return gated;
104
105
  }
105
- // Same idea, for ctx.queryProjection — a single function rather than a pair.
106
+ // Same idea, for ctx.dispatch.queryProjection — a single function rather than a pair.
106
107
  const ungatedProjectionReaderByGated = new WeakMap();
107
- // ctx.queryProjection's gate: only { unsafeAllTenants: true } on a projection with a
108
+ // ctx.dispatch.queryProjection's gate: only { unsafeAllTenants: true } on a projection with a
108
109
  // tenant column is grant-checked — a plain call always passes through, tenant-scoped
109
110
  // by the projection's own table, and the flag is a no-op on a tenant-less one.
110
111
  export function createGatedProjectionReader(callerLabel, hasGrant, ungated, audit, projectionHasTenantColumn = () => true) {
@@ -121,19 +122,20 @@ export function createGatedProjectionReader(callerLabel, hasGrant, ungated, audi
121
122
  ungatedProjectionReaderByGated.set(gated, { ungated, report: audit?.report });
122
123
  return gated;
123
124
  }
124
- function readIdentitySwitchFn(context, key) {
125
- if (!(key in context))
125
+ // Reads own keys only — never touch a property of a resolved value, which may be a Proxy that throws on any get.
126
+ function readMember(namespace, key) {
127
+ if (namespace === undefined || !(key in namespace))
126
128
  return undefined;
127
- const value = Reflect.get(context, key);
128
- return typeof value === "function" ? value : undefined; // @cast-boundary engine-bridge — checked via typeof above
129
+ return Reflect.get(namespace, key);
129
130
  }
130
- // context's own keys only — never touch a property of the resolved value, which may be a Proxy that throws on any get.
131
- function readDbLikeValue(context, key) {
132
- if (!(key in context))
133
- return undefined;
134
- const value = Reflect.get(context, key);
131
+ function readObjectMember(namespace, key) {
132
+ const value = readMember(namespace, key);
135
133
  return typeof value === "object" && value !== null ? value : undefined;
136
134
  }
135
+ function readFunctionMember(namespace, key) {
136
+ const value = readMember(namespace, key);
137
+ return typeof value === "function" ? value : undefined; // @cast-boundary engine-bridge — checked via typeof above
138
+ }
137
139
  function unavailableIdentitySwitchFn(callerLabel, kind) {
138
140
  return async () => {
139
141
  throw new InternalError({
@@ -179,8 +181,8 @@ function gatedIdentitySwitchFields(callerLabel, escapeHatch, ctxQueryAs, ctxWrit
179
181
  ...(ctxWriteAs && { writeAs: gated.writeAs }),
180
182
  };
181
183
  }
182
- // Unlike ctx.resolveActiveMembership (deny-only), a hook's own escapeHatch
183
- // can grant queryAsMember even when the enclosing handler has none.
184
+ // Unlike ctx.auth.resolveActiveMembership (deny-only), a hook's own escapeHatch
185
+ // can grant dispatch.queryAsMember even when the enclosing handler has none.
184
186
  function gatedMemberReaderField(callerLabel, escapeHatch, ctxQueryAsMember) {
185
187
  if (!ctxQueryAsMember)
186
188
  return {};
@@ -193,7 +195,7 @@ function gatedMemberReaderField(callerLabel, escapeHatch, ctxQueryAsMember) {
193
195
  queryAsMember: createGatedMemberReader(callerLabel, escapeHatch !== undefined, ungated, audit),
194
196
  };
195
197
  }
196
- // Re-gates ctx.queryProjection under the hook's own escapeHatch, same
198
+ // Re-gates ctx.dispatch.queryProjection under the hook's own escapeHatch, same
197
199
  // re-gating rule as the other fields below — see withHookEscapeHatchGrant.
198
200
  function gatedProjectionReaderField(callerLabel, escapeHatch, ctxQueryProjection) {
199
201
  if (!ctxQueryProjection)
@@ -205,15 +207,26 @@ function gatedProjectionReaderField(callerLabel, escapeHatch, ctxQueryProjection
205
207
  queryProjection: createGatedProjectionReader(callerLabel, escapeHatch !== undefined, ungated, audit),
206
208
  };
207
209
  }
210
+ // A rebound db is a new object, so the outsideTransaction property has to be carried over; an input
211
+ // withUnsafeRawGrant passes through unchanged keeps its own.
212
+ function regatedDb(ctxDb, ctxDbOutsideTransaction, rawHatch) {
213
+ const gatedDb = withUnsafeRawGrant(ctxDb, rawHatch);
214
+ if (gatedDb !== ctxDb && ctxDbOutsideTransaction) {
215
+ attachOutsideTransaction(gatedDb, withUnsafeRawGrant(ctxDbOutsideTransaction, rawHatch));
216
+ }
217
+ return gatedDb;
218
+ }
208
219
  export function withHookEscapeHatchGrant(context, callerLabel, escapeHatch) {
209
- const ctxQueryAs = readIdentitySwitchFn(context, "queryAs");
210
- const ctxWriteAs = readIdentitySwitchFn(context, "writeAs");
211
- const ctxResolveActiveMembership = readIdentitySwitchFn(context, "resolveActiveMembership");
212
- const ctxQueryAsMember = readIdentitySwitchFn(context, "queryAsMember");
213
- const ctxQueryProjection = readIdentitySwitchFn(context, "queryProjection");
214
- const ctxDb = readDbLikeValue(context, "db");
215
- const ctxDbOutsideTransaction = readDbLikeValue(context, "dbOutsideTransaction");
216
- const ctxSystemDb = readDbLikeValue(context, "systemDb");
220
+ const dispatch = readObjectMember(context, "dispatch");
221
+ const auth = readObjectMember(context, "auth");
222
+ const ctxQueryAs = readFunctionMember(dispatch, "queryAs");
223
+ const ctxWriteAs = readFunctionMember(dispatch, "writeAs");
224
+ const ctxResolveActiveMembership = readFunctionMember(auth, "resolveActiveMembership");
225
+ const ctxQueryAsMember = readFunctionMember(dispatch, "queryAsMember");
226
+ const ctxQueryProjection = readFunctionMember(dispatch, "queryProjection");
227
+ const ctxDb = readObjectMember(context, "db");
228
+ const ctxDbOutsideTransaction = readObjectMember(ctxDb, "outsideTransaction");
229
+ const ctxSystemDb = readObjectMember(context, "systemDb");
217
230
  const identityHatch = escapeHatchFor(escapeHatch, "systemIdentity");
218
231
  const rawHatch = escapeHatchFor(escapeHatch, "unsafeRaw");
219
232
  if (!ctxQueryAs &&
@@ -222,29 +235,31 @@ export function withHookEscapeHatchGrant(context, callerLabel, escapeHatch) {
222
235
  !ctxQueryAsMember &&
223
236
  !ctxQueryProjection &&
224
237
  !ctxDb &&
225
- !ctxDbOutsideTransaction &&
226
238
  !ctxSystemDb) {
227
239
  return context;
228
240
  }
229
241
  return {
230
242
  ...context,
231
- ...gatedIdentitySwitchFields(callerLabel, identityHatch, ctxQueryAs, ctxWriteAs),
232
- ...(ctxResolveActiveMembership &&
233
- identityHatch === undefined && {
234
- resolveActiveMembership: deniedResolveActiveMembership(callerLabel),
243
+ ...(dispatch && {
244
+ dispatch: {
245
+ ...dispatch,
246
+ ...gatedIdentitySwitchFields(callerLabel, identityHatch, ctxQueryAs, ctxWriteAs),
247
+ ...gatedMemberReaderField(callerLabel, identityHatch, ctxQueryAsMember),
248
+ ...gatedProjectionReaderField(callerLabel, identityHatch, ctxQueryProjection),
249
+ },
235
250
  }),
236
- ...gatedMemberReaderField(callerLabel, identityHatch, ctxQueryAsMember),
237
- ...gatedProjectionReaderField(callerLabel, identityHatch, ctxQueryProjection),
238
- ...(ctxDb && { db: withUnsafeRawGrant(ctxDb, rawHatch) }),
239
- ...(ctxDbOutsideTransaction && {
240
- dbOutsideTransaction: withUnsafeRawGrant(ctxDbOutsideTransaction, rawHatch),
251
+ ...(auth &&
252
+ ctxResolveActiveMembership &&
253
+ identityHatch === undefined && {
254
+ auth: { ...auth, resolveActiveMembership: deniedResolveActiveMembership(callerLabel) },
241
255
  }),
256
+ ...(ctxDb && { db: regatedDb(ctxDb, ctxDbOutsideTransaction, rawHatch) }),
242
257
  ...(ctxSystemDb && {
243
258
  systemDb: withSystemDbUnsafeRawGrant(ctxSystemDb, rawHatch, callerLabel),
244
259
  }),
245
260
  };
246
261
  }
247
- // Re-gates a hook's own ctx.queryAs/ctx.writeAs/ctx.queryProjection/ctx.db/ctx.dbOutsideTransaction/ctx.systemDb instead of inheriting the handler's grant.
262
+ // Re-gates a hook's own ctx.dispatch.*/ctx.auth.resolveActiveMembership/ctx.db (incl. db.outsideTransaction)/ctx.systemDb instead of inheriting the handler's grant.
248
263
  export function bindHookEscapeHatchGrant(fn, label, escapeHatch) {
249
264
  return ((payload, context) => fn(payload, withHookEscapeHatchGrant(context, label, escapeHatch))); // @cast-boundary engine-bridge — LifecycleHookFn union, same (payload, context) shape at runtime
250
265
  }
@@ -0,0 +1,2 @@
1
+ import type { AppendEventFn, UnsafeAppendEventFn } from "@cosmicdrift/kumiko-types/handlers";
2
+ export declare function asTypedAppendEventFn(append: UnsafeAppendEventFn): AppendEventFn;
@@ -0,0 +1,4 @@
1
+ // The per-event-type signature is only enforced at the call site; at runtime the payload is validated against the registered schema.
2
+ export function asTypedAppendEventFn(append) {
3
+ return append; // @cast-boundary engine-bridge
4
+ }
@@ -1,5 +1,5 @@
1
1
  // The static check in boot-validator/access-declarations.ts only sees a handler's own
2
- // input schema; writes reached via ctx.write/writeAs/queryAs, hooks or foreign-feature
2
+ // input schema; writes reached via ctx.dispatch.write/writeAs/queryAs, hooks or foreign-feature
3
3
  // tables are only visible at the actual write, so the gate runs there at runtime.
4
4
  import { isPersonalDataGated } from "@cosmicdrift/kumiko-types/event-store-types";
5
5
  import * as z from "zod";
@@ -37,7 +37,7 @@ function declaresPublicIntake(access) {
37
37
  return accessAllowsAnonymous(access) && declaredPersonalData(access) === "public-intake";
38
38
  }
39
39
  // Only the public dispatcher entry points compute a root; every nested call inherits
40
- // it, so switching identity via ctx.writeAs(SYSTEM, ...) cannot shed an anonymous root.
40
+ // it, so switching identity via ctx.dispatch.writeAs(SYSTEM, ...) cannot shed an anonymous root.
41
41
  export function rootWriteOrigin(registry, type, user) {
42
42
  const rootHandler = registry.getWriteHandler(type) ?? registry.getQueryHandler(type);
43
43
  return {
@@ -1,4 +1,4 @@
1
- import type { WriteResult } from "../engine/types/index.ts";
1
+ import type { WriteResult } from "@cosmicdrift/kumiko-types/handlers";
2
2
  import type { BatchCommand, BatchResult, DispatchContext } from "./dispatch-shared.ts";
3
3
  type EntityLookup = Pick<DispatchContext["registry"], "getHandlerEntity" | "getEntity">;
4
4
  export declare function maskWriteResultForClient(registry: EntityLookup, handlerType: string, result: WriteResult): WriteResult;
@@ -1,2 +1 @@
1
- export { type AdjNounNameOptions, type GenerateUniqueNameOptions, generateAdjNounName, generateNoConfusableId, generateUniqueName, } from "./generate.ts";
2
- export { ADJECTIVES, NOUNS } from "./words.ts";
1
+ export { generateUniqueName } from "./generate.ts";
@@ -1,2 +1 @@
1
- export { generateAdjNounName, generateNoConfusableId, generateUniqueName, } from "./generate.js";
2
- export { ADJECTIVES, NOUNS } from "./words.js";
1
+ export { generateUniqueName } from "./generate.js";
@@ -1,4 +1,5 @@
1
- import type { PayloadBucketNormalization, RateLimitOption, SessionUser } from "../engine/types/index.ts";
1
+ import type { PayloadBucketNormalization, RateLimitOption } from "@cosmicdrift/kumiko-types/handlers";
2
+ import type { SessionUser } from "../engine/types/index.ts";
2
3
  export type BucketContext = {
3
4
  readonly handlerName: string;
4
5
  readonly user: SessionUser;
@@ -1,7 +1,8 @@
1
1
  import { isAuthRateLimitExempt } from "../api/api-constants.js";
2
2
  import { clientIpSourceFromHonoContext, createClientIpResolver, } from "../api/client-ip.js";
3
3
  import { requestContext } from "../api/request-context.js";
4
- import { RateLimitError, serializeError } from "../errors/index.js";
4
+ import { RateLimitError } from "../errors/index.js";
5
+ import { serializeError } from "../errors/serialize.js";
5
6
  import { createFallbackLogger, scrubLogText } from "../logging/index.js";
6
7
  import { emitRateLimitFailOpen } from "../observability/standard-metrics.js";
7
8
  import { toPublicBucketName } from "./bucket.js";
@@ -1,8 +1,7 @@
1
- export type { CacheSyncBus, CacheSyncBusOverSignalOptions, ClosableCacheSyncBus, RedisCacheSyncBusOptions, ResolvedCacheSyncBus, } from "./cache-sync-bus.ts";
2
- export { createCacheSyncBusOverSignal, createDefaultCacheSyncBus, createLocalCacheSyncBus, createRedisCacheSyncBus, resolveCacheSyncBus, } from "./cache-sync-bus.ts";
1
+ export type { CacheSyncBus, ClosableCacheSyncBus, } from "./cache-sync-bus.ts";
2
+ export { createDefaultCacheSyncBus, createLocalCacheSyncBus, createRedisCacheSyncBus, } from "./cache-sync-bus.ts";
3
3
  export type { TenantConfigSyncMessage, TierAssignmentSyncMessage } from "./cache-sync-topics.ts";
4
- export { CACHE_SYNC_TOPICS, isTenantConfigSyncMessage, isTierAssignmentSyncMessage, } from "./cache-sync-topics.ts";
4
+ export { CACHE_SYNC_TOPICS, isTierAssignmentSyncMessage, } from "./cache-sync-topics.ts";
5
5
  export type { RedisClientOptions } from "./client.ts";
6
6
  export { createRedisClient, logRedisConnectionState, redisChannelPrefixFromEnv, redisClientOptionsFromEnv, } from "./client.ts";
7
- export type { PubSubSignal, PubSubSignalOptions } from "./pubsub-signal.ts";
8
7
  export { createRedisPubSubSignal } from "./pubsub-signal.ts";
@@ -1,4 +1,4 @@
1
- export { createCacheSyncBusOverSignal, createDefaultCacheSyncBus, createLocalCacheSyncBus, createRedisCacheSyncBus, resolveCacheSyncBus, } from "./cache-sync-bus.js";
2
- export { CACHE_SYNC_TOPICS, isTenantConfigSyncMessage, isTierAssignmentSyncMessage, } from "./cache-sync-topics.js";
1
+ export { createDefaultCacheSyncBus, createLocalCacheSyncBus, createRedisCacheSyncBus, } from "./cache-sync-bus.js";
2
+ export { CACHE_SYNC_TOPICS, isTierAssignmentSyncMessage, } from "./cache-sync-topics.js";
3
3
  export { createRedisClient, logRedisConnectionState, redisChannelPrefixFromEnv, redisClientOptionsFromEnv, } from "./client.js";
4
4
  export { createRedisPubSubSignal } from "./pubsub-signal.js";
@@ -4,7 +4,7 @@ import { createRegistry } from "../engine/registry.js";
4
4
  import { createEventsTable } from "../event-store/index.js";
5
5
  import { queueRebuildsFromMarkers, reportPendingRebuildRun, runPendingRebuilds, } from "../migrations/index.js";
6
6
  import { createEventConsumerStateTable, createProjectionStateTable } from "../pipeline/index.js";
7
- import { migrationsDirExistsOrReport, readDatabaseUrlOrReport, } from "./shared.js";
7
+ import { loadRowLevelSecurityModeOrReport, migrationsDirExistsOrReport, readDatabaseUrlOrReport, } from "./shared.js";
8
8
  async function ensureFrameworkInfrastructureTables(db) {
9
9
  // Framework infrastructure tables (event store + pipeline state) are not captured by
10
10
  // `generate`, which handles only entity read tables. Existing databases have them
@@ -52,7 +52,10 @@ export async function runApplyCommand(ctx) {
52
52
  return 1;
53
53
  if (!migrationsDirExistsOrReport(ctx))
54
54
  return 1;
55
- const { db, close } = createDbConnection({ url: dbUrl });
55
+ const rowLevelSecurity = await loadRowLevelSecurityModeOrReport(ctx);
56
+ if (rowLevelSecurity === undefined)
57
+ return 1;
58
+ const { db, close } = createDbConnection({ url: dbUrl, rowLevelSecurity });
56
59
  let wiring;
57
60
  try {
58
61
  const result = await runMigrationsFromDir(db, migrationsDir);
@@ -1,4 +1,5 @@
1
- import { baselineMigrations, createDbConnection, loadMigrationsFromDir } from "../db/index.js";
1
+ import { createDbConnection } from "../db/index.js";
2
+ import { baselineMigrations, loadMigrationsFromDir } from "../db/migrate-runner.js";
2
3
  import { describeThrown, migrationsDirExistsOrReport, readDatabaseUrlOrReport, } from "./shared.js";
3
4
  export async function runBaselineCommand(ctx) {
4
5
  const { out, migrationsDir } = ctx;
@@ -10,7 +11,11 @@ export async function runBaselineCommand(ctx) {
10
11
  return 1;
11
12
  if (!migrationsDirExistsOrReport(ctx))
12
13
  return 1;
13
- const { db, close } = createDbConnection({ url: dbUrl, maxConnections: 1 });
14
+ const { db, close } = createDbConnection({
15
+ url: dbUrl,
16
+ maxConnections: 1,
17
+ rowLevelSecurity: "off", // journal-only tool: touches no tenant rows
18
+ });
14
19
  try {
15
20
  const result = await baselineMigrations(db, loadMigrationsFromDir(migrationsDir));
16
21
  out.log("");
@@ -1,6 +1,9 @@
1
1
  import { existsSync, mkdirSync, writeFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { assertValidMigrationName, generateMigration, readMigrationSqlTexts, rebuildTablesFromDiff, writeRebuildMarker, writeSnapshotJson, } from "../db/index.js";
3
+ import { generateMigration, writeSnapshotJson } from "../db/index.js";
4
+ import { assertValidMigrationName, hasNoSchemaChanges } from "../db/migrate-generator.js";
5
+ import { readMigrationSqlTexts } from "../db/migrate-runner.js";
6
+ import { rebuildTablesFromDiff, writeRebuildMarker } from "../db/rebuild-marker.js";
4
7
  import { describeThrown, loadPreviousSnapshot, loadSchemaModOrReport, nextSequenceNumber, SNAPSHOT_FILENAME, } from "./shared.js";
5
8
  const GENERATE_USAGE = " Usage: schema generate <name>";
6
9
  function parseGenerateName(ctx) {
@@ -35,12 +38,6 @@ function parseGenerateName(ctx) {
35
38
  }
36
39
  return { kind: "name", name };
37
40
  }
38
- function isEmptyMigration(result) {
39
- return (result.diff.newTables.length === 0 &&
40
- result.diff.changedTables.length === 0 &&
41
- result.diff.droppedTables.length === 0 &&
42
- result.retiredDrops.length === 0);
43
- }
44
41
  function writeMigrationFiles(migrationsDir, snapshotPath, result) {
45
42
  if (!existsSync(migrationsDir))
46
43
  mkdirSync(migrationsDir, { recursive: true });
@@ -50,7 +47,7 @@ function writeMigrationFiles(migrationsDir, snapshotPath, result) {
50
47
  function reportGeneratedMigration(out, result, rebuildTables) {
51
48
  out.log("");
52
49
  out.log(` ✓ ${result.filename}`);
53
- out.log(` new tables: ${result.diff.newTables.length}, changed: ${result.diff.changedTables.length}, dropped: ${result.diff.droppedTables.length}, retired framework tables dropped: ${result.retiredDrops.length}`);
50
+ out.log(` new tables: ${result.diff.newTables.length}, changed: ${result.diff.changedTables.length}, dropped: ${result.diff.droppedTables.length}, retired framework tables dropped: ${result.retiredDrops.length}, row level security changes: ${result.rowLevelSecurityChanges.length}`);
54
51
  if (rebuildTables.length > 0) {
55
52
  out.log(` rebuild-marker: ${result.filename.replace(/\.sql$/, ".rebuild.json")} (${rebuildTables.length} table(s))`);
56
53
  }
@@ -70,12 +67,13 @@ export async function runGenerateCommand(ctx) {
70
67
  const prevSnapshot = loadPreviousSnapshot(snapshotPath);
71
68
  const result = generateMigration({
72
69
  metas: schemaMod.entityMetas,
70
+ rowLevelSecurity: schemaMod.rowLevelSecurity,
73
71
  prevSnapshot,
74
72
  name: parsed.name,
75
73
  sequenceNumber: nextSequenceNumber(migrationsDir),
76
74
  priorMigrationsSql: readMigrationSqlTexts(migrationsDir),
77
75
  });
78
- if (isEmptyMigration(result)) {
76
+ if (hasNoSchemaChanges(result)) {
79
77
  out.log(" No schema changes detected — no new migration file written.");
80
78
  return 0;
81
79
  }
@@ -1,10 +1,16 @@
1
1
  import { type renderTablesDdl } from "../db/index.ts";
2
+ import { type RowLevelSecurityMode } from "../db/render-rls-ddl.ts";
2
3
  import type { FeatureDefinition } from "../engine/types/feature.ts";
3
4
  export type SchemaCliOut = {
4
5
  readonly log: (line: string) => void;
5
6
  readonly err: (line: string) => void;
6
7
  };
7
- export type RunSchemaCliOptions = {
8
+ type RunSchemaCliRowLevelSecurityOption = {
9
+ /** The mode the app's runtime boots with (`AppConfig.rowLevelSecurity`). Wins over the schema
10
+ * file, so `apply` heals the same mode the boot check enforces. */
11
+ readonly rowLevelSecurity?: RowLevelSecurityMode;
12
+ };
13
+ export type RunSchemaCliOptions = RunSchemaCliRowLevelSecurityOption & ({
8
14
  readonly features?: undefined;
9
15
  readonly kmsSlots?: undefined;
10
16
  } | {
@@ -16,7 +22,7 @@ export type RunSchemaCliOptions = {
16
22
  * `[]` when the app wires none. This CLI parses no env schema, so the
17
23
  * rebuild's KMS wiring cannot derive them itself. */
18
24
  readonly kmsSlots: readonly string[];
19
- };
25
+ });
20
26
  export type SchemaCliContext = {
21
27
  readonly argv: readonly string[];
22
28
  readonly out: SchemaCliOut;
@@ -30,10 +36,14 @@ export type SchemaMod = {
30
36
  readonly entityMetas: Parameters<typeof renderTablesDdl>[0];
31
37
  readonly features?: unknown;
32
38
  readonly validateBootOptions?: unknown;
39
+ readonly rowLevelSecurity: RowLevelSecurityMode;
33
40
  };
41
+ export declare function parseSchemaRowLevelSecurity(value: unknown, schemaFile: string): RowLevelSecurityMode;
34
42
  export declare function describeThrown(e: unknown): string;
35
43
  export declare function nextSequenceNumber(migrationsDir: string): number;
36
44
  export declare function loadPreviousSnapshot(snapshotPath: string): import("../db/migrate-generator.ts").Snapshot | null;
37
45
  export declare function loadSchemaModOrReport(ctx: SchemaCliContext): Promise<SchemaMod | undefined>;
46
+ export declare function loadRowLevelSecurityModeOrReport(ctx: SchemaCliContext): Promise<RowLevelSecurityMode | undefined>;
38
47
  export declare function readDatabaseUrlOrReport(out: SchemaCliOut): string | undefined;
39
48
  export declare function migrationsDirExistsOrReport(ctx: SchemaCliContext): boolean;
49
+ export {};
@@ -7,10 +7,20 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
7
7
  return path;
8
8
  };
9
9
  import { existsSync, readdirSync } from "node:fs";
10
- import { isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
11
- import { assertUniqueTableNames, loadSnapshotJson } from "../db/index.js";
10
+ import { isOneOf, isPlainObject } from "@cosmicdrift/kumiko-types/type-guards";
11
+ import { loadSnapshotJson } from "../db/index.js";
12
+ import { assertUniqueTableNames } from "../db/migrate-generator.js";
13
+ import { DEFAULT_ROW_LEVEL_SECURITY_MODE, ROW_LEVEL_SECURITY_MODES, } from "../db/render-rls-ddl.js";
12
14
  import { isEntityTableMeta } from "../db/table-introspection.js";
13
15
  export const SNAPSHOT_FILENAME = ".snapshot.json";
16
+ // An absent export means the default mode; a typo must not silently switch tenant isolation off.
17
+ export function parseSchemaRowLevelSecurity(value, schemaFile) {
18
+ if (value === undefined)
19
+ return DEFAULT_ROW_LEVEL_SECURITY_MODE;
20
+ if (isOneOf(ROW_LEVEL_SECURITY_MODES, value))
21
+ return value;
22
+ throw new Error(`Schema file ${schemaFile}: ROW_LEVEL_SECURITY must be one of ${ROW_LEVEL_SECURITY_MODES.join(", ")}, got ${String(value)}.`);
23
+ }
14
24
  export function describeThrown(e) {
15
25
  return e instanceof Error ? e.message : String(e);
16
26
  }
@@ -43,6 +53,7 @@ async function loadSchemaModFromApp(schemaFile) {
43
53
  entityMetas: validMetas,
44
54
  features: mod["FEATURES"],
45
55
  validateBootOptions: mod["VALIDATE_BOOT_OPTIONS"],
56
+ rowLevelSecurity: parseSchemaRowLevelSecurity(mod["ROW_LEVEL_SECURITY"], schemaFile),
46
57
  };
47
58
  }
48
59
  export function nextSequenceNumber(migrationsDir) {
@@ -79,6 +90,17 @@ export async function loadSchemaModOrReport(ctx) {
79
90
  return undefined;
80
91
  }
81
92
  }
93
+ // `apply` needs only the mode: migrations and rebuilds on a role that RLS binds see nothing unless
94
+ // the connection runs in system scope, which only an "on" connection sets. The prod image ships no
95
+ // kumiko/schema.ts, so without one apply falls back to the runtime's default instead of "off":
96
+ // otherwise the framework tables stay unhealed and the boot check of an "on" app fails.
97
+ export async function loadRowLevelSecurityModeOrReport(ctx) {
98
+ if (ctx.options.rowLevelSecurity !== undefined)
99
+ return ctx.options.rowLevelSecurity;
100
+ if (!existsSync(ctx.schemaFile))
101
+ return DEFAULT_ROW_LEVEL_SECURITY_MODE;
102
+ return (await loadSchemaModOrReport(ctx))?.rowLevelSecurity;
103
+ }
82
104
  export function readDatabaseUrlOrReport(out) {
83
105
  const dbUrl = process.env["DATABASE_URL"];
84
106
  if (!dbUrl) {
@@ -1,6 +1,8 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { createDbConnection, fetchAppliedMigrations, findCommentedDropTables, isRetiredFrameworkTable, loadMigrationsFromDir, readMigrationSqlTexts, tableExists, } from "../db/index.js";
3
+ import { createDbConnection, tableExists } from "../db/index.js";
4
+ import { fetchAppliedMigrations, loadMigrationsFromDir, readMigrationSqlTexts, } from "../db/migrate-runner.js";
5
+ import { findCommentedDropTables, isRetiredFrameworkTable, } from "../db/retired-framework-tables.js";
4
6
  import { describeThrown, loadPreviousSnapshot, readDatabaseUrlOrReport, SNAPSHOT_FILENAME, } from "./shared.js";
5
7
  // A table that a migration only drops as a commented DESTRUCTIVE marker and
6
8
  // that the snapshot no longer has is gone on paper but still in the live DB.
@@ -42,7 +44,11 @@ export async function runStatusCommand(ctx) {
42
44
  return 0;
43
45
  }
44
46
  const local = loadMigrationsFromDir(migrationsDir);
45
- const { db, close } = createDbConnection({ url: dbUrl, maxConnections: 1 });
47
+ const { db, close } = createDbConnection({
48
+ url: dbUrl,
49
+ maxConnections: 1,
50
+ rowLevelSecurity: "off", // journal-only tool: touches no tenant rows
51
+ });
46
52
  try {
47
53
  const applied = await fetchAppliedMigrationIds(db);
48
54
  out.log("");
@@ -1,6 +1,9 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { diffReplayAgainstSnapshot, generateMigration, readMigrationSqlTexts, replayMigrationsDir, } from "../db/index.js";
3
+ import { assertRowLevelSecurityTableState, createDbConnection, generateMigration, } from "../db/index.js";
4
+ import { isLiveFrameworkTable } from "../db/known-table-names.js";
5
+ import { readMigrationSqlTexts } from "../db/migrate-runner.js";
6
+ import { diffReplayAgainstSnapshot, replayMigrationsDir } from "../db/replay-migration-sql.js";
4
7
  import { validateBoot } from "../engine/boot-validator.js";
5
8
  import { describeThrown, loadPreviousSnapshot, loadSchemaModOrReport, nextSequenceNumber, SNAPSHOT_FILENAME, } from "./shared.js";
6
9
  import { featureDefinitionsOf, parseValidateBootOptions, withFileStoragePresence, } from "./validate-boot-input.js";
@@ -9,6 +12,7 @@ function checkSchemaDrift(ctx, schemaMod, prevSnapshot) {
9
12
  const { out, migrationsDir } = ctx;
10
13
  const drift = generateMigration({
11
14
  metas: schemaMod.entityMetas,
15
+ rowLevelSecurity: schemaMod.rowLevelSecurity,
12
16
  prevSnapshot,
13
17
  name: "validate",
14
18
  sequenceNumber: nextSequenceNumber(migrationsDir),
@@ -19,13 +23,14 @@ function checkSchemaDrift(ctx, schemaMod, prevSnapshot) {
19
23
  ...drift.diff.changedTables.map((t) => t.tableName),
20
24
  ...drift.diff.droppedTables,
21
25
  ...drift.retiredDrops.map((t) => t.tableName),
26
+ ...drift.rowLevelSecurityChanges.map((c) => c.tableName),
22
27
  ];
23
28
  if (pendingTables.length === 0) {
24
29
  out.log(" ✓ schema: migrations match the entity definitions");
25
30
  return true;
26
31
  }
27
32
  out.err(" ✗ schema drift: entity definitions are ahead of kumiko/migrations.");
28
- out.err(` pending — new: ${drift.diff.newTables.length}, changed: ${drift.diff.changedTables.length}, dropped: ${drift.diff.droppedTables.length}`);
33
+ out.err(` pending — new: ${drift.diff.newTables.length}, changed: ${drift.diff.changedTables.length}, dropped: ${drift.diff.droppedTables.length}, row level security: ${drift.rowLevelSecurityChanges.length}`);
29
34
  out.err(` tables: ${pendingTables.join(", ")}`);
30
35
  out.err(" Fix: `kumiko-schema generate <name>`, then commit the migration.");
31
36
  return false;
@@ -57,6 +62,42 @@ function checkBootValidity(out, schemaMod) {
57
62
  return false;
58
63
  }
59
64
  }
65
+ function declaredTablesOf(schemaMod) {
66
+ const names = new Set(schemaMod.entityMetas.map((meta) => meta.tableName));
67
+ return { has: (tableName) => names.has(tableName) || isLiveFrameworkTable(tableName) };
68
+ }
69
+ // 4. Live row-level security table state — the table half of the boot check. Only with a DATABASE_URL;
70
+ // without one the command stays database-free. Scoped to the tables kumiko/schema.ts declares plus the
71
+ // framework tables, because a local DATABASE_URL may point at a dev database several apps share.
72
+ async function checkLiveRowLevelSecurity(out, schemaMod) {
73
+ const dbUrl = process.env["DATABASE_URL"];
74
+ if (!dbUrl) {
75
+ out.log(" · row-level security: skipped — set DATABASE_URL to check the live database.");
76
+ return true;
77
+ }
78
+ const { db, close } = createDbConnection({
79
+ url: dbUrl,
80
+ maxConnections: 1,
81
+ rowLevelSecurity: schemaMod.rowLevelSecurity,
82
+ });
83
+ try {
84
+ await assertRowLevelSecurityTableState(db, schemaMod.rowLevelSecurity, declaredTablesOf(schemaMod), "declared tables");
85
+ out.log(" ✓ row-level security: live database matches the configured mode for this app's tables and the framework tables (tables of other apps sharing the database are not checked)");
86
+ return true;
87
+ }
88
+ catch (e) {
89
+ out.err(` ✗ row-level security: ${describeThrown(e)}`);
90
+ return false;
91
+ }
92
+ finally {
93
+ try {
94
+ await close();
95
+ }
96
+ catch {
97
+ // The check result is already reported; a failing close must not hide it.
98
+ }
99
+ }
100
+ }
60
101
  function reportMigrationContentMismatches(out, mismatches) {
61
102
  out.err(" ✗ migration-content drift: committed *.sql files don't produce .snapshot.json.");
62
103
  for (const m of mismatches) {
@@ -72,7 +113,7 @@ function reportMigrationContentMismatches(out, mismatches) {
72
113
  "job-run-log store table for the pattern.");
73
114
  }
74
115
  if (mismatches.some((m) => m.kind !== "unexpected-table")) {
75
- out.err(" Fix (missing-table/column-drift): a migration file's body doesn't match " +
116
+ out.err(" Fix (missing-table/column-drift/row-level-security-drift): a migration file's body doesn't match " +
76
117
  "what it (or the snapshot) claims — hand-fix the file, or ship a corrective " +
77
118
  "migration if it's already applied in prod.");
78
119
  }
@@ -117,6 +158,8 @@ function checkMigrationContentDrift(ctx, prevSnapshot) {
117
158
  // Layer 1 alone misses this: it only compares ENTITY_METAS to the
118
159
  // snapshot, never the snapshot to the SQL that's supposed to have
119
160
  // produced it.
161
+ // 4. live row-level security (only with DATABASE_URL): the boot's
162
+ // table-state check against the real database (not the role: that is a boot-time property).
120
163
  // The DB-level gate (assertKumikoSchemaCurrent) stays at boot/deploy.
121
164
  export async function runValidateCommand(ctx) {
122
165
  const schemaMod = await loadSchemaModOrReport(ctx);
@@ -126,5 +169,6 @@ export async function runValidateCommand(ctx) {
126
169
  const schemaOk = checkSchemaDrift(ctx, schemaMod, prevSnapshot);
127
170
  const bootOk = checkBootValidity(ctx.out, schemaMod);
128
171
  const migrationsOk = checkMigrationContentDrift(ctx, prevSnapshot);
129
- return schemaOk && bootOk && migrationsOk ? 0 : 1;
172
+ const rowLevelSecurityOk = await checkLiveRowLevelSecurity(ctx.out, schemaMod);
173
+ return schemaOk && bootOk && migrationsOk && rowLevelSecurityOk ? 0 : 1;
130
174
  }
@@ -1,5 +1,4 @@
1
1
  import type { RunSchemaCliOptions, SchemaCliOut } from "./schema-cli/shared.ts";
2
- export type { RunSchemaCliOptions, SchemaCliOut } from "./schema-cli/shared.ts";
3
2
  /**
4
3
  * Runs a schema-CLI subcommand. `appCwd` is the app workspace root (where
5
4
  * `kumiko/schema.ts` + `kumiko/migrations/` live). Returns a process exit code.
@@ -1,4 +1,2 @@
1
- import type { Registry, TenantId } from "../engine/types/index.ts";
2
- import type { SearchAdapter } from "./types.ts";
1
+ import type { Registry } from "../engine/types/index.ts";
3
2
  export declare function collectSearchableFieldNames(registry: Registry): readonly string[];
4
- export declare function configureTenantSearchIndex(searchAdapter: SearchAdapter, registry: Registry, tenantId: TenantId): Promise<void>;
@@ -2,7 +2,3 @@ import { deriveSearchAdapterConfig } from "./derive-search-adapter-config.js";
2
2
  export function collectSearchableFieldNames(registry) {
3
3
  return deriveSearchAdapterConfig(registry)?.searchableFields ?? [];
4
4
  }
5
- export async function configureTenantSearchIndex(searchAdapter, registry, tenantId) {
6
- const fields = collectSearchableFieldNames(registry);
7
- await searchAdapter.configure(tenantId, { searchableFields: fields, rankingFields: fields });
8
- }
@@ -1,7 +1,4 @@
1
- export { collectSearchableFieldNames, configureTenantSearchIndex, } from "./configure-tenant-index.ts";
2
- export { deriveSearchAdapterConfig } from "./derive-search-adapter-config.ts";
3
1
  export { createInMemorySearchAdapter } from "./in-memory-adapter.ts";
4
2
  export { purgeSearchDocumentsForSubject } from "./purge-subject.ts";
5
- export type { ReindexEntityFailure, ReindexEntityOptions, ReindexEntityResult, } from "./reindex-entity.ts";
6
3
  export { reindexEntity } from "./reindex-entity.ts";
7
- export type { SearchAdapter, SearchAdapterConfig, SearchDocument, SearchOptions, SearchResult, } from "./types.ts";
4
+ export type { SearchAdapter, SearchAdapterConfig, } from "./types.ts";
@@ -2,8 +2,6 @@
2
2
  // `@cosmicdrift/kumiko-framework/search/meilisearch`. This keeps the main barrel from loading a
3
3
  // Meilisearch client when consumers only use SearchAdapter types, so apps that do not use
4
4
  // Meilisearch do not pull in the client code.
5
- export { collectSearchableFieldNames, configureTenantSearchIndex, } from "./configure-tenant-index.js";
6
- export { deriveSearchAdapterConfig } from "./derive-search-adapter-config.js";
7
5
  export { createInMemorySearchAdapter } from "./in-memory-adapter.js";
8
6
  export { purgeSearchDocumentsForSubject } from "./purge-subject.js";
9
7
  export { reindexEntity } from "./reindex-entity.js";
@@ -0,0 +1,8 @@
1
+ import type { EntityId, TenantId } from "../engine/types/identifiers.ts";
2
+ export type MeilisearchAdapterOptions = {
3
+ url: string;
4
+ apiKey: string;
5
+ indexPrefix?: string;
6
+ };
7
+ export declare function meilisearchTenantIndex(prefix: string, tenantId: TenantId): string;
8
+ export declare function meilisearchDocId(entityType: string, entityId: EntityId): string;