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,556 @@
1
+ /**
2
+ * HTTP router — compiled RegExp matching with a Trie fallback
3
+ * (Hono's SmartRouter idea), plus a linear preset for cold-start edge builds.
4
+ *
5
+ * Chosen at build/startup: try RegExp first; on unsupported patterns fall
6
+ * back to Trie. The `edge` preset uses LinearRouter for fast registration.
7
+ */
8
+
9
+ /** Thrown when a router cannot express a path pattern. */
10
+ export class UnsupportedPathError extends Error {
11
+ /** Offending path pattern. */
12
+ readonly path: string;
13
+
14
+ /**
15
+ * @param path - Offending path pattern
16
+ */
17
+ constructor(path: string) {
18
+ super(`Unsupported path pattern: ${path}`);
19
+ this.name = "UnsupportedPathError";
20
+ this.path = path;
21
+ }
22
+ }
23
+
24
+ /** One match result. */
25
+ export interface RouteMatch<T> {
26
+ readonly value: T;
27
+ readonly params: Readonly<Record<string, string>>;
28
+ }
29
+
30
+ /** Router surface shared by all strategies. */
31
+ export interface Router<T> {
32
+ readonly name: string;
33
+ /**
34
+ * Register a route.
35
+ *
36
+ * @param method - HTTP method (uppercase)
37
+ * @param path - Path pattern
38
+ * @param value - Payload (usually a flow binding)
39
+ */
40
+ add(method: string, path: string, value: T): void;
41
+ /**
42
+ * Match a method + pathname.
43
+ *
44
+ * @param method - HTTP method
45
+ * @param path - Request pathname
46
+ */
47
+ match(method: string, path: string): RouteMatch<T> | undefined;
48
+ }
49
+
50
+ /** True when the pattern cannot be expressed by the RegExp strategy. */
51
+ export function isUnsupportedByRegExp(path: string): boolean {
52
+ // optional params, wildcards, custom regex segments, greedy rests
53
+ return /\/:/.test(path) === false
54
+ ? /[*?{}()]/.test(path)
55
+ : /[*?{}]|\/:[^/]+\?/.test(path);
56
+ }
57
+
58
+ function escapeRegex(segment: string): string {
59
+ return segment.replace(/[.^$+{}()|[\]\\]/g, "\\$&");
60
+ }
61
+
62
+ interface CompiledDynamic<T> {
63
+ readonly regex: RegExp;
64
+ /** Per-alternative: which capture index holds the wrapper, param names. */
65
+ readonly alts: readonly {
66
+ readonly wrapGroup: number;
67
+ readonly keys: readonly string[];
68
+ readonly value: T;
69
+ }[];
70
+ }
71
+
72
+ interface MethodTable<T> {
73
+ readonly staticMap: Map<string, T>;
74
+ /**
75
+ * Dynamic routes bucketed by the first path segment (or `""` when the
76
+ * first segment is a param). Each bucket compiles to one RegExp.
77
+ */
78
+ buckets: Map<string, CompiledDynamic<T>> | undefined;
79
+ readonly dynamicRoutes: { path: string; value: T }[];
80
+ }
81
+
82
+ function emptyTable<T>(): MethodTable<T> {
83
+ return { staticMap: new Map(), buckets: undefined, dynamicRoutes: [] };
84
+ }
85
+
86
+ /** First segment key used for dynamic bucketing (`""` if param/empty). */
87
+ function bucketKey(path: string): string {
88
+ const parts = path.startsWith("/")
89
+ ? path.split("/").slice(1)
90
+ : path.split("/");
91
+ const first = parts[0] ?? "";
92
+ if (first.startsWith(":") || first === "*" || first === "") return "";
93
+ return first;
94
+ }
95
+
96
+ function compileDynamic<T>(
97
+ routes: readonly { path: string; value: T }[],
98
+ ): CompiledDynamic<T> {
99
+ const alts: CompiledDynamic<T>["alts"][number][] = [];
100
+ const parts: string[] = [];
101
+ let group = 1;
102
+
103
+ for (const route of routes) {
104
+ if (isUnsupportedByRegExp(route.path)) {
105
+ throw new UnsupportedPathError(route.path);
106
+ }
107
+ const keys: string[] = [];
108
+ const segments = route.path.split("/");
109
+ const body = segments
110
+ .map((seg) => {
111
+ if (seg.startsWith(":") && seg.length > 1) {
112
+ keys.push(seg.slice(1));
113
+ return "([^/]+)";
114
+ }
115
+ return escapeRegex(seg);
116
+ })
117
+ .join("/");
118
+
119
+ parts.push(`(${body})`);
120
+ alts.push({ wrapGroup: group, keys, value: route.value });
121
+ group += 1 + keys.length;
122
+ }
123
+
124
+ const regex =
125
+ parts.length === 0
126
+ ? /(?!)/
127
+ : new RegExp(`^(?:${parts.join("|")})$`);
128
+
129
+ return { regex, alts };
130
+ }
131
+
132
+ function matchCompiled<T>(
133
+ dyn: CompiledDynamic<T>,
134
+ path: string,
135
+ ): RouteMatch<T> | undefined {
136
+ const m = dyn.regex.exec(path);
137
+ if (!m) return undefined;
138
+
139
+ for (const alt of dyn.alts) {
140
+ if (m[alt.wrapGroup] === undefined) continue;
141
+ const params: Record<string, string> = {};
142
+ for (let i = 0; i < alt.keys.length; i++) {
143
+ const key = alt.keys[i];
144
+ const captured = m[alt.wrapGroup + 1 + i];
145
+ if (key !== undefined && captured !== undefined) {
146
+ params[key] = captured;
147
+ }
148
+ }
149
+ return { value: alt.value, params };
150
+ }
151
+ return undefined;
152
+ }
153
+
154
+ /**
155
+ * Compiled RegExp router — O(1) static map, plus per-bucket compiled
156
+ * regular expressions for parametric routes (Hono RegExpRouter idea).
157
+ */
158
+ export class RegExpRouter<T> implements Router<T> {
159
+ readonly name = "RegExpRouter";
160
+ readonly #tables = new Map<string, MethodTable<T>>();
161
+ #built = false;
162
+
163
+ /**
164
+ * @param method - HTTP method
165
+ * @param path - Path pattern
166
+ * @param value - Route value
167
+ */
168
+ add(method: string, path: string, value: T): void {
169
+ if (this.#built) {
170
+ throw new Error("RegExpRouter matcher is already built");
171
+ }
172
+ if (isUnsupportedByRegExp(path)) {
173
+ throw new UnsupportedPathError(path);
174
+ }
175
+ let table = this.#tables.get(method);
176
+ if (!table) {
177
+ table = emptyTable();
178
+ this.#tables.set(method, table);
179
+ }
180
+ if (!path.includes("/:")) {
181
+ table.staticMap.set(path, value);
182
+ return;
183
+ }
184
+ table.dynamicRoutes.push({ path, value });
185
+ }
186
+
187
+ /**
188
+ * Compile dynamic routes. Idempotent.
189
+ */
190
+ build(): void {
191
+ if (this.#built) return;
192
+ for (const table of this.#tables.values()) {
193
+ if (table.dynamicRoutes.length === 0) continue;
194
+ const grouped = new Map<string, { path: string; value: T }[]>();
195
+ for (const route of table.dynamicRoutes) {
196
+ const key = bucketKey(route.path);
197
+ let list = grouped.get(key);
198
+ if (!list) {
199
+ list = [];
200
+ grouped.set(key, list);
201
+ }
202
+ list.push(route);
203
+ }
204
+ const buckets = new Map<string, CompiledDynamic<T>>();
205
+ for (const [key, routes] of grouped) {
206
+ buckets.set(key, compileDynamic(routes));
207
+ }
208
+ table.buckets = buckets;
209
+ }
210
+ this.#built = true;
211
+ }
212
+
213
+ /**
214
+ * @param method - HTTP method
215
+ * @param path - Pathname
216
+ */
217
+ match(method: string, path: string): RouteMatch<T> | undefined {
218
+ this.build();
219
+ const table = this.#tables.get(method);
220
+ if (!table) return undefined;
221
+
222
+ const staticHit = table.staticMap.get(path);
223
+ if (staticHit !== undefined) {
224
+ return { value: staticHit, params: {} };
225
+ }
226
+
227
+ const buckets = table.buckets;
228
+ if (!buckets) return undefined;
229
+
230
+ const key = bucketKey(path);
231
+ const primary = buckets.get(key);
232
+ if (primary) {
233
+ const hit = matchCompiled(primary, path);
234
+ if (hit) return hit;
235
+ }
236
+ // Routes whose first segment is a param live in the `""` bucket.
237
+ if (key !== "") {
238
+ const catchAll = buckets.get("");
239
+ if (catchAll) return matchCompiled(catchAll, path);
240
+ }
241
+ return undefined;
242
+ }
243
+ }
244
+
245
+ interface TrieNode<T> {
246
+ staticChildren: Map<string, TrieNode<T>>;
247
+ paramChild?: { name: string; node: TrieNode<T> };
248
+ wildcardChild?: TrieNode<T>;
249
+ value?: T;
250
+ }
251
+
252
+ function newTrieNode<T>(): TrieNode<T> {
253
+ return { staticChildren: new Map() };
254
+ }
255
+
256
+ /**
257
+ * Trie router — supports wildcards and optional-style rests the RegExp
258
+ * path cannot express. Used as SmartRouter fallback.
259
+ */
260
+ export class TrieRouter<T> implements Router<T> {
261
+ readonly name = "TrieRouter";
262
+ readonly #roots = new Map<string, TrieNode<T>>();
263
+
264
+ /**
265
+ * @param method - HTTP method
266
+ * @param path - Path pattern
267
+ * @param value - Route value
268
+ */
269
+ add(method: string, path: string, value: T): void {
270
+ let root = this.#roots.get(method);
271
+ if (!root) {
272
+ root = newTrieNode();
273
+ this.#roots.set(method, root);
274
+ }
275
+ const parts = path.startsWith("/")
276
+ ? path.split("/").slice(1)
277
+ : path.split("/");
278
+
279
+ let node = root;
280
+ for (const seg of parts) {
281
+ if (seg === "*") {
282
+ node.wildcardChild ??= newTrieNode();
283
+ node = node.wildcardChild;
284
+ continue;
285
+ }
286
+ if (seg.startsWith(":") && seg.length > 1) {
287
+ const name = seg.endsWith("?") ? seg.slice(1, -1) : seg.slice(1);
288
+ node.paramChild ??= { name, node: newTrieNode() };
289
+ node = node.paramChild.node;
290
+ continue;
291
+ }
292
+ let next = node.staticChildren.get(seg);
293
+ if (!next) {
294
+ next = newTrieNode();
295
+ node.staticChildren.set(seg, next);
296
+ }
297
+ node = next;
298
+ }
299
+ node.value = value;
300
+ }
301
+
302
+ /**
303
+ * @param method - HTTP method
304
+ * @param path - Pathname
305
+ */
306
+ match(method: string, path: string): RouteMatch<T> | undefined {
307
+ const root = this.#roots.get(method);
308
+ if (!root) return undefined;
309
+ const parts = path.startsWith("/")
310
+ ? path.split("/").slice(1)
311
+ : path.split("/");
312
+ // trailing slash: empty last segment
313
+ if (parts.length > 0 && parts[parts.length - 1] === "") {
314
+ parts.pop();
315
+ }
316
+ const params: Record<string, string> = {};
317
+ const found = this.#walk(root, parts, 0, params);
318
+ if (found === undefined) return undefined;
319
+ return { value: found, params };
320
+ }
321
+
322
+ #walk(
323
+ node: TrieNode<T>,
324
+ parts: readonly string[],
325
+ index: number,
326
+ params: Record<string, string>,
327
+ ): T | undefined {
328
+ if (index === parts.length) {
329
+ return node.value;
330
+ }
331
+ const seg = parts[index] ?? "";
332
+ const staticNext = node.staticChildren.get(seg);
333
+ if (staticNext) {
334
+ const hit = this.#walk(staticNext, parts, index + 1, params);
335
+ if (hit !== undefined) return hit;
336
+ }
337
+ if (node.paramChild) {
338
+ params[node.paramChild.name] = seg;
339
+ const hit = this.#walk(node.paramChild.node, parts, index + 1, params);
340
+ if (hit !== undefined) return hit;
341
+ delete params[node.paramChild.name];
342
+ }
343
+ if (node.wildcardChild) {
344
+ params["*"] = parts.slice(index).join("/");
345
+ return node.wildcardChild.value;
346
+ }
347
+ return undefined;
348
+ }
349
+ }
350
+
351
+ interface LinearRoute<T> {
352
+ readonly method: string;
353
+ readonly path: string;
354
+ readonly value: T;
355
+ readonly parts: readonly string[];
356
+ }
357
+
358
+ /**
359
+ * Linear router — fast registration, O(n) string-scan match.
360
+ * Edge / cold-start preset (no compile phase).
361
+ */
362
+ export class LinearRouter<T> implements Router<T> {
363
+ readonly name = "LinearRouter";
364
+ readonly #routes: LinearRoute<T>[] = [];
365
+
366
+ /**
367
+ * @param method - HTTP method
368
+ * @param path - Path pattern
369
+ * @param value - Route value
370
+ */
371
+ add(method: string, path: string, value: T): void {
372
+ const parts = path.startsWith("/")
373
+ ? path.split("/").slice(1)
374
+ : path.split("/");
375
+ this.#routes.push({ method, path, value, parts });
376
+ }
377
+
378
+ /**
379
+ * @param method - HTTP method
380
+ * @param path - Pathname
381
+ */
382
+ match(method: string, path: string): RouteMatch<T> | undefined {
383
+ const pathParts = path.startsWith("/")
384
+ ? path.split("/").slice(1)
385
+ : path.split("/");
386
+ if (pathParts.length > 0 && pathParts[pathParts.length - 1] === "") {
387
+ pathParts.pop();
388
+ }
389
+
390
+ for (const route of this.#routes) {
391
+ if (route.method !== method) continue;
392
+
393
+ if (!route.path.includes(":") && !route.path.includes("*")) {
394
+ if (route.path === path || `${route.path}/` === path) {
395
+ return { value: route.value, params: {} };
396
+ }
397
+ continue;
398
+ }
399
+
400
+ const params: Record<string, string> = {};
401
+ let pi = 0;
402
+ let matched = true;
403
+
404
+ for (let ri = 0; ri < route.parts.length; ri++) {
405
+ const part = route.parts[ri] ?? "";
406
+ if (part === "*") {
407
+ params["*"] = pathParts.slice(pi).join("/");
408
+ pi = pathParts.length;
409
+ break;
410
+ }
411
+ if (pi >= pathParts.length) {
412
+ matched = false;
413
+ break;
414
+ }
415
+ const got = pathParts[pi] ?? "";
416
+ if (part.startsWith(":") && part.length > 1) {
417
+ const name = part.endsWith("?") ? part.slice(1, -1) : part.slice(1);
418
+ params[name] = got;
419
+ pi += 1;
420
+ continue;
421
+ }
422
+ if (part !== got) {
423
+ matched = false;
424
+ break;
425
+ }
426
+ pi += 1;
427
+ }
428
+
429
+ if (matched && pi === pathParts.length) {
430
+ return { value: route.value, params };
431
+ }
432
+ }
433
+ return undefined;
434
+ }
435
+ }
436
+
437
+ /** Factory that produces a fresh router candidate. */
438
+ export type RouterFactory<T> = () => Router<T>;
439
+
440
+ /**
441
+ * Smart router — buffers routes, then at first match (startup) selects
442
+ * RegExpRouter, falling back to TrieRouter on {@link UnsupportedPathError}.
443
+ */
444
+ export class SmartRouter<T> implements Router<T> {
445
+ name = "SmartRouter";
446
+ readonly #factories: readonly RouterFactory<T>[];
447
+ #routes: [string, string, T][] | undefined = [];
448
+ #active: Router<T> | undefined;
449
+
450
+ /**
451
+ * @param init - Candidate factories, fastest first (fresh instance per try)
452
+ */
453
+ constructor(init: {
454
+ readonly routers?: Router<T>[];
455
+ readonly factories?: readonly RouterFactory<T>[];
456
+ }) {
457
+ if (init.factories) {
458
+ this.#factories = init.factories;
459
+ } else if (init.routers) {
460
+ // Wrap pre-built instances once — prefer factories for isolation.
461
+ this.#factories = init.routers.map((r) => () => r);
462
+ } else {
463
+ this.#factories = [];
464
+ }
465
+ }
466
+
467
+ /**
468
+ * @param method - HTTP method
469
+ * @param path - Path pattern
470
+ * @param value - Route value
471
+ */
472
+ add(method: string, path: string, value: T): void {
473
+ if (!this.#routes) {
474
+ throw new Error("SmartRouter matcher is already built");
475
+ }
476
+ this.#routes.push([method, path, value]);
477
+ }
478
+
479
+ /**
480
+ * Force selection now (startup), without waiting for the first match.
481
+ */
482
+ build(): Router<T> {
483
+ return this.#select();
484
+ }
485
+
486
+ /** Active delegate after {@link build} / first {@link match}. */
487
+ get activeRouter(): Router<T> {
488
+ if (!this.#active) {
489
+ throw new Error("No active router has been determined yet.");
490
+ }
491
+ return this.#active;
492
+ }
493
+
494
+ /**
495
+ * @param method - HTTP method
496
+ * @param path - Pathname
497
+ */
498
+ match(method: string, path: string): RouteMatch<T> | undefined {
499
+ const active = this.#active ?? this.#select();
500
+ return active.match(method, path);
501
+ }
502
+
503
+ #select(): Router<T> {
504
+ if (this.#active) return this.#active;
505
+ const routes = this.#routes;
506
+ if (!routes) {
507
+ throw new Error("SmartRouter has no routes buffer");
508
+ }
509
+
510
+ for (const factory of this.#factories) {
511
+ const candidate = factory();
512
+ try {
513
+ for (const [method, path, value] of routes) {
514
+ candidate.add(method, path, value);
515
+ }
516
+ if (candidate instanceof RegExpRouter) {
517
+ candidate.build();
518
+ }
519
+ this.#active = candidate;
520
+ this.name = `SmartRouter + ${candidate.name}`;
521
+ this.#routes = undefined;
522
+ this.match = candidate.match.bind(candidate);
523
+ return candidate;
524
+ } catch (e) {
525
+ if (e instanceof UnsupportedPathError) {
526
+ continue;
527
+ }
528
+ throw e;
529
+ }
530
+ }
531
+
532
+ throw new Error("No router candidate accepted the registered routes");
533
+ }
534
+ }
535
+
536
+ /** Router preset names. */
537
+ export type RouterPreset = "default" | "edge";
538
+
539
+ /**
540
+ * Create a router for the given preset.
541
+ *
542
+ * - `default` — SmartRouter(RegExp → Trie), long-lived servers
543
+ * - `edge` — SmartRouter(Linear → Trie), cold-start / one-shot isolates
544
+ *
545
+ * @param preset - Preset name
546
+ */
547
+ export function createRouter<T>(preset: RouterPreset = "default"): SmartRouter<T> {
548
+ if (preset === "edge") {
549
+ return new SmartRouter<T>({
550
+ factories: [() => new LinearRouter<T>(), () => new TrieRouter<T>()],
551
+ });
552
+ }
553
+ return new SmartRouter<T>({
554
+ factories: [() => new RegExpRouter<T>(), () => new TrieRouter<T>()],
555
+ });
556
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * p99 routing overhead budget — AGENTS.md / unified-theory §24.
3
+ * Limit: < 1 ms per match on a compiled RegExp router.
4
+ */
5
+
6
+ import { describe, expect, test } from "bun:test";
7
+ import { ROUTING_P99_BUDGET_MS } from "../release/limits.ts";
8
+ import { measureRoutingP99Ms } from "../release/measure.ts";
9
+
10
+ describe("routing overhead budget", () => {
11
+ test(`p99 match < ${ROUTING_P99_BUDGET_MS} ms`, () => {
12
+ const p99 = measureRoutingP99Ms();
13
+ console.log(
14
+ `routing p99=${p99.toFixed(4)} ms budget=${ROUTING_P99_BUDGET_MS}`,
15
+ );
16
+ expect(p99).toBeGreaterThanOrEqual(0);
17
+ expect(p99).toBeLessThan(ROUTING_P99_BUDGET_MS);
18
+ });
19
+ });
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Per-invocation telemetry collected through `fx` without flow instrumentation.
3
+ * Consumed by the runs store when building wide events.
4
+ */
5
+
6
+ /** One structured log line captured from `fx.log` during a run. */
7
+ export interface RunLogLine {
8
+ /** Log level. */
9
+ readonly level: "debug" | "info" | "warn" | "error";
10
+ /** Message (secrets already redacted when a vault is wired). */
11
+ readonly message: string;
12
+ /** Optional structured payload. */
13
+ readonly data?: Record<string, unknown>;
14
+ /** Epoch-ms when the line was emitted. */
15
+ readonly at: number;
16
+ }
17
+
18
+ /**
19
+ * Mutable collector attached to one `createFx` invocation.
20
+ * Cache hits/misses, gates, cost, and logs accumulate here automatically.
21
+ */
22
+ export interface RunTelemetry {
23
+ /** Cache hit count via `fx.cache`. */
24
+ cacheHits: number;
25
+ /** Cache miss count via `fx.cache`. */
26
+ cacheMisses: number;
27
+ /** Gate names evaluated (when a gate runtime records them). */
28
+ gates: string[];
29
+ /** SQL role when observed. */
30
+ replica?: "primary" | "replica";
31
+ /** Replica lag ms when observed. */
32
+ replicaLagMs?: number;
33
+ /** Accumulated AI cost. */
34
+ cost: number;
35
+ /** Last prompt version seen. */
36
+ promptVersion?: number;
37
+ /** Subject for crypto-shredding when known. */
38
+ subjectId?: string;
39
+ /** Extra dimensions contributed by the engine (not by the flow body). */
40
+ dimensions: Record<string, string | number | boolean | null>;
41
+ /** Captured `fx.log` lines. */
42
+ logs: RunLogLine[];
43
+ }
44
+
45
+ /**
46
+ * Create an empty telemetry collector.
47
+ */
48
+ export function createRunTelemetry(): RunTelemetry {
49
+ return {
50
+ cacheHits: 0,
51
+ cacheMisses: 0,
52
+ gates: [],
53
+ cost: 0,
54
+ dimensions: {},
55
+ logs: [],
56
+ };
57
+ }
58
+
59
+ /**
60
+ * Derive cache dimension from hit/miss counters.
61
+ *
62
+ * @param t - Telemetry
63
+ */
64
+ export function cacheDimensionOf(
65
+ t: RunTelemetry,
66
+ ): "hit" | "miss" | "none" {
67
+ if (t.cacheHits > 0 && t.cacheMisses === 0) return "hit";
68
+ if (t.cacheMisses > 0) return "miss";
69
+ return "none";
70
+ }