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,245 @@
1
+ /**
2
+ * Request pipeline hooks for element integration.
3
+ *
4
+ * - `onAuth` resolves the principal into `fx.auth` / `fx.operator`
5
+ * - `beforeHandle` evaluates the declared gate chain in registration order,
6
+ * short-circuiting on the first denial with a typed error value
7
+ * (`Unauthorized` · `Forbidden` · `RateLimited { retryAfterMs }`)
8
+ *
9
+ * Every evaluation — pass and deny — is recorded on the run's gates dimension.
10
+ * Gate denial is a typed error value, never a thrown exception.
11
+ */
12
+
13
+ import type { GateEvaluation, GateRuntime } from "../elements/gate.ts";
14
+ import type { GatePolicyContext } from "../elements/gate/declare.ts";
15
+ import { fail, type FlowFailure } from "./errors.ts";
16
+ import type { Fx, FxAuth, FxOperator } from "./fx.ts";
17
+ import type { HookFn, InvocationContext } from "./hooks.ts";
18
+ import type { RunTelemetry } from "./run-telemetry.ts";
19
+ import type { HttpTrigger, Trigger } from "./triggers.ts";
20
+
21
+ /** Mutable principal bag shared with {@link createFx}. */
22
+ export interface PrincipalBag {
23
+ readonly auth: {
24
+ userId: string | null;
25
+ scopes: Set<string>;
26
+ verified?: boolean;
27
+ };
28
+ readonly operator: {
29
+ id: string | null;
30
+ };
31
+ }
32
+
33
+ /** Resolved identity from auth middleware / test harness. */
34
+ export interface ResolvedPrincipal {
35
+ readonly plane?: "user" | "operator";
36
+ readonly userId?: string | null;
37
+ readonly operatorId?: string | null;
38
+ readonly scopes?: Iterable<string>;
39
+ readonly verified?: boolean;
40
+ }
41
+
42
+ /** Dependencies for {@link createElementPipelineHooks}. */
43
+ export interface PipelineDeps {
44
+ /** Gate runtime (required for gate evaluation). */
45
+ readonly gates?: GateRuntime;
46
+ /**
47
+ * Cryptographically verify a Bearer access token.
48
+ * Required in production when an `Authorization` header is present.
49
+ *
50
+ * @param token - Raw token (no `Bearer ` prefix)
51
+ * @returns Principal on success
52
+ * @throws On forge / expiry / revoke — pipeline maps to `Unauthorized`
53
+ */
54
+ readonly verifyBearer?: (token: string) => Promise<ResolvedPrincipal>;
55
+ /**
56
+ * When true, `ctx.state.principal` / execute `extras.principal` injection
57
+ * is honoured (test harness only). Must be false for production HTTP.
58
+ */
59
+ readonly allowTestPrincipals?: boolean;
60
+ /** Per-invocation principal bag (same object passed into createFx). */
61
+ readonly principals: PrincipalBag;
62
+ /** Telemetry collector for the current run (gates dimension). */
63
+ readonly telemetry: RunTelemetry;
64
+ }
65
+
66
+ /**
67
+ * Typed gate-denial failures the Gates simulator promises.
68
+ */
69
+ export type GateDenialCode = "Unauthorized" | "Forbidden" | "RateLimited";
70
+
71
+ /**
72
+ * Map a denied gate evaluation to the typed error the simulator promises.
73
+ *
74
+ * @param evaluation - First denying evaluation
75
+ * @param ctx - Policy context at denial time
76
+ */
77
+ export function gateDenialFailure(
78
+ evaluation: GateEvaluation,
79
+ ctx: GatePolicyContext,
80
+ ): FlowFailure {
81
+ if (evaluation.kind === "rate" || evaluation.reason === "rate limited") {
82
+ return fail("RateLimited", {
83
+ retryAfterMs: evaluation.retryAfterMs ?? 0,
84
+ });
85
+ }
86
+
87
+ const authenticated =
88
+ ctx.auth.userId !== null && ctx.auth.userId !== undefined;
89
+ if (!authenticated) {
90
+ return fail("Unauthorized", {});
91
+ }
92
+ return fail("Forbidden", {
93
+ gate: evaluation.name,
94
+ reason: evaluation.reason ?? "policy denied",
95
+ });
96
+ }
97
+
98
+ /**
99
+ * Collect gate names from an HTTP trigger (registration order).
100
+ *
101
+ * @param trigger - Active trigger
102
+ */
103
+ export function gateNamesOf(trigger: Trigger): string[] {
104
+ if (trigger.kind !== "http") return [];
105
+ return (trigger as HttpTrigger).gates.map((g) =>
106
+ typeof g === "string" ? g : g.name,
107
+ );
108
+ }
109
+
110
+ /**
111
+ * Record evaluations onto run telemetry (pass and deny).
112
+ *
113
+ * @param telemetry - Run collector
114
+ * @param evaluations - Ordered results
115
+ */
116
+ export function recordGateEvaluations(
117
+ telemetry: RunTelemetry,
118
+ evaluations: readonly GateEvaluation[],
119
+ ): void {
120
+ for (const ev of evaluations) {
121
+ telemetry.gates.push(ev.name);
122
+ telemetry.dimensions[`gate:${ev.name}`] = ev.allowed ? "pass" : "deny";
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Apply a resolved principal onto the shared bags (and thus `fx`).
128
+ *
129
+ * @param bag - Mutable principal bag
130
+ * @param resolved - Identity
131
+ */
132
+ export function applyPrincipal(
133
+ bag: PrincipalBag,
134
+ resolved: ResolvedPrincipal | undefined,
135
+ ): void {
136
+ if (!resolved) return;
137
+ if (resolved.plane === "operator" || resolved.operatorId !== undefined) {
138
+ bag.operator.id = resolved.operatorId ?? null;
139
+ }
140
+ if (
141
+ resolved.plane === "user" ||
142
+ resolved.userId !== undefined ||
143
+ resolved.scopes !== undefined ||
144
+ resolved.verified !== undefined
145
+ ) {
146
+ if (resolved.userId !== undefined) bag.auth.userId = resolved.userId;
147
+ if (resolved.scopes !== undefined) {
148
+ bag.auth.scopes.clear();
149
+ for (const s of resolved.scopes) bag.auth.scopes.add(s);
150
+ }
151
+ if (resolved.verified !== undefined) bag.auth.verified = resolved.verified;
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Build `onAuth` + `beforeHandle` hooks for element-aware execution.
157
+ *
158
+ * @param deps - Gate runtime, principal bag, telemetry
159
+ */
160
+ export function createElementPipelineHooks(deps: PipelineDeps): {
161
+ readonly onAuth: HookFn;
162
+ readonly beforeHandle: HookFn;
163
+ } {
164
+ const onAuth: HookFn = async (ctx) => {
165
+ // Production: never honour injected principals on the request bag.
166
+ if (!deps.allowTestPrincipals && "principal" in ctx.state) {
167
+ delete ctx.state.principal;
168
+ }
169
+
170
+ const header = ctx.request?.headers.get("authorization");
171
+ if (header?.startsWith("Bearer ")) {
172
+ const token = header.slice("Bearer ".length).trim();
173
+ if (!token) {
174
+ return fail("Unauthorized", {});
175
+ }
176
+ if (!deps.verifyBearer) {
177
+ // Bearer present but no auth binding — refuse rather than trust.
178
+ return fail("Unauthorized", {});
179
+ }
180
+ try {
181
+ const principal = await deps.verifyBearer(token);
182
+ applyPrincipal(deps.principals, principal);
183
+ return;
184
+ } catch {
185
+ // Forge / expiry / revoke → typed Unauthorized (never throw).
186
+ return fail("Unauthorized", {});
187
+ }
188
+ }
189
+
190
+ // Test-harness injection only (createTestApp / unit tests).
191
+ if (deps.allowTestPrincipals) {
192
+ const fromState = ctx.state.principal as ResolvedPrincipal | undefined;
193
+ if (fromState) applyPrincipal(deps.principals, fromState);
194
+ }
195
+ };
196
+
197
+ const beforeHandle: HookFn = async (ctx, fxOrErr) => {
198
+ const names = gateNamesOf(ctx.trigger);
199
+ if (names.length === 0 || !deps.gates) return;
200
+
201
+ const policyCtx = policyContextOf(fxOrErr as Fx, ctx);
202
+ const evaluations = await deps.gates.check(names, policyCtx);
203
+ recordGateEvaluations(deps.telemetry, evaluations);
204
+
205
+ const denied = evaluations.find((e) => !e.allowed);
206
+ if (denied) {
207
+ return gateDenialFailure(denied, policyCtx);
208
+ }
209
+ };
210
+
211
+ return { onAuth, beforeHandle };
212
+ }
213
+
214
+ /**
215
+ * Build a policy context from the live `fx` principals.
216
+ *
217
+ * @param fx - Fx door
218
+ * @param ctx - Invocation context (for IP / meta)
219
+ */
220
+ export function policyContextOf(
221
+ fx: Fx,
222
+ ctx: InvocationContext,
223
+ ): GatePolicyContext {
224
+ const auth = fx.auth as FxAuth;
225
+ const operator = fx.operator as FxOperator;
226
+ const ip =
227
+ ctx.request?.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ??
228
+ ctx.request?.headers.get("x-real-ip") ??
229
+ undefined;
230
+ return {
231
+ auth: {
232
+ userId: auth.userId,
233
+ scopes: auth.scopes,
234
+ verified: auth.verified,
235
+ },
236
+ operator: { id: operator.id },
237
+ meta: {
238
+ ip,
239
+ userId: auth.userId,
240
+ ...(typeof ctx.state.meta === "object" && ctx.state.meta !== null
241
+ ? (ctx.state.meta as Record<string, unknown>)
242
+ : {}),
243
+ },
244
+ };
245
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * `.plug()` — attach a plugin at an attachment point.
3
+ *
4
+ * Scope is the attachment point:
5
+ * - `app.plug()` — app-wide
6
+ * - `unit.plug()` — that unit only
7
+ * - `flow.plug()` — one flow only
8
+ *
9
+ * No `global: true`, no escape hatch, no inheritance rule.
10
+ * The position is the scope.
11
+ *
12
+ * @see docs/spec/console.md §9.15
13
+ */
14
+
15
+ import type { AnyFlowDef } from "./flow.ts";
16
+ import { isPlugin, type DecorationsOf, type PluginDef } from "./plugin.ts";
17
+ import {
18
+ type PluginRegistry,
19
+ type PluginScope,
20
+ } from "./registry.ts";
21
+
22
+ /**
23
+ * Apply a plugin to a registry at the given scope.
24
+ *
25
+ * @param registry - App plugin registry
26
+ * @param pluginDef - Plugin definition
27
+ * @param scope - Attachment point
28
+ */
29
+ export function applyPlugin(
30
+ registry: PluginRegistry,
31
+ pluginDef: PluginDef,
32
+ scope: PluginScope,
33
+ ): void {
34
+ if (!isPlugin(pluginDef)) {
35
+ throw new TypeError(".plug() expected a plugin() definition");
36
+ }
37
+ registry.plug(pluginDef, scope);
38
+ }
39
+
40
+ /**
41
+ * Type-level accumulation helper: merge decorations from a plugged plugin.
42
+ *
43
+ * @typeParam Base - Existing decorations
44
+ * @typeParam P - Plugin being plugged
45
+ */
46
+ export type AccumulateDecorations<
47
+ Base extends Record<string, unknown>,
48
+ P,
49
+ > = Base & DecorationsOf<P>;
50
+
51
+ /** Something that can receive `.plug()` with type accumulation. */
52
+ export interface Pluggable<D extends Record<string, unknown> = {}> {
53
+ /**
54
+ * Attach a plugin. Scope is this attachment point.
55
+ *
56
+ * @param pluginDef - Plugin from {@link plugin}
57
+ */
58
+ plug<P extends PluginDef>(
59
+ pluginDef: P,
60
+ ): Pluggable<AccumulateDecorations<D, P>>;
61
+ }
62
+
63
+ /**
64
+ * Resolve the plugin scope for a flow attachment.
65
+ *
66
+ * @param flowDef - Flow being plugged into
67
+ */
68
+ export function flowPluginScope(flowDef: AnyFlowDef): PluginScope {
69
+ return { kind: "flow", name: flowDef.name };
70
+ }
71
+
72
+ /**
73
+ * Resolve the plugin scope for a unit attachment.
74
+ *
75
+ * @param unitName - Unit name
76
+ */
77
+ export function unitPluginScope(unitName: string): PluginScope {
78
+ return { kind: "unit", name: unitName };
79
+ }
80
+
81
+ /** App-wide plugin scope. */
82
+ export const appPluginScope: PluginScope = { kind: "app" };
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Capability capture — registration against the builder we supply.
3
+ */
4
+
5
+ import { describe, expect, test } from "bun:test";
6
+ import { flow } from "../flow.ts";
7
+ import { plugin } from "../plugin.ts";
8
+ import { createPluginRegistry, createRecordingApi } from "../registry.ts";
9
+
10
+ describe("plugin capability capture", () => {
11
+ test("recording api captures declares vs intercepts", () => {
12
+ const audit = plugin("audit", { version: "1.0.0" })
13
+ .config({} as never)
14
+ .element({ kind: "store.sql", name: "audit" })
15
+ .needs("store.kv")
16
+ .decorate("audit", { enabled: true })
17
+ .hook("afterHandle", async () => {})
18
+ .errors({ AuditWriteFailed: {} as never })
19
+ .consolePanel({
20
+ id: "audit",
21
+ title: "Audit Trail",
22
+ entry: "./panel.tsx",
23
+ })
24
+ .cli("audit:export", () => undefined)
25
+ .table("audit_events")
26
+ .driver("postgres")
27
+ .image("store.sql", "postgres:16")
28
+ .flow(flow({ name: "audit.flush", do: () => undefined }))
29
+ .client("audit", { subscribe: true });
30
+
31
+ const { api, snapshot } = createRecordingApi({
32
+ name: "audit",
33
+ version: "1.0.0",
34
+ });
35
+ audit.register(api);
36
+ const caps = snapshot().capabilities;
37
+
38
+ const expected = {
39
+ name: "audit",
40
+ version: "1.0.0",
41
+ declares: [
42
+ "config",
43
+ "store.sql:audit",
44
+ "decorate:audit",
45
+ "errors:AuditWriteFailed",
46
+ "consolePanel:audit",
47
+ "cli:audit:export",
48
+ "table:audit_events",
49
+ "driver:postgres",
50
+ "image:store.sql",
51
+ "flow:audit.flush",
52
+ "client:audit",
53
+ ],
54
+ intercepts: ["afterHandle"],
55
+ needs: ["store.kv"],
56
+ };
57
+
58
+ expect(caps).toEqual(expected);
59
+ });
60
+
61
+ test("registry.capabilities matches hand-written expectation after plug", () => {
62
+ const registry = createPluginRegistry();
63
+ const p = plugin("audit", { version: "1.0.0" })
64
+ .element({ kind: "store.sql", name: "audit" })
65
+ .consolePanel({
66
+ id: "audit",
67
+ title: "Audit Trail",
68
+ entry: "./panel.tsx",
69
+ })
70
+ .hook("afterHandle", () => {});
71
+
72
+ registry.plug(p, { kind: "app" });
73
+
74
+ expect(registry.capabilities()).toEqual({
75
+ audit: {
76
+ name: "audit",
77
+ version: "1.0.0",
78
+ declares: ["store.sql:audit", "consolePanel:audit"],
79
+ intercepts: ["afterHandle"],
80
+ needs: [],
81
+ },
82
+ });
83
+ });
84
+ });
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Conflict detection — never last-write-wins.
3
+ */
4
+
5
+ import { describe, expect, test } from "bun:test";
6
+ import { plugin } from "../plugin.ts";
7
+ import { createPluginRegistry } from "../registry.ts";
8
+
9
+ describe("plugin conflict detection", () => {
10
+ test("table-name collision fails the boot with both plugin names", () => {
11
+ const registry = createPluginRegistry();
12
+
13
+ registry.plug(
14
+ plugin("audit", { version: "1.0.0" }).table("events"),
15
+ { kind: "app" },
16
+ );
17
+
18
+ expect(() =>
19
+ registry.plug(
20
+ plugin("billing", { version: "1.0.0" }).table("events"),
21
+ { kind: "app" },
22
+ ),
23
+ ).toThrow(
24
+ 'Plugin conflict: table "events" claimed by "audit" and "billing"',
25
+ );
26
+ });
27
+
28
+ test("panel-id collision names both sides", () => {
29
+ const registry = createPluginRegistry();
30
+
31
+ registry.plug(
32
+ plugin("a", { version: "1.0.0" }).consolePanel({
33
+ id: "trail",
34
+ title: "A",
35
+ entry: "./a.tsx",
36
+ }),
37
+ { kind: "app" },
38
+ );
39
+
40
+ expect(() =>
41
+ registry.plug(
42
+ plugin("b", { version: "1.0.0" }).consolePanel({
43
+ id: "trail",
44
+ title: "B",
45
+ entry: "./b.tsx",
46
+ }),
47
+ { kind: "app" },
48
+ ),
49
+ ).toThrow('Plugin conflict: panel "trail" claimed by "a" and "b"');
50
+ });
51
+
52
+ test("driver-id collision names both sides", () => {
53
+ const registry = createPluginRegistry();
54
+
55
+ registry.plug(plugin("a", { version: "1.0.0" }).driver("postgres"), {
56
+ kind: "app",
57
+ });
58
+
59
+ expect(() =>
60
+ registry.plug(plugin("b", { version: "1.0.0" }).driver("postgres"), {
61
+ kind: "app",
62
+ }),
63
+ ).toThrow('Plugin conflict: driver "postgres" claimed by "a" and "b"');
64
+ });
65
+
66
+ test("same plugin twice at the same scope is a no-op", () => {
67
+ const registry = createPluginRegistry();
68
+ const p = plugin("audit", { version: "1.0.0" }).table("audit_log");
69
+
70
+ expect(registry.plug(p, { kind: "app" })).toBeDefined();
71
+ expect(registry.plug(p, { kind: "app" })).toBeUndefined();
72
+ expect(registry.installed).toHaveLength(1);
73
+ });
74
+
75
+ test("same plugin+config at two scopes is allowed", () => {
76
+ const registry = createPluginRegistry();
77
+ const p = plugin("rate-limit", {
78
+ version: "1.0.0",
79
+ config: { max: 30 },
80
+ }).hook("onRequest", () => {});
81
+
82
+ expect(
83
+ registry.plug(p, { kind: "unit", name: "orders" }),
84
+ ).toBeDefined();
85
+ expect(
86
+ registry.plug(p, { kind: "unit", name: "payments" }),
87
+ ).toBeDefined();
88
+ expect(registry.installed).toHaveLength(2);
89
+ });
90
+
91
+ test("same plugin twice with conflicting config is a boot error", () => {
92
+ const registry = createPluginRegistry();
93
+
94
+ registry.plug(
95
+ plugin("rate-limit", { version: "1.0.0", config: { max: 30 } }),
96
+ { kind: "unit", name: "orders" },
97
+ );
98
+
99
+ expect(() =>
100
+ registry.plug(
101
+ plugin("rate-limit", { version: "1.0.0", config: { max: 60 } }),
102
+ { kind: "unit", name: "payments" },
103
+ ),
104
+ ).toThrow(/conflicting config/);
105
+ });
106
+ });
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Type accumulation through `.plug()` — decorations visible downstream.
3
+ */
4
+
5
+ import { beforeEach, describe, expect, test } from "bun:test";
6
+ import { oke, type OkeApp } from "../app.ts";
7
+ import { flow, resetFlowSeq } from "../flow.ts";
8
+ import { on, resetBindings } from "../on.ts";
9
+ import { plugin, type PluginDef } from "../plugin.ts";
10
+ import { http } from "../triggers.ts";
11
+
12
+ beforeEach(() => {
13
+ resetBindings();
14
+ resetFlowSeq();
15
+ });
16
+
17
+ /** Compile-time assert: `Actual` extends `Expected`. */
18
+ type ExpectExtends<Actual, Expected> =
19
+ Actual extends Expected ? true : false;
20
+
21
+ describe("plugin decorate — types and runtime", () => {
22
+ test("decoration is visible in downstream handlers", async () => {
23
+ const audit = plugin("audit", { version: "1.0.0" }).decorate("audit", {
24
+ enabled: true,
25
+ retain: "2y",
26
+ });
27
+
28
+ let seen: unknown;
29
+ on(
30
+ http.get("/x"),
31
+ flow({
32
+ name: "x",
33
+ do: (_input, _fx) => {
34
+ return { ok: true };
35
+ },
36
+ }).hook("beforeHandle", (ctx) => {
37
+ seen = ctx.decorations.audit;
38
+ }),
39
+ );
40
+
41
+ const app = oke({ name: "decorate" }).plug(audit);
42
+ await app.fetch(new Request("http://localhost/x"));
43
+
44
+ expect(seen).toEqual({ enabled: true, retain: "2y" });
45
+ });
46
+
47
+ test("types accumulate through .plug()", () => {
48
+ const withAudit = plugin("audit", { version: "1.0.0" }).decorate(
49
+ "audit",
50
+ { enabled: true as const },
51
+ );
52
+ const withBilling = plugin("billing", { version: "1.0.0" }).decorate(
53
+ "billing",
54
+ { currency: "SAR" as const },
55
+ );
56
+
57
+ const app = oke({ name: "types" }).plug(withAudit).plug(withBilling);
58
+
59
+ type AppDeco = typeof app extends OkeApp<infer D> ? D : never;
60
+ type HasBoth = ExpectExtends<
61
+ AppDeco,
62
+ { audit: { enabled: true }; billing: { currency: "SAR" } }
63
+ >;
64
+
65
+ const _typeCheck: HasBoth = true;
66
+ expect(_typeCheck).toBe(true);
67
+
68
+ // PluginDef decoration param also accumulates on the builder itself.
69
+ type AuditPlugin = typeof withAudit;
70
+ type AuditDeco = AuditPlugin extends PluginDef<infer D> ? D : never;
71
+ type HasAudit = ExpectExtends<AuditDeco, { audit: { enabled: true } }>;
72
+ const _pluginType: HasAudit = true;
73
+ expect(_pluginType).toBe(true);
74
+ });
75
+
76
+ test("unit-scoped decoration does not leak to another unit", async () => {
77
+ const seen: Record<string, unknown> = {};
78
+
79
+ on(
80
+ http.get("/orders"),
81
+ flow({
82
+ name: "orders.list",
83
+ unit: "orders",
84
+ do: () => ({}),
85
+ }).hook("beforeHandle", (ctx) => {
86
+ seen.orders = ctx.decorations.flag;
87
+ }),
88
+ );
89
+ on(
90
+ http.get("/payments"),
91
+ flow({
92
+ name: "payments.list",
93
+ unit: "payments",
94
+ do: () => ({}),
95
+ }).hook("beforeHandle", (ctx) => {
96
+ seen.payments = ctx.decorations.flag;
97
+ }),
98
+ );
99
+
100
+ const app = oke({ name: "deco-scope" });
101
+ app.unit("orders").plug(
102
+ plugin("flag", { version: "1.0.0" }).decorate("flag", "orders-only"),
103
+ );
104
+
105
+ await app.fetch(new Request("http://localhost/orders"));
106
+ await app.fetch(new Request("http://localhost/payments"));
107
+
108
+ expect(seen.orders).toBe("orders-only");
109
+ expect(seen.payments).toBeUndefined();
110
+ });
111
+ });