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
@@ -8,12 +8,15 @@
8
8
  /**
9
9
  * Environment role keys used in driver maps.
10
10
  *
11
- * - `dev` — local laptop (`oke dev`)
12
- * - `stack` — local server (`oke dev -s` / compose infra + host Bun)
11
+ * - `local` — laptop defaults (`oke dev` / `oke dev -l`)
12
+ * - `docker` — compose infra + host Bun (`oke dev -d`)
13
13
  * - `test` — automated tests
14
14
  * - `prod` — production deploy
15
15
  */
16
- export type ConfigEnv = "dev" | "stack" | "test" | "prod";
16
+ export type ConfigEnv = "local" | "docker" | "test" | "prod";
17
+
18
+ /** Legacy driver-map keys accepted during soft-compat migration. */
19
+ type LegacyConfigEnv = "dev" | "stack";
17
20
 
18
21
  /** Pool options for SQL drivers. */
19
22
  export interface DriverPoolOptions {
@@ -38,6 +41,12 @@ export type DriverRef =
38
41
  /** Map of env → driver ref. */
39
42
  export type EnvDriverMap = Partial<Record<ConfigEnv, DriverRef>>;
40
43
 
44
+ /**
45
+ * Raw map that may still use deprecated `dev` / `stack` keys.
46
+ * Normalized by {@link normalizeEnvDriverMap}.
47
+ */
48
+ export type RawEnvDriverMap = Partial<Record<ConfigEnv | LegacyConfigEnv, DriverRef>>;
49
+
41
50
  /** Store facet driver maps. */
42
51
  export interface StoreDriversConfig {
43
52
  readonly sql?: EnvDriverMap;
@@ -92,9 +101,7 @@ export interface TenancyResolveContext {
92
101
  export interface TenancyConfig {
93
102
  readonly isolation?: "row" | "schema" | "database";
94
103
  /** Tenant resolver — opaque string id or function (Skyport). */
95
- readonly resolve?:
96
- | string
97
- | ((ctx: TenancyResolveContext) => string | null | undefined);
104
+ readonly resolve?: string | ((ctx: TenancyResolveContext) => string | null | undefined);
98
105
  }
99
106
 
100
107
  /** Port overrides (defaults: app 6530 · console 6533 · mcp 6535). */
@@ -126,6 +133,42 @@ export interface RunsConfig {
126
133
  */
127
134
  export type PrivacyConfig = Readonly<Record<string, unknown>>;
128
135
 
136
+ /**
137
+ * Domain schema sync via drizzle-kit (`oke db push|generate|migrate`).
138
+ *
139
+ * Distinct from `oke schema generate` (core/plugin stub tables).
140
+ */
141
+ export interface DbConfig {
142
+ /**
143
+ * Auto-run `oke db push` when domain schema files change under `oke dev`
144
+ * (local mode only). Default `true`. Set `false` to opt out explicitly.
145
+ * Forced off for `docker` / `prod`.
146
+ */
147
+ readonly autoPush?: boolean;
148
+ /**
149
+ * Path to `drizzle.config.ts` (relative to project root).
150
+ * Default `"drizzle.config.ts"`.
151
+ */
152
+ readonly config?: string;
153
+ /**
154
+ * Abstract schema declare module (`store.schema.table` exports).
155
+ * When present, `oke db` emits Drizzle into {@link generated} before sync.
156
+ * Default `"src/schema.decl.ts"` (emit skipped if the file is absent).
157
+ */
158
+ readonly declare?: string;
159
+ /**
160
+ * Generated Drizzle schema path written from abstract decls.
161
+ * Default `"src/schema.generated.ts"`. Point `drizzle.config.ts` `schema`
162
+ * at this file when using the abstract path.
163
+ */
164
+ readonly generated?: string;
165
+ /**
166
+ * App entry used to collect live `.plug()` table contributions for emit.
167
+ * Default: `package.json` `okengine.entry` / `src/app.ts` (same as `oke start`).
168
+ */
169
+ readonly entry?: string;
170
+ }
171
+
129
172
  /**
130
173
  * Application config returned by {@link defineConfig}.
131
174
  */
@@ -144,108 +187,209 @@ export interface OkeConfig {
144
187
  * Not the same key as `drivers.runs`.
145
188
  */
146
189
  readonly runs?: RunsConfig;
190
+ /**
191
+ * Domain Drizzle schema sync (`oke db …`). Not related to `oke schema`.
192
+ */
193
+ readonly db?: DbConfig;
147
194
  readonly topology?: "monolith" | "services";
148
195
  readonly ports?: PortsConfig;
149
196
  readonly console?: ConsoleConfig;
150
197
  }
151
198
 
152
199
  /**
153
- * Fill missing `stack` pins from `prod` (local server production protocols).
200
+ * Whether domain auto-DDL (`ensureFromMeta`) should run for this env.
201
+ *
202
+ * - `ensure` — `CREATE TABLE IF NOT EXISTS` on first touch (test / local opt-out)
203
+ * - `off` — migrations / `oke db push` own DDL (docker, prod, local+autoPush)
204
+ */
205
+ export type DomainDdlMode = "ensure" | "off";
206
+
207
+ /**
208
+ * Resolve domain DDL policy from env + `db.autoPush`.
209
+ *
210
+ * @param env - Active config env
211
+ * @param autoPush - Effective auto-push flag (default true)
212
+ */
213
+ export function resolveDomainDdlMode(env: ConfigEnv, autoPush = true): DomainDdlMode {
214
+ if (env === "test") return "ensure";
215
+ if (env === "docker" || env === "prod") return "off";
216
+ return autoPush ? "off" : "ensure";
217
+ }
218
+
219
+ /** Whether a legacy-key deprecation warning was already emitted this process. */
220
+ let legacyKeyWarned = false;
221
+
222
+ /**
223
+ * Normalize deprecated `dev`/`stack` driver-map keys to `local`/`docker`.
224
+ *
225
+ * Emits a one-time stderr warning when legacy keys are present.
226
+ *
227
+ * @param raw - Env → driver map (possibly legacy keys)
228
+ */
229
+ export function normalizeEnvDriverMap(
230
+ raw: RawEnvDriverMap | EnvDriverMap | undefined,
231
+ ): EnvDriverMap | undefined {
232
+ if (!raw) return undefined;
233
+ const hasLegacy =
234
+ (raw as RawEnvDriverMap).dev !== undefined || (raw as RawEnvDriverMap).stack !== undefined;
235
+ if (hasLegacy && !legacyKeyWarned) {
236
+ legacyKeyWarned = true;
237
+ console.warn(
238
+ "oke: driver map keys `dev`/`stack` are deprecated — use `local`/`docker` (run `oke upgrade`)",
239
+ );
240
+ }
241
+ const out: EnvDriverMap = { ...(raw as EnvDriverMap) };
242
+ const legacy = raw as RawEnvDriverMap;
243
+ if (legacy.local === undefined && legacy.dev !== undefined) {
244
+ out.local = legacy.dev;
245
+ }
246
+ if (legacy.docker === undefined && legacy.stack !== undefined) {
247
+ out.docker = legacy.stack;
248
+ }
249
+ delete (out as RawEnvDriverMap).dev;
250
+ delete (out as RawEnvDriverMap).stack;
251
+ return out;
252
+ }
253
+
254
+ /**
255
+ * Normalize every env map under a drivers block.
154
256
  *
155
- * Vault is the exception: `prod: "sops"` becomes `stack: "dotenv"` so
156
- * `oke dev -s` can read `.env.stack` without age keys.
257
+ * @param drivers - Drivers block
258
+ */
259
+ export function normalizeDriversConfig(
260
+ drivers: DriversConfig | undefined,
261
+ ): DriversConfig | undefined {
262
+ if (!drivers) return undefined;
263
+ const store = drivers.store
264
+ ? {
265
+ ...drivers.store,
266
+ sql: normalizeEnvDriverMap(drivers.store.sql as RawEnvDriverMap),
267
+ kv: normalizeEnvDriverMap(drivers.store.kv as RawEnvDriverMap),
268
+ files: normalizeEnvDriverMap(drivers.store.files as RawEnvDriverMap),
269
+ index: normalizeEnvDriverMap(drivers.store.index as RawEnvDriverMap),
270
+ }
271
+ : undefined;
272
+ const channel = drivers.channel
273
+ ? {
274
+ ...drivers.channel,
275
+ email: normalizeEnvDriverMap(drivers.channel.email as RawEnvDriverMap),
276
+ sms: normalizeEnvDriverMap(drivers.channel.sms as RawEnvDriverMap),
277
+ whatsapp: normalizeEnvDriverMap(drivers.channel.whatsapp as RawEnvDriverMap),
278
+ push: normalizeEnvDriverMap(drivers.channel.push as RawEnvDriverMap),
279
+ }
280
+ : undefined;
281
+ return {
282
+ ...drivers,
283
+ ...(store !== undefined ? { store } : {}),
284
+ signal: normalizeEnvDriverMap(drivers.signal as RawEnvDriverMap),
285
+ clock: normalizeEnvDriverMap(drivers.clock as RawEnvDriverMap),
286
+ vault: normalizeEnvDriverMap(drivers.vault as RawEnvDriverMap),
287
+ ...(channel !== undefined ? { channel } : {}),
288
+ ai: normalizeEnvDriverMap(drivers.ai as RawEnvDriverMap),
289
+ runs: normalizeEnvDriverMap(drivers.runs as RawEnvDriverMap),
290
+ };
291
+ }
292
+
293
+ /**
294
+ * Fill missing `docker` pins from `prod` (compose infra ≈ production protocols).
295
+ *
296
+ * Vault is the exception: `prod: "sops"` becomes `docker: "dotenv"` so
297
+ * `oke dev -d` can read `docker/.env.docker` without age keys.
157
298
  *
158
299
  * @param map - Env → driver map
159
300
  * @param options - Element-specific defaults
160
301
  */
161
- export function fillStackFromProd(
302
+ export function fillDockerFromProd(
162
303
  map: EnvDriverMap | undefined,
163
304
  options: { readonly vault?: boolean } = {},
164
305
  ): EnvDriverMap | undefined {
165
306
  if (!map) return undefined;
166
- if (map.stack !== undefined || map.prod === undefined) return map;
307
+ if (map.docker !== undefined || map.prod === undefined) return map;
167
308
  if (options.vault) {
168
309
  const prodId = typeof map.prod === "string" ? map.prod : map.prod.driver;
169
310
  if (prodId === "sops") {
170
- return { ...map, stack: "dotenv" };
311
+ return { ...map, docker: "dotenv" };
171
312
  }
172
313
  }
173
- return { ...map, stack: map.prod };
314
+ return { ...map, docker: map.prod };
174
315
  }
175
316
 
176
317
  /**
177
- * Copy production driver pins onto `stack` wherever `stack` is omitted.
318
+ * Copy production driver pins onto `docker` wherever `docker` is omitted.
178
319
  *
179
320
  * @param drivers - Drivers block
180
321
  */
181
- export function fillDriversStackFromProd(
322
+ export function fillDriversDockerFromProd(
182
323
  drivers: DriversConfig | undefined,
183
324
  ): DriversConfig | undefined {
184
325
  if (!drivers) return undefined;
185
326
  const store = drivers.store
186
327
  ? {
187
328
  ...drivers.store,
188
- sql: fillStackFromProd(drivers.store.sql),
189
- kv: fillStackFromProd(drivers.store.kv),
190
- files: fillStackFromProd(drivers.store.files),
191
- index: fillStackFromProd(drivers.store.index),
329
+ sql: fillDockerFromProd(drivers.store.sql),
330
+ kv: fillDockerFromProd(drivers.store.kv),
331
+ files: fillDockerFromProd(drivers.store.files),
332
+ index: fillDockerFromProd(drivers.store.index),
192
333
  }
193
334
  : undefined;
194
335
  const channel = drivers.channel
195
336
  ? {
196
337
  ...drivers.channel,
197
- email: fillStackFromProd(drivers.channel.email),
198
- sms: fillStackFromProd(drivers.channel.sms),
199
- whatsapp: fillStackFromProd(drivers.channel.whatsapp),
200
- push: fillStackFromProd(drivers.channel.push),
338
+ email: fillDockerFromProd(drivers.channel.email),
339
+ sms: fillDockerFromProd(drivers.channel.sms),
340
+ whatsapp: fillDockerFromProd(drivers.channel.whatsapp),
341
+ push: fillDockerFromProd(drivers.channel.push),
201
342
  }
202
343
  : undefined;
203
344
  return {
204
345
  ...drivers,
205
346
  ...(store !== undefined ? { store } : {}),
206
- signal: fillStackFromProd(drivers.signal),
207
- clock: fillStackFromProd(drivers.clock),
208
- vault: fillStackFromProd(drivers.vault, { vault: true }),
347
+ signal: fillDockerFromProd(drivers.signal),
348
+ clock: fillDockerFromProd(drivers.clock),
349
+ vault: fillDockerFromProd(drivers.vault, { vault: true }),
209
350
  ...(channel !== undefined ? { channel } : {}),
210
- ai: fillStackFromProd(drivers.ai),
211
- runs: fillStackFromProd(drivers.runs),
351
+ ai: fillDockerFromProd(drivers.ai),
352
+ runs: fillDockerFromProd(drivers.runs),
212
353
  };
213
354
  }
214
355
 
215
356
  /**
216
357
  * Define an `oke.config.ts` document.
217
358
  *
218
- * Missing `stack` driver pins are filled from `prod` so `oke dev -s` uses the
219
- * same server protocols as production (vault → dotenv for `.env.stack`).
359
+ * Missing `docker` driver pins are filled from `prod` so `oke dev -d` uses the
360
+ * same server protocols as production (vault → dotenv for `docker/.env.docker`).
361
+ * Legacy `dev`/`stack` keys are normalized to `local`/`docker`.
220
362
  *
221
363
  * @param config - Driver / tenancy / i18n / topology
222
364
  */
223
365
  export function defineConfig(config: OkeConfig): OkeConfig {
224
366
  if (!config.drivers) return config;
367
+ const normalized = normalizeDriversConfig(config.drivers);
225
368
  return {
226
369
  ...config,
227
- drivers: fillDriversStackFromProd(config.drivers),
370
+ drivers: fillDriversDockerFromProd(normalized),
228
371
  };
229
372
  }
230
373
 
231
374
  /**
232
375
  * Resolve a driver id for an env from an {@link EnvDriverMap}.
233
376
  *
234
- * `stack` falls back to `prod` then `dev` so existing configs keep working
235
- * until an explicit `stack:` pin is added.
377
+ * `docker` falls back to `prod` then `local` so existing configs keep working
378
+ * until an explicit `docker:` pin is added. Legacy keys are normalized first.
236
379
  *
237
380
  * @param map - Env → driver map
238
381
  * @param env - Active environment
239
382
  */
240
383
  export function resolveDriverId(
241
- map: EnvDriverMap | undefined,
384
+ map: EnvDriverMap | RawEnvDriverMap | undefined,
242
385
  env: ConfigEnv,
243
386
  ): string | undefined {
244
387
  if (!map) return undefined;
388
+ const normalized = normalizeEnvDriverMap(map as RawEnvDriverMap) ?? map;
245
389
  const ref =
246
- env === "stack"
247
- ? (map.stack ?? map.prod ?? map.dev ?? map.test)
248
- : (map[env] ?? map.dev ?? map.test);
390
+ env === "docker"
391
+ ? (normalized.docker ?? normalized.prod ?? normalized.local ?? normalized.test)
392
+ : (normalized[env] ?? normalized.local ?? normalized.test);
249
393
  if (ref === undefined) return undefined;
250
394
  return typeof ref === "string" ? ref : ref.driver;
251
395
  }
@@ -1,30 +1,41 @@
1
1
  /**
2
- * Driver map resolution — including `stack` → prod fallback.
2
+ * Driver map resolution — including `docker` → prod fallback.
3
3
  */
4
4
 
5
5
  import { describe, expect, test } from "bun:test";
6
- import { resolveDriverId } from "./index.ts";
6
+ import { resolveDomainDdlMode, resolveDriverId } from "./index.ts";
7
+
8
+ describe("resolveDomainDdlMode", () => {
9
+ test("test keeps ensure; docker/prod always off", () => {
10
+ expect(resolveDomainDdlMode("test", true)).toBe("ensure");
11
+ expect(resolveDomainDdlMode("docker", true)).toBe("off");
12
+ expect(resolveDomainDdlMode("prod", true)).toBe("off");
13
+ });
14
+
15
+ test("local follows autoPush", () => {
16
+ expect(resolveDomainDdlMode("local", true)).toBe("off");
17
+ expect(resolveDomainDdlMode("local", false)).toBe("ensure");
18
+ });
19
+ });
7
20
 
8
21
  describe("resolveDriverId", () => {
9
22
  test("reads the named env key", () => {
10
- expect(
11
- resolveDriverId({ dev: "sqlite", prod: "postgres" }, "dev"),
12
- ).toBe("sqlite");
13
- expect(
14
- resolveDriverId({ dev: "sqlite", prod: "postgres" }, "prod"),
15
- ).toBe("postgres");
23
+ expect(resolveDriverId({ local: "sqlite", prod: "postgres" }, "local")).toBe("sqlite");
24
+ expect(resolveDriverId({ local: "sqlite", prod: "postgres" }, "prod")).toBe("postgres");
16
25
  });
17
26
 
18
- test("stack prefers stack, then prod, then dev", () => {
19
- expect(
20
- resolveDriverId(
21
- { dev: "sqlite", stack: "postgres", prod: "postgres" },
22
- "stack",
23
- ),
24
- ).toBe("postgres");
27
+ test("docker prefers docker, then prod, then local", () => {
25
28
  expect(
26
- resolveDriverId({ dev: "sqlite", prod: "postgres" }, "stack"),
29
+ resolveDriverId({ local: "sqlite", docker: "postgres", prod: "postgres" }, "docker"),
27
30
  ).toBe("postgres");
28
- expect(resolveDriverId({ dev: "sqlite" }, "stack")).toBe("sqlite");
31
+ expect(resolveDriverId({ local: "sqlite", prod: "postgres" }, "docker")).toBe("postgres");
32
+ expect(resolveDriverId({ local: "sqlite" }, "docker")).toBe("sqlite");
33
+ });
34
+
35
+ test("legacy keys resolve after normalize", () => {
36
+ expect(resolveDriverId({ dev: "sqlite", stack: "postgres" } as never, "local")).toBe("sqlite");
37
+ expect(resolveDriverId({ dev: "sqlite", stack: "postgres" } as never, "docker")).toBe(
38
+ "postgres",
39
+ );
29
40
  });
30
41
  });
@@ -32,10 +32,7 @@ describe("console bundle budget", () => {
32
32
  console.log(
33
33
  "other (not initial, not panel-*):\n" +
34
34
  breakdown.other
35
- .map(
36
- (a) =>
37
- ` ${a.name}: ${a.gzip} (${(a.gzip / 1024).toFixed(2)} kB)`,
38
- )
35
+ .map((a) => ` ${a.name}: ${a.gzip} (${(a.gzip / 1024).toFixed(2)} kB)`)
39
36
  .join("\n"),
40
37
  );
41
38
  }
@@ -37,7 +37,4 @@ export {
37
37
  type ConsoleServerHandle,
38
38
  type ServeConsoleOptions,
39
39
  } from "./server/serve.ts";
40
- export {
41
- createConsoleState,
42
- type ConsoleState,
43
- } from "./server/state.ts";
40
+ export { createConsoleState, type ConsoleState } from "./server/state.ts";
@@ -126,26 +126,14 @@ describe("projectAccessPanel", () => {
126
126
  expect(projection.userPlane.operators).toBeUndefined();
127
127
 
128
128
  // Cross-plane scopes absent from grantable lists.
129
- expect(
130
- projection.operatorPlane.grantableScopes.every((s) =>
131
- s.startsWith("console:"),
132
- ),
133
- ).toBe(true);
134
- expect(
135
- projection.userPlane.grantableScopes.every(
136
- (s) => !s.startsWith("console:"),
137
- ),
138
- ).toBe(true);
139
-
140
- expect(projection.hygiene.unusedKeys.some((k) => k.id === "key_stale")).toBe(
129
+ expect(projection.operatorPlane.grantableScopes.every((s) => s.startsWith("console:"))).toBe(
141
130
  true,
142
131
  );
143
- expect(
144
- projection.hygiene.neverSignedInOperators.some((o) => o.id === "op_never"),
145
- ).toBe(true);
146
- expect(
147
- projection.hygiene.expiredInvitations.some((i) => i.id === "inv1"),
148
- ).toBe(true);
132
+ expect(projection.userPlane.grantableScopes.every((s) => !s.startsWith("console:"))).toBe(true);
133
+
134
+ expect(projection.hygiene.unusedKeys.some((k) => k.id === "key_stale")).toBe(true);
135
+ expect(projection.hygiene.neverSignedInOperators.some((o) => o.id === "op_never")).toBe(true);
136
+ expect(projection.hygiene.expiredInvitations.some((i) => i.id === "inv1")).toBe(true);
149
137
  });
150
138
 
151
139
  test("scope not held is not grantable (absence, not refusal)", () => {
@@ -163,12 +151,8 @@ describe("projectAccessPanel", () => {
163
151
  now: () => 0,
164
152
  });
165
153
  expect(projection.userPlane.grantableScopes).not.toContain("booking:create");
166
- expect(projection.operatorPlane.grantableScopes).toContain(
167
- "console:store.sql:read",
168
- );
169
- expect(projection.operatorPlane.grantableScopes).not.toContain(
170
- "console:store.sql:write",
171
- );
154
+ expect(projection.operatorPlane.grantableScopes).toContain("console:store.sql:read");
155
+ expect(projection.operatorPlane.grantableScopes).not.toContain("console:store.sql:write");
172
156
  });
173
157
  });
174
158
 
@@ -266,9 +250,7 @@ describe("keyBlastRadius", () => {
266
250
  expect(blast.lastUsedAt).toBe(200);
267
251
  expect(blast.sourceAddresses).toEqual(["198.51.100.7", "203.0.113.10"]);
268
252
  expect(blast.accessTtlMs).toBe(ttl);
269
- expect(blast.residualAccessNote).toBe(
270
- residualAccessNote(ttl),
271
- );
253
+ expect(blast.residualAccessNote).toBe(residualAccessNote(ttl));
272
254
  expect(blast.residualAccessNote).toContain("7 minute");
273
255
  });
274
256
  });
@@ -331,22 +313,16 @@ describe("accessCreateKey / revoke", () => {
331
313
 
332
314
  describe("helpers", () => {
333
315
  test("expandAccessCeiling adds application scopes for console:*", () => {
334
- const held = expandAccessCeiling(["console:*"], [
335
- "console:store.sql:read",
336
- "booking:create",
337
- ]);
316
+ const held = expandAccessCeiling(["console:*"], ["console:store.sql:read", "booking:create"]);
338
317
  expect(held.has("console:store.sql:read")).toBe(true);
339
318
  expect(held.has("booking:create")).toBe(true);
340
319
  });
341
320
 
342
321
  test("isKeyUnused90d", () => {
343
322
  const now = () => 1_000_000 + KEY_UNUSED_MS;
344
- expect(
345
- isKeyUnused90d(
346
- { createdAt: 1_000_000, lastUsedAt: null, revokedAt: null },
347
- now,
348
- ),
349
- ).toBe(true);
323
+ expect(isKeyUnused90d({ createdAt: 1_000_000, lastUsedAt: null, revokedAt: null }, now)).toBe(
324
+ true,
325
+ );
350
326
  expect(
351
327
  isKeyUnused90d(
352
328
  {
@@ -360,11 +336,7 @@ describe("helpers", () => {
360
336
  });
361
337
 
362
338
  test("residualAccessNote uses config TTL, not a hardcoded 14", () => {
363
- expect(residualAccessNote(60_000)).toBe(
364
- "Existing access may continue up to 1 minute",
365
- );
366
- expect(residualAccessNote(90_000)).toBe(
367
- "Existing access may continue up to 2 minutes",
368
- );
339
+ expect(residualAccessNote(60_000)).toBe("Existing access may continue up to 1 minute");
340
+ expect(residualAccessNote(90_000)).toBe("Existing access may continue up to 2 minutes");
369
341
  });
370
342
  });
@@ -180,9 +180,7 @@ export interface ProjectAccessOptions {
180
180
  *
181
181
  * @param options - Auth stores + actor ceiling
182
182
  */
183
- export function projectAccessPanel(
184
- options: ProjectAccessOptions,
185
- ): AccessPanelProjection {
183
+ export function projectAccessPanel(options: ProjectAccessOptions): AccessPanelProjection {
186
184
  const now = options.now ?? (() => Date.now());
187
185
  const accessTtlMs = options.accessTtlMs ?? ACCESS_TTL_MS;
188
186
  const catalog = options.manifest
@@ -269,9 +267,7 @@ export function effectivePermissions(options: {
269
267
  .sort((a, b) => a.localeCompare(b))
270
268
  .map((scope) => ({
271
269
  scope,
272
- sources: [
273
- { kind: "direct" as const, id: key.id, name: key.name },
274
- ],
270
+ sources: [{ kind: "direct" as const, id: key.id, name: key.name }],
275
271
  })),
276
272
  };
277
273
  }
@@ -288,9 +284,7 @@ export function effectivePermissions(options: {
288
284
  plane: role.plane,
289
285
  scopes: scopes.map((scope) => ({
290
286
  scope,
291
- sources: [
292
- { kind: "role" as const, id: role.id, name: role.name },
293
- ],
287
+ sources: [{ kind: "role" as const, id: role.id, name: role.name }],
294
288
  })),
295
289
  };
296
290
  }
@@ -318,9 +312,7 @@ export function effectivePermissions(options: {
318
312
  if (covered.has(scope)) continue;
319
313
  scopes.push({
320
314
  scope,
321
- sources: [
322
- { kind: "direct" as const, id: identity.id, name: identity.name },
323
- ],
315
+ sources: [{ kind: "direct" as const, id: identity.id, name: identity.name }],
324
316
  });
325
317
  }
326
318
  scopes.sort((a, b) => a.scope.localeCompare(b.scope));
@@ -412,9 +404,7 @@ export async function accessCreateKey(
412
404
  for (const scope of input.scopes) {
413
405
  if (!allowed.has(scope)) {
414
406
  assertAttenuated(held, [scope], "api key");
415
- throw new AccessGrantError(
416
- `scope ${scope} is not grantable on the ${input.plane} plane`,
417
- );
407
+ throw new AccessGrantError(`scope ${scope} is not grantable on the ${input.plane} plane`);
418
408
  }
419
409
  }
420
410
  const created = await createApiKey(store, {
@@ -461,9 +451,7 @@ export function accessSetRoleGrants(options: {
461
451
  );
462
452
  for (const scope of options.scopes) {
463
453
  if (!allowed.has(scope)) {
464
- throw new AccessGrantError(
465
- `scope ${scope} is not grantable on the ${role.plane} plane`,
466
- );
454
+ throw new AccessGrantError(`scope ${scope} is not grantable on the ${role.plane} plane`);
467
455
  }
468
456
  }
469
457
  setRoleGrants(options.roles, options.roleId, options.scopes);
@@ -565,15 +553,13 @@ export function expandAccessCeiling(
565
553
  return out;
566
554
  }
567
555
 
568
- function projectOperators(
569
- options: ProjectAccessOptions,
570
- ): AccessOperatorRow[] {
556
+ function projectOperators(options: ProjectAccessOptions): AccessOperatorRow[] {
571
557
  const rows: AccessOperatorRow[] = [];
572
558
  for (const op of options.operators.operators.values()) {
573
559
  const roleIds = options.operators.roles.get(op.id) ?? [];
574
- const scopes = [
575
- ...scopesForRoles(options.roles, roleIds, "operator"),
576
- ].sort((a, b) => a.localeCompare(b));
560
+ const scopes = [...scopesForRoles(options.roles, roleIds, "operator")].sort((a, b) =>
561
+ a.localeCompare(b),
562
+ );
577
563
  rows.push({
578
564
  id: op.id,
579
565
  email: op.email,
@@ -592,12 +578,10 @@ function projectUsers(options: ProjectAccessOptions): AccessUserRow[] {
592
578
  return options.identities
593
579
  .map((identity) => {
594
580
  const roleIds = roleIdsForMember(options.roleMembers, identity.id);
595
- const fromRoles = [
596
- ...scopesForRoles(options.roles, roleIds, "user"),
597
- ];
598
- const scopes = [
599
- ...new Set([...fromRoles, ...identity.scopes]),
600
- ].sort((a, b) => a.localeCompare(b));
581
+ const fromRoles = [...scopesForRoles(options.roles, roleIds, "user")];
582
+ const scopes = [...new Set([...fromRoles, ...identity.scopes])].sort((a, b) =>
583
+ a.localeCompare(b),
584
+ );
601
585
  return {
602
586
  id: identity.id,
603
587
  email: identity.email,
@@ -618,19 +602,14 @@ function projectRoles(options: ProjectAccessOptions): AccessRoleRow[] {
618
602
  name: role.name,
619
603
  plane: role.plane,
620
604
  description: role.description,
621
- scopes: [...(options.roles.grants.get(role.id) ?? [])].sort((a, b) =>
622
- a.localeCompare(b),
623
- ),
605
+ scopes: [...(options.roles.grants.get(role.id) ?? [])].sort((a, b) => a.localeCompare(b)),
624
606
  memberCount: options.roleMembers.get(role.id)?.length ?? 0,
625
607
  });
626
608
  }
627
609
  return rows.sort((a, b) => a.name.localeCompare(b.name));
628
610
  }
629
611
 
630
- function projectKeys(
631
- options: ProjectAccessOptions,
632
- now: () => number,
633
- ): AccessKeyRow[] {
612
+ function projectKeys(options: ProjectAccessOptions, now: () => number): AccessKeyRow[] {
634
613
  const rows: AccessKeyRow[] = [];
635
614
  for (const key of options.apiKeys.keys.values()) {
636
615
  rows.push(toKeyRow(key, now));
@@ -638,10 +617,7 @@ function projectKeys(
638
617
  return rows.sort((a, b) => a.name.localeCompare(b.name));
639
618
  }
640
619
 
641
- function projectInvites(
642
- options: ProjectAccessOptions,
643
- now: () => number,
644
- ): AccessInviteRow[] {
620
+ function projectInvites(options: ProjectAccessOptions, now: () => number): AccessInviteRow[] {
645
621
  const rows: AccessInviteRow[] = [];
646
622
  for (const invite of options.invites.invites.values()) {
647
623
  rows.push({
@@ -714,10 +690,7 @@ function provenanceForRoles(
714
690
  roleIds: readonly string[],
715
691
  plane: "user" | "operator",
716
692
  ): AccessScopeProvenance[] {
717
- const byScope = new Map<
718
- string,
719
- { kind: "role"; id: string; name: string }[]
720
- >();
693
+ const byScope = new Map<string, { kind: "role"; id: string; name: string }[]>();
721
694
  for (const roleId of roleIds) {
722
695
  const role = roles.roles.get(roleId);
723
696
  if (!role || role.plane !== plane) continue;
@@ -762,10 +735,7 @@ function sourceAddressOf(run: WideEvent): string | null {
762
735
  return null;
763
736
  }
764
737
 
765
- function collectCatalogFromStores(
766
- roles: RoleStore,
767
- apiKeys: ApiKeyStore,
768
- ): string[] {
738
+ function collectCatalogFromStores(roles: RoleStore, apiKeys: ApiKeyStore): string[] {
769
739
  const set = new Set<string>();
770
740
  for (const grants of roles.grants.values()) {
771
741
  for (const g of grants) set.add(g);