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,418 @@
1
+ /**
2
+ * Hybrid sessions — short JWT access + revocable refresh.
3
+ *
4
+ * Refresh tokens rotate on every use. Presenting a previously-used refresh
5
+ * token is reuse detection: the entire token family is revoked.
6
+ *
7
+ * @see docs/spec/unified-theory.md §13 · console.md §9.14
8
+ */
9
+
10
+ import type { AuthPlane } from "./planes.ts";
11
+ import type { RefreshTokenRow, SessionRow } from "./tables.ts";
12
+
13
+ /** Default access-token TTL (14 minutes — residual validity after revoke). */
14
+ export const ACCESS_TTL_MS = 14 * 60 * 1000;
15
+
16
+ /** Default refresh-token TTL (30 days). */
17
+ export const REFRESH_TTL_MS = 30 * 24 * 60 * 60 * 1000;
18
+
19
+ /** Session store. */
20
+ export interface SessionStore {
21
+ sessions: Map<string, SessionRow>;
22
+ refresh: Map<string, RefreshTokenRow>;
23
+ }
24
+
25
+ /** Issued session bundle. */
26
+ export interface IssuedSession {
27
+ readonly session: SessionRow;
28
+ readonly accessToken: string;
29
+ readonly refreshToken: string;
30
+ readonly accessExpiresAt: number;
31
+ }
32
+
33
+ /** Access-token claims (unsigned JSON for the builtin path; HMAC below). */
34
+ export interface AccessClaims {
35
+ readonly sub: string;
36
+ readonly plane: AuthPlane;
37
+ readonly sid: string;
38
+ readonly scopes: string[];
39
+ readonly iat: number;
40
+ readonly exp: number;
41
+ /**
42
+ * Intended audience (`oke-console` · `oke-mcp` · `oke-app`).
43
+ * Validated when the verifier supplies {@link VerifyAccessOptions.audience}.
44
+ */
45
+ readonly aud?: string;
46
+ }
47
+
48
+ /** Options for {@link createSessionStore}. */
49
+ export interface SessionCrypto {
50
+ /** HMAC secret for access tokens. */
51
+ readonly secret: string;
52
+ readonly now?: () => number;
53
+ readonly accessTtlMs?: number;
54
+ readonly refreshTtlMs?: number;
55
+ /**
56
+ * Audience stamped on issued access tokens.
57
+ * MCP tokens must use `"oke-mcp"` (console §10.3 — never accept another aud).
58
+ */
59
+ readonly audience?: string;
60
+ }
61
+
62
+ /** Options for {@link verifyAccess}. */
63
+ export interface VerifyAccessOptions {
64
+ /** Clock (defaults to `Date.now`). */
65
+ readonly now?: () => number;
66
+ /**
67
+ * When set, the token's `aud` must match exactly.
68
+ * Tokens minted for another audience (or missing `aud`) are rejected.
69
+ */
70
+ readonly audience?: string;
71
+ }
72
+
73
+ /**
74
+ * Create an empty session store.
75
+ */
76
+ export function createSessionStore(): SessionStore {
77
+ return { sessions: new Map(), refresh: new Map() };
78
+ }
79
+
80
+ /**
81
+ * Issue a hybrid session for a principal.
82
+ *
83
+ * @param store - Session store
84
+ * @param crypto - Signing + TTLs
85
+ * @param principal - Subject
86
+ */
87
+ export async function issueSession(
88
+ store: SessionStore,
89
+ crypto: SessionCrypto,
90
+ principal: {
91
+ readonly id: string;
92
+ readonly plane: AuthPlane;
93
+ readonly scopes: Iterable<string>;
94
+ },
95
+ ): Promise<IssuedSession> {
96
+ const now = crypto.now ?? (() => Date.now());
97
+ const t = now();
98
+ const accessTtl = crypto.accessTtlMs ?? ACCESS_TTL_MS;
99
+ const refreshTtl = crypto.refreshTtlMs ?? REFRESH_TTL_MS;
100
+ const sessionId = cryptoRandomId();
101
+ const familyId = cryptoRandomId();
102
+
103
+ const session: SessionRow = {
104
+ id: sessionId,
105
+ plane: principal.plane,
106
+ principalId: principal.id,
107
+ familyId,
108
+ revokedAt: null,
109
+ createdAt: t,
110
+ expiresAt: t + refreshTtl,
111
+ };
112
+ store.sessions.set(sessionId, session);
113
+ if (crypto.audience !== undefined) {
114
+ sessionAudiences.set(sessionId, crypto.audience);
115
+ }
116
+
117
+ const refreshRaw = `rt_${cryptoRandomId()}`;
118
+ const refreshRow: RefreshTokenRow = {
119
+ id: cryptoRandomId(),
120
+ sessionId,
121
+ familyId,
122
+ hash: await hashToken(refreshRaw),
123
+ expiresAt: t + refreshTtl,
124
+ usedAt: null,
125
+ revokedAt: null,
126
+ };
127
+ store.refresh.set(refreshRow.id, refreshRow);
128
+
129
+ const accessExpiresAt = t + accessTtl;
130
+ const accessToken = await signAccess(crypto.secret, {
131
+ sub: principal.id,
132
+ plane: principal.plane,
133
+ sid: sessionId,
134
+ scopes: [...principal.scopes],
135
+ iat: t,
136
+ exp: accessExpiresAt,
137
+ ...(crypto.audience !== undefined ? { aud: crypto.audience } : {}),
138
+ });
139
+
140
+ return { session, accessToken, refreshToken: refreshRaw, accessExpiresAt };
141
+ }
142
+
143
+ /**
144
+ * Rotate a refresh token. Reuse of an already-used token revokes the family.
145
+ *
146
+ * @param store - Session store
147
+ * @param crypto - Signing + TTLs
148
+ * @param refreshToken - Raw refresh token
149
+ */
150
+ export async function rotateRefresh(
151
+ store: SessionStore,
152
+ crypto: SessionCrypto,
153
+ refreshToken: string,
154
+ ): Promise<IssuedSession> {
155
+ const now = crypto.now ?? (() => Date.now());
156
+ const t = now();
157
+ const hash = await hashToken(refreshToken);
158
+ const existing = [...store.refresh.values()].find((r) => r.hash === hash);
159
+
160
+ if (!existing) {
161
+ throw new SessionError("unknown refresh token");
162
+ }
163
+
164
+ // Reuse detection: token already consumed → revoke family.
165
+ if (existing.usedAt !== null || existing.revokedAt !== null) {
166
+ revokeFamily(store, existing.familyId, t);
167
+ throw new SessionError("refresh token reuse detected; family revoked");
168
+ }
169
+
170
+ const session = store.sessions.get(existing.sessionId);
171
+ if (!session || session.revokedAt !== null) {
172
+ throw new SessionError("session revoked");
173
+ }
174
+ if (existing.expiresAt <= t || session.expiresAt <= t) {
175
+ throw new SessionError("refresh token expired");
176
+ }
177
+
178
+ existing.usedAt = t;
179
+ existing.revokedAt = t;
180
+
181
+ const accessTtl = crypto.accessTtlMs ?? ACCESS_TTL_MS;
182
+ const refreshTtl = crypto.refreshTtlMs ?? REFRESH_TTL_MS;
183
+
184
+ const newRefreshRaw = `rt_${cryptoRandomId()}`;
185
+ const newRefresh: RefreshTokenRow = {
186
+ id: cryptoRandomId(),
187
+ sessionId: session.id,
188
+ familyId: existing.familyId,
189
+ hash: await hashToken(newRefreshRaw),
190
+ expiresAt: t + refreshTtl,
191
+ usedAt: null,
192
+ revokedAt: null,
193
+ };
194
+ store.refresh.set(newRefresh.id, newRefresh);
195
+
196
+ // Recover scopes from the previous access path — stored on session via
197
+ // a side map would be ideal; for builtin we re-sign with empty and let
198
+ // callers pass scopes through verify. We keep scopes on a claim cache:
199
+ const priorScopes = sessionScopes.get(session.id) ?? [];
200
+ const priorAud = sessionAudiences.get(session.id);
201
+ const accessExpiresAt = t + accessTtl;
202
+ const accessToken = await signAccess(crypto.secret, {
203
+ sub: session.principalId,
204
+ plane: session.plane,
205
+ sid: session.id,
206
+ scopes: priorScopes,
207
+ iat: t,
208
+ exp: accessExpiresAt,
209
+ ...(priorAud !== undefined ? { aud: priorAud } : {}),
210
+ });
211
+
212
+ return {
213
+ session,
214
+ accessToken,
215
+ refreshToken: newRefreshRaw,
216
+ accessExpiresAt,
217
+ };
218
+ }
219
+
220
+ /** Session id → scopes (access-token material). */
221
+ const sessionScopes = new Map<string, string[]>();
222
+
223
+ /** Session id → audience stamped at issue time. */
224
+ const sessionAudiences = new Map<string, string>();
225
+
226
+ /**
227
+ * Remember scopes for refresh rotation (call after {@link issueSession}).
228
+ *
229
+ * @param sessionId - Session id
230
+ * @param scopes - Scopes
231
+ */
232
+ export function bindSessionScopes(
233
+ sessionId: string,
234
+ scopes: Iterable<string>,
235
+ ): void {
236
+ sessionScopes.set(sessionId, [...scopes]);
237
+ }
238
+
239
+ /**
240
+ * Remember audience for refresh rotation (call after {@link issueSession}).
241
+ *
242
+ * @param sessionId - Session id
243
+ * @param audience - Audience claim
244
+ */
245
+ export function bindSessionAudience(
246
+ sessionId: string,
247
+ audience: string,
248
+ ): void {
249
+ sessionAudiences.set(sessionId, audience);
250
+ }
251
+
252
+ /**
253
+ * Issue a session and bind scopes for later rotation.
254
+ *
255
+ * @param store - Session store
256
+ * @param crypto - Crypto
257
+ * @param principal - Subject + scopes
258
+ */
259
+ export async function issueSessionWithScopes(
260
+ store: SessionStore,
261
+ crypto: SessionCrypto,
262
+ principal: {
263
+ readonly id: string;
264
+ readonly plane: AuthPlane;
265
+ readonly scopes: Iterable<string>;
266
+ },
267
+ ): Promise<IssuedSession> {
268
+ const issued = await issueSession(store, crypto, principal);
269
+ bindSessionScopes(issued.session.id, principal.scopes);
270
+ if (crypto.audience !== undefined) {
271
+ bindSessionAudience(issued.session.id, crypto.audience);
272
+ }
273
+ return issued;
274
+ }
275
+
276
+ /**
277
+ * Verify an access token; rejects revoked sessions and wrong audiences.
278
+ *
279
+ * The third argument may be a clock function (legacy) or
280
+ * {@link VerifyAccessOptions}. Prefer the options form when validating
281
+ * audience (console §10.3 — never accept a token minted for another surface).
282
+ *
283
+ * @param store - Session store
284
+ * @param secret - HMAC secret
285
+ * @param token - Access token
286
+ * @param nowOrOptions - Clock, or options including expected audience
287
+ */
288
+ export async function verifyAccess(
289
+ store: SessionStore,
290
+ secret: string,
291
+ token: string,
292
+ nowOrOptions: (() => number) | VerifyAccessOptions = () => Date.now(),
293
+ ): Promise<AccessClaims> {
294
+ const options: VerifyAccessOptions =
295
+ typeof nowOrOptions === "function"
296
+ ? { now: nowOrOptions }
297
+ : nowOrOptions;
298
+ const now = options.now ?? (() => Date.now());
299
+ const claims = await verifyAccessSignature(secret, token);
300
+ if (claims.exp <= now()) {
301
+ throw new SessionError("access token expired");
302
+ }
303
+ if (options.audience !== undefined) {
304
+ if (claims.aud !== options.audience) {
305
+ throw new SessionError(
306
+ `access token audience mismatch: expected ${options.audience}`,
307
+ );
308
+ }
309
+ }
310
+ const session = store.sessions.get(claims.sid);
311
+ if (!session || session.revokedAt !== null) {
312
+ throw new SessionError("session revoked");
313
+ }
314
+ // Per-request: session must still belong to the token subject.
315
+ if (session.principalId !== claims.sub) {
316
+ throw new SessionError("session does not belong to requester");
317
+ }
318
+ return claims;
319
+ }
320
+
321
+ /**
322
+ * Revoke an entire refresh-token family (reuse detection / logout).
323
+ *
324
+ * @param store - Session store
325
+ * @param familyId - Family id
326
+ * @param at - Timestamp
327
+ */
328
+ export function revokeFamily(
329
+ store: SessionStore,
330
+ familyId: string,
331
+ at: number = Date.now(),
332
+ ): void {
333
+ for (const session of store.sessions.values()) {
334
+ if (session.familyId === familyId) session.revokedAt = at;
335
+ }
336
+ for (const token of store.refresh.values()) {
337
+ if (token.familyId === familyId) token.revokedAt = at;
338
+ }
339
+ }
340
+
341
+ /** Session / token error. */
342
+ export class SessionError extends Error {
343
+ /** @param message - Diagnostic */
344
+ constructor(message: string) {
345
+ super(message);
346
+ this.name = "SessionError";
347
+ }
348
+ }
349
+
350
+ async function hashToken(raw: string): Promise<string> {
351
+ const digest = await crypto.subtle.digest(
352
+ "SHA-256",
353
+ new TextEncoder().encode(raw),
354
+ );
355
+ return [...new Uint8Array(digest)]
356
+ .map((b) => b.toString(16).padStart(2, "0"))
357
+ .join("");
358
+ }
359
+
360
+ function cryptoRandomId(): string {
361
+ return crypto.randomUUID().replace(/-/g, "");
362
+ }
363
+
364
+ async function signAccess(
365
+ secret: string,
366
+ claims: AccessClaims,
367
+ ): Promise<string> {
368
+ const header = b64url(JSON.stringify({ alg: "HS256", typ: "JWT" }));
369
+ const payload = b64url(JSON.stringify(claims));
370
+ const data = `${header}.${payload}`;
371
+ const sig = await hmac(secret, data);
372
+ return `${data}.${sig}`;
373
+ }
374
+
375
+ async function verifyAccessSignature(
376
+ secret: string,
377
+ token: string,
378
+ ): Promise<AccessClaims> {
379
+ const parts = token.split(".");
380
+ if (parts.length !== 3) throw new SessionError("malformed access token");
381
+ const [header, payload, sig] = parts as [string, string, string];
382
+ const data = `${header}.${payload}`;
383
+ const expected = await hmac(secret, data);
384
+ if (sig !== expected) throw new SessionError("invalid access token signature");
385
+ return JSON.parse(b64urlDecode(payload)) as AccessClaims;
386
+ }
387
+
388
+ async function hmac(secret: string, data: string): Promise<string> {
389
+ const key = await crypto.subtle.importKey(
390
+ "raw",
391
+ new TextEncoder().encode(secret),
392
+ { name: "HMAC", hash: "SHA-256" },
393
+ false,
394
+ ["sign"],
395
+ );
396
+ const sig = await crypto.subtle.sign(
397
+ "HMAC",
398
+ key,
399
+ new TextEncoder().encode(data),
400
+ );
401
+ return b64urlBytes(new Uint8Array(sig));
402
+ }
403
+
404
+ function b64url(s: string): string {
405
+ return b64urlBytes(new TextEncoder().encode(s));
406
+ }
407
+
408
+ function b64urlBytes(bytes: Uint8Array): string {
409
+ let bin = "";
410
+ for (const b of bytes) bin += String.fromCharCode(b);
411
+ return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
412
+ }
413
+
414
+ function b64urlDecode(s: string): string {
415
+ const padded = s.replace(/-/g, "+").replace(/_/g, "/");
416
+ const pad = padded.length % 4 === 0 ? "" : "=".repeat(4 - (padded.length % 4));
417
+ return atob(padded + pad);
418
+ }
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Auth Store tables — `oke_` prefix, planes never joined.
3
+ *
4
+ * @see docs/spec/console.md §8
5
+ */
6
+
7
+ /** Auth / Console table names. */
8
+ export const AUTH_TABLES = {
9
+ // Operator plane — never joined to the user plane
10
+ operators: "oke_operators",
11
+ operatorCredentials: "oke_operator_credentials",
12
+ operatorSsoLinks: "oke_operator_sso_links",
13
+ operatorRoles: "oke_operator_roles",
14
+ operatorInvites: "oke_operator_invites",
15
+ // User plane
16
+ identities: "oke_identities",
17
+ credentials: "oke_credentials",
18
+ identityRoles: "oke_identity_roles",
19
+ // Shared grammar, separate grants
20
+ roles: "oke_roles",
21
+ roleGrants: "oke_role_grants",
22
+ apiKeys: "oke_api_keys",
23
+ // Session tables (auth element owns these)
24
+ sessions: "oke_sessions",
25
+ refreshTokens: "oke_refresh_tokens",
26
+ } as const;
27
+
28
+ /** Plane column values stored on shared tables. */
29
+ export type TablePlane = "user" | "operator";
30
+
31
+ /** Row shapes (in-memory / descriptor — not ORM-bound). */
32
+ export interface OperatorRow {
33
+ id: string;
34
+ email: string;
35
+ name: string;
36
+ status: "active" | "suspended" | "invited";
37
+ mfaEnabled: boolean;
38
+ invitedBy: string | null;
39
+ lastSeenAt: number | null;
40
+ }
41
+
42
+ /** Local password hash — always present for operators, never removable. */
43
+ export interface OperatorCredentialRow {
44
+ operatorId: string;
45
+ passwordHash: string;
46
+ /** Local login may be disabled after SSO-primary, but the row remains. */
47
+ loginEnabled: boolean;
48
+ }
49
+
50
+ /** Optional linked SSO identity (additional method only). */
51
+ export interface OperatorSsoLinkRow {
52
+ operatorId: string;
53
+ provider: string;
54
+ subject: string;
55
+ }
56
+
57
+ /** User-plane identity. */
58
+ export interface IdentityRow {
59
+ id: string;
60
+ provider: string;
61
+ subject: string;
62
+ email: string;
63
+ name: string;
64
+ status: "active" | "suspended";
65
+ lastSeenAt: number | null;
66
+ }
67
+
68
+ /** Role (data, not code). */
69
+ export interface RoleRow {
70
+ id: string;
71
+ name: string;
72
+ plane: TablePlane;
73
+ description: string;
74
+ }
75
+
76
+ /** Role → Module:Action grant. */
77
+ export interface RoleGrantRow {
78
+ roleId: string;
79
+ action: string;
80
+ }
81
+
82
+ /** API key principal. */
83
+ export interface ApiKeyRow {
84
+ id: string;
85
+ plane: TablePlane;
86
+ hash: string;
87
+ name: string;
88
+ scopes: string[];
89
+ expiresAt: number | null;
90
+ rateLimit: { max: number; per: string } | null;
91
+ ipAllowlist: string[];
92
+ creatorId: string;
93
+ creatorScopes: string[];
94
+ /** Epoch-ms when the key was created (hygiene: unused 90d+). */
95
+ createdAt: number;
96
+ lastUsedAt: number | null;
97
+ /** Epoch-ms when revoked; `null` while active. */
98
+ revokedAt: number | null;
99
+ }
100
+
101
+ /** Pending operator invitation (invite-only plane). */
102
+ export interface OperatorInviteRow {
103
+ id: string;
104
+ email: string;
105
+ invitedBy: string;
106
+ createdAt: number;
107
+ expiresAt: number;
108
+ acceptedAt: number | null;
109
+ }
110
+
111
+ /** Hybrid session (short JWT + revocable refresh). */
112
+ export interface SessionRow {
113
+ id: string;
114
+ plane: TablePlane;
115
+ principalId: string;
116
+ familyId: string;
117
+ revokedAt: number | null;
118
+ createdAt: number;
119
+ expiresAt: number;
120
+ }
121
+
122
+ /** Refresh token (hashed at rest); rotation with reuse detection. */
123
+ export interface RefreshTokenRow {
124
+ id: string;
125
+ sessionId: string;
126
+ familyId: string;
127
+ hash: string;
128
+ expiresAt: number;
129
+ usedAt: number | null;
130
+ revokedAt: number | null;
131
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Tiny argv helpers shared by `oke` subcommands.
3
+ */
4
+
5
+ /**
6
+ * True when `--json` / `-j` is present.
7
+ *
8
+ * @param args - Argv slice
9
+ */
10
+ export function wantsJson(args: readonly string[]): boolean {
11
+ return args.includes("--json") || args.includes("-j");
12
+ }
13
+
14
+ /**
15
+ * Read a flag value for long and optional short forms.
16
+ *
17
+ * @param args - Argv slice
18
+ * @param long - Long flag (e.g. `--config`)
19
+ * @param short - Optional short flag (e.g. `-c`)
20
+ */
21
+ export function flagValue(
22
+ args: readonly string[],
23
+ long: string,
24
+ short?: string,
25
+ ): string | undefined {
26
+ for (let i = 0; i < args.length; i++) {
27
+ const a = args[i]!;
28
+ if (a === long || (short !== undefined && a === short)) {
29
+ return args[i + 1];
30
+ }
31
+ if (a.startsWith(`${long}=`)) return a.slice(long.length + 1);
32
+ if (short && a.startsWith(`${short}=`)) return a.slice(short.length + 1);
33
+ }
34
+ return undefined;
35
+ }
36
+
37
+ /**
38
+ * True when a boolean flag (long or short) is present.
39
+ *
40
+ * @param args - Argv slice
41
+ * @param long - Long flag
42
+ * @param short - Optional short flag
43
+ */
44
+ export function hasFlag(
45
+ args: readonly string[],
46
+ long: string,
47
+ short?: string,
48
+ ): boolean {
49
+ return args.includes(long) || (short !== undefined && args.includes(short));
50
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * `oke branch <name> --at <when>` — fork journaled state into a sandbox.
3
+ */
4
+
5
+ /** Options for {@link runBranch}. */
6
+ export interface BranchOptions {
7
+ readonly name: string;
8
+ readonly at?: string;
9
+ readonly cwd?: string;
10
+ readonly write?: (text: string) => void;
11
+ /**
12
+ * Fork hook (tests / wired journal).
13
+ *
14
+ * @param name - Branch name
15
+ * @param at - Time expression
16
+ */
17
+ readonly fork?: (name: string, at: string | undefined) => Promise<string>;
18
+ }
19
+
20
+ /**
21
+ * Fork journaled state into a named sandbox branch.
22
+ *
23
+ * @param options - Name / time
24
+ */
25
+ export async function runBranch(options: BranchOptions): Promise<number> {
26
+ const write = options.write ?? ((t) => process.stdout.write(t));
27
+ if (!options.name) {
28
+ console.error("Usage: oke branch <name> --at <when>");
29
+ return 1;
30
+ }
31
+ const fork =
32
+ options.fork ??
33
+ (async (name, at) => {
34
+ const dir = `${options.cwd ?? process.cwd()}/.oke/branches/${name}`;
35
+ await Bun.write(
36
+ `${dir}/meta.json`,
37
+ `${JSON.stringify({ name, at: at ?? "now", createdAt: new Date().toISOString() }, null, 2)}\n`,
38
+ );
39
+ return dir;
40
+ });
41
+ try {
42
+ const path = await fork(options.name, options.at);
43
+ write(`oke branch: ${options.name} at ${options.at ?? "now"} → ${path}\n`);
44
+ return 0;
45
+ } catch (err) {
46
+ console.error(err instanceof Error ? err.message : String(err));
47
+ return 1;
48
+ }
49
+ }
50
+
51
+ /**
52
+ * CLI entry for `oke branch`.
53
+ *
54
+ * @param args - Args after `branch`
55
+ */
56
+ export async function branchCli(args: readonly string[]): Promise<number> {
57
+ let name: string | undefined;
58
+ let at: string | undefined;
59
+ for (let i = 0; i < args.length; i++) {
60
+ const a = args[i]!;
61
+ if (a === "--at" || a === "-a") at = args[++i];
62
+ else if (a === "--help" || a === "-h") {
63
+ console.log(`oke branch <name> --at|-a "yesterday"
64
+
65
+ Fork journaled state into a sandbox for replay / time-travel.
66
+ `);
67
+ return 0;
68
+ } else if (!a.startsWith("-") && !name) name = a;
69
+ }
70
+ if (!name) {
71
+ console.error("Usage: oke branch <name> --at <when>");
72
+ return 1;
73
+ }
74
+ return runBranch({ name, at });
75
+ }