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,982 @@
1
+ /**
2
+ * Console server state — operators, sessions, claim code, Manifest snapshot.
3
+ */
4
+
5
+ import {
6
+ ACCESS_TTL_MS,
7
+ createOperatorInviteStore,
8
+ createOperatorStore,
9
+ createSessionStore,
10
+ type ApiKeyStore,
11
+ type OperatorInviteStore,
12
+ type OperatorStore,
13
+ type RoleStore,
14
+ type SessionStore,
15
+ } from "../../auth/index.ts";
16
+ import {
17
+ accessCreateInvite,
18
+ accessCreateKey,
19
+ accessRevokeKey,
20
+ accessRotateKey,
21
+ accessSetRoleGrants,
22
+ effectivePermissions,
23
+ keyBlastRadius,
24
+ projectAccessPanel,
25
+ type AccessEffectivePermissions,
26
+ type AccessKeyBlastRadius,
27
+ type AccessKeyRow,
28
+ type AccessPanelProjection,
29
+ } from "./access.ts";
30
+ import { deriveModuleActions, type GateRuntime } from "../../elements/gate.ts";
31
+ import type {
32
+ SignalBus,
33
+ SignalDiscardOptions,
34
+ SignalReplayOptions,
35
+ SignalReplayResult,
36
+ } from "../../drivers/signal-types.ts";
37
+ import type { AiRuntime, EvalSuiteResult } from "../../elements/ai.ts";
38
+ import {
39
+ createMemorySignalConfigStore,
40
+ type SignalConfigStore,
41
+ } from "../../elements/signal/reconcile.ts";
42
+ import type { Manifest } from "../../manifest/types.ts";
43
+ import type { WideEvent } from "../../runs/types.ts";
44
+ import {
45
+ effectsForFlowFromManifest,
46
+ projectAiPanel,
47
+ type ConsoleAiProjection,
48
+ } from "./ai.ts";
49
+ import {
50
+ createLoginAttemptBag,
51
+ type LoginAttemptBag,
52
+ } from "./auth-rate.ts";
53
+ import { mintClaimCode, type ClaimCodeState } from "./claim.ts";
54
+ import {
55
+ discardViaBus,
56
+ projectSignalsList,
57
+ replayViaBus,
58
+ type ConsoleSignalRow,
59
+ } from "./signals.ts";
60
+ import {
61
+ deleteStore,
62
+ editStore,
63
+ projectStoresList,
64
+ purgeStoreCache,
65
+ queryStore,
66
+ runStoreSql,
67
+ type ConsoleStoreRow,
68
+ type StoreDeleteInput,
69
+ type StoreEditInput,
70
+ type StoreQueryInput,
71
+ type StoreQueryResult,
72
+ } from "./store.ts";
73
+ import type { ClockRuntime, EditScheduleInput } from "../../elements/clock.ts";
74
+ import type { StoreRuntime } from "../../elements/store.ts";
75
+ import type { VaultRuntime } from "../../elements/vault.ts";
76
+ import type { JournalStore } from "../../kernel/journal.ts";
77
+ import type { ResourceRef } from "../../manifest/types.ts";
78
+ import {
79
+ editCronSchedule,
80
+ pauseCronNow,
81
+ projectClocksList,
82
+ runCronNow,
83
+ wakeEarlyNow,
84
+ type ConsoleClockList,
85
+ } from "./clock.ts";
86
+ import {
87
+ createDefaultGateAuthStores,
88
+ createManifestGateRuntime,
89
+ powersForPrincipal,
90
+ projectGatesPanel,
91
+ simulateGates,
92
+ type GatesPanelProjection,
93
+ type SimulateGatesInput,
94
+ type SimulateGatesResult,
95
+ } from "./gates.ts";
96
+ import {
97
+ projectVaultList,
98
+ rotateVaultValue,
99
+ setVaultValue,
100
+ type ConsoleVaultRow,
101
+ type VaultWriteInput,
102
+ } from "./vault.ts";
103
+ import type { ChannelInbox } from "../../drivers/channel-types.ts";
104
+ import type { ChannelRuntime, TemplateCatalog } from "../../elements/channel.ts";
105
+ import {
106
+ previewChannelTemplate,
107
+ projectChannelsList,
108
+ revealChannelRecipient,
109
+ sendChannelTest,
110
+ verifyChannelAuth,
111
+ type ConsoleChannelPreview,
112
+ type ConsoleChannelsList,
113
+ type EmailAuthResult,
114
+ } from "./channels.ts";
115
+ import type { OkeConfig } from "../../config/index.ts";
116
+ import type { PluginRegistry } from "../../kernel/registry.ts";
117
+ import {
118
+ projectPluginsList,
119
+ type ConsolePluginsList,
120
+ } from "./plugins.ts";
121
+ import {
122
+ projectManifestDiff,
123
+ type ConsoleDiffProjection,
124
+ } from "./diff.ts";
125
+
126
+ /** User-plane identity row for the Flows invoke-as picker. */
127
+ export interface ConsoleIdentity {
128
+ readonly id: string;
129
+ readonly email: string;
130
+ readonly name: string;
131
+ readonly status: "active" | "disabled";
132
+ readonly scopes: readonly string[];
133
+ }
134
+
135
+ /** Mutable Console runtime state for one process. */
136
+ export interface ConsoleState {
137
+ readonly operators: OperatorStore;
138
+ readonly sessions: SessionStore;
139
+ readonly claim: ClaimCodeState;
140
+ /** Auth HMAC secret (operator sessions). */
141
+ readonly secret: string;
142
+ /** Clock. */
143
+ readonly now: () => number;
144
+ /** Working-tree root for structural diffs. */
145
+ readonly cwd: string;
146
+ /** Latest Manifest snapshot fed to the live channel. */
147
+ manifest: Manifest | null;
148
+ /** Previous Manifest — for permission-widening deploy diff. */
149
+ previousManifest: Manifest | null;
150
+ /** Live-channel subscribers. */
151
+ readonly liveSubscribers: Set<(msg: ConsoleLiveMessage) => void>;
152
+ /** Role store (data, not code) — Gates · Access. */
153
+ readonly roles: RoleStore;
154
+ /** API key store — first-class principals. */
155
+ readonly apiKeys: ApiKeyStore;
156
+ /** Operator invitations — Access hygiene. */
157
+ readonly invites: OperatorInviteStore;
158
+ /** Access-token TTL (ms) from auth config — residual revoke delay. */
159
+ readonly accessTtlMs: number;
160
+ /** roleId → member principal ids. */
161
+ readonly roleMembers: Map<string, string[]>;
162
+ /** Project Access panel (planes · grantable · hygiene). */
163
+ listAccess: (actorScopes: Iterable<string>) => Promise<AccessPanelProjection>;
164
+ /** Effective permissions with provenance. */
165
+ accessEffective: (input: {
166
+ readonly kind: "operator" | "user" | "role" | "key";
167
+ readonly id: string;
168
+ }) => Promise<AccessEffectivePermissions | null>;
169
+ /** Blast radius for a key from Runs. */
170
+ accessKeyBlast: (keyId: string) => Promise<AccessKeyBlastRadius>;
171
+ /** Create an attenuated API key (secret once). */
172
+ accessCreateKey: (input: {
173
+ readonly plane: "user" | "operator";
174
+ readonly name: string;
175
+ readonly scopes: readonly string[];
176
+ readonly creatorId: string;
177
+ readonly creatorScopes: Iterable<string>;
178
+ readonly expiresAt?: number | null;
179
+ readonly rateLimit?: { max: number; per: string } | null;
180
+ readonly ipAllowlist?: readonly string[];
181
+ }) => Promise<{ readonly row: AccessKeyRow; readonly secret: string }>;
182
+ /** Revoke a key (irreversible). */
183
+ accessRevokeKey: (keyId: string) => Promise<AccessKeyRow | null>;
184
+ /** Rotate a key secret (shown once). */
185
+ accessRotateKey: (
186
+ keyId: string,
187
+ ) => Promise<{ readonly row: AccessKeyRow; readonly secret: string } | null>;
188
+ /** Replace role grants (grantable scopes only). */
189
+ accessSetRoleGrants: (input: {
190
+ readonly roleId: string;
191
+ readonly scopes: readonly string[];
192
+ readonly actorScopes: Iterable<string>;
193
+ }) => Promise<void>;
194
+ /** Invite an operator. */
195
+ accessCreateInvite: (input: {
196
+ readonly email: string;
197
+ readonly invitedBy: string;
198
+ }) => Promise<{ readonly id: string; readonly email: string; readonly expiresAt: number }>;
199
+ /**
200
+ * Live GateRuntime from host boot (A). Bound after boot; Manifest
201
+ * reconstruction is the Console-only fallback.
202
+ */
203
+ gateRuntime: GateRuntime | null;
204
+ /** Project Gates panel (inquiry surfaces + audit + widenings). */
205
+ listGates: () => Promise<GatesPanelProjection>;
206
+ /** Evaluate-only simulator — never invokes the flow handler. */
207
+ simulateGates: (input: SimulateGatesInput) => Promise<SimulateGatesResult>;
208
+ /** Principal → powers (scopes + allowed flows). */
209
+ powersForPrincipal: (input: {
210
+ readonly kind: "role" | "key" | "user";
211
+ readonly id: string;
212
+ }) => Promise<{
213
+ readonly scopes: readonly string[];
214
+ readonly allowedFlowIds: readonly string[];
215
+ readonly deniedFlowIds: readonly string[];
216
+ }>;
217
+ /** Bound after Console app boot — reads the runs store. */
218
+ listRuns: () => Promise<WideEvent[]>;
219
+ /** Signal config store (`oke_signal_config`) — retains orphaned rows. */
220
+ readonly signalConfig: SignalConfigStore;
221
+ /**
222
+ * Live signal bus. Bound after host app boot when available;
223
+ * `null` until wired (list still returns reconciled Manifest rows).
224
+ */
225
+ signalBus: SignalBus | null;
226
+ /** Project operator-plane signal rows (Manifest + bus + orphans). */
227
+ listSignals: () => Promise<readonly ConsoleSignalRow[]>;
228
+ /** Replay / dry-run via the real bus. */
229
+ replaySignals: (options: SignalReplayOptions) => Promise<SignalReplayResult>;
230
+ /** Discard dead letters via the real bus. */
231
+ discardSignals: (
232
+ options: SignalDiscardOptions,
233
+ ) => Promise<{ readonly discarded: number }>;
234
+ /**
235
+ * Live store runtime. Bound after boot from Manifest (memory default)
236
+ * or host injection.
237
+ */
238
+ storeRuntime: StoreRuntime | null;
239
+ /** Project operator-plane store rows. */
240
+ listStores: () => Promise<{
241
+ readonly stores: readonly ConsoleStoreRow[];
242
+ readonly tenancyDeclared: boolean;
243
+ readonly tenants: readonly string[];
244
+ }>;
245
+ /** Browse a store facet. */
246
+ queryStore: (input: StoreQueryInput) => Promise<StoreQueryResult>;
247
+ /** Direct edit (not a flow execution). */
248
+ editStore: (
249
+ input: StoreEditInput,
250
+ options?: { readonly dryRun?: boolean },
251
+ ) => Promise<Awaited<ReturnType<typeof editStore>>>;
252
+ /** Delete rows/keys. */
253
+ deleteStore: (
254
+ input: StoreDeleteInput,
255
+ ) => Promise<{ readonly deleted: number }>;
256
+ /** Purge cache keys for a resource. */
257
+ purgeStoreCache: (
258
+ resource: ResourceRef,
259
+ ) => Promise<{ readonly keys: readonly string[] }>;
260
+ /** Raw SQL console. */
261
+ runStoreSql: (
262
+ ref: ResourceRef,
263
+ sqlText: string,
264
+ options: {
265
+ readonly allowWrite: boolean;
266
+ readonly revealPii?: boolean;
267
+ readonly tenant?: string;
268
+ },
269
+ ) => Promise<{
270
+ readonly rows: readonly Record<string, unknown>[];
271
+ readonly masked: boolean;
272
+ readonly routedRole: "primary" | "replica";
273
+ }>;
274
+ /**
275
+ * Live Clock runtime. Bound after boot from Manifest clocks
276
+ * or host injection (A — reuse reconciliation / lease / DST).
277
+ */
278
+ clockRuntime: ClockRuntime | null;
279
+ /** Project Clock panel (timeline + waiting-on + cron health). */
280
+ listClocks: () => Promise<ConsoleClockList>;
281
+ /** Run a cron now (lease-gated). */
282
+ runCronNow: (name: string) => Promise<{ readonly ran: boolean }>;
283
+ /** Pause a cron. */
284
+ pauseCron: (name: string) => Promise<{ readonly name: string; readonly status: string }>;
285
+ /** Edit overridable schedule. */
286
+ editSchedule: (
287
+ input: EditScheduleInput,
288
+ ) => Promise<{ readonly name: string; readonly effectiveCron?: string; readonly effectiveEvery?: string }>;
289
+ /** Wake a sleeping durable run early and resume. */
290
+ wakeEarly: (runId: string) => Promise<{
291
+ readonly runId: string;
292
+ readonly wakeAt: number;
293
+ readonly resumed: boolean;
294
+ }>;
295
+ /**
296
+ * Live vault runtime. Bound after boot from Manifest (standard chain)
297
+ * or host injection.
298
+ */
299
+ vaultRuntime: VaultRuntime | null;
300
+ /** Durable journal for rotation blast radius + Clock waiting-on. */
301
+ journalStore: JournalStore | null;
302
+ /** Current environment label for fingerprint columns. */
303
+ vaultEnv: string;
304
+ /** Project operator-plane vault rows (fingerprints only for secrets). */
305
+ listVault: () => Promise<{
306
+ readonly secrets: readonly ConsoleVaultRow[];
307
+ readonly env: string;
308
+ }>;
309
+ /** Set a vault value (write-only). */
310
+ setVault: (
311
+ input: VaultWriteInput,
312
+ ) => Promise<{ readonly name: string; readonly fingerprint: string | null }>;
313
+ /** Rotate a vault value (write-only; distinct confirm phrase). */
314
+ rotateVault: (
315
+ input: VaultWriteInput,
316
+ ) => Promise<{ readonly name: string; readonly fingerprint: string | null }>;
317
+ /** User-plane identities available for invoke-as. */
318
+ readonly identities: ConsoleIdentity[];
319
+ /** Whether this process is treated as production (typed confirm). */
320
+ readonly production: boolean;
321
+ /**
322
+ * Live AI runtime — journal, denial ledger, agent trails (console §9.10).
323
+ * Bound after host boot; null until wired.
324
+ */
325
+ aiRuntime: AiRuntime | null;
326
+ /** Eval suite history for score distributions. */
327
+ evalResults: EvalSuiteResult[];
328
+ /** Project AI panel from runtime + Manifest + runs. */
329
+ listAi: () => Promise<ConsoleAiProjection>;
330
+ /**
331
+ * Project Manifest Diff — `diffManifest` + Runs traffic + weekly bill
332
+ * (console §9.12).
333
+ */
334
+ listDiff: () => Promise<ConsoleDiffProjection>;
335
+ /**
336
+ * Project Plugins panel — origin × state, supply-chain, capability diff
337
+ * (console §9.15). Read-only; never installs.
338
+ */
339
+ listPlugins: () => Promise<ConsolePluginsList>;
340
+ /** Loaded oke.config for CORE tenancy/privacy state derivation. */
341
+ okeConfig: OkeConfig | null;
342
+ /** Live plugin registry from host boot (optional). */
343
+ pluginRegistry: PluginRegistry | null;
344
+ /**
345
+ * Live Channel runtime + shared console inbox (console §9.9).
346
+ * Bound after boot from Manifest or host injection.
347
+ */
348
+ channelRuntime: ChannelRuntime | null;
349
+ /** Dev console-driver inbox (all media land here). */
350
+ channelInbox: ChannelInbox | null;
351
+ /** Optional i18n body catalog for previews. */
352
+ channelCatalog: TemplateCatalog;
353
+ /** Project Channels panel (inbox / deliverability). */
354
+ listChannels: () => Promise<ConsoleChannelsList>;
355
+ /** Locale-resolved template preview. */
356
+ previewChannel: (input: {
357
+ readonly template: string;
358
+ readonly locale?: string;
359
+ readonly profileLocale?: string;
360
+ readonly acceptLanguage?: string;
361
+ readonly data?: Readonly<Record<string, unknown>>;
362
+ }) => Promise<ConsoleChannelPreview>;
363
+ /** SPF/DKIM/DMARC for a From domain. */
364
+ verifyChannelAuth: (fromOrDomain: string) => Promise<EmailAuthResult>;
365
+ /** Audited recipient reveal. */
366
+ revealChannel: (id: string) => Promise<{
367
+ readonly id: string;
368
+ readonly to: string;
369
+ } | null>;
370
+ /** Real send-test through the Channel runtime. */
371
+ sendChannelTest: (input: {
372
+ readonly template: string;
373
+ readonly to: string;
374
+ readonly locale?: string;
375
+ readonly data?: Readonly<Record<string, unknown>>;
376
+ }) => Promise<{
377
+ readonly ok: boolean;
378
+ readonly messageId: string;
379
+ readonly status: string;
380
+ readonly chain: string;
381
+ }>;
382
+ /** Whether first operator exists (wizard permanently closed). */
383
+ get setupClosed(): boolean;
384
+ /**
385
+ * Per-email login attempt timestamps for credential-check rate limiting
386
+ * (console §10.4 — same 5/60s strategy as setup-claim).
387
+ */
388
+ readonly loginAttempts: LoginAttemptBag;
389
+ }
390
+
391
+ /** Live channel message kinds. */
392
+ export type ConsoleLiveMessage =
393
+ | { readonly type: "manifest"; readonly manifest: Manifest }
394
+ | {
395
+ readonly type: "manifest.diff";
396
+ readonly before: Manifest;
397
+ readonly after: Manifest;
398
+ }
399
+ | { readonly type: "ping"; readonly at: number };
400
+
401
+ /** Options for {@link createConsoleState}. */
402
+ export interface CreateConsoleStateOptions {
403
+ readonly secret?: string;
404
+ readonly now?: () => number;
405
+ readonly cwd?: string;
406
+ readonly manifest?: Manifest | null;
407
+ /** Skip printing the claim code (tests). */
408
+ readonly silentClaim?: boolean;
409
+ /** Seed identities for the invoke-as picker. */
410
+ readonly identities?: readonly ConsoleIdentity[];
411
+ /** Production flag — irreversible invokes require typed confirm. */
412
+ readonly production?: boolean;
413
+ /** Access-token TTL override (ms) — residual revoke delay note. */
414
+ readonly accessTtlMs?: number;
415
+ /** Injected vault runtime (tests / host). */
416
+ readonly vaultRuntime?: VaultRuntime | null;
417
+ /** Injected journal store for blast-radius / waiting-on queries. */
418
+ readonly journalStore?: JournalStore | null;
419
+ /** Environment label for vault fingerprints. */
420
+ readonly vaultEnv?: string;
421
+ /** Injected GateRuntime (tests / host). */
422
+ readonly gateRuntime?: GateRuntime | null;
423
+ /** Injected ClockRuntime (tests / host). */
424
+ readonly clockRuntime?: ClockRuntime | null;
425
+ /** Previous Manifest for widenings (tests). */
426
+ readonly previousManifest?: Manifest | null;
427
+ /** Injected ChannelRuntime (tests / host). */
428
+ readonly channelRuntime?: ChannelRuntime | null;
429
+ /** Injected console inbox (tests / host). */
430
+ readonly channelInbox?: ChannelInbox | null;
431
+ /** Template body catalog for previews. */
432
+ readonly channelCatalog?: TemplateCatalog;
433
+ /** Loaded oke.config (tenancy / privacy state derivation). */
434
+ readonly okeConfig?: OkeConfig | null;
435
+ /** Host plugin registry for scopes / capabilities. */
436
+ readonly pluginRegistry?: PluginRegistry | null;
437
+ }
438
+
439
+ /**
440
+ * Create Console state and mint a claim code for this boot.
441
+ *
442
+ * @param options - Secret, clock, cwd
443
+ */
444
+ export function createConsoleState(
445
+ options: CreateConsoleStateOptions = {},
446
+ ): ConsoleState {
447
+ const secret =
448
+ options.secret ??
449
+ process.env.OKE_CONSOLE_SECRET ??
450
+ `oke-console-dev-${crypto.randomUUID()}`;
451
+ const now = options.now ?? (() => Date.now());
452
+ const claim = mintClaimCode(now);
453
+ const operators = createOperatorStore();
454
+ const sessions = createSessionStore();
455
+ const liveSubscribers = new Set<(msg: ConsoleLiveMessage) => void>();
456
+
457
+ const signalConfig = createMemorySignalConfigStore();
458
+ const gateAuth = createDefaultGateAuthStores();
459
+ const invites = createOperatorInviteStore();
460
+ seedAccessDemoData(gateAuth.apiKeys, invites, now);
461
+
462
+ const state: ConsoleState = {
463
+ operators,
464
+ sessions,
465
+ claim,
466
+ loginAttempts: createLoginAttemptBag(),
467
+ secret,
468
+ now,
469
+ cwd: options.cwd ?? process.cwd(),
470
+ manifest: options.manifest ?? null,
471
+ previousManifest: options.previousManifest ?? null,
472
+ liveSubscribers,
473
+ roles: gateAuth.roles,
474
+ apiKeys: gateAuth.apiKeys,
475
+ invites,
476
+ accessTtlMs: options.accessTtlMs ?? ACCESS_TTL_MS,
477
+ roleMembers: gateAuth.roleMembers,
478
+ listAccess: async (actorScopes) => {
479
+ return projectAccessPanel({
480
+ manifest: state.manifest,
481
+ roles: state.roles,
482
+ apiKeys: state.apiKeys,
483
+ operators: state.operators,
484
+ invites: state.invites,
485
+ identities: state.identities,
486
+ roleMembers: state.roleMembers,
487
+ actorScopes,
488
+ accessTtlMs: state.accessTtlMs,
489
+ now: state.now,
490
+ });
491
+ },
492
+ accessEffective: async (input) => {
493
+ return effectivePermissions({
494
+ ...input,
495
+ roles: state.roles,
496
+ apiKeys: state.apiKeys,
497
+ operators: state.operators,
498
+ identities: state.identities,
499
+ roleMembers: state.roleMembers,
500
+ });
501
+ },
502
+ accessKeyBlast: async (keyId) => {
503
+ const runs = await state.listRuns();
504
+ return keyBlastRadius({
505
+ keyId,
506
+ apiKeys: state.apiKeys,
507
+ runs,
508
+ accessTtlMs: state.accessTtlMs,
509
+ });
510
+ },
511
+ accessCreateKey: async (input) => {
512
+ return accessCreateKey(state.apiKeys, {
513
+ ...input,
514
+ catalog: accessCatalog(state),
515
+ now: state.now,
516
+ });
517
+ },
518
+ accessRevokeKey: async (keyId) => {
519
+ return accessRevokeKey({
520
+ apiKeys: state.apiKeys,
521
+ sessions: state.sessions,
522
+ keyId,
523
+ now: state.now,
524
+ });
525
+ },
526
+ accessRotateKey: async (keyId) => accessRotateKey(state.apiKeys, keyId),
527
+ accessSetRoleGrants: async (input) => {
528
+ accessSetRoleGrants({
529
+ roles: state.roles,
530
+ roleId: input.roleId,
531
+ scopes: input.scopes,
532
+ actorScopes: input.actorScopes,
533
+ catalog: accessCatalog(state),
534
+ });
535
+ },
536
+ accessCreateInvite: async (input) => {
537
+ const row = accessCreateInvite(state.invites, {
538
+ ...input,
539
+ now: state.now,
540
+ });
541
+ return { id: row.id, email: row.email, expiresAt: row.expiresAt };
542
+ },
543
+ gateRuntime: options.gateRuntime ?? null,
544
+ listGates: async () => {
545
+ const operatorRoles = new Map<string, readonly string[]>();
546
+ const ops = new Map<string, { name: string; email: string }>();
547
+ for (const [id, roleIds] of operators.roles) {
548
+ operatorRoles.set(id, roleIds);
549
+ }
550
+ for (const op of operators.operators.values()) {
551
+ ops.set(op.id, { name: op.name, email: op.email });
552
+ }
553
+ return projectGatesPanel({
554
+ manifest: state.manifest,
555
+ roles: state.roles,
556
+ apiKeys: state.apiKeys,
557
+ identities: state.identities,
558
+ operatorRoles,
559
+ operators: ops,
560
+ roleMembers: state.roleMembers,
561
+ previousManifest: state.previousManifest,
562
+ });
563
+ },
564
+ simulateGates: async (input) => {
565
+ return simulateGates({
566
+ ...input,
567
+ manifest: state.manifest,
568
+ gateRuntime: state.gateRuntime,
569
+ roles: state.roles,
570
+ apiKeys: state.apiKeys,
571
+ identities: state.identities,
572
+ now: state.now,
573
+ });
574
+ },
575
+ powersForPrincipal: async (input) => {
576
+ return powersForPrincipal({
577
+ ...input,
578
+ manifest: state.manifest,
579
+ gateRuntime: state.gateRuntime,
580
+ roles: state.roles,
581
+ apiKeys: state.apiKeys,
582
+ identities: state.identities,
583
+ now: state.now,
584
+ });
585
+ },
586
+ listRuns: async () => [],
587
+ signalConfig,
588
+ signalBus: null,
589
+ listSignals: async () => {
590
+ const runs = await state.listRuns();
591
+ return projectSignalsList({
592
+ manifest: state.manifest,
593
+ config: state.signalConfig,
594
+ bus: state.signalBus,
595
+ runs: runs.map((r) => ({
596
+ id: r.id,
597
+ flow: r.flow,
598
+ startedAt: r.startedAt,
599
+ effects: r.effects.map((e) => ({
600
+ kind: e.kind,
601
+ resource: e.resource,
602
+ })),
603
+ })),
604
+ });
605
+ },
606
+ replaySignals: async (opts) => {
607
+ if (!state.signalBus) {
608
+ return {
609
+ attempted: 0,
610
+ succeeded: 0,
611
+ failed: 0,
612
+ dryRun: opts.dryRun,
613
+ results: [],
614
+ wouldHaveFired: [],
615
+ };
616
+ }
617
+ return replayViaBus(state.signalBus, opts);
618
+ },
619
+ discardSignals: async (opts) => {
620
+ if (!state.signalBus) return { discarded: 0 };
621
+ return discardViaBus(state.signalBus, opts);
622
+ },
623
+ storeRuntime: null,
624
+ listStores: async () => {
625
+ const runs = await state.listRuns();
626
+ return projectStoresList({
627
+ manifest: state.manifest,
628
+ runtime: state.storeRuntime,
629
+ cwd: state.cwd,
630
+ runs: runs.map((r) => ({
631
+ flow: r.flow,
632
+ replicaLagMs: r.replicaLagMs,
633
+ tenant: r.tenant,
634
+ effects: r.effects,
635
+ })),
636
+ });
637
+ },
638
+ queryStore: async (input) => {
639
+ if (!state.storeRuntime) {
640
+ return { facet: input.ref.split(":")[0] as "sql", rows: [], masked: true };
641
+ }
642
+ return queryStore(state.storeRuntime, state.manifest, input);
643
+ },
644
+ editStore: async (input, opts) => {
645
+ if (!state.storeRuntime) {
646
+ throw new Error("Store runtime not bound");
647
+ }
648
+ return editStore(state.storeRuntime, state.manifest, input, {
649
+ production: state.production,
650
+ dryRun: opts?.dryRun,
651
+ });
652
+ },
653
+ deleteStore: async (input) => {
654
+ if (!state.storeRuntime) return { deleted: 0 };
655
+ return deleteStore(state.storeRuntime, input);
656
+ },
657
+ purgeStoreCache: async (resource) => {
658
+ if (!state.storeRuntime) return { keys: [] };
659
+ return purgeStoreCache(state.storeRuntime, resource);
660
+ },
661
+ runStoreSql: async (ref, sqlText, options) => {
662
+ if (!state.storeRuntime) {
663
+ throw new Error("Store runtime not bound");
664
+ }
665
+ return runStoreSql(state.storeRuntime, ref, sqlText, options);
666
+ },
667
+ clockRuntime: options.clockRuntime ?? null,
668
+ listClocks: async () => {
669
+ return projectClocksList({
670
+ manifest: state.manifest,
671
+ runtime: state.clockRuntime,
672
+ journal: state.journalStore,
673
+ now: state.now,
674
+ });
675
+ },
676
+ runCronNow: async (name) => {
677
+ if (!state.clockRuntime) {
678
+ throw new Error("Clock runtime not bound");
679
+ }
680
+ return runCronNow(state.clockRuntime, name);
681
+ },
682
+ pauseCron: async (name) => {
683
+ if (!state.clockRuntime) {
684
+ throw new Error("Clock runtime not bound");
685
+ }
686
+ const row = await pauseCronNow(state.clockRuntime, name);
687
+ return { name: row.name, status: row.status };
688
+ },
689
+ editSchedule: async (input) => {
690
+ if (!state.clockRuntime) {
691
+ throw new Error("Clock runtime not bound");
692
+ }
693
+ const row = await editCronSchedule(state.clockRuntime, input);
694
+ return {
695
+ name: row.name,
696
+ effectiveCron: row.effectiveCron,
697
+ effectiveEvery: row.effectiveEvery,
698
+ };
699
+ },
700
+ wakeEarly: async (runId) => {
701
+ if (!state.journalStore) {
702
+ throw new Error("Journal store not bound");
703
+ }
704
+ const result = await wakeEarlyNow(state.journalStore, runId, {
705
+ now: state.now,
706
+ });
707
+ return {
708
+ runId: result.runId,
709
+ wakeAt: result.wakeAt,
710
+ resumed: result.resumed,
711
+ };
712
+ },
713
+ vaultRuntime: options.vaultRuntime ?? null,
714
+ journalStore: options.journalStore ?? null,
715
+ vaultEnv: options.vaultEnv ?? "dev",
716
+ listVault: async () => {
717
+ return projectVaultList({
718
+ manifest: state.manifest,
719
+ runtime: state.vaultRuntime,
720
+ journal: state.journalStore,
721
+ env: state.vaultEnv,
722
+ now: state.now,
723
+ });
724
+ },
725
+ setVault: async (input) => {
726
+ if (!state.vaultRuntime) {
727
+ throw new Error("Vault runtime not bound");
728
+ }
729
+ return setVaultValue(state.vaultRuntime, input);
730
+ },
731
+ rotateVault: async (input) => {
732
+ if (!state.vaultRuntime) {
733
+ throw new Error("Vault runtime not bound");
734
+ }
735
+ return rotateVaultValue(state.vaultRuntime, input);
736
+ },
737
+ identities: [...(options.identities ?? defaultDevIdentities())],
738
+ production: options.production ?? process.env.NODE_ENV === "production",
739
+ aiRuntime: null,
740
+ evalResults: [],
741
+ listAi: async () => {
742
+ const runs = await state.listRuns();
743
+ return projectAiPanel({
744
+ manifest: state.manifest,
745
+ aiRuntime: state.aiRuntime,
746
+ runs,
747
+ evalResults: state.evalResults,
748
+ });
749
+ },
750
+ listDiff: async () => {
751
+ const runs = await state.listRuns();
752
+ return projectManifestDiff({
753
+ before: state.previousManifest,
754
+ after: state.manifest,
755
+ runs,
756
+ now: state.now(),
757
+ });
758
+ },
759
+ okeConfig: options.okeConfig ?? null,
760
+ pluginRegistry: options.pluginRegistry ?? null,
761
+ listPlugins: async () =>
762
+ projectPluginsList({
763
+ manifest: state.manifest,
764
+ config: state.okeConfig,
765
+ registry: state.pluginRegistry,
766
+ cwd: state.cwd,
767
+ now: state.now,
768
+ fetchNpm: false,
769
+ }),
770
+ channelRuntime: options.channelRuntime ?? null,
771
+ channelInbox: options.channelInbox ?? null,
772
+ channelCatalog: options.channelCatalog ?? {},
773
+ listChannels: async () =>
774
+ projectChannelsList({
775
+ manifest: state.manifest,
776
+ runtime: state.channelRuntime,
777
+ inbox: state.channelInbox,
778
+ production: state.production,
779
+ now: state.now,
780
+ catalog: state.channelCatalog,
781
+ }),
782
+ previewChannel: async (input) =>
783
+ previewChannelTemplate({
784
+ runtime: state.channelRuntime,
785
+ manifest: state.manifest,
786
+ catalog: state.channelCatalog,
787
+ template: input.template,
788
+ locale: input.locale,
789
+ profileLocale: input.profileLocale,
790
+ acceptLanguage: input.acceptLanguage,
791
+ data: input.data,
792
+ }),
793
+ verifyChannelAuth: async (fromOrDomain) =>
794
+ verifyChannelAuth(fromOrDomain),
795
+ revealChannel: async (id) =>
796
+ revealChannelRecipient({
797
+ runtime: state.channelRuntime,
798
+ inbox: state.channelInbox,
799
+ id,
800
+ }),
801
+ sendChannelTest: async (input) => {
802
+ if (!state.channelRuntime) {
803
+ throw new Error("Channel runtime not bound");
804
+ }
805
+ return sendChannelTest(state.channelRuntime, input);
806
+ },
807
+ get setupClosed() {
808
+ return operators.operators.size > 0;
809
+ },
810
+ };
811
+
812
+ return state;
813
+ }
814
+
815
+ /**
816
+ * Bind a live {@link AiRuntime} and wire Manifest effects into agent trails.
817
+ *
818
+ * @param state - Console state
819
+ * @param runtime - AI runtime
820
+ */
821
+ export function bindAiRuntime(state: ConsoleState, runtime: AiRuntime): void {
822
+ state.aiRuntime = runtime;
823
+ }
824
+
825
+ /**
826
+ * Resolve tool-flow effects from the current Manifest (for AiRuntime options).
827
+ *
828
+ * @param state - Console state
829
+ * @param flowName - Tool flow
830
+ */
831
+ export function consoleEffectsForFlow(
832
+ state: ConsoleState,
833
+ flowName: string,
834
+ ): ReturnType<typeof effectsForFlowFromManifest> {
835
+ return effectsForFlowFromManifest(state.manifest, flowName);
836
+ }
837
+
838
+ /**
839
+ * Publish a live message to all WebSocket / channel subscribers.
840
+ *
841
+ * @param state - Console state
842
+ * @param message - Payload
843
+ */
844
+ export function publishLive(
845
+ state: ConsoleState,
846
+ message: ConsoleLiveMessage,
847
+ ): void {
848
+ for (const sub of state.liveSubscribers) {
849
+ try {
850
+ sub(message);
851
+ } catch {
852
+ // Drop broken subscribers.
853
+ }
854
+ }
855
+ }
856
+
857
+ /**
858
+ * Replace the Manifest snapshot and notify live subscribers.
859
+ *
860
+ * @param state - Console state
861
+ * @param manifest - New Manifest
862
+ */
863
+ export function setManifest(state: ConsoleState, manifest: Manifest): void {
864
+ const before = state.manifest;
865
+ if (before) state.previousManifest = before;
866
+ state.manifest = manifest;
867
+ publishLive(state, { type: "manifest", manifest });
868
+ if (before) {
869
+ publishLive(state, { type: "manifest.diff", before, after: manifest });
870
+ }
871
+ }
872
+
873
+ /**
874
+ * Bind a live {@link GateRuntime} from the host app (preferred over Manifest
875
+ * reconstruction).
876
+ *
877
+ * @param state - Console state
878
+ * @param runtime - Gate runtime
879
+ */
880
+ export function bindGateRuntime(
881
+ state: ConsoleState,
882
+ runtime: GateRuntime,
883
+ ): void {
884
+ state.gateRuntime = runtime;
885
+ }
886
+
887
+ /**
888
+ * Open a GateRuntime from the Manifest when no host runtime is attached.
889
+ *
890
+ * @param state - Console state
891
+ */
892
+ export async function bindManifestGateRuntime(
893
+ state: ConsoleState,
894
+ ): Promise<void> {
895
+ if (state.gateRuntime) return;
896
+ if (!state.manifest?.gates && !state.manifest?.flows) return;
897
+ const hasGates =
898
+ Object.keys(state.manifest.gates ?? {}).length > 0 ||
899
+ Object.values(state.manifest.flows ?? {}).some(
900
+ (f) => (f.gates?.length ?? 0) > 0,
901
+ );
902
+ if (!hasGates) return;
903
+ const { runtime } = await createManifestGateRuntime(
904
+ state.manifest,
905
+ state.now,
906
+ );
907
+ state.gateRuntime = runtime;
908
+ }
909
+
910
+ /**
911
+ * Default development identities for the invoke-as picker.
912
+ */
913
+ function defaultDevIdentities(): ConsoleIdentity[] {
914
+ return [
915
+ {
916
+ id: "user_demo",
917
+ email: "demo@example.com",
918
+ name: "Demo User",
919
+ status: "active",
920
+ scopes: ["booking:create", "member"],
921
+ },
922
+ {
923
+ id: "user_member",
924
+ email: "member@example.com",
925
+ name: "Member",
926
+ status: "active",
927
+ scopes: ["member"],
928
+ },
929
+ ];
930
+ }
931
+
932
+ function accessCatalog(state: ConsoleState): string[] {
933
+ if (state.manifest) return deriveModuleActions(state.manifest);
934
+ const set = new Set<string>();
935
+ for (const grants of state.roles.grants.values()) {
936
+ for (const g of grants) set.add(g);
937
+ }
938
+ for (const key of state.apiKeys.keys.values()) {
939
+ for (const s of key.scopes) set.add(s);
940
+ }
941
+ return [...set];
942
+ }
943
+
944
+ /**
945
+ * Seed hygiene demos that do not close the setup wizard (no operators).
946
+ * Never-signed-in operators appear once real invites land with lastSeenAt null.
947
+ */
948
+ function seedAccessDemoData(
949
+ apiKeys: ApiKeyStore,
950
+ invites: OperatorInviteStore,
951
+ now: () => number,
952
+ ): void {
953
+ const t = now();
954
+ const staleCreated = t - 100 * 24 * 60 * 60 * 1000;
955
+ if (!apiKeys.keys.has("key_stale")) {
956
+ apiKeys.keys.set("key_stale", {
957
+ id: "key_stale",
958
+ plane: "user",
959
+ hash: "stale",
960
+ name: "Stale unused key",
961
+ scopes: ["member"],
962
+ expiresAt: null,
963
+ rateLimit: null,
964
+ ipAllowlist: [],
965
+ creatorId: "user_demo",
966
+ creatorScopes: ["member"],
967
+ createdAt: staleCreated,
968
+ lastUsedAt: null,
969
+ revokedAt: null,
970
+ });
971
+ }
972
+ if (!invites.invites.has("invite_expired")) {
973
+ invites.invites.set("invite_expired", {
974
+ id: "invite_expired",
975
+ email: "expired@example.com",
976
+ invitedBy: "seed",
977
+ createdAt: t - 14 * 24 * 60 * 60 * 1000,
978
+ expiresAt: t - 24 * 60 * 60 * 1000,
979
+ acceptedAt: null,
980
+ });
981
+ }
982
+ }