@cosmicdrift/kumiko-framework 0.14.0 → 0.15.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 (314) hide show
  1. package/package.json +6 -6
  2. package/src/__tests__/{anonymous-access.integration.ts → anonymous-access.integration.test.ts} +12 -9
  3. package/src/__tests__/{error-contract.integration.ts → error-contract.integration.test.ts} +5 -4
  4. package/src/__tests__/{field-access.integration.ts → field-access.integration.test.ts} +3 -3
  5. package/src/__tests__/{full-stack.integration.ts → full-stack.integration.test.ts} +7 -16
  6. package/src/__tests__/{ownership.integration.ts → ownership.integration.test.ts} +3 -2
  7. package/src/__tests__/{raw-table.integration.ts → raw-table.integration.test.ts} +18 -30
  8. package/src/__tests__/{reference-data.integration.ts → reference-data.integration.test.ts} +24 -11
  9. package/src/__tests__/{transition-guard.integration.ts → transition-guard.integration.test.ts} +12 -10
  10. package/src/api/__tests__/api.test.ts +1 -1
  11. package/src/api/__tests__/auth-middleware-transport.test.ts +1 -1
  12. package/src/api/__tests__/auth-routes-cookie.test.ts +1 -1
  13. package/src/api/__tests__/{batch.integration.ts → batch.integration.test.ts} +30 -30
  14. package/src/api/__tests__/body-limit.test.ts +1 -1
  15. package/src/api/__tests__/csrf-middleware.test.ts +1 -1
  16. package/src/api/__tests__/{dispatcher-live.integration.ts → dispatcher-live.integration.test.ts} +10 -9
  17. package/src/api/__tests__/metrics-endpoint.test.ts +1 -1
  18. package/src/api/__tests__/{nested-write.integration.ts → nested-write.integration.test.ts} +13 -16
  19. package/src/api/__tests__/readiness.test.ts +1 -1
  20. package/src/api/__tests__/request-id-middleware.test.ts +1 -1
  21. package/src/api/__tests__/sse-broker.test.ts +12 -12
  22. package/src/api/__tests__/sse-route.test.ts +1 -1
  23. package/src/api/readiness.ts +2 -2
  24. package/src/auth/__tests__/roles.test.ts +2 -2
  25. package/src/bun-db/__tests__/PATTERN.md +73 -0
  26. package/src/bun-db/__tests__/_helpers.ts +103 -0
  27. package/src/bun-db/__tests__/batch-methods.integration.test.ts +143 -0
  28. package/src/bun-db/__tests__/batch-methods.test.ts +20 -0
  29. package/src/bun-db/__tests__/bun-test-db.ts +19 -0
  30. package/src/bun-db/__tests__/bun-test-stack.ts +6 -0
  31. package/src/bun-db/__tests__/column-types.integration.test.ts +132 -0
  32. package/src/bun-db/__tests__/compound-types.integration.test.ts +134 -0
  33. package/src/bun-db/__tests__/jsonb-edge-cases.integration.test.ts +235 -0
  34. package/src/bun-db/__tests__/smoke.integration.test.ts +43 -0
  35. package/src/bun-db/__tests__/sql-methods.integration.test.ts +231 -0
  36. package/src/bun-db/__tests__/where-patterns.integration.test.ts +185 -0
  37. package/src/bun-db/connection.ts +84 -0
  38. package/src/bun-db/index.ts +31 -0
  39. package/src/bun-db/query.ts +845 -0
  40. package/src/compliance/__tests__/duration-spec.test.ts +1 -1
  41. package/src/compliance/__tests__/profiles.test.ts +1 -1
  42. package/src/compliance/__tests__/sub-processors.test.ts +1 -1
  43. package/src/db/__tests__/{apply-entity-event-tenant.integration.ts → apply-entity-event-tenant.integration.test.ts} +13 -11
  44. package/src/db/__tests__/big-int-field.test.ts +15 -14
  45. package/src/db/__tests__/column-ddl.integration.test.ts +113 -0
  46. package/src/db/__tests__/compound-types.test.ts +1 -1
  47. package/src/db/__tests__/{config-seed.integration.ts → config-seed.integration.test.ts} +32 -27
  48. package/src/db/__tests__/connection-options.test.ts +1 -1
  49. package/src/db/__tests__/dialect-instant.test.ts +1 -1
  50. package/src/db/__tests__/encryption.test.ts +1 -1
  51. package/src/db/__tests__/{drizzle-table-types.test.ts → entity-table-types.test.ts} +16 -16
  52. package/src/db/__tests__/{event-store-executor-list.integration.ts → event-store-executor-list.integration.test.ts} +12 -7
  53. package/src/db/__tests__/{event-store-executor.integration.ts → event-store-executor.integration.test.ts} +19 -12
  54. package/src/db/__tests__/{implicit-projection-equivalence.integration.ts → implicit-projection-equivalence.integration.test.ts} +35 -29
  55. package/src/db/__tests__/located-timestamp.test.ts +1 -1
  56. package/src/db/__tests__/money.test.ts +1 -1
  57. package/src/db/__tests__/{multi-row-insert.integration.ts → multi-row-insert.integration.test.ts} +18 -11
  58. package/src/db/__tests__/parse-auto-verb.test.ts +1 -1
  59. package/src/db/__tests__/{required-not-null-migration-safety.integration.ts → required-not-null-migration-safety.integration.test.ts} +28 -24
  60. package/src/db/__tests__/{schema-migration.integration.ts → schema-migration.integration.test.ts} +32 -28
  61. package/src/db/__tests__/sql-inventory.test.ts +56 -0
  62. package/src/db/__tests__/table-builder-indexes.test.ts +30 -11
  63. package/src/db/__tests__/table-builder-required.test.ts +20 -22
  64. package/src/db/__tests__/{tenant-db.integration.ts → tenant-db.integration.test.ts} +106 -144
  65. package/src/db/__tests__/{unique-violation-mapping.integration.ts → unique-violation-mapping.integration.test.ts} +13 -8
  66. package/src/db/api.ts +46 -0
  67. package/src/db/apply-entity-event.ts +45 -36
  68. package/src/db/assert-exists-in.ts +5 -16
  69. package/src/db/bun-provider.ts +37 -0
  70. package/src/db/config-seed.ts +4 -4
  71. package/src/db/connection.ts +14 -57
  72. package/src/db/cursor.ts +5 -56
  73. package/src/db/dialect.ts +472 -99
  74. package/src/db/eagerload.ts +5 -12
  75. package/src/db/entity-table-meta.ts +390 -0
  76. package/src/db/event-store-executor.ts +158 -100
  77. package/src/db/index.ts +33 -5
  78. package/src/db/migrate-generator.ts +350 -0
  79. package/src/db/migrate-runner.ts +206 -0
  80. package/src/db/postgres-provider.ts +25 -0
  81. package/src/db/queries/entity-read.ts +15 -0
  82. package/src/db/queries/es-ops.ts +17 -0
  83. package/src/db/queries/event-consumer.ts +170 -0
  84. package/src/db/queries/event-store-admin.ts +127 -0
  85. package/src/db/queries/event-store.ts +155 -0
  86. package/src/db/queries/projection-rebuild.ts +59 -0
  87. package/src/db/queries/raw-sql.ts +15 -0
  88. package/src/db/queries/schema-drift.ts +35 -0
  89. package/src/db/queries/seed-context.ts +58 -0
  90. package/src/db/queries/table-ops.ts +11 -0
  91. package/src/db/queries/test-stack.ts +56 -0
  92. package/src/db/query-api.ts +22 -0
  93. package/src/db/query.ts +30 -0
  94. package/src/db/reference-data.ts +19 -22
  95. package/src/db/render-ddl.ts +57 -0
  96. package/src/db/row-helpers.ts +3 -52
  97. package/src/db/schema-inspection.ts +17 -4
  98. package/src/db/sql-inventory.ts +208 -0
  99. package/src/db/table-builder.ts +48 -40
  100. package/src/db/tenant-db.ts +105 -326
  101. package/src/engine/__tests__/auth-claims-registrar.test.ts +1 -1
  102. package/src/engine/__tests__/boot-validator-api-exposure.test.ts +3 -3
  103. package/src/engine/__tests__/boot-validator-located-timestamps.test.ts +1 -1
  104. package/src/engine/__tests__/boot-validator-pii-retention.test.ts +5 -5
  105. package/src/engine/__tests__/boot-validator-s0-integration.test.ts +3 -3
  106. package/src/engine/__tests__/boot-validator.test.ts +4 -3
  107. package/src/engine/__tests__/build-app-schema.test.ts +1 -1
  108. package/src/engine/__tests__/build-target.test.ts +1 -1
  109. package/src/engine/__tests__/claim-keys.test.ts +1 -1
  110. package/src/engine/__tests__/codemod-pipeline.test.ts +3 -3
  111. package/src/engine/__tests__/config-helpers.test.ts +1 -1
  112. package/src/engine/__tests__/effective-features.test.ts +1 -1
  113. package/src/engine/__tests__/engine.test.ts +1 -1
  114. package/src/engine/__tests__/entity-handlers.test.ts +3 -3
  115. package/src/engine/__tests__/event-helpers.test.ts +3 -3
  116. package/src/engine/__tests__/extends-registrar.test.ts +4 -4
  117. package/src/engine/__tests__/factories-long-text.test.ts +1 -1
  118. package/src/engine/__tests__/factories-time.test.ts +1 -1
  119. package/src/engine/__tests__/field-predicates.test.ts +1 -1
  120. package/src/engine/__tests__/hook-phases.test.ts +1 -1
  121. package/src/engine/__tests__/identifiers.test.ts +1 -1
  122. package/src/engine/__tests__/lifecycle-hooks.test.ts +1 -1
  123. package/src/engine/__tests__/nav.test.ts +1 -1
  124. package/src/engine/__tests__/ownership.test.ts +10 -11
  125. package/src/engine/__tests__/parse-ref-target.test.ts +1 -1
  126. package/src/engine/__tests__/pipeline-engine.test.ts +1 -1
  127. package/src/engine/__tests__/{pipeline-handler.integration.ts → pipeline-handler.integration.test.ts} +38 -52
  128. package/src/engine/__tests__/{pipeline-observability.integration.ts → pipeline-observability.integration.test.ts} +1 -1
  129. package/src/engine/__tests__/{pipeline-performance.integration.ts → pipeline-performance.integration.test.ts} +1 -1
  130. package/src/engine/__tests__/pipeline-sub-pipelines.test.ts +1 -1
  131. package/src/engine/__tests__/post-query-hook.test.ts +1 -1
  132. package/src/engine/__tests__/projection-helpers.test.ts +25 -17
  133. package/src/engine/__tests__/projection.test.ts +4 -4
  134. package/src/engine/__tests__/qualified-name.test.ts +1 -1
  135. package/src/engine/__tests__/raw-table.test.ts +9 -8
  136. package/src/engine/__tests__/resolve-config-or-param.test.ts +5 -5
  137. package/src/engine/__tests__/run-in.test.ts +1 -1
  138. package/src/engine/__tests__/schema-builder.test.ts +1 -1
  139. package/src/engine/__tests__/screen.test.ts +1 -1
  140. package/src/engine/__tests__/search-payload-extension.test.ts +3 -3
  141. package/src/engine/__tests__/state-machine.test.ts +1 -1
  142. package/src/engine/__tests__/steps-aggregate-append-event.test.ts +7 -7
  143. package/src/engine/__tests__/steps-aggregate-create.test.ts +4 -4
  144. package/src/engine/__tests__/steps-aggregate-update.test.ts +3 -3
  145. package/src/engine/__tests__/steps-call-feature.test.ts +5 -5
  146. package/src/engine/__tests__/steps-mail-send.test.ts +7 -7
  147. package/src/engine/__tests__/steps-read.test.ts +34 -40
  148. package/src/engine/__tests__/steps-resolver-utils.test.ts +6 -6
  149. package/src/engine/__tests__/steps-unsafe-projection-delete.test.ts +24 -19
  150. package/src/engine/__tests__/steps-unsafe-projection-upsert.test.ts +28 -17
  151. package/src/engine/__tests__/steps-webhook-send.test.ts +6 -6
  152. package/src/engine/__tests__/steps-workflow.test.ts +7 -7
  153. package/src/engine/__tests__/system-user.test.ts +1 -1
  154. package/src/engine/__tests__/validate-projection-allowlist.test.ts +4 -5
  155. package/src/engine/__tests__/validation-hooks.test.ts +1 -1
  156. package/src/engine/__tests__/visual-tree-patterns.test.ts +1 -1
  157. package/src/engine/boot-validator/entity-handler.ts +3 -3
  158. package/src/engine/boot-validator/ownership.ts +1 -1
  159. package/src/engine/define-feature.ts +1 -2
  160. package/src/engine/entity-handlers.ts +5 -5
  161. package/src/engine/factories.ts +1 -1
  162. package/src/engine/feature-ast/__tests__/canonical-form.test.ts +1 -1
  163. package/src/engine/feature-ast/__tests__/parse-happy-path.test.ts +1 -1
  164. package/src/engine/feature-ast/__tests__/parse-real-features.test.ts +2 -2
  165. package/src/engine/feature-ast/__tests__/parse.test.ts +1 -1
  166. package/src/engine/feature-ast/__tests__/patch.test.ts +1 -1
  167. package/src/engine/feature-ast/__tests__/patcher.test.ts +1 -1
  168. package/src/engine/feature-ast/__tests__/render-roundtrip.test.ts +1 -1
  169. package/src/engine/feature-ast/__tests__/visual-tree-parse.test.ts +1 -1
  170. package/src/engine/ownership.ts +113 -41
  171. package/src/engine/pattern-library/__tests__/library.test.ts +2 -2
  172. package/src/engine/projection-helpers.ts +2 -11
  173. package/src/engine/registry.ts +2 -2
  174. package/src/engine/steps/read-find-many.ts +13 -13
  175. package/src/engine/steps/read-find-one.ts +7 -9
  176. package/src/engine/steps/unsafe-projection-delete.ts +4 -5
  177. package/src/engine/steps/unsafe-projection-upsert.ts +63 -31
  178. package/src/engine/types/feature.ts +7 -2
  179. package/src/engine/types/fields.ts +4 -5
  180. package/src/engine/types/step.ts +10 -10
  181. package/src/engine/validate-projection-allowlist.ts +23 -3
  182. package/src/entrypoint/__tests__/{entrypoint-job-wiring.integration.ts → entrypoint-job-wiring.integration.test.ts} +4 -3
  183. package/src/entrypoint/__tests__/{split-deploy.integration.ts → split-deploy.integration.test.ts} +4 -3
  184. package/src/env/__tests__/compose-env-schema.test.ts +1 -1
  185. package/src/env/__tests__/dry-run.test.ts +1 -1
  186. package/src/errors/__tests__/classes.test.ts +1 -1
  187. package/src/errors/__tests__/write-failures.test.ts +1 -1
  188. package/src/es-ops/__tests__/{context.integration.ts → context.integration.test.ts} +43 -29
  189. package/src/es-ops/__tests__/{runner.integration.ts → runner.integration.test.ts} +25 -23
  190. package/src/es-ops/__tests__/runner.test.ts +29 -19
  191. package/src/es-ops/context.ts +9 -43
  192. package/src/es-ops/operations-schema.ts +2 -2
  193. package/src/es-ops/runner.ts +12 -26
  194. package/src/event-store/__tests__/{admin-api.integration.ts → admin-api.integration.test.ts} +71 -45
  195. package/src/event-store/__tests__/{event-store.integration.ts → event-store.integration.test.ts} +7 -5
  196. package/src/event-store/__tests__/{get-stream-version-perf.integration.ts → get-stream-version-perf.integration.test.ts} +5 -3
  197. package/src/event-store/__tests__/{perf.integration.ts → perf.integration.test.ts} +24 -16
  198. package/src/event-store/__tests__/{snapshot.integration.ts → snapshot.integration.test.ts} +34 -28
  199. package/src/event-store/__tests__/{upcaster-dead-letter.integration.ts → upcaster-dead-letter.integration.test.ts} +11 -12
  200. package/src/event-store/__tests__/{upcaster.integration.ts → upcaster.integration.test.ts} +19 -32
  201. package/src/event-store/admin-api.ts +55 -83
  202. package/src/event-store/archive.ts +15 -39
  203. package/src/event-store/event-store.ts +92 -86
  204. package/src/event-store/events-schema.ts +2 -1
  205. package/src/event-store/index.ts +1 -0
  206. package/src/event-store/snapshot.ts +26 -24
  207. package/src/event-store/upcaster-dead-letter.ts +19 -18
  208. package/src/files/__tests__/content-disposition.test.ts +1 -1
  209. package/src/files/__tests__/{file-field-pipeline.integration.ts → file-field-pipeline.integration.test.ts} +8 -5
  210. package/src/files/__tests__/file-handle.test.ts +1 -1
  211. package/src/files/__tests__/{files.integration.ts → files.integration.test.ts} +32 -17
  212. package/src/files/__tests__/read-stream.test.ts +1 -1
  213. package/src/files/__tests__/{storage-tracking.integration.ts → storage-tracking.integration.test.ts} +26 -30
  214. package/src/files/__tests__/write-stream.test.ts +1 -1
  215. package/src/files/__tests__/zip-stream.test.ts +1 -1
  216. package/src/files/file-ref-table.ts +2 -2
  217. package/src/files/file-routes.ts +7 -9
  218. package/src/files/storage-tracking.ts +9 -17
  219. package/src/i18n/__tests__/i18n.test.ts +1 -1
  220. package/src/jobs/__tests__/{job-event-trigger.integration.ts → job-event-trigger.integration.test.ts} +6 -3
  221. package/src/jobs/__tests__/{job-multi-trigger.integration.ts → job-multi-trigger.integration.test.ts} +6 -3
  222. package/src/jobs/__tests__/{jobs.integration.ts → jobs.integration.test.ts} +5 -7
  223. package/src/lifecycle/__tests__/{lifecycle-server.integration.ts → lifecycle-server.integration.test.ts} +1 -1
  224. package/src/lifecycle/__tests__/lifecycle.test.ts +6 -6
  225. package/src/lifecycle/__tests__/signal-handlers.test.ts +6 -6
  226. package/src/logging/__tests__/pino-trace-bridge.test.ts +1 -1
  227. package/src/migrations/__tests__/compare-snapshots.test.ts +1 -1
  228. package/src/migrations/__tests__/{detect-drift.integration.ts → detect-drift.integration.test.ts} +34 -26
  229. package/src/migrations/__tests__/{detect-projections-to-rebuild.integration.ts → detect-projections-to-rebuild.integration.test.ts} +1 -1
  230. package/src/migrations/__tests__/rebuild-marker.test.ts +1 -1
  231. package/src/migrations/projection-detection.ts +12 -1
  232. package/src/migrations/schema-drift.ts +7 -23
  233. package/src/observability/__tests__/console-provider.test.ts +1 -1
  234. package/src/observability/__tests__/metric-validator.test.ts +1 -1
  235. package/src/observability/__tests__/noop-provider.test.ts +1 -1
  236. package/src/observability/__tests__/{observability.integration.ts → observability.integration.test.ts} +5 -8
  237. package/src/observability/__tests__/prometheus-meter.test.ts +1 -1
  238. package/src/observability/__tests__/recording-meter.test.ts +1 -1
  239. package/src/observability/__tests__/recording-tracer.test.ts +1 -1
  240. package/src/observability/__tests__/sensitive-filter.test.ts +1 -1
  241. package/src/pipeline/__tests__/{archive-stream.integration.ts → archive-stream.integration.test.ts} +3 -3
  242. package/src/pipeline/__tests__/auth-claims-resolver.test.ts +9 -9
  243. package/src/pipeline/__tests__/{cascade-handler.integration.ts → cascade-handler.integration.test.ts} +18 -15
  244. package/src/pipeline/__tests__/cascade-handler.test.ts +1 -1
  245. package/src/pipeline/__tests__/{causation-chain.integration.ts → causation-chain.integration.test.ts} +12 -13
  246. package/src/pipeline/__tests__/{ctx-bridge.integration.ts → ctx-bridge.integration.test.ts} +12 -11
  247. package/src/pipeline/__tests__/dispatcher.test.ts +2 -2
  248. package/src/pipeline/__tests__/{distributed-lock.integration.ts → distributed-lock.integration.test.ts} +1 -1
  249. package/src/pipeline/__tests__/{domain-events-projections.integration.ts → domain-events-projections.integration.test.ts} +13 -15
  250. package/src/pipeline/__tests__/{event-dedup.integration.ts → event-dedup.integration.test.ts} +1 -1
  251. package/src/pipeline/__tests__/{event-define-event-strict.integration.ts → event-define-event-strict.integration.test.ts} +6 -16
  252. package/src/pipeline/__tests__/{event-dispatcher-lifecycle.integration.ts → event-dispatcher-lifecycle.integration.test.ts} +1 -1
  253. package/src/pipeline/__tests__/{event-dispatcher-multi-instance.integration.ts → event-dispatcher-multi-instance.integration.test.ts} +3 -2
  254. package/src/pipeline/__tests__/{event-dispatcher-pg-listen.integration.ts → event-dispatcher-pg-listen.integration.test.ts} +1 -1
  255. package/src/pipeline/__tests__/{event-dispatcher-recovery.integration.ts → event-dispatcher-recovery.integration.test.ts} +2 -2
  256. package/src/pipeline/__tests__/{event-dispatcher-second-audit.integration.ts → event-dispatcher-second-audit.integration.test.ts} +17 -16
  257. package/src/pipeline/__tests__/event-dispatcher-strict.test.ts +14 -12
  258. package/src/pipeline/__tests__/{event-dispatcher.integration.ts → event-dispatcher.integration.test.ts} +8 -15
  259. package/src/pipeline/__tests__/{event-retention.integration.ts → event-retention.integration.test.ts} +28 -25
  260. package/src/pipeline/__tests__/{fetch-for-writing.integration.ts → fetch-for-writing.integration.test.ts} +6 -6
  261. package/src/pipeline/__tests__/lifecycle-pipeline.test.ts +4 -4
  262. package/src/pipeline/__tests__/{load-aggregate-query.integration.ts → load-aggregate-query.integration.test.ts} +9 -5
  263. package/src/pipeline/__tests__/{msp-error-mode.integration.ts → msp-error-mode.integration.test.ts} +1 -1
  264. package/src/pipeline/__tests__/{msp-multi-hop.integration.ts → msp-multi-hop.integration.test.ts} +9 -8
  265. package/src/pipeline/__tests__/{msp-rebuild.integration.ts → msp-rebuild.integration.test.ts} +47 -55
  266. package/src/pipeline/__tests__/{multi-stream-projection.integration.ts → multi-stream-projection.integration.test.ts} +19 -53
  267. package/src/pipeline/__tests__/{perf-rebuild.integration.ts → perf-rebuild.integration.test.ts} +36 -34
  268. package/src/pipeline/__tests__/{post-query-hook.integration.ts → post-query-hook.integration.test.ts} +1 -1
  269. package/src/pipeline/__tests__/{projection-rebuild.integration.ts → projection-rebuild.integration.test.ts} +21 -30
  270. package/src/pipeline/__tests__/{query-projection.integration.ts → query-projection.integration.test.ts} +6 -5
  271. package/src/pipeline/__tests__/{redis-pipeline.integration.ts → redis-pipeline.integration.test.ts} +3 -1
  272. package/src/pipeline/cascade-handler.ts +13 -21
  273. package/src/pipeline/dispatcher.ts +43 -48
  274. package/src/pipeline/event-consumer-state.ts +11 -2
  275. package/src/pipeline/event-dispatcher.ts +86 -146
  276. package/src/pipeline/event-retention.ts +14 -24
  277. package/src/pipeline/msp-rebuild.ts +54 -78
  278. package/src/pipeline/projection-rebuild.ts +65 -67
  279. package/src/pipeline/projection-state.ts +2 -2
  280. package/src/random/__tests__/generate.test.ts +13 -13
  281. package/src/rate-limit/__tests__/{dispatcher-l3.integration.ts → dispatcher-l3.integration.test.ts} +1 -1
  282. package/src/rate-limit/__tests__/{middleware.integration.ts → middleware.integration.test.ts} +1 -1
  283. package/src/rate-limit/__tests__/{resolver.integration.ts → resolver.integration.test.ts} +1 -1
  284. package/src/redis/__tests__/redis-options.test.ts +1 -1
  285. package/src/search/__tests__/{meilisearch-adapter.integration.ts → meilisearch-adapter.integration.test.ts} +1 -1
  286. package/src/search/__tests__/search-adapter.test.ts +1 -1
  287. package/src/secrets/__tests__/dek-cache.test.ts +1 -3
  288. package/src/secrets/__tests__/env-master-key-provider.test.ts +1 -1
  289. package/src/secrets/__tests__/envelope.test.ts +1 -1
  290. package/src/secrets/__tests__/leak-guard.test.ts +1 -1
  291. package/src/secrets/__tests__/rotation.test.ts +1 -1
  292. package/src/stack/db.ts +25 -48
  293. package/src/stack/push-entity-projection-tables.ts +2 -4
  294. package/src/stack/table-helpers.ts +98 -61
  295. package/src/stack/test-stack.ts +8 -7
  296. package/src/testing/__tests__/db-cleanup.test.ts +40 -0
  297. package/src/testing/__tests__/e2e-generator.test.ts +1 -1
  298. package/src/testing/__tests__/{ensure-entity-table.integration.ts → ensure-entity-table.integration.test.ts} +7 -14
  299. package/src/testing/db-cleanup.ts +44 -0
  300. package/src/testing/expect-error.ts +1 -1
  301. package/src/testing/index.ts +2 -0
  302. package/src/testing/multipart-helper.ts +94 -0
  303. package/src/testing/shared-entities.ts +5 -5
  304. package/src/time/__tests__/polyfill.test.ts +1 -1
  305. package/src/time/__tests__/tz-context.test.ts +1 -1
  306. package/src/utils/__tests__/assert.test.ts +1 -1
  307. package/src/utils/__tests__/env-parse.test.ts +1 -1
  308. package/CHANGELOG.md +0 -474
  309. package/src/db/__tests__/cursor.test.ts +0 -41
  310. package/src/db/__tests__/db-helpers.test.ts +0 -369
  311. package/src/db/__tests__/drizzle-helpers.integration.ts +0 -186
  312. package/src/db/__tests__/row-helpers.test.ts +0 -59
  313. package/src/engine/steps/_drizzle-boundary.ts +0 -19
  314. package/src/files/__tests__/file-field-column.integration.ts +0 -103
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-framework",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "Framework core — engine, pipeline, API, DB, and every other bit that makes Kumiko go.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -20,7 +20,6 @@
20
20
  "command-based",
21
21
  "typescript",
22
22
  "hono",
23
- "drizzle",
24
23
  "zod"
25
24
  ],
26
25
  "type": "module",
@@ -60,6 +59,10 @@
60
59
  "types": "./src/errors/index.ts",
61
60
  "default": "./src/errors/index.ts"
62
61
  },
62
+ "./bun-db": {
63
+ "types": "./src/bun-db/index.ts",
64
+ "default": "./src/bun-db/index.ts"
65
+ },
63
66
  "./db": {
64
67
  "types": "./src/db/index.ts",
65
68
  "default": "./src/db/index.ts"
@@ -157,8 +160,6 @@
157
160
  "dependencies": {
158
161
  "bullmq": "^5.76.7",
159
162
  "bun-types": "^1.3.13",
160
- "drizzle-kit": "^0.31.10",
161
- "drizzle-orm": "^0.45.2",
162
163
  "hono": "^4.12.18",
163
164
  "i18next": "^26.1.0",
164
165
  "ioredis": "^5.10.1",
@@ -175,7 +176,6 @@
175
176
  "@cosmicdrift/kumiko-dispatcher-live": "0.14.0",
176
177
  "@types/uuid": "^11.0.0",
177
178
  "bun-types": "^1.3.13",
178
- "drizzle-kit": "^0.31.10",
179
179
  "pino-pretty": "^13.1.3"
180
180
  },
181
181
  "publishConfig": {
@@ -187,4 +187,4 @@
187
187
  "README.md",
188
188
  "LICENSE"
189
189
  ]
190
- }
190
+ }
@@ -3,11 +3,14 @@
3
3
  // authentication. Covers the resolution chain (defaultTenantId, X-Tenant
4
4
  // header, kumiko_tenant cookie, custom resolver) plus the rejection paths
5
5
  // (no tenant, unknown tenant, openToAll-protected).
6
+ //
7
+ // Bun.SQL-only setup. KEIN postgres-js, KEIN setupTestStack.
6
8
 
7
- import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
9
+ import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
8
10
  import { z } from "zod";
9
11
  import { createEventStoreExecutor } from "../db/event-store-executor";
10
- import { buildDrizzleTable } from "../db/table-builder";
12
+ import { asRawClient, selectMany } from "../db/query";
13
+ import { buildEntityTable } from "../db/table-builder";
11
14
  import {
12
15
  ANONYMOUS_USER_ID,
13
16
  createEntity,
@@ -28,7 +31,7 @@ const productEntity = createEntity({
28
31
  name: createTextField({ required: true }),
29
32
  },
30
33
  });
31
- const productTable = buildDrizzleTable("product", productEntity);
34
+ const productTable = buildEntityTable("product", productEntity);
32
35
 
33
36
  const orderEntity = createEntity({
34
37
  table: "anon_orders",
@@ -37,7 +40,7 @@ const orderEntity = createEntity({
37
40
  placedBy: createTextField({ default: "" }),
38
41
  },
39
42
  });
40
- const orderTable = buildDrizzleTable("order", orderEntity);
43
+ const orderTable = buildEntityTable("order", orderEntity);
41
44
 
42
45
  const shopFeature = defineFeature("anonshop", (r) => {
43
46
  r.entity("product", productEntity);
@@ -48,7 +51,7 @@ const shopFeature = defineFeature("anonshop", (r) => {
48
51
  "product:list",
49
52
  z.object({}),
50
53
  async (_event, ctx) => {
51
- const rows = await ctx.db.select().from(productTable);
54
+ const rows = await selectMany(ctx.db, productTable);
52
55
  return rows;
53
56
  },
54
57
  { access: { roles: ["anonymous", "User", "Admin"] } },
@@ -59,7 +62,7 @@ const shopFeature = defineFeature("anonshop", (r) => {
59
62
  "product:list-auth-only",
60
63
  z.object({}),
61
64
  async (_event, ctx) => {
62
- const rows = await ctx.db.select().from(productTable);
65
+ const rows = await selectMany(ctx.db, productTable);
63
66
  return rows;
64
67
  },
65
68
  { access: { openToAll: true } },
@@ -111,8 +114,8 @@ describe("anonymous access — single-tenant default", () => {
111
114
  afterAll(() => stack.cleanup());
112
115
 
113
116
  beforeEach(async () => {
114
- await stack.db.delete(productTable);
115
- await stack.db.delete(orderTable);
117
+ await asRawClient(stack.db).unsafe(`DELETE FROM "${productTable.tableName}"`);
118
+ await asRawClient(stack.db).unsafe(`DELETE FROM "${orderTable.tableName}"`);
116
119
  });
117
120
 
118
121
  test("anonymous query succeeds without any auth headers", async () => {
@@ -146,7 +149,7 @@ describe("anonymous access — single-tenant default", () => {
146
149
 
147
150
  // Verify the row landed with placedBy=anonymous in the DB. Confirms the
148
151
  // synthesised SessionUser actually flows through to the handler.
149
- const rows = await stack.db.select().from(orderTable);
152
+ const rows = await selectMany(stack.db, orderTable);
150
153
  expect(rows).toHaveLength(1);
151
154
  expect(rows[0]?.["placedBy"]).toBe(ANONYMOUS_USER_ID);
152
155
  });
@@ -3,10 +3,11 @@
3
3
  // come back with a stable code + i18nKey and the shape that the client SDK
4
4
  // and docs promise. If you change the contract, this is the file that moves.
5
5
 
6
- import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
6
+ import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
7
7
  import { z } from "zod";
8
8
  import { createEventStoreExecutor } from "../db/event-store-executor";
9
- import { buildDrizzleTable } from "../db/table-builder";
9
+ import { asRawClient } from "../db/query";
10
+ import { buildEntityTable } from "../db/table-builder";
10
11
  import {
11
12
  createEntity,
12
13
  createNumberField,
@@ -38,7 +39,7 @@ const itemEntity = createEntity({
38
39
  stock: createNumberField({ default: 0 }),
39
40
  },
40
41
  });
41
- const itemTable = buildDrizzleTable("item", itemEntity);
42
+ const itemTable = buildEntityTable("item", itemEntity);
42
43
 
43
44
  const errorFeature = defineFeature("errctr", (r) => {
44
45
  r.entity("item", itemEntity);
@@ -192,7 +193,7 @@ beforeAll(async () => {
192
193
  afterAll(async () => stack.cleanup());
193
194
  beforeEach(async () => {
194
195
  stack.events.reset();
195
- await stack.db.delete(itemTable);
196
+ await asRawClient(stack.db).unsafe(`DELETE FROM "${itemTable.tableName}"`);
196
197
  });
197
198
 
198
199
  // --- Helpers ---
@@ -1,8 +1,8 @@
1
- import { afterAll, beforeAll, describe, expect, test } from "vitest";
1
+ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
2
2
  import { z } from "zod";
3
3
  import { buildServer } from "../api/server";
4
4
  import { createEventStoreExecutor } from "../db/event-store-executor";
5
- import { buildDrizzleTable } from "../db/table-builder";
5
+ import { buildEntityTable } from "../db/table-builder";
6
6
  import {
7
7
  createEntity,
8
8
  createNumberField,
@@ -33,7 +33,7 @@ const employeeEntity = createEntity({
33
33
  },
34
34
  });
35
35
 
36
- const employeeTable = buildDrizzleTable("employee", employeeEntity);
36
+ const employeeTable = buildEntityTable("employee", employeeEntity);
37
37
 
38
38
  // --- Test infra ---
39
39
 
@@ -1,6 +1,7 @@
1
- import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
1
+ import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
2
2
  import { z } from "zod";
3
3
  import { createEventStoreExecutor } from "../db/event-store-executor";
4
+ import { selectMany, updateMany } from "../db/query";
4
5
  import { defineFeature, type EntityId, type HandlerContext, type SaveContext } from "../engine";
5
6
  import { UnprocessableError, writeFailure } from "../errors";
6
7
  import { eventsTable } from "../event-store";
@@ -714,11 +715,7 @@ describe("full stack: entity cache", () => {
714
715
  await stack.http.queryOk("users:query:user:detail", { id }, adminUser);
715
716
 
716
717
  // Raw DB update — bypasses cache invalidation
717
- const { eq } = await import("drizzle-orm");
718
- await stack.db
719
- .update(userTable)
720
- .set({ firstName: "RawDbChange" })
721
- .where(eq(userTable["id"], id));
718
+ await updateMany(stack.db, userTable, { firstName: "RawDbChange" }, { id: id });
722
719
 
723
720
  // Detail still returns cached (old) value
724
721
  const stale = await stack.http.queryOk<Record<string, unknown>>(
@@ -789,16 +786,10 @@ describe("full stack: ctx.appendEvent via event-dispatcher", () => {
789
786
  // events table is shared across tests so we pick out just the ones this
790
787
  // test appended.
791
788
  async function domainEventsForEmail(email: string) {
792
- const rows = await stack.db
793
- .select()
794
- .from(eventsTable)
795
- .where(
796
- // eq + and via a lazy dynamic import keeps the top-level imports lean.
797
- (await import("drizzle-orm")).and(
798
- (await import("drizzle-orm")).eq(eventsTable.aggregateType, "user"),
799
- (await import("drizzle-orm")).eq(eventsTable.type, USER_CREATED_EVENT),
800
- ),
801
- );
789
+ const rows = await selectMany(stack.db, eventsTable, {
790
+ aggregateType: "user",
791
+ type: USER_CREATED_EVENT,
792
+ });
802
793
  return rows.filter((r) => (r.payload as { email?: string }).email === email);
803
794
  }
804
795
 
@@ -4,7 +4,8 @@
4
4
  // entity-write, field-level) into one file with shared fixtures. Each
5
5
  // `describe` block maps to a cell of the core-auth.md Policy-Matrix.
6
6
 
7
- import { afterAll, beforeAll, beforeEach, describe, expect, test } from "vitest";
7
+ import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
8
+ import { asRawClient } from "../db/query";
8
9
  import {
9
10
  createEntity,
10
11
  createTextField,
@@ -134,7 +135,7 @@ let engRow: { id: string; version: number };
134
135
  let opsRow: { id: string; version: number };
135
136
 
136
137
  beforeEach(async () => {
137
- await stack.db.execute("DELETE FROM h2_contracts");
138
+ await asRawClient(stack.db).unsafe("DELETE FROM h2_contracts");
138
139
  const eng = await stack.http.writeOk<{ id: string; data: { version: number } }>(
139
140
  "h2contracts:write:contract:create",
140
141
  {
@@ -3,9 +3,9 @@
3
3
  // INSERT/SELECT against the real DB roundtrip. Plan reference:
4
4
  // kumiko-platform/docs/plans/architecture/table-ddl-guard.md (Stufe 3).
5
5
 
6
- import { eq, sql } from "drizzle-orm";
7
- import { pgTable, text, timestamp } from "drizzle-orm/pg-core";
8
- import { afterAll, beforeAll, describe, expect, test } from "vitest";
6
+ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
7
+ import { table, text, timestamp } from "../db/dialect";
8
+ import { asRawClient, insertOne, selectMany } from "../db/query";
9
9
  import { defineFeature } from "../engine";
10
10
  import { setupTestStack, type TestStack, unsafePushTables } from "../stack";
11
11
 
@@ -13,7 +13,7 @@ import { setupTestStack, type TestStack, unsafePushTables } from "../stack";
13
13
  // write-only by an integration handler, read-only by a query, never
14
14
  // event-sourced (the data isn't a domain fact, it's a side-effect
15
15
  // snapshot).
16
- const stripeWebhookCache = pgTable("rt_int_stripe_webhook_cache", {
16
+ const stripeWebhookCache = table("rt_int_stripe_webhook_cache", {
17
17
  eventId: text("event_id").primaryKey(),
18
18
  payload: text("payload").notNull(),
19
19
  receivedAt: timestamp("received_at", { withTimezone: true }).notNull().defaultNow(),
@@ -22,7 +22,7 @@ const stripeWebhookCache = pgTable("rt_int_stripe_webhook_cache", {
22
22
  // A second physical table reachable through two distinct r.rawTable
23
23
  // registrations — pins the seenTables-by-reference dedupe at push time.
24
24
  // Two logical names, one CREATE.
25
- const sharedSyncCache = pgTable("rt_int_shared_sync_cache", {
25
+ const sharedSyncCache = table("rt_int_shared_sync_cache", {
26
26
  syncId: text("sync_id").primaryKey(),
27
27
  payload: text("payload").notNull(),
28
28
  });
@@ -54,16 +54,13 @@ describe("r.rawTable — DB roundtrip via setupTestStack", () => {
54
54
  const eventId = "evt_test_123";
55
55
  const payload = JSON.stringify({ type: "invoice.paid", amount: 4200 });
56
56
 
57
- await stack.db.insert(stripeWebhookCache).values({ eventId, payload });
57
+ await insertOne(stack.db, stripeWebhookCache, { eventId, payload });
58
58
 
59
- const rows = await stack.db
60
- .select()
61
- .from(stripeWebhookCache)
62
- .where(eq(stripeWebhookCache.eventId, eventId));
59
+ const rows = await selectMany(stack.db, stripeWebhookCache, { eventId: eventId });
63
60
 
64
61
  expect(rows).toHaveLength(1);
65
62
  expect(rows[0]?.payload).toBe(payload);
66
- expect(rows[0]?.receivedAt).toBeInstanceOf(Date);
63
+ expect(rows[0]?.receivedAt).toBeInstanceOf(Temporal.Instant);
67
64
  });
68
65
 
69
66
  test("registry exposes the raw table with its reason and featureName", () => {
@@ -80,18 +77,18 @@ describe("r.rawTable — DB roundtrip via setupTestStack", () => {
80
77
  // a write to it shouldn't append anything to kumiko_events. If a
81
78
  // future regression accidentally routed raw-table writes through
82
79
  // the executor, a row would show up here.
83
- const before = await stack.db.execute<{ count: string }>(
84
- sql`SELECT COUNT(*)::text AS count FROM kumiko_events`,
80
+ const before = await asRawClient(stack.db).unsafe<{ count: string }>(
81
+ `SELECT COUNT(*)::text AS count FROM kumiko_events`,
85
82
  );
86
83
  const beforeCount = Number(before[0]?.count ?? 0);
87
84
 
88
- await stack.db.insert(stripeWebhookCache).values({
85
+ await insertOne(stack.db, stripeWebhookCache, {
89
86
  eventId: "evt_no_event_emitted",
90
87
  payload: "{}",
91
88
  });
92
89
 
93
- const after = await stack.db.execute<{ count: string }>(
94
- sql`SELECT COUNT(*)::text AS count FROM kumiko_events`,
90
+ const after = await asRawClient(stack.db).unsafe<{ count: string }>(
91
+ `SELECT COUNT(*)::text AS count FROM kumiko_events`,
95
92
  );
96
93
  const afterCount = Number(after[0]?.count ?? 0);
97
94
 
@@ -103,11 +100,8 @@ describe("r.rawTable — DB roundtrip via setupTestStack", () => {
103
100
  // setupTestStack dedupe (seenTables-by-table-reference) had silently
104
101
  // broken, beforeAll's setupTestStack would have raised a 42P07 on
105
102
  // the second push and never reached this test.
106
- await stack.db.insert(sharedSyncCache).values({ syncId: "sync_1", payload: "{}" });
107
- const rows = await stack.db
108
- .select()
109
- .from(sharedSyncCache)
110
- .where(eq(sharedSyncCache.syncId, "sync_1"));
103
+ await insertOne(stack.db, sharedSyncCache, { syncId: "sync_1", payload: "{}" });
104
+ const rows = await selectMany(stack.db, sharedSyncCache, { syncId: "sync_1" });
111
105
  expect(rows).toHaveLength(1);
112
106
  // Both registrations are visible in the registry — same physical
113
107
  // target, different logical handles.
@@ -115,14 +109,8 @@ describe("r.rawTable — DB roundtrip via setupTestStack", () => {
115
109
  expect(stack.registry.getAllRawTables().get("secondary-sync")?.table).toBe(sharedSyncCache);
116
110
  });
117
111
 
118
- test("a second push on the same rawTable would crashproves tableExists-filter is load-bearing", async () => {
119
- // The setupTestStack push is idempotent because it filters by
120
- // tableExists before calling unsafePushTables (which is itself
121
- // strict — that's the contract of the unsafe-prefix). Pin the
122
- // failure mode of the unfiltered call: a direct second push on
123
- // the same Drizzle schema raises the underlying PG error. This
124
- // is the negative form of the idempotency contract — without the
125
- // filter, a re-boot against a persistent dev DB would crash here.
126
- await expect(unsafePushTables(stack.db, { idem: stripeWebhookCache })).rejects.toThrow();
112
+ test("a second push on the same rawTable is idempotentCREATE IF NOT EXISTS", async () => {
113
+ // unsafePushTables uses CREATE TABLE IF NOT EXISTS idempotent by design.
114
+ await expect(unsafePushTables(stack.db, { idem: stripeWebhookCache })).resolves.toBeUndefined();
127
115
  });
128
116
  });
@@ -1,8 +1,11 @@
1
- import { afterAll, beforeAll, describe, expect, test } from "vitest";
1
+ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
2
+ import { type BunTestDb, createTestDb } from "../bun-db/__tests__/bun-test-db";
2
3
  import { integer, table as pgTable, serial, text } from "../db/dialect";
4
+ import { selectMany } from "../db/query";
3
5
  import { seedReferenceData } from "../db/reference-data";
4
6
  import type { ReferenceDataDef } from "../engine/types";
5
- import { createTestDb, type TestDb, unsafePushTables } from "../stack";
7
+ import { unsafePushTables } from "../stack";
8
+ import { ensureTemporalPolyfill } from "../time/polyfill";
6
9
 
7
10
  // --- Tables ---
8
11
 
@@ -21,9 +24,10 @@ const statusTable = pgTable("ref_statuses", {
21
24
 
22
25
  // --- Test state ---
23
26
 
24
- let testDb: TestDb;
27
+ let testDb: BunTestDb;
25
28
 
26
29
  beforeAll(async () => {
30
+ await ensureTemporalPolyfill();
27
31
  testDb = await createTestDb();
28
32
  await unsafePushTables(testDb.db, { countryTable, statusTable });
29
33
  });
@@ -34,13 +38,13 @@ afterAll(async () => {
34
38
 
35
39
  // Helper: read all rows from a table
36
40
  async function readCountries() {
37
- const rows = await testDb.db.select().from(countryTable);
38
- return rows.sort((a, b) => a.code.localeCompare(b.code));
41
+ const rows = await selectMany(testDb.db, countryTable);
42
+ return rows.toSorted((a, b) => a.code.localeCompare(b.code));
39
43
  }
40
44
 
41
45
  async function readStatuses() {
42
- const rows = await testDb.db.select().from(statusTable);
43
- return rows.sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0));
46
+ const rows = await selectMany(testDb.db, statusTable);
47
+ return rows.toSorted((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0));
44
48
  }
45
49
 
46
50
  describe("seedReferenceData", () => {
@@ -132,7 +136,10 @@ describe("seedReferenceData", () => {
132
136
 
133
137
  const rows = await readCountries();
134
138
  expect(rows).toHaveLength(4);
135
- expect(rows.find((r) => r.code === "CH")).toMatchObject({ name: "Schweiz", region: "Europe" });
139
+ expect(rows.find((r: Record<string, unknown>) => r["code"] === "CH")).toMatchObject({
140
+ name: "Schweiz",
141
+ region: "Europe",
142
+ });
136
143
  });
137
144
 
138
145
  test("custom upsertKey — matches on specified field instead of first", async () => {
@@ -167,9 +174,15 @@ describe("seedReferenceData", () => {
167
174
  expect(updateResult).toEqual({ inserted: 0, updated: 1 });
168
175
 
169
176
  const rows = await readStatuses();
170
- expect(rows.find((r) => r.slug === "draft")).toMatchObject({ label: "Entwurf" });
171
- expect(rows.find((r) => r.slug === "active")).toMatchObject({ label: "Active" });
172
- expect(rows.find((r) => r.slug === "archived")).toMatchObject({ label: "Archived" });
177
+ expect(rows.find((r: Record<string, unknown>) => r["slug"] === "draft")).toMatchObject({
178
+ label: "Entwurf",
179
+ });
180
+ expect(rows.find((r: Record<string, unknown>) => r["slug"] === "active")).toMatchObject({
181
+ label: "Active",
182
+ });
183
+ expect(rows.find((r: Record<string, unknown>) => r["slug"] === "archived")).toMatchObject({
184
+ label: "Archived",
185
+ });
173
186
  });
174
187
 
175
188
  test("skips unknown entity names gracefully", async () => {
@@ -1,7 +1,8 @@
1
- import { afterAll, beforeAll, describe, expect, test } from "vitest";
1
+ import { afterAll, beforeAll, describe, expect, test } from "bun:test";
2
2
  import { z } from "zod";
3
3
  import { createEventStoreExecutor } from "../db/event-store-executor";
4
- import { buildDrizzleTable } from "../db/table-builder";
4
+ import { updateMany } from "../db/query";
5
+ import { buildEntityTable } from "../db/table-builder";
5
6
  import {
6
7
  createBooleanField,
7
8
  createEntity,
@@ -67,9 +68,9 @@ const ticketEntity = createEntity({
67
68
  },
68
69
  });
69
70
 
70
- const invoiceTable = buildDrizzleTable("invoice", invoiceEntity);
71
- const orderTable = buildDrizzleTable("order", orderEntity);
72
- const ticketTable = buildDrizzleTable("ticket", ticketEntity);
71
+ const invoiceTable = buildEntityTable("invoice", invoiceEntity);
72
+ const orderTable = buildEntityTable("order", orderEntity);
73
+ const ticketTable = buildEntityTable("ticket", ticketEntity);
73
74
 
74
75
  const feature = defineFeature("txguard", (r) => {
75
76
  r.entity("invoice", invoiceEntity);
@@ -267,11 +268,12 @@ describe("auto transition guard: per-entity transition map (cache key includes e
267
268
  // Raw-DB-mark-deleted — we need a soft-deleted row whose status is a
268
269
  // terminal state. If the guard fired, any status write would throw
269
270
  // "Invalid transition: closed → <x>". We want it silently skipped.
270
- const { eq } = await import("drizzle-orm");
271
- await stack.db
272
- .update(ticketTable)
273
- .set({ status: "closed", isDeleted: true })
274
- .where(eq(ticketTable["id"], ticket["id"]));
271
+ await updateMany(
272
+ stack.db,
273
+ ticketTable,
274
+ { status: "closed", isDeleted: true },
275
+ { id: ticket["id"] },
276
+ );
275
277
 
276
278
  // Attempting to move a deleted ticket to "open" would normally violate
277
279
  // "closed → []" (no allowed targets). With the softDelete skip, the
@@ -1,4 +1,4 @@
1
- import { describe, expect, test } from "vitest";
1
+ import { describe, expect, test } from "bun:test";
2
2
  import { z } from "zod";
3
3
  import {
4
4
  createEntity,
@@ -2,8 +2,8 @@
2
2
  // against a hand-rolled Hono app — no DB, no dispatcher. Exercises the
3
3
  // transport-extraction path that drives the csrf-middleware downstream.
4
4
 
5
+ import { describe, expect, test } from "bun:test";
5
6
  import { Hono } from "hono";
6
- import { describe, expect, test } from "vitest";
7
7
  import { TestUsers } from "../../stack";
8
8
  import { AUTH_COOKIE_NAME, authMiddleware, getAuthTransport, getUser } from "../auth-middleware";
9
9
  import { createJwtHelper } from "../jwt";
@@ -5,9 +5,9 @@
5
5
  // logic — full-stack login via real loginHandler is covered by the
6
6
  // auth-cookie sample integration test.
7
7
 
8
+ import { describe, expect, test } from "bun:test";
8
9
  import type { Hono } from "hono";
9
10
  import { Hono as HonoCtor } from "hono";
10
- import { describe, expect, test } from "vitest";
11
11
  import type { SessionUser } from "../../engine/types";
12
12
  import type { BatchResult, Dispatcher, WriteResult } from "../../pipeline/dispatcher";
13
13
  import { TestUsers } from "../../stack";