okengine 0.1.4

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 (674) hide show
  1. package/AGENTS.md +91 -0
  2. package/README.md +327 -0
  3. package/docs/spec/complete-example.md +1188 -0
  4. package/docs/spec/console.md +739 -0
  5. package/docs/spec/four-applications.md +1188 -0
  6. package/docs/spec/unified-theory.md +489 -0
  7. package/package.json +152 -0
  8. package/spec/manifest.v1.schema.json +624 -0
  9. package/src/auth/api-keys.ts +168 -0
  10. package/src/auth/attenuation.ts +116 -0
  11. package/src/auth/auth.test.ts +273 -0
  12. package/src/auth/cross-plane.ts +98 -0
  13. package/src/auth/index.ts +112 -0
  14. package/src/auth/invites.ts +66 -0
  15. package/src/auth/invoke-as.ts +49 -0
  16. package/src/auth/operator.ts +178 -0
  17. package/src/auth/planes.ts +102 -0
  18. package/src/auth/plugin.ts +44 -0
  19. package/src/auth/roles.ts +84 -0
  20. package/src/auth/sessions.ts +418 -0
  21. package/src/auth/tables.ts +131 -0
  22. package/src/cli/args.ts +50 -0
  23. package/src/cli/branch.ts +75 -0
  24. package/src/cli/build.ts +86 -0
  25. package/src/cli/client-add.test.ts +140 -0
  26. package/src/cli/client-add.ts +164 -0
  27. package/src/cli/completion.test.ts +58 -0
  28. package/src/cli/completion.ts +296 -0
  29. package/src/cli/dev-app-runner.ts +77 -0
  30. package/src/cli/dev.test.ts +435 -0
  31. package/src/cli/dev.ts +594 -0
  32. package/src/cli/doc-drift.test.ts +146 -0
  33. package/src/cli/doc-drift.ts +397 -0
  34. package/src/cli/docker-cli.test.ts +221 -0
  35. package/src/cli/docker.ts +127 -0
  36. package/src/cli/doctor-diff-examples.ts +92 -0
  37. package/src/cli/doctor-diff.test.ts +91 -0
  38. package/src/cli/doctor-diff.ts +274 -0
  39. package/src/cli/doctor-pii.test.ts +98 -0
  40. package/src/cli/doctor-pii.ts +151 -0
  41. package/src/cli/doctor.test.ts +150 -0
  42. package/src/cli/doctor.ts +223 -0
  43. package/src/cli/eval.ts +122 -0
  44. package/src/cli/exit.ts +19 -0
  45. package/src/cli/gates-list.test.ts +47 -0
  46. package/src/cli/gates-list.ts +84 -0
  47. package/src/cli/images.ts +277 -0
  48. package/src/cli/index.ts +99 -0
  49. package/src/cli/json-out.test.ts +129 -0
  50. package/src/cli/load-config.ts +71 -0
  51. package/src/cli/mcp-from-console.ts +50 -0
  52. package/src/cli/privacy-erase.ts +73 -0
  53. package/src/cli/registry.ts +455 -0
  54. package/src/cli/safe-defaults.test.ts +92 -0
  55. package/src/cli/schema.ts +196 -0
  56. package/src/cli/stack.ts +82 -0
  57. package/src/cli/start.ts +106 -0
  58. package/src/cli/upgrade.ts +105 -0
  59. package/src/cli/vault-cmd.ts +140 -0
  60. package/src/client/budget-entry.ts +34 -0
  61. package/src/client/budget.test.ts +17 -0
  62. package/src/client/create.test.ts +159 -0
  63. package/src/client/create.ts +152 -0
  64. package/src/client/errors.ts +60 -0
  65. package/src/client/index.ts +35 -0
  66. package/src/client/notes-contract.test.ts +289 -0
  67. package/src/client/transport.test.ts +123 -0
  68. package/src/client/transport.ts +254 -0
  69. package/src/client/types.ts +282 -0
  70. package/src/compiler/aot.test.ts +248 -0
  71. package/src/compiler/aot.ts +182 -0
  72. package/src/compiler/differential.test.ts +241 -0
  73. package/src/compiler/dynamic.ts +54 -0
  74. package/src/compiler/effects-infer.ts +541 -0
  75. package/src/compiler/emit.ts +40 -0
  76. package/src/compiler/extract.test.ts +177 -0
  77. package/src/compiler/extract.ts +1368 -0
  78. package/src/compiler/fixtures/raw/raw-unannotated.ts +28 -0
  79. package/src/compiler/fixtures/skyport/oke.config.ts +24 -0
  80. package/src/compiler/fixtures/skyport/src/ai.ts +15 -0
  81. package/src/compiler/fixtures/skyport/src/app.ts +10 -0
  82. package/src/compiler/fixtures/skyport/src/channels.ts +6 -0
  83. package/src/compiler/fixtures/skyport/src/core.ts +3 -0
  84. package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +57 -0
  85. package/src/compiler/fixtures/skyport/src/flows/bookings/signals.ts +11 -0
  86. package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +14 -0
  87. package/src/compiler/fixtures/skyport/src/flows/support/index.ts +20 -0
  88. package/src/compiler/fixtures/skyport/src/gates.ts +14 -0
  89. package/src/compiler/fixtures/skyport/src/journeys.ts +9 -0
  90. package/src/compiler/fixtures/skyport/src/schema.ts +3 -0
  91. package/src/compiler/fixtures/skyport/src/vault.ts +6 -0
  92. package/src/compiler/fixtures/skyport.expected.json +241 -0
  93. package/src/compiler/fixtures/triggers/five-triggers.ts +69 -0
  94. package/src/compiler/http-parse.ts +214 -0
  95. package/src/compiler/index.ts +67 -0
  96. package/src/compiler/response.ts +89 -0
  97. package/src/compiler/sucrose.ts +238 -0
  98. package/src/config/index.ts +167 -0
  99. package/src/console/budget.test.ts +73 -0
  100. package/src/console/index.ts +30 -0
  101. package/src/console/server/access.test.ts +370 -0
  102. package/src/console/server/access.ts +777 -0
  103. package/src/console/server/ai.test.ts +172 -0
  104. package/src/console/server/ai.ts +632 -0
  105. package/src/console/server/app.ts +294 -0
  106. package/src/console/server/auth-rate.test.ts +81 -0
  107. package/src/console/server/auth-rate.ts +72 -0
  108. package/src/console/server/bind.ts +25 -0
  109. package/src/console/server/channels.test.ts +179 -0
  110. package/src/console/server/channels.ts +469 -0
  111. package/src/console/server/claim.test.ts +66 -0
  112. package/src/console/server/claim.ts +134 -0
  113. package/src/console/server/clock.test.ts +239 -0
  114. package/src/console/server/clock.ts +390 -0
  115. package/src/console/server/console.test.ts +338 -0
  116. package/src/console/server/diff.test.ts +299 -0
  117. package/src/console/server/diff.ts +352 -0
  118. package/src/console/server/dry-run.audit.test.ts +118 -0
  119. package/src/console/server/flows-invoke.test.ts +148 -0
  120. package/src/console/server/flows.ts +3633 -0
  121. package/src/console/server/gates.test.ts +360 -0
  122. package/src/console/server/gates.ts +869 -0
  123. package/src/console/server/index.ts +141 -0
  124. package/src/console/server/live.test.ts +30 -0
  125. package/src/console/server/live.ts +109 -0
  126. package/src/console/server/plugin.ts +50 -0
  127. package/src/console/server/plugins.test.ts +131 -0
  128. package/src/console/server/plugins.ts +429 -0
  129. package/src/console/server/runs-pii.ts +98 -0
  130. package/src/console/server/security-headers.ts +97 -0
  131. package/src/console/server/security.gate.test.ts +286 -0
  132. package/src/console/server/serve.ts +319 -0
  133. package/src/console/server/signals.test.ts +88 -0
  134. package/src/console/server/signals.ts +282 -0
  135. package/src/console/server/state.ts +982 -0
  136. package/src/console/server/store.test.ts +233 -0
  137. package/src/console/server/store.ts +861 -0
  138. package/src/console/server/structural.ts +95 -0
  139. package/src/console/server/vault.test.ts +251 -0
  140. package/src/console/server/vault.ts +430 -0
  141. package/src/console/ui/access/AccessA11yView.tsx +237 -0
  142. package/src/console/ui/access/a11y.test.tsx +122 -0
  143. package/src/console/ui/access/acknowledgement.test.ts +13 -0
  144. package/src/console/ui/access/acknowledgement.ts +35 -0
  145. package/src/console/ui/access/blast-radius.test.ts +26 -0
  146. package/src/console/ui/access/blast-radius.ts +40 -0
  147. package/src/console/ui/access/confirmation.test.ts +38 -0
  148. package/src/console/ui/access/confirmation.ts +36 -0
  149. package/src/console/ui/access/fixture.ts +203 -0
  150. package/src/console/ui/access/grantable.test.ts +17 -0
  151. package/src/console/ui/access/grantable.ts +36 -0
  152. package/src/console/ui/access/hygiene.test.ts +12 -0
  153. package/src/console/ui/access/hygiene.ts +39 -0
  154. package/src/console/ui/access/index.ts +54 -0
  155. package/src/console/ui/access/provenance.test.ts +12 -0
  156. package/src/console/ui/access/provenance.ts +29 -0
  157. package/src/console/ui/access/search.test.ts +17 -0
  158. package/src/console/ui/access/search.ts +72 -0
  159. package/src/console/ui/access/types.ts +111 -0
  160. package/src/console/ui/ai/AiA11yView.tsx +265 -0
  161. package/src/console/ui/ai/a11y.test.tsx +99 -0
  162. package/src/console/ui/ai/findings.ts +41 -0
  163. package/src/console/ui/ai/fixture.ts +182 -0
  164. package/src/console/ui/ai/format.ts +90 -0
  165. package/src/console/ui/ai/group.test.ts +37 -0
  166. package/src/console/ui/ai/group.ts +88 -0
  167. package/src/console/ui/ai/index.ts +66 -0
  168. package/src/console/ui/ai/promotion.test.ts +77 -0
  169. package/src/console/ui/ai/promotion.ts +150 -0
  170. package/src/console/ui/ai/search.test.ts +40 -0
  171. package/src/console/ui/ai/search.ts +89 -0
  172. package/src/console/ui/ai/types.ts +139 -0
  173. package/src/console/ui/architecture/ArchitectureA11yView.tsx +163 -0
  174. package/src/console/ui/architecture/a11y.test.tsx +97 -0
  175. package/src/console/ui/architecture/boundary.ts +42 -0
  176. package/src/console/ui/architecture/declared.ts +165 -0
  177. package/src/console/ui/architecture/fixture.ts +74 -0
  178. package/src/console/ui/architecture/index.ts +84 -0
  179. package/src/console/ui/architecture/layers.ts +64 -0
  180. package/src/console/ui/architecture/layout.ts +68 -0
  181. package/src/console/ui/architecture/pathologies.ts +260 -0
  182. package/src/console/ui/architecture/search.ts +145 -0
  183. package/src/console/ui/architecture/traffic.ts +102 -0
  184. package/src/console/ui/architecture/types.ts +144 -0
  185. package/src/console/ui/architecture/view.test.ts +165 -0
  186. package/src/console/ui/architecture/view.ts +516 -0
  187. package/src/console/ui/channels/ChannelsA11yView.tsx +180 -0
  188. package/src/console/ui/channels/a11y.test.tsx +96 -0
  189. package/src/console/ui/channels/confirmation.test.ts +37 -0
  190. package/src/console/ui/channels/confirmation.ts +27 -0
  191. package/src/console/ui/channels/fallback.test.ts +15 -0
  192. package/src/console/ui/channels/fallback.ts +20 -0
  193. package/src/console/ui/channels/findings.ts +38 -0
  194. package/src/console/ui/channels/fixture.ts +134 -0
  195. package/src/console/ui/channels/group.ts +25 -0
  196. package/src/console/ui/channels/index.ts +57 -0
  197. package/src/console/ui/channels/locale.test.ts +17 -0
  198. package/src/console/ui/channels/locale.ts +31 -0
  199. package/src/console/ui/channels/mask.test.ts +14 -0
  200. package/src/console/ui/channels/mask.ts +12 -0
  201. package/src/console/ui/channels/search.ts +58 -0
  202. package/src/console/ui/channels/taxonomy.test.ts +17 -0
  203. package/src/console/ui/channels/taxonomy.ts +49 -0
  204. package/src/console/ui/channels/types.ts +117 -0
  205. package/src/console/ui/clock/ClockA11yView.tsx +182 -0
  206. package/src/console/ui/clock/a11y.test.tsx +99 -0
  207. package/src/console/ui/clock/confirmation.test.ts +32 -0
  208. package/src/console/ui/clock/confirmation.ts +34 -0
  209. package/src/console/ui/clock/findings.ts +40 -0
  210. package/src/console/ui/clock/fixture.ts +111 -0
  211. package/src/console/ui/clock/health.test.ts +25 -0
  212. package/src/console/ui/clock/health.ts +61 -0
  213. package/src/console/ui/clock/index.ts +49 -0
  214. package/src/console/ui/clock/search.test.ts +39 -0
  215. package/src/console/ui/clock/search.ts +76 -0
  216. package/src/console/ui/clock/timeline.test.ts +44 -0
  217. package/src/console/ui/clock/timeline.ts +41 -0
  218. package/src/console/ui/clock/types.ts +78 -0
  219. package/src/console/ui/clock/waiting-on.test.ts +34 -0
  220. package/src/console/ui/clock/waiting-on.ts +83 -0
  221. package/src/console/ui/confirmation.unify.test.ts +92 -0
  222. package/src/console/ui/diff/DiffA11yView.tsx +85 -0
  223. package/src/console/ui/diff/a11y.test.tsx +99 -0
  224. package/src/console/ui/diff/fixture.ts +85 -0
  225. package/src/console/ui/diff/group.test.ts +58 -0
  226. package/src/console/ui/diff/group.ts +97 -0
  227. package/src/console/ui/diff/index.ts +38 -0
  228. package/src/console/ui/diff/search.test.ts +32 -0
  229. package/src/console/ui/diff/search.ts +75 -0
  230. package/src/console/ui/diff/summary.ts +74 -0
  231. package/src/console/ui/diff/types.ts +48 -0
  232. package/src/console/ui/dist/assets/index-B71Yl_SS.js +10 -0
  233. package/src/console/ui/dist/assets/panel-access-Dd37LU2c.js +64 -0
  234. package/src/console/ui/dist/assets/panel-ai-CC7LR6-J.js +1 -0
  235. package/src/console/ui/dist/assets/panel-architecture-B5b3iKCz.js +1 -0
  236. package/src/console/ui/dist/assets/panel-channels-CeNjTKXp.js +1 -0
  237. package/src/console/ui/dist/assets/panel-clock-DgFTLoHV.js +1 -0
  238. package/src/console/ui/dist/assets/panel-diff-DxehccqB.js +1 -0
  239. package/src/console/ui/dist/assets/panel-flows-BtrVn-Eg.js +45 -0
  240. package/src/console/ui/dist/assets/panel-gates-Z9MKRGdH.js +1 -0
  241. package/src/console/ui/dist/assets/panel-overview-Bd48d9km.js +1 -0
  242. package/src/console/ui/dist/assets/panel-plugins-DWd0TowH.js +1 -0
  243. package/src/console/ui/dist/assets/panel-runs-BwsWqKeB.js +1 -0
  244. package/src/console/ui/dist/assets/panel-signals-9najbZY2.js +1 -0
  245. package/src/console/ui/dist/assets/panel-store-OHkP2pDp.js +1 -0
  246. package/src/console/ui/dist/assets/panel-traces-tn2JoY8U.js +1 -0
  247. package/src/console/ui/dist/assets/panel-vault-BbfWdox0.js +1 -0
  248. package/src/console/ui/dist/assets/rolldown-runtime-CNC7AqOf.js +1 -0
  249. package/src/console/ui/dist/assets/style-Cnl7WLya.css +3 -0
  250. package/src/console/ui/dist/index.html +14 -0
  251. package/src/console/ui/flows/FlowsA11yView.tsx +155 -0
  252. package/src/console/ui/flows/a11y.test.tsx +105 -0
  253. package/src/console/ui/flows/buffer.test.ts +91 -0
  254. package/src/console/ui/flows/buffer.ts +118 -0
  255. package/src/console/ui/flows/confirmation.ts +131 -0
  256. package/src/console/ui/flows/contract.test.ts +89 -0
  257. package/src/console/ui/flows/contract.ts +353 -0
  258. package/src/console/ui/flows/fixture.ts +81 -0
  259. package/src/console/ui/flows/graph.test.ts +101 -0
  260. package/src/console/ui/flows/graph.ts +549 -0
  261. package/src/console/ui/flows/index.ts +87 -0
  262. package/src/console/ui/flows/save-as-test.test.ts +47 -0
  263. package/src/console/ui/flows/save-as-test.ts +99 -0
  264. package/src/console/ui/flows/search.ts +255 -0
  265. package/src/console/ui/flows/tiers.ts +140 -0
  266. package/src/console/ui/gates/GatesA11yView.tsx +192 -0
  267. package/src/console/ui/gates/a11y.test.tsx +116 -0
  268. package/src/console/ui/gates/audit.test.ts +40 -0
  269. package/src/console/ui/gates/audit.ts +63 -0
  270. package/src/console/ui/gates/denial.test.ts +36 -0
  271. package/src/console/ui/gates/denial.ts +51 -0
  272. package/src/console/ui/gates/findings.ts +19 -0
  273. package/src/console/ui/gates/fixture.ts +189 -0
  274. package/src/console/ui/gates/group.test.ts +30 -0
  275. package/src/console/ui/gates/group.ts +102 -0
  276. package/src/console/ui/gates/index.ts +47 -0
  277. package/src/console/ui/gates/search.test.ts +49 -0
  278. package/src/console/ui/gates/search.ts +115 -0
  279. package/src/console/ui/gates/types.ts +121 -0
  280. package/src/console/ui/overview/OverviewA11yView.tsx +152 -0
  281. package/src/console/ui/overview/a11y.test.tsx +113 -0
  282. package/src/console/ui/overview/busiest.ts +26 -0
  283. package/src/console/ui/overview/compose.ts +133 -0
  284. package/src/console/ui/overview/cost.test.ts +39 -0
  285. package/src/console/ui/overview/cost.ts +138 -0
  286. package/src/console/ui/overview/fixture.ts +161 -0
  287. package/src/console/ui/overview/golden.ts +57 -0
  288. package/src/console/ui/overview/index.ts +59 -0
  289. package/src/console/ui/overview/rank.test.ts +136 -0
  290. package/src/console/ui/overview/rank.ts +210 -0
  291. package/src/console/ui/overview/slo.test.ts +73 -0
  292. package/src/console/ui/overview/slo.ts +229 -0
  293. package/src/console/ui/overview/types.ts +121 -0
  294. package/src/console/ui/overview/verdict.ts +131 -0
  295. package/src/console/ui/plugins/PluginsA11yView.tsx +227 -0
  296. package/src/console/ui/plugins/a11y.test.tsx +97 -0
  297. package/src/console/ui/plugins/command.test.ts +22 -0
  298. package/src/console/ui/plugins/command.ts +27 -0
  299. package/src/console/ui/plugins/findings.ts +39 -0
  300. package/src/console/ui/plugins/fixture.ts +233 -0
  301. package/src/console/ui/plugins/group.test.ts +38 -0
  302. package/src/console/ui/plugins/group.ts +67 -0
  303. package/src/console/ui/plugins/index.ts +40 -0
  304. package/src/console/ui/plugins/search.ts +67 -0
  305. package/src/console/ui/plugins/types.ts +115 -0
  306. package/src/console/ui/runs/RunsA11yView.tsx +267 -0
  307. package/src/console/ui/runs/a11y.test.tsx +99 -0
  308. package/src/console/ui/runs/explain.test.ts +23 -0
  309. package/src/console/ui/runs/explain.ts +32 -0
  310. package/src/console/ui/runs/fixture.ts +189 -0
  311. package/src/console/ui/runs/group.test.ts +24 -0
  312. package/src/console/ui/runs/group.ts +85 -0
  313. package/src/console/ui/runs/histogram.test.ts +31 -0
  314. package/src/console/ui/runs/histogram.ts +85 -0
  315. package/src/console/ui/runs/index.ts +75 -0
  316. package/src/console/ui/runs/project.ts +122 -0
  317. package/src/console/ui/runs/query.test.ts +50 -0
  318. package/src/console/ui/runs/query.ts +283 -0
  319. package/src/console/ui/runs/search.test.ts +45 -0
  320. package/src/console/ui/runs/search.ts +141 -0
  321. package/src/console/ui/runs/trace-link.test.ts +30 -0
  322. package/src/console/ui/runs/trace-link.ts +99 -0
  323. package/src/console/ui/runs/types.ts +137 -0
  324. package/src/console/ui/shell/App.tsx +56 -0
  325. package/src/console/ui/shell/client.ts +1715 -0
  326. package/src/console/ui/shell/components/ui.tsx +110 -0
  327. package/src/console/ui/shell/index.html +12 -0
  328. package/src/console/ui/shell/layout/Shell.tsx +95 -0
  329. package/src/console/ui/shell/main.tsx +281 -0
  330. package/src/console/ui/shell/panels/Access.tsx +5 -0
  331. package/src/console/ui/shell/panels/Ai.tsx +5 -0
  332. package/src/console/ui/shell/panels/Architecture.tsx +5 -0
  333. package/src/console/ui/shell/panels/Channels.tsx +5 -0
  334. package/src/console/ui/shell/panels/Clock.tsx +5 -0
  335. package/src/console/ui/shell/panels/Diff.tsx +5 -0
  336. package/src/console/ui/shell/panels/Flows.tsx +5 -0
  337. package/src/console/ui/shell/panels/Gates.tsx +5 -0
  338. package/src/console/ui/shell/panels/Overview.tsx +6 -0
  339. package/src/console/ui/shell/panels/Plugins.tsx +5 -0
  340. package/src/console/ui/shell/panels/Runs.tsx +5 -0
  341. package/src/console/ui/shell/panels/Signals.tsx +5 -0
  342. package/src/console/ui/shell/panels/Store.tsx +5 -0
  343. package/src/console/ui/shell/panels/Traces.tsx +5 -0
  344. package/src/console/ui/shell/panels/Vault.tsx +5 -0
  345. package/src/console/ui/shell/panels/access/AccessPanel.tsx +813 -0
  346. package/src/console/ui/shell/panels/ai/AiPanel.tsx +563 -0
  347. package/src/console/ui/shell/panels/architecture/ArchitecturePanel.tsx +377 -0
  348. package/src/console/ui/shell/panels/channels/ChannelsPanel.tsx +454 -0
  349. package/src/console/ui/shell/panels/clock/ClockPanel.tsx +479 -0
  350. package/src/console/ui/shell/panels/diff/DiffPanel.tsx +275 -0
  351. package/src/console/ui/shell/panels/flows/ContractEditor.tsx +301 -0
  352. package/src/console/ui/shell/panels/flows/FlowDrawer.tsx +350 -0
  353. package/src/console/ui/shell/panels/flows/FlowsPanel.tsx +502 -0
  354. package/src/console/ui/shell/panels/gates/GatesPanel.tsx +482 -0
  355. package/src/console/ui/shell/panels/overview/OverviewPanel.tsx +428 -0
  356. package/src/console/ui/shell/panels/plugins/PluginsPanel.tsx +413 -0
  357. package/src/console/ui/shell/panels/runs/RunsPanel.tsx +649 -0
  358. package/src/console/ui/shell/panels/signals/SignalsPanel.tsx +840 -0
  359. package/src/console/ui/shell/panels/store/StorePanel.tsx +787 -0
  360. package/src/console/ui/shell/panels/traces/TracesPanel.tsx +539 -0
  361. package/src/console/ui/shell/panels/vault/VaultPanel.tsx +449 -0
  362. package/src/console/ui/shell/plugin/Sandbox.tsx +29 -0
  363. package/src/console/ui/shell/setup/Wizard.tsx +189 -0
  364. package/src/console/ui/shell/styles.css +75 -0
  365. package/src/console/ui/signals/SignalsA11yView.tsx +276 -0
  366. package/src/console/ui/signals/a11y.test.tsx +99 -0
  367. package/src/console/ui/signals/confirmation.test.ts +39 -0
  368. package/src/console/ui/signals/confirmation.ts +63 -0
  369. package/src/console/ui/signals/dry-run.test.ts +18 -0
  370. package/src/console/ui/signals/dry-run.ts +36 -0
  371. package/src/console/ui/signals/durable.test.ts +22 -0
  372. package/src/console/ui/signals/durable.ts +41 -0
  373. package/src/console/ui/signals/findings.ts +33 -0
  374. package/src/console/ui/signals/fixture.ts +242 -0
  375. package/src/console/ui/signals/group.test.ts +32 -0
  376. package/src/console/ui/signals/group.ts +49 -0
  377. package/src/console/ui/signals/index.ts +52 -0
  378. package/src/console/ui/signals/monitor.test.ts +30 -0
  379. package/src/console/ui/signals/monitor.ts +79 -0
  380. package/src/console/ui/signals/schema-form.test.ts +34 -0
  381. package/src/console/ui/signals/schema-form.ts +112 -0
  382. package/src/console/ui/signals/search.ts +102 -0
  383. package/src/console/ui/signals/types.ts +71 -0
  384. package/src/console/ui/store/StoreA11yView.tsx +199 -0
  385. package/src/console/ui/store/a11y.test.tsx +99 -0
  386. package/src/console/ui/store/cache-view.test.ts +13 -0
  387. package/src/console/ui/store/cache-view.ts +36 -0
  388. package/src/console/ui/store/confirmation.test.ts +38 -0
  389. package/src/console/ui/store/confirmation.ts +55 -0
  390. package/src/console/ui/store/dry-run.test.ts +15 -0
  391. package/src/console/ui/store/dry-run.ts +29 -0
  392. package/src/console/ui/store/fixture.ts +163 -0
  393. package/src/console/ui/store/group.test.ts +21 -0
  394. package/src/console/ui/store/group.ts +41 -0
  395. package/src/console/ui/store/index.ts +40 -0
  396. package/src/console/ui/store/search.ts +78 -0
  397. package/src/console/ui/store/types.ts +65 -0
  398. package/src/console/ui/store/will-not-fire.test.ts +19 -0
  399. package/src/console/ui/store/will-not-fire.ts +40 -0
  400. package/src/console/ui/traces/TracesA11yView.tsx +200 -0
  401. package/src/console/ui/traces/a11y.test.tsx +97 -0
  402. package/src/console/ui/traces/chain.test.ts +61 -0
  403. package/src/console/ui/traces/chain.ts +144 -0
  404. package/src/console/ui/traces/critical-path.test.ts +24 -0
  405. package/src/console/ui/traces/critical-path.ts +59 -0
  406. package/src/console/ui/traces/filter.test.ts +78 -0
  407. package/src/console/ui/traces/filter.ts +112 -0
  408. package/src/console/ui/traces/fixture.ts +126 -0
  409. package/src/console/ui/traces/fold.test.ts +67 -0
  410. package/src/console/ui/traces/fold.ts +170 -0
  411. package/src/console/ui/traces/index.ts +64 -0
  412. package/src/console/ui/traces/mini.ts +65 -0
  413. package/src/console/ui/traces/replay.test.ts +24 -0
  414. package/src/console/ui/traces/replay.ts +35 -0
  415. package/src/console/ui/traces/sampling.test.ts +26 -0
  416. package/src/console/ui/traces/sampling.ts +66 -0
  417. package/src/console/ui/traces/search.ts +148 -0
  418. package/src/console/ui/traces/tier.ts +72 -0
  419. package/src/console/ui/traces/types.ts +125 -0
  420. package/src/console/ui/tsconfig.json +20 -0
  421. package/src/console/ui/vault/VaultA11yView.tsx +177 -0
  422. package/src/console/ui/vault/a11y.test.tsx +97 -0
  423. package/src/console/ui/vault/blast-radius.test.ts +35 -0
  424. package/src/console/ui/vault/blast-radius.ts +55 -0
  425. package/src/console/ui/vault/confirmation.test.ts +41 -0
  426. package/src/console/ui/vault/confirmation.ts +39 -0
  427. package/src/console/ui/vault/dormant.test.ts +37 -0
  428. package/src/console/ui/vault/dormant.ts +28 -0
  429. package/src/console/ui/vault/export-safe.test.ts +30 -0
  430. package/src/console/ui/vault/export-safe.ts +65 -0
  431. package/src/console/ui/vault/fixture.ts +75 -0
  432. package/src/console/ui/vault/group.test.ts +25 -0
  433. package/src/console/ui/vault/group.ts +50 -0
  434. package/src/console/ui/vault/index.ts +45 -0
  435. package/src/console/ui/vault/search.ts +62 -0
  436. package/src/console/ui/vault/types.ts +57 -0
  437. package/src/console/ui/vite.config.ts +84 -0
  438. package/src/console/xss.gate.test.ts +118 -0
  439. package/src/docker/compose.ts +226 -0
  440. package/src/docker/credentials.ts +25 -0
  441. package/src/docker/derive.ts +83 -0
  442. package/src/docker/docker.test.ts +185 -0
  443. package/src/docker/dockerfile.integration.test.ts +170 -0
  444. package/src/docker/dockerfile.ts +39 -0
  445. package/src/docker/helpers.ts +103 -0
  446. package/src/docker/index.ts +52 -0
  447. package/src/docker/pin.ts +90 -0
  448. package/src/docker/recipes/index.ts +33 -0
  449. package/src/docker/recipes/postgres.ts +18 -0
  450. package/src/docker/recipes/redis.ts +18 -0
  451. package/src/docker/stack.integration.test.ts +140 -0
  452. package/src/docker/stack.ts +62 -0
  453. package/src/docker/types.ts +134 -0
  454. package/src/drivers/ai-anthropic.ts +128 -0
  455. package/src/drivers/ai-mock.ts +82 -0
  456. package/src/drivers/ai-openai-compatible.ts +139 -0
  457. package/src/drivers/ai-providers.test.ts +163 -0
  458. package/src/drivers/ai-types.ts +83 -0
  459. package/src/drivers/bun-native-completeness.test.ts +155 -0
  460. package/src/drivers/channel-console.ts +118 -0
  461. package/src/drivers/channel-fcm.ts +96 -0
  462. package/src/drivers/channel-resend.ts +27 -0
  463. package/src/drivers/channel-smtp.ts +33 -0
  464. package/src/drivers/channel-types.ts +160 -0
  465. package/src/drivers/channel-unifonic.ts +79 -0
  466. package/src/drivers/channel-wa-cloud.ts +84 -0
  467. package/src/drivers/channel-webpush.ts +317 -0
  468. package/src/drivers/conformance.test.ts +89 -0
  469. package/src/drivers/conformance.ts +162 -0
  470. package/src/drivers/fs.ts +73 -0
  471. package/src/drivers/index.ts +194 -0
  472. package/src/drivers/kv-lua.ts +222 -0
  473. package/src/drivers/memory.ts +472 -0
  474. package/src/drivers/pgvector.ts +130 -0
  475. package/src/drivers/postgres.ts +221 -0
  476. package/src/drivers/redis.ts +254 -0
  477. package/src/drivers/s3.ts +129 -0
  478. package/src/drivers/signal-engine.ts +690 -0
  479. package/src/drivers/signal-memory.ts +27 -0
  480. package/src/drivers/signal-nats.ts +131 -0
  481. package/src/drivers/signal-postgres.ts +1089 -0
  482. package/src/drivers/signal-redis.ts +275 -0
  483. package/src/drivers/signal-types.ts +328 -0
  484. package/src/drivers/sqlite.ts +53 -0
  485. package/src/drivers/types.ts +334 -0
  486. package/src/drivers/vault-dotenv-parse.ts +56 -0
  487. package/src/drivers/vault-env.ts +101 -0
  488. package/src/drivers/vault-infisical.ts +61 -0
  489. package/src/drivers/vault-managed.ts +42 -0
  490. package/src/drivers/vault-memory.ts +38 -0
  491. package/src/drivers/vault-openbao.ts +80 -0
  492. package/src/drivers/vault-sops.ts +252 -0
  493. package/src/drivers/vault-types.ts +84 -0
  494. package/src/elements/ai/declare.ts +206 -0
  495. package/src/elements/ai/eval.ts +113 -0
  496. package/src/elements/ai/pii.ts +108 -0
  497. package/src/elements/ai/runtime.ts +540 -0
  498. package/src/elements/ai/schema.ts +194 -0
  499. package/src/elements/ai.test.ts +393 -0
  500. package/src/elements/ai.ts +56 -0
  501. package/src/elements/channel/consent.ts +81 -0
  502. package/src/elements/channel/costs.test.ts +62 -0
  503. package/src/elements/channel/costs.ts +130 -0
  504. package/src/elements/channel/declare.ts +141 -0
  505. package/src/elements/channel/email-auth.test.ts +47 -0
  506. package/src/elements/channel/email-auth.ts +109 -0
  507. package/src/elements/channel/locale.ts +97 -0
  508. package/src/elements/channel/mask.test.ts +19 -0
  509. package/src/elements/channel/mask.ts +60 -0
  510. package/src/elements/channel/mime.ts +23 -0
  511. package/src/elements/channel/outcomes.test.ts +40 -0
  512. package/src/elements/channel/outcomes.ts +126 -0
  513. package/src/elements/channel/receipts.ts +121 -0
  514. package/src/elements/channel/runtime.ts +500 -0
  515. package/src/elements/channel/suppression.ts +136 -0
  516. package/src/elements/channel.test.ts +232 -0
  517. package/src/elements/channel.ts +109 -0
  518. package/src/elements/clock/actions.ts +170 -0
  519. package/src/elements/clock/declare.ts +58 -0
  520. package/src/elements/clock/dst.ts +197 -0
  521. package/src/elements/clock/durable.ts +140 -0
  522. package/src/elements/clock/duration.ts +29 -0
  523. package/src/elements/clock/health.test.ts +103 -0
  524. package/src/elements/clock/health.ts +112 -0
  525. package/src/elements/clock/leader.ts +127 -0
  526. package/src/elements/clock/reconcile.ts +241 -0
  527. package/src/elements/clock/runtime.ts +243 -0
  528. package/src/elements/clock/schedule.ts +262 -0
  529. package/src/elements/clock/time-travel.ts +53 -0
  530. package/src/elements/clock.test.ts +365 -0
  531. package/src/elements/clock.ts +80 -0
  532. package/src/elements/gate/declare.ts +134 -0
  533. package/src/elements/gate/permissions.ts +104 -0
  534. package/src/elements/gate/runtime.ts +177 -0
  535. package/src/elements/gate/strategies.ts +388 -0
  536. package/src/elements/gate.test.ts +145 -0
  537. package/src/elements/gate.ts +41 -0
  538. package/src/elements/index.ts +169 -0
  539. package/src/elements/signal/chaos-child.ts +47 -0
  540. package/src/elements/signal/declare.ts +77 -0
  541. package/src/elements/signal/dry-run-replay.test.ts +95 -0
  542. package/src/elements/signal/dry-run-write-isolation.test.ts +94 -0
  543. package/src/elements/signal/reconcile.test.ts +23 -0
  544. package/src/elements/signal/reconcile.ts +122 -0
  545. package/src/elements/signal/runtime.ts +94 -0
  546. package/src/elements/signal.test.ts +457 -0
  547. package/src/elements/signal.ts +26 -0
  548. package/src/elements/store/cache.ts +197 -0
  549. package/src/elements/store/classify.ts +125 -0
  550. package/src/elements/store/declare.ts +200 -0
  551. package/src/elements/store/files-policy.test.ts +31 -0
  552. package/src/elements/store/files-policy.ts +70 -0
  553. package/src/elements/store/replica.ts +68 -0
  554. package/src/elements/store/runtime.ts +393 -0
  555. package/src/elements/store/sql-condition.ts +205 -0
  556. package/src/elements/store/sql-session.ts +579 -0
  557. package/src/elements/store/table.ts +282 -0
  558. package/src/elements/store.test.ts +370 -0
  559. package/src/elements/store.ts +99 -0
  560. package/src/elements/vault/declare.ts +143 -0
  561. package/src/elements/vault/fingerprint.ts +30 -0
  562. package/src/elements/vault/redact.ts +52 -0
  563. package/src/elements/vault/runtime.ts +461 -0
  564. package/src/elements/vault.test.ts +296 -0
  565. package/src/elements/vault.ts +44 -0
  566. package/src/index.ts +183 -0
  567. package/src/kernel/adopt-routes.ts +194 -0
  568. package/src/kernel/app.ts +1068 -0
  569. package/src/kernel/auth-resolve.ts +93 -0
  570. package/src/kernel/boot.test.ts +173 -0
  571. package/src/kernel/boot.ts +439 -0
  572. package/src/kernel/budget-entry.ts +55 -0
  573. package/src/kernel/budget.test.ts +19 -0
  574. package/src/kernel/call.test.ts +83 -0
  575. package/src/kernel/capability.ts +113 -0
  576. package/src/kernel/dry-run.test.ts +64 -0
  577. package/src/kernel/dry-run.ts +171 -0
  578. package/src/kernel/effects.test.ts +89 -0
  579. package/src/kernel/effects.ts +140 -0
  580. package/src/kernel/errors.registry.test.ts +39 -0
  581. package/src/kernel/errors.ts +225 -0
  582. package/src/kernel/flow.test.ts +154 -0
  583. package/src/kernel/flow.ts +290 -0
  584. package/src/kernel/fx.test.ts +245 -0
  585. package/src/kernel/fx.ts +996 -0
  586. package/src/kernel/hook-timing.test.ts +72 -0
  587. package/src/kernel/hook-timing.ts +190 -0
  588. package/src/kernel/hooks.test.ts +181 -0
  589. package/src/kernel/hooks.ts +275 -0
  590. package/src/kernel/index.ts +278 -0
  591. package/src/kernel/journal.ts +405 -0
  592. package/src/kernel/journey.ts +75 -0
  593. package/src/kernel/on.ts +74 -0
  594. package/src/kernel/pipeline.test.ts +349 -0
  595. package/src/kernel/pipeline.ts +245 -0
  596. package/src/kernel/plug.ts +82 -0
  597. package/src/kernel/plugin/capabilities.test.ts +84 -0
  598. package/src/kernel/plugin/conflicts.test.ts +106 -0
  599. package/src/kernel/plugin/decorate.test.ts +111 -0
  600. package/src/kernel/plugin/scoping.test.ts +138 -0
  601. package/src/kernel/plugin.ts +485 -0
  602. package/src/kernel/rate-limit.ts +25 -0
  603. package/src/kernel/registry.ts +398 -0
  604. package/src/kernel/router.test.ts +114 -0
  605. package/src/kernel/router.ts +556 -0
  606. package/src/kernel/routing-budget.test.ts +19 -0
  607. package/src/kernel/run-telemetry.ts +70 -0
  608. package/src/kernel/triggers.ts +324 -0
  609. package/src/kernel/unit.ts +88 -0
  610. package/src/manifest/diff.test.ts +866 -0
  611. package/src/manifest/diff.ts +1670 -0
  612. package/src/manifest/fixtures/base.manifest.json +112 -0
  613. package/src/manifest/fixtures/skyport.excerpt.json +51 -0
  614. package/src/manifest/fixtures/skyport.manifest.json +153 -0
  615. package/src/manifest/index.ts +27 -0
  616. package/src/manifest/types.ts +358 -0
  617. package/src/manifest/undeclared.test.ts +82 -0
  618. package/src/manifest/undeclared.ts +65 -0
  619. package/src/manifest/validate.test.ts +105 -0
  620. package/src/manifest/validate.ts +174 -0
  621. package/src/mcp/authorization.ts +340 -0
  622. package/src/mcp/confirmation.ts +174 -0
  623. package/src/mcp/data.ts +90 -0
  624. package/src/mcp/index.ts +80 -0
  625. package/src/mcp/injection.gate.test.ts +176 -0
  626. package/src/mcp/mcp.test.ts +348 -0
  627. package/src/mcp/protocol.ts +172 -0
  628. package/src/mcp/server.ts +283 -0
  629. package/src/mcp/session.ts +139 -0
  630. package/src/mcp/tools.ts +391 -0
  631. package/src/plugins/catalogue.test.ts +48 -0
  632. package/src/plugins/catalogue.ts +113 -0
  633. package/src/plugins/node-import-scan.test.ts +28 -0
  634. package/src/plugins/node-import-scan.ts +98 -0
  635. package/src/plugins/supply-chain.test.ts +48 -0
  636. package/src/plugins/supply-chain.ts +460 -0
  637. package/src/release/index.ts +30 -0
  638. package/src/release/limits.ts +20 -0
  639. package/src/release/measure.ts +443 -0
  640. package/src/release/publish.ts +56 -0
  641. package/src/runs/bench.test.ts +93 -0
  642. package/src/runs/collect.ts +144 -0
  643. package/src/runs/drivers/clickhouse.ts +108 -0
  644. package/src/runs/drivers/files.ts +201 -0
  645. package/src/runs/drivers/memory.ts +94 -0
  646. package/src/runs/drivers/postgres.ts +110 -0
  647. package/src/runs/duckdb.ts +99 -0
  648. package/src/runs/index.ts +82 -0
  649. package/src/runs/outlier.ts +180 -0
  650. package/src/runs/parquet.ts +210 -0
  651. package/src/runs/privacy.ts +49 -0
  652. package/src/runs/runs.test.ts +324 -0
  653. package/src/runs/runtime.ts +229 -0
  654. package/src/runs/shred.ts +243 -0
  655. package/src/runs/telemetry.ts +10 -0
  656. package/src/runs/types.ts +179 -0
  657. package/src/runtime/bun.ts +140 -0
  658. package/src/runtime/cold-start.bench.ts +20 -0
  659. package/src/runtime/index.ts +46 -0
  660. package/src/runtime/primitives.ts +242 -0
  661. package/src/runtime/security.test.ts +170 -0
  662. package/src/runtime/security.ts +168 -0
  663. package/src/runtime/serve.test.ts +223 -0
  664. package/src/runtime/types.ts +217 -0
  665. package/src/runtime/web-standard.ts +77 -0
  666. package/src/test/create-test-app.test.ts +161 -0
  667. package/src/test/create-test-app.ts +533 -0
  668. package/src/test/index.ts +21 -0
  669. package/src/test/provisions.integration.test.ts +174 -0
  670. package/src/upgrade/codemods.test.ts +58 -0
  671. package/src/upgrade/codemods.ts +83 -0
  672. package/src/validation/index.ts +23 -0
  673. package/src/validation/standard-schema.test.ts +96 -0
  674. package/src/validation/standard-schema.ts +316 -0
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Dockerfile derivation — production image whose CMD is `oke start`.
3
+ */
4
+
5
+ import { APP_PORT } from "../runtime/types.ts";
6
+
7
+ /** Options for {@link emitDockerfile}. */
8
+ export interface DockerfileOptions {
9
+ /** App listen port. */
10
+ readonly appPort?: number;
11
+ /** Bun base image. */
12
+ readonly baseImage?: string;
13
+ }
14
+
15
+ /**
16
+ * Emit a production Dockerfile. CMD is exactly `oke start`.
17
+ *
18
+ * @param options - Port / base image
19
+ */
20
+ export function emitDockerfile(options: DockerfileOptions = {}): string {
21
+ const port = options.appPort ?? APP_PORT;
22
+ const base = options.baseImage ?? "oven/bun:1.3";
23
+ return `# generated by oke docker — do not edit
24
+ FROM ${base} AS deps
25
+ WORKDIR /app
26
+ COPY package.json bun.lock* ./
27
+ RUN bun install --frozen-lockfile --production
28
+
29
+ FROM ${base} AS runner
30
+ WORKDIR /app
31
+ ENV NODE_ENV=production
32
+ ENV PORT=${port}
33
+ ENV PATH="/app/node_modules/.bin:\${PATH}"
34
+ COPY --from=deps /app/node_modules ./node_modules
35
+ COPY . .
36
+ EXPOSE ${port}
37
+ CMD ["oke", "start"]
38
+ `;
39
+ }
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Shared helpers for image recipes — keep recipe files ≤15 lines.
3
+ */
4
+
5
+ import type { ServiceSpec } from "./types.ts";
6
+
7
+ /**
8
+ * Env-var *reference* for a credential field — value never enters YAML.
9
+ *
10
+ * @param spec - Service
11
+ * @param field - USER | PASSWORD | DB
12
+ */
13
+ export function credEnv(spec: ServiceSpec, field: "USER" | "PASSWORD" | "DB"): string {
14
+ const key = `OKE_${spec.role.replaceAll(".", "_").toUpperCase()}_${field}`;
15
+ return `\${${key}}`;
16
+ }
17
+
18
+ /**
19
+ * Compose service name for a role (`store.sql` → `store-sql`).
20
+ *
21
+ * @param role - Role key
22
+ */
23
+ export function serviceNameFor(role: string): string {
24
+ return role.replaceAll(".", "-");
25
+ }
26
+
27
+ /**
28
+ * Env key prefix for a role (`store.sql` → `OKE_STORE_SQL`).
29
+ *
30
+ * @param role - Role key
31
+ */
32
+ export function envPrefix(role: string): string {
33
+ return `OKE_${role.replaceAll(".", "_").toUpperCase()}`;
34
+ }
35
+
36
+ /**
37
+ * Default host port for well-known roles.
38
+ *
39
+ * @param role - Role key
40
+ * @param containerPort - Container port
41
+ */
42
+ export function defaultHostPort(role: string, containerPort: number): number {
43
+ if (role === "store.sql") return 5432;
44
+ if (role === "store.kv") return 6379;
45
+ if (role === "signal") return 4222;
46
+ return containerPort;
47
+ }
48
+
49
+ /**
50
+ * Escape a YAML double-quoted string.
51
+ *
52
+ * @param value - Raw string
53
+ */
54
+ export function yamlQuote(value: string): string {
55
+ return `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
56
+ }
57
+
58
+ /**
59
+ * Render a plain YAML mapping (2-space indent, no library).
60
+ *
61
+ * @param value - JSON-like structure
62
+ * @param indent - Current indent level
63
+ */
64
+ export function toYaml(value: unknown, indent = 0): string {
65
+ const pad = " ".repeat(indent);
66
+ if (value === null || value === undefined) return "null";
67
+ if (typeof value === "string") return yamlQuote(value);
68
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
69
+ if (Array.isArray(value)) {
70
+ if (value.length === 0) return "[]";
71
+ return value
72
+ .map((item) => {
73
+ if (item !== null && typeof item === "object" && !Array.isArray(item)) {
74
+ const body = toYaml(item, indent + 1);
75
+ const lines = body.split("\n");
76
+ const first = lines[0] ?? "";
77
+ const rest = lines.slice(1).map((l) => `${pad} ${l}`).join("\n");
78
+ return rest
79
+ ? `${pad}- ${first}\n${rest}`
80
+ : `${pad}- ${first}`;
81
+ }
82
+ return `${pad}- ${toYaml(item, 0)}`;
83
+ })
84
+ .join("\n");
85
+ }
86
+ if (typeof value === "object") {
87
+ const entries = Object.entries(value as Record<string, unknown>).filter(
88
+ ([, v]) => v !== undefined,
89
+ );
90
+ if (entries.length === 0) return "{}";
91
+ return entries
92
+ .map(([k, v]) => {
93
+ if (v !== null && typeof v === "object") {
94
+ const nested = toYaml(v, indent + 1);
95
+ if (nested === "{}" || nested === "[]") return `${pad}${k}: ${nested}`;
96
+ return `${pad}${k}:\n${nested}`;
97
+ }
98
+ return `${pad}${k}: ${toYaml(v, 0)}`;
99
+ })
100
+ .join("\n");
101
+ }
102
+ return yamlQuote(String(value));
103
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Image recipes and compose derivation.
3
+ *
4
+ * Recipes translate a normalised {@link ServiceSpec} into image-specific
5
+ * env / command / healthcheck and expose {@link ImageRecipe.url} so the
6
+ * kernel never learns an env-var name. Four compose override layers end
7
+ * in an untouched `compose.override.yml`. Credentials never enter YAML.
8
+ */
9
+
10
+ export type {
11
+ ComposeHealthcheck,
12
+ DeriveOptions,
13
+ DeriveResult,
14
+ GeneratedFile,
15
+ ImageRecipe,
16
+ RecipeApplyResult,
17
+ ServiceCredentials,
18
+ ServiceEndpoint,
19
+ ServiceSpec,
20
+ } from "./types.ts";
21
+
22
+ export {
23
+ COMPOSE_OVERRIDE,
24
+ assertNoCredentialsInYaml,
25
+ buildSpecs,
26
+ buildStackEnv,
27
+ emitComposeLayers,
28
+ formatStackEnv,
29
+ } from "./compose.ts";
30
+
31
+ export { deriveInfrastructure, writeDerivedFiles } from "./derive.ts";
32
+ export { emitDockerfile } from "./dockerfile.ts";
33
+ export { credEnv, envPrefix, serviceNameFor } from "./helpers.ts";
34
+ export { generateCredentials } from "./credentials.ts";
35
+ export {
36
+ builtinRecipes,
37
+ postgres,
38
+ recipeFor,
39
+ redis,
40
+ } from "./recipes/index.ts";
41
+ export {
42
+ formatStackPreview,
43
+ resolveStack,
44
+ type StackRow,
45
+ } from "./stack.ts";
46
+ export {
47
+ formatImagesLock,
48
+ pinImages,
49
+ type DigestResolver,
50
+ type ImageLockEntry,
51
+ type ImagesLock,
52
+ } from "./pin.ts";
@@ -0,0 +1,90 @@
1
+ /**
2
+ * `oke images pin` — tags → digests in `oke.images.lock`.
3
+ */
4
+
5
+ /** One lock entry. */
6
+ export interface ImageLockEntry {
7
+ readonly image: string;
8
+ readonly digest: string;
9
+ readonly pinnedAt: string;
10
+ }
11
+
12
+ /** Lock file shape. */
13
+ export interface ImagesLock {
14
+ readonly oke: "1.0";
15
+ readonly images: Readonly<Record<string, ImageLockEntry>>;
16
+ }
17
+
18
+ /** Resolve a tag to a digest (injectable for tests). */
19
+ export type DigestResolver = (image: string) => Promise<string>;
20
+
21
+ /**
22
+ * Pin every image tag to a digest.
23
+ *
24
+ * @param images - Role → image tag
25
+ * @param resolveDigest - Digest resolver (defaults to `docker buildx imagetools`)
26
+ */
27
+ export async function pinImages(
28
+ images: Readonly<Record<string, string>>,
29
+ resolveDigest: DigestResolver = dockerDigest,
30
+ ): Promise<ImagesLock> {
31
+ const entries: Record<string, ImageLockEntry> = {};
32
+ const pinnedAt = new Date().toISOString();
33
+ for (const [role, image] of Object.entries(images)) {
34
+ if (image.includes("@sha256:")) {
35
+ entries[role] = { image, digest: image.split("@")[1]!, pinnedAt };
36
+ continue;
37
+ }
38
+ const digest = await resolveDigest(image);
39
+ entries[role] = {
40
+ image: `${image.replace(/@sha256:[a-f0-9]+$/i, "")}@${digest}`,
41
+ digest,
42
+ pinnedAt,
43
+ };
44
+ }
45
+ return { oke: "1.0", images: entries };
46
+ }
47
+
48
+ /**
49
+ * Format lock file JSON.
50
+ *
51
+ * @param lock - Lock document
52
+ */
53
+ export function formatImagesLock(lock: ImagesLock): string {
54
+ return `${JSON.stringify(lock, null, 2)}\n`;
55
+ }
56
+
57
+ /**
58
+ * Default digest resolver via `docker buildx imagetools inspect`.
59
+ *
60
+ * @param image - Image tag
61
+ */
62
+ async function dockerDigest(image: string): Promise<string> {
63
+ const proc = Bun.spawn(
64
+ [
65
+ "docker",
66
+ "buildx",
67
+ "imagetools",
68
+ "inspect",
69
+ "--format",
70
+ "{{.Manifest.Digest}}",
71
+ image,
72
+ ],
73
+ { stdout: "pipe", stderr: "pipe" },
74
+ );
75
+ const [stdout, stderr, code] = await Promise.all([
76
+ new Response(proc.stdout).text(),
77
+ new Response(proc.stderr).text(),
78
+ proc.exited,
79
+ ]);
80
+ if (code !== 0) {
81
+ throw new Error(
82
+ `oke images pin: failed to resolve ${image}: ${stderr.trim() || `exit ${code}`}`,
83
+ );
84
+ }
85
+ const digest = stdout.trim();
86
+ if (!digest.startsWith("sha256:")) {
87
+ throw new Error(`oke images pin: unexpected digest for ${image}: ${digest}`);
88
+ }
89
+ return digest;
90
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Built-in image recipes — match by image ref, never by vendor driver id.
3
+ */
4
+
5
+ import type { ImageRecipe } from "../types.ts";
6
+ import { postgres } from "./postgres.ts";
7
+ import { redis } from "./redis.ts";
8
+
9
+ /** Default recipe catalogue. */
10
+ export const builtinRecipes: readonly ImageRecipe[] = [postgres, redis];
11
+
12
+ export { postgres, redis };
13
+
14
+ /**
15
+ * Resolve the recipe for an image reference.
16
+ *
17
+ * @param image - Image pin
18
+ * @param extra - Plugin / test recipes (tried first)
19
+ */
20
+ export function recipeFor(
21
+ image: string,
22
+ extra: readonly ImageRecipe[] = [],
23
+ ): ImageRecipe {
24
+ for (const r of extra) {
25
+ if (r.match(image)) return r;
26
+ }
27
+ for (const r of builtinRecipes) {
28
+ if (r.match(image)) return r;
29
+ }
30
+ throw new Error(
31
+ `oke docker: no image recipe matches ${JSON.stringify(image)} — add a recipe (≤15 lines) or pin a known image`,
32
+ );
33
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Postgres / pgvector / Timescale image recipe (≤15 lines of recipe body).
3
+ */
4
+
5
+ import { credEnv } from "../helpers.ts";
6
+ import type { ImageRecipe } from "../types.ts";
7
+
8
+ /** Postgres-protocol servers (Postgres · Neon · Supabase · pgvector · Timescale). */
9
+ export const postgres: ImageRecipe = {
10
+ id: "postgres",
11
+ port: 5432,
12
+ match: (i) => /postgres|pgvector|timescale/i.test(i),
13
+ apply: (s) => ({
14
+ environment: { POSTGRES_USER: credEnv(s, "USER"), POSTGRES_PASSWORD: credEnv(s, "PASSWORD"), POSTGRES_DB: credEnv(s, "DB") },
15
+ healthcheck: { test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER"], interval: "5s", timeout: "3s", retries: 10 },
16
+ }),
17
+ url: (_s, c) => `postgres://${c.user}:${encodeURIComponent(c.password)}@${c.host}:${c.port}/${c.database}`,
18
+ };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Redis-protocol image recipe (Redis · Valkey · Dragonfly · KeyDB).
3
+ */
4
+
5
+ import { credEnv } from "../helpers.ts";
6
+ import type { ImageRecipe } from "../types.ts";
7
+
8
+ /** Redis-protocol servers. */
9
+ export const redis: ImageRecipe = {
10
+ id: "redis",
11
+ port: 6379,
12
+ match: (i) => /redis|valkey|dragonfly|keydb/i.test(i),
13
+ apply: (s) => ({
14
+ command: ["redis-server", "--requirepass", credEnv(s, "PASSWORD")],
15
+ healthcheck: { test: ["CMD", "redis-cli", "-a", credEnv(s, "PASSWORD"), "ping"], interval: "5s", timeout: "3s", retries: 10 },
16
+ }),
17
+ url: (_s, c) => `redis://:${encodeURIComponent(c.password)}@${c.host}:${c.port}`,
18
+ };
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Integration: generated compose brings up postgres; app URL talks to it.
3
+ */
4
+
5
+ import { describe, expect, test } from "bun:test";
6
+ import { mkdtemp, rm } from "node:fs/promises";
7
+ import { tmpdir } from "node:os";
8
+ import { join } from "node:path";
9
+ import {
10
+ deriveInfrastructure,
11
+ formatStackEnv,
12
+ writeDerivedFiles,
13
+ } from "./index.ts";
14
+
15
+ async function dockerAvailable(): Promise<boolean> {
16
+ try {
17
+ const proc = Bun.spawn(["docker", "info"], {
18
+ stdout: "pipe",
19
+ stderr: "pipe",
20
+ });
21
+ return (await proc.exited) === 0;
22
+ } catch {
23
+ return false;
24
+ }
25
+ }
26
+
27
+ describe("oke dev --stack postgres integration", () => {
28
+ test("compose brings up postgres and the app talks to it", async () => {
29
+ if (!(await dockerAvailable())) {
30
+ console.warn("skipping: docker daemon not available");
31
+ return;
32
+ }
33
+
34
+ const dir = await mkdtemp(join(tmpdir(), "oke-stack-pg-"));
35
+ const project = `oke-pg-${Date.now()}`;
36
+ try {
37
+ const derived = deriveInfrastructure({
38
+ images: { "store.sql": "postgres:16-alpine" },
39
+ credentials: {
40
+ "store.sql": {
41
+ user: "oke",
42
+ password: "stack-integration-pass",
43
+ database: "oke",
44
+ },
45
+ },
46
+ app: "stacktest",
47
+ host: "127.0.0.1",
48
+ });
49
+ await writeDerivedFiles(derived, dir, { writeStackEnv: true });
50
+
51
+ // Stack-only: no app service — just the role compose file.
52
+ const composeFiles = ["compose.store.sql.yml"];
53
+ const up = Bun.spawn(
54
+ [
55
+ "docker",
56
+ "compose",
57
+ "-p",
58
+ project,
59
+ ...composeFiles.flatMap((f) => ["-f", f]),
60
+ "up",
61
+ "-d",
62
+ ],
63
+ {
64
+ cwd: dir,
65
+ stdout: "pipe",
66
+ stderr: "pipe",
67
+ env: {
68
+ ...process.env,
69
+ ...derived.stackEnv,
70
+ },
71
+ },
72
+ );
73
+ const [upOut, upErr, upCode] = await Promise.all([
74
+ new Response(up.stdout).text(),
75
+ new Response(up.stderr).text(),
76
+ up.exited,
77
+ ]);
78
+ expect(upCode).toBe(0);
79
+ if (upCode !== 0) console.error(upOut, upErr);
80
+
81
+ // Wait for healthy
82
+ let healthy = false;
83
+ for (let i = 0; i < 40; i++) {
84
+ const ps = Bun.spawn(
85
+ [
86
+ "docker",
87
+ "compose",
88
+ "-p",
89
+ project,
90
+ ...composeFiles.flatMap((f) => ["-f", f]),
91
+ "ps",
92
+ "--format",
93
+ "json",
94
+ ],
95
+ { cwd: dir, stdout: "pipe", stderr: "pipe" },
96
+ );
97
+ const text = await new Response(ps.stdout).text();
98
+ await ps.exited;
99
+ if (/healthy/i.test(text)) {
100
+ healthy = true;
101
+ break;
102
+ }
103
+ await Bun.sleep(500);
104
+ }
105
+ expect(healthy).toBe(true);
106
+
107
+ const url = derived.stackEnv.DATABASE_URL!;
108
+ // App talks to postgres via recipe URL (Bun.SQL) — kernel never sees env-var names.
109
+ const sql = new Bun.SQL(url);
110
+ try {
111
+ const rows = (await sql`select 1::int as n`) as Array<{ n: number }>;
112
+ expect(rows[0]?.n).toBe(1);
113
+ } finally {
114
+ await sql.close();
115
+ }
116
+
117
+ // Prove credentials live in .env.stack, not YAML.
118
+ const yml = await Bun.file(join(dir, "compose.store.sql.yml")).text();
119
+ expect(yml).not.toContain("stack-integration-pass");
120
+ expect(formatStackEnv(derived.stackEnv)).toContain(
121
+ "stack-integration-pass",
122
+ );
123
+ } finally {
124
+ await Bun.spawn(
125
+ [
126
+ "docker",
127
+ "compose",
128
+ "-p",
129
+ project,
130
+ "-f",
131
+ "compose.store.sql.yml",
132
+ "down",
133
+ "-v",
134
+ ],
135
+ { cwd: dir, stdout: "pipe", stderr: "pipe" },
136
+ ).exited.catch(() => {});
137
+ await rm(dir, { recursive: true, force: true }).catch(() => {});
138
+ }
139
+ }, 120_000);
140
+ });
@@ -0,0 +1,62 @@
1
+ /**
2
+ * `oke stack` — preview resolved images / tags / ports (writes nothing).
3
+ */
4
+
5
+ import { buildSpecs } from "./compose.ts";
6
+ import { recipeFor } from "./recipes/index.ts";
7
+ import type { DeriveOptions, ServiceSpec } from "./types.ts";
8
+
9
+ /** One resolved stack row for preview. */
10
+ export interface StackRow {
11
+ readonly role: string;
12
+ readonly image: string;
13
+ readonly recipe: string;
14
+ readonly service: string;
15
+ readonly containerPort: number;
16
+ readonly hostPort: number;
17
+ }
18
+
19
+ /**
20
+ * Resolve stack preview rows from image pins.
21
+ *
22
+ * @param options - Images (+ optional recipes)
23
+ */
24
+ export function resolveStack(options: DeriveOptions): readonly StackRow[] {
25
+ const specs = buildSpecs(options);
26
+ return specs.map((s) => toRow(s, options));
27
+ }
28
+
29
+ /**
30
+ * Format stack preview for the CLI.
31
+ *
32
+ * @param rows - Resolved rows
33
+ */
34
+ export function formatStackPreview(rows: readonly StackRow[]): string {
35
+ if (rows.length === 0) return "oke stack: no images configured\n";
36
+ const lines = [
37
+ "ROLE RECIPE IMAGE HOST:CONTAINER",
38
+ "-------------- --------- --------------------------------- --------------",
39
+ ];
40
+ for (const r of rows) {
41
+ lines.push(
42
+ `${pad(r.role, 14)} ${pad(r.recipe, 9)} ${pad(r.image, 33)} ${r.hostPort}:${r.containerPort}`,
43
+ );
44
+ }
45
+ return `${lines.join("\n")}\n`;
46
+ }
47
+
48
+ function toRow(spec: ServiceSpec, options: DeriveOptions): StackRow {
49
+ const recipe = recipeFor(spec.image, options.recipes ?? []);
50
+ return {
51
+ role: spec.role,
52
+ image: spec.image,
53
+ recipe: recipe.id,
54
+ service: spec.serviceName,
55
+ containerPort: spec.port,
56
+ hostPort: spec.hostPort,
57
+ };
58
+ }
59
+
60
+ function pad(s: string, n: number): string {
61
+ return s.length >= n ? s.slice(0, n) : s + " ".repeat(n - s.length);
62
+ }
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Normalised service + image-recipe contracts for compose derivation.
3
+ *
4
+ * Recipes translate a {@link ServiceSpec} into image-specific env / command /
5
+ * healthcheck and expose {@link ImageRecipe.url} so the kernel never learns
6
+ * an env-var name.
7
+ */
8
+
9
+ /** Credential material for a role — never serialised into generated YAML. */
10
+ export interface ServiceCredentials {
11
+ readonly user: string;
12
+ readonly password: string;
13
+ readonly database: string;
14
+ }
15
+
16
+ /** Connection endpoint used by {@link ImageRecipe.url}. */
17
+ export interface ServiceEndpoint {
18
+ readonly host: string;
19
+ readonly port: number;
20
+ readonly user: string;
21
+ readonly password: string;
22
+ readonly database: string;
23
+ }
24
+
25
+ /**
26
+ * Normalised service description produced from config `images` + role.
27
+ * Image-agnostic — recipes specialise it.
28
+ */
29
+ export interface ServiceSpec {
30
+ /** Role key (`store.sql`, `store.kv`, …). */
31
+ readonly role: string;
32
+ /** Compose service name (`store-sql`). */
33
+ readonly serviceName: string;
34
+ /** Image reference (tag or digest). */
35
+ readonly image: string;
36
+ /** Container listen port. */
37
+ readonly port: number;
38
+ /** Host port published in compose (dev defaults). */
39
+ readonly hostPort: number;
40
+ /** Credential placeholders (values live in `.env.stack`, not YAML). */
41
+ readonly credentials: ServiceCredentials;
42
+ }
43
+
44
+ /** Compose healthcheck block. */
45
+ export interface ComposeHealthcheck {
46
+ readonly test: readonly string[];
47
+ readonly interval?: string;
48
+ readonly timeout?: string;
49
+ readonly retries?: number;
50
+ readonly start_period?: string;
51
+ }
52
+
53
+ /** Image-specific compose fragment from {@link ImageRecipe.apply}. */
54
+ export interface RecipeApplyResult {
55
+ readonly environment?: Readonly<Record<string, string>>;
56
+ readonly command?: string | readonly string[];
57
+ readonly healthcheck?: ComposeHealthcheck;
58
+ readonly volumes?: readonly string[];
59
+ readonly user?: string;
60
+ }
61
+
62
+ /**
63
+ * Image recipe — match an image ref, specialise a {@link ServiceSpec},
64
+ * and build a connection URL without teaching the kernel env-var names.
65
+ */
66
+ export interface ImageRecipe {
67
+ /** Stable recipe id (`postgres`, `redis`, …). */
68
+ readonly id: string;
69
+ /** Default container port when the spec does not override. */
70
+ readonly port: number;
71
+ /**
72
+ * Whether this recipe handles `image`.
73
+ *
74
+ * @param image - Image reference
75
+ */
76
+ match(image: string): boolean;
77
+ /**
78
+ * Translate a normalised spec into image-specific compose fields.
79
+ * Environment values must be `${VAR}` refs — never cleartext secrets.
80
+ *
81
+ * @param spec - Normalised service
82
+ */
83
+ apply(spec: ServiceSpec): RecipeApplyResult;
84
+ /**
85
+ * Build a driver URL from endpoint credentials.
86
+ *
87
+ * @param spec - Normalised service
88
+ * @param endpoint - Host / port / credentials
89
+ */
90
+ url(spec: ServiceSpec, endpoint: ServiceEndpoint): string;
91
+ }
92
+
93
+ /** Options for compose / Dockerfile derivation. */
94
+ export interface DeriveOptions {
95
+ /** Role → image pin (from `oke.config.ts` / Manifest). */
96
+ readonly images: Readonly<Record<string, string>>;
97
+ /** Application name (compose project / app service). */
98
+ readonly app?: string;
99
+ /** App listen port (default 6530). */
100
+ readonly appPort?: number;
101
+ /** When true, emit prod overlays (limits, secret refs, deploy.replicas). */
102
+ readonly prod?: boolean;
103
+ /** Output directory (default `.`). */
104
+ readonly outDir?: string;
105
+ /** Inject credentials (tests). Defaults to generated randoms. */
106
+ readonly credentials?: Readonly<Record<string, ServiceCredentials>>;
107
+ /** Host for URL builders (default `127.0.0.1` in stack env). */
108
+ readonly host?: string;
109
+ /** Extra image recipes (plugins). */
110
+ readonly recipes?: readonly ImageRecipe[];
111
+ }
112
+
113
+ /** One generated file. */
114
+ export interface GeneratedFile {
115
+ /** Relative path under `outDir`. */
116
+ readonly path: string;
117
+ /** File contents. */
118
+ readonly content: string;
119
+ }
120
+
121
+ /** Result of {@link deriveInfrastructure}. */
122
+ export interface DeriveResult {
123
+ /** Normalised specs (one per image role). */
124
+ readonly specs: readonly ServiceSpec[];
125
+ /** Generated files (Dockerfile + compose layers). */
126
+ readonly files: readonly GeneratedFile[];
127
+ /**
128
+ * Stack env contents for `.env.stack` — written by `oke dev --stack`,
129
+ * never embedded in YAML.
130
+ */
131
+ readonly stackEnv: Readonly<Record<string, string>>;
132
+ /** Compose `-f` merge order (four override layers). */
133
+ readonly composeFiles: readonly string[];
134
+ }