@cosmicdrift/kumiko-framework 0.389.0 → 0.390.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (616) hide show
  1. package/AGENTS.md +9 -4
  2. package/README.md +1 -1
  3. package/agents/examples/apex-surface-auth.md +2 -3
  4. package/agents/examples/api-worker-split.md +9 -2
  5. package/agents/examples/auth-claims.md +1 -1
  6. package/agents/examples/cross-feature-events.md +12 -12
  7. package/agents/examples/crypto-shredding-hr.md +2 -2
  8. package/agents/examples/encrypted-tenant-config.md +1 -1
  9. package/agents/examples/error-contract.md +12 -7
  10. package/agents/examples/event-sourcing.md +29 -29
  11. package/agents/examples/files-post-processing.md +10 -8
  12. package/agents/examples/inbound-mail-triage.md +1 -0
  13. package/agents/examples/lane-routing.md +2 -1
  14. package/agents/examples/legal-pages.md +2 -2
  15. package/agents/examples/lifecycle-hooks.md +3 -3
  16. package/agents/examples/managed-config.md +4 -4
  17. package/agents/examples/managed-pages.md +1 -1
  18. package/agents/examples/relations.md +19 -4
  19. package/agents/examples/search.md +4 -4
  20. package/agents/examples/secrets-demo.md +9 -6
  21. package/agents/examples/state-machine.md +2 -2
  22. package/agents/examples/tenant-settings.md +1 -1
  23. package/agents/examples/user-data-rights.md +3 -6
  24. package/agents/examples/workflow-engine.md +53 -47
  25. package/agents/examples.md +4 -4
  26. package/agents/features.md +1 -1
  27. package/dist/api/auth-middleware.js +1 -1
  28. package/dist/api/auth-routes-invite.js +2 -1
  29. package/dist/api/entity-read-access.d.ts +3 -1
  30. package/dist/api/export/export-columns.d.ts +3 -1
  31. package/dist/api/export/export-route.js +3 -2
  32. package/dist/api/export/export-screen.d.ts +2 -1
  33. package/dist/api/extra-route.d.ts +3 -1
  34. package/dist/api/index.d.ts +23 -27
  35. package/dist/api/index.js +13 -15
  36. package/dist/api/jwt.js +1 -1
  37. package/dist/api/observability-middleware.d.ts +1 -1
  38. package/dist/api/observability-middleware.js +2 -1
  39. package/dist/api/request-context-internals.d.ts +31 -0
  40. package/dist/api/request-context-internals.js +11 -0
  41. package/dist/api/request-context-scopes.d.ts +14 -0
  42. package/dist/api/request-context-scopes.js +69 -0
  43. package/dist/api/request-context.d.ts +1 -40
  44. package/dist/api/request-context.js +22 -51
  45. package/dist/api/request-id-middleware.d.ts +1 -1
  46. package/dist/api/route-registrars.d.ts +2 -1
  47. package/dist/api/route-registrars.js +1 -1
  48. package/dist/api/routes.js +7 -3
  49. package/dist/api/server-boot-checks.d.ts +1 -1
  50. package/dist/api/server-boot-checks.js +2 -2
  51. package/dist/api/server-event-dispatcher.d.ts +6 -1
  52. package/dist/api/server-event-dispatcher.js +3 -4
  53. package/dist/api/server-extra-routes.d.ts +1 -1
  54. package/dist/api/server-extra-routes.js +2 -1
  55. package/dist/api/server-middleware.js +3 -1
  56. package/dist/api/server-routes.d.ts +2 -1
  57. package/dist/api/server-wiring.js +6 -4
  58. package/dist/api/server.d.ts +2 -1
  59. package/dist/api/sse-route.d.ts +2 -1
  60. package/dist/api/tenant-scoped-secrets.d.ts +2 -0
  61. package/dist/api/tenant-scoped-secrets.js +13 -0
  62. package/dist/api/websocket-route.d.ts +1 -1
  63. package/dist/auth/index.d.ts +0 -1
  64. package/dist/auth/roles.d.ts +0 -5
  65. package/dist/compliance/duration-spec.d.ts +0 -1
  66. package/dist/compliance/duration-spec.js +0 -5
  67. package/dist/compliance/index.d.ts +4 -4
  68. package/dist/compliance/index.js +2 -2
  69. package/dist/compliance/profiles.d.ts +0 -15
  70. package/dist/compliance/profiles.js +0 -23
  71. package/dist/config/index.d.ts +10 -10
  72. package/dist/config/index.js +13 -1
  73. package/dist/config/internals.d.ts +9 -0
  74. package/dist/config/internals.js +1 -0
  75. package/dist/consumer-cli-internals.d.ts +4 -0
  76. package/dist/consumer-cli-internals.js +1 -0
  77. package/dist/consumer-cli.d.ts +1 -4
  78. package/dist/consumer-cli.js +5 -1
  79. package/dist/crypto/event-pii.js +1 -1
  80. package/dist/crypto/index.d.ts +8 -9
  81. package/dist/crypto/index.js +7 -8
  82. package/dist/crypto/pg-kms-adapter.js +6 -1
  83. package/dist/db/apply-entity-event.d.ts +1 -1
  84. package/dist/db/apply-entity-event.js +15 -47
  85. package/dist/db/blind-index-cleanup.js +91 -77
  86. package/dist/db/collect-table-metas.js +1 -1
  87. package/dist/db/compound-types.d.ts +1 -1
  88. package/dist/db/compound-types.js +0 -7
  89. package/dist/db/config-seed.d.ts +2 -1
  90. package/dist/db/config-seed.js +6 -1
  91. package/dist/db/connection.d.ts +3 -1
  92. package/dist/db/connection.js +15 -5
  93. package/dist/db/cross-tenant-reads.d.ts +1 -1
  94. package/dist/db/cross-tenant-reads.js +1 -1
  95. package/dist/db/dialect.d.ts +0 -5
  96. package/dist/db/dialect.js +0 -3
  97. package/dist/db/eagerload.d.ts +2 -1
  98. package/dist/db/entity-field-encryption.d.ts +1 -1
  99. package/dist/db/entity-table-meta.d.ts +1 -1
  100. package/dist/db/event-store-executor-context.d.ts +3 -1
  101. package/dist/db/event-store-executor-context.js +4 -3
  102. package/dist/db/event-store-executor-read-filter.d.ts +1 -1
  103. package/dist/db/event-store-executor-read-rows.d.ts +2 -1
  104. package/dist/db/event-store-executor-read-search.d.ts +2 -1
  105. package/dist/db/event-store-executor-read-sort.d.ts +2 -1
  106. package/dist/db/event-store-executor-read.js +2 -2
  107. package/dist/db/event-store-executor-write-atomic.js +8 -7
  108. package/dist/db/event-store-executor-write-steps.d.ts +3 -2
  109. package/dist/db/event-store-executor-write.js +7 -4
  110. package/dist/db/event-store-executor.d.ts +1 -1
  111. package/dist/db/executor-managed-tables.d.ts +7 -1
  112. package/dist/db/executor-managed-tables.js +11 -2
  113. package/dist/db/index.d.ts +29 -28
  114. package/dist/db/index.js +22 -20
  115. package/dist/db/known-table-names.d.ts +6 -0
  116. package/dist/db/known-table-names.js +21 -0
  117. package/dist/db/list-aggregate-labels.d.ts +1 -1
  118. package/dist/db/located-timestamp.d.ts +1 -1
  119. package/dist/db/located-timestamp.js +0 -5
  120. package/dist/db/migrate-generator.d.ts +17 -1
  121. package/dist/db/migrate-generator.js +50 -20
  122. package/dist/db/migrate-primary-key.d.ts +12 -0
  123. package/dist/db/migrate-primary-key.js +45 -0
  124. package/dist/db/migrate-rls-diff.d.ts +20 -0
  125. package/dist/db/migrate-rls-diff.js +61 -0
  126. package/dist/db/migrate-runner.js +4 -0
  127. package/dist/db/money.d.ts +1 -1
  128. package/dist/db/money.js +1 -1
  129. package/dist/db/parent-ref-clause.d.ts +2 -1
  130. package/dist/db/pg-error.d.ts +2 -0
  131. package/dist/db/pg-error.js +11 -0
  132. package/dist/db/queries/ddl.d.ts +3 -0
  133. package/dist/db/queries/ddl.js +34 -1
  134. package/dist/db/queries/event-store.js +4 -2
  135. package/dist/db/queries/event-tenants.d.ts +2 -0
  136. package/dist/db/queries/event-tenants.js +17 -0
  137. package/dist/db/queries/rebuild-rls-guard.d.ts +2 -0
  138. package/dist/db/queries/rebuild-rls-guard.js +29 -0
  139. package/dist/db/queries/rls-boot-catalog.d.ts +16 -0
  140. package/dist/db/queries/rls-boot-catalog.js +39 -0
  141. package/dist/db/queries/rls-catalog.d.ts +6 -0
  142. package/dist/db/queries/rls-catalog.js +82 -0
  143. package/dist/db/queries/rls-scope.d.ts +3 -0
  144. package/dist/db/queries/rls-scope.js +17 -0
  145. package/dist/db/queries/rls-shape.d.ts +10 -0
  146. package/dist/db/queries/rls-shape.js +42 -0
  147. package/dist/db/queries/session-advisory-lock.d.ts +2 -0
  148. package/dist/db/queries/session-advisory-lock.js +23 -0
  149. package/dist/db/queries/shadow-swap.d.ts +1 -2
  150. package/dist/db/queries/shadow-swap.js +9 -25
  151. package/dist/db/queries/test-stack.d.ts +4 -1
  152. package/dist/db/queries/test-stack.js +83 -2
  153. package/dist/db/query.js +11 -7
  154. package/dist/db/reference-data.d.ts +1 -1
  155. package/dist/db/reference-data.js +6 -1
  156. package/dist/db/render-ddl.d.ts +6 -2
  157. package/dist/db/render-ddl.js +7 -7
  158. package/dist/db/render-rls-ddl.d.ts +35 -0
  159. package/dist/db/render-rls-ddl.js +127 -0
  160. package/dist/db/replay-migration-sql.d.ts +3 -1
  161. package/dist/db/replay-migration-sql.js +22 -5
  162. package/dist/db/replay-rls.d.ts +25 -0
  163. package/dist/db/replay-rls.js +156 -0
  164. package/dist/db/row-level-security-boot-check.d.ts +5 -0
  165. package/dist/db/row-level-security-boot-check.js +85 -0
  166. package/dist/db/row-level-security-connection.d.ts +3 -0
  167. package/dist/db/row-level-security-connection.js +213 -0
  168. package/dist/db/row-level-security-scope.d.ts +33 -0
  169. package/dist/db/row-level-security-scope.js +127 -0
  170. package/dist/db/scope-tenant-db-to-tenant.d.ts +3 -0
  171. package/dist/db/scope-tenant-db-to-tenant.js +14 -0
  172. package/dist/db/sql-identifier.d.ts +1 -0
  173. package/dist/db/sql-identifier.js +3 -0
  174. package/dist/db/table-builder.d.ts +2 -1
  175. package/dist/db/table-builder.js +1 -1
  176. package/dist/db/table-info.js +1 -1
  177. package/dist/db/table-push.d.ts +11 -2
  178. package/dist/db/table-push.js +15 -2
  179. package/dist/db/tenant-db-runner.d.ts +3 -1
  180. package/dist/db/tenant-db-runner.js +4 -3
  181. package/dist/db/tenant-db-scoped-rebind.d.ts +10 -0
  182. package/dist/db/tenant-db-scoped-rebind.js +33 -0
  183. package/dist/db/tenant-db-statement-runner.d.ts +13 -0
  184. package/dist/db/tenant-db-statement-runner.js +48 -0
  185. package/dist/db/tenant-db.d.ts +17 -12
  186. package/dist/db/tenant-db.js +49 -120
  187. package/dist/db/tenant-id-filter.d.ts +3 -0
  188. package/dist/db/tenant-id-filter.js +30 -0
  189. package/dist/db/transaction-serialization.d.ts +6 -0
  190. package/dist/db/transaction-serialization.js +60 -0
  191. package/dist/derivatives/delete-stored-file.js +1 -1
  192. package/dist/derivatives/index.d.ts +2 -5
  193. package/dist/derivatives/index.js +2 -3
  194. package/dist/engine/access.d.ts +2 -1
  195. package/dist/engine/access.js +1 -1
  196. package/dist/engine/boot-validator/entity-handler.d.ts +2 -1
  197. package/dist/engine/boot-validator/entity-handler.js +1 -1
  198. package/dist/engine/boot-validator/entity-list-aggregate-options.d.ts +1 -1
  199. package/dist/engine/boot-validator/list-table-aggregate-options.d.ts +1 -1
  200. package/dist/engine/boot-validator/list-table-aggregate-query.d.ts +2 -1
  201. package/dist/engine/boot-validator/nav.d.ts +3 -1
  202. package/dist/engine/boot-validator/nav.js +1 -1
  203. package/dist/engine/boot-validator/ownership.d.ts +2 -1
  204. package/dist/engine/boot-validator/parent-ref.d.ts +2 -1
  205. package/dist/engine/boot-validator/projection-list-screens.d.ts +2 -1
  206. package/dist/engine/boot-validator/query-refs.d.ts +2 -1
  207. package/dist/engine/boot-validator/screens-forms.d.ts +2 -1
  208. package/dist/engine/boot-validator/screens-kind-shared.d.ts +3 -1
  209. package/dist/engine/boot-validator/screens.d.ts +2 -1
  210. package/dist/engine/boot-validator/workspaces.d.ts +3 -1
  211. package/dist/engine/bridge-stub.d.ts +5 -2
  212. package/dist/engine/bridge-stub.js +39 -24
  213. package/dist/engine/config-helpers.d.ts +2 -2
  214. package/dist/engine/config-helpers.js +0 -9
  215. package/dist/engine/constants.d.ts +0 -10
  216. package/dist/engine/constants.js +0 -8
  217. package/dist/engine/create-app.js +1 -1
  218. package/dist/engine/define-feature.d.ts +2 -1
  219. package/dist/engine/define-feature.js +1 -2
  220. package/dist/engine/define-handler.d.ts +1 -1
  221. package/dist/engine/define-step.d.ts +0 -1
  222. package/dist/engine/define-step.js +0 -3
  223. package/dist/engine/embedded-derived.d.ts +1 -1
  224. package/dist/engine/entity-handlers.d.ts +2 -1
  225. package/dist/engine/entity-handlers.js +7 -7
  226. package/dist/engine/entity-list-runtime-options.js +3 -1
  227. package/dist/engine/entity-list-searchability.d.ts +2 -1
  228. package/dist/engine/event-def.d.ts +2 -1
  229. package/dist/engine/event-helpers.d.ts +3 -1
  230. package/dist/engine/event-helpers.js +3 -3
  231. package/dist/engine/extension-names.d.ts +2 -8
  232. package/dist/engine/extension-names.js +2 -2
  233. package/dist/engine/extension-selector-plugins.d.ts +1 -1
  234. package/dist/engine/extensions/storage-provider.d.ts +1 -2
  235. package/dist/engine/extensions/user-data.d.ts +0 -8
  236. package/dist/engine/factories.d.ts +2 -1
  237. package/dist/engine/feature-builder-state.d.ts +8 -1
  238. package/dist/engine/feature-changelog.d.ts +1 -1
  239. package/dist/engine/feature-config-events-jobs.d.ts +4 -1
  240. package/dist/engine/feature-entity-handlers.d.ts +5 -1
  241. package/dist/engine/feature-manifest.js +1 -1
  242. package/dist/engine/feature-ui-extensions.d.ts +7 -1
  243. package/dist/engine/feature-ui-extensions.js +6 -4
  244. package/dist/engine/field-access.d.ts +2 -1
  245. package/dist/engine/handler-field-references.d.ts +0 -4
  246. package/dist/engine/index.d.ts +57 -54
  247. package/dist/engine/index.js +22 -27
  248. package/dist/engine/instruction-fields.d.ts +1 -1
  249. package/dist/engine/personal-data-fields.d.ts +1 -1
  250. package/dist/engine/qualified-name.d.ts +0 -1
  251. package/dist/engine/read-claim.d.ts +2 -1
  252. package/dist/engine/registry-facade.js +0 -3
  253. package/dist/engine/registry-ingest.d.ts +2 -1
  254. package/dist/engine/registry-ingest.js +1 -2
  255. package/dist/engine/registry-state.d.ts +12 -2
  256. package/dist/engine/registry-state.js +2 -3
  257. package/dist/engine/registry-validate.d.ts +3 -1
  258. package/dist/engine/registry-validate.js +7 -7
  259. package/dist/engine/run-in.d.ts +1 -1
  260. package/dist/engine/run-in.js +0 -1
  261. package/dist/engine/schema-builder.d.ts +1 -1
  262. package/dist/engine/schema-builder.js +1 -1
  263. package/dist/engine/screen-filter-ops.d.ts +2 -1
  264. package/dist/engine/screen-filter-ops.js +0 -5
  265. package/dist/engine/soft-delete-cleanup.d.ts +1 -1
  266. package/dist/engine/soft-delete-cleanup.js +4 -4
  267. package/dist/engine/state-machine.js +2 -1
  268. package/dist/engine/steps/_read-source.js +1 -1
  269. package/dist/engine/steps/aggregate-append-event.js +2 -2
  270. package/dist/engine/steps/call-feature.js +2 -2
  271. package/dist/engine/steps/mail-send.js +1 -1
  272. package/dist/engine/steps/retry.js +1 -1
  273. package/dist/engine/steps/wait-for-event.js +1 -1
  274. package/dist/engine/steps/wait.js +1 -1
  275. package/dist/engine/steps/webhook-send.js +1 -1
  276. package/dist/engine/template-variables.d.ts +2 -1
  277. package/dist/engine/transfer-adjacency.d.ts +1 -1
  278. package/dist/engine/types/index.d.ts +8 -31
  279. package/dist/engine/types/index.js +2 -10
  280. package/dist/engine/validation.d.ts +2 -1
  281. package/dist/entrypoint/index.d.ts +7 -35
  282. package/dist/entrypoint/index.js +7 -1
  283. package/dist/entrypoint/internals.d.ts +40 -0
  284. package/dist/entrypoint/internals.js +1 -0
  285. package/dist/entrypoint/row-level-security-mode-check.d.ts +3 -0
  286. package/dist/entrypoint/row-level-security-mode-check.js +19 -0
  287. package/dist/env/dry-run-internals.d.ts +10 -0
  288. package/dist/env/dry-run-internals.js +1 -0
  289. package/dist/env/dry-run.d.ts +1 -10
  290. package/dist/env/dry-run.js +2 -1
  291. package/dist/env/index.d.ts +1 -85
  292. package/dist/env/index.js +6 -50
  293. package/dist/env/internals.d.ts +87 -0
  294. package/dist/env/internals.js +53 -0
  295. package/dist/errors/classes.js +2 -2
  296. package/dist/errors/index.d.ts +5 -14
  297. package/dist/errors/index.js +4 -9
  298. package/dist/errors/member-resolution.js +1 -1
  299. package/dist/errors/reasons.d.ts +0 -1
  300. package/dist/errors/reasons.js +7 -7
  301. package/dist/errors/serialize.d.ts +0 -18
  302. package/dist/errors/serialize.js +0 -27
  303. package/dist/es-ops/index.d.ts +4 -4
  304. package/dist/es-ops/index.js +2 -2
  305. package/dist/es-ops/operations-schema.d.ts +1 -1
  306. package/dist/es-ops/types.d.ts +4 -5
  307. package/dist/event-store/admin-api-internals.d.ts +14 -0
  308. package/dist/event-store/admin-api-internals.js +1 -0
  309. package/dist/event-store/admin-api.d.ts +1 -14
  310. package/dist/event-store/admin-api.js +11 -6
  311. package/dist/event-store/archive.js +4 -2
  312. package/dist/event-store/errors.js +2 -2
  313. package/dist/event-store/event-store.js +41 -34
  314. package/dist/event-store/events-schema.js +4 -1
  315. package/dist/event-store/index.d.ts +11 -13
  316. package/dist/event-store/index.js +7 -9
  317. package/dist/event-store/rebuild-dead-letter.js +4 -2
  318. package/dist/event-store/snapshot.js +4 -3
  319. package/dist/event-store/stream-scope.d.ts +2 -0
  320. package/dist/event-store/stream-scope.js +6 -0
  321. package/dist/event-store/upcaster-dead-letter.js +4 -2
  322. package/dist/event-store/upcaster.d.ts +2 -1
  323. package/dist/files/action-form-upload.d.ts +2 -1
  324. package/dist/files/action-form-upload.js +1 -1
  325. package/dist/files/assert-file-refs-belong-to-tenant.d.ts +2 -1
  326. package/dist/files/assert-file-refs-belong-to-tenant.js +1 -1
  327. package/dist/files/bind-pending-file-refs.d.ts +2 -1
  328. package/dist/files/bind-pending-file-refs.js +2 -1
  329. package/dist/files/bind-referenced-files.write.js +1 -1
  330. package/dist/files/create-file-ref-from-bytes.d.ts +6 -3
  331. package/dist/files/create-file-ref-from-bytes.js +3 -3
  332. package/dist/files/create-file-ref.d.ts +3 -2
  333. package/dist/files/create-file-ref.js +2 -2
  334. package/dist/files/dispose-removed-file-refs.d.ts +2 -1
  335. package/dist/files/dispose-removed-file-refs.js +1 -1
  336. package/dist/files/feature.js +2 -2
  337. package/dist/files/file-handle.js +1 -1
  338. package/dist/files/file-routes.d.ts +1 -1
  339. package/dist/files/file-routes.js +12 -2
  340. package/dist/files/index.d.ts +11 -13
  341. package/dist/files/index.js +5 -7
  342. package/dist/files/load-save-file-refs.d.ts +2 -1
  343. package/dist/files/load-save-file-refs.js +1 -1
  344. package/dist/files/provider-resolver.d.ts +5 -4
  345. package/dist/files/provider-resolver.js +4 -4
  346. package/dist/files/storage-tracking.js +4 -2
  347. package/dist/files/sweep-orphaned-uploads.d.ts +1 -1
  348. package/dist/files/sweep-orphaned-uploads.js +1 -1
  349. package/dist/i18n/index.d.ts +2 -8
  350. package/dist/i18n/index.js +1 -1
  351. package/dist/i18n/internals.d.ts +7 -0
  352. package/dist/i18n/internals.js +1 -0
  353. package/dist/i18n/required-surface-keys.d.ts +4 -1
  354. package/dist/internal/row-level-security.d.ts +3 -0
  355. package/dist/internal/row-level-security.js +3 -0
  356. package/dist/internal/stack-support.d.ts +1 -1
  357. package/dist/internal/stack-support.js +1 -1
  358. package/dist/internal/testing.d.ts +1 -0
  359. package/dist/internal/testing.js +9 -5
  360. package/dist/jobs/index.d.ts +1 -1
  361. package/dist/jobs/job-append-event.d.ts +12 -0
  362. package/dist/jobs/job-append-event.js +30 -0
  363. package/dist/jobs/job-runner-context.d.ts +2 -2
  364. package/dist/jobs/job-runner-context.js +46 -16
  365. package/dist/jobs/job-runner-execution.d.ts +1 -1
  366. package/dist/jobs/job-runner-execution.js +6 -4
  367. package/dist/jobs/job-runner-gates.d.ts +1 -1
  368. package/dist/jobs/job-runner-gates.js +0 -1
  369. package/dist/jobs/job-runner-helpers.d.ts +11 -4
  370. package/dist/jobs/job-runner-helpers.js +10 -1
  371. package/dist/jobs/job-runner-scope.d.ts +5 -2
  372. package/dist/jobs/job-runner-types.d.ts +2 -1
  373. package/dist/jobs/job-runner.js +19 -6
  374. package/dist/jobs/max-per-tenant.d.ts +1 -1
  375. package/dist/logging/index.d.ts +1 -2
  376. package/dist/logging/index.js +1 -1
  377. package/dist/logging/pino-logger.js +1 -1
  378. package/dist/logging/utils.d.ts +1 -0
  379. package/dist/logging/utils.js +6 -0
  380. package/dist/migrations/index.d.ts +3 -3
  381. package/dist/migrations/index.js +3 -3
  382. package/dist/migrations/pending-rebuilds.d.ts +1 -1
  383. package/dist/migrations/pending-rebuilds.js +1 -1
  384. package/dist/migrations/pii-event-backfill.js +4 -1
  385. package/dist/observability/escape-hatch-report.d.ts +2 -1
  386. package/dist/observability/index.d.ts +7 -15
  387. package/dist/observability/index.js +4 -12
  388. package/dist/observability/metric-validator.js +1 -1
  389. package/dist/observability/metrics-handle.d.ts +0 -1
  390. package/dist/observability/metrics-handle.js +2 -15
  391. package/dist/observability/recording-tracer.d.ts +1 -2
  392. package/dist/observability/recording-tracer.js +0 -6
  393. package/dist/observability/sensitive-filter.d.ts +0 -2
  394. package/dist/observability/sensitive-filter.js +0 -29
  395. package/dist/pipeline/active-membership.d.ts +2 -1
  396. package/dist/pipeline/active-membership.js +6 -2
  397. package/dist/pipeline/append-event-core.d.ts +2 -1
  398. package/dist/pipeline/append-event-core.js +2 -2
  399. package/dist/pipeline/attach-outside-transaction.d.ts +3 -0
  400. package/dist/pipeline/attach-outside-transaction.js +13 -0
  401. package/dist/pipeline/auth-claims-resolver.d.ts +2 -1
  402. package/dist/pipeline/cascade-handler.d.ts +2 -1
  403. package/dist/pipeline/cascade-handler.js +3 -2
  404. package/dist/pipeline/config-accessor-factory.d.ts +1 -1
  405. package/dist/pipeline/config-accessor-factory.js +1 -1
  406. package/dist/pipeline/context-services.d.ts +56 -0
  407. package/dist/pipeline/context-services.js +73 -0
  408. package/dist/pipeline/dispatch-batch.d.ts +2 -1
  409. package/dist/pipeline/dispatch-batch.js +31 -18
  410. package/dist/pipeline/dispatch-query.js +5 -4
  411. package/dist/pipeline/dispatch-scope.d.ts +6 -0
  412. package/dist/pipeline/dispatch-scope.js +27 -0
  413. package/dist/pipeline/dispatch-shared.d.ts +13 -9
  414. package/dist/pipeline/dispatch-shared.js +75 -198
  415. package/dist/pipeline/dispatch-stream.js +8 -4
  416. package/dist/pipeline/dispatch-write.d.ts +2 -1
  417. package/dist/pipeline/dispatch-write.js +10 -8
  418. package/dist/pipeline/dispatcher-utils.d.ts +3 -1
  419. package/dist/pipeline/dispatcher-utils.js +8 -2
  420. package/dist/pipeline/dispatcher.d.ts +3 -2
  421. package/dist/pipeline/dispatcher.js +4 -3
  422. package/dist/pipeline/event-consumer-state.d.ts +0 -1
  423. package/dist/pipeline/event-dispatcher-delivery.d.ts +1 -1
  424. package/dist/pipeline/event-dispatcher-delivery.js +4 -2
  425. package/dist/pipeline/event-dispatcher.d.ts +2 -2
  426. package/dist/pipeline/event-dispatcher.js +7 -3
  427. package/dist/pipeline/event-retention.js +59 -56
  428. package/dist/pipeline/handler-access-error.js +2 -1
  429. package/dist/pipeline/handler-context-auth.d.ts +5 -6
  430. package/dist/pipeline/handler-context-auth.js +7 -4
  431. package/dist/pipeline/handler-context-config.d.ts +2 -5
  432. package/dist/pipeline/handler-context-config.js +2 -2
  433. package/dist/pipeline/handler-context-db.d.ts +32 -7
  434. package/dist/pipeline/handler-context-db.js +26 -17
  435. package/dist/pipeline/handler-context-dispatch.d.ts +13 -7
  436. package/dist/pipeline/handler-context-dispatch.js +9 -8
  437. package/dist/pipeline/handler-context-events.d.ts +22 -36
  438. package/dist/pipeline/handler-context-events.js +36 -31
  439. package/dist/pipeline/handler-context-member-resolution.d.ts +2 -0
  440. package/dist/pipeline/handler-context-member-resolution.js +110 -0
  441. package/dist/pipeline/handler-context-notify.d.ts +3 -2
  442. package/dist/pipeline/handler-context-notify.js +1 -1
  443. package/dist/pipeline/handler-context-observability.d.ts +2 -4
  444. package/dist/pipeline/handler-context-observability.js +7 -5
  445. package/dist/pipeline/handler-context-phase-denials.d.ts +11 -0
  446. package/dist/pipeline/handler-context-phase-denials.js +98 -0
  447. package/dist/pipeline/handler-context-scope.d.ts +7 -10
  448. package/dist/pipeline/handler-context-scope.js +18 -20
  449. package/dist/pipeline/index.d.ts +9 -21
  450. package/dist/pipeline/index.js +5 -7
  451. package/dist/pipeline/irreversible-operation-gate.d.ts +1 -1
  452. package/dist/pipeline/irreversible-operation-gate.js +2 -2
  453. package/dist/pipeline/lifecycle-pipeline.d.ts +8 -7
  454. package/dist/pipeline/lifecycle-pipeline.js +9 -15
  455. package/dist/pipeline/member-read-only-transaction.js +11 -3
  456. package/dist/pipeline/member-reader.d.ts +1 -1
  457. package/dist/pipeline/member-reader.js +2 -2
  458. package/dist/pipeline/msp-rebuild.js +5 -3
  459. package/dist/pipeline/multi-stream-apply-context.js +3 -2
  460. package/dist/pipeline/notify-scope.d.ts +2 -1
  461. package/dist/pipeline/pre-handler-gates.d.ts +2 -1
  462. package/dist/pipeline/pre-transaction-reservations.d.ts +3 -3
  463. package/dist/pipeline/pre-transaction-reservations.js +9 -7
  464. package/dist/pipeline/projection-rebuild.js +12 -5
  465. package/dist/pipeline/projection-state.d.ts +0 -6
  466. package/dist/pipeline/projection-state.js +0 -5
  467. package/dist/pipeline/projections-runner.d.ts +2 -1
  468. package/dist/pipeline/projections-runner.js +10 -6
  469. package/dist/pipeline/system-hooks.d.ts +3 -1
  470. package/dist/pipeline/system-hooks.js +6 -4
  471. package/dist/pipeline/system-identity-switch.d.ts +4 -2
  472. package/dist/pipeline/system-identity-switch.js +51 -36
  473. package/dist/pipeline/typed-append-event.d.ts +2 -0
  474. package/dist/pipeline/typed-append-event.js +4 -0
  475. package/dist/pipeline/write-origin.js +2 -2
  476. package/dist/pipeline/write-result-masking.d.ts +1 -1
  477. package/dist/random/index.d.ts +1 -2
  478. package/dist/random/index.js +1 -2
  479. package/dist/rate-limit/bucket.d.ts +2 -1
  480. package/dist/rate-limit/middleware.js +2 -1
  481. package/dist/redis/index.d.ts +3 -4
  482. package/dist/redis/index.js +2 -2
  483. package/dist/schema-cli/apply-command.js +5 -2
  484. package/dist/schema-cli/baseline-command.js +7 -2
  485. package/dist/schema-cli/generate-command.js +7 -9
  486. package/dist/schema-cli/shared.d.ts +4 -0
  487. package/dist/schema-cli/shared.js +21 -2
  488. package/dist/schema-cli/status-command.js +8 -2
  489. package/dist/schema-cli/validate-command.js +52 -4
  490. package/dist/schema-cli.d.ts +0 -1
  491. package/dist/search/configure-tenant-index.d.ts +1 -3
  492. package/dist/search/configure-tenant-index.js +0 -4
  493. package/dist/search/index.d.ts +1 -4
  494. package/dist/search/index.js +0 -2
  495. package/dist/search/meilisearch-adapter-internals.d.ts +8 -0
  496. package/dist/search/meilisearch-adapter-internals.js +9 -0
  497. package/dist/search/meilisearch-adapter.d.ts +1 -8
  498. package/dist/search/meilisearch-adapter.js +6 -7
  499. package/dist/search/meilisearch-peer.d.ts +2 -0
  500. package/dist/search/meilisearch-peer.js +5 -0
  501. package/dist/search/reindex-entity.js +93 -87
  502. package/dist/secrets/index.d.ts +3 -4
  503. package/dist/secrets/index.js +2 -3
  504. package/dist/seeding/index.d.ts +2 -2
  505. package/dist/seeding/index.js +1 -2
  506. package/dist/time/index.d.ts +2 -2
  507. package/dist/time/index.js +1 -1
  508. package/dist/time/tz-context.d.ts +0 -5
  509. package/dist/time/tz-context.js +0 -9
  510. package/dist/ui-types/index.d.ts +8 -11
  511. package/dist/ui-types/index.js +3 -3
  512. package/dist/upgrade-changelog.d.ts +3 -2
  513. package/dist/upgrade-changelog.js +12 -8
  514. package/dist/upgrade-cli-internals.d.ts +8 -0
  515. package/dist/upgrade-cli-internals.js +63 -0
  516. package/dist/upgrade-cli.d.ts +1 -9
  517. package/dist/upgrade-cli.js +10 -64
  518. package/dist/utils/import-optional-peer.d.ts +6 -0
  519. package/dist/utils/import-optional-peer.js +19 -0
  520. package/dist/utils/index.d.ts +1 -4
  521. package/dist/utils/index.js +1 -4
  522. package/package.json +22 -18
  523. package/src/changes.json +206 -0
  524. package/dist/crypto/request-kms-cache.d.ts +0 -8
  525. package/dist/crypto/request-kms-cache.js +0 -21
  526. package/dist/engine/codemod/index.d.ts +0 -2
  527. package/dist/engine/codemod/index.js +0 -1
  528. package/dist/engine/codemod/pipeline-codemod.d.ts +0 -50
  529. package/dist/engine/codemod/pipeline-codemod.js +0 -536
  530. package/dist/engine/feature-ast/entity-field-types.d.ts +0 -13
  531. package/dist/engine/feature-ast/entity-field-types.js +0 -35
  532. package/dist/engine/feature-ast/extractors/ai-steps.d.ts +0 -6
  533. package/dist/engine/feature-ast/extractors/ai-steps.js +0 -254
  534. package/dist/engine/feature-ast/extractors/events.d.ts +0 -5
  535. package/dist/engine/feature-ast/extractors/events.js +0 -275
  536. package/dist/engine/feature-ast/extractors/handlers.d.ts +0 -24
  537. package/dist/engine/feature-ast/extractors/handlers.js +0 -358
  538. package/dist/engine/feature-ast/extractors/hooks.d.ts +0 -24
  539. package/dist/engine/feature-ast/extractors/hooks.js +0 -248
  540. package/dist/engine/feature-ast/extractors/index.d.ts +0 -14
  541. package/dist/engine/feature-ast/extractors/index.js +0 -13
  542. package/dist/engine/feature-ast/extractors/jobs-routes.d.ts +0 -7
  543. package/dist/engine/feature-ast/extractors/jobs-routes.js +0 -145
  544. package/dist/engine/feature-ast/extractors/projections-screens.d.ts +0 -10
  545. package/dist/engine/feature-ast/extractors/projections-screens.js +0 -195
  546. package/dist/engine/feature-ast/extractors/resolve-import.d.ts +0 -21
  547. package/dist/engine/feature-ast/extractors/resolve-import.js +0 -180
  548. package/dist/engine/feature-ast/extractors/round1.d.ts +0 -11
  549. package/dist/engine/feature-ast/extractors/round1.js +0 -87
  550. package/dist/engine/feature-ast/extractors/round2.d.ts +0 -7
  551. package/dist/engine/feature-ast/extractors/round2.js +0 -191
  552. package/dist/engine/feature-ast/extractors/round3.d.ts +0 -23
  553. package/dist/engine/feature-ast/extractors/round3.js +0 -292
  554. package/dist/engine/feature-ast/extractors/round5.d.ts +0 -9
  555. package/dist/engine/feature-ast/extractors/round5.js +0 -68
  556. package/dist/engine/feature-ast/extractors/round6.d.ts +0 -4
  557. package/dist/engine/feature-ast/extractors/round6.js +0 -17
  558. package/dist/engine/feature-ast/extractors/shared.d.ts +0 -94
  559. package/dist/engine/feature-ast/extractors/shared.js +0 -343
  560. package/dist/engine/feature-ast/index.d.ts +0 -16
  561. package/dist/engine/feature-ast/index.js +0 -10
  562. package/dist/engine/feature-ast/parse.d.ts +0 -31
  563. package/dist/engine/feature-ast/parse.js +0 -485
  564. package/dist/engine/feature-ast/patch.d.ts +0 -212
  565. package/dist/engine/feature-ast/patch.js +0 -611
  566. package/dist/engine/feature-ast/patcher.d.ts +0 -217
  567. package/dist/engine/feature-ast/patcher.js +0 -281
  568. package/dist/engine/feature-ast/pattern-change-schema.d.ts +0 -1238
  569. package/dist/engine/feature-ast/pattern-change-schema.js +0 -1072
  570. package/dist/engine/feature-ast/pattern-id-matchers.d.ts +0 -7
  571. package/dist/engine/feature-ast/pattern-id-matchers.js +0 -211
  572. package/dist/engine/feature-ast/pattern-id-schema.d.ts +0 -251
  573. package/dist/engine/feature-ast/pattern-id-schema.js +0 -166
  574. package/dist/engine/feature-ast/patterns.d.ts +0 -322
  575. package/dist/engine/feature-ast/patterns.js +0 -107
  576. package/dist/engine/feature-ast/render.d.ts +0 -47
  577. package/dist/engine/feature-ast/render.js +0 -666
  578. package/dist/engine/feature-ast/source-location.d.ts +0 -17
  579. package/dist/engine/feature-ast/source-location.js +0 -27
  580. package/dist/engine/pattern-library/index.d.ts +0 -2
  581. package/dist/engine/pattern-library/index.js +0 -3
  582. package/dist/engine/pattern-library/library.d.ts +0 -14
  583. package/dist/engine/pattern-library/library.js +0 -94
  584. package/dist/engine/pattern-library/mixed-schemas.d.ts +0 -16
  585. package/dist/engine/pattern-library/mixed-schemas.js +0 -559
  586. package/dist/engine/pattern-library/opaque-schemas.d.ts +0 -7
  587. package/dist/engine/pattern-library/opaque-schemas.js +0 -115
  588. package/dist/engine/pattern-library/shared-fields.d.ts +0 -122
  589. package/dist/engine/pattern-library/shared-fields.js +0 -88
  590. package/dist/engine/pattern-library/static-schemas.d.ts +0 -21
  591. package/dist/engine/pattern-library/static-schemas.js +0 -487
  592. package/dist/engine/pattern-library/types.d.ts +0 -158
  593. package/dist/engine/pattern-library/types.js +0 -36
  594. package/dist/engine/resolve-config-or-param.d.ts +0 -18
  595. package/dist/engine/resolve-config-or-param.js +0 -76
  596. package/src/scripts/codemod/README.md +0 -187
  597. package/src/scripts/codemod/codemod-support.ts +0 -334
  598. package/src/scripts/codemod/collect-source-files.ts +0 -48
  599. package/src/scripts/codemod/crypto-shredding-testing-move.ts +0 -119
  600. package/src/scripts/codemod/db-factory.ts +0 -810
  601. package/src/scripts/codemod/feature-factory.ts +0 -429
  602. package/src/scripts/codemod/feature-layout.ts +0 -424
  603. package/src/scripts/codemod/import-extensions.ts +0 -118
  604. package/src/scripts/codemod/migrate-cross-tenant.ts +0 -328
  605. package/src/scripts/codemod/migrate-db-raw.ts +0 -401
  606. package/src/scripts/codemod/migrate-open-to-all.ts +0 -235
  607. package/src/scripts/codemod/object-form.ts +0 -746
  608. package/src/scripts/codemod/package-merge.ts +0 -299
  609. package/src/scripts/codemod/pii-personal-migration.ts +0 -816
  610. package/src/scripts/codemod/remove-engine-payload-casts.ts +0 -318
  611. package/src/scripts/codemod/s3-imports.ts +0 -236
  612. package/src/scripts/codemod/tenant-db-options.ts +0 -454
  613. package/src/scripts/codemod/testing-injection.ts +0 -215
  614. package/src/scripts/codemod/testing-move-targets.ts +0 -161
  615. package/src/scripts/codemod/testing-move.ts +0 -542
  616. package/src/scripts/codemod/unprocessable-error-details-reason.ts +0 -411
@@ -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,4 +1,5 @@
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;
@@ -30,10 +31,13 @@ export type SchemaMod = {
30
31
  readonly entityMetas: Parameters<typeof renderTablesDdl>[0];
31
32
  readonly features?: unknown;
32
33
  readonly validateBootOptions?: unknown;
34
+ readonly rowLevelSecurity: RowLevelSecurityMode;
33
35
  };
36
+ export declare function parseSchemaRowLevelSecurity(value: unknown, schemaFile: string): RowLevelSecurityMode;
34
37
  export declare function describeThrown(e: unknown): string;
35
38
  export declare function nextSequenceNumber(migrationsDir: string): number;
36
39
  export declare function loadPreviousSnapshot(snapshotPath: string): import("../db/migrate-generator.ts").Snapshot | null;
37
40
  export declare function loadSchemaModOrReport(ctx: SchemaCliContext): Promise<SchemaMod | undefined>;
41
+ export declare function loadRowLevelSecurityModeOrReport(ctx: SchemaCliContext): Promise<RowLevelSecurityMode | undefined>;
38
42
  export declare function readDatabaseUrlOrReport(out: SchemaCliOut): string | undefined;
39
43
  export declare function migrationsDirExistsOrReport(ctx: SchemaCliContext): boolean;
@@ -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,14 @@ 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. Without a schema file
95
+ // (dev CLI against a bare checkout) there is nothing to enforce.
96
+ export async function loadRowLevelSecurityModeOrReport(ctx) {
97
+ if (!existsSync(ctx.schemaFile))
98
+ return "off";
99
+ return (await loadSchemaModOrReport(ctx))?.rowLevelSecurity;
100
+ }
82
101
  export function readDatabaseUrlOrReport(out) {
83
102
  const dbUrl = process.env["DATABASE_URL"];
84
103
  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 { knownTablesOf } 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,46 @@ function checkBootValidity(out, schemaMod) {
57
62
  return false;
58
63
  }
59
64
  }
65
+ // 4. Live row-level security table state — the table half of the boot check. Only with a DATABASE_URL;
66
+ // without one the command stays database-free.
67
+ async function checkLiveRowLevelSecurity(out, schemaMod) {
68
+ const dbUrl = process.env["DATABASE_URL"];
69
+ if (!dbUrl) {
70
+ out.log(" · row-level security: skipped — set DATABASE_URL to check the live database.");
71
+ return true;
72
+ }
73
+ let features;
74
+ try {
75
+ features = featureDefinitionsOf(schemaMod.features);
76
+ }
77
+ catch {
78
+ // skip: the boot check already reported the unreadable FEATURES export
79
+ return true;
80
+ }
81
+ const knownTables = features === undefined ? { has: () => true } : knownTablesOf(features);
82
+ const { db, close } = createDbConnection({
83
+ url: dbUrl,
84
+ maxConnections: 1,
85
+ rowLevelSecurity: schemaMod.rowLevelSecurity,
86
+ });
87
+ try {
88
+ await assertRowLevelSecurityTableState(db, schemaMod.rowLevelSecurity, knownTables);
89
+ out.log(" ✓ row-level security: live database matches the configured mode");
90
+ return true;
91
+ }
92
+ catch (e) {
93
+ out.err(` ✗ row-level security: ${describeThrown(e)}`);
94
+ return false;
95
+ }
96
+ finally {
97
+ try {
98
+ await close();
99
+ }
100
+ catch {
101
+ // The check result is already reported; a failing close must not hide it.
102
+ }
103
+ }
104
+ }
60
105
  function reportMigrationContentMismatches(out, mismatches) {
61
106
  out.err(" ✗ migration-content drift: committed *.sql files don't produce .snapshot.json.");
62
107
  for (const m of mismatches) {
@@ -72,7 +117,7 @@ function reportMigrationContentMismatches(out, mismatches) {
72
117
  "job-run-log store table for the pattern.");
73
118
  }
74
119
  if (mismatches.some((m) => m.kind !== "unexpected-table")) {
75
- out.err(" Fix (missing-table/column-drift): a migration file's body doesn't match " +
120
+ out.err(" Fix (missing-table/column-drift/row-level-security-drift): a migration file's body doesn't match " +
76
121
  "what it (or the snapshot) claims — hand-fix the file, or ship a corrective " +
77
122
  "migration if it's already applied in prod.");
78
123
  }
@@ -117,6 +162,8 @@ function checkMigrationContentDrift(ctx, prevSnapshot) {
117
162
  // Layer 1 alone misses this: it only compares ENTITY_METAS to the
118
163
  // snapshot, never the snapshot to the SQL that's supposed to have
119
164
  // produced it.
165
+ // 4. live row-level security (only with DATABASE_URL): the boot's
166
+ // table-state check against the real database (not the role: that is a boot-time property).
120
167
  // The DB-level gate (assertKumikoSchemaCurrent) stays at boot/deploy.
121
168
  export async function runValidateCommand(ctx) {
122
169
  const schemaMod = await loadSchemaModOrReport(ctx);
@@ -126,5 +173,6 @@ export async function runValidateCommand(ctx) {
126
173
  const schemaOk = checkSchemaDrift(ctx, schemaMod, prevSnapshot);
127
174
  const bootOk = checkBootValidity(ctx.out, schemaMod);
128
175
  const migrationsOk = checkMigrationContentDrift(ctx, prevSnapshot);
129
- return schemaOk && bootOk && migrationsOk ? 0 : 1;
176
+ const rowLevelSecurityOk = await checkLiveRowLevelSecurity(ctx.out, schemaMod);
177
+ return schemaOk && bootOk && migrationsOk && rowLevelSecurityOk ? 0 : 1;
130
178
  }
@@ -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;
@@ -0,0 +1,9 @@
1
+ // Exported for unit tests (index-name / primary-key shape) without a live Meili.
2
+ export function meilisearchTenantIndex(prefix, tenantId) {
3
+ return `${prefix}t${tenantId}`;
4
+ }
5
+ // Meilisearch primary-key-ids: alphanumerics, `-`, `_`. UUIDs contain `-` —
6
+ // legal. Replace anything else just in case callers pass unexpected shapes.
7
+ export function meilisearchDocId(entityType, entityId) {
8
+ return `${entityType}_${String(entityId).replace(/[^0-9A-Za-z_-]/g, "_")}`;
9
+ }
@@ -1,10 +1,3 @@
1
- import type { EntityId, TenantId } from "../engine/types/identifiers.ts";
1
+ import { type MeilisearchAdapterOptions } from "./meilisearch-adapter-internals.ts";
2
2
  import type { SearchAdapter } from "./types.ts";
3
- export type MeilisearchAdapterOptions = {
4
- url: string;
5
- apiKey: string;
6
- indexPrefix?: string;
7
- };
8
- export declare function meilisearchTenantIndex(prefix: string, tenantId: TenantId): string;
9
- export declare function meilisearchDocId(entityType: string, entityId: EntityId): string;
10
3
  export declare function createMeilisearchAdapter(options: MeilisearchAdapterOptions): SearchAdapter;