@elie-laloum/outpost 5.0.0 → 7.0.0

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 (647) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +11 -11
  3. package/SECURITY.md +10 -0
  4. package/dist/adapters/agents/antigravity-adapter.d.ts +3 -0
  5. package/dist/adapters/agents/antigravity-adapter.js +41 -0
  6. package/dist/adapters/agents/antigravity-adapter.js.map +1 -0
  7. package/dist/adapters/agents/antigravity-authentication.d.ts +2 -0
  8. package/dist/adapters/agents/antigravity-authentication.js +27 -0
  9. package/dist/adapters/agents/antigravity-authentication.js.map +1 -0
  10. package/dist/adapters/agents/antigravity-diagnostics.d.ts +1 -0
  11. package/dist/adapters/agents/antigravity-diagnostics.js +6 -0
  12. package/dist/adapters/agents/antigravity-diagnostics.js.map +1 -0
  13. package/dist/adapters/agents/antigravity-events.d.ts +2 -0
  14. package/dist/adapters/agents/antigravity-events.js +75 -0
  15. package/dist/adapters/agents/antigravity-events.js.map +1 -0
  16. package/dist/adapters/agents/antigravity-request.d.ts +5 -0
  17. package/dist/adapters/agents/antigravity-request.js +37 -0
  18. package/dist/adapters/agents/antigravity-request.js.map +1 -0
  19. package/dist/adapters/agents/antigravity.constants.d.ts +3 -0
  20. package/dist/adapters/agents/antigravity.constants.js +4 -0
  21. package/dist/adapters/agents/antigravity.constants.js.map +1 -0
  22. package/dist/adapters/agents/{gemini.types.d.ts → antigravity.types.d.ts} +2 -2
  23. package/dist/adapters/agents/antigravity.types.js +2 -0
  24. package/dist/adapters/agents/antigravity.types.js.map +1 -0
  25. package/dist/adapters/agents/authentication.constants.d.ts +19 -9
  26. package/dist/adapters/agents/authentication.constants.js +12 -9
  27. package/dist/adapters/agents/authentication.constants.js.map +1 -1
  28. package/dist/adapters/agents/authentication.d.ts +11 -2
  29. package/dist/adapters/agents/authentication.js +70 -47
  30. package/dist/adapters/agents/authentication.js.map +1 -1
  31. package/dist/adapters/agents/authentication.types.d.ts +20 -0
  32. package/dist/adapters/agents/authentication.types.js +2 -0
  33. package/dist/adapters/agents/authentication.types.js.map +1 -0
  34. package/dist/adapters/agents/claude-adapter.js +4 -2
  35. package/dist/adapters/agents/claude-adapter.js.map +1 -1
  36. package/dist/adapters/agents/claude-authentication.d.ts +2 -0
  37. package/dist/adapters/agents/claude-authentication.js +34 -0
  38. package/dist/adapters/agents/claude-authentication.js.map +1 -0
  39. package/dist/adapters/agents/claude-events.js +52 -9
  40. package/dist/adapters/agents/claude-events.js.map +1 -1
  41. package/dist/adapters/agents/claude-request.js +2 -0
  42. package/dist/adapters/agents/claude-request.js.map +1 -1
  43. package/dist/adapters/agents/cli-diagnostics.constants.d.ts +6 -6
  44. package/dist/adapters/agents/cli-diagnostics.constants.js +6 -6
  45. package/dist/adapters/agents/cli-diagnostics.constants.js.map +1 -1
  46. package/dist/adapters/agents/cli-diagnostics.d.ts +1 -0
  47. package/dist/adapters/agents/cli-diagnostics.js +18 -0
  48. package/dist/adapters/agents/cli-diagnostics.js.map +1 -1
  49. package/dist/adapters/agents/codex-adapter.js +4 -2
  50. package/dist/adapters/agents/codex-adapter.js.map +1 -1
  51. package/dist/adapters/agents/codex-authentication.d.ts +3 -0
  52. package/dist/adapters/agents/codex-authentication.js +47 -0
  53. package/dist/adapters/agents/codex-authentication.js.map +1 -0
  54. package/dist/adapters/agents/codex-events.js +28 -2
  55. package/dist/adapters/agents/codex-events.js.map +1 -1
  56. package/dist/adapters/agents/copilot-adapter.d.ts +3 -0
  57. package/dist/adapters/agents/copilot-adapter.js +45 -0
  58. package/dist/adapters/agents/copilot-adapter.js.map +1 -0
  59. package/dist/adapters/agents/copilot-authentication.d.ts +2 -0
  60. package/dist/adapters/agents/copilot-authentication.js +46 -0
  61. package/dist/adapters/agents/copilot-authentication.js.map +1 -0
  62. package/dist/adapters/agents/copilot-diagnostics.d.ts +1 -0
  63. package/dist/adapters/agents/copilot-diagnostics.js +6 -0
  64. package/dist/adapters/agents/copilot-diagnostics.js.map +1 -0
  65. package/dist/adapters/agents/copilot-events.d.ts +2 -0
  66. package/dist/adapters/agents/copilot-events.js +66 -0
  67. package/dist/adapters/agents/copilot-events.js.map +1 -0
  68. package/dist/adapters/agents/copilot-request.d.ts +5 -0
  69. package/dist/adapters/agents/copilot-request.js +24 -0
  70. package/dist/adapters/agents/copilot-request.js.map +1 -0
  71. package/dist/adapters/agents/copilot-usage.d.ts +3 -0
  72. package/dist/adapters/agents/copilot-usage.js +19 -0
  73. package/dist/adapters/agents/copilot-usage.js.map +1 -0
  74. package/dist/adapters/agents/copilot.types.d.ts +6 -0
  75. package/dist/adapters/agents/copilot.types.js +2 -0
  76. package/dist/adapters/agents/copilot.types.js.map +1 -0
  77. package/dist/adapters/agents/event-decoder.d.ts +2 -2
  78. package/dist/adapters/agents/event-decoder.js +6 -5
  79. package/dist/adapters/agents/event-decoder.js.map +1 -1
  80. package/dist/adapters/agents/kimi-adapter.d.ts +3 -0
  81. package/dist/adapters/agents/kimi-adapter.js +51 -0
  82. package/dist/adapters/agents/kimi-adapter.js.map +1 -0
  83. package/dist/adapters/agents/kimi-authentication.d.ts +3 -0
  84. package/dist/adapters/agents/kimi-authentication.js +63 -0
  85. package/dist/adapters/agents/kimi-authentication.js.map +1 -0
  86. package/dist/adapters/agents/kimi-diagnostics.d.ts +2 -0
  87. package/dist/adapters/agents/kimi-diagnostics.js +14 -0
  88. package/dist/adapters/agents/kimi-diagnostics.js.map +1 -0
  89. package/dist/adapters/agents/kimi-events.d.ts +2 -0
  90. package/dist/adapters/agents/kimi-events.js +55 -0
  91. package/dist/adapters/agents/kimi-events.js.map +1 -0
  92. package/dist/adapters/agents/kimi-fork.d.ts +2 -0
  93. package/dist/adapters/agents/kimi-fork.js +11 -0
  94. package/dist/adapters/agents/kimi-fork.js.map +1 -0
  95. package/dist/adapters/agents/{gemini-request.d.ts → kimi-request.d.ts} +2 -2
  96. package/dist/adapters/agents/kimi-request.js +33 -0
  97. package/dist/adapters/agents/kimi-request.js.map +1 -0
  98. package/dist/adapters/agents/kimi-usage.d.ts +2 -0
  99. package/dist/adapters/agents/kimi-usage.js +7 -0
  100. package/dist/adapters/agents/kimi-usage.js.map +1 -0
  101. package/dist/adapters/agents/kimi.constants.d.ts +13 -0
  102. package/dist/adapters/agents/kimi.constants.js +14 -0
  103. package/dist/adapters/agents/kimi.constants.js.map +1 -0
  104. package/dist/adapters/agents/kimi.types.d.ts +7 -0
  105. package/dist/adapters/agents/kimi.types.js +2 -0
  106. package/dist/adapters/agents/kimi.types.js.map +1 -0
  107. package/dist/adapters/agents/model-support.constants.d.ts +3 -1
  108. package/dist/adapters/agents/model-support.constants.js +12 -2
  109. package/dist/adapters/agents/model-support.constants.js.map +1 -1
  110. package/dist/adapters/agents/protocol-fixtures.constants.d.ts +2 -2
  111. package/dist/adapters/agents/protocol-fixtures.constants.js +131 -9
  112. package/dist/adapters/agents/protocol-fixtures.constants.js.map +1 -1
  113. package/dist/adapters/agents/protocol-fixtures.types.d.ts +1 -0
  114. package/dist/adapters/agents/protocol-fixtures.types.js.map +1 -1
  115. package/dist/adapters/agents/protocol.d.ts +1 -0
  116. package/dist/adapters/agents/protocol.js +9 -0
  117. package/dist/adapters/agents/protocol.js.map +1 -1
  118. package/dist/adapters/agents/session-usage.constants.d.ts +10 -0
  119. package/dist/adapters/agents/session-usage.constants.js +110 -0
  120. package/dist/adapters/agents/session-usage.constants.js.map +1 -0
  121. package/dist/adapters/agents/session-usage.d.ts +5 -0
  122. package/dist/adapters/agents/session-usage.js +45 -0
  123. package/dist/adapters/agents/session-usage.js.map +1 -0
  124. package/dist/adapters/agents/settings.types.d.ts +1 -0
  125. package/dist/adapters/agents/settings.types.js.map +1 -1
  126. package/dist/adapters/agents/tool-result.d.ts +2 -0
  127. package/dist/adapters/agents/tool-result.js +17 -0
  128. package/dist/adapters/agents/tool-result.js.map +1 -0
  129. package/dist/adapters/models/anthropic-response.js +3 -0
  130. package/dist/adapters/models/anthropic-response.js.map +1 -1
  131. package/dist/adapters/models/http-provider.js +6 -1
  132. package/dist/adapters/models/http-provider.js.map +1 -1
  133. package/dist/adapters/models/openai-responses.js +10 -0
  134. package/dist/adapters/models/openai-responses.js.map +1 -1
  135. package/dist/adapters/models/retry-after.d.ts +1 -0
  136. package/dist/adapters/models/retry-after.js +16 -0
  137. package/dist/adapters/models/retry-after.js.map +1 -0
  138. package/dist/application/activity-watchdog.js +1 -2
  139. package/dist/application/activity-watchdog.js.map +1 -1
  140. package/dist/application/agent-authentication.d.ts +4 -0
  141. package/dist/application/agent-authentication.js +32 -0
  142. package/dist/application/agent-authentication.js.map +1 -0
  143. package/dist/application/agent-bootstrap.constants.d.ts +2 -5
  144. package/dist/application/agent-bootstrap.constants.js +27 -4
  145. package/dist/application/agent-bootstrap.constants.js.map +1 -1
  146. package/dist/application/agent-bootstrap.js +39 -12
  147. package/dist/application/agent-bootstrap.js.map +1 -1
  148. package/dist/application/agent-bootstrap.types.d.ts +19 -0
  149. package/dist/application/agent-bootstrap.types.js +2 -0
  150. package/dist/application/agent-bootstrap.types.js.map +1 -0
  151. package/dist/application/agent-output.js +74 -8
  152. package/dist/application/agent-output.js.map +1 -1
  153. package/dist/application/agent-request.d.ts +3 -0
  154. package/dist/application/agent-request.js +11 -0
  155. package/dist/application/agent-request.js.map +1 -0
  156. package/dist/application/agent-turn.js +74 -6
  157. package/dist/application/agent-turn.js.map +1 -1
  158. package/dist/application/agent-usage.d.ts +6 -0
  159. package/dist/application/agent-usage.js +57 -0
  160. package/dist/application/agent-usage.js.map +1 -0
  161. package/dist/application/attach.js +2 -0
  162. package/dist/application/attach.js.map +1 -1
  163. package/dist/application/credential-installer.constants.d.ts +1 -0
  164. package/dist/application/credential-installer.constants.js +22 -0
  165. package/dist/application/credential-installer.constants.js.map +1 -0
  166. package/dist/application/custom-turn.js +44 -49
  167. package/dist/application/custom-turn.js.map +1 -1
  168. package/dist/application/dispatch-observation.d.ts +1 -1
  169. package/dist/application/dispatch-observation.js +141 -21
  170. package/dist/application/dispatch-observation.js.map +1 -1
  171. package/dist/application/dispatch-observation.types.d.ts +2 -0
  172. package/dist/application/dispatch-observation.types.js.map +1 -1
  173. package/dist/application/dispatch-validation.js +2 -0
  174. package/dist/application/dispatch-validation.js.map +1 -1
  175. package/dist/application/dispatch.js +1 -1
  176. package/dist/application/dispatch.js.map +1 -1
  177. package/dist/application/doctor-agent.constants.d.ts +2 -8
  178. package/dist/application/doctor-agent.constants.js +43 -6
  179. package/dist/application/doctor-agent.constants.js.map +1 -1
  180. package/dist/application/doctor-agent.d.ts +2 -1
  181. package/dist/application/doctor-agent.js +15 -3
  182. package/dist/application/doctor-agent.js.map +1 -1
  183. package/dist/application/doctor-image.js +4 -6
  184. package/dist/application/doctor-image.js.map +1 -1
  185. package/dist/application/doctor-protocol.js +6 -11
  186. package/dist/application/doctor-protocol.js.map +1 -1
  187. package/dist/application/doctor-protocol.types.d.ts +1 -1
  188. package/dist/application/doctor-protocol.types.js.map +1 -1
  189. package/dist/application/doctor-sandbox.js +2 -5
  190. package/dist/application/doctor-sandbox.js.map +1 -1
  191. package/dist/application/doctor.js +28 -10
  192. package/dist/application/doctor.js.map +1 -1
  193. package/dist/application/doctor.types.d.ts +10 -1
  194. package/dist/application/doctor.types.js.map +1 -1
  195. package/dist/application/execution.constants.d.ts +2 -0
  196. package/dist/application/execution.constants.js +2 -0
  197. package/dist/application/execution.constants.js.map +1 -1
  198. package/dist/application/execution.types.d.ts +8 -0
  199. package/dist/application/execution.types.js.map +1 -1
  200. package/dist/application/harness-budget.d.ts +3 -0
  201. package/dist/application/harness-budget.js +42 -0
  202. package/dist/application/harness-budget.js.map +1 -0
  203. package/dist/application/harness-budget.types.d.ts +5 -0
  204. package/dist/application/harness-budget.types.js +2 -0
  205. package/dist/application/harness-budget.types.js.map +1 -0
  206. package/dist/application/harness-hooks.js +34 -3
  207. package/dist/application/harness-hooks.js.map +1 -1
  208. package/dist/application/harness-loop.js +52 -24
  209. package/dist/application/harness-loop.js.map +1 -1
  210. package/dist/application/harness-model-provider.d.ts +3 -0
  211. package/dist/application/harness-model-provider.js +49 -0
  212. package/dist/application/harness-model-provider.js.map +1 -0
  213. package/dist/application/harness-model-provider.types.d.ts +10 -0
  214. package/dist/application/harness-model-provider.types.js +2 -0
  215. package/dist/application/harness-model-provider.types.js.map +1 -0
  216. package/dist/application/harness-subagent.d.ts +4 -0
  217. package/dist/application/harness-subagent.js +110 -0
  218. package/dist/application/harness-subagent.js.map +1 -0
  219. package/dist/application/harness.types.d.ts +11 -0
  220. package/dist/application/harness.types.js.map +1 -1
  221. package/dist/application/lifecycle-hooks.d.ts +1 -1
  222. package/dist/application/lifecycle-hooks.js +5 -4
  223. package/dist/application/lifecycle-hooks.js.map +1 -1
  224. package/dist/application/observed-lease.d.ts +3 -0
  225. package/dist/application/observed-lease.js +26 -0
  226. package/dist/application/observed-lease.js.map +1 -0
  227. package/dist/application/outpost.types.d.ts +3 -1
  228. package/dist/application/outpost.types.js.map +1 -1
  229. package/dist/application/output-lines.d.ts +4 -0
  230. package/dist/application/output-lines.js +28 -0
  231. package/dist/application/output-lines.js.map +1 -0
  232. package/dist/application/queue-worker.js +1 -1
  233. package/dist/application/queue-worker.js.map +1 -1
  234. package/dist/application/queue-worker.types.d.ts +1 -0
  235. package/dist/application/queue-worker.types.js.map +1 -1
  236. package/dist/application/queued-task.js +24 -5
  237. package/dist/application/queued-task.js.map +1 -1
  238. package/dist/application/recovery-archive.d.ts +3 -2
  239. package/dist/application/recovery-archive.js +9 -2
  240. package/dist/application/recovery-archive.js.map +1 -1
  241. package/dist/application/recovery-restore.d.ts +3 -2
  242. package/dist/application/recovery-restore.js +9 -2
  243. package/dist/application/recovery-restore.js.map +1 -1
  244. package/dist/application/recovery-retention.d.ts +3 -2
  245. package/dist/application/recovery-retention.js +74 -26
  246. package/dist/application/recovery-retention.js.map +1 -1
  247. package/dist/application/remote-workspace.js +5 -4
  248. package/dist/application/remote-workspace.js.map +1 -1
  249. package/dist/application/remote-workspace.types.d.ts +1 -0
  250. package/dist/application/remote-workspace.types.js.map +1 -1
  251. package/dist/application/sandbox-agents.js +19 -19
  252. package/dist/application/sandbox-agents.js.map +1 -1
  253. package/dist/application/sandbox-attach.js +12 -3
  254. package/dist/application/sandbox-attach.js.map +1 -1
  255. package/dist/application/sandbox-dispatch.js +13 -27
  256. package/dist/application/sandbox-dispatch.js.map +1 -1
  257. package/dist/application/sandbox-provision.js +15 -9
  258. package/dist/application/sandbox-provision.js.map +1 -1
  259. package/dist/application/sandbox-session.types.d.ts +7 -2
  260. package/dist/application/sandbox-session.types.js.map +1 -1
  261. package/dist/application/sandbox.js +13 -6
  262. package/dist/application/sandbox.js.map +1 -1
  263. package/dist/application/speculation-checkpoint.d.ts +6 -0
  264. package/dist/application/speculation-checkpoint.js +206 -0
  265. package/dist/application/speculation-checkpoint.js.map +1 -0
  266. package/dist/application/speculation-checkpoint.types.d.ts +24 -0
  267. package/dist/application/speculation-checkpoint.types.js +2 -0
  268. package/dist/application/speculation-checkpoint.types.js.map +1 -0
  269. package/dist/application/speculation-integration.constants.d.ts +4 -0
  270. package/dist/application/speculation-integration.constants.js +5 -0
  271. package/dist/application/speculation-integration.constants.js.map +1 -0
  272. package/dist/application/speculation-integration.d.ts +2 -0
  273. package/dist/application/speculation-integration.js +67 -0
  274. package/dist/application/speculation-integration.js.map +1 -0
  275. package/dist/application/speculation-resume.d.ts +4 -0
  276. package/dist/application/speculation-resume.js +71 -0
  277. package/dist/application/speculation-resume.js.map +1 -0
  278. package/dist/application/speculation-run.d.ts +4 -0
  279. package/dist/application/speculation-run.js +320 -0
  280. package/dist/application/speculation-run.js.map +1 -0
  281. package/dist/application/speculation-timeout.d.ts +1 -0
  282. package/dist/application/speculation-timeout.js +15 -0
  283. package/dist/application/speculation-timeout.js.map +1 -0
  284. package/dist/application/speculation.constants.d.ts +1 -0
  285. package/dist/application/speculation.constants.js +5 -1
  286. package/dist/application/speculation.constants.js.map +1 -1
  287. package/dist/application/speculation.js +41 -149
  288. package/dist/application/speculation.js.map +1 -1
  289. package/dist/application/speculation.types.d.ts +23 -0
  290. package/dist/application/speculation.types.js.map +1 -1
  291. package/dist/application/startup-recovery.js +14 -1
  292. package/dist/application/startup-recovery.js.map +1 -1
  293. package/dist/application/startup-recovery.types.d.ts +1 -0
  294. package/dist/application/startup-recovery.types.js.map +1 -1
  295. package/dist/application/stop-reason.d.ts +2 -0
  296. package/dist/application/stop-reason.js +21 -0
  297. package/dist/application/stop-reason.js.map +1 -0
  298. package/dist/application/stop-reason.types.d.ts +4 -0
  299. package/dist/application/stop-reason.types.js +2 -0
  300. package/dist/application/stop-reason.types.js.map +1 -0
  301. package/dist/application/storage-reservation.js +9 -2
  302. package/dist/application/storage-reservation.js.map +1 -1
  303. package/dist/application/task-observation.d.ts +3 -0
  304. package/dist/application/task-observation.js +22 -0
  305. package/dist/application/task-observation.js.map +1 -0
  306. package/dist/application/task-usage.js +5 -12
  307. package/dist/application/task-usage.js.map +1 -1
  308. package/dist/application/tasks.js +41 -16
  309. package/dist/application/tasks.js.map +1 -1
  310. package/dist/application/tool-execution.js +42 -19
  311. package/dist/application/tool-execution.js.map +1 -1
  312. package/dist/application/workspace.js +6 -4
  313. package/dist/application/workspace.js.map +1 -1
  314. package/dist/cli/doctor-command.js +6 -2
  315. package/dist/cli/doctor-command.js.map +1 -1
  316. package/dist/cli/init-authentication.d.ts +4 -1
  317. package/dist/cli/init-authentication.js +28 -33
  318. package/dist/cli/init-authentication.js.map +1 -1
  319. package/dist/cli/init-command.js +3 -3
  320. package/dist/cli/init-command.js.map +1 -1
  321. package/dist/cli/main.constants.d.ts +50 -13
  322. package/dist/cli/main.constants.js +70 -8
  323. package/dist/cli/main.constants.js.map +1 -1
  324. package/dist/cli/main.js +2 -1
  325. package/dist/cli/main.js.map +1 -1
  326. package/dist/cli/scaffold-files.js +1 -1
  327. package/dist/cli/scaffold-files.js.map +1 -1
  328. package/dist/cli/scaffold-validation.js +29 -22
  329. package/dist/cli/scaffold-validation.js.map +1 -1
  330. package/dist/cli/scaffold.constants.d.ts +0 -1
  331. package/dist/cli/scaffold.constants.js +6 -2
  332. package/dist/cli/scaffold.constants.js.map +1 -1
  333. package/dist/cli/scaffold.types.d.ts +8 -2
  334. package/dist/cli/scaffold.types.js.map +1 -1
  335. package/dist/cli/starters.js +1 -3
  336. package/dist/cli/starters.js.map +1 -1
  337. package/dist/domain/agent-observation.d.ts +4 -0
  338. package/dist/domain/agent-observation.js +27 -0
  339. package/dist/domain/agent-observation.js.map +1 -0
  340. package/dist/domain/agent.types.d.ts +122 -14
  341. package/dist/domain/agent.types.js.map +1 -1
  342. package/dist/domain/authentication.constants.d.ts +3 -0
  343. package/dist/domain/authentication.constants.js +11 -0
  344. package/dist/domain/authentication.constants.js.map +1 -0
  345. package/dist/domain/authentication.d.ts +3 -0
  346. package/dist/domain/authentication.js +22 -0
  347. package/dist/domain/authentication.js.map +1 -0
  348. package/dist/domain/authentication.types.d.ts +5 -0
  349. package/dist/domain/authentication.types.js +2 -0
  350. package/dist/domain/authentication.types.js.map +1 -0
  351. package/dist/domain/harness.d.ts +2 -2
  352. package/dist/domain/harness.js +6 -0
  353. package/dist/domain/harness.js.map +1 -1
  354. package/dist/domain/harness.types.d.ts +4 -3
  355. package/dist/domain/harness.types.js.map +1 -1
  356. package/dist/domain/model.types.d.ts +8 -0
  357. package/dist/domain/model.types.js.map +1 -1
  358. package/dist/domain/observation.constants.d.ts +8 -0
  359. package/dist/domain/observation.constants.js +9 -0
  360. package/dist/domain/observation.constants.js.map +1 -0
  361. package/dist/domain/observation.d.ts +2 -0
  362. package/dist/domain/observation.js +190 -0
  363. package/dist/domain/observation.js.map +1 -0
  364. package/dist/domain/observation.types.d.ts +84 -0
  365. package/dist/domain/observation.types.js +2 -0
  366. package/dist/domain/observation.types.js.map +1 -0
  367. package/dist/domain/observed-operation.d.ts +2 -0
  368. package/dist/domain/observed-operation.js +30 -0
  369. package/dist/domain/observed-operation.js.map +1 -0
  370. package/dist/domain/sandbox.types.d.ts +2 -0
  371. package/dist/domain/sandbox.types.js.map +1 -1
  372. package/dist/domain/subagent.constants.d.ts +13 -0
  373. package/dist/domain/subagent.constants.js +9 -0
  374. package/dist/domain/subagent.constants.js.map +1 -0
  375. package/dist/domain/subagent.d.ts +4 -0
  376. package/dist/domain/subagent.js +28 -0
  377. package/dist/domain/subagent.js.map +1 -0
  378. package/dist/domain/subagent.types.d.ts +13 -0
  379. package/dist/domain/subagent.types.js +2 -0
  380. package/dist/domain/subagent.types.js.map +1 -0
  381. package/dist/domain/transcript.types.d.ts +2 -0
  382. package/dist/domain/transcript.types.js.map +1 -1
  383. package/dist/domain/usage.d.ts +1 -0
  384. package/dist/domain/usage.js +16 -0
  385. package/dist/domain/usage.js.map +1 -1
  386. package/dist/domain/workflow/budget.d.ts +7 -3
  387. package/dist/domain/workflow/budget.js +26 -0
  388. package/dist/domain/workflow/budget.js.map +1 -1
  389. package/dist/domain/workflow/budget.types.d.ts +1 -1
  390. package/dist/domain/workflow/budget.types.js.map +1 -1
  391. package/dist/domain/workflow/checkpoint-validation.js +7 -1
  392. package/dist/domain/workflow/checkpoint-validation.js.map +1 -1
  393. package/dist/domain/workflow/checkpoint.js +3 -0
  394. package/dist/domain/workflow/checkpoint.js.map +1 -1
  395. package/dist/domain/workflow/gate-validation.js +14 -1
  396. package/dist/domain/workflow/gate-validation.js.map +1 -1
  397. package/dist/domain/workflow/gates.d.ts +1 -1
  398. package/dist/domain/workflow/gates.js +52 -4
  399. package/dist/domain/workflow/gates.js.map +1 -1
  400. package/dist/domain/workflow/gates.types.d.ts +15 -1
  401. package/dist/domain/workflow/gates.types.js.map +1 -1
  402. package/dist/domain/workflow/idempotency.d.ts +1 -0
  403. package/dist/domain/workflow/idempotency.js +7 -0
  404. package/dist/domain/workflow/idempotency.js.map +1 -0
  405. package/dist/domain/workflow/retry.constants.d.ts +2 -0
  406. package/dist/domain/workflow/retry.constants.js +3 -0
  407. package/dist/domain/workflow/retry.constants.js.map +1 -0
  408. package/dist/domain/workflow/retry.d.ts +4 -0
  409. package/dist/domain/workflow/retry.js +49 -0
  410. package/dist/domain/workflow/retry.js.map +1 -0
  411. package/dist/domain/workflow/task-runner.js +9 -5
  412. package/dist/domain/workflow/task-runner.js.map +1 -1
  413. package/dist/domain/workflow/task.js +6 -6
  414. package/dist/domain/workflow/task.js.map +1 -1
  415. package/dist/domain/workflow/workflow-scheduler.js +110 -72
  416. package/dist/domain/workflow/workflow-scheduler.js.map +1 -1
  417. package/dist/domain/workflow/workflow-state.js +28 -12
  418. package/dist/domain/workflow/workflow-state.js.map +1 -1
  419. package/dist/domain/workflow.d.ts +1 -1
  420. package/dist/domain/workflow.js +1 -1
  421. package/dist/domain/workflow.js.map +1 -1
  422. package/dist/domain/workflow.types.d.ts +13 -2
  423. package/dist/domain/workflow.types.js.map +1 -1
  424. package/dist/index.d.ts +16 -11
  425. package/dist/index.js +7 -4
  426. package/dist/index.js.map +1 -1
  427. package/dist/infrastructure/conversations/capture.js +10 -0
  428. package/dist/infrastructure/conversations/capture.js.map +1 -1
  429. package/dist/infrastructure/conversations/harness-transcript.js +6 -0
  430. package/dist/infrastructure/conversations/harness-transcript.js.map +1 -1
  431. package/dist/infrastructure/conversations/harness-transcript.types.d.ts +2 -0
  432. package/dist/infrastructure/conversations/harness-transcript.types.js.map +1 -1
  433. package/dist/infrastructure/conversations/layout.js +2 -0
  434. package/dist/infrastructure/conversations/layout.js.map +1 -1
  435. package/dist/infrastructure/conversations/locate.js +7 -1
  436. package/dist/infrastructure/conversations/locate.js.map +1 -1
  437. package/dist/infrastructure/conversations/native-store.js +8 -1
  438. package/dist/infrastructure/conversations/native-store.js.map +1 -1
  439. package/dist/infrastructure/conversations/paths.js +3 -0
  440. package/dist/infrastructure/conversations/paths.js.map +1 -1
  441. package/dist/infrastructure/conversations/restore.js +7 -0
  442. package/dist/infrastructure/conversations/restore.js.map +1 -1
  443. package/dist/infrastructure/conversations/session-bundle.constants.d.ts +5 -0
  444. package/dist/infrastructure/conversations/session-bundle.constants.js +173 -0
  445. package/dist/infrastructure/conversations/session-bundle.constants.js.map +1 -0
  446. package/dist/infrastructure/conversations/session-bundle.d.ts +6 -0
  447. package/dist/infrastructure/conversations/session-bundle.js +98 -0
  448. package/dist/infrastructure/conversations/session-bundle.js.map +1 -0
  449. package/dist/infrastructure/conversations/session-bundle.types.d.ts +1 -0
  450. package/dist/infrastructure/conversations/session-bundle.types.js +2 -0
  451. package/dist/infrastructure/conversations/session-bundle.types.js.map +1 -0
  452. package/dist/infrastructure/conversations.js +4 -2
  453. package/dist/infrastructure/conversations.js.map +1 -1
  454. package/dist/infrastructure/conversations.types.d.ts +1 -1
  455. package/dist/infrastructure/conversations.types.js.map +1 -1
  456. package/dist/infrastructure/custom-reporter.js +32 -24
  457. package/dist/infrastructure/custom-reporter.js.map +1 -1
  458. package/dist/infrastructure/custom-reporter.types.d.ts +2 -0
  459. package/dist/infrastructure/custom-reporter.types.js.map +1 -1
  460. package/dist/infrastructure/git/git.constants.d.ts +1 -1
  461. package/dist/infrastructure/git/git.constants.js +1 -0
  462. package/dist/infrastructure/git/git.constants.js.map +1 -1
  463. package/dist/infrastructure/git/workspace-lease.js +4 -3
  464. package/dist/infrastructure/git/workspace-lease.js.map +1 -1
  465. package/dist/infrastructure/git/workspace.js +7 -6
  466. package/dist/infrastructure/git/workspace.js.map +1 -1
  467. package/dist/infrastructure/git/workspace.types.d.ts +1 -0
  468. package/dist/infrastructure/git/workspace.types.js.map +1 -1
  469. package/dist/infrastructure/host-credentials.constants.d.ts +1 -0
  470. package/dist/infrastructure/host-credentials.constants.js +2 -0
  471. package/dist/infrastructure/host-credentials.constants.js.map +1 -0
  472. package/dist/infrastructure/host-credentials.d.ts +4 -0
  473. package/dist/infrastructure/host-credentials.js +89 -0
  474. package/dist/infrastructure/host-credentials.js.map +1 -0
  475. package/dist/infrastructure/inspection-path.js +4 -3
  476. package/dist/infrastructure/inspection-path.js.map +1 -1
  477. package/dist/infrastructure/journal.constants.js +10 -1
  478. package/dist/infrastructure/journal.constants.js.map +1 -1
  479. package/dist/infrastructure/journal.d.ts +1 -1
  480. package/dist/infrastructure/journal.js +8 -75
  481. package/dist/infrastructure/journal.js.map +1 -1
  482. package/dist/infrastructure/journal.types.d.ts +2 -4
  483. package/dist/infrastructure/journal.types.js.map +1 -1
  484. package/dist/infrastructure/local-transport.js +9 -4
  485. package/dist/infrastructure/local-transport.js.map +1 -1
  486. package/dist/infrastructure/opentelemetry-dispatch.d.ts +3 -3
  487. package/dist/infrastructure/opentelemetry-dispatch.js +5 -4
  488. package/dist/infrastructure/opentelemetry-dispatch.js.map +1 -1
  489. package/dist/infrastructure/opentelemetry-observation.d.ts +5 -0
  490. package/dist/infrastructure/opentelemetry-observation.js +59 -0
  491. package/dist/infrastructure/opentelemetry-observation.js.map +1 -0
  492. package/dist/infrastructure/opentelemetry.js +15 -1
  493. package/dist/infrastructure/opentelemetry.js.map +1 -1
  494. package/dist/infrastructure/opentelemetry.types.d.ts +9 -1
  495. package/dist/infrastructure/opentelemetry.types.js.map +1 -1
  496. package/dist/infrastructure/reporter.d.ts +2 -2
  497. package/dist/infrastructure/reporter.js +5 -1
  498. package/dist/infrastructure/reporter.js.map +1 -1
  499. package/dist/infrastructure/repository-transport.constants.d.ts +1 -0
  500. package/dist/infrastructure/repository-transport.constants.js +2 -0
  501. package/dist/infrastructure/repository-transport.constants.js.map +1 -0
  502. package/dist/infrastructure/repository-transport.d.ts +2 -0
  503. package/dist/infrastructure/repository-transport.js +9 -0
  504. package/dist/infrastructure/repository-transport.js.map +1 -0
  505. package/dist/infrastructure/resource-activity-inspection.js +19 -24
  506. package/dist/infrastructure/resource-activity-inspection.js.map +1 -1
  507. package/dist/infrastructure/resource-activity.constants.d.ts +0 -1
  508. package/dist/infrastructure/resource-activity.constants.js +0 -1
  509. package/dist/infrastructure/resource-activity.constants.js.map +1 -1
  510. package/dist/infrastructure/resource-activity.js +20 -83
  511. package/dist/infrastructure/resource-activity.js.map +1 -1
  512. package/dist/infrastructure/s3-transport.constants.d.ts +2 -0
  513. package/dist/infrastructure/s3-transport.constants.js +3 -0
  514. package/dist/infrastructure/s3-transport.constants.js.map +1 -0
  515. package/dist/infrastructure/s3-transport.js +57 -3
  516. package/dist/infrastructure/s3-transport.js.map +1 -1
  517. package/dist/infrastructure/s3-transport.types.d.ts +1 -0
  518. package/dist/infrastructure/s3-transport.types.js.map +1 -1
  519. package/dist/infrastructure/speculation-store.constants.d.ts +3 -0
  520. package/dist/infrastructure/speculation-store.constants.js +2 -0
  521. package/dist/infrastructure/speculation-store.constants.js.map +1 -0
  522. package/dist/infrastructure/speculation-store.d.ts +4 -0
  523. package/dist/infrastructure/speculation-store.js +73 -0
  524. package/dist/infrastructure/speculation-store.js.map +1 -0
  525. package/dist/infrastructure/speculation-store.types.d.ts +12 -0
  526. package/dist/infrastructure/speculation-store.types.js +2 -0
  527. package/dist/infrastructure/speculation-store.types.js.map +1 -0
  528. package/dist/infrastructure/storage-inventory.constants.js +1 -0
  529. package/dist/infrastructure/storage-inventory.constants.js.map +1 -1
  530. package/dist/infrastructure/storage-inventory.types.d.ts +1 -1
  531. package/dist/infrastructure/storage-inventory.types.js.map +1 -1
  532. package/dist/infrastructure/storage-reservations.types.d.ts +0 -8
  533. package/dist/infrastructure/storage-reservations.types.js.map +1 -1
  534. package/dist/infrastructure/task-queue-bullmq-resources.js +3 -0
  535. package/dist/infrastructure/task-queue-bullmq-resources.js.map +1 -1
  536. package/dist/infrastructure/task-queue-http.js +29 -4
  537. package/dist/infrastructure/task-queue-http.js.map +1 -1
  538. package/dist/infrastructure/task-queue-http.types.d.ts +2 -2
  539. package/dist/infrastructure/task-queue-http.types.js.map +1 -1
  540. package/dist/infrastructure/transport-conversations.js +2 -0
  541. package/dist/infrastructure/transport-conversations.js.map +1 -1
  542. package/dist/infrastructure/transport-journal.d.ts +1 -1
  543. package/dist/infrastructure/transport-journal.js +8 -2
  544. package/dist/infrastructure/transport-journal.js.map +1 -1
  545. package/dist/infrastructure/transport-reservations.d.ts +1 -1
  546. package/dist/infrastructure/transport-reservations.js +14 -8
  547. package/dist/infrastructure/transport-reservations.js.map +1 -1
  548. package/dist/infrastructure/workflow-decision-signature.constants.d.ts +4 -0
  549. package/dist/infrastructure/workflow-decision-signature.constants.js +5 -0
  550. package/dist/infrastructure/workflow-decision-signature.constants.js.map +1 -0
  551. package/dist/infrastructure/workflow-decision-signature.d.ts +4 -0
  552. package/dist/infrastructure/workflow-decision-signature.js +83 -0
  553. package/dist/infrastructure/workflow-decision-signature.js.map +1 -0
  554. package/dist/infrastructure/workflow-decision-signature.types.d.ts +16 -0
  555. package/dist/infrastructure/workflow-decision-signature.types.js +2 -0
  556. package/dist/infrastructure/workflow-decision-signature.types.js.map +1 -0
  557. package/dist/providers/agents.d.ts +7 -2
  558. package/dist/providers/agents.js +4 -1
  559. package/dist/providers/agents.js.map +1 -1
  560. package/dist/providers/antigravity-install.constants.d.ts +2 -0
  561. package/dist/providers/antigravity-install.constants.js +28 -0
  562. package/dist/providers/antigravity-install.constants.js.map +1 -0
  563. package/dist/providers/antigravity-install.d.ts +2 -0
  564. package/dist/providers/antigravity-install.js +29 -0
  565. package/dist/providers/antigravity-install.js.map +1 -0
  566. package/dist/providers/antigravity-install.types.d.ts +4 -0
  567. package/dist/providers/antigravity-install.types.js +2 -0
  568. package/dist/providers/antigravity-install.types.js.map +1 -0
  569. package/dist/providers/container-recovery.d.ts +4 -0
  570. package/dist/providers/container-recovery.js +28 -0
  571. package/dist/providers/container-recovery.js.map +1 -0
  572. package/dist/providers/container.js +8 -0
  573. package/dist/providers/container.js.map +1 -1
  574. package/dist/providers/daytona-network.constants.d.ts +5 -0
  575. package/dist/providers/daytona-network.constants.js +8 -0
  576. package/dist/providers/daytona-network.constants.js.map +1 -0
  577. package/dist/providers/daytona-network.d.ts +4 -0
  578. package/dist/providers/daytona-network.js +33 -0
  579. package/dist/providers/daytona-network.js.map +1 -0
  580. package/dist/providers/daytona.d.ts +1 -0
  581. package/dist/providers/daytona.js +9 -3
  582. package/dist/providers/daytona.js.map +1 -1
  583. package/dist/providers/daytona.types.d.ts +2 -0
  584. package/dist/providers/daytona.types.js.map +1 -1
  585. package/dist/providers/firecracker-command.js +1 -1
  586. package/dist/providers/firecracker-command.js.map +1 -1
  587. package/dist/providers/firecracker-jailer.constants.d.ts +9 -0
  588. package/dist/providers/firecracker-jailer.constants.js +10 -0
  589. package/dist/providers/firecracker-jailer.constants.js.map +1 -0
  590. package/dist/providers/firecracker-jailer.d.ts +4 -0
  591. package/dist/providers/firecracker-jailer.js +171 -0
  592. package/dist/providers/firecracker-jailer.js.map +1 -0
  593. package/dist/providers/firecracker-machine.js +30 -8
  594. package/dist/providers/firecracker-machine.js.map +1 -1
  595. package/dist/providers/firecracker.types.d.ts +16 -0
  596. package/dist/providers/firecracker.types.js.map +1 -1
  597. package/dist/providers/vercel-network.js +1 -1
  598. package/dist/providers/vercel-network.js.map +1 -1
  599. package/dist/providers/vercel.js +6 -3
  600. package/dist/providers/vercel.js.map +1 -1
  601. package/dist/providers/versions.constants.d.ts +3 -1
  602. package/dist/providers/versions.constants.js +3 -1
  603. package/dist/providers/versions.constants.js.map +1 -1
  604. package/package.json +3 -3
  605. package/dist/adapters/agents/gemini-adapter.d.ts +0 -3
  606. package/dist/adapters/agents/gemini-adapter.js +0 -34
  607. package/dist/adapters/agents/gemini-adapter.js.map +0 -1
  608. package/dist/adapters/agents/gemini-diagnostics.d.ts +0 -2
  609. package/dist/adapters/agents/gemini-diagnostics.js +0 -15
  610. package/dist/adapters/agents/gemini-diagnostics.js.map +0 -1
  611. package/dist/adapters/agents/gemini-events.d.ts +0 -2
  612. package/dist/adapters/agents/gemini-events.js +0 -50
  613. package/dist/adapters/agents/gemini-events.js.map +0 -1
  614. package/dist/adapters/agents/gemini-request.js +0 -23
  615. package/dist/adapters/agents/gemini-request.js.map +0 -1
  616. package/dist/adapters/agents/gemini.types.js +0 -2
  617. package/dist/adapters/agents/gemini.types.js.map +0 -1
  618. package/dist/infrastructure/artifact-store.d.ts +0 -3
  619. package/dist/infrastructure/artifact-store.js +0 -110
  620. package/dist/infrastructure/artifact-store.js.map +0 -1
  621. package/dist/infrastructure/artifact-store.types.d.ts +0 -6
  622. package/dist/infrastructure/artifact-store.types.js +0 -2
  623. package/dist/infrastructure/artifact-store.types.js.map +0 -1
  624. package/dist/infrastructure/journal-retention.constants.d.ts +0 -4
  625. package/dist/infrastructure/journal-retention.constants.js +0 -5
  626. package/dist/infrastructure/journal-retention.constants.js.map +0 -1
  627. package/dist/infrastructure/journal-retention.d.ts +0 -2
  628. package/dist/infrastructure/journal-retention.js +0 -51
  629. package/dist/infrastructure/journal-retention.js.map +0 -1
  630. package/dist/infrastructure/storage-mutation-lock.constants.d.ts +0 -5
  631. package/dist/infrastructure/storage-mutation-lock.constants.js +0 -6
  632. package/dist/infrastructure/storage-mutation-lock.constants.js.map +0 -1
  633. package/dist/infrastructure/storage-mutation-lock.d.ts +0 -1
  634. package/dist/infrastructure/storage-mutation-lock.js +0 -21
  635. package/dist/infrastructure/storage-mutation-lock.js.map +0 -1
  636. package/dist/infrastructure/storage-reservations.constants.d.ts +0 -4
  637. package/dist/infrastructure/storage-reservations.constants.js +0 -5
  638. package/dist/infrastructure/storage-reservations.constants.js.map +0 -1
  639. package/dist/infrastructure/storage-reservations.d.ts +0 -2
  640. package/dist/infrastructure/storage-reservations.js +0 -150
  641. package/dist/infrastructure/storage-reservations.js.map +0 -1
  642. package/dist/infrastructure/workflow-checkpoint.d.ts +0 -3
  643. package/dist/infrastructure/workflow-checkpoint.js +0 -84
  644. package/dist/infrastructure/workflow-checkpoint.js.map +0 -1
  645. package/dist/infrastructure/workflow-checkpoint.types.d.ts +0 -6
  646. package/dist/infrastructure/workflow-checkpoint.types.js +0 -2
  647. package/dist/infrastructure/workflow-checkpoint.types.js.map +0 -1
@@ -0,0 +1,4 @@
1
+ export interface AntigravityRelease {
2
+ readonly url: string;
3
+ readonly sha512: string;
4
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=antigravity-install.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"antigravity-install.types.js","sourceRoot":"","sources":["../../src/providers/antigravity-install.types.ts"],"names":[],"mappings":"","sourcesContent":["export interface AntigravityRelease {\n readonly url: string;\n readonly sha512: string;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { TransferOptions } from "../domain/sandbox.types.ts";
2
+ import type { Executor } from "../infrastructure/process.types.ts";
3
+ import type { ContainerEngine } from "./container.types.ts";
4
+ export declare function recoverContainer(engine: ContainerEngine, executor: Executor, resourceId: string, options?: TransferOptions): Promise<void>;
@@ -0,0 +1,28 @@
1
+ import { invariant } from "../domain/errors.js";
2
+ import { requireSuccess } from "../infrastructure/process.js";
3
+ import { containerDefaults } from "./container.constants.js";
4
+ export async function recoverContainer(engine, executor, resourceId, options = {}) {
5
+ invariant(/^outpost-[a-f0-9-]{36}$/.test(resourceId), "Invalid recoverable container identity");
6
+ const limits = {
7
+ deadlineMs: options.deadlineMs ?? containerDefaults.cleanupMs,
8
+ ...(options.signal ? { signal: options.signal } : {}),
9
+ };
10
+ const result = await requireSuccess({
11
+ executable: engine,
12
+ arguments: [
13
+ "container",
14
+ "ls",
15
+ "--all",
16
+ "--filter",
17
+ `name=^${resourceId}$`,
18
+ "--format",
19
+ "{{.Names}}",
20
+ ],
21
+ ...limits,
22
+ }, executor);
23
+ if (!result.stdout.trim())
24
+ return;
25
+ invariant(result.stdout.trim() === resourceId, "Recoverable container identity mismatch");
26
+ await requireSuccess({ executable: engine, arguments: ["rm", "--force", resourceId], ...limits }, executor);
27
+ }
28
+ //# sourceMappingURL=container-recovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container-recovery.js","sourceRoot":"","sources":["../../src/providers/container-recovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAuB,EACvB,QAAkB,EAClB,UAAkB,EAClB,UAA2B,EAAE;IAE7B,SAAS,CACP,yBAAyB,CAAC,IAAI,CAAC,UAAU,CAAC,EAC1C,wCAAwC,CACzC,CAAC;IACF,MAAM,MAAM,GAAG;QACb,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,iBAAiB,CAAC,SAAS;QAC7D,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtD,CAAC;IACF,MAAM,MAAM,GAAG,MAAM,cAAc,CACjC;QACE,UAAU,EAAE,MAAM;QAClB,SAAS,EAAE;YACT,WAAW;YACX,IAAI;YACJ,OAAO;YACP,UAAU;YACV,SAAS,UAAU,GAAG;YACtB,UAAU;YACV,YAAY;SACb;QACD,GAAG,MAAM;KACV,EACD,QAAQ,CACT,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QAAE,OAAO;IAClC,SAAS,CACP,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,UAAU,EACnC,yCAAyC,CAC1C,CAAC;IACF,MAAM,cAAc,CAClB,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,EAAE,GAAG,MAAM,EAAE,EAC3E,QAAQ,CACT,CAAC;AACJ,CAAC","sourcesContent":["import { invariant } from \"../domain/errors.ts\";\nimport type { TransferOptions } from \"../domain/sandbox.types.ts\";\nimport { requireSuccess } from \"../infrastructure/process.ts\";\nimport type { Executor } from \"../infrastructure/process.types.ts\";\nimport { containerDefaults } from \"./container.constants.ts\";\nimport type { ContainerEngine } from \"./container.types.ts\";\n\nexport async function recoverContainer(\n engine: ContainerEngine,\n executor: Executor,\n resourceId: string,\n options: TransferOptions = {},\n): Promise<void> {\n invariant(\n /^outpost-[a-f0-9-]{36}$/.test(resourceId),\n \"Invalid recoverable container identity\",\n );\n const limits = {\n deadlineMs: options.deadlineMs ?? containerDefaults.cleanupMs,\n ...(options.signal ? { signal: options.signal } : {}),\n };\n const result = await requireSuccess(\n {\n executable: engine,\n arguments: [\n \"container\",\n \"ls\",\n \"--all\",\n \"--filter\",\n `name=^${resourceId}$`,\n \"--format\",\n \"{{.Names}}\",\n ],\n ...limits,\n },\n executor,\n );\n if (!result.stdout.trim()) return;\n invariant(\n result.stdout.trim() === resourceId,\n \"Recoverable container identity mismatch\",\n );\n await requireSuccess(\n { executable: engine, arguments: [\"rm\", \"--force\", resourceId], ...limits },\n executor,\n );\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { recoverContainer } from "./container-recovery.js";
1
2
  import { execFileSync } from "node:child_process";
2
3
  import { randomUUID } from "node:crypto";
3
4
  import { basename } from "node:path";
@@ -37,6 +38,11 @@ export function containerProvider(engine, options = {}, executor = executeProces
37
38
  name: engine,
38
39
  placement: config.repositoryMode === "isolated" ? "remote" : "mounted",
39
40
  variables: { ...config.variables },
41
+ ...(config.repositoryMode !== "isolated"
42
+ ? {
43
+ recover: (resourceId, recoveryOptions) => recoverContainer(engine, executor, resourceId, recoveryOptions),
44
+ }
45
+ : {}),
40
46
  async acquire(context) {
41
47
  context.signal?.throwIfAborted();
42
48
  const name = `outpost-${randomUUID()}`;
@@ -97,6 +103,8 @@ export function containerProvider(engine, options = {}, executor = executeProces
97
103
  `${cacheDefaults.label}=true`,
98
104
  cache.volume,
99
105
  ], context.signal ? { signal: context.signal } : {});
106
+ await context.registerRecovery?.(name);
107
+ context.signal?.throwIfAborted();
100
108
  await call(args, {
101
109
  ...(context.signal ? { signal: context.signal } : {}),
102
110
  });
@@ -1 +1 @@
1
- {"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/providers/container.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFileSync } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { basename } from \"node:path\";\nimport type { Command } from \"../domain/command.types.ts\";\nimport { containerNetworks } from \"./container-network.ts\";\nimport { invariant } from \"../domain/errors.ts\";\nimport type { SandboxProvider } from \"../domain/sandbox.types.ts\";\nimport {\n executeProcess,\n quote,\n requireSuccess,\n} from \"../infrastructure/process.ts\";\nimport type { Executor } from \"../infrastructure/process.types.ts\";\nimport { registerCleanup } from \"../infrastructure/shutdown.ts\";\nimport { cacheMounts, validateCaches } from \"./container-cache.ts\";\nimport {\n cacheCreateOptions,\n cacheDefaults,\n} from \"./container-cache.constants.ts\";\nimport { containerCommand } from \"./container-command.ts\";\nimport { containerFiles } from \"./container-files.ts\";\nimport { containerMounts } from \"./container-mounts.ts\";\nimport { containerPlan } from \"./container-plan.ts\";\nimport { containerPreflight } from \"./container-preflight.ts\";\nimport { containerDefaults } from \"./container.constants.ts\";\nimport type { ContainerEngine, ContainerOptions } from \"./container.types.ts\";\n\nexport type { ContainerOptions } from \"./container.types.ts\";\n\nexport function imageName(repository: string): string {\n return `outpost:${\n basename(repository)\n .toLowerCase()\n .replace(/[^a-z0-9_.-]/g, \"-\") || \"workspace\"\n }`;\n}\n\nexport function containerProvider(\n engine: ContainerEngine,\n options: ContainerOptions = {},\n executor: Executor = executeProcess,\n platform: NodeJS.Platform = process.platform,\n): SandboxProvider {\n const config = {\n ...options,\n networks: containerNetworks(options),\n caches: (options.caches ?? []).map((cache) => ({ ...cache })),\n };\n invariant(\n config.repositoryMode === undefined ||\n config.repositoryMode === \"mounted\" ||\n config.repositoryMode === \"isolated\",\n \"repositoryMode must be mounted or isolated\",\n );\n validateCaches(config);\n if (config.cpus !== undefined)\n invariant(\n Number.isFinite(config.cpus) && config.cpus > 0,\n \"cpus must be positive\",\n );\n if (config.memoryMb !== undefined)\n invariant(\n Number.isSafeInteger(config.memoryMb) &&\n config.memoryMb >= containerDefaults.minimumMemoryMb,\n \"memoryMb must be at least 64\",\n );\n return {\n name: engine,\n placement: config.repositoryMode === \"isolated\" ? \"remote\" : \"mounted\",\n variables: { ...config.variables },\n async acquire(context) {\n context.signal?.throwIfAborted();\n const name = `outpost-${randomUUID()}`;\n const image = config.image ?? imageName(context.repository);\n const user = config.user ?? {\n uid: process.getuid?.() ?? containerDefaults.uid,\n gid: process.getgid?.() ?? containerDefaults.gid,\n };\n invariant(\n Number.isInteger(user.uid) &&\n user.uid >= 0 &&\n Number.isInteger(user.gid) &&\n user.gid >= 0,\n \"Invalid container user\",\n );\n const call = (args: readonly string[], extra: Partial<Command> = {}) =>\n requireSuccess(\n {\n executable: engine,\n arguments: args,\n deadlineMs: containerDefaults.deadlineMs,\n ...extra,\n },\n executor,\n );\n await containerPreflight(engine, platform, call, config, image, user);\n const root =\n config.repositoryMode === \"isolated\"\n ? containerDefaults.isolatedRoot\n : containerDefaults.root,\n home = containerDefaults.home;\n const { env, volumes, fileParents } = await containerMounts(\n context,\n config,\n platform,\n root,\n home,\n );\n const caches = await cacheMounts(\n config.caches ?? [],\n context.repository,\n image,\n user,\n );\n for (const cache of caches)\n volumes.push(\"--volume\", `${cache.volume}:${cache.target}:nocopy`);\n const args = containerPlan({\n config,\n engine,\n user,\n root,\n name,\n image,\n volumes,\n fileParents,\n });\n let closed = false,\n releasing: Promise<void> | undefined;\n let unregister = () => {};\n const release = (): Promise<void> => {\n closed = true;\n releasing ??= call([\"rm\", \"--force\", name])\n .then(() => {\n unregister();\n })\n .catch((error) => {\n releasing = undefined;\n throw error;\n });\n return releasing;\n };\n try {\n for (const cache of caches)\n await call(\n [\n \"volume\",\n \"create\",\n ...cacheCreateOptions[engine],\n \"--label\",\n `${cacheDefaults.label}=true`,\n cache.volume,\n ],\n context.signal ? { signal: context.signal } : {},\n );\n await call(args, {\n ...(context.signal ? { signal: context.signal } : {}),\n });\n await call(\n [\"start\", name],\n context.signal ? { signal: context.signal } : {},\n );\n for (const cache of caches) {\n await call(\n [\n \"exec\",\n \"--user\",\n \"0:0\",\n name,\n \"chown\",\n `${user.uid}:${user.gid}`,\n cache.target,\n ],\n context.signal ? { signal: context.signal } : {},\n );\n await call(\n [\"exec\", name, \"chmod\", \"700\", cache.target],\n context.signal ? { signal: context.signal } : {},\n );\n }\n for (const parent of fileParents)\n await call([\n \"exec\",\n \"--user\",\n \"0:0\",\n name,\n \"sh\",\n \"-c\",\n `mkdir -p ${quote(parent)} && chown ${user.uid}:${user.gid} ${quote(parent)}`,\n ]);\n if (fileParents.size)\n await call([\n \"exec\",\n \"--user\",\n \"0:0\",\n name,\n \"chown\",\n `${user.uid}:${user.gid}`,\n home,\n ]);\n if (config.repositoryMode === \"isolated\")\n await call(\n [\n \"exec\",\n \"--user\",\n \"0:0\",\n name,\n \"sh\",\n \"-c\",\n `mkdir -p ${quote(root)} && chmod 700 ${quote(root)} /tmp/outpost && chown ${user.uid}:${user.gid} ${quote(root)} /tmp/outpost`,\n ],\n context.signal ? { signal: context.signal } : {},\n );\n await call([\n \"exec\",\n name,\n \"sh\",\n \"-c\",\n \"command -v setsid >/dev/null && command -v kill >/dev/null && command -v tar >/dev/null && command -v cp >/dev/null\",\n ]);\n } catch (cause) {\n try {\n await release();\n } catch (cleanup) {\n throw new AggregateError(\n [cause, cleanup],\n \"Sandbox provisioning and cleanup failed\",\n );\n }\n throw cause;\n }\n unregister = registerCleanup(release, () => {\n if (!closed)\n execFileSync(engine, [\"rm\", \"--force\", name], {\n timeout: containerDefaults.cleanupMs,\n stdio: \"ignore\",\n windowsHide: true,\n });\n });\n return {\n root,\n home,\n invoke: containerCommand({\n engine,\n config,\n executor,\n root,\n name,\n env,\n call,\n isClosed: () => closed,\n }),\n ...containerFiles({\n engine,\n config,\n executor,\n root,\n name,\n env,\n call,\n isClosed: () => closed,\n }),\n release,\n };\n },\n };\n}\n"]}
1
+ {"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/providers/container.ts"],"names":[],"mappings":"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","sourcesContent":["import { recoverContainer } from \"./container-recovery.ts\";\nimport { execFileSync } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { basename } from \"node:path\";\nimport type { Command } from \"../domain/command.types.ts\";\nimport { containerNetworks } from \"./container-network.ts\";\nimport { invariant } from \"../domain/errors.ts\";\nimport type { SandboxProvider } from \"../domain/sandbox.types.ts\";\nimport {\n executeProcess,\n quote,\n requireSuccess,\n} from \"../infrastructure/process.ts\";\nimport type { Executor } from \"../infrastructure/process.types.ts\";\nimport { registerCleanup } from \"../infrastructure/shutdown.ts\";\nimport { cacheMounts, validateCaches } from \"./container-cache.ts\";\nimport {\n cacheCreateOptions,\n cacheDefaults,\n} from \"./container-cache.constants.ts\";\nimport { containerCommand } from \"./container-command.ts\";\nimport { containerFiles } from \"./container-files.ts\";\nimport { containerMounts } from \"./container-mounts.ts\";\nimport { containerPlan } from \"./container-plan.ts\";\nimport { containerPreflight } from \"./container-preflight.ts\";\nimport { containerDefaults } from \"./container.constants.ts\";\nimport type { ContainerEngine, ContainerOptions } from \"./container.types.ts\";\n\nexport type { ContainerOptions } from \"./container.types.ts\";\n\nexport function imageName(repository: string): string {\n return `outpost:${\n basename(repository)\n .toLowerCase()\n .replace(/[^a-z0-9_.-]/g, \"-\") || \"workspace\"\n }`;\n}\n\nexport function containerProvider(\n engine: ContainerEngine,\n options: ContainerOptions = {},\n executor: Executor = executeProcess,\n platform: NodeJS.Platform = process.platform,\n): SandboxProvider {\n const config = {\n ...options,\n networks: containerNetworks(options),\n caches: (options.caches ?? []).map((cache) => ({ ...cache })),\n };\n invariant(\n config.repositoryMode === undefined ||\n config.repositoryMode === \"mounted\" ||\n config.repositoryMode === \"isolated\",\n \"repositoryMode must be mounted or isolated\",\n );\n validateCaches(config);\n if (config.cpus !== undefined)\n invariant(\n Number.isFinite(config.cpus) && config.cpus > 0,\n \"cpus must be positive\",\n );\n if (config.memoryMb !== undefined)\n invariant(\n Number.isSafeInteger(config.memoryMb) &&\n config.memoryMb >= containerDefaults.minimumMemoryMb,\n \"memoryMb must be at least 64\",\n );\n return {\n name: engine,\n placement: config.repositoryMode === \"isolated\" ? \"remote\" : \"mounted\",\n variables: { ...config.variables },\n ...(config.repositoryMode !== \"isolated\"\n ? {\n recover: (resourceId, recoveryOptions) =>\n recoverContainer(engine, executor, resourceId, recoveryOptions),\n }\n : {}),\n async acquire(context) {\n context.signal?.throwIfAborted();\n const name = `outpost-${randomUUID()}`;\n const image = config.image ?? imageName(context.repository);\n const user = config.user ?? {\n uid: process.getuid?.() ?? containerDefaults.uid,\n gid: process.getgid?.() ?? containerDefaults.gid,\n };\n invariant(\n Number.isInteger(user.uid) &&\n user.uid >= 0 &&\n Number.isInteger(user.gid) &&\n user.gid >= 0,\n \"Invalid container user\",\n );\n const call = (args: readonly string[], extra: Partial<Command> = {}) =>\n requireSuccess(\n {\n executable: engine,\n arguments: args,\n deadlineMs: containerDefaults.deadlineMs,\n ...extra,\n },\n executor,\n );\n await containerPreflight(engine, platform, call, config, image, user);\n const root =\n config.repositoryMode === \"isolated\"\n ? containerDefaults.isolatedRoot\n : containerDefaults.root,\n home = containerDefaults.home;\n const { env, volumes, fileParents } = await containerMounts(\n context,\n config,\n platform,\n root,\n home,\n );\n const caches = await cacheMounts(\n config.caches ?? [],\n context.repository,\n image,\n user,\n );\n for (const cache of caches)\n volumes.push(\"--volume\", `${cache.volume}:${cache.target}:nocopy`);\n const args = containerPlan({\n config,\n engine,\n user,\n root,\n name,\n image,\n volumes,\n fileParents,\n });\n let closed = false,\n releasing: Promise<void> | undefined;\n let unregister = () => {};\n const release = (): Promise<void> => {\n closed = true;\n releasing ??= call([\"rm\", \"--force\", name])\n .then(() => {\n unregister();\n })\n .catch((error) => {\n releasing = undefined;\n throw error;\n });\n return releasing;\n };\n try {\n for (const cache of caches)\n await call(\n [\n \"volume\",\n \"create\",\n ...cacheCreateOptions[engine],\n \"--label\",\n `${cacheDefaults.label}=true`,\n cache.volume,\n ],\n context.signal ? { signal: context.signal } : {},\n );\n await context.registerRecovery?.(name);\n context.signal?.throwIfAborted();\n await call(args, {\n ...(context.signal ? { signal: context.signal } : {}),\n });\n await call(\n [\"start\", name],\n context.signal ? { signal: context.signal } : {},\n );\n for (const cache of caches) {\n await call(\n [\n \"exec\",\n \"--user\",\n \"0:0\",\n name,\n \"chown\",\n `${user.uid}:${user.gid}`,\n cache.target,\n ],\n context.signal ? { signal: context.signal } : {},\n );\n await call(\n [\"exec\", name, \"chmod\", \"700\", cache.target],\n context.signal ? { signal: context.signal } : {},\n );\n }\n for (const parent of fileParents)\n await call([\n \"exec\",\n \"--user\",\n \"0:0\",\n name,\n \"sh\",\n \"-c\",\n `mkdir -p ${quote(parent)} && chown ${user.uid}:${user.gid} ${quote(parent)}`,\n ]);\n if (fileParents.size)\n await call([\n \"exec\",\n \"--user\",\n \"0:0\",\n name,\n \"chown\",\n `${user.uid}:${user.gid}`,\n home,\n ]);\n if (config.repositoryMode === \"isolated\")\n await call(\n [\n \"exec\",\n \"--user\",\n \"0:0\",\n name,\n \"sh\",\n \"-c\",\n `mkdir -p ${quote(root)} && chmod 700 ${quote(root)} /tmp/outpost && chown ${user.uid}:${user.gid} ${quote(root)} /tmp/outpost`,\n ],\n context.signal ? { signal: context.signal } : {},\n );\n await call([\n \"exec\",\n name,\n \"sh\",\n \"-c\",\n \"command -v setsid >/dev/null && command -v kill >/dev/null && command -v tar >/dev/null && command -v cp >/dev/null\",\n ]);\n } catch (cause) {\n try {\n await release();\n } catch (cleanup) {\n throw new AggregateError(\n [cause, cleanup],\n \"Sandbox provisioning and cleanup failed\",\n );\n }\n throw cause;\n }\n unregister = registerCleanup(release, () => {\n if (!closed)\n execFileSync(engine, [\"rm\", \"--force\", name], {\n timeout: containerDefaults.cleanupMs,\n stdio: \"ignore\",\n windowsHide: true,\n });\n });\n return {\n root,\n home,\n invoke: containerCommand({\n engine,\n config,\n executor,\n root,\n name,\n env,\n call,\n isClosed: () => closed,\n }),\n ...containerFiles({\n engine,\n config,\n executor,\n root,\n name,\n env,\n call,\n isClosed: () => closed,\n }),\n release,\n };\n },\n };\n}\n"]}
@@ -0,0 +1,5 @@
1
+ export declare const daytonaNetworkFields: readonly ["networkBlockAll", "networkAllowList", "domainAllowList", "outboundProxyUrl"];
2
+ export declare const daytonaNetworkLimits: {
3
+ readonly domains: 100;
4
+ readonly cidrs: 10;
5
+ };
@@ -0,0 +1,8 @@
1
+ export const daytonaNetworkFields = [
2
+ "networkBlockAll",
3
+ "networkAllowList",
4
+ "domainAllowList",
5
+ "outboundProxyUrl",
6
+ ];
7
+ export const daytonaNetworkLimits = { domains: 100, cidrs: 10 };
8
+ //# sourceMappingURL=daytona-network.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daytona-network.constants.js","sourceRoot":"","sources":["../../src/providers/daytona-network.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,iBAAiB;IACjB,kBAAkB;IAClB,iBAAiB;IACjB,kBAAkB;CACV,CAAC;AAEX,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAW,CAAC","sourcesContent":["export const daytonaNetworkFields = [\n \"networkBlockAll\",\n \"networkAllowList\",\n \"domainAllowList\",\n \"outboundProxyUrl\",\n] as const;\n\nexport const daytonaNetworkLimits = { domains: 100, cidrs: 10 } as const;\n"]}
@@ -0,0 +1,4 @@
1
+ import type { Sandbox } from "@daytona/sdk";
2
+ import type { DaytonaOptions } from "./daytona.types.ts";
3
+ export declare function daytonaNetworkPolicy(options: DaytonaOptions): Parameters<Sandbox["updateNetworkSettings"]>[0] | undefined;
4
+ export declare function confirmDaytonaNetworkPolicy(sandbox: Pick<Sandbox, "updateNetworkSettings">, policy: Parameters<Sandbox["updateNetworkSettings"]>[0]): Promise<void>;
@@ -0,0 +1,33 @@
1
+ import { isIP } from "node:net";
2
+ import { validateEgress } from "../domain/egress.js";
3
+ import { invariant, OutpostError } from "../domain/errors.js";
4
+ import { daytonaNetworkFields, daytonaNetworkLimits, } from "./daytona-network.constants.js";
5
+ export function daytonaNetworkPolicy(options) {
6
+ const policy = validateEgress(options.egress);
7
+ if (!policy)
8
+ return undefined;
9
+ invariant(daytonaNetworkFields.every((field) => options.create?.[field] === undefined), "Use egress or Daytona create network settings, not both");
10
+ if (policy.mode === "deny-all")
11
+ return { networkBlockAll: true };
12
+ const domains = policy.domains ?? [];
13
+ const cidrs = policy.allowCidrs ?? [];
14
+ invariant(!policy.denyCidrs?.length, "Daytona cannot enforce egress denyCidrs");
15
+ invariant(!domains.length || !cidrs.length, "Daytona cannot combine egress domains and allowCidrs");
16
+ invariant(cidrs.every((entry) => isIP(entry.split("/")[0]) === 4), "Daytona egress allowCidrs supports IPv4 only");
17
+ invariant(cidrs.length <= daytonaNetworkLimits.cidrs &&
18
+ domains.length <= daytonaNetworkLimits.domains, "Daytona egress supports at most 10 CIDRs or 100 domains");
19
+ const names = new Set(domains.map((name) => name.toLowerCase()));
20
+ invariant(domains.every((name) => !name.startsWith("*.") || names.has(name.slice(2).toLowerCase())), "Daytona wildcard domains also allow the apex; list the apex domain explicitly");
21
+ if (domains.length)
22
+ return { domainAllowList: domains.join(",") };
23
+ return { networkAllowList: cidrs.join(",") };
24
+ }
25
+ export async function confirmDaytonaNetworkPolicy(sandbox, policy) {
26
+ try {
27
+ await sandbox.updateNetworkSettings({ ...policy });
28
+ }
29
+ catch (cause) {
30
+ throw new OutpostError("provider", "Daytona could not confirm egress enforcement; sandbox-level network controls require Tier 3/4 and WRITE_SANDBOXES permission", { stage: "egress-confirmation" }, cause);
31
+ }
32
+ }
33
+ //# sourceMappingURL=daytona-network.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daytona-network.js","sourceRoot":"","sources":["../../src/providers/daytona-network.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,gCAAgC,CAAC;AAGxC,MAAM,UAAU,oBAAoB,CAClC,OAAuB;IAEvB,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,SAAS,CACP,oBAAoB,CAAC,KAAK,CACxB,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,KAAK,SAAS,CACjD,EACD,yDAAyD,CAC1D,CAAC;IACF,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;IACjE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;IACrC,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;IACtC,SAAS,CACP,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,EACzB,yCAAyC,CAC1C,CAAC;IACF,SAAS,CACP,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,EAChC,sDAAsD,CACvD,CAAC;IACF,SAAS,CACP,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,EACxD,8CAA8C,CAC/C,CAAC;IACF,SAAS,CACP,KAAK,CAAC,MAAM,IAAI,oBAAoB,CAAC,KAAK;QACxC,OAAO,CAAC,MAAM,IAAI,oBAAoB,CAAC,OAAO,EAChD,yDAAyD,CAC1D,CAAC;IACF,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACjE,SAAS,CACP,OAAO,CAAC,KAAK,CACX,CAAC,IAAI,EAAE,EAAE,CACP,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CACnE,EACD,+EAA+E,CAChF,CAAC;IACF,IAAI,OAAO,CAAC,MAAM;QAAE,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IAClE,OAAO,EAAE,gBAAgB,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,OAA+C,EAC/C,MAAuD;IAEvD,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,qBAAqB,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IACrD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,YAAY,CACpB,UAAU,EACV,8HAA8H,EAC9H,EAAE,KAAK,EAAE,qBAAqB,EAAE,EAChC,KAAK,CACN,CAAC;IACJ,CAAC;AACH,CAAC","sourcesContent":["import { isIP } from \"node:net\";\nimport type { Sandbox } from \"@daytona/sdk\";\nimport { validateEgress } from \"../domain/egress.ts\";\nimport { invariant, OutpostError } from \"../domain/errors.ts\";\nimport {\n daytonaNetworkFields,\n daytonaNetworkLimits,\n} from \"./daytona-network.constants.ts\";\nimport type { DaytonaOptions } from \"./daytona.types.ts\";\n\nexport function daytonaNetworkPolicy(\n options: DaytonaOptions,\n): Parameters<Sandbox[\"updateNetworkSettings\"]>[0] | undefined {\n const policy = validateEgress(options.egress);\n if (!policy) return undefined;\n invariant(\n daytonaNetworkFields.every(\n (field) => options.create?.[field] === undefined,\n ),\n \"Use egress or Daytona create network settings, not both\",\n );\n if (policy.mode === \"deny-all\") return { networkBlockAll: true };\n const domains = policy.domains ?? [];\n const cidrs = policy.allowCidrs ?? [];\n invariant(\n !policy.denyCidrs?.length,\n \"Daytona cannot enforce egress denyCidrs\",\n );\n invariant(\n !domains.length || !cidrs.length,\n \"Daytona cannot combine egress domains and allowCidrs\",\n );\n invariant(\n cidrs.every((entry) => isIP(entry.split(\"/\")[0]!) === 4),\n \"Daytona egress allowCidrs supports IPv4 only\",\n );\n invariant(\n cidrs.length <= daytonaNetworkLimits.cidrs &&\n domains.length <= daytonaNetworkLimits.domains,\n \"Daytona egress supports at most 10 CIDRs or 100 domains\",\n );\n const names = new Set(domains.map((name) => name.toLowerCase()));\n invariant(\n domains.every(\n (name) =>\n !name.startsWith(\"*.\") || names.has(name.slice(2).toLowerCase()),\n ),\n \"Daytona wildcard domains also allow the apex; list the apex domain explicitly\",\n );\n if (domains.length) return { domainAllowList: domains.join(\",\") };\n return { networkAllowList: cidrs.join(\",\") };\n}\n\nexport async function confirmDaytonaNetworkPolicy(\n sandbox: Pick<Sandbox, \"updateNetworkSettings\">,\n policy: Parameters<Sandbox[\"updateNetworkSettings\"]>[0],\n): Promise<void> {\n try {\n await sandbox.updateNetworkSettings({ ...policy });\n } catch (cause) {\n throw new OutpostError(\n \"provider\",\n \"Daytona could not confirm egress enforcement; sandbox-level network controls require Tier 3/4 and WRITE_SANDBOXES permission\",\n { stage: \"egress-confirmation\" },\n cause,\n );\n }\n}\n"]}
@@ -3,3 +3,4 @@ import type { SandboxProvider } from "../domain/sandbox.types.ts";
3
3
  import type { DaytonaOptions } from "./daytona.types.ts";
4
4
  export type { DaytonaOptions } from "./daytona.types.ts";
5
5
  export declare function daytonaSandboxProvider(options?: DaytonaOptions, connect?: (config?: DaytonaConfig) => Promise<Pick<Daytona, "create" | "delete">>): SandboxProvider;
6
+ export type { EgressPolicy } from "../domain/egress.types.ts";
@@ -1,12 +1,13 @@
1
- import { invariant } from "../domain/errors.js";
2
1
  import { posix } from "node:path";
3
2
  import { fileBatches } from "./file-batches.js";
4
3
  import { registerCleanup } from "../infrastructure/shutdown.js";
5
4
  import { cloudRoots } from "./cloud.constants.js";
5
+ import { daytonaNetworkPolicy, confirmDaytonaNetworkPolicy, } from "./daytona-network.js";
6
6
  import { daytonaCommand } from "./daytona-command.js";
7
7
  import { daytonaFiles } from "./daytona-files.js";
8
8
  export function daytonaSandboxProvider(options = {}, connect = async (config) => new (await import("@daytona/sdk")).Daytona(config)) {
9
- invariant(!("egress" in options) || options.egress === undefined, "Daytona does not support Outpost egress policies; configure provider-native networking explicitly");
9
+ const networkPolicy = daytonaNetworkPolicy(options);
10
+ const create = { ...options.create, ...networkPolicy };
10
11
  return {
11
12
  name: "daytona",
12
13
  placement: "remote",
@@ -14,7 +15,7 @@ export function daytonaSandboxProvider(options = {}, connect = async (config) =>
14
15
  async acquire(context) {
15
16
  context.signal?.throwIfAborted();
16
17
  const client = await connect(options.connection);
17
- const sandbox = await client.create(options.create ?? {});
18
+ const sandbox = await client.create({ ...create });
18
19
  let closed = false, releasing;
19
20
  let unregister = () => { };
20
21
  const release = () => (releasing ??= client
@@ -31,6 +32,11 @@ export function daytonaSandboxProvider(options = {}, connect = async (config) =>
31
32
  let home;
32
33
  let root;
33
34
  try {
35
+ context.signal?.throwIfAborted();
36
+ if (networkPolicy) {
37
+ await confirmDaytonaNetworkPolicy(sandbox, networkPolicy);
38
+ context.signal?.throwIfAborted();
39
+ }
34
40
  home = (await sandbox.getUserHomeDir()) ?? cloudRoots.daytonaHome;
35
41
  root = options.root ?? posix.join(home, "outpost");
36
42
  await sandbox.fs.createFolder(root, "755");
@@ -1 +1 @@
1
- {"version":3,"file":"daytona.js","sourceRoot":"","sources":["../../src/providers/daytona.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Daytona, DaytonaConfig } from \"@daytona/sdk\";\nimport { invariant } from \"../domain/errors.ts\";\nimport { posix } from \"node:path\";\nimport type { SandboxProvider } from \"../domain/sandbox.types.ts\";\nimport { fileBatches } from \"./file-batches.ts\";\nimport { registerCleanup } from \"../infrastructure/shutdown.ts\";\nimport { cloudRoots } from \"./cloud.constants.ts\";\nimport { daytonaCommand } from \"./daytona-command.ts\";\nimport { daytonaFiles } from \"./daytona-files.ts\";\nimport type { DaytonaOptions } from \"./daytona.types.ts\";\n\nexport type { DaytonaOptions } from \"./daytona.types.ts\";\n\nexport function daytonaSandboxProvider(\n options: DaytonaOptions = {},\n connect: (\n config?: DaytonaConfig,\n ) => Promise<Pick<Daytona, \"create\" | \"delete\">> = async (config) =>\n new (await import(\"@daytona/sdk\")).Daytona(config),\n): SandboxProvider {\n invariant(\n !(\"egress\" in options) || options.egress === undefined,\n \"Daytona does not support Outpost egress policies; configure provider-native networking explicitly\",\n );\n return {\n name: \"daytona\",\n placement: \"remote\",\n variables: { ...options.variables },\n async acquire(context) {\n context.signal?.throwIfAborted();\n const client = await connect(options.connection);\n const sandbox = await client.create(options.create ?? {});\n let closed = false,\n releasing: Promise<void> | undefined;\n let unregister = () => {};\n const release = () =>\n (releasing ??= client\n .delete(sandbox)\n .then(() => {\n closed = true;\n unregister();\n })\n .catch((error) => {\n releasing = undefined;\n throw error;\n }));\n unregister = registerCleanup(release);\n let home: string;\n let root: string;\n try {\n home = (await sandbox.getUserHomeDir()) ?? cloudRoots.daytonaHome;\n root = options.root ?? posix.join(home, \"outpost\");\n await sandbox.fs.createFolder(root, \"755\");\n } catch (cause) {\n try {\n await release();\n } catch (cleanup) {\n throw new AggregateError(\n [cause, cleanup],\n \"Cloud setup and cleanup failed\",\n );\n }\n throw cause;\n }\n const lease = {\n root,\n home,\n invoke: daytonaCommand({\n sandbox,\n root,\n options,\n context,\n isClosed: () => closed,\n }),\n ...daytonaFiles(sandbox),\n release,\n };\n return { ...lease, fileTransfers: fileBatches(lease) };\n },\n };\n}\n"]}
1
+ {"version":3,"file":"daytona.js","sourceRoot":"","sources":["../../src/providers/daytona.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Daytona, DaytonaConfig } from \"@daytona/sdk\";\nimport { posix } from \"node:path\";\nimport type { SandboxProvider } from \"../domain/sandbox.types.ts\";\nimport { fileBatches } from \"./file-batches.ts\";\nimport { registerCleanup } from \"../infrastructure/shutdown.ts\";\nimport { cloudRoots } from \"./cloud.constants.ts\";\nimport {\n daytonaNetworkPolicy,\n confirmDaytonaNetworkPolicy,\n} from \"./daytona-network.ts\";\nimport { daytonaCommand } from \"./daytona-command.ts\";\nimport { daytonaFiles } from \"./daytona-files.ts\";\nimport type { DaytonaOptions } from \"./daytona.types.ts\";\n\nexport type { DaytonaOptions } from \"./daytona.types.ts\";\n\nexport function daytonaSandboxProvider(\n options: DaytonaOptions = {},\n connect: (\n config?: DaytonaConfig,\n ) => Promise<Pick<Daytona, \"create\" | \"delete\">> = async (config) =>\n new (await import(\"@daytona/sdk\")).Daytona(config),\n): SandboxProvider {\n const networkPolicy = daytonaNetworkPolicy(options);\n const create = { ...options.create, ...networkPolicy };\n return {\n name: \"daytona\",\n placement: \"remote\",\n variables: { ...options.variables },\n async acquire(context) {\n context.signal?.throwIfAborted();\n const client = await connect(options.connection);\n const sandbox = await client.create({ ...create });\n let closed = false,\n releasing: Promise<void> | undefined;\n let unregister = () => {};\n const release = () =>\n (releasing ??= client\n .delete(sandbox)\n .then(() => {\n closed = true;\n unregister();\n })\n .catch((error) => {\n releasing = undefined;\n throw error;\n }));\n unregister = registerCleanup(release);\n let home: string;\n let root: string;\n try {\n context.signal?.throwIfAborted();\n if (networkPolicy) {\n await confirmDaytonaNetworkPolicy(sandbox, networkPolicy);\n context.signal?.throwIfAborted();\n }\n home = (await sandbox.getUserHomeDir()) ?? cloudRoots.daytonaHome;\n root = options.root ?? posix.join(home, \"outpost\");\n await sandbox.fs.createFolder(root, \"755\");\n } catch (cause) {\n try {\n await release();\n } catch (cleanup) {\n throw new AggregateError(\n [cause, cleanup],\n \"Cloud setup and cleanup failed\",\n );\n }\n throw cause;\n }\n const lease = {\n root,\n home,\n invoke: daytonaCommand({\n sandbox,\n root,\n options,\n context,\n isClosed: () => closed,\n }),\n ...daytonaFiles(sandbox),\n release,\n };\n return { ...lease, fileTransfers: fileBatches(lease) };\n },\n };\n}\n\nexport type { EgressPolicy } from \"../domain/egress.types.ts\";\n"]}
@@ -1,7 +1,9 @@
1
+ import type { EgressPolicy } from "../domain/egress.types.ts";
1
2
  import type { CreateSandboxFromImageParams, CreateSandboxFromSnapshotParams, DaytonaConfig, Sandbox as DaytonaSandbox } from "@daytona/sdk";
2
3
  import type { Variables } from "../domain/command.types.ts";
3
4
  import type { SandboxContext } from "../domain/sandbox.types.ts";
4
5
  export interface DaytonaOptions {
6
+ readonly egress?: EgressPolicy;
5
7
  readonly connection?: DaytonaConfig;
6
8
  readonly create?: CreateSandboxFromImageParams | CreateSandboxFromSnapshotParams;
7
9
  readonly variables?: Variables;
@@ -1 +1 @@
1
- {"version":3,"file":"daytona.types.js","sourceRoot":"","sources":["../../src/providers/daytona.types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n CreateSandboxFromImageParams,\n CreateSandboxFromSnapshotParams,\n DaytonaConfig,\n Sandbox as DaytonaSandbox,\n} from \"@daytona/sdk\";\nimport type { Variables } from \"../domain/command.types.ts\";\nimport type { SandboxContext } from \"../domain/sandbox.types.ts\";\n\nexport interface DaytonaOptions {\n readonly connection?: DaytonaConfig;\n readonly create?:\n CreateSandboxFromImageParams | CreateSandboxFromSnapshotParams;\n readonly variables?: Variables;\n readonly root?: string;\n readonly retain?: number;\n}\n\nexport interface DaytonaRuntime {\n readonly sandbox: DaytonaSandbox;\n readonly root: string;\n readonly options: DaytonaOptions;\n readonly context: SandboxContext;\n readonly isClosed: () => boolean;\n}\n"]}
1
+ {"version":3,"file":"daytona.types.js","sourceRoot":"","sources":["../../src/providers/daytona.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { EgressPolicy } from \"../domain/egress.types.ts\";\nimport type {\n CreateSandboxFromImageParams,\n CreateSandboxFromSnapshotParams,\n DaytonaConfig,\n Sandbox as DaytonaSandbox,\n} from \"@daytona/sdk\";\nimport type { Variables } from \"../domain/command.types.ts\";\nimport type { SandboxContext } from \"../domain/sandbox.types.ts\";\n\nexport interface DaytonaOptions {\n readonly egress?: EgressPolicy;\n readonly connection?: DaytonaConfig;\n readonly create?:\n CreateSandboxFromImageParams | CreateSandboxFromSnapshotParams;\n readonly variables?: Variables;\n readonly root?: string;\n readonly retain?: number;\n}\n\nexport interface DaytonaRuntime {\n readonly sandbox: DaytonaSandbox;\n readonly root: string;\n readonly options: DaytonaOptions;\n readonly context: SandboxContext;\n readonly isClosed: () => boolean;\n}\n"]}
@@ -5,7 +5,7 @@ import { firecrackerDefaults } from "./firecracker.constants.js";
5
5
  export function firecrackerSsh(options, script) {
6
6
  const ssh = options.ssh;
7
7
  return {
8
- executable: ssh.binary ?? "ssh",
8
+ executable: ssh.binary ?? (options.jailer ? "/usr/bin/ssh" : "ssh"),
9
9
  arguments: [
10
10
  "-F",
11
11
  "/dev/null",
@@ -1 +1 @@
1
- {"version":3,"file":"firecracker-command.js","sourceRoot":"","sources":["../../src/providers/firecracker-command.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { invariant, OutpostError, positive } from \"../domain/errors.ts\";\nimport type { Command } from \"../domain/command.types.ts\";\nimport type { SandboxLease } from \"../domain/sandbox.types.ts\";\nimport {\n executeProcess,\n quote,\n requireSuccess,\n} from \"../infrastructure/process.ts\";\nimport { firecrackerDefaults } from \"./firecracker.constants.ts\";\nimport type {\n FirecrackerOptions,\n FirecrackerRuntime,\n} from \"./firecracker.types.ts\";\n\nexport function firecrackerSsh(\n options: FirecrackerOptions,\n script: string,\n): Command {\n const ssh = options.ssh;\n return {\n executable: ssh.binary ?? \"ssh\",\n arguments: [\n \"-F\",\n \"/dev/null\",\n \"-T\",\n \"-o\",\n \"BatchMode=yes\",\n \"-o\",\n \"IdentitiesOnly=yes\",\n \"-o\",\n \"StrictHostKeyChecking=yes\",\n \"-o\",\n `UserKnownHostsFile=${ssh.knownHosts}`,\n \"-o\",\n \"GlobalKnownHostsFile=/dev/null\",\n \"-o\",\n \"ConnectTimeout=2\",\n \"-o\",\n \"ServerAliveInterval=2\",\n \"-o\",\n \"ServerAliveCountMax=2\",\n \"-i\",\n ssh.identity,\n \"-p\",\n String(ssh.port ?? 22),\n \"-l\",\n ssh.user,\n \"--\",\n ssh.host,\n script,\n ],\n };\n}\n\nexport function firecrackerCommand(\n runtime: FirecrackerRuntime,\n): SandboxLease[\"invoke\"] {\n return async (command) => {\n if (runtime.isClosed())\n throw new OutpostError(\"provider\", \"Firecracker sandbox is closed\");\n invariant(\n !command.interactive && !command.elevated,\n \"Firecracker research provider does not support interactive or elevated commands\",\n );\n command.signal?.throwIfAborted();\n const variables = { ...runtime.variables, ...command.variables };\n invariant(\n Object.keys(variables).every((key) =>\n /^[A-Za-z_][A-Za-z0-9_]*$/.test(key),\n ),\n \"Invalid environment key\",\n );\n const id = `/tmp/outpost-command-${randomUUID()}`;\n const wrapper = `umask 077; echo $$ > ${quote(id)}; test ! -e ${quote(id + \".cancel\")} || exit 130; cd ${quote(command.directory ?? runtime.root)} || exit; exec env ${Object.entries(\n variables,\n )\n .map(([key, value]) => quote(`${key}=${value}`))\n .join(\n \" \",\n )} ${[command.executable, ...(command.arguments ?? [])].map(quote).join(\" \")}`;\n const stop = new AbortController();\n const signal = command.signal\n ? AbortSignal.any([command.signal, stop.signal])\n : stop.signal;\n const deadlineMs = command.deadlineMs ?? firecrackerDefaults.commandMs;\n positive(deadlineMs, \"deadlineMs\");\n let cancellation: Promise<unknown> | undefined;\n const cancel = () => {\n cancellation ??= requireSuccess(\n {\n ...firecrackerSsh(\n runtime.options,\n `umask 077; touch ${quote(id + \".cancel\")}; if [ -f ${quote(id)} ]; then node -e ${quote(\"const fs=require('node:fs');const pid=Number(fs.readFileSync(process.argv[1],'utf8'));if(!Number.isSafeInteger(pid)||pid<2)process.exit(1);const kill=s=>{try{process.kill(-pid,s)}catch(e){if(e.code!=='ESRCH')throw e}};kill('SIGTERM');setTimeout(()=>kill('SIGKILL'),100)\")} ${quote(id)}; fi`,\n ),\n deadlineMs: firecrackerDefaults.cleanupMs,\n },\n executeProcess,\n );\n void cancellation.catch(() => undefined);\n };\n signal.addEventListener(\"abort\", cancel, { once: true });\n const timer = setTimeout(\n () =>\n stop.abort(\n new OutpostError(\"timeout\", `Command exceeded ${deadlineMs} ms`),\n ),\n deadlineMs,\n );\n let interrupted = false;\n try {\n const {\n directory: _directory,\n variables: _variables,\n ...invocation\n } = command;\n const result = await runtime.executor({\n ...invocation,\n ...(command.observe\n ? {\n observe: (channel, text) => {\n try {\n command.observe!(channel, text);\n } catch (cause) {\n stop.abort(cause);\n }\n },\n }\n : {}),\n signal,\n ...firecrackerSsh(\n runtime.options,\n `setsid --wait sh -c ${quote(wrapper)}`,\n ),\n });\n signal.throwIfAborted();\n return result;\n } catch (cause) {\n interrupted = true;\n try {\n cancel();\n await cancellation;\n } catch (cleanup) {\n throw new AggregateError(\n [cause, cleanup],\n \"Guest cancellation could not be confirmed; release the VM\",\n );\n }\n throw cause;\n } finally {\n clearTimeout(timer);\n signal.removeEventListener(\"abort\", cancel);\n if (!interrupted && !runtime.isClosed())\n await executeProcess({\n ...firecrackerSsh(runtime.options, `rm -f -- ${quote(id)}`),\n deadlineMs: firecrackerDefaults.cleanupMs,\n }).catch(() => undefined);\n }\n };\n}\n"]}
1
+ {"version":3,"file":"firecracker-command.js","sourceRoot":"","sources":["../../src/providers/firecracker-command.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { invariant, OutpostError, positive } from \"../domain/errors.ts\";\nimport type { Command } from \"../domain/command.types.ts\";\nimport type { SandboxLease } from \"../domain/sandbox.types.ts\";\nimport {\n executeProcess,\n quote,\n requireSuccess,\n} from \"../infrastructure/process.ts\";\nimport { firecrackerDefaults } from \"./firecracker.constants.ts\";\nimport type {\n FirecrackerOptions,\n FirecrackerRuntime,\n} from \"./firecracker.types.ts\";\n\nexport function firecrackerSsh(\n options: FirecrackerOptions,\n script: string,\n): Command {\n const ssh = options.ssh;\n return {\n executable: ssh.binary ?? (options.jailer ? \"/usr/bin/ssh\" : \"ssh\"),\n arguments: [\n \"-F\",\n \"/dev/null\",\n \"-T\",\n \"-o\",\n \"BatchMode=yes\",\n \"-o\",\n \"IdentitiesOnly=yes\",\n \"-o\",\n \"StrictHostKeyChecking=yes\",\n \"-o\",\n `UserKnownHostsFile=${ssh.knownHosts}`,\n \"-o\",\n \"GlobalKnownHostsFile=/dev/null\",\n \"-o\",\n \"ConnectTimeout=2\",\n \"-o\",\n \"ServerAliveInterval=2\",\n \"-o\",\n \"ServerAliveCountMax=2\",\n \"-i\",\n ssh.identity,\n \"-p\",\n String(ssh.port ?? 22),\n \"-l\",\n ssh.user,\n \"--\",\n ssh.host,\n script,\n ],\n };\n}\n\nexport function firecrackerCommand(\n runtime: FirecrackerRuntime,\n): SandboxLease[\"invoke\"] {\n return async (command) => {\n if (runtime.isClosed())\n throw new OutpostError(\"provider\", \"Firecracker sandbox is closed\");\n invariant(\n !command.interactive && !command.elevated,\n \"Firecracker research provider does not support interactive or elevated commands\",\n );\n command.signal?.throwIfAborted();\n const variables = { ...runtime.variables, ...command.variables };\n invariant(\n Object.keys(variables).every((key) =>\n /^[A-Za-z_][A-Za-z0-9_]*$/.test(key),\n ),\n \"Invalid environment key\",\n );\n const id = `/tmp/outpost-command-${randomUUID()}`;\n const wrapper = `umask 077; echo $$ > ${quote(id)}; test ! -e ${quote(id + \".cancel\")} || exit 130; cd ${quote(command.directory ?? runtime.root)} || exit; exec env ${Object.entries(\n variables,\n )\n .map(([key, value]) => quote(`${key}=${value}`))\n .join(\n \" \",\n )} ${[command.executable, ...(command.arguments ?? [])].map(quote).join(\" \")}`;\n const stop = new AbortController();\n const signal = command.signal\n ? AbortSignal.any([command.signal, stop.signal])\n : stop.signal;\n const deadlineMs = command.deadlineMs ?? firecrackerDefaults.commandMs;\n positive(deadlineMs, \"deadlineMs\");\n let cancellation: Promise<unknown> | undefined;\n const cancel = () => {\n cancellation ??= requireSuccess(\n {\n ...firecrackerSsh(\n runtime.options,\n `umask 077; touch ${quote(id + \".cancel\")}; if [ -f ${quote(id)} ]; then node -e ${quote(\"const fs=require('node:fs');const pid=Number(fs.readFileSync(process.argv[1],'utf8'));if(!Number.isSafeInteger(pid)||pid<2)process.exit(1);const kill=s=>{try{process.kill(-pid,s)}catch(e){if(e.code!=='ESRCH')throw e}};kill('SIGTERM');setTimeout(()=>kill('SIGKILL'),100)\")} ${quote(id)}; fi`,\n ),\n deadlineMs: firecrackerDefaults.cleanupMs,\n },\n executeProcess,\n );\n void cancellation.catch(() => undefined);\n };\n signal.addEventListener(\"abort\", cancel, { once: true });\n const timer = setTimeout(\n () =>\n stop.abort(\n new OutpostError(\"timeout\", `Command exceeded ${deadlineMs} ms`),\n ),\n deadlineMs,\n );\n let interrupted = false;\n try {\n const {\n directory: _directory,\n variables: _variables,\n ...invocation\n } = command;\n const result = await runtime.executor({\n ...invocation,\n ...(command.observe\n ? {\n observe: (channel, text) => {\n try {\n command.observe!(channel, text);\n } catch (cause) {\n stop.abort(cause);\n }\n },\n }\n : {}),\n signal,\n ...firecrackerSsh(\n runtime.options,\n `setsid --wait sh -c ${quote(wrapper)}`,\n ),\n });\n signal.throwIfAborted();\n return result;\n } catch (cause) {\n interrupted = true;\n try {\n cancel();\n await cancellation;\n } catch (cleanup) {\n throw new AggregateError(\n [cause, cleanup],\n \"Guest cancellation could not be confirmed; release the VM\",\n );\n }\n throw cause;\n } finally {\n clearTimeout(timer);\n signal.removeEventListener(\"abort\", cancel);\n if (!interrupted && !runtime.isClosed())\n await executeProcess({\n ...firecrackerSsh(runtime.options, `rm -f -- ${quote(id)}`),\n deadlineMs: firecrackerDefaults.cleanupMs,\n }).catch(() => undefined);\n }\n };\n}\n"]}
@@ -0,0 +1,9 @@
1
+ export declare const firecrackerJailerLimits: {
2
+ readonly cgroupRoot: "/sys/fs/cgroup";
3
+ readonly cgroupFilesystem: 1667723888;
4
+ readonly cpuPeriodUs: 100000;
5
+ readonly minimumCpuQuotaUs: 1000;
6
+ readonly minimumProcesses: 16;
7
+ readonly maximumIdentity: 4294967294;
8
+ readonly bytesPerMiB: number;
9
+ };
@@ -0,0 +1,10 @@
1
+ export const firecrackerJailerLimits = {
2
+ cgroupRoot: "/sys/fs/cgroup",
3
+ cgroupFilesystem: 0x63677270,
4
+ cpuPeriodUs: 100_000,
5
+ minimumCpuQuotaUs: 1000,
6
+ minimumProcesses: 16,
7
+ maximumIdentity: 4_294_967_294,
8
+ bytesPerMiB: 1024 * 1024,
9
+ };
10
+ //# sourceMappingURL=firecracker-jailer.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firecracker-jailer.constants.js","sourceRoot":"","sources":["../../src/providers/firecracker-jailer.constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,UAAU,EAAE,gBAAgB;IAC5B,gBAAgB,EAAE,UAAU;IAC5B,WAAW,EAAE,OAAO;IACpB,iBAAiB,EAAE,IAAI;IACvB,gBAAgB,EAAE,EAAE;IACpB,eAAe,EAAE,aAAa;IAC9B,WAAW,EAAE,IAAI,GAAG,IAAI;CAChB,CAAC","sourcesContent":["export const firecrackerJailerLimits = {\n cgroupRoot: \"/sys/fs/cgroup\",\n cgroupFilesystem: 0x63677270,\n cpuPeriodUs: 100_000,\n minimumCpuQuotaUs: 1000,\n minimumProcesses: 16,\n maximumIdentity: 4_294_967_294,\n bytesPerMiB: 1024 * 1024,\n} as const;\n"]}
@@ -0,0 +1,4 @@
1
+ import type { FirecrackerOptions, FirecrackerLaunch } from "./firecracker.types.ts";
2
+ export declare function validateJailer(options: FirecrackerOptions): void;
3
+ export declare function trustedJailerPath(path: string): Promise<void>;
4
+ export declare function prepareJailer(options: FirecrackerOptions, directory: string, signal?: AbortSignal): Promise<FirecrackerLaunch>;
@@ -0,0 +1,171 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { constants } from "node:fs";
3
+ import { access, chmod, chown, copyFile, lstat, mkdir, readFile, rm, rmdir, statfs, writeFile, } from "node:fs/promises";
4
+ import { basename, dirname, isAbsolute, join, normalize, relative, } from "node:path";
5
+ import { invariant, OutpostError } from "../domain/errors.js";
6
+ import { firecrackerJailerLimits as limits } from "./firecracker-jailer.constants.js";
7
+ import { firecrackerDefaults } from "./firecracker.constants.js";
8
+ export function validateJailer(options) {
9
+ const jailer = options.jailer;
10
+ if (!jailer)
11
+ return;
12
+ for (const path of [jailer.binary, jailer.directory, jailer.cgroup])
13
+ invariant(path.startsWith("/") &&
14
+ !path.includes("\0") &&
15
+ !path.split("/").includes(".."), "Jailer paths must be absolute without traversal");
16
+ invariant(jailer.cgroup.startsWith(`${limits.cgroupRoot}/`) &&
17
+ relative(limits.cgroupRoot, jailer.cgroup) !== "", "Jailer requires a dedicated cgroup v2 parent beneath /sys/fs/cgroup");
18
+ for (const value of [
19
+ jailer.uid,
20
+ jailer.gid,
21
+ jailer.cpuQuotaUs,
22
+ jailer.memoryMaxMb,
23
+ jailer.processes,
24
+ ])
25
+ invariant(Number.isSafeInteger(value) && value > 0, "Jailer identities and resource limits must be positive integers");
26
+ invariant(jailer.cpuQuotaUs >= limits.minimumCpuQuotaUs, "Jailer CPU quota must be at least 1000 microseconds per 100000 microseconds");
27
+ invariant(jailer.memoryMaxMb > (options.memoryMb ?? firecrackerDefaults.memoryMb), "Jailer memory limit must exceed guest memory to allow VMM overhead");
28
+ invariant(Number.isSafeInteger(jailer.memoryMaxMb * limits.bytesPerMiB), "Jailer memory limit is too large");
29
+ invariant(jailer.uid <= limits.maximumIdentity &&
30
+ jailer.gid <= limits.maximumIdentity, "Jailer identities must fit Linux UID/GID limits");
31
+ invariant(jailer.processes >= limits.minimumProcesses, "Jailer process limit must allow at least 16 threads");
32
+ }
33
+ export async function trustedJailerPath(path) {
34
+ invariant(isAbsolute(path) && normalize(path) === path, "Jailer paths must be canonical absolute paths");
35
+ let current = path;
36
+ while (true) {
37
+ const entry = await lstat(current);
38
+ invariant(!entry.isSymbolicLink() && entry.uid === 0 && (entry.mode & 0o022) === 0, `Jailer path must be root-owned, without symlinks or group/world write access: ${current}`);
39
+ const parent = dirname(current);
40
+ if (parent === current)
41
+ return;
42
+ current = parent;
43
+ }
44
+ }
45
+ export async function prepareJailer(options, directory, signal) {
46
+ const jailer = options.jailer;
47
+ invariant(jailer, "Jailer configuration is required");
48
+ invariant(process.getuid?.() === 0, "Jailer allocation requires a trusted root supervisor; Outpost never invokes sudo");
49
+ await Promise.all([
50
+ jailer.binary,
51
+ jailer.directory,
52
+ jailer.cgroup,
53
+ options.binary,
54
+ options.kernel,
55
+ options.rootfs,
56
+ options.ssh.identity,
57
+ options.ssh.knownHosts,
58
+ options.ssh.binary ?? "/usr/bin/ssh",
59
+ ].map(trustedJailerPath));
60
+ await access(jailer.binary, constants.X_OK);
61
+ invariant((await statfs(jailer.cgroup)).type === limits.cgroupFilesystem, "Jailer parent must be on cgroup v2");
62
+ const controllers = (await readFile(join(jailer.cgroup, "cgroup.subtree_control"), "utf8")).split(/\s+/);
63
+ invariant(["cpu", "memory", "pids"].every((name) => controllers.includes(name)), "Enable cpu, memory and pids controllers in the dedicated jailer parent");
64
+ const parent = join(jailer.directory, basename(options.binary));
65
+ await mkdir(parent, { recursive: true, mode: 0o700 });
66
+ await trustedJailerPath(parent);
67
+ const id = randomUUID();
68
+ const jail = join(parent, id);
69
+ const root = join(jail, "root");
70
+ const cgroup = join(jailer.cgroup, id);
71
+ await mkdir(jail, { mode: 0o700 });
72
+ const cleanup = async () => {
73
+ try {
74
+ const events = await readFile(join(cgroup, "cgroup.events"), "utf8");
75
+ if (/^populated 1$/m.test(events))
76
+ throw new OutpostError("provider", `Jailer cgroup is still populated; recovery files retained at ${jail}`);
77
+ await rmdir(cgroup);
78
+ }
79
+ catch (cause) {
80
+ if (!(cause instanceof Error &&
81
+ "code" in cause &&
82
+ cause.code === "ENOENT"))
83
+ throw cause;
84
+ }
85
+ await rm(jail, { recursive: true, force: true });
86
+ };
87
+ try {
88
+ await mkdir(root, { mode: 0o700 });
89
+ await copyFile(options.kernel, join(root, "kernel"));
90
+ await copyFile(join(directory, "rootfs.ext4"), join(root, "rootfs.ext4"), constants.COPYFILE_FICLONE);
91
+ const config = JSON.parse(await readFile(join(directory, "config.json"), "utf8"));
92
+ invariant(config !== null &&
93
+ typeof config === "object" &&
94
+ "boot-source" in config &&
95
+ "drives" in config, "Invalid Firecracker boot configuration");
96
+ await writeFile(join(root, "config.json"), JSON.stringify({
97
+ ...config,
98
+ "boot-source": {
99
+ kernel_image_path: "/kernel",
100
+ boot_args: options.bootArgs,
101
+ },
102
+ drives: [
103
+ {
104
+ drive_id: "rootfs",
105
+ path_on_host: "/rootfs.ext4",
106
+ is_root_device: true,
107
+ is_read_only: false,
108
+ },
109
+ ],
110
+ }), { mode: 0o400 });
111
+ for (const name of ["kernel", "rootfs.ext4", "config.json"]) {
112
+ await chown(join(root, name), jailer.uid, jailer.gid);
113
+ await chmod(join(root, name), name === "rootfs.ext4" ? 0o600 : 0o400);
114
+ }
115
+ signal?.throwIfAborted();
116
+ }
117
+ catch (cause) {
118
+ try {
119
+ await cleanup();
120
+ }
121
+ catch (cleanupFailure) {
122
+ throw new AggregateError([cause, cleanupFailure], `Jailer preparation and cleanup failed; inspect ${jail}`);
123
+ }
124
+ throw cause;
125
+ }
126
+ return {
127
+ binary: jailer.binary,
128
+ arguments: [
129
+ "--id",
130
+ id,
131
+ "--exec-file",
132
+ options.binary,
133
+ "--uid",
134
+ String(jailer.uid),
135
+ "--gid",
136
+ String(jailer.gid),
137
+ "--chroot-base-dir",
138
+ jailer.directory,
139
+ "--cgroup-version",
140
+ "2",
141
+ "--parent-cgroup",
142
+ relative(limits.cgroupRoot, jailer.cgroup),
143
+ "--cgroup",
144
+ `cpu.max=${jailer.cpuQuotaUs} ${limits.cpuPeriodUs}`,
145
+ "--cgroup",
146
+ `memory.max=${jailer.memoryMaxMb * limits.bytesPerMiB}`,
147
+ "--cgroup",
148
+ "memory.swap.max=0",
149
+ "--cgroup",
150
+ `pids.max=${jailer.processes}`,
151
+ "--",
152
+ "--api-sock",
153
+ "/api.sock",
154
+ "--config-file",
155
+ "/config.json",
156
+ ],
157
+ async stop() {
158
+ try {
159
+ await writeFile(join(cgroup, "cgroup.kill"), "1");
160
+ }
161
+ catch (cause) {
162
+ if (!(cause instanceof Error &&
163
+ "code" in cause &&
164
+ cause.code === "ENOENT"))
165
+ throw cause;
166
+ }
167
+ },
168
+ cleanup,
169
+ };
170
+ }
171
+ //# sourceMappingURL=firecracker-jailer.js.map