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,197 @@
1
+ /**
2
+ * Three cache tiers.
3
+ *
4
+ * - Tier 1 — automatic for live / read flows; invalidation computed from effects
5
+ * - Tier 2 — a flag on any flow (`cache: "5m"`)
6
+ * - Tier 3 — manual via `fx.cache.getOrSet`
7
+ */
8
+
9
+ import type { Effects, ResourceRef } from "../../manifest/types.ts";
10
+
11
+ /** Cache tier identifiers. */
12
+ export type CacheTier = 1 | 2 | 3;
13
+
14
+ /** One cached entry with its provenance. */
15
+ export interface CacheEntry<T = unknown> {
16
+ readonly tier: CacheTier;
17
+ readonly key: string;
18
+ readonly value: T;
19
+ /** Resources this entry was derived from (tier 1). */
20
+ readonly resources: readonly ResourceRef[];
21
+ /** Absolute expiry epoch-ms, or null for no TTL. */
22
+ readonly expiresAt: number | null;
23
+ }
24
+
25
+ /** Invalidation event produced by a write. */
26
+ export interface InvalidationEvent {
27
+ /** Resources written. */
28
+ readonly resources: readonly ResourceRef[];
29
+ /** Keys removed. */
30
+ readonly keys: readonly string[];
31
+ }
32
+
33
+ /**
34
+ * Compute the tier-1 cache key for a read effect set.
35
+ *
36
+ * Format: `computed:{resource}` or `computed:{resource}/{dim}` when dims given.
37
+ *
38
+ * @param resource - Store resource ref
39
+ * @param dims - Optional dimension suffixes (e.g. `userId`)
40
+ */
41
+ export function computedCacheKey(
42
+ resource: ResourceRef,
43
+ dims?: readonly string[],
44
+ ): string {
45
+ if (!dims || dims.length === 0) return `computed:${resource}`;
46
+ return `computed:${resource}/${dims.join("/")}`;
47
+ }
48
+
49
+ /**
50
+ * Tier-1 keys implied by a read effect set.
51
+ *
52
+ * @param effects - Flow effects (must include reads)
53
+ * @param dimsByResource - Optional per-resource dimension suffixes
54
+ */
55
+ export function tier1KeysForReads(
56
+ effects: Effects,
57
+ dimsByResource?: Readonly<Record<string, readonly string[]>>,
58
+ ): string[] {
59
+ const reads = effects.reads ?? [];
60
+ return reads.map((resource) =>
61
+ computedCacheKey(resource, dimsByResource?.[resource]),
62
+ );
63
+ }
64
+
65
+ /**
66
+ * Resources whose tier-1 entries a write must invalidate.
67
+ *
68
+ * @param effects - Write flow effects
69
+ */
70
+ export function resourcesTouchedByWrites(effects: Effects): ResourceRef[] {
71
+ return [...(effects.writes ?? [])];
72
+ }
73
+
74
+ /**
75
+ * Whether a tier-1 key is invalidated by a write effect set.
76
+ *
77
+ * Auto-invalidation fires on exactly the writes touching the read's keys.
78
+ *
79
+ * @param key - Tier-1 cache key (`computed:…`)
80
+ * @param writeEffects - Effects of the writing flow
81
+ */
82
+ export function isInvalidatedByWrite(
83
+ key: string,
84
+ writeEffects: Effects,
85
+ ): boolean {
86
+ if (!key.startsWith("computed:")) return false;
87
+ const body = key.slice("computed:".length);
88
+ const resource = body.split("/")[0] ?? "";
89
+ return (writeEffects.writes ?? []).some((w) => w === resource);
90
+ }
91
+
92
+ /** In-memory multi-tier cache used by the store runtime and tests. */
93
+ export interface StoreCache {
94
+ /**
95
+ * Get a value by key.
96
+ *
97
+ * @param key - Cache key
98
+ */
99
+ get<T = unknown>(key: string): T | undefined;
100
+ /**
101
+ * Set a value.
102
+ *
103
+ * @param entry - Entry to store
104
+ */
105
+ set<T>(entry: CacheEntry<T>): void;
106
+ /**
107
+ * Invalidate every tier-1 entry whose resources intersect `resources`.
108
+ *
109
+ * @param resources - Written resources
110
+ */
111
+ invalidate(resources: readonly ResourceRef[]): InvalidationEvent;
112
+ /**
113
+ * Apply write effects: invalidate exactly the keys those writes touch.
114
+ *
115
+ * @param writeEffects - Writing flow's effects
116
+ */
117
+ invalidateFromEffects(writeEffects: Effects): InvalidationEvent;
118
+ /** Snapshot of keys currently held. */
119
+ keys(): string[];
120
+ /** Clear all tiers. */
121
+ clear(): void;
122
+ }
123
+
124
+ /**
125
+ * Create an in-memory store cache (all three tiers share one map; tier is metadata).
126
+ *
127
+ * @param now - Clock for TTL expiry
128
+ */
129
+ export function createStoreCache(now: () => number = () => Date.now()): StoreCache {
130
+ const entries = new Map<string, CacheEntry>();
131
+
132
+ function alive(entry: CacheEntry): boolean {
133
+ return entry.expiresAt === null || entry.expiresAt > now();
134
+ }
135
+
136
+ return {
137
+ get<T = unknown>(key: string): T | undefined {
138
+ const entry = entries.get(key);
139
+ if (!entry) return undefined;
140
+ if (!alive(entry)) {
141
+ entries.delete(key);
142
+ return undefined;
143
+ }
144
+ return entry.value as T;
145
+ },
146
+ set<T>(entry: CacheEntry<T>): void {
147
+ entries.set(entry.key, entry as CacheEntry);
148
+ },
149
+ invalidate(resources: readonly ResourceRef[]): InvalidationEvent {
150
+ const set = new Set(resources);
151
+ const keys: string[] = [];
152
+ for (const [key, entry] of entries) {
153
+ if (entry.tier !== 1) continue;
154
+ if (entry.resources.some((r) => set.has(r))) {
155
+ keys.push(key);
156
+ entries.delete(key);
157
+ }
158
+ }
159
+ return { resources: [...resources], keys };
160
+ },
161
+ invalidateFromEffects(writeEffects: Effects): InvalidationEvent {
162
+ return this.invalidate(resourcesTouchedByWrites(writeEffects));
163
+ },
164
+ keys(): string[] {
165
+ return [...entries.keys()];
166
+ },
167
+ clear(): void {
168
+ entries.clear();
169
+ },
170
+ };
171
+ }
172
+
173
+ /**
174
+ * Parse a short TTL string (`"5m"`, `"1h"`, `"30s"`) to milliseconds.
175
+ *
176
+ * @param ttl - Duration string
177
+ */
178
+ export function parseTtlMs(ttl: string): number {
179
+ const match = /^(\d+)(ms|s|m|h|d)$/.exec(ttl.trim());
180
+ if (!match) return 0;
181
+ const n = Number(match[1]);
182
+ const unit = match[2];
183
+ switch (unit) {
184
+ case "ms":
185
+ return n;
186
+ case "s":
187
+ return n * 1000;
188
+ case "m":
189
+ return n * 60_000;
190
+ case "h":
191
+ return n * 3_600_000;
192
+ case "d":
193
+ return n * 86_400_000;
194
+ default:
195
+ return 0;
196
+ }
197
+ }
@@ -0,0 +1,125 @@
1
+ /**
2
+ * PII / sensitivity classification — lives in the schema, enforced at the
3
+ * driver boundary so it survives raw SQL (`SELECT *` masks classified columns).
4
+ */
5
+
6
+ import type { ColumnClassification } from "../../manifest/types.ts";
7
+ import {
8
+ classificationKey,
9
+ type ClassificationMap,
10
+ type SqlRow,
11
+ } from "../../drivers/types.ts";
12
+
13
+ /** Default mask token for PII columns when reveal is denied. */
14
+ export const PII_MASK = "[redacted]";
15
+
16
+ /**
17
+ * Tag a column (or field) with privacy / retention classification.
18
+ *
19
+ * Use in schema metadata or `store.sql` classify maps:
20
+ * `email: classify({ pii: true })`.
21
+ *
22
+ * @param classification - Tags to attach
23
+ */
24
+ export function classify(
25
+ classification: ColumnClassification,
26
+ ): ColumnClassification {
27
+ return { ...classification };
28
+ }
29
+
30
+ /**
31
+ * Build a classification map from a nested table → column → tags structure.
32
+ *
33
+ * @param tables - Per-table column classifications
34
+ */
35
+ export function buildClassificationMap(
36
+ tables: Readonly<
37
+ Record<string, Readonly<Record<string, ColumnClassification>>>
38
+ >,
39
+ ): ClassificationMap {
40
+ const map = new Map<string, ColumnClassification>();
41
+ for (const [table, cols] of Object.entries(tables)) {
42
+ for (const [column, tags] of Object.entries(cols)) {
43
+ map.set(classificationKey(table, column), tags);
44
+ }
45
+ }
46
+ return map;
47
+ }
48
+
49
+ /**
50
+ * Whether a column is classified as PII.
51
+ *
52
+ * @param map - Classification map
53
+ * @param table - Table name (may be unknown for opaque queries)
54
+ * @param column - Column name
55
+ */
56
+ export function isPiiColumn(
57
+ map: ClassificationMap,
58
+ table: string | undefined,
59
+ column: string,
60
+ ): boolean {
61
+ if (table) {
62
+ const direct = map.get(classificationKey(table, column));
63
+ if (direct?.pii) return true;
64
+ }
65
+ // Survive raw SQL when only the column name is known: match any table.
66
+ for (const [key, tags] of map) {
67
+ if (tags.pii && key.endsWith(`.${column}`)) return true;
68
+ }
69
+ return false;
70
+ }
71
+
72
+ /** Options for {@link maskRows}. */
73
+ export interface MaskRowsOptions {
74
+ /** Classification map from the schema. */
75
+ readonly classifications: ClassificationMap;
76
+ /** Table hint when known (from query builder). */
77
+ readonly table?: string;
78
+ /**
79
+ * When true, PII columns are returned in cleartext (requires `pii:reveal`).
80
+ * Default false.
81
+ */
82
+ readonly revealPii?: boolean;
83
+ /** Mask token (defaults to {@link PII_MASK}). */
84
+ readonly mask?: string;
85
+ }
86
+
87
+ /**
88
+ * Mask classified columns on result rows at the driver boundary.
89
+ *
90
+ * @param rows - Raw driver rows
91
+ * @param options - Classification + reveal policy
92
+ */
93
+ export function maskRows(
94
+ rows: readonly SqlRow[],
95
+ options: MaskRowsOptions,
96
+ ): SqlRow[] {
97
+ if (options.revealPii || options.classifications.size === 0) {
98
+ return rows.map((r) => ({ ...r }));
99
+ }
100
+ const mask = options.mask ?? PII_MASK;
101
+ return rows.map((row) => {
102
+ const out: SqlRow = {};
103
+ for (const [column, value] of Object.entries(row)) {
104
+ out[column] = isPiiColumn(
105
+ options.classifications,
106
+ options.table,
107
+ column,
108
+ )
109
+ ? mask
110
+ : value;
111
+ }
112
+ return out;
113
+ });
114
+ }
115
+
116
+ /**
117
+ * Extract a FROM table name from a SQL string when possible.
118
+ * Best-effort — used so `SELECT *` still finds classifications.
119
+ *
120
+ * @param sql - SQL text
121
+ */
122
+ export function tableFromSql(sql: string): string | undefined {
123
+ const match = /\bfrom\s+["`]?([a-zA-Z_][a-zA-Z0-9_]*)["`]?/i.exec(sql);
124
+ return match?.[1];
125
+ }
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Store facet declarations — `store.sql` · `store.kv` · `store.files` · `store.index`.
3
+ *
4
+ * Declarations are data; I/O happens only through drivers via the runtime / `fx`.
5
+ */
6
+
7
+ import type { ColumnClassification, ResourceRef, StoreFacet } from "../../manifest/types.ts";
8
+ import { resolveTableName, type TableHandle } from "./table.ts";
9
+
10
+ /** CDC trigger shape (mirrors kernel `CdcTrigger` without importing it). */
11
+ export interface StoreCdcTrigger {
12
+ readonly kind: "cdc";
13
+ readonly table: string;
14
+ readonly column?: string;
15
+ readonly store?: string;
16
+ }
17
+
18
+ /** Handle from {@link SqlStoreDecl.table}. */
19
+ export interface StoreTableCdc {
20
+ readonly name: string;
21
+ /**
22
+ * CDC trigger when `column` (or any column) changes.
23
+ *
24
+ * @param column - Optional column name
25
+ */
26
+ changed(column?: string): StoreCdcTrigger;
27
+ }
28
+
29
+ /** Base fields shared by every facet declaration. */
30
+ export interface StoreDeclBase {
31
+ /** Facet kind. */
32
+ readonly facet: StoreFacet;
33
+ /** Logical name (becomes the resource suffix). */
34
+ readonly name: string;
35
+ /** Resource ref `facet:name`. */
36
+ readonly ref: ResourceRef;
37
+ }
38
+
39
+ /** Options for {@link store.sql}. */
40
+ export interface SqlStoreOptions {
41
+ /**
42
+ * Schema tables — okengine {@link TableHandle}s and/or Drizzle tables.
43
+ * Classification is read from TableHandle columns when present.
44
+ */
45
+ readonly schema?: Readonly<Record<string, TableHandle | unknown>>;
46
+ /**
47
+ * Explicit classifications: `table → column → tags`.
48
+ * Merged with schema-derived tags; wins on conflict for the same column.
49
+ */
50
+ readonly classify?: Readonly<
51
+ Record<string, Readonly<Record<string, ColumnClassification>>>
52
+ >;
53
+ }
54
+
55
+ /** SQL store declaration. */
56
+ export interface SqlStoreDecl extends StoreDeclBase {
57
+ readonly facet: "sql";
58
+ readonly ref: `sql:${string}`;
59
+ readonly schema?: SqlStoreOptions["schema"];
60
+ readonly classify?: SqlStoreOptions["classify"];
61
+ /**
62
+ * CDC handle — `db.table(orders).changed("status")`.
63
+ *
64
+ * @param table - Table handle or Drizzle table
65
+ */
66
+ table(table: TableHandle | unknown): StoreTableCdc;
67
+ }
68
+
69
+ /** Options for {@link store.kv}. */
70
+ export interface KvStoreOptions {
71
+ /** Optional description. */
72
+ readonly description?: string;
73
+ }
74
+
75
+ /** KV store declaration. */
76
+ export interface KvStoreDecl extends StoreDeclBase {
77
+ readonly facet: "kv";
78
+ readonly ref: `kv:${string}`;
79
+ readonly description?: string;
80
+ }
81
+
82
+ /** Options for {@link store.files}. */
83
+ export interface FilesStoreOptions {
84
+ /** Optional description. */
85
+ readonly description?: string;
86
+ }
87
+
88
+ /** Files store declaration. */
89
+ export interface FilesStoreDecl extends StoreDeclBase {
90
+ readonly facet: "files";
91
+ readonly ref: `files:${string}`;
92
+ readonly description?: string;
93
+ }
94
+
95
+ /** Options for {@link store.index}. */
96
+ export interface IndexStoreOptions {
97
+ /** Vector dimensions (default 3 for tests; set explicitly in apps). */
98
+ readonly dims?: number;
99
+ }
100
+
101
+ /** Index store declaration. */
102
+ export interface IndexStoreDecl extends StoreDeclBase {
103
+ readonly facet: "index";
104
+ readonly ref: `index:${string}`;
105
+ readonly dims?: number;
106
+ }
107
+
108
+ /** Any store declaration. */
109
+ export type StoreDecl =
110
+ | SqlStoreDecl
111
+ | KvStoreDecl
112
+ | FilesStoreDecl
113
+ | IndexStoreDecl;
114
+
115
+ /**
116
+ * Declare a SQL store.
117
+ *
118
+ * @param name - Store name
119
+ * @param options - Schema / classification
120
+ */
121
+ export function sql(name: string, options: SqlStoreOptions = {}): SqlStoreDecl {
122
+ const decl: SqlStoreDecl = {
123
+ facet: "sql",
124
+ name,
125
+ ref: `sql:${name}`,
126
+ schema: options.schema,
127
+ classify: options.classify,
128
+ table(table) {
129
+ const tableName = resolveTableName(table);
130
+ return {
131
+ name: tableName,
132
+ changed(column?: string): StoreCdcTrigger {
133
+ return column === undefined
134
+ ? { kind: "cdc", table: tableName, store: name }
135
+ : { kind: "cdc", table: tableName, column, store: name };
136
+ },
137
+ };
138
+ },
139
+ };
140
+ return decl;
141
+ }
142
+
143
+ /**
144
+ * Declare a KV store.
145
+ *
146
+ * @param name - Namespace name
147
+ * @param options - Options
148
+ */
149
+ export function kv(name: string, options: KvStoreOptions = {}): KvStoreDecl {
150
+ return {
151
+ facet: "kv",
152
+ name,
153
+ ref: `kv:${name}`,
154
+ description: options.description,
155
+ };
156
+ }
157
+
158
+ /**
159
+ * Declare a files store.
160
+ *
161
+ * @param name - Bucket name
162
+ * @param options - Options
163
+ */
164
+ export function files(
165
+ name: string,
166
+ options: FilesStoreOptions = {},
167
+ ): FilesStoreDecl {
168
+ return {
169
+ facet: "files",
170
+ name,
171
+ ref: `files:${name}`,
172
+ description: options.description,
173
+ };
174
+ }
175
+
176
+ /**
177
+ * Declare a vector index store.
178
+ *
179
+ * @param name - Index name
180
+ * @param options - Dimensions
181
+ */
182
+ export function index(
183
+ name: string,
184
+ options: IndexStoreOptions = {},
185
+ ): IndexStoreDecl {
186
+ return {
187
+ facet: "index",
188
+ name,
189
+ ref: `index:${name}`,
190
+ dims: options.dims,
191
+ };
192
+ }
193
+
194
+ /** Public `store` element — four facets. */
195
+ export const store = {
196
+ sql,
197
+ kv,
198
+ files,
199
+ index,
200
+ } as const;
@@ -0,0 +1,31 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import {
3
+ contentAddressedKey,
4
+ fileKeyWarnings,
5
+ projectFileKeys,
6
+ } from "./files-policy.ts";
7
+
8
+ describe("files-policy", () => {
9
+ test("flags non-ASCII keys for signed-URL risk", () => {
10
+ const warnings = fileKeyWarnings("фото/id.jpg");
11
+ expect(warnings).toHaveLength(1);
12
+ expect(warnings[0]?.code).toBe("non_ascii_key");
13
+ });
14
+
15
+ test("ascii keys produce no warnings", () => {
16
+ expect(fileKeyWarnings("a/b/c.png")).toEqual([]);
17
+ });
18
+
19
+ test("contentAddressedKey is stable sha256 hex", async () => {
20
+ const a = await contentAddressedKey("hello");
21
+ const b = await contentAddressedKey("hello");
22
+ expect(a).toBe(b);
23
+ expect(a).toMatch(/^[0-9a-f]{64}$/);
24
+ });
25
+
26
+ test("projectFileKeys attaches warnings per key", () => {
27
+ const rows = projectFileKeys(["ok.txt", "café.bin"]);
28
+ expect(rows[0]?.warnings).toEqual([]);
29
+ expect(rows[1]?.warnings[0]?.code).toBe("non_ascii_key");
30
+ });
31
+ });
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Files facet operational policy — content-addressed keys + driver warnings.
3
+ *
4
+ * Warnings are generated here (element physics) so the Console surfaces them
5
+ * automatically rather than inventing hand-written copy (console §9.5 · §11).
6
+ */
7
+
8
+ /** One operational warning attached to a files key. */
9
+ export interface FileKeyWarning {
10
+ /** Stable machine code. */
11
+ readonly code: "non_ascii_key";
12
+ /** Human-readable operator message. */
13
+ readonly message: string;
14
+ /** Object key that triggered the warning. */
15
+ readonly key: string;
16
+ }
17
+
18
+ /**
19
+ * Operational warnings for a files object key.
20
+ *
21
+ * Non-ASCII keys break signed-URL percent-encoding on S3-compatible stores.
22
+ *
23
+ * @param key - Object key
24
+ */
25
+ export function fileKeyWarnings(key: string): readonly FileKeyWarning[] {
26
+ const warnings: FileKeyWarning[] = [];
27
+ // eslint-disable-next-line no-control-regex -- intentional: detect non-ASCII
28
+ if (/[^\x00-\x7F]/.test(key)) {
29
+ warnings.push({
30
+ code: "non_ascii_key",
31
+ message:
32
+ "Non-ASCII object key — signed URL encoding may break on S3-compatible stores.",
33
+ key,
34
+ });
35
+ }
36
+ return warnings;
37
+ }
38
+
39
+ /**
40
+ * Content-addressed object key (sha256 hex of bytes).
41
+ *
42
+ * @param data - Object bytes or UTF-8 string
43
+ */
44
+ export async function contentAddressedKey(
45
+ data: Uint8Array | string,
46
+ ): Promise<string> {
47
+ const bytes =
48
+ typeof data === "string"
49
+ ? new TextEncoder().encode(data)
50
+ : new Uint8Array(data);
51
+ const digest = await crypto.subtle.digest("SHA-256", bytes);
52
+ return [...new Uint8Array(digest)]
53
+ .map((b) => b.toString(16).padStart(2, "0"))
54
+ .join("");
55
+ }
56
+
57
+ /**
58
+ * Attach warnings to a list of object keys.
59
+ *
60
+ * @param keys - Object keys from the driver
61
+ */
62
+ export function projectFileKeys(keys: readonly string[]): ReadonlyArray<{
63
+ readonly key: string;
64
+ readonly warnings: readonly FileKeyWarning[];
65
+ }> {
66
+ return keys.map((key) => ({
67
+ key,
68
+ warnings: fileKeyWarnings(key),
69
+ }));
70
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Automatic replica routing — derived from the effect set.
3
+ *
4
+ * Read-only flows (reads declared, no store writes) route to replicas.
5
+ * No annotations required on the flow.
6
+ */
7
+
8
+ import type { Effects } from "../../manifest/types.ts";
9
+ import type { SqlConnectOptions, SqlRole } from "../../drivers/types.ts";
10
+
11
+ /**
12
+ * Whether a flow's effect set is store-read-only (eligible for replica routing).
13
+ *
14
+ * Emits / sends / asks do not force the primary — only `writes` do.
15
+ *
16
+ * @param effects - Declared or inferred effects
17
+ */
18
+ export function isReadOnlyStoreFlow(effects: Effects): boolean {
19
+ const writes = effects.writes?.length ?? 0;
20
+ return writes === 0;
21
+ }
22
+
23
+ /**
24
+ * Choose the SQL connection role for a flow from its effects.
25
+ *
26
+ * @param effects - Flow effects
27
+ * @param hasReplicas - Whether replicas are configured
28
+ */
29
+ export function sqlRoleForEffects(
30
+ effects: Effects,
31
+ hasReplicas: boolean,
32
+ ): SqlRole {
33
+ if (hasReplicas && isReadOnlyStoreFlow(effects)) return "replica";
34
+ return "primary";
35
+ }
36
+
37
+ /** SQL binding with optional read replicas. */
38
+ export interface SqlBindingConfig {
39
+ /** Primary connection options. */
40
+ readonly primary: SqlConnectOptions;
41
+ /** Read replicas (round-robin). */
42
+ readonly replicas?: readonly SqlConnectOptions[];
43
+ }
44
+
45
+ /**
46
+ * Resolve which connection options to use for a flow.
47
+ *
48
+ * @param config - Primary + replicas
49
+ * @param effects - Flow effects
50
+ * @param pickReplica - Index picker (defaults to 0)
51
+ */
52
+ export function resolveSqlTarget(
53
+ config: SqlBindingConfig,
54
+ effects: Effects,
55
+ pickReplica: (count: number) => number = () => 0,
56
+ ): { readonly role: SqlRole; readonly options: SqlConnectOptions } {
57
+ const replicas = config.replicas ?? [];
58
+ const role = sqlRoleForEffects(effects, replicas.length > 0);
59
+ if (role === "replica") {
60
+ const idx = Math.abs(pickReplica(replicas.length)) % replicas.length;
61
+ const options = replicas[idx]!;
62
+ return { role: "replica", options: { ...options, role: "replica" } };
63
+ }
64
+ return {
65
+ role: "primary",
66
+ options: { ...config.primary, role: "primary" },
67
+ };
68
+ }