@intutic/cli 1.10.0 → 1.10.1

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 (357) hide show
  1. package/README.md +1 -0
  2. package/dist/cli.js +868 -30
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/attenuate.d.ts +39 -0
  5. package/dist/commands/attenuate.d.ts.map +1 -0
  6. package/dist/commands/attenuate.js +98 -0
  7. package/dist/commands/attenuate.js.map +1 -0
  8. package/dist/commands/budget.d.ts +80 -0
  9. package/dist/commands/budget.d.ts.map +1 -1
  10. package/dist/commands/budget.js +119 -3
  11. package/dist/commands/budget.js.map +1 -1
  12. package/dist/commands/connect.d.ts +10 -0
  13. package/dist/commands/connect.d.ts.map +1 -1
  14. package/dist/commands/connect.js +358 -48
  15. package/dist/commands/connect.js.map +1 -1
  16. package/dist/commands/credentials.d.ts +31 -0
  17. package/dist/commands/credentials.d.ts.map +1 -0
  18. package/dist/commands/credentials.js +134 -0
  19. package/dist/commands/credentials.js.map +1 -0
  20. package/dist/commands/decision.d.ts +37 -0
  21. package/dist/commands/decision.d.ts.map +1 -0
  22. package/dist/commands/decision.js +56 -0
  23. package/dist/commands/decision.js.map +1 -0
  24. package/dist/commands/doctor.d.ts +38 -1
  25. package/dist/commands/doctor.d.ts.map +1 -1
  26. package/dist/commands/doctor.js +228 -18
  27. package/dist/commands/doctor.js.map +1 -1
  28. package/dist/commands/enforce.d.ts +33 -0
  29. package/dist/commands/enforce.d.ts.map +1 -0
  30. package/dist/commands/enforce.js +150 -0
  31. package/dist/commands/enforce.js.map +1 -0
  32. package/dist/commands/enterprise.d.ts +29 -0
  33. package/dist/commands/enterprise.d.ts.map +1 -0
  34. package/dist/commands/enterprise.js +141 -0
  35. package/dist/commands/enterprise.js.map +1 -0
  36. package/dist/commands/env.d.ts +7 -0
  37. package/dist/commands/env.d.ts.map +1 -0
  38. package/dist/commands/env.js +55 -0
  39. package/dist/commands/env.js.map +1 -0
  40. package/dist/commands/exec.d.ts +38 -2
  41. package/dist/commands/exec.d.ts.map +1 -1
  42. package/dist/commands/exec.js +247 -10
  43. package/dist/commands/exec.js.map +1 -1
  44. package/dist/commands/findings.d.ts +84 -0
  45. package/dist/commands/findings.d.ts.map +1 -0
  46. package/dist/commands/findings.js +329 -0
  47. package/dist/commands/findings.js.map +1 -0
  48. package/dist/commands/gateway.d.ts +62 -0
  49. package/dist/commands/gateway.d.ts.map +1 -0
  50. package/dist/commands/gateway.js +298 -0
  51. package/dist/commands/gateway.js.map +1 -0
  52. package/dist/commands/guardrails.d.ts +81 -0
  53. package/dist/commands/guardrails.d.ts.map +1 -0
  54. package/dist/commands/guardrails.js +735 -0
  55. package/dist/commands/guardrails.js.map +1 -0
  56. package/dist/commands/init.d.ts +8 -0
  57. package/dist/commands/init.d.ts.map +1 -1
  58. package/dist/commands/init.js +14 -2
  59. package/dist/commands/init.js.map +1 -1
  60. package/dist/commands/install-daemon.d.ts +70 -3
  61. package/dist/commands/install-daemon.d.ts.map +1 -1
  62. package/dist/commands/install-daemon.js +482 -47
  63. package/dist/commands/install-daemon.js.map +1 -1
  64. package/dist/commands/integrity.d.ts +205 -0
  65. package/dist/commands/integrity.d.ts.map +1 -0
  66. package/dist/commands/integrity.js +620 -0
  67. package/dist/commands/integrity.js.map +1 -0
  68. package/dist/commands/judge.d.ts +31 -0
  69. package/dist/commands/judge.d.ts.map +1 -0
  70. package/dist/commands/judge.js +118 -0
  71. package/dist/commands/judge.js.map +1 -0
  72. package/dist/commands/org.d.ts +31 -0
  73. package/dist/commands/org.d.ts.map +1 -0
  74. package/dist/commands/org.js +159 -0
  75. package/dist/commands/org.js.map +1 -0
  76. package/dist/commands/policy.d.ts +138 -4
  77. package/dist/commands/policy.d.ts.map +1 -1
  78. package/dist/commands/policy.js +538 -97
  79. package/dist/commands/policy.js.map +1 -1
  80. package/dist/commands/predict-cost.d.ts +45 -0
  81. package/dist/commands/predict-cost.d.ts.map +1 -0
  82. package/dist/commands/predict-cost.js +123 -0
  83. package/dist/commands/predict-cost.js.map +1 -0
  84. package/dist/commands/rollback.d.ts +5 -0
  85. package/dist/commands/rollback.d.ts.map +1 -0
  86. package/dist/commands/rollback.js +142 -0
  87. package/dist/commands/rollback.js.map +1 -0
  88. package/dist/commands/routing.d.ts +62 -0
  89. package/dist/commands/routing.d.ts.map +1 -0
  90. package/dist/commands/routing.js +121 -0
  91. package/dist/commands/routing.js.map +1 -0
  92. package/dist/commands/setup.d.ts +62 -0
  93. package/dist/commands/setup.d.ts.map +1 -0
  94. package/dist/commands/setup.js +238 -0
  95. package/dist/commands/setup.js.map +1 -0
  96. package/dist/commands/skill.d.ts +268 -1
  97. package/dist/commands/skill.d.ts.map +1 -1
  98. package/dist/commands/skill.js +744 -39
  99. package/dist/commands/skill.js.map +1 -1
  100. package/dist/commands/sops.d.ts +95 -0
  101. package/dist/commands/sops.d.ts.map +1 -1
  102. package/dist/commands/sops.js +334 -34
  103. package/dist/commands/sops.js.map +1 -1
  104. package/dist/commands/start.d.ts.map +1 -1
  105. package/dist/commands/start.js +1 -18
  106. package/dist/commands/start.js.map +1 -1
  107. package/dist/commands/status.d.ts.map +1 -1
  108. package/dist/commands/status.js +44 -1
  109. package/dist/commands/status.js.map +1 -1
  110. package/dist/commands/team.d.ts +38 -0
  111. package/dist/commands/team.d.ts.map +1 -0
  112. package/dist/commands/team.js +140 -0
  113. package/dist/commands/team.js.map +1 -0
  114. package/dist/commands/traces.d.ts +8 -1
  115. package/dist/commands/traces.d.ts.map +1 -1
  116. package/dist/commands/traces.js +114 -15
  117. package/dist/commands/traces.js.map +1 -1
  118. package/dist/commands/whoami.d.ts.map +1 -1
  119. package/dist/commands/whoami.js +2 -1
  120. package/dist/commands/whoami.js.map +1 -1
  121. package/dist/config/keychain.d.ts +10 -2
  122. package/dist/config/keychain.d.ts.map +1 -1
  123. package/dist/config/keychain.js +83 -14
  124. package/dist/config/keychain.js.map +1 -1
  125. package/dist/config/paths.d.ts +27 -0
  126. package/dist/config/paths.d.ts.map +1 -1
  127. package/dist/config/paths.js +37 -6
  128. package/dist/config/paths.js.map +1 -1
  129. package/dist/config/store.d.ts.map +1 -1
  130. package/dist/config/store.js +19 -3
  131. package/dist/config/store.js.map +1 -1
  132. package/dist/harness/ag2.d.ts +22 -0
  133. package/dist/harness/ag2.d.ts.map +1 -0
  134. package/dist/harness/ag2.js +34 -0
  135. package/dist/harness/ag2.js.map +1 -0
  136. package/dist/harness/agentcore.d.ts +55 -0
  137. package/dist/harness/agentcore.d.ts.map +1 -0
  138. package/dist/harness/agentcore.js +119 -0
  139. package/dist/harness/agentcore.js.map +1 -0
  140. package/dist/harness/agenticOrchestrator.d.ts +52 -0
  141. package/dist/harness/agenticOrchestrator.d.ts.map +1 -0
  142. package/dist/harness/agenticOrchestrator.js +115 -0
  143. package/dist/harness/agenticOrchestrator.js.map +1 -0
  144. package/dist/harness/aiSdkHarness.d.ts +30 -0
  145. package/dist/harness/aiSdkHarness.d.ts.map +1 -0
  146. package/dist/harness/aiSdkHarness.js +51 -0
  147. package/dist/harness/aiSdkHarness.js.map +1 -0
  148. package/dist/harness/aiSdkWorkflow.d.ts +26 -0
  149. package/dist/harness/aiSdkWorkflow.d.ts.map +1 -0
  150. package/dist/harness/aiSdkWorkflow.js +39 -0
  151. package/dist/harness/aiSdkWorkflow.js.map +1 -0
  152. package/dist/harness/autogen.d.ts +24 -0
  153. package/dist/harness/autogen.d.ts.map +1 -0
  154. package/dist/harness/autogen.js +36 -0
  155. package/dist/harness/autogen.js.map +1 -0
  156. package/dist/harness/base.js.map +1 -1
  157. package/dist/harness/continue.d.ts.map +1 -1
  158. package/dist/harness/continue.js +2 -1
  159. package/dist/harness/continue.js.map +1 -1
  160. package/dist/harness/crewai.d.ts +15 -0
  161. package/dist/harness/crewai.d.ts.map +1 -0
  162. package/dist/harness/crewai.js +26 -0
  163. package/dist/harness/crewai.js.map +1 -0
  164. package/dist/harness/detector.d.ts +1 -1
  165. package/dist/harness/detector.d.ts.map +1 -1
  166. package/dist/harness/detector.js +47 -1
  167. package/dist/harness/detector.js.map +1 -1
  168. package/dist/harness/dsh.d.ts +19 -0
  169. package/dist/harness/dsh.d.ts.map +1 -0
  170. package/dist/harness/dsh.js +93 -0
  171. package/dist/harness/dsh.js.map +1 -0
  172. package/dist/harness/eve.d.ts +40 -0
  173. package/dist/harness/eve.d.ts.map +1 -0
  174. package/dist/harness/eve.js +67 -0
  175. package/dist/harness/eve.js.map +1 -0
  176. package/dist/harness/googleAdk.d.ts +18 -0
  177. package/dist/harness/googleAdk.d.ts.map +1 -0
  178. package/dist/harness/googleAdk.js +29 -0
  179. package/dist/harness/googleAdk.js.map +1 -0
  180. package/dist/harness/goose.d.ts.map +1 -1
  181. package/dist/harness/goose.js +5 -1
  182. package/dist/harness/goose.js.map +1 -1
  183. package/dist/harness/grok.d.ts +16 -0
  184. package/dist/harness/grok.d.ts.map +1 -0
  185. package/dist/harness/grok.js +78 -0
  186. package/dist/harness/grok.js.map +1 -0
  187. package/dist/harness/jsSdkGatedAdapter.d.ts +102 -0
  188. package/dist/harness/jsSdkGatedAdapter.d.ts.map +1 -0
  189. package/dist/harness/jsSdkGatedAdapter.js +139 -0
  190. package/dist/harness/jsSdkGatedAdapter.js.map +1 -0
  191. package/dist/harness/langchain.d.ts +22 -0
  192. package/dist/harness/langchain.d.ts.map +1 -0
  193. package/dist/harness/langchain.js +33 -0
  194. package/dist/harness/langchain.js.map +1 -0
  195. package/dist/harness/langgraph.d.ts +22 -0
  196. package/dist/harness/langgraph.d.ts.map +1 -0
  197. package/dist/harness/langgraph.js +80 -0
  198. package/dist/harness/langgraph.js.map +1 -0
  199. package/dist/harness/mastra.d.ts +21 -0
  200. package/dist/harness/mastra.d.ts.map +1 -0
  201. package/dist/harness/mastra.js +33 -0
  202. package/dist/harness/mastra.js.map +1 -0
  203. package/dist/harness/muse.d.ts +22 -0
  204. package/dist/harness/muse.d.ts.map +1 -0
  205. package/dist/harness/muse.js +92 -0
  206. package/dist/harness/muse.js.map +1 -0
  207. package/dist/harness/n8n.d.ts.map +1 -1
  208. package/dist/harness/n8n.js +36 -11
  209. package/dist/harness/n8n.js.map +1 -1
  210. package/dist/harness/openaiAgents.d.ts +40 -0
  211. package/dist/harness/openaiAgents.d.ts.map +1 -0
  212. package/dist/harness/openaiAgents.js +107 -0
  213. package/dist/harness/openaiAgents.js.map +1 -0
  214. package/dist/harness/opencode.d.ts +24 -0
  215. package/dist/harness/opencode.d.ts.map +1 -0
  216. package/dist/harness/opencode.js +97 -0
  217. package/dist/harness/opencode.js.map +1 -0
  218. package/dist/harness/pydanticAi.d.ts +19 -0
  219. package/dist/harness/pydanticAi.d.ts.map +1 -0
  220. package/dist/harness/pydanticAi.js +30 -0
  221. package/dist/harness/pydanticAi.js.map +1 -0
  222. package/dist/harness/sdkGatedAdapter.d.ts +55 -0
  223. package/dist/harness/sdkGatedAdapter.d.ts.map +1 -0
  224. package/dist/harness/sdkGatedAdapter.js +85 -0
  225. package/dist/harness/sdkGatedAdapter.js.map +1 -0
  226. package/dist/harness/smolagents.d.ts +22 -0
  227. package/dist/harness/smolagents.d.ts.map +1 -0
  228. package/dist/harness/smolagents.js +33 -0
  229. package/dist/harness/smolagents.js.map +1 -0
  230. package/dist/harness/strands.d.ts +22 -0
  231. package/dist/harness/strands.d.ts.map +1 -0
  232. package/dist/harness/strands.js +35 -0
  233. package/dist/harness/strands.js.map +1 -0
  234. package/dist/harness/trueforge.d.ts +25 -0
  235. package/dist/harness/trueforge.d.ts.map +1 -0
  236. package/dist/harness/trueforge.js +40 -0
  237. package/dist/harness/trueforge.js.map +1 -0
  238. package/dist/harness/types.d.ts.map +1 -1
  239. package/dist/harness/types.js +70 -0
  240. package/dist/harness/types.js.map +1 -1
  241. package/dist/harness/vercelAiSdk.d.ts +31 -0
  242. package/dist/harness/vercelAiSdk.d.ts.map +1 -0
  243. package/dist/harness/vercelAiSdk.js +44 -0
  244. package/dist/harness/vercelAiSdk.js.map +1 -0
  245. package/dist/harness/xirp.d.ts +43 -0
  246. package/dist/harness/xirp.d.ts.map +1 -0
  247. package/dist/harness/xirp.js +95 -0
  248. package/dist/harness/xirp.js.map +1 -0
  249. package/dist/lib/api.d.ts +68 -0
  250. package/dist/lib/api.d.ts.map +1 -1
  251. package/dist/lib/api.js +108 -67
  252. package/dist/lib/api.js.map +1 -1
  253. package/dist/lib/authMessages.d.ts +19 -0
  254. package/dist/lib/authMessages.d.ts.map +1 -0
  255. package/dist/lib/authMessages.js +20 -0
  256. package/dist/lib/authMessages.js.map +1 -0
  257. package/dist/lib/binaryChecksum.d.ts +12 -0
  258. package/dist/lib/binaryChecksum.d.ts.map +1 -0
  259. package/dist/lib/binaryChecksum.js +45 -0
  260. package/dist/lib/binaryChecksum.js.map +1 -0
  261. package/dist/lib/binaryOnPath.d.ts +24 -0
  262. package/dist/lib/binaryOnPath.d.ts.map +1 -0
  263. package/dist/lib/binaryOnPath.js +31 -0
  264. package/dist/lib/binaryOnPath.js.map +1 -0
  265. package/dist/lib/caTrust.d.ts +69 -0
  266. package/dist/lib/caTrust.d.ts.map +1 -0
  267. package/dist/lib/caTrust.js +169 -0
  268. package/dist/lib/caTrust.js.map +1 -0
  269. package/dist/lib/ciscoScanner.d.ts +178 -0
  270. package/dist/lib/ciscoScanner.d.ts.map +1 -0
  271. package/dist/lib/ciscoScanner.js +292 -0
  272. package/dist/lib/ciscoScanner.js.map +1 -0
  273. package/dist/lib/decisionsLogRefresh.d.ts +28 -0
  274. package/dist/lib/decisionsLogRefresh.d.ts.map +1 -0
  275. package/dist/lib/decisionsLogRefresh.js +54 -0
  276. package/dist/lib/decisionsLogRefresh.js.map +1 -0
  277. package/dist/lib/deviceReport.d.ts +26 -0
  278. package/dist/lib/deviceReport.d.ts.map +1 -0
  279. package/dist/lib/deviceReport.js +55 -0
  280. package/dist/lib/deviceReport.js.map +1 -0
  281. package/dist/lib/elevation.d.ts +58 -0
  282. package/dist/lib/elevation.d.ts.map +1 -0
  283. package/dist/lib/elevation.js +83 -0
  284. package/dist/lib/elevation.js.map +1 -0
  285. package/dist/lib/enforcementState.d.ts +69 -0
  286. package/dist/lib/enforcementState.d.ts.map +1 -0
  287. package/dist/lib/enforcementState.js +113 -0
  288. package/dist/lib/enforcementState.js.map +1 -0
  289. package/dist/lib/ensureValkey.d.ts.map +1 -1
  290. package/dist/lib/ensureValkey.js +2 -2
  291. package/dist/lib/ensureValkey.js.map +1 -1
  292. package/dist/lib/envInjector.d.ts.map +1 -1
  293. package/dist/lib/envInjector.js +22 -4
  294. package/dist/lib/envInjector.js.map +1 -1
  295. package/dist/lib/gitHooks.d.ts +7 -2
  296. package/dist/lib/gitHooks.d.ts.map +1 -1
  297. package/dist/lib/gitHooks.js +180 -13
  298. package/dist/lib/gitHooks.js.map +1 -1
  299. package/dist/lib/gracefulShutdown.d.ts +37 -0
  300. package/dist/lib/gracefulShutdown.d.ts.map +1 -0
  301. package/dist/lib/gracefulShutdown.js +57 -0
  302. package/dist/lib/gracefulShutdown.js.map +1 -0
  303. package/dist/lib/graphIdentity.d.ts +80 -0
  304. package/dist/lib/graphIdentity.d.ts.map +1 -0
  305. package/dist/lib/graphIdentity.js +120 -0
  306. package/dist/lib/graphIdentity.js.map +1 -0
  307. package/dist/lib/localTraces.d.ts +61 -0
  308. package/dist/lib/localTraces.d.ts.map +1 -0
  309. package/dist/lib/localTraces.js +173 -0
  310. package/dist/lib/localTraces.js.map +1 -0
  311. package/dist/lib/mdmManifest.d.ts +73 -0
  312. package/dist/lib/mdmManifest.d.ts.map +1 -0
  313. package/dist/lib/mdmManifest.js +190 -0
  314. package/dist/lib/mdmManifest.js.map +1 -0
  315. package/dist/lib/onboarding.d.ts.map +1 -1
  316. package/dist/lib/onboarding.js +60 -1
  317. package/dist/lib/onboarding.js.map +1 -1
  318. package/dist/lib/otelPropagation.d.ts +26 -0
  319. package/dist/lib/otelPropagation.d.ts.map +1 -0
  320. package/dist/lib/otelPropagation.js +40 -0
  321. package/dist/lib/otelPropagation.js.map +1 -0
  322. package/dist/lib/policySnapshot.d.ts +92 -0
  323. package/dist/lib/policySnapshot.d.ts.map +1 -0
  324. package/dist/lib/policySnapshot.js +173 -0
  325. package/dist/lib/policySnapshot.js.map +1 -0
  326. package/dist/lib/process.d.ts.map +1 -1
  327. package/dist/lib/process.js +60 -0
  328. package/dist/lib/process.js.map +1 -1
  329. package/dist/lib/providerProbe.d.ts +28 -0
  330. package/dist/lib/providerProbe.d.ts.map +1 -0
  331. package/dist/lib/providerProbe.js +57 -0
  332. package/dist/lib/providerProbe.js.map +1 -0
  333. package/dist/lib/proxyBinary.d.ts +19 -0
  334. package/dist/lib/proxyBinary.d.ts.map +1 -0
  335. package/dist/lib/proxyBinary.js +30 -0
  336. package/dist/lib/proxyBinary.js.map +1 -0
  337. package/dist/lib/sandbox/firecracker.d.ts +89 -0
  338. package/dist/lib/sandbox/firecracker.d.ts.map +1 -0
  339. package/dist/lib/sandbox/firecracker.js +135 -0
  340. package/dist/lib/sandbox/firecracker.js.map +1 -0
  341. package/dist/lib/sandbox/index.d.ts +34 -0
  342. package/dist/lib/sandbox/index.d.ts.map +1 -0
  343. package/dist/lib/sandbox/index.js +54 -0
  344. package/dist/lib/sandbox/index.js.map +1 -0
  345. package/dist/lib/sandbox/oci.d.ts +38 -0
  346. package/dist/lib/sandbox/oci.d.ts.map +1 -0
  347. package/dist/lib/sandbox/oci.js +108 -0
  348. package/dist/lib/sandbox/oci.js.map +1 -0
  349. package/dist/lib/sandbox/types.d.ts +48 -0
  350. package/dist/lib/sandbox/types.d.ts.map +1 -0
  351. package/dist/lib/sandbox/types.js +12 -0
  352. package/dist/lib/sandbox/types.js.map +1 -0
  353. package/dist/lib/sopFrontMatter.d.ts +50 -0
  354. package/dist/lib/sopFrontMatter.d.ts.map +1 -0
  355. package/dist/lib/sopFrontMatter.js +129 -0
  356. package/dist/lib/sopFrontMatter.js.map +1 -0
  357. package/package.json +11 -6
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxyBinary.js","sourceRoot":"","sources":["../../src/lib/proxyBinary.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,SAAS,MAAM,WAAW,CAAA;AACtC,OAAO,KAAK,OAAO,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,oBAAoB,CAAwB,CAAA;AAE/F;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAA;IACtD,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,iBAAiB,OAAO,GAAG,GAAG,EAAE,CAAC,CAAA;IAC1F,OAAO,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAA;AACzD,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,kBAAkB;IAChC,OAAO,gBAAgB,EAAE,IAAI,eAAe,CAAA;AAC9C,CAAC"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * FirecrackerBackend — VM-grade isolation via a Firecracker microVM (LLD #63 §6,
3
+ * Increment 4). Same `SandboxBackend` interface as the container backend; the
4
+ * difference is the boundary: a separate guest kernel over KVM rather than
5
+ * shared-kernel namespaces.
6
+ *
7
+ * The egress model is identical in spirit — the microVM's only route out is the
8
+ * governing proxy — but enforced on the *host* side, by a default-deny firewall
9
+ * on the guest's tap interface (the L2 rule shape, scoped to the guest's
10
+ * source address). That keeps the enforcement outside the guest, where the
11
+ * agent cannot touch it, which is stronger than the in-container firewall.
12
+ *
13
+ * Honesty status (see LLD #63 §7 + TECH_DEBT): the microVM *boots on real KVM*
14
+ * — validated on a GCE nested-virt host, where Firecracker loaded and ran the
15
+ * guest kernel through this exact config + API sequence (the launch script this
16
+ * backend invokes). What is NOT yet validated end-to-end is an agent running to
17
+ * completion *inside* a fully-booted guest: that needs a matched
18
+ * kernel+rootfs pair the operator supplies (as an OCI sandbox needs an image
19
+ * containing the agent). `health()` therefore gates on KVM + the firecracker
20
+ * binary + the operator-supplied kernel/rootfs, and refuses rather than
21
+ * pretend — it never falls back to a weaker backend.
22
+ *
23
+ * @module
24
+ */
25
+ import type { SandboxBackend, SandboxHealth, SandboxSpec } from './types.js';
26
+ /** Firecracker-specific inputs, beyond the generic SandboxSpec. */
27
+ export interface FirecrackerOptions {
28
+ /** Guest kernel image (vmlinux). Operator-supplied. */
29
+ kernelPath: string;
30
+ /** Root filesystem image (ext4). Operator-supplied, must contain the agent. */
31
+ rootfsPath: string;
32
+ /** Host tap device name. */
33
+ tapDevice: string;
34
+ /** Guest IP on the point-to-point tap link. */
35
+ guestIp: string;
36
+ /** Host IP on the tap link — the address the guest reaches the proxy at. */
37
+ hostIp: string;
38
+ /** Netmask (prefix length) for the tap link. */
39
+ prefixLen: number;
40
+ vcpus: number;
41
+ memMib: number;
42
+ }
43
+ /** The Firecracker VM configuration, as `firecracker --config-file` consumes. */
44
+ export interface FirecrackerConfig {
45
+ 'boot-source': {
46
+ kernel_image_path: string;
47
+ boot_args: string;
48
+ };
49
+ drives: Array<{
50
+ drive_id: string;
51
+ path_on_host: string;
52
+ is_root_device: boolean;
53
+ is_read_only: boolean;
54
+ }>;
55
+ 'network-interfaces': Array<{
56
+ iface_id: string;
57
+ host_dev_name: string;
58
+ }>;
59
+ 'machine-config': {
60
+ vcpu_count: number;
61
+ mem_size_mib: number;
62
+ };
63
+ }
64
+ /**
65
+ * Build the Firecracker VM config. Pure and exported so the exact boot config
66
+ * — the one proven to boot a guest kernel on KVM — is asserted without a VM.
67
+ *
68
+ * The boot args are load-bearing: `root=/dev/vda rw` (the rootfs is the first
69
+ * virtio-blk device) and the kernel `ip=` directive that configures the guest's
70
+ * eth0 on the point-to-point tap link so its only reachable peer is the host.
71
+ */
72
+ export declare function buildFirecrackerConfig(opts: FirecrackerOptions): FirecrackerConfig;
73
+ /** Dotted-quad netmask for a prefix length (IPv4). */
74
+ export declare function prefixToNetmask(prefix: number): string;
75
+ export declare class FirecrackerBackend implements SandboxBackend {
76
+ readonly name = "firecracker";
77
+ private readonly opts;
78
+ private readonly env;
79
+ constructor(opts: FirecrackerOptions, env: Record<string, string>);
80
+ /**
81
+ * Available only where a microVM can actually run: KVM present, the
82
+ * firecracker binary on PATH, and the operator's kernel + rootfs readable.
83
+ * Any of these missing → unavailable, and the caller refuses rather than
84
+ * downgrade (the honesty rule).
85
+ */
86
+ health(): Promise<SandboxHealth>;
87
+ run(spec: SandboxSpec): Promise<number>;
88
+ }
89
+ //# sourceMappingURL=firecracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firecracker.d.ts","sourceRoot":"","sources":["../../../src/lib/sandbox/firecracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAQH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE5E,mEAAmE;AACnE,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAA;IAClB,+EAA+E;IAC/E,UAAU,EAAE,MAAM,CAAA;IAClB,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAA;IACf,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAA;IACd,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,iFAAiF;AACjF,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE;QAAE,iBAAiB,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;IAC/D,MAAM,EAAE,KAAK,CAAC;QACZ,QAAQ,EAAE,MAAM,CAAA;QAChB,YAAY,EAAE,MAAM,CAAA;QACpB,cAAc,EAAE,OAAO,CAAA;QACvB,YAAY,EAAE,OAAO,CAAA;KACtB,CAAC,CAAA;IACF,oBAAoB,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACxE,gBAAgB,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAA;CAC/D;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,kBAAkB,GAAG,iBAAiB,CAkBlF;AAED,sDAAsD;AACtD,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAGtD;AASD,qBAAa,kBAAmB,YAAW,cAAc;IACvD,QAAQ,CAAC,IAAI,iBAAgB;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoB;IACzC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAwB;gBAEhC,IAAI,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAKjE;;;;;OAKG;IACG,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC;IAiBhC,GAAG,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;CAoC9C"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * FirecrackerBackend — VM-grade isolation via a Firecracker microVM (LLD #63 §6,
3
+ * Increment 4). Same `SandboxBackend` interface as the container backend; the
4
+ * difference is the boundary: a separate guest kernel over KVM rather than
5
+ * shared-kernel namespaces.
6
+ *
7
+ * The egress model is identical in spirit — the microVM's only route out is the
8
+ * governing proxy — but enforced on the *host* side, by a default-deny firewall
9
+ * on the guest's tap interface (the L2 rule shape, scoped to the guest's
10
+ * source address). That keeps the enforcement outside the guest, where the
11
+ * agent cannot touch it, which is stronger than the in-container firewall.
12
+ *
13
+ * Honesty status (see LLD #63 §7 + TECH_DEBT): the microVM *boots on real KVM*
14
+ * — validated on a GCE nested-virt host, where Firecracker loaded and ran the
15
+ * guest kernel through this exact config + API sequence (the launch script this
16
+ * backend invokes). What is NOT yet validated end-to-end is an agent running to
17
+ * completion *inside* a fully-booted guest: that needs a matched
18
+ * kernel+rootfs pair the operator supplies (as an OCI sandbox needs an image
19
+ * containing the agent). `health()` therefore gates on KVM + the firecracker
20
+ * binary + the operator-supplied kernel/rootfs, and refuses rather than
21
+ * pretend — it never falls back to a weaker backend.
22
+ *
23
+ * @module
24
+ */
25
+ import { spawn } from 'node:child_process';
26
+ import { existsSync } from 'node:fs';
27
+ import { fileURLToPath } from 'node:url';
28
+ import * as path from 'node:path';
29
+ import { log } from '../logger.js';
30
+ import { binaryOnPath } from '../binaryOnPath.js';
31
+ /**
32
+ * Build the Firecracker VM config. Pure and exported so the exact boot config
33
+ * — the one proven to boot a guest kernel on KVM — is asserted without a VM.
34
+ *
35
+ * The boot args are load-bearing: `root=/dev/vda rw` (the rootfs is the first
36
+ * virtio-blk device) and the kernel `ip=` directive that configures the guest's
37
+ * eth0 on the point-to-point tap link so its only reachable peer is the host.
38
+ */
39
+ export function buildFirecrackerConfig(opts) {
40
+ const netmask = prefixToNetmask(opts.prefixLen);
41
+ const bootArgs = 'console=ttyS0 reboot=k panic=1 pci=off root=/dev/vda rw ' +
42
+ `ip=${opts.guestIp}::${opts.hostIp}:${netmask}::eth0:off`;
43
+ return {
44
+ 'boot-source': { kernel_image_path: opts.kernelPath, boot_args: bootArgs },
45
+ drives: [
46
+ {
47
+ drive_id: 'rootfs',
48
+ path_on_host: opts.rootfsPath,
49
+ is_root_device: true,
50
+ is_read_only: false,
51
+ },
52
+ ],
53
+ 'network-interfaces': [{ iface_id: 'eth0', host_dev_name: opts.tapDevice }],
54
+ 'machine-config': { vcpu_count: opts.vcpus, mem_size_mib: opts.memMib },
55
+ };
56
+ }
57
+ /** Dotted-quad netmask for a prefix length (IPv4). */
58
+ export function prefixToNetmask(prefix) {
59
+ const mask = prefix === 0 ? 0 : (0xffffffff << (32 - prefix)) >>> 0;
60
+ return [24, 16, 8, 0].map((s) => (mask >>> s) & 0xff).join('.');
61
+ }
62
+ /** Path to the validated launch script shipped with the CLI. */
63
+ function launchScriptPath() {
64
+ // dist layout: dist/lib/sandbox/firecracker.js → ../../../resources/…
65
+ const here = path.dirname(fileURLToPath(import.meta.url));
66
+ return path.resolve(here, '../../../resources/sandbox/firecracker-launch.sh');
67
+ }
68
+ export class FirecrackerBackend {
69
+ name = 'firecracker';
70
+ opts;
71
+ env;
72
+ constructor(opts, env) {
73
+ this.opts = opts;
74
+ this.env = env;
75
+ }
76
+ /**
77
+ * Available only where a microVM can actually run: KVM present, the
78
+ * firecracker binary on PATH, and the operator's kernel + rootfs readable.
79
+ * Any of these missing → unavailable, and the caller refuses rather than
80
+ * downgrade (the honesty rule).
81
+ */
82
+ async health() {
83
+ if (!existsSync('/dev/kvm')) {
84
+ return { available: false, detail: 'no /dev/kvm (needs a KVM host; nested-virt on Intel)' };
85
+ }
86
+ if (!existsSync(this.opts.kernelPath)) {
87
+ return { available: false, detail: `guest kernel not found: ${this.opts.kernelPath}` };
88
+ }
89
+ if (!existsSync(this.opts.rootfsPath)) {
90
+ return { available: false, detail: `guest rootfs not found: ${this.opts.rootfsPath}` };
91
+ }
92
+ const hasBinary = await binaryOnPath('firecracker');
93
+ if (!hasBinary) {
94
+ return { available: false, detail: 'firecracker binary not on PATH' };
95
+ }
96
+ return { available: true, detail: 'kvm + firecracker + kernel + rootfs present' };
97
+ }
98
+ async run(spec) {
99
+ // The launch script is the artifact validated on real KVM: it sets up the
100
+ // tap, installs the host-side default-deny egress firewall for the guest,
101
+ // boots the microVM with the config above, runs the agent command in the
102
+ // guest, and tears everything down. run() is a thin, faithful invoker of it
103
+ // so the shipped boot path is exactly the proven one.
104
+ const script = launchScriptPath();
105
+ if (!existsSync(script)) {
106
+ log.error(`firecracker launch script missing: ${script}`);
107
+ return 1;
108
+ }
109
+ const args = [
110
+ script,
111
+ '--kernel', this.opts.kernelPath,
112
+ '--rootfs', this.opts.rootfsPath,
113
+ '--tap', this.opts.tapDevice,
114
+ '--guest-ip', this.opts.guestIp,
115
+ '--host-ip', this.opts.hostIp,
116
+ '--prefix', String(this.opts.prefixLen),
117
+ '--vcpus', String(this.opts.vcpus),
118
+ '--mem', String(this.opts.memMib),
119
+ '--allow', spec.allowCidrs.join(','),
120
+ '--', ...spec.command,
121
+ ];
122
+ return new Promise((resolve) => {
123
+ const child = spawn('bash', args, {
124
+ stdio: 'inherit',
125
+ env: { ...process.env, ...this.env },
126
+ });
127
+ child.on('error', (err) => {
128
+ log.error(`firecracker launch failed: ${err.message}`);
129
+ resolve(127);
130
+ });
131
+ child.on('exit', (code, signal) => resolve(signal ? 128 : (code ?? 0)));
132
+ });
133
+ }
134
+ }
135
+ //# sourceMappingURL=firecracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firecracker.js","sourceRoot":"","sources":["../../../src/lib/sandbox/firecracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Sandbox backend selection (LLD #63 §6).
3
+ *
4
+ * Picks the requested backend, or the best available one. The honesty rule:
5
+ * a backend whose `health()` is false is never silently swapped for a weaker
6
+ * one — the caller is told what is unavailable and why, and can decide.
7
+ *
8
+ * @module
9
+ */
10
+ import { type FirecrackerOptions } from './firecracker.js';
11
+ import { OciBackend, type OciRuntime } from './oci.js';
12
+ import type { SandboxBackend } from './types.js';
13
+ export * from './types.js';
14
+ export { buildOciArgs, OciBackend } from './oci.js';
15
+ export { buildFirecrackerConfig, FirecrackerBackend } from './firecracker.js';
16
+ export type SandboxKind = 'oci' | 'firecracker';
17
+ /**
18
+ * Resolve a container backend, preferring docker then podman. `env` holds the
19
+ * values the runtime will read for `--env NAME` references (proxy vars, keys).
20
+ */
21
+ export declare function ociBackend(env: Record<string, string>, runtime?: OciRuntime): OciBackend;
22
+ /**
23
+ * Firecracker options from env, with defaults. The kernel + rootfs are
24
+ * operator-supplied (INTUTIC_FC_KERNEL / INTUTIC_FC_ROOTFS), like an OCI image
25
+ * is operator-supplied — the backend's `health()` refuses if they are missing.
26
+ */
27
+ export declare function firecrackerOptionsFromEnv(env?: NodeJS.ProcessEnv): FirecrackerOptions;
28
+ /**
29
+ * Select a backend by kind. Both backends gate on their own `health()`; the
30
+ * caller refuses when a backend is unavailable rather than downgrading to a
31
+ * weaker one (the honesty rule, LLD #63 §6).
32
+ */
33
+ export declare function selectBackend(kind: SandboxKind, env: Record<string, string>, runtime?: OciRuntime): SandboxBackend;
34
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/sandbox/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAC9E,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAE7E,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,aAAa,CAAA;AAE/C;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,UAAU,CAExF;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,kBAAkB,CAWlG;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,OAAO,CAAC,EAAE,UAAU,GACnB,cAAc,CAShB"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Sandbox backend selection (LLD #63 §6).
3
+ *
4
+ * Picks the requested backend, or the best available one. The honesty rule:
5
+ * a backend whose `health()` is false is never silently swapped for a weaker
6
+ * one — the caller is told what is unavailable and why, and can decide.
7
+ *
8
+ * @module
9
+ */
10
+ import { FirecrackerBackend } from './firecracker.js';
11
+ import { OciBackend } from './oci.js';
12
+ export * from './types.js';
13
+ export { buildOciArgs, OciBackend } from './oci.js';
14
+ export { buildFirecrackerConfig, FirecrackerBackend } from './firecracker.js';
15
+ /**
16
+ * Resolve a container backend, preferring docker then podman. `env` holds the
17
+ * values the runtime will read for `--env NAME` references (proxy vars, keys).
18
+ */
19
+ export function ociBackend(env, runtime) {
20
+ return new OciBackend(runtime ?? 'docker', env);
21
+ }
22
+ /**
23
+ * Firecracker options from env, with defaults. The kernel + rootfs are
24
+ * operator-supplied (INTUTIC_FC_KERNEL / INTUTIC_FC_ROOTFS), like an OCI image
25
+ * is operator-supplied — the backend's `health()` refuses if they are missing.
26
+ */
27
+ export function firecrackerOptionsFromEnv(env = process.env) {
28
+ return {
29
+ kernelPath: env.INTUTIC_FC_KERNEL ?? '',
30
+ rootfsPath: env.INTUTIC_FC_ROOTFS ?? '',
31
+ tapDevice: env.INTUTIC_FC_TAP ?? 'tap-intutic',
32
+ guestIp: env.INTUTIC_FC_GUEST_IP ?? '172.16.0.2',
33
+ hostIp: env.INTUTIC_FC_HOST_IP ?? '172.16.0.1',
34
+ prefixLen: Number.parseInt(env.INTUTIC_FC_PREFIX ?? '30', 10),
35
+ vcpus: Number.parseInt(env.INTUTIC_FC_VCPUS ?? '1', 10),
36
+ memMib: Number.parseInt(env.INTUTIC_FC_MEM ?? '512', 10),
37
+ };
38
+ }
39
+ /**
40
+ * Select a backend by kind. Both backends gate on their own `health()`; the
41
+ * caller refuses when a backend is unavailable rather than downgrading to a
42
+ * weaker one (the honesty rule, LLD #63 §6).
43
+ */
44
+ export function selectBackend(kind, env, runtime) {
45
+ switch (kind) {
46
+ case 'oci':
47
+ return ociBackend(env, runtime);
48
+ case 'firecracker':
49
+ return new FirecrackerBackend(firecrackerOptionsFromEnv(), env);
50
+ default:
51
+ throw new Error(`unknown sandbox backend '${kind}'`);
52
+ }
53
+ }
54
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/sandbox/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,kBAAkB,EAA2B,MAAM,kBAAkB,CAAA;AAC9E,OAAO,EAAE,UAAU,EAAmB,MAAM,UAAU,CAAA;AAGtD,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAI7E;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,GAA2B,EAAE,OAAoB;IAC1E,OAAO,IAAI,UAAU,CAAC,OAAO,IAAI,QAAQ,EAAE,GAAG,CAAC,CAAA;AACjD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC5E,OAAO;QACL,UAAU,EAAE,GAAG,CAAC,iBAAiB,IAAI,EAAE;QACvC,UAAU,EAAE,GAAG,CAAC,iBAAiB,IAAI,EAAE;QACvC,SAAS,EAAE,GAAG,CAAC,cAAc,IAAI,aAAa;QAC9C,OAAO,EAAE,GAAG,CAAC,mBAAmB,IAAI,YAAY;QAChD,MAAM,EAAE,GAAG,CAAC,kBAAkB,IAAI,YAAY;QAC9C,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,IAAI,IAAI,EAAE,EAAE,CAAC;QAC7D,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,gBAAgB,IAAI,GAAG,EAAE,EAAE,CAAC;QACvD,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,IAAI,KAAK,EAAE,EAAE,CAAC;KACzD,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAiB,EACjB,GAA2B,EAC3B,OAAoB;IAEpB,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,KAAK;YACR,OAAO,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;QACjC,KAAK,aAAa;YAChB,OAAO,IAAI,kBAAkB,CAAC,yBAAyB,EAAE,EAAE,GAAG,CAAC,CAAA;QACjE;YACE,MAAM,IAAI,KAAK,CAAC,4BAA4B,IAAc,GAAG,CAAC,CAAA;IAClE,CAAC;AACH,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * OciBackend — a genuinely-isolating container sandbox (LLD #63 §6).
3
+ *
4
+ * The isolation envelope, and why each piece is here:
5
+ * --cap-drop=ALL start from zero capabilities
6
+ * --cap-add NET_ADMIN,NET_RAW the entrypoint needs them to install nft…
7
+ * --cap-add SETPCAP,SETUID,SETGID …and to drop those + switch user, after
8
+ * which the agent runs with an EMPTY cap set
9
+ * --security-opt no-new-privileges no setuid-root escalation
10
+ * --read-only + tmpfs immutable rootfs; scratch space in tmpfs
11
+ * --pids-limit/--memory/--cpus fork-bomb / resource-exhaustion bounds
12
+ * --add-host host.docker.internal:host-gateway reach the proxy on the host
13
+ * -v <workdir>:/work the project, the one writable mount
14
+ *
15
+ * The entrypoint (resources/sandbox/entrypoint.sh) then default-denies egress
16
+ * to everything except the proxy + DNS and drops privilege, so the agent cannot
17
+ * reach the network except through governance and cannot undo the firewall.
18
+ *
19
+ * @module
20
+ */
21
+ import type { SandboxBackend, SandboxHealth, SandboxSpec } from './types.js';
22
+ export type OciRuntime = 'docker' | 'podman';
23
+ /**
24
+ * Build the container runtime argv for a spec. Pure and exported so the
25
+ * envelope can be asserted without launching anything — the isolation flags are
26
+ * security-load-bearing and must not silently drift.
27
+ */
28
+ export declare function buildOciArgs(runtime: OciRuntime, spec: SandboxSpec): string[];
29
+ export declare class OciBackend implements SandboxBackend {
30
+ readonly name: string;
31
+ private readonly runtime;
32
+ /** Env values to hand the runtime process (referenced by name in argv). */
33
+ private readonly env;
34
+ constructor(runtime: OciRuntime, env: Record<string, string>);
35
+ health(): Promise<SandboxHealth>;
36
+ run(spec: SandboxSpec): Promise<number>;
37
+ }
38
+ //# sourceMappingURL=oci.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oci.d.ts","sourceRoot":"","sources":["../../../src/lib/sandbox/oci.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE5E,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAE5C;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,GAAG,MAAM,EAAE,CAoC7E;AAED,qBAAa,UAAW,YAAW,cAAc;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAY;IACpC,2EAA2E;IAC3E,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAwB;gBAEhC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAMtD,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC;IAgBhC,GAAG,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;CAuB9C"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * OciBackend — a genuinely-isolating container sandbox (LLD #63 §6).
3
+ *
4
+ * The isolation envelope, and why each piece is here:
5
+ * --cap-drop=ALL start from zero capabilities
6
+ * --cap-add NET_ADMIN,NET_RAW the entrypoint needs them to install nft…
7
+ * --cap-add SETPCAP,SETUID,SETGID …and to drop those + switch user, after
8
+ * which the agent runs with an EMPTY cap set
9
+ * --security-opt no-new-privileges no setuid-root escalation
10
+ * --read-only + tmpfs immutable rootfs; scratch space in tmpfs
11
+ * --pids-limit/--memory/--cpus fork-bomb / resource-exhaustion bounds
12
+ * --add-host host.docker.internal:host-gateway reach the proxy on the host
13
+ * -v <workdir>:/work the project, the one writable mount
14
+ *
15
+ * The entrypoint (resources/sandbox/entrypoint.sh) then default-denies egress
16
+ * to everything except the proxy + DNS and drops privilege, so the agent cannot
17
+ * reach the network except through governance and cannot undo the firewall.
18
+ *
19
+ * @module
20
+ */
21
+ import { spawn } from 'node:child_process';
22
+ import { log } from '../logger.js';
23
+ /**
24
+ * Build the container runtime argv for a spec. Pure and exported so the
25
+ * envelope can be asserted without launching anything — the isolation flags are
26
+ * security-load-bearing and must not silently drift.
27
+ */
28
+ export function buildOciArgs(runtime, spec) {
29
+ const args = ['run', '--rm'];
30
+ // -i always (pipe stdin); -t only when we have a real terminal.
31
+ args.push(spec.tty ? '-it' : '-i');
32
+ // Capability envelope: drop everything, add back only what the entrypoint
33
+ // needs to install the firewall and drop privilege.
34
+ args.push('--cap-drop=ALL');
35
+ for (const cap of ['NET_ADMIN', 'NET_RAW', 'SETPCAP', 'SETUID', 'SETGID']) {
36
+ args.push(`--cap-add=${cap}`);
37
+ }
38
+ args.push('--security-opt=no-new-privileges');
39
+ // Immutable rootfs with writable scratch.
40
+ args.push('--read-only');
41
+ for (const t of ['/tmp', '/run', '/home/sandbox'])
42
+ args.push('--tmpfs', t);
43
+ // Resource bounds.
44
+ args.push(`--pids-limit=${spec.pidsLimit}`);
45
+ args.push(`--memory=${spec.memory}`);
46
+ args.push(`--cpus=${spec.cpus}`);
47
+ // Reach the proxy on the host.
48
+ args.push(`--add-host=${spec.proxyHostAlias}:host-gateway`);
49
+ // The project, read-write; nothing else from the host.
50
+ args.push('-v', `${spec.workdir}:/work`, '-w', '/work');
51
+ // Env by name — values come from the launcher's environment at spawn time, so
52
+ // secrets never land in argv.
53
+ for (const key of spec.envKeys)
54
+ args.push('--env', key);
55
+ args.push(spec.image);
56
+ // The entrypoint consumes a leading `--` then execs the rest.
57
+ args.push('--', ...spec.command);
58
+ return args;
59
+ }
60
+ export class OciBackend {
61
+ name;
62
+ runtime;
63
+ /** Env values to hand the runtime process (referenced by name in argv). */
64
+ env;
65
+ constructor(runtime, env) {
66
+ this.runtime = runtime;
67
+ this.name = runtime;
68
+ this.env = env;
69
+ }
70
+ async health() {
71
+ return new Promise((resolve) => {
72
+ const child = spawn(this.runtime, ['info', '--format', '{{.ServerVersion}}'], {
73
+ stdio: ['ignore', 'ignore', 'ignore'],
74
+ });
75
+ child.on('error', () => resolve({ available: false, detail: `${this.runtime} not found on PATH` }));
76
+ child.on('exit', (code) => code === 0
77
+ ? resolve({ available: true, detail: `${this.runtime} daemon reachable` })
78
+ : resolve({ available: false, detail: `${this.runtime} daemon not reachable` }));
79
+ });
80
+ }
81
+ async run(spec) {
82
+ const args = buildOciArgs(this.runtime, spec);
83
+ log.dim(`sandbox: ${this.runtime} ${args.slice(0, 12).join(' ')} …`);
84
+ return new Promise((resolve) => {
85
+ const child = spawn(this.runtime, args, {
86
+ stdio: 'inherit',
87
+ // Values for the `--env NAME` references live here, not in argv.
88
+ env: { ...process.env, ...this.env },
89
+ });
90
+ child.on('error', (err) => {
91
+ if (err.code === 'ENOENT') {
92
+ log.error(`Sandbox runtime '${this.runtime}' not found. Install Docker or Podman.`);
93
+ }
94
+ else {
95
+ log.error(`Sandbox failed to start: ${err.message}`);
96
+ }
97
+ resolve(127);
98
+ });
99
+ child.on('exit', (code, signal) => {
100
+ if (signal)
101
+ resolve(128);
102
+ else
103
+ resolve(code ?? 0);
104
+ });
105
+ });
106
+ }
107
+ }
108
+ //# sourceMappingURL=oci.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oci.js","sourceRoot":"","sources":["../../../src/lib/sandbox/oci.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Sandbox runtime abstraction (LLD #63 §6).
3
+ *
4
+ * A `SandboxBackend` launches an agent command inside an isolated runtime whose
5
+ * *only* egress is the governing proxy — unifying "isolate the process" with
6
+ * "force traffic through governance". The container backend ships today; the
7
+ * Firecracker microVM backend implements the same interface (Increment 4).
8
+ *
9
+ * @module
10
+ */
11
+ /** What to run, and the isolation envelope to run it in. */
12
+ export interface SandboxSpec {
13
+ /** The agent command + args, e.g. ['claude'] or ['python', 'agent.py']. */
14
+ command: string[];
15
+ /** Host directory bind-mounted read-write at /work (the project). */
16
+ workdir: string;
17
+ /** Container image. Must contain the agent + nftables + capsh. */
18
+ image: string;
19
+ /**
20
+ * Environment for the sandboxed process, by name. Values are read from the
21
+ * launcher's own environment at spawn time and referenced by name on the
22
+ * command line, so secrets (API keys) never appear in argv / `docker inspect`.
23
+ */
24
+ envKeys: string[];
25
+ /** Hostname the sandbox reaches the proxy at (mapped to the host gateway). */
26
+ proxyHostAlias: string;
27
+ /** Extra destination CIDRs the sandbox may reach, beyond the proxy + DNS. */
28
+ allowCidrs: string[];
29
+ /** Hard resource caps. */
30
+ memory: string;
31
+ cpus: string;
32
+ pidsLimit: number;
33
+ /** Allocate a TTY (interactive agents). */
34
+ tty: boolean;
35
+ }
36
+ /** Health of a backend on this host. */
37
+ export interface SandboxHealth {
38
+ available: boolean;
39
+ detail: string;
40
+ }
41
+ export interface SandboxBackend {
42
+ readonly name: string;
43
+ /** Whether this backend can run here (e.g. docker reachable, KVM present). */
44
+ health(): Promise<SandboxHealth>;
45
+ /** Launch the spec; resolves with the process exit code. */
46
+ run(spec: SandboxSpec): Promise<number>;
47
+ }
48
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/sandbox/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,4DAA4D;AAC5D,MAAM,WAAW,WAAW;IAC1B,2EAA2E;IAC3E,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAA;IACf,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;IACb;;;;OAIG;IACH,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,8EAA8E;IAC9E,cAAc,EAAE,MAAM,CAAA;IACtB,6EAA6E;IAC7E,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,2CAA2C;IAC3C,GAAG,EAAE,OAAO,CAAA;CACb;AAED,wCAAwC;AACxC,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,8EAA8E;IAC9E,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC,CAAA;IAChC,4DAA4D;IAC5D,GAAG,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CACxC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Sandbox runtime abstraction (LLD #63 §6).
3
+ *
4
+ * A `SandboxBackend` launches an agent command inside an isolated runtime whose
5
+ * *only* egress is the governing proxy — unifying "isolate the process" with
6
+ * "force traffic through governance". The container backend ships today; the
7
+ * Firecracker microVM backend implements the same interface (Increment 4).
8
+ *
9
+ * @module
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/lib/sandbox/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
@@ -0,0 +1,50 @@
1
+ export type SopRiskTier = 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
2
+ export interface ParsedSopFile {
3
+ /** From a `title:` front-matter key, else the file's first `# ` heading, else `null` — the caller falls back to the file name. */
4
+ title: string | null;
5
+ /** From a `risk_tier:` key, case-insensitively; `null` if unstated or unrecognised — never guessed. */
6
+ riskTier: SopRiskTier | null;
7
+ /** From a `version:` key; `null` if unstated. */
8
+ version: string | null;
9
+ /**
10
+ * From a `content_hash:` key — `intutic sops pull`'s own dirty-check
11
+ * marker, recording the body hash at the moment it wrote the file. `null`
12
+ * for a file `pull` never wrote (hand-authored, or pushed but not pulled).
13
+ */
14
+ contentHash: string | null;
15
+ /** Everything after the front-matter fence, or the whole trimmed input when there is none. */
16
+ body: string;
17
+ }
18
+ export declare function parseSopFile(raw: string): ParsedSopFile;
19
+ /**
20
+ * Render a pulled SOP back into a front-matter-carrying file, with
21
+ * `content_hash:` recording `sha256(body)` at write time — the marker
22
+ * `runSopsPull` compares against on a later pull to tell "the DB changed
23
+ * upstream" (safe to overwrite) from "a human hand-edited this file since
24
+ * the last pull" (refuse without `--force`).
25
+ */
26
+ export declare function renderSopFile(sop: {
27
+ title: string;
28
+ riskTier: string;
29
+ version: string;
30
+ body: string;
31
+ }): string;
32
+ /** `Deploy Checklist` / `deploy checklist!!` → `deploy-checklist`. */
33
+ export declare function slugifyTitle(title: string): string;
34
+ /** `postgres-migration` → `Postgres Migration`; `deploy_checklist.md` → `Deploy Checklist`. */
35
+ export declare function titleFromFileName(fileName: string): string;
36
+ /**
37
+ * Add `intutic sops pull`'s `content_hash:` marker to a file that already
38
+ * carries its own front matter — a projected guardrail, whose fence holds
39
+ * the enforcing keys the proxy reads (LLD #71, Wave 9).
40
+ *
41
+ * Not `renderSopFile`: that wraps a second fence around the text, and the
42
+ * proxy reads only the first, so the enforcing keys would become body prose
43
+ * and the rule would load, be listed, and never fire. The marker goes INSIDE
44
+ * the existing fence, as the last line before it closes; the hash is over
45
+ * what `parseSopFile` will read back as `body`, so the dirty check is the
46
+ * same one `sops pull` runs. A file with no fence gets one holding only the
47
+ * marker. Unknown keys are inert to the proxy, so enforcement is unchanged.
48
+ */
49
+ export declare function withContentHash(raw: string): string;
50
+ //# sourceMappingURL=sopFrontMatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sopFrontMatter.d.ts","sourceRoot":"","sources":["../../src/lib/sopFrontMatter.ts"],"names":[],"mappings":"AAkBA,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAA;AAIhE,MAAM,WAAW,aAAa;IAC5B,kIAAkI;IAClI,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,uGAAuG;IACvG,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAA;IAC5B,iDAAiD;IACjD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB;;;;OAIG;IACH,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,8FAA8F;IAC9F,IAAI,EAAE,MAAM,CAAA;CACb;AAaD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAkCvD;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,MAAM,CAaT;AAED,sEAAsE;AACtE,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOlD;AAED,+FAA+F;AAC/F,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO1D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAcnD"}