okengine 0.2.6 → 0.2.8

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 (584) hide show
  1. package/AGENTS.md +24 -23
  2. package/README.md +52 -346
  3. package/docs/spec/console.md +165 -142
  4. package/docs/spec/example.md +490 -312
  5. package/docs/spec/four-applications.md +495 -314
  6. package/docs/spec/unified-theory.md +184 -175
  7. package/package.json +45 -37
  8. package/spec/manifest.v1.schema.json +40 -9
  9. package/src/auth/api-keys.ts +2 -5
  10. package/src/auth/attenuation.ts +2 -6
  11. package/src/auth/auth.test.ts +53 -31
  12. package/src/auth/invoke-as.ts +1 -3
  13. package/src/auth/operator.ts +8 -26
  14. package/src/auth/planes.ts +2 -7
  15. package/src/auth/plugin.ts +4 -7
  16. package/src/auth/roles.ts +1 -5
  17. package/src/auth/sessions.ts +10 -39
  18. package/src/cli/args.ts +1 -5
  19. package/src/cli/ask-dev-mode.ts +40 -0
  20. package/src/cli/build.ts +1 -2
  21. package/src/cli/client-add.test.ts +8 -15
  22. package/src/cli/client-add.ts +5 -14
  23. package/src/cli/completion.test.ts +1 -5
  24. package/src/cli/completion.ts +4 -17
  25. package/src/cli/db-auto-push.test.ts +64 -0
  26. package/src/cli/db-auto-push.ts +72 -0
  27. package/src/cli/db.test.ts +189 -0
  28. package/src/cli/db.ts +386 -0
  29. package/src/cli/dev-app-runner.ts +2 -8
  30. package/src/cli/dev-db-push.test.ts +163 -0
  31. package/src/cli/dev-mode.test.ts +45 -0
  32. package/src/cli/dev-mode.ts +78 -0
  33. package/src/cli/dev.test.ts +148 -21
  34. package/src/cli/dev.ts +208 -134
  35. package/src/cli/doc-drift.test.ts +3 -2
  36. package/src/cli/doc-drift.ts +21 -50
  37. package/src/cli/doc-staleness.test.ts +69 -0
  38. package/src/cli/docker-cli.test.ts +7 -8
  39. package/src/cli/docker.ts +1 -3
  40. package/src/cli/doctor-diff-examples.ts +1 -3
  41. package/src/cli/doctor-diff.test.ts +1 -5
  42. package/src/cli/doctor-diff.ts +17 -46
  43. package/src/cli/doctor-pii.ts +2 -7
  44. package/src/cli/doctor.test.ts +26 -4
  45. package/src/cli/doctor.ts +35 -11
  46. package/src/cli/eval.ts +4 -14
  47. package/src/cli/gates-list.ts +1 -4
  48. package/src/cli/hero-meta.test.ts +17 -19
  49. package/src/cli/hero-meta.ts +20 -30
  50. package/src/cli/images.ts +3 -8
  51. package/src/cli/index.ts +11 -2
  52. package/src/cli/load-config.images.test.ts +14 -14
  53. package/src/cli/load-config.ts +41 -47
  54. package/src/cli/mcp-from-console.ts +1 -4
  55. package/src/cli/mode.ts +45 -0
  56. package/src/cli/ports.test.ts +4 -13
  57. package/src/cli/ports.ts +1 -3
  58. package/src/cli/privacy-erase.ts +1 -3
  59. package/src/cli/registry.ts +75 -25
  60. package/src/cli/schema.ts +3 -10
  61. package/src/cli/stack.ts +2 -7
  62. package/src/cli/start.ts +4 -15
  63. package/src/cli/upgrade.ts +1 -4
  64. package/src/client/budget-entry.ts +1 -6
  65. package/src/client/create.test.ts +6 -12
  66. package/src/client/create.ts +2 -8
  67. package/src/client/errors.ts +1 -4
  68. package/src/client/index.ts +1 -6
  69. package/src/client/notes-contract.test.ts +4 -13
  70. package/src/client/transport.ts +9 -30
  71. package/src/client/types.ts +8 -29
  72. package/src/compiler/aot.test.ts +2 -9
  73. package/src/compiler/aot.ts +1 -4
  74. package/src/compiler/differential.test.ts +3 -11
  75. package/src/compiler/dynamic.ts +1 -4
  76. package/src/compiler/effects-infer.ts +8 -34
  77. package/src/compiler/emit.ts +1 -3
  78. package/src/compiler/extract.test.ts +96 -30
  79. package/src/compiler/extract.ts +362 -156
  80. package/src/compiler/fixtures/skyport/oke.config.ts +1 -1
  81. package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -3
  82. package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +1 -3
  83. package/src/compiler/fixtures/skyport/src/flows/support/index.ts +4 -1
  84. package/src/compiler/fixtures/skyport.expected.json +24 -83
  85. package/src/compiler/fixtures/triggers/five-triggers.ts +1 -2
  86. package/src/compiler/http-parse.ts +2 -9
  87. package/src/compiler/index.ts +1 -5
  88. package/src/compiler/response.ts +4 -7
  89. package/src/compiler/sucrose.ts +11 -31
  90. package/src/config/define-config.test.ts +57 -34
  91. package/src/config/index.ts +181 -37
  92. package/src/config/resolve-driver.test.ts +28 -17
  93. package/src/console/budget.test.ts +1 -4
  94. package/src/console/index.ts +1 -4
  95. package/src/console/server/access.test.ts +15 -43
  96. package/src/console/server/access.ts +19 -49
  97. package/src/console/server/ai.test.ts +3 -11
  98. package/src/console/server/ai.ts +23 -46
  99. package/src/console/server/app.ts +14 -45
  100. package/src/console/server/auth-rate.test.ts +4 -12
  101. package/src/console/server/bind.ts +1 -5
  102. package/src/console/server/channels.test.ts +2 -6
  103. package/src/console/server/channels.ts +10 -35
  104. package/src/console/server/claim.ts +2 -8
  105. package/src/console/server/clock.test.ts +2 -6
  106. package/src/console/server/clock.ts +8 -26
  107. package/src/console/server/console.test.ts +1 -3
  108. package/src/console/server/diff.test.ts +5 -17
  109. package/src/console/server/diff.ts +10 -31
  110. package/src/console/server/dry-run.audit.test.ts +2 -8
  111. package/src/console/server/flows.ts +64 -233
  112. package/src/console/server/gates.test.ts +14 -50
  113. package/src/console/server/gates.ts +13 -48
  114. package/src/console/server/index.ts +2 -9
  115. package/src/console/server/live.ts +3 -12
  116. package/src/console/server/operator-db.test.ts +4 -15
  117. package/src/console/server/operator-db.ts +13 -32
  118. package/src/console/server/plugin.ts +50 -53
  119. package/src/console/server/plugins.test.ts +2 -6
  120. package/src/console/server/plugins.ts +17 -56
  121. package/src/console/server/runs-pii.ts +2 -7
  122. package/src/console/server/security.gate.test.ts +18 -40
  123. package/src/console/server/serve.ts +10 -25
  124. package/src/console/server/signals.test.ts +1 -3
  125. package/src/console/server/signals.ts +17 -40
  126. package/src/console/server/state.ts +21 -59
  127. package/src/console/server/store.test.ts +20 -22
  128. package/src/console/server/store.ts +31 -76
  129. package/src/console/server/vault.test.ts +12 -29
  130. package/src/console/server/vault.ts +23 -60
  131. package/src/console/ui/access/AccessA11yView.tsx +6 -21
  132. package/src/console/ui/access/a11y.test.tsx +3 -12
  133. package/src/console/ui/access/acknowledgement.test.ts +1 -4
  134. package/src/console/ui/access/acknowledgement.ts +1 -3
  135. package/src/console/ui/access/blast-radius.ts +1 -3
  136. package/src/console/ui/access/confirmation.test.ts +1 -5
  137. package/src/console/ui/access/confirmation.ts +1 -4
  138. package/src/console/ui/access/fixture.ts +1 -5
  139. package/src/console/ui/access/grantable.test.ts +1 -3
  140. package/src/console/ui/access/grantable.ts +2 -7
  141. package/src/console/ui/access/index.ts +2 -9
  142. package/src/console/ui/access/provenance.test.ts +1 -3
  143. package/src/console/ui/access/provenance.ts +2 -6
  144. package/src/console/ui/access/search.test.ts +1 -5
  145. package/src/console/ui/access/search.ts +2 -6
  146. package/src/console/ui/ai/AiA11yView.tsx +6 -17
  147. package/src/console/ui/ai/a11y.test.tsx +2 -5
  148. package/src/console/ui/ai/fixture.ts +2 -7
  149. package/src/console/ui/ai/format.ts +1 -3
  150. package/src/console/ui/ai/group.test.ts +1 -3
  151. package/src/console/ui/ai/group.ts +4 -12
  152. package/src/console/ui/ai/index.ts +2 -9
  153. package/src/console/ui/ai/promotion.test.ts +2 -7
  154. package/src/console/ui/ai/promotion.ts +4 -13
  155. package/src/console/ui/ai/search.test.ts +2 -11
  156. package/src/console/ui/ai/search.ts +3 -13
  157. package/src/console/ui/ai/types.ts +1 -8
  158. package/src/console/ui/architecture/ArchitectureA11yView.tsx +8 -29
  159. package/src/console/ui/architecture/a11y.test.tsx +1 -2
  160. package/src/console/ui/architecture/declared.ts +1 -5
  161. package/src/console/ui/architecture/index.ts +7 -35
  162. package/src/console/ui/architecture/layout.ts +1 -3
  163. package/src/console/ui/architecture/pathologies.ts +10 -19
  164. package/src/console/ui/architecture/search.ts +6 -15
  165. package/src/console/ui/architecture/traffic.ts +4 -14
  166. package/src/console/ui/architecture/types.ts +2 -10
  167. package/src/console/ui/architecture/view.test.ts +7 -19
  168. package/src/console/ui/architecture/view.ts +9 -36
  169. package/src/console/ui/channels/ChannelsA11yView.tsx +4 -13
  170. package/src/console/ui/channels/a11y.test.tsx +1 -2
  171. package/src/console/ui/channels/confirmation.test.ts +1 -4
  172. package/src/console/ui/channels/confirmation.ts +1 -4
  173. package/src/console/ui/channels/findings.ts +1 -5
  174. package/src/console/ui/channels/index.ts +2 -8
  175. package/src/console/ui/channels/locale.test.ts +1 -3
  176. package/src/console/ui/channels/locale.ts +2 -8
  177. package/src/console/ui/channels/search.ts +4 -13
  178. package/src/console/ui/channels/taxonomy.ts +1 -3
  179. package/src/console/ui/clock/ClockA11yView.tsx +9 -26
  180. package/src/console/ui/clock/a11y.test.tsx +2 -5
  181. package/src/console/ui/clock/confirmation.test.ts +1 -3
  182. package/src/console/ui/clock/confirmation.ts +1 -4
  183. package/src/console/ui/clock/findings.ts +1 -4
  184. package/src/console/ui/clock/health.ts +2 -7
  185. package/src/console/ui/clock/index.ts +2 -10
  186. package/src/console/ui/clock/search.test.ts +1 -3
  187. package/src/console/ui/clock/search.ts +2 -6
  188. package/src/console/ui/clock/timeline.test.ts +1 -3
  189. package/src/console/ui/clock/waiting-on.test.ts +1 -5
  190. package/src/console/ui/clock/waiting-on.ts +2 -7
  191. package/src/console/ui/diff/DiffA11yView.tsx +8 -17
  192. package/src/console/ui/diff/a11y.test.tsx +2 -5
  193. package/src/console/ui/diff/group.test.ts +3 -13
  194. package/src/console/ui/diff/group.ts +2 -8
  195. package/src/console/ui/diff/index.ts +2 -8
  196. package/src/console/ui/diff/search.test.ts +1 -5
  197. package/src/console/ui/diff/search.ts +4 -16
  198. package/src/console/ui/diff/summary.ts +1 -2
  199. package/src/console/ui/dist/assets/{index-Dy4jht9P.js → index-BWo8R7NR.js} +2 -2
  200. package/src/console/ui/dist/assets/{panel-access-Dd37LU2c.js → panel-access-C0J2D-a2.js} +1 -1
  201. package/src/console/ui/dist/assets/{panel-ai-CC7LR6-J.js → panel-ai-D_m6WQI8.js} +1 -1
  202. package/src/console/ui/dist/assets/{panel-architecture-B5b3iKCz.js → panel-architecture-CKnXFyUx.js} +1 -1
  203. package/src/console/ui/dist/assets/{panel-channels-CeNjTKXp.js → panel-channels-BOmQ-onL.js} +1 -1
  204. package/src/console/ui/dist/assets/{panel-clock-DgFTLoHV.js → panel-clock-giAq0Ccv.js} +1 -1
  205. package/src/console/ui/dist/assets/{panel-diff-DxehccqB.js → panel-diff-cdonmH8c.js} +1 -1
  206. package/src/console/ui/dist/assets/{panel-flows-BtrVn-Eg.js → panel-flows-DlCU5zjA.js} +2 -2
  207. package/src/console/ui/dist/assets/{panel-gates-Z9MKRGdH.js → panel-gates-XclZxWD5.js} +1 -1
  208. package/src/console/ui/dist/assets/{panel-overview-Dt_AeXgd.js → panel-overview-BznEOTnb.js} +1 -1
  209. package/src/console/ui/dist/assets/{panel-plugins-DWd0TowH.js → panel-plugins-CcGM1g64.js} +1 -1
  210. package/src/console/ui/dist/assets/{panel-runs-DGstFHeq.js → panel-runs-CGWNHLR4.js} +1 -1
  211. package/src/console/ui/dist/assets/{panel-signals-DzEa2Fnt.js → panel-signals-CNywkdak.js} +1 -1
  212. package/src/console/ui/dist/assets/{panel-store-BJkbNgxx.js → panel-store-KmTbFHMH.js} +1 -1
  213. package/src/console/ui/dist/assets/{panel-traces-BaRVO3gM.js → panel-traces-DBLx2ilD.js} +1 -1
  214. package/src/console/ui/dist/assets/panel-vault-CEnFc0dk.js +1 -0
  215. package/src/console/ui/dist/index.html +1 -1
  216. package/src/console/ui/flows/FlowsA11yView.tsx +7 -22
  217. package/src/console/ui/flows/a11y.test.tsx +2 -8
  218. package/src/console/ui/flows/buffer.test.ts +3 -11
  219. package/src/console/ui/flows/buffer.ts +4 -11
  220. package/src/console/ui/flows/confirmation.ts +1 -3
  221. package/src/console/ui/flows/contract.test.ts +3 -7
  222. package/src/console/ui/flows/contract.ts +12 -36
  223. package/src/console/ui/flows/graph.test.ts +3 -11
  224. package/src/console/ui/flows/graph.ts +5 -15
  225. package/src/console/ui/flows/index.ts +1 -6
  226. package/src/console/ui/flows/save-as-test.ts +1 -3
  227. package/src/console/ui/flows/search.ts +8 -25
  228. package/src/console/ui/flows/tiers.ts +2 -9
  229. package/src/console/ui/gates/GatesA11yView.tsx +4 -13
  230. package/src/console/ui/gates/a11y.test.tsx +2 -5
  231. package/src/console/ui/gates/audit.ts +1 -3
  232. package/src/console/ui/gates/denial.test.ts +1 -3
  233. package/src/console/ui/gates/denial.ts +4 -12
  234. package/src/console/ui/gates/findings.ts +1 -3
  235. package/src/console/ui/gates/group.test.ts +3 -3
  236. package/src/console/ui/gates/group.ts +3 -11
  237. package/src/console/ui/gates/index.ts +2 -10
  238. package/src/console/ui/gates/search.ts +3 -10
  239. package/src/console/ui/overview/OverviewA11yView.tsx +9 -27
  240. package/src/console/ui/overview/a11y.test.tsx +1 -2
  241. package/src/console/ui/overview/busiest.ts +1 -3
  242. package/src/console/ui/overview/compose.ts +1 -13
  243. package/src/console/ui/overview/cost.ts +34 -38
  244. package/src/console/ui/overview/fixture.ts +21 -26
  245. package/src/console/ui/overview/golden.ts +4 -14
  246. package/src/console/ui/overview/index.ts +2 -9
  247. package/src/console/ui/overview/rank.test.ts +3 -10
  248. package/src/console/ui/overview/rank.ts +2 -7
  249. package/src/console/ui/overview/slo.test.ts +5 -9
  250. package/src/console/ui/overview/slo.ts +6 -23
  251. package/src/console/ui/overview/verdict.ts +3 -10
  252. package/src/console/ui/plugins/PluginsA11yView.tsx +8 -18
  253. package/src/console/ui/plugins/a11y.test.tsx +1 -2
  254. package/src/console/ui/plugins/fixture.ts +2 -4
  255. package/src/console/ui/plugins/group.test.ts +1 -3
  256. package/src/console/ui/plugins/group.ts +1 -6
  257. package/src/console/ui/plugins/index.ts +3 -13
  258. package/src/console/ui/plugins/search.ts +7 -19
  259. package/src/console/ui/runs/RunsA11yView.tsx +5 -20
  260. package/src/console/ui/runs/a11y.test.tsx +2 -5
  261. package/src/console/ui/runs/explain.ts +2 -6
  262. package/src/console/ui/runs/group.ts +3 -12
  263. package/src/console/ui/runs/histogram.test.ts +2 -11
  264. package/src/console/ui/runs/histogram.ts +1 -4
  265. package/src/console/ui/runs/index.ts +4 -18
  266. package/src/console/ui/runs/project.ts +2 -6
  267. package/src/console/ui/runs/query.test.ts +1 -3
  268. package/src/console/ui/runs/query.ts +12 -35
  269. package/src/console/ui/runs/search.ts +5 -19
  270. package/src/console/ui/runs/trace-link.test.ts +2 -6
  271. package/src/console/ui/runs/trace-link.ts +4 -16
  272. package/src/console/ui/runs/types.ts +1 -3
  273. package/src/console/ui/shell/App.tsx +2 -10
  274. package/src/console/ui/shell/client.ts +22 -115
  275. package/src/console/ui/shell/components/ui.tsx +1 -4
  276. package/src/console/ui/shell/layout/Shell.tsx +2 -4
  277. package/src/console/ui/shell/main.tsx +31 -96
  278. package/src/console/ui/shell/panels/access/AccessPanel.tsx +34 -98
  279. package/src/console/ui/shell/panels/ai/AiPanel.tsx +35 -106
  280. package/src/console/ui/shell/panels/architecture/ArchitecturePanel.tsx +18 -66
  281. package/src/console/ui/shell/panels/channels/ChannelsPanel.tsx +20 -57
  282. package/src/console/ui/shell/panels/clock/ClockPanel.tsx +22 -54
  283. package/src/console/ui/shell/panels/diff/DiffPanel.tsx +20 -61
  284. package/src/console/ui/shell/panels/flows/ContractEditor.tsx +6 -23
  285. package/src/console/ui/shell/panels/flows/FlowDrawer.tsx +13 -28
  286. package/src/console/ui/shell/panels/flows/FlowsPanel.tsx +9 -29
  287. package/src/console/ui/shell/panels/gates/GatesPanel.tsx +24 -80
  288. package/src/console/ui/shell/panels/overview/OverviewPanel.tsx +20 -58
  289. package/src/console/ui/shell/panels/plugins/PluginsPanel.tsx +16 -41
  290. package/src/console/ui/shell/panels/runs/RunsPanel.tsx +31 -99
  291. package/src/console/ui/shell/panels/signals/SignalsPanel.tsx +38 -101
  292. package/src/console/ui/shell/panels/store/StorePanel.tsx +27 -66
  293. package/src/console/ui/shell/panels/traces/TracesPanel.tsx +28 -89
  294. package/src/console/ui/shell/panels/vault/VaultPanel.tsx +22 -53
  295. package/src/console/ui/shell/setup/Wizard.tsx +3 -5
  296. package/src/console/ui/shell/styles.css +1 -2
  297. package/src/console/ui/signals/SignalsA11yView.tsx +9 -33
  298. package/src/console/ui/signals/a11y.test.tsx +2 -5
  299. package/src/console/ui/signals/confirmation.test.ts +1 -5
  300. package/src/console/ui/signals/confirmation.ts +2 -6
  301. package/src/console/ui/signals/dry-run.ts +1 -3
  302. package/src/console/ui/signals/durable.ts +1 -3
  303. package/src/console/ui/signals/findings.ts +1 -3
  304. package/src/console/ui/signals/group.test.ts +2 -8
  305. package/src/console/ui/signals/group.ts +2 -10
  306. package/src/console/ui/signals/index.ts +1 -4
  307. package/src/console/ui/signals/monitor.ts +2 -7
  308. package/src/console/ui/signals/schema-form.test.ts +3 -14
  309. package/src/console/ui/signals/schema-form.ts +1 -4
  310. package/src/console/ui/signals/search.ts +4 -13
  311. package/src/console/ui/store/StoreA11yView.tsx +3 -9
  312. package/src/console/ui/store/a11y.test.tsx +2 -5
  313. package/src/console/ui/store/confirmation.test.ts +1 -3
  314. package/src/console/ui/store/confirmation.ts +1 -4
  315. package/src/console/ui/store/dry-run.ts +2 -5
  316. package/src/console/ui/store/fixture.ts +1 -2
  317. package/src/console/ui/store/group.test.ts +1 -6
  318. package/src/console/ui/store/group.ts +1 -4
  319. package/src/console/ui/store/index.ts +1 -5
  320. package/src/console/ui/store/search.ts +2 -6
  321. package/src/console/ui/store/will-not-fire.ts +1 -2
  322. package/src/console/ui/traces/TracesA11yView.tsx +10 -29
  323. package/src/console/ui/traces/a11y.test.tsx +1 -2
  324. package/src/console/ui/traces/chain.test.ts +5 -19
  325. package/src/console/ui/traces/chain.ts +1 -3
  326. package/src/console/ui/traces/critical-path.test.ts +1 -3
  327. package/src/console/ui/traces/critical-path.ts +2 -6
  328. package/src/console/ui/traces/filter.test.ts +2 -6
  329. package/src/console/ui/traces/filter.ts +5 -13
  330. package/src/console/ui/traces/fold.test.ts +4 -12
  331. package/src/console/ui/traces/fold.ts +1 -3
  332. package/src/console/ui/traces/mini.ts +1 -3
  333. package/src/console/ui/traces/replay.test.ts +1 -3
  334. package/src/console/ui/traces/replay.ts +1 -3
  335. package/src/console/ui/traces/sampling.ts +1 -4
  336. package/src/console/ui/traces/search.ts +4 -17
  337. package/src/console/ui/traces/tier.ts +1 -3
  338. package/src/console/ui/vault/VaultA11yView.tsx +5 -17
  339. package/src/console/ui/vault/a11y.test.tsx +1 -2
  340. package/src/console/ui/vault/blast-radius.ts +1 -3
  341. package/src/console/ui/vault/confirmation.test.ts +1 -5
  342. package/src/console/ui/vault/confirmation.ts +1 -4
  343. package/src/console/ui/vault/dormant.test.ts +1 -4
  344. package/src/console/ui/vault/export-safe.test.ts +1 -5
  345. package/src/console/ui/vault/export-safe.ts +1 -4
  346. package/src/console/ui/vault/fixture.ts +3 -3
  347. package/src/console/ui/vault/group.ts +1 -2
  348. package/src/console/ui/vault/index.ts +2 -10
  349. package/src/console/ui/vault/search.ts +2 -6
  350. package/src/console/ui/vault/types.ts +1 -1
  351. package/src/console/xss.gate.test.ts +1 -3
  352. package/src/docker/compose.ts +112 -20
  353. package/src/docker/derive.ts +5 -19
  354. package/src/docker/docker.test.ts +15 -15
  355. package/src/docker/dockerfile.integration.test.ts +12 -21
  356. package/src/docker/helpers.ts +5 -4
  357. package/src/docker/index.ts +4 -11
  358. package/src/docker/pin.ts +1 -9
  359. package/src/docker/recipes/index.ts +5 -6
  360. package/src/docker/recipes/mailpit.ts +22 -0
  361. package/src/docker/recipes/postgres.ts +17 -6
  362. package/src/docker/recipes/redis.ts +6 -1
  363. package/src/docker/recipes/rustfs.ts +33 -0
  364. package/src/docker/stack-id.test.ts +33 -0
  365. package/src/docker/stack-id.ts +25 -13
  366. package/src/docker/stack.integration.test.ts +6 -21
  367. package/src/docker/types.ts +13 -4
  368. package/src/drivers/ai-anthropic.ts +5 -14
  369. package/src/drivers/ai-mock.ts +2 -5
  370. package/src/drivers/ai-openai-compatible.ts +4 -10
  371. package/src/drivers/ai-providers.test.ts +6 -13
  372. package/src/drivers/bun-native-completeness.test.ts +6 -15
  373. package/src/drivers/channel-console.ts +6 -7
  374. package/src/drivers/channel-fcm.ts +20 -30
  375. package/src/drivers/channel-resend.ts +1 -3
  376. package/src/drivers/channel-smtp.ts +2 -6
  377. package/src/drivers/channel-types.ts +2 -12
  378. package/src/drivers/channel-unifonic.ts +2 -6
  379. package/src/drivers/channel-wa-cloud.ts +2 -6
  380. package/src/drivers/channel-webpush.ts +21 -60
  381. package/src/drivers/conformance.test.ts +2 -10
  382. package/src/drivers/conformance.ts +8 -21
  383. package/src/drivers/fs.ts +2 -8
  384. package/src/drivers/index.ts +12 -56
  385. package/src/drivers/memory.ts +14 -41
  386. package/src/drivers/pgvector.ts +7 -11
  387. package/src/drivers/postgres.ts +7 -13
  388. package/src/drivers/redis.ts +13 -37
  389. package/src/drivers/s3.ts +5 -17
  390. package/src/drivers/signal-engine.ts +12 -49
  391. package/src/drivers/signal-memory.ts +2 -8
  392. package/src/drivers/signal-nats.ts +4 -9
  393. package/src/drivers/signal-postgres.ts +62 -129
  394. package/src/drivers/signal-redis.ts +7 -21
  395. package/src/drivers/signal-types.ts +1 -4
  396. package/src/drivers/sqlite.ts +3 -12
  397. package/src/drivers/types.ts +4 -23
  398. package/src/drivers/vault-env.ts +2 -6
  399. package/src/drivers/vault-infisical.ts +1 -5
  400. package/src/drivers/vault-managed.ts +1 -5
  401. package/src/drivers/vault-memory.ts +1 -5
  402. package/src/drivers/vault-openbao.ts +1 -5
  403. package/src/drivers/vault-sops.ts +10 -35
  404. package/src/drivers/vault-types.ts +1 -7
  405. package/src/elements/ai/declare.ts +4 -14
  406. package/src/elements/ai/eval.ts +2 -6
  407. package/src/elements/ai/pii.ts +1 -3
  408. package/src/elements/ai/runtime.ts +12 -50
  409. package/src/elements/ai/schema.ts +4 -15
  410. package/src/elements/ai.test.ts +13 -24
  411. package/src/elements/ai.ts +1 -5
  412. package/src/elements/channel/consent.ts +3 -12
  413. package/src/elements/channel/costs.ts +4 -15
  414. package/src/elements/channel/declare.ts +1 -4
  415. package/src/elements/channel/email-auth.ts +1 -4
  416. package/src/elements/channel/locale.ts +2 -10
  417. package/src/elements/channel/mask.ts +1 -3
  418. package/src/elements/channel/mime.ts +2 -12
  419. package/src/elements/channel/outcomes.test.ts +1 -5
  420. package/src/elements/channel/outcomes.ts +5 -15
  421. package/src/elements/channel/receipts.ts +2 -7
  422. package/src/elements/channel/runtime.ts +28 -74
  423. package/src/elements/channel/suppression.ts +8 -14
  424. package/src/elements/channel.test.ts +8 -31
  425. package/src/elements/channel.ts +3 -14
  426. package/src/elements/clock/actions.ts +6 -18
  427. package/src/elements/clock/declare.ts +1 -3
  428. package/src/elements/clock/dst.ts +1 -5
  429. package/src/elements/clock/durable.ts +4 -16
  430. package/src/elements/clock/health.ts +2 -7
  431. package/src/elements/clock/leader.ts +2 -9
  432. package/src/elements/clock/reconcile.ts +4 -15
  433. package/src/elements/clock/runtime.ts +2 -5
  434. package/src/elements/clock/schedule.ts +4 -20
  435. package/src/elements/clock.test.ts +2 -7
  436. package/src/elements/clock.ts +5 -23
  437. package/src/elements/gate/permissions.ts +1 -4
  438. package/src/elements/gate/runtime.ts +7 -28
  439. package/src/elements/gate.ts +1 -5
  440. package/src/elements/index.ts +9 -7
  441. package/src/elements/signal/declare.ts +2 -7
  442. package/src/elements/signal/reconcile.test.ts +1 -4
  443. package/src/elements/signal/runtime.ts +1 -3
  444. package/src/elements/signal.test.ts +3 -15
  445. package/src/elements/signal.ts +2 -8
  446. package/src/elements/store/cache.test.ts +46 -0
  447. package/src/elements/store/cache.ts +3 -11
  448. package/src/elements/store/classify.ts +5 -22
  449. package/src/elements/store/declare.ts +8 -17
  450. package/src/elements/store/domain-ddl.test.ts +86 -0
  451. package/src/elements/store/emit-drizzle.ts +363 -0
  452. package/src/elements/store/files-policy.test.ts +1 -5
  453. package/src/elements/store/files-policy.ts +4 -12
  454. package/src/elements/store/load-plugin-tables.ts +103 -0
  455. package/src/elements/store/missing-relation.test.ts +83 -0
  456. package/src/elements/store/missing-relation.ts +38 -0
  457. package/src/elements/store/replica.ts +1 -4
  458. package/src/elements/store/runtime.ts +25 -28
  459. package/src/elements/store/schema-decl.test.ts +227 -0
  460. package/src/elements/store/schema-decl.ts +516 -0
  461. package/src/elements/store/sql-condition.ts +11 -21
  462. package/src/elements/store/sql-session.test.ts +50 -0
  463. package/src/elements/store/sql-session.ts +60 -63
  464. package/src/elements/store/table.ts +35 -19
  465. package/src/elements/store.test.ts +17 -39
  466. package/src/elements/store.ts +37 -31
  467. package/src/elements/vault/chain.ts +34 -0
  468. package/src/elements/vault/declare.ts +22 -32
  469. package/src/elements/vault/fingerprint.ts +2 -7
  470. package/src/elements/vault/redact.ts +2 -6
  471. package/src/elements/vault/runtime.ts +18 -32
  472. package/src/elements/vault.test.ts +12 -28
  473. package/src/elements/vault.ts +8 -12
  474. package/src/index.ts +5 -2
  475. package/src/kernel/adopt-routes.ts +15 -29
  476. package/src/kernel/app.ts +34 -94
  477. package/src/kernel/auth-resolve.ts +2 -9
  478. package/src/kernel/boot-bind/ai.ts +1 -4
  479. package/src/kernel/boot-bind/channel.ts +2 -8
  480. package/src/kernel/boot-bind/clock.ts +2 -6
  481. package/src/kernel/boot-bind/gate.ts +2 -8
  482. package/src/kernel/boot-bind/runs.ts +1 -3
  483. package/src/kernel/boot-bind/signal.ts +3 -10
  484. package/src/kernel/boot-bind/store.test.ts +17 -17
  485. package/src/kernel/boot-bind/store.ts +44 -50
  486. package/src/kernel/boot-bind/vault.ts +2 -8
  487. package/src/kernel/boot.test.ts +4 -9
  488. package/src/kernel/boot.ts +29 -76
  489. package/src/kernel/budget.test.ts +1 -3
  490. package/src/kernel/capability.ts +3 -10
  491. package/src/kernel/dry-run.test.ts +1 -4
  492. package/src/kernel/dry-run.ts +3 -11
  493. package/src/kernel/effects.test.ts +1 -5
  494. package/src/kernel/effects.ts +4 -11
  495. package/src/kernel/errors.registry.test.ts +2 -8
  496. package/src/kernel/errors.ts +23 -32
  497. package/src/kernel/flow.test.ts +12 -25
  498. package/src/kernel/flow.ts +5 -25
  499. package/src/kernel/fx.test.ts +15 -44
  500. package/src/kernel/fx.ts +27 -79
  501. package/src/kernel/hook-timing.test.ts +3 -6
  502. package/src/kernel/hook-timing.ts +5 -14
  503. package/src/kernel/hooks.test.ts +10 -10
  504. package/src/kernel/hooks.ts +3 -12
  505. package/src/kernel/index.ts +4 -17
  506. package/src/kernel/journal.ts +7 -31
  507. package/src/kernel/on.ts +1 -6
  508. package/src/kernel/pipeline.test.ts +10 -19
  509. package/src/kernel/pipeline.ts +5 -17
  510. package/src/kernel/plug.ts +4 -11
  511. package/src/kernel/plugin/conflicts.test.ts +13 -25
  512. package/src/kernel/plugin/decorate.test.ts +8 -13
  513. package/src/kernel/plugin/scoping.test.ts +4 -11
  514. package/src/kernel/plugin.ts +48 -24
  515. package/src/kernel/registry.ts +80 -29
  516. package/src/kernel/router.test.ts +15 -13
  517. package/src/kernel/router.ts +9 -29
  518. package/src/kernel/routing-budget.test.ts +1 -3
  519. package/src/kernel/run-telemetry.ts +1 -3
  520. package/src/kernel/triggers.ts +4 -21
  521. package/src/manifest/diff.test.ts +26 -91
  522. package/src/manifest/diff.ts +95 -225
  523. package/src/manifest/index.ts +2 -9
  524. package/src/manifest/types.ts +29 -5
  525. package/src/manifest/undeclared.test.ts +4 -12
  526. package/src/manifest/undeclared.ts +1 -2
  527. package/src/manifest/validate.test.ts +2 -6
  528. package/src/manifest/validate.ts +4 -14
  529. package/src/mcp/authorization.ts +8 -27
  530. package/src/mcp/confirmation.ts +3 -10
  531. package/src/mcp/data.ts +2 -6
  532. package/src/mcp/docs-index.ts +4 -7
  533. package/src/mcp/docs-mcp.test.ts +3 -12
  534. package/src/mcp/docs-server.ts +7 -27
  535. package/src/mcp/docs-tools.ts +2 -6
  536. package/src/mcp/index.ts +1 -6
  537. package/src/mcp/injection.gate.test.ts +4 -18
  538. package/src/mcp/mcp.test.ts +18 -49
  539. package/src/mcp/protocol.ts +3 -10
  540. package/src/mcp/server.ts +11 -52
  541. package/src/mcp/session.ts +4 -14
  542. package/src/mcp/tools.ts +14 -50
  543. package/src/plugins/catalogue.test.ts +3 -7
  544. package/src/plugins/catalogue.ts +1 -3
  545. package/src/plugins/node-import-scan.ts +2 -5
  546. package/src/plugins/supply-chain.ts +5 -17
  547. package/src/release/exports.ts +3 -8
  548. package/src/release/measure.exports.test.ts +1 -3
  549. package/src/release/measure.ts +15 -43
  550. package/src/runs/bench.test.ts +1 -3
  551. package/src/runs/collect.ts +8 -25
  552. package/src/runs/drivers/clickhouse.ts +2 -9
  553. package/src/runs/drivers/files.ts +9 -31
  554. package/src/runs/drivers/memory.ts +5 -22
  555. package/src/runs/drivers/postgres.ts +8 -20
  556. package/src/runs/duckdb.ts +2 -8
  557. package/src/runs/index.ts +3 -14
  558. package/src/runs/outlier.ts +3 -10
  559. package/src/runs/parquet.ts +8 -26
  560. package/src/runs/privacy.ts +2 -8
  561. package/src/runs/runs.test.ts +3 -9
  562. package/src/runs/runtime.ts +7 -32
  563. package/src/runs/shred.ts +10 -29
  564. package/src/runs/types.ts +1 -4
  565. package/src/runtime/bun.ts +4 -15
  566. package/src/runtime/cold-start.bench.ts +1 -3
  567. package/src/runtime/dev-request-log.test.ts +1 -4
  568. package/src/runtime/dev-request-log.ts +1 -4
  569. package/src/runtime/index.ts +1 -6
  570. package/src/runtime/primitives.ts +5 -4
  571. package/src/runtime/security.ts +3 -13
  572. package/src/runtime/serve.test.ts +4 -7
  573. package/src/runtime/types.ts +1 -4
  574. package/src/runtime/web-standard.ts +3 -15
  575. package/src/term.test.ts +4 -6
  576. package/src/term.ts +49 -98
  577. package/src/test/create-test-app.test.ts +4 -14
  578. package/src/test/create-test-app.ts +13 -31
  579. package/src/test/provisions.integration.test.ts +3 -11
  580. package/src/upgrade/codemods.test.ts +25 -6
  581. package/src/upgrade/codemods.ts +116 -3
  582. package/src/validation/standard-schema.test.ts +2 -5
  583. package/src/validation/standard-schema.ts +13 -33
  584. package/src/console/ui/dist/assets/panel-vault-BbfWdox0.js +0 -1
@@ -0,0 +1,516 @@
1
+ /**
2
+ * Abstract store schema — ORM-agnostic declare site (`field.*` + `store.schema.table`).
3
+ *
4
+ * Survey-backed v1 primitives: `text` · `integer` + modifiers + PII tags + FKs.
5
+ * Dialect-specific Drizzle is emitted separately ({@link emitDrizzleSource}).
6
+ */
7
+
8
+ import type { ColumnClassification } from "../../manifest/types.ts";
9
+ import type { ColumnDef, TableHandle } from "./table.ts";
10
+ import { id as idHelper, now as nowHelper } from "./table.ts";
11
+
12
+ /** SQL type primitives supported in v1. */
13
+ export type FieldSqlType = "text" | "integer";
14
+
15
+ /** Known `$defaultFn` helpers recognized by the Drizzle emitter. */
16
+ export type DefaultFnKind = "id" | "now" | "custom";
17
+
18
+ /** FK action — mirrors Drizzle `UpdateDeleteAction`. */
19
+ export type ReferenceAction = "cascade" | "restrict" | "no action" | "set null" | "set default";
20
+
21
+ /** Optional ON DELETE / ON UPDATE for {@link FieldBuilder.references}. */
22
+ export interface ReferenceActions {
23
+ readonly onDelete?: ReferenceAction;
24
+ readonly onUpdate?: ReferenceAction;
25
+ }
26
+
27
+ /** Resolved foreign-key target (lazy ref evaluated at finalize/emit). */
28
+ export interface ColumnReference {
29
+ /** Lazy target column (evaluated when emitting / finalizing). */
30
+ readonly ref: () => SchemaColumnDecl;
31
+ readonly actions?: ReferenceActions;
32
+ }
33
+
34
+ /**
35
+ * Finalized column declaration — also satisfies {@link ColumnDef} so
36
+ * {@link classificationsFromTable} / runtime masking work without Drizzle.
37
+ */
38
+ export interface SchemaColumnDecl extends ColumnDef {
39
+ /** JS object key (e.g. `createdAt`). */
40
+ readonly key: string;
41
+ /** Database column name (e.g. `created_at`). */
42
+ readonly sqlName: string;
43
+ /** Declared SQL type. */
44
+ readonly sqlType: FieldSqlType;
45
+ readonly primaryKey: boolean;
46
+ readonly notNull: boolean;
47
+ readonly unique: boolean;
48
+ /** Literal `.default(v)` when set. */
49
+ readonly defaultValue?: string | number | boolean | null;
50
+ /** Runtime default applied on insert when the key is missing. */
51
+ readonly defaultFn?: () => unknown;
52
+ /** Emitter hint for `$defaultFn(id|now)`. */
53
+ readonly defaultFnKind?: DefaultFnKind;
54
+ /** Owning table SQL name (stamped by {@link schemaTable}). */
55
+ readonly tableName?: string;
56
+ /** Foreign key when `.references()` was used. */
57
+ readonly references?: ColumnReference;
58
+ }
59
+
60
+ /** Table from {@link store.schema.table} — extends {@link TableHandle}. */
61
+ export interface SchemaTableDecl extends TableHandle {
62
+ readonly kind: "schema-table";
63
+ readonly columns: Readonly<Record<string, SchemaColumnDecl>>;
64
+ }
65
+
66
+ /** Fluent field builder before key finalization. */
67
+ export interface FieldBuilder {
68
+ primaryKey(): FieldBuilder;
69
+ notNull(): FieldBuilder;
70
+ unique(): FieldBuilder;
71
+ default(value: string | number | boolean | null): FieldBuilder;
72
+ defaultFn(fn: () => unknown): FieldBuilder;
73
+ pii(): FieldBuilder;
74
+ sensitive(): FieldBuilder;
75
+ retain(duration: string): FieldBuilder;
76
+ /** Override snake_case SQL name. */
77
+ as(sqlName: string): FieldBuilder;
78
+ /**
79
+ * Declare a foreign key to another column (dialect-agnostic).
80
+ *
81
+ * @param ref - Lazy target column (`() => links.code`)
82
+ * @param actions - Optional ON DELETE / ON UPDATE
83
+ */
84
+ references(ref: () => SchemaColumnDecl, actions?: ReferenceActions): FieldBuilder;
85
+ /**
86
+ * Bind the JS key and produce a {@link SchemaColumnDecl}.
87
+ *
88
+ * @param key - Object key in the table column map
89
+ */
90
+ finalize(key: string): SchemaColumnDecl;
91
+ }
92
+
93
+ interface FieldState {
94
+ readonly sqlType: FieldSqlType;
95
+ readonly primaryKey: boolean;
96
+ readonly notNull: boolean;
97
+ readonly unique: boolean;
98
+ readonly defaultValue?: string | number | boolean | null;
99
+ readonly defaultFn?: () => unknown;
100
+ readonly defaultFnKind?: DefaultFnKind;
101
+ readonly classification?: ColumnClassification;
102
+ readonly sqlName?: string;
103
+ readonly references?: ColumnReference;
104
+ }
105
+
106
+ function camelToSnake(key: string): string {
107
+ return key
108
+ .replace(/([a-z0-9])([A-Z])/g, "$1_$2")
109
+ .replace(/([A-Z])([A-Z][a-z])/g, "$1_$2")
110
+ .toLowerCase();
111
+ }
112
+
113
+ function defaultFnKindOf(fn: () => unknown): DefaultFnKind {
114
+ if (fn === idHelper) return "id";
115
+ if (fn === nowHelper) return "now";
116
+ const name = typeof fn.name === "string" ? fn.name : "";
117
+ if (name === "id") return "id";
118
+ if (name === "now") return "now";
119
+ return "custom";
120
+ }
121
+
122
+ function mergeClassification(
123
+ current: ColumnClassification | undefined,
124
+ patch: ColumnClassification,
125
+ ): ColumnClassification {
126
+ return { ...(current ?? {}), ...patch };
127
+ }
128
+
129
+ function createBuilder(state: FieldState): FieldBuilder {
130
+ const next = (patch: Partial<FieldState>): FieldBuilder => createBuilder({ ...state, ...patch });
131
+
132
+ return {
133
+ primaryKey: () => next({ primaryKey: true, notNull: true }),
134
+ notNull: () => next({ notNull: true }),
135
+ unique: () => next({ unique: true }),
136
+ default: (value) => next({ defaultValue: value }),
137
+ defaultFn: (fn) =>
138
+ next({
139
+ defaultFn: fn,
140
+ defaultFnKind: defaultFnKindOf(fn),
141
+ }),
142
+ pii: () => next({ classification: mergeClassification(state.classification, { pii: true }) }),
143
+ sensitive: () =>
144
+ next({ classification: mergeClassification(state.classification, { sensitive: true }) }),
145
+ retain: (duration) =>
146
+ next({ classification: mergeClassification(state.classification, { retain: duration }) }),
147
+ as: (sqlName) => next({ sqlName }),
148
+ references: (ref, actions) =>
149
+ next({
150
+ references: actions ? { ref, actions } : { ref },
151
+ }),
152
+ finalize(key: string): SchemaColumnDecl {
153
+ const sqlName = state.sqlName ?? camelToSnake(key);
154
+ return {
155
+ key,
156
+ name: sqlName,
157
+ sqlName,
158
+ sqlType: state.sqlType,
159
+ primaryKey: state.primaryKey,
160
+ notNull: state.notNull || state.primaryKey,
161
+ unique: state.unique,
162
+ ...(state.defaultValue !== undefined ? { defaultValue: state.defaultValue } : {}),
163
+ ...(state.defaultFn ? { defaultFn: state.defaultFn } : {}),
164
+ ...(state.defaultFnKind ? { defaultFnKind: state.defaultFnKind } : {}),
165
+ ...(state.classification ? { classification: state.classification } : {}),
166
+ ...(state.references ? { references: state.references } : {}),
167
+ };
168
+ },
169
+ };
170
+ }
171
+
172
+ /**
173
+ * Field builders — `field.text()` / `field.integer()`.
174
+ */
175
+ export const field = {
176
+ text: (): FieldBuilder =>
177
+ createBuilder({
178
+ sqlType: "text",
179
+ primaryKey: false,
180
+ notNull: false,
181
+ unique: false,
182
+ }),
183
+ integer: (): FieldBuilder =>
184
+ createBuilder({
185
+ sqlType: "integer",
186
+ primaryKey: false,
187
+ notNull: false,
188
+ unique: false,
189
+ }),
190
+ } as const;
191
+
192
+ /** Column map input for {@link schemaTable}. */
193
+ export type SchemaColumnInput = FieldBuilder | SchemaColumnDecl;
194
+
195
+ /**
196
+ * Whether a value is a finalized {@link SchemaColumnDecl}.
197
+ *
198
+ * @param value - Unknown
199
+ */
200
+ export function isSchemaColumnDecl(value: unknown): value is SchemaColumnDecl {
201
+ return (
202
+ !!value &&
203
+ typeof value === "object" &&
204
+ "sqlType" in value &&
205
+ "sqlName" in value &&
206
+ "primaryKey" in value &&
207
+ typeof (value as SchemaColumnDecl).sqlType === "string" &&
208
+ typeof (value as SchemaColumnDecl).sqlName === "string"
209
+ );
210
+ }
211
+
212
+ /**
213
+ * Whether a value is a fluent {@link FieldBuilder}.
214
+ *
215
+ * @param value - Unknown
216
+ */
217
+ export function isFieldBuilder(value: unknown): value is FieldBuilder {
218
+ return (
219
+ !!value &&
220
+ typeof value === "object" &&
221
+ typeof (value as FieldBuilder).finalize === "function" &&
222
+ typeof (value as FieldBuilder).primaryKey === "function" &&
223
+ !isSchemaColumnDecl(value)
224
+ );
225
+ }
226
+
227
+ /**
228
+ * Finalize a column map (builders → decls).
229
+ *
230
+ * @param columns - Key → builder or decl
231
+ */
232
+ export function finalizeColumnMap(
233
+ columns: Readonly<Record<string, SchemaColumnInput>>,
234
+ ): Record<string, SchemaColumnDecl> {
235
+ const out: Record<string, SchemaColumnDecl> = {};
236
+ for (const [key, value] of Object.entries(columns)) {
237
+ out[key] = isFieldBuilder(value) ? value.finalize(key) : value;
238
+ }
239
+ return out;
240
+ }
241
+
242
+ /**
243
+ * Whether a value is a {@link SchemaTableDecl}.
244
+ *
245
+ * @param value - Unknown
246
+ */
247
+ export function isSchemaTableDecl(value: unknown): value is SchemaTableDecl {
248
+ return (
249
+ !!value &&
250
+ typeof value === "object" &&
251
+ (value as SchemaTableDecl).kind === "schema-table" &&
252
+ typeof (value as SchemaTableDecl).name === "string" &&
253
+ "columns" in value
254
+ );
255
+ }
256
+
257
+ /**
258
+ * Table decl with columns as own properties (`links.code`) for FK / relations.
259
+ */
260
+ export type SchemaTableWithColumns<
261
+ C extends Record<string, SchemaColumnDecl> = Record<string, SchemaColumnDecl>,
262
+ > = Omit<SchemaTableDecl, "columns"> & {
263
+ readonly columns: Readonly<C>;
264
+ } & C;
265
+
266
+ /**
267
+ * Declare an abstract schema table (ORM-agnostic).
268
+ *
269
+ * Columns are also exposed as own properties (`links.code`) for
270
+ * `.references(() => links.code)` ergonomics matching Drizzle.
271
+ *
272
+ * @param name - SQL table name
273
+ * @param columns - Column map using {@link field} builders
274
+ */
275
+ export function schemaTable<C extends Record<string, SchemaColumnInput>>(
276
+ name: string,
277
+ columns: C,
278
+ ): SchemaTableWithColumns<{ [K in keyof C]: SchemaColumnDecl }> {
279
+ const finalized = finalizeColumnMap(columns);
280
+ const stamped: Record<string, SchemaColumnDecl> = {};
281
+ for (const [key, col] of Object.entries(finalized)) {
282
+ stamped[key] = { ...col, tableName: name };
283
+ }
284
+ const table = {
285
+ kind: "schema-table" as const,
286
+ name,
287
+ columns: stamped,
288
+ ...stamped,
289
+ };
290
+ return table as SchemaTableWithColumns<{ [K in keyof C]: SchemaColumnDecl }>;
291
+ }
292
+
293
+ // ─── Relations (mirrors drizzle-orm `defineRelations`) ───────────────────────
294
+
295
+ /** Column path recorded by relation helpers (`r.links.code`). */
296
+ export interface RelationColumnRef {
297
+ readonly table: string;
298
+ readonly column: string;
299
+ }
300
+
301
+ /** One relation config (serializable for emit). */
302
+ export interface SchemaRelationOne {
303
+ readonly kind: "one";
304
+ readonly target: string;
305
+ readonly from?: RelationColumnRef | readonly RelationColumnRef[];
306
+ readonly to?: RelationColumnRef | readonly RelationColumnRef[];
307
+ readonly optional?: boolean;
308
+ readonly alias?: string;
309
+ }
310
+
311
+ /** Many relation config (serializable for emit). */
312
+ export interface SchemaRelationMany {
313
+ readonly kind: "many";
314
+ readonly target: string;
315
+ readonly from?: RelationColumnRef | readonly RelationColumnRef[];
316
+ readonly to?: RelationColumnRef | readonly RelationColumnRef[];
317
+ readonly alias?: string;
318
+ }
319
+
320
+ /** One named relation on a source table. */
321
+ export type SchemaRelationEntry = SchemaRelationOne | SchemaRelationMany;
322
+
323
+ /** Per-table relation map. */
324
+ export type SchemaTableRelations = Readonly<Record<string, SchemaRelationEntry>>;
325
+
326
+ /** Full relations declaration from {@link schemaRelations}. */
327
+ export interface SchemaRelationsDecl {
328
+ readonly kind: "schema-relations";
329
+ /** Export names of tables passed to {@link schemaRelations}. */
330
+ readonly tableKeys: readonly string[];
331
+ /** Table export name → relation name → config. */
332
+ readonly config: Readonly<Record<string, SchemaTableRelations>>;
333
+ }
334
+
335
+ /** Config input for one/many helpers. */
336
+ export interface RelationHelperConfig {
337
+ readonly from?: RelationColumnRef | readonly RelationColumnRef[];
338
+ readonly to?: RelationColumnRef | readonly RelationColumnRef[];
339
+ readonly optional?: boolean;
340
+ readonly alias?: string;
341
+ }
342
+
343
+ type RelationTableCols = Record<string, RelationColumnRef> & {
344
+ readonly __table: string;
345
+ };
346
+
347
+ type RelationsBuilderFor<Keys extends string> = {
348
+ readonly [K in Keys]: RelationTableCols;
349
+ } & {
350
+ readonly one: {
351
+ readonly [K in Keys]: (config?: RelationHelperConfig) => SchemaRelationOne;
352
+ };
353
+ readonly many: {
354
+ readonly [K in Keys]: (config?: RelationHelperConfig) => SchemaRelationMany;
355
+ };
356
+ };
357
+
358
+ /** Untyped relations builder (emit / dynamic paths). */
359
+ type RelationsBuilder = RelationsBuilderFor<string>;
360
+
361
+ /**
362
+ * Whether a value is a {@link SchemaRelationsDecl}.
363
+ *
364
+ * @param value - Unknown
365
+ */
366
+ export function isSchemaRelationsDecl(value: unknown): value is SchemaRelationsDecl {
367
+ return (
368
+ !!value &&
369
+ typeof value === "object" &&
370
+ (value as SchemaRelationsDecl).kind === "schema-relations" &&
371
+ Array.isArray((value as SchemaRelationsDecl).tableKeys) &&
372
+ typeof (value as SchemaRelationsDecl).config === "object"
373
+ );
374
+ }
375
+
376
+ function columnRefFrom(value: unknown): RelationColumnRef | undefined {
377
+ if (!value || typeof value !== "object") return undefined;
378
+ const col = value as SchemaColumnDecl & RelationColumnRef;
379
+ if (typeof col.table === "string" && typeof col.column === "string") {
380
+ return { table: col.table, column: col.column };
381
+ }
382
+ if (isSchemaColumnDecl(col) && typeof col.tableName === "string" && typeof col.key === "string") {
383
+ return { table: col.tableName, column: col.key };
384
+ }
385
+ return undefined;
386
+ }
387
+
388
+ function normalizeColRefs(
389
+ value: RelationColumnRef | readonly RelationColumnRef[] | undefined,
390
+ ): RelationColumnRef | readonly RelationColumnRef[] | undefined {
391
+ if (value === undefined) return undefined;
392
+ if (Array.isArray(value)) {
393
+ const out: RelationColumnRef[] = [];
394
+ for (const item of value) {
395
+ const ref = columnRefFrom(item) ?? (item as RelationColumnRef);
396
+ if (ref?.table && ref?.column) out.push({ table: ref.table, column: ref.column });
397
+ }
398
+ return out.length === 1 ? out[0] : out;
399
+ }
400
+ return columnRefFrom(value) ?? value;
401
+ }
402
+
403
+ /**
404
+ * Build recording helpers isomorphic to drizzle-orm `defineRelations` helpers.
405
+ *
406
+ * @param tableKeys - Export names of tables in the schema object
407
+ * @param tables - Table decls keyed by export name
408
+ */
409
+ function createRelationsBuilder(
410
+ tableKeys: readonly string[],
411
+ tables: Readonly<Record<string, SchemaTableDecl>>,
412
+ ): RelationsBuilder {
413
+ const builder: Record<string, unknown> = {};
414
+
415
+ for (const key of tableKeys) {
416
+ const table = tables[key];
417
+ if (!table) continue;
418
+ const cols = { __table: table.name } as RelationTableCols;
419
+ for (const [colKey] of Object.entries(table.columns)) {
420
+ cols[colKey] = { table: key, column: colKey };
421
+ }
422
+ builder[key] = cols;
423
+ }
424
+
425
+ const one: Record<string, (config?: RelationHelperConfig) => SchemaRelationOne> = {};
426
+ const many: Record<string, (config?: RelationHelperConfig) => SchemaRelationMany> = {};
427
+
428
+ for (const key of tableKeys) {
429
+ one[key] = (config) => ({
430
+ kind: "one",
431
+ target: key,
432
+ ...(config?.from !== undefined ? { from: normalizeColRefs(config.from) } : {}),
433
+ ...(config?.to !== undefined ? { to: normalizeColRefs(config.to) } : {}),
434
+ ...(config?.optional !== undefined ? { optional: config.optional } : {}),
435
+ ...(config?.alias !== undefined ? { alias: config.alias } : {}),
436
+ });
437
+ many[key] = (config) => ({
438
+ kind: "many",
439
+ target: key,
440
+ ...(config?.from !== undefined ? { from: normalizeColRefs(config.from) } : {}),
441
+ ...(config?.to !== undefined ? { to: normalizeColRefs(config.to) } : {}),
442
+ ...(config?.alias !== undefined ? { alias: config.alias } : {}),
443
+ });
444
+ }
445
+
446
+ builder.one = one;
447
+ builder.many = many;
448
+ return builder as RelationsBuilder;
449
+ }
450
+
451
+ /**
452
+ * Declare abstract relations — mirrors drizzle-orm `defineRelations` shape.
453
+ *
454
+ * @param tables - Schema object of {@link SchemaTableDecl}s (export-name keys)
455
+ * @param configure - `(r) => ({ links: { daily: r.many.daily({ from, to }) } })`
456
+ */
457
+ export function schemaRelations<T extends Readonly<Record<string, SchemaTableDecl>>>(
458
+ tables: T,
459
+ configure: (
460
+ r: RelationsBuilderFor<Extract<keyof T, string>>,
461
+ ) => Readonly<Record<string, SchemaTableRelations | undefined>>,
462
+ ): SchemaRelationsDecl {
463
+ const tableKeys = Object.keys(tables).filter((k) => isSchemaTableDecl(tables[k]));
464
+ const tableMap: Record<string, SchemaTableDecl> = {};
465
+ for (const k of tableKeys) {
466
+ tableMap[k] = tables[k]!;
467
+ }
468
+ const builder = createRelationsBuilder(tableKeys, tableMap) as RelationsBuilderFor<
469
+ Extract<keyof T, string>
470
+ >;
471
+ const raw = configure(builder);
472
+ const config: Record<string, SchemaTableRelations> = {};
473
+ for (const [tableKey, rels] of Object.entries(raw)) {
474
+ if (!rels) continue;
475
+ config[tableKey] = rels;
476
+ }
477
+ return {
478
+ kind: "schema-relations",
479
+ tableKeys,
480
+ config,
481
+ };
482
+ }
483
+
484
+ /** `store.schema` namespace — avoids colliding with {@link SqlStoreDecl.table} CDC. */
485
+ export const schema = {
486
+ table: schemaTable,
487
+ relations: schemaRelations,
488
+ } as const;
489
+
490
+ /**
491
+ * Collect {@link SchemaTableDecl} values from a module's exports.
492
+ *
493
+ * @param mod - Module namespace object
494
+ */
495
+ export function tablesFromExports(mod: Readonly<Record<string, unknown>>): SchemaTableDecl[] {
496
+ const out: SchemaTableDecl[] = [];
497
+ for (const value of Object.values(mod)) {
498
+ if (isSchemaTableDecl(value)) out.push(value);
499
+ }
500
+ return out;
501
+ }
502
+
503
+ /**
504
+ * Collect {@link SchemaRelationsDecl} values from a module's exports.
505
+ *
506
+ * @param mod - Module namespace object
507
+ */
508
+ export function relationsFromExports(
509
+ mod: Readonly<Record<string, unknown>>,
510
+ ): SchemaRelationsDecl[] {
511
+ const out: SchemaRelationsDecl[] = [];
512
+ for (const value of Object.values(mod)) {
513
+ if (isSchemaRelationsDecl(value)) out.push(value);
514
+ }
515
+ return out;
516
+ }
@@ -55,19 +55,17 @@ export function compileWhere(where: unknown): CompiledWhere {
55
55
  }
56
56
 
57
57
  if (typeof where === "object" && !Array.isArray(where)) {
58
- const predicates: CompiledPredicate[] = Object.entries(
59
- where as WhereMap,
60
- ).map(([column, value]) => ({
61
- column,
62
- op: "=" as const,
63
- value,
64
- }));
58
+ const predicates: CompiledPredicate[] = Object.entries(where as WhereMap).map(
59
+ ([column, value]) => ({
60
+ column,
61
+ op: "=" as const,
62
+ value,
63
+ }),
64
+ );
65
65
  return predicatesToWhere(predicates);
66
66
  }
67
67
 
68
- throw new TypeError(
69
- "sql where: expected equality map or Drizzle SQL condition",
70
- );
68
+ throw new TypeError("sql where: expected equality map or Drizzle SQL condition");
71
69
  }
72
70
 
73
71
  /**
@@ -75,15 +73,11 @@ export function compileWhere(where: unknown): CompiledWhere {
75
73
  *
76
74
  * @param predicates - Ordered predicates
77
75
  */
78
- function predicatesToWhere(
79
- predicates: readonly CompiledPredicate[],
80
- ): CompiledWhere {
76
+ function predicatesToWhere(predicates: readonly CompiledPredicate[]): CompiledWhere {
81
77
  if (predicates.length === 0) {
82
78
  return { clause: "", params: [], predicates: [] };
83
79
  }
84
- const clause = predicates
85
- .map((p) => `${quoteIdent(p.column)} ${p.op} ?`)
86
- .join(" AND ");
80
+ const clause = predicates.map((p) => `${quoteIdent(p.column)} ${p.op} ?`).join(" AND ");
87
81
  return {
88
82
  clause,
89
83
  params: predicates.map((p) => p.value),
@@ -138,11 +132,7 @@ function asColumn(chunk: unknown): string | undefined {
138
132
  function asOperator(chunk: unknown): CompiledPredicate["op"] | undefined {
139
133
  if (!chunk || typeof chunk !== "object") return undefined;
140
134
  const value = (chunk as { value?: unknown }).value;
141
- const text = Array.isArray(value)
142
- ? value.join("")
143
- : typeof value === "string"
144
- ? value
145
- : "";
135
+ const text = Array.isArray(value) ? value.join("") : typeof value === "string" ? value : "";
146
136
  const trimmed = text.trim();
147
137
  switch (trimmed) {
148
138
  case "=":
@@ -0,0 +1,50 @@
1
+ /**
2
+ * SqlStoreHandle surface lock — single-table SQL session only.
3
+ *
4
+ * Relational `with:` / Drizzle RQB (`db.query.*.findMany({ with })`) is a
5
+ * documented limitation: effects, cache keys, and PII masking assume one
6
+ * table per call, so no relational query surface may appear on the handle.
7
+ */
8
+
9
+ import { describe, expect, test } from "bun:test";
10
+ import { Database } from "bun:sqlite";
11
+ import { sqliteDriver } from "../../drivers/sqlite.ts";
12
+ import { createSqlStoreHandle } from "./sql-session.ts";
13
+
14
+ describe("SqlStoreHandle — no relational query surface (path b)", () => {
15
+ test("created handle exposes exactly the single-table surface", async () => {
16
+ const db = new Database(":memory:");
17
+ const conn = await sqliteDriver.connect({ client: db, role: "primary" });
18
+ const handle = createSqlStoreHandle("sql:app", {
19
+ connection: conn,
20
+ classifications: new Map(),
21
+ routedRole: "primary",
22
+ domainDdl: "ensure",
23
+ });
24
+
25
+ expect(Object.keys(handle).sort()).toEqual(
26
+ [
27
+ "ref",
28
+ "routedRole",
29
+ "driverId",
30
+ "select",
31
+ "insert",
32
+ "update",
33
+ "findById",
34
+ "delete",
35
+ "exists",
36
+ "increment",
37
+ "raw",
38
+ "ensureTable",
39
+ ].sort(),
40
+ );
41
+
42
+ // No Drizzle RQB / with: surface — ever.
43
+ expect("query" in handle).toBe(false);
44
+ expect("findMany" in handle).toBe(false);
45
+ expect("findFirst" in handle).toBe(false);
46
+ expect("with" in handle).toBe(false);
47
+
48
+ await conn.close();
49
+ });
50
+ });