windows-development-sandbox 1.5.0 → 1.9.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 (709) hide show
  1. package/README.md +1 -0
  2. package/config.example.json +27 -1
  3. package/dist/app/context.d.ts +8 -0
  4. package/dist/app/context.js +12 -0
  5. package/dist/app/features/defs.d.ts +322 -0
  6. package/dist/app/features/defs.js +28 -0
  7. package/dist/app/features/sandbox/index.d.ts +2 -0
  8. package/dist/app/features/sandbox/index.js +3 -0
  9. package/dist/app/features/sandbox/sandbox.def.d.ts +193 -0
  10. package/dist/app/features/sandbox/sandbox.def.js +245 -0
  11. package/dist/app/features/sandbox/sandbox.run.d.ts +72 -0
  12. package/dist/app/features/sandbox/sandbox.run.js +98 -0
  13. package/dist/app/features/sessions/index.d.ts +2 -0
  14. package/dist/app/features/sessions/index.js +3 -0
  15. package/dist/app/features/sessions/sessions.def.d.ts +141 -0
  16. package/dist/app/features/sessions/sessions.def.js +176 -0
  17. package/dist/app/features/sessions/sessions.run.d.ts +39 -0
  18. package/dist/app/features/sessions/sessions.run.js +58 -0
  19. package/dist/{cli/menu/settings/categories.d.ts → app/features/settings/categories.def.d.ts} +4 -0
  20. package/dist/{cli/menu/settings/categories.js → app/features/settings/categories.def.js} +40 -46
  21. package/dist/app/features/settings/index.d.ts +5 -0
  22. package/dist/app/features/settings/index.js +6 -0
  23. package/dist/{cli/menu/settings/config-file.d.ts → app/features/settings/settings-file.d.ts} +1 -1
  24. package/dist/{cli/menu/settings/config-file.js → app/features/settings/settings-file.js} +1 -1
  25. package/dist/app/features/settings/settings-rows.d.ts +35 -0
  26. package/dist/app/features/settings/settings-rows.js +94 -0
  27. package/dist/app/features/settings/settings.def.d.ts +157 -0
  28. package/dist/app/features/settings/settings.def.js +179 -0
  29. package/dist/app/features/settings/settings.run.d.ts +67 -0
  30. package/dist/app/features/settings/settings.run.js +84 -0
  31. package/dist/app/kernel/define.d.ts +143 -0
  32. package/dist/app/kernel/define.js +42 -0
  33. package/dist/app/kernel/errors.d.ts +34 -0
  34. package/dist/app/kernel/errors.js +45 -0
  35. package/dist/app/kernel/fields.d.ts +70 -0
  36. package/dist/app/kernel/fields.js +243 -0
  37. package/dist/app/kernel/index.d.ts +8 -0
  38. package/dist/app/kernel/index.js +10 -0
  39. package/dist/app/kernel/io.d.ts +193 -0
  40. package/dist/app/kernel/io.js +126 -0
  41. package/dist/app/kernel/rpc.d.ts +156 -0
  42. package/dist/app/kernel/rpc.js +47 -0
  43. package/dist/{cli/menu/settings → app/kernel}/schema-node.d.ts +9 -0
  44. package/dist/{cli/menu/settings → app/kernel}/schema-node.js +26 -0
  45. package/dist/app/kernel/text.d.ts +6 -0
  46. package/dist/app/kernel/text.js +57 -0
  47. package/dist/app/kernel/view.d.ts +146 -0
  48. package/dist/app/kernel/view.js +28 -0
  49. package/dist/app/registry.d.ts +10 -0
  50. package/dist/app/registry.js +50 -0
  51. package/dist/cli/args.d.ts +18 -2
  52. package/dist/cli/args.js +101 -24
  53. package/dist/cli/commands/accounts.js +45 -17
  54. package/dist/cli/commands/context.d.ts +2 -0
  55. package/dist/cli/commands/context.js +9 -2
  56. package/dist/cli/commands/data/clean.js +32 -9
  57. package/dist/cli/commands/engine.d.ts +2 -0
  58. package/dist/cli/commands/engine.js +60 -0
  59. package/dist/cli/commands/index.d.ts +2 -1
  60. package/dist/cli/commands/index.js +2 -1
  61. package/dist/cli/commands/launch/add-root.d.ts +3 -2
  62. package/dist/cli/commands/launch/add-root.js +11 -10
  63. package/dist/cli/commands/launch/launch.js +102 -9
  64. package/dist/cli/commands/launch/prepare.js +6 -4
  65. package/dist/cli/commands/launch/running.js +2 -1
  66. package/dist/cli/commands/launch/summary.d.ts +2 -0
  67. package/dist/cli/commands/maintenance/audit.js +1 -1
  68. package/dist/cli/commands/maintenance/clean.d.ts +1 -1
  69. package/dist/cli/commands/maintenance/clean.js +17 -3
  70. package/dist/cli/commands/maintenance/config-share.d.ts +12 -0
  71. package/dist/cli/commands/maintenance/config-share.js +80 -0
  72. package/dist/cli/commands/maintenance/config.d.ts +1 -1
  73. package/dist/cli/commands/maintenance/config.js +38 -10
  74. package/dist/cli/commands/maintenance/doctor.d.ts +1 -1
  75. package/dist/cli/commands/maintenance/doctor.js +2 -4
  76. package/dist/cli/commands/maintenance/logs.js +14 -0
  77. package/dist/cli/commands/maintenance/migrate.d.ts +2 -1
  78. package/dist/cli/commands/maintenance/migrate.js +19 -4
  79. package/dist/cli/commands/maintenance/sync.js +2 -0
  80. package/dist/cli/commands/maintenance/update.d.ts +2 -0
  81. package/dist/cli/commands/maintenance/update.js +27 -4
  82. package/dist/cli/commands/projects/here.js +12 -7
  83. package/dist/cli/commands/projects/projects.js +26 -17
  84. package/dist/cli/commands/registry.js +10 -7
  85. package/dist/cli/commands/repair/checks/agents.d.ts +2 -0
  86. package/dist/cli/commands/repair/checks/agents.js +70 -0
  87. package/dist/cli/commands/repair/checks/common.d.ts +8 -0
  88. package/dist/cli/commands/repair/checks/common.js +22 -0
  89. package/dist/cli/commands/repair/checks/contained.d.ts +2 -0
  90. package/dist/cli/commands/repair/checks/contained.js +139 -0
  91. package/dist/cli/commands/repair/checks/data.d.ts +2 -0
  92. package/dist/cli/commands/repair/checks/data.js +241 -0
  93. package/dist/cli/commands/repair/checks/hcs.d.ts +7 -0
  94. package/dist/cli/commands/repair/checks/hcs.js +28 -0
  95. package/dist/cli/commands/repair/checks/index.d.ts +2 -0
  96. package/dist/cli/commands/repair/checks/index.js +24 -0
  97. package/dist/cli/commands/repair/checks/install.d.ts +5 -0
  98. package/dist/cli/commands/repair/checks/install.js +318 -0
  99. package/dist/cli/commands/repair/checks/machine.d.ts +2 -0
  100. package/dist/cli/commands/repair/checks/machine.js +232 -0
  101. package/dist/cli/commands/repair/checks/network.d.ts +6 -0
  102. package/dist/cli/commands/repair/checks/network.js +60 -0
  103. package/dist/cli/commands/repair/checks/pc.d.ts +4 -0
  104. package/dist/cli/commands/repair/checks/pc.js +86 -0
  105. package/dist/cli/commands/repair/checks/sandbox.d.ts +2 -0
  106. package/dist/cli/commands/repair/checks/sandbox.js +282 -0
  107. package/dist/cli/commands/repair/checks/settings.d.ts +2 -0
  108. package/dist/cli/commands/repair/checks/settings.js +169 -0
  109. package/dist/cli/commands/repair/checks/vpn.d.ts +2 -0
  110. package/dist/cli/commands/repair/checks/vpn.js +78 -0
  111. package/dist/cli/commands/repair/engine.d.ts +32 -0
  112. package/dist/cli/commands/repair/engine.js +127 -0
  113. package/dist/cli/commands/repair/env.d.ts +7 -0
  114. package/dist/cli/commands/repair/env.js +50 -0
  115. package/dist/cli/commands/repair/index.d.ts +1 -9
  116. package/dist/cli/commands/repair/index.js +2 -54
  117. package/dist/cli/commands/repair/log.d.ts +17 -0
  118. package/dist/cli/commands/repair/log.js +82 -0
  119. package/dist/cli/commands/repair/printer.d.ts +32 -0
  120. package/dist/cli/commands/repair/printer.js +132 -0
  121. package/dist/cli/commands/repair/run.d.ts +33 -0
  122. package/dist/cli/commands/repair/run.js +133 -0
  123. package/dist/cli/commands/repair/types.d.ts +97 -9
  124. package/dist/cli/commands/repair/types.js +11 -7
  125. package/dist/cli/commands/resume.js +2 -2
  126. package/dist/cli/commands/sessions/index.d.ts +0 -4
  127. package/dist/cli/commands/sessions/index.js +3 -7
  128. package/dist/cli/commands/setup/index.d.ts +5 -0
  129. package/dist/cli/commands/setup/index.js +25 -1
  130. package/dist/cli/commands/shared-use.d.ts +5 -2
  131. package/dist/cli/commands/shared-use.js +11 -8
  132. package/dist/cli/commands/storage/contained.d.ts +3 -0
  133. package/dist/cli/commands/storage/contained.js +179 -0
  134. package/dist/cli/commands/storage/index.d.ts +2 -0
  135. package/dist/cli/commands/storage/index.js +2 -0
  136. package/dist/cli/commands/storage/offer.d.ts +3 -0
  137. package/dist/cli/commands/storage/offer.js +91 -0
  138. package/dist/cli/commands/storage/storage.d.ts +8 -0
  139. package/dist/cli/commands/storage/storage.js +179 -0
  140. package/dist/cli/commands/user-config.js +2 -2
  141. package/dist/cli/commands/vpn.d.ts +4 -0
  142. package/dist/cli/commands/vpn.js +91 -0
  143. package/dist/cli/commands/web.d.ts +4 -0
  144. package/dist/cli/commands/web.js +97 -0
  145. package/dist/cli/history.js +1 -1
  146. package/dist/cli/index.js +48 -4
  147. package/dist/cli/manifest.d.ts +339 -97
  148. package/dist/cli/manifest.js +222 -67
  149. package/dist/cli/menu/add-agent.d.ts +47 -0
  150. package/dist/cli/menu/add-agent.js +168 -0
  151. package/dist/cli/menu/apps.d.ts +38 -3
  152. package/dist/cli/menu/apps.js +80 -5
  153. package/dist/cli/menu/command-fields.d.ts +18 -0
  154. package/dist/cli/menu/command-fields.js +61 -0
  155. package/dist/cli/menu/command-form.d.ts +22 -0
  156. package/dist/cli/menu/command-form.js +169 -46
  157. package/dist/cli/menu/data-folder.d.ts +18 -0
  158. package/dist/cli/menu/data-folder.js +99 -0
  159. package/dist/cli/menu/io-menu.d.ts +29 -0
  160. package/dist/cli/menu/io-menu.js +126 -0
  161. package/dist/cli/menu/live.d.ts +27 -0
  162. package/dist/cli/menu/live.js +69 -0
  163. package/dist/cli/menu/memory.d.ts +19 -0
  164. package/dist/cli/menu/memory.js +53 -0
  165. package/dist/cli/menu/menu.d.ts +11 -2
  166. package/dist/cli/menu/menu.js +36 -15
  167. package/dist/cli/menu/pages/accounts-page.js +55 -24
  168. package/dist/cli/menu/pages/agents-page.d.ts +68 -0
  169. package/dist/cli/menu/pages/agents-page.js +345 -0
  170. package/dist/cli/menu/pages/apps-page.d.ts +3 -1
  171. package/dist/cli/menu/pages/apps-page.js +20 -4
  172. package/dist/cli/menu/pages/list-page.d.ts +43 -3
  173. package/dist/cli/menu/pages/list-page.js +146 -12
  174. package/dist/cli/menu/pages/maintenance-page.d.ts +9 -5
  175. package/dist/cli/menu/pages/maintenance-page.js +172 -85
  176. package/dist/cli/menu/pages/sandbox-page.d.ts +7 -6
  177. package/dist/cli/menu/pages/sandbox-page.js +117 -120
  178. package/dist/cli/menu/pages/scopes.d.ts +1 -1
  179. package/dist/cli/menu/pages/sessions-page.d.ts +6 -8
  180. package/dist/cli/menu/pages/sessions-page.js +22 -75
  181. package/dist/cli/menu/pages/settings-page.d.ts +10 -14
  182. package/dist/cli/menu/pages/settings-page.js +95 -102
  183. package/dist/cli/menu/render-view.d.ts +28 -0
  184. package/dist/cli/menu/render-view.js +112 -0
  185. package/dist/cli/menu/settings/ask-path.d.ts +14 -0
  186. package/dist/cli/menu/settings/ask-path.js +14 -0
  187. package/dist/cli/menu/settings/collections/collection-editor.d.ts +8 -2
  188. package/dist/cli/menu/settings/collections/collection-editor.js +12 -8
  189. package/dist/cli/menu/settings/collections/map-editor.js +5 -1
  190. package/dist/cli/menu/settings/collections/object-list-editor.js +2 -2
  191. package/dist/cli/menu/settings/collections/object-map-editor.js +2 -2
  192. package/dist/cli/menu/settings/collections/string-list-editor.d.ts +10 -1
  193. package/dist/cli/menu/settings/collections/string-list-editor.js +23 -0
  194. package/dist/cli/menu/settings/draft.d.ts +1 -1
  195. package/dist/cli/menu/settings/format.d.ts +1 -3
  196. package/dist/cli/menu/settings/format.js +6 -36
  197. package/dist/cli/menu/settings/index.d.ts +1 -3
  198. package/dist/cli/menu/settings/index.js +3 -3
  199. package/dist/cli/menu/settings/object-editor.d.ts +6 -2
  200. package/dist/cli/menu/settings/object-editor.js +15 -4
  201. package/dist/cli/menu/settings/share.d.ts +36 -0
  202. package/dist/cli/menu/settings/share.js +131 -0
  203. package/dist/cli/menu/settings/value-editor.d.ts +10 -1
  204. package/dist/cli/menu/settings/value-editor.js +99 -63
  205. package/dist/cli/menu/several.js +7 -5
  206. package/dist/cli/menu/share-settings.d.ts +21 -0
  207. package/dist/cli/menu/share-settings.js +112 -0
  208. package/dist/cli/menu/shell.d.ts +53 -10
  209. package/dist/cli/menu/shell.js +115 -10
  210. package/dist/cli/menu/views.d.ts +7 -0
  211. package/dist/cli/menu/views.js +11 -0
  212. package/dist/cli/menu/vpn-login.d.ts +16 -0
  213. package/dist/cli/menu/vpn-login.js +74 -0
  214. package/dist/cli/operations/handler.d.ts +6 -0
  215. package/dist/cli/operations/handler.js +61 -0
  216. package/dist/cli/operations/index.d.ts +4 -0
  217. package/dist/cli/operations/index.js +5 -0
  218. package/dist/cli/operations/input.d.ts +6 -0
  219. package/dist/cli/operations/input.js +37 -0
  220. package/dist/cli/operations/io-cli.d.ts +7 -0
  221. package/dist/cli/operations/io-cli.js +62 -0
  222. package/dist/cli/operations/spec.d.ts +18 -0
  223. package/dist/cli/operations/spec.js +108 -0
  224. package/dist/cli/output/colors.d.ts +2 -2
  225. package/dist/cli/output/colors.js +2 -11
  226. package/dist/cli/output/index.d.ts +1 -0
  227. package/dist/cli/output/index.js +1 -0
  228. package/dist/cli/output/print.d.ts +5 -1
  229. package/dist/cli/output/print.js +15 -4
  230. package/dist/cli/output/progress.d.ts +15 -0
  231. package/dist/cli/output/progress.js +44 -0
  232. package/dist/cli/output/render-view.d.ts +4 -0
  233. package/dist/cli/output/render-view.js +63 -0
  234. package/dist/cli/services/accounts-service.d.ts +2 -0
  235. package/dist/cli/services/accounts-service.js +2 -2
  236. package/dist/cli/services/agent-commands-service.d.ts +2 -0
  237. package/dist/cli/services/agent-commands-service.js +11 -2
  238. package/dist/cli/services/health-service.d.ts +0 -6
  239. package/dist/cli/services/health-service.js +5 -42
  240. package/dist/cli/services/index.d.ts +3 -1
  241. package/dist/cli/services/index.js +3 -1
  242. package/dist/cli/services/logs-service.js +4 -3
  243. package/dist/cli/services/migrate-service.js +1 -1
  244. package/dist/cli/services/update-service.d.ts +2 -0
  245. package/dist/cli/services/update-service.js +13 -6
  246. package/dist/cli/services/vpn-service.d.ts +28 -0
  247. package/dist/cli/services/vpn-service.js +46 -0
  248. package/dist/cli/services/web-service.d.ts +22 -0
  249. package/dist/cli/services/web-service.js +111 -0
  250. package/dist/cli/tui/app.d.ts +12 -4
  251. package/dist/cli/tui/app.js +38 -9
  252. package/dist/cli/tui/dialogs/path-listing.d.ts +43 -0
  253. package/dist/cli/tui/dialogs/path-listing.js +127 -0
  254. package/dist/cli/tui/dialogs/path-picker.d.ts +67 -0
  255. package/dist/cli/tui/dialogs/path-picker.js +423 -0
  256. package/dist/cli/tui/dialogs/text-screen.d.ts +6 -0
  257. package/dist/cli/tui/dialogs/text-screen.js +10 -3
  258. package/dist/cli/tui/frame.d.ts +7 -10
  259. package/dist/cli/tui/frame.js +19 -10
  260. package/dist/cli/tui/index.d.ts +4 -3
  261. package/dist/cli/tui/index.js +2 -1
  262. package/dist/cli/tui/list/list-screen.d.ts +28 -2
  263. package/dist/cli/tui/list/list-screen.js +130 -66
  264. package/dist/cli/tui/list/list-types.d.ts +10 -4
  265. package/dist/cli/tui/nav.d.ts +29 -0
  266. package/dist/cli/tui/nav.js +67 -0
  267. package/dist/cli/tui/terminal.d.ts +7 -0
  268. package/dist/cli/tui/terminal.js +30 -10
  269. package/dist/cli/validate.d.ts +1 -1
  270. package/dist/cli/validate.js +3 -3
  271. package/dist/cli/version.d.ts +2 -0
  272. package/dist/cli/version.js +11 -0
  273. package/dist/core/config/defaults.js +13 -1
  274. package/dist/core/config/loader.js +12 -2
  275. package/dist/core/local-config/overrides.js +1 -0
  276. package/dist/core/prompt.d.ts +19 -0
  277. package/dist/core/prompt.js +43 -3
  278. package/dist/core/schema/common.d.ts +6 -0
  279. package/dist/core/schema/common.js +8 -0
  280. package/dist/core/schema/config.d.ts +36 -0
  281. package/dist/core/schema/config.js +26 -2
  282. package/dist/core/schema/harness.d.ts +2 -0
  283. package/dist/core/schema/harness.js +13 -2
  284. package/dist/core/schema/index.d.ts +3 -1
  285. package/dist/core/schema/index.js +3 -1
  286. package/dist/core/schema/profile.d.ts +1 -0
  287. package/dist/core/schema/profile.js +3 -0
  288. package/dist/core/schema/redact.d.ts +13 -0
  289. package/dist/core/schema/redact.js +75 -0
  290. package/dist/core/schema/sandbox.d.ts +6 -0
  291. package/dist/core/schema/sandbox.js +21 -3
  292. package/dist/core/schema/vpn.d.ts +18 -0
  293. package/dist/core/schema/vpn.js +22 -0
  294. package/dist/core/schema/web.d.ts +6 -0
  295. package/dist/core/schema/web.js +14 -0
  296. package/dist/core/types.d.ts +44 -0
  297. package/dist/core/util/fs.d.ts +2 -0
  298. package/dist/core/util/fs.js +9 -0
  299. package/dist/core/util/index.d.ts +1 -1
  300. package/dist/core/util/index.js +1 -1
  301. package/dist/guest/agents/agent-files.d.ts +54 -0
  302. package/dist/guest/agents/agent-files.js +67 -0
  303. package/dist/guest/agents/agent-installer.js +2 -9
  304. package/dist/guest/agents/local-state.d.ts +14 -0
  305. package/dist/guest/agents/local-state.js +218 -0
  306. package/dist/guest/agents/sbx-agent.d.ts +2 -0
  307. package/dist/guest/agents/sbx-agent.js +35 -0
  308. package/dist/guest/boot/boot.d.ts +4 -0
  309. package/dist/guest/boot/boot.js +51 -11
  310. package/dist/guest/daemon/daemon.js +8 -1
  311. package/dist/guest/daemon/exec.js +2 -1
  312. package/dist/guest/daemon/idle-shutdown.js +2 -0
  313. package/dist/guest/daemon/sessions.d.ts +5 -0
  314. package/dist/guest/daemon/sessions.js +20 -3
  315. package/dist/guest/entries/agent.d.ts +1 -0
  316. package/dist/guest/entries/agent.js +10 -0
  317. package/dist/guest/entries/daemon.js +5 -0
  318. package/dist/guest/governor/decide.d.ts +61 -0
  319. package/dist/guest/governor/decide.js +182 -0
  320. package/dist/guest/governor/governor.d.ts +42 -0
  321. package/dist/guest/governor/governor.js +214 -0
  322. package/dist/guest/governor/index.d.ts +2 -0
  323. package/dist/guest/governor/index.js +2 -0
  324. package/dist/guest/runtime/csc.d.ts +2 -0
  325. package/dist/guest/runtime/csc.js +2 -0
  326. package/dist/guest/runtime/secrets.d.ts +12 -0
  327. package/dist/guest/runtime/secrets.js +63 -0
  328. package/dist/guest/sessions/viewer.js +3 -1
  329. package/dist/guest/setup/claude-profile.d.ts +2 -1
  330. package/dist/guest/setup/claude-profile.js +12 -1
  331. package/dist/guest/setup/environment.d.ts +6 -0
  332. package/dist/guest/setup/environment.js +56 -6
  333. package/dist/guest/setup/path-plan.d.ts +32 -0
  334. package/dist/guest/setup/path-plan.js +67 -0
  335. package/dist/guest/setup/shell-path.d.ts +1 -0
  336. package/dist/guest/setup/shell-path.js +22 -0
  337. package/dist/guest/toolchains/languages/python.js +1 -1
  338. package/dist/guest/toolchains/native/rust-extras.js +4 -2
  339. package/dist/guest/toolchains/runtimes.js +2 -2
  340. package/dist/guest/vpn/index.d.ts +1 -0
  341. package/dist/guest/vpn/index.js +1 -0
  342. package/dist/guest/vpn/openvpn.d.ts +9 -0
  343. package/dist/guest/vpn/openvpn.js +47 -0
  344. package/dist/guest/vpn/tunnel.d.ts +17 -0
  345. package/dist/guest/vpn/tunnel.js +78 -0
  346. package/dist/guest/vpn/vpn.d.ts +6 -0
  347. package/dist/guest/vpn/vpn.js +174 -0
  348. package/dist/guest/vpn/wireguard.d.ts +32 -0
  349. package/dist/guest/vpn/wireguard.js +132 -0
  350. package/dist/host/agent-commands/commands.d.ts +4 -0
  351. package/dist/host/agent-commands/commands.js +31 -7
  352. package/dist/host/audit/log.d.ts +1 -1
  353. package/dist/host/channel/attach.d.ts +6 -2
  354. package/dist/host/channel/attach.js +6 -3
  355. package/dist/host/channel/channel.d.ts +9 -0
  356. package/dist/host/channel/channel.js +30 -2
  357. package/dist/host/engines/engine.d.ts +12 -0
  358. package/dist/host/engines/engine.js +1 -0
  359. package/dist/host/engines/hcs/check.d.ts +25 -0
  360. package/dist/host/engines/hcs/check.js +95 -0
  361. package/dist/host/engines/hcs/documents.d.ts +44 -0
  362. package/dist/host/engines/hcs/documents.js +155 -0
  363. package/dist/host/engines/hcs/engine.d.ts +39 -0
  364. package/dist/host/engines/hcs/engine.js +171 -0
  365. package/dist/host/engines/hcs/helper.d.ts +43 -0
  366. package/dist/host/engines/hcs/helper.js +173 -0
  367. package/dist/host/engines/hcs/images.d.ts +37 -0
  368. package/dist/host/engines/hcs/images.js +152 -0
  369. package/dist/host/engines/index.d.ts +7 -0
  370. package/dist/host/engines/index.js +5 -0
  371. package/dist/host/engines/registry.d.ts +16 -0
  372. package/dist/host/engines/registry.js +30 -0
  373. package/dist/host/engines/types.d.ts +58 -0
  374. package/dist/host/engines/types.js +1 -0
  375. package/dist/host/engines/windows-sandbox/engine.d.ts +16 -0
  376. package/dist/host/engines/windows-sandbox/engine.js +63 -0
  377. package/dist/host/engines/windows-sandbox/wsb-text.d.ts +2 -0
  378. package/dist/host/engines/windows-sandbox/wsb-text.js +29 -0
  379. package/dist/host/health/acl-read.d.ts +17 -0
  380. package/dist/host/health/acl-read.js +45 -0
  381. package/dist/host/health/config-backup.d.ts +11 -0
  382. package/dist/host/health/config-backup.js +73 -0
  383. package/dist/host/health/index.d.ts +6 -0
  384. package/dist/host/health/index.js +7 -0
  385. package/dist/host/health/install-state.d.ts +33 -0
  386. package/dist/host/health/install-state.js +110 -0
  387. package/dist/host/health/path-copies.d.ts +32 -0
  388. package/dist/host/health/path-copies.js +82 -0
  389. package/dist/host/health/stale.d.ts +45 -0
  390. package/dist/host/health/stale.js +120 -0
  391. package/dist/host/health/system.d.ts +37 -0
  392. package/dist/host/health/system.js +87 -0
  393. package/dist/host/install/copies.d.ts +13 -0
  394. package/dist/host/install/copies.js +63 -0
  395. package/dist/host/install/index.d.ts +1 -0
  396. package/dist/host/install/index.js +1 -0
  397. package/dist/host/launch/generate.d.ts +5 -1
  398. package/dist/host/launch/generate.js +73 -7
  399. package/dist/host/launch/index.d.ts +3 -1
  400. package/dist/host/launch/index.js +3 -1
  401. package/dist/host/launch/launch-plan.d.ts +13 -0
  402. package/dist/host/launch/launch-plan.js +26 -0
  403. package/dist/host/launch/mappings.js +2 -1
  404. package/dist/host/launch/risk-notes.d.ts +10 -0
  405. package/dist/host/launch/risk-notes.js +18 -0
  406. package/dist/host/launch/session-file.d.ts +2 -0
  407. package/dist/host/launch/session-file.js +11 -2
  408. package/dist/host/launch/stage.js +1 -1
  409. package/dist/host/launch/wsb-file.d.ts +28 -4
  410. package/dist/host/launch/wsb-file.js +61 -42
  411. package/dist/host/life/crash-report.d.ts +27 -1
  412. package/dist/host/life/crash-report.js +173 -7
  413. package/dist/host/life/host-memory.d.ts +40 -0
  414. package/dist/host/life/host-memory.js +137 -0
  415. package/dist/host/life/index.d.ts +2 -0
  416. package/dist/host/life/index.js +2 -0
  417. package/dist/host/life/stop-events.d.ts +2 -0
  418. package/dist/host/life/stop-events.js +20 -3
  419. package/dist/host/life/stop-warning.js +1 -1
  420. package/dist/host/life/watchdog.d.ts +54 -0
  421. package/dist/host/life/watchdog.js +108 -0
  422. package/dist/host/migrate/backup.js +3 -0
  423. package/dist/host/migrate/migrations/config-file.d.ts +2 -0
  424. package/dist/host/migrate/migrations/config-file.js +7 -0
  425. package/dist/host/migrate/migrations/follow-machine-storage.js +9 -1
  426. package/dist/host/migrate/migrations/pin-storage-root.d.ts +4 -0
  427. package/dist/host/migrate/migrations/pin-storage-root.js +46 -0
  428. package/dist/host/migrate/migrations/unpin-config-defaults.js +4 -1
  429. package/dist/host/migrate/registry.js +2 -1
  430. package/dist/host/native.d.ts +3 -2
  431. package/dist/host/native.js +22 -3
  432. package/dist/host/profile/accounts.d.ts +25 -1
  433. package/dist/host/profile/accounts.js +96 -13
  434. package/dist/host/profile/agent-accounts.d.ts +5 -1
  435. package/dist/host/profile/agent-accounts.js +35 -5
  436. package/dist/host/profile/claude-login.js +3 -2
  437. package/dist/host/profile/index.d.ts +2 -1
  438. package/dist/host/profile/index.js +1 -0
  439. package/dist/host/profile/plugin-share.d.ts +26 -0
  440. package/dist/host/profile/plugin-share.js +146 -0
  441. package/dist/host/projects/join.d.ts +7 -1
  442. package/dist/host/projects/join.js +21 -4
  443. package/dist/host/projects/registry.d.ts +16 -10
  444. package/dist/host/projects/registry.js +74 -6
  445. package/dist/host/sandbox/contained-deps.d.ts +2 -0
  446. package/dist/host/sandbox/contained-deps.js +17 -0
  447. package/dist/host/sandbox/index.d.ts +2 -0
  448. package/dist/host/sandbox/index.js +2 -0
  449. package/dist/host/sandbox/platform.d.ts +4 -0
  450. package/dist/host/sandbox/platform.js +23 -4
  451. package/dist/host/sandbox/tasklist.d.ts +13 -0
  452. package/dist/host/sandbox/tasklist.js +47 -0
  453. package/dist/host/secrets/index.d.ts +2 -0
  454. package/dist/host/secrets/index.js +2 -0
  455. package/dist/host/secrets/launch-secrets.d.ts +17 -0
  456. package/dist/host/secrets/launch-secrets.js +94 -0
  457. package/dist/host/secrets/secret-store.d.ts +25 -0
  458. package/dist/host/secrets/secret-store.js +89 -0
  459. package/dist/host/sharing/acl.d.ts +16 -2
  460. package/dist/host/sharing/acl.js +35 -10
  461. package/dist/host/sharing/current.js +8 -3
  462. package/dist/host/sharing/doctor.d.ts +2 -0
  463. package/dist/host/sharing/doctor.js +44 -0
  464. package/dist/host/sharing/group-access.d.ts +6 -0
  465. package/dist/host/sharing/group-access.js +24 -0
  466. package/dist/host/sharing/index.d.ts +2 -1
  467. package/dist/host/sharing/index.js +2 -1
  468. package/dist/host/sharing/lifecycle.d.ts +8 -2
  469. package/dist/host/sharing/lifecycle.js +16 -7
  470. package/dist/host/storage/cleanup.d.ts +2 -0
  471. package/dist/host/storage/cleanup.js +2 -1
  472. package/dist/host/storage/contained/check.d.ts +9 -0
  473. package/dist/host/storage/contained/check.js +37 -0
  474. package/dist/host/storage/contained/contained-storage.d.ts +66 -0
  475. package/dist/host/storage/contained/contained-storage.js +168 -0
  476. package/dist/host/storage/contained/disk-port.d.ts +43 -0
  477. package/dist/host/storage/contained/disk-port.js +122 -0
  478. package/dist/host/storage/contained/index.d.ts +9 -0
  479. package/dist/host/storage/contained/index.js +8 -0
  480. package/dist/host/storage/contained/layout.d.ts +28 -0
  481. package/dist/host/storage/contained/layout.js +45 -0
  482. package/dist/host/storage/contained/resolve.d.ts +4 -0
  483. package/dist/host/storage/contained/resolve.js +30 -0
  484. package/dist/host/storage/contained/setting.d.ts +1 -0
  485. package/dist/host/storage/contained/setting.js +5 -0
  486. package/dist/host/storage/contained/state.d.ts +89 -0
  487. package/dist/host/storage/contained/state.js +166 -0
  488. package/dist/host/storage/contained/transfer.d.ts +24 -0
  489. package/dist/host/storage/contained/transfer.js +121 -0
  490. package/dist/host/storage/history.d.ts +21 -0
  491. package/dist/host/storage/history.js +49 -0
  492. package/dist/host/storage/index.d.ts +6 -0
  493. package/dist/host/storage/index.js +6 -0
  494. package/dist/host/storage/move.d.ts +95 -0
  495. package/dist/host/storage/move.js +384 -0
  496. package/dist/host/storage/offer.d.ts +11 -0
  497. package/dist/host/storage/offer.js +36 -0
  498. package/dist/host/storage/providers/contained.d.ts +15 -0
  499. package/dist/host/storage/providers/contained.js +39 -0
  500. package/dist/host/storage/providers/folder.d.ts +12 -0
  501. package/dist/host/storage/providers/folder.js +20 -0
  502. package/dist/host/storage/providers/index.d.ts +4 -0
  503. package/dist/host/storage/providers/index.js +3 -0
  504. package/dist/host/storage/providers/registry.d.ts +9 -0
  505. package/dist/host/storage/providers/registry.js +14 -0
  506. package/dist/host/storage/providers/types.d.ts +33 -0
  507. package/dist/host/storage/providers/types.js +1 -0
  508. package/dist/host/storage/root.d.ts +18 -0
  509. package/dist/host/storage/root.js +77 -0
  510. package/dist/host/tools/conpty.js +3 -2
  511. package/dist/host/tools/windows-terminal.d.ts +2 -0
  512. package/dist/host/tools/windows-terminal.js +31 -12
  513. package/dist/host/update/index.d.ts +1 -1
  514. package/dist/host/update/index.js +1 -1
  515. package/dist/host/update/notice.d.ts +2 -0
  516. package/dist/host/update/notice.js +13 -1
  517. package/dist/host/update/update-state.d.ts +6 -0
  518. package/dist/host/update/update-state.js +2 -0
  519. package/dist/host/update/updater.d.ts +19 -0
  520. package/dist/host/update/updater.js +88 -12
  521. package/dist/host/vpn/index.d.ts +4 -0
  522. package/dist/host/vpn/index.js +4 -0
  523. package/dist/host/vpn/login.d.ts +24 -0
  524. package/dist/host/vpn/login.js +79 -0
  525. package/dist/host/vpn/nordvpn.d.ts +21 -0
  526. package/dist/host/vpn/nordvpn.js +77 -0
  527. package/dist/host/vpn/prepare.d.ts +19 -0
  528. package/dist/host/vpn/prepare.js +138 -0
  529. package/dist/host/vpn/status.d.ts +12 -0
  530. package/dist/host/vpn/status.js +53 -0
  531. package/dist/host/web/auth.d.ts +38 -0
  532. package/dist/host/web/auth.js +96 -0
  533. package/dist/host/web/backend.d.ts +14 -0
  534. package/dist/host/web/backend.js +1 -0
  535. package/dist/host/web/bridge.d.ts +27 -0
  536. package/dist/host/web/bridge.js +144 -0
  537. package/dist/host/web/browser.d.ts +3 -0
  538. package/dist/host/web/browser.js +23 -0
  539. package/dist/host/web/control.d.ts +17 -0
  540. package/dist/host/web/control.js +67 -0
  541. package/dist/host/web/index.d.ts +10 -0
  542. package/dist/host/web/index.js +9 -0
  543. package/dist/host/web/rpc.d.ts +24 -0
  544. package/dist/host/web/rpc.js +149 -0
  545. package/dist/host/web/runner.d.ts +16 -0
  546. package/dist/host/web/runner.js +44 -0
  547. package/dist/host/web/server.d.ts +47 -0
  548. package/dist/host/web/server.js +238 -0
  549. package/dist/host/web/state.d.ts +20 -0
  550. package/dist/host/web/state.js +41 -0
  551. package/dist/host/web/static-files.d.ts +13 -0
  552. package/dist/host/web/static-files.js +57 -0
  553. package/dist/runtime/agent.js +27675 -0
  554. package/dist/runtime/daemon.js +1950 -1122
  555. package/dist/runtime/db.js +302 -111
  556. package/dist/runtime/main.js +1560 -275
  557. package/dist/runtime/netproxy.js +168 -8
  558. package/dist/runtime/view.js +186 -13
  559. package/dist/selftest/accounts.test.js +40 -0
  560. package/dist/selftest/agent-paths.test.d.ts +2 -0
  561. package/dist/selftest/agent-paths.test.js +125 -0
  562. package/dist/selftest/app.test.d.ts +2 -0
  563. package/dist/selftest/app.test.js +324 -0
  564. package/dist/selftest/channel.test.js +18 -0
  565. package/dist/selftest/cli.test.js +35 -4
  566. package/dist/selftest/config.test.js +59 -0
  567. package/dist/selftest/contained.test.d.ts +2 -0
  568. package/dist/selftest/contained.test.js +544 -0
  569. package/dist/selftest/credentials.test.d.ts +2 -0
  570. package/dist/selftest/credentials.test.js +198 -0
  571. package/dist/selftest/engine.test.d.ts +2 -0
  572. package/dist/selftest/engine.test.js +127 -0
  573. package/dist/selftest/generate.test.js +1 -1
  574. package/dist/selftest/hcs.test.d.ts +2 -0
  575. package/dist/selftest/hcs.test.js +482 -0
  576. package/dist/selftest/health.test.d.ts +2 -0
  577. package/dist/selftest/health.test.js +470 -0
  578. package/dist/selftest/heavy-load.test.d.ts +2 -0
  579. package/dist/selftest/heavy-load.test.js +329 -0
  580. package/dist/selftest/host-sim.test.js +2 -0
  581. package/dist/selftest/index.js +31 -0
  582. package/dist/selftest/layout.test.js +14 -0
  583. package/dist/selftest/menu-perf.test.d.ts +2 -0
  584. package/dist/selftest/menu-perf.test.js +248 -0
  585. package/dist/selftest/menu-screens.d.ts +7 -0
  586. package/dist/selftest/menu-screens.js +68 -17
  587. package/dist/selftest/menu.test.js +603 -22
  588. package/dist/selftest/migrate.test.js +1 -1
  589. package/dist/selftest/personalization.test.js +3 -1
  590. package/dist/selftest/projects.test.js +39 -1
  591. package/dist/selftest/shared-use.test.js +64 -2
  592. package/dist/selftest/sharing.test.js +50 -1
  593. package/dist/selftest/storage.test.d.ts +2 -0
  594. package/dist/selftest/storage.test.js +363 -0
  595. package/dist/selftest/support/engine-cases.d.ts +8 -0
  596. package/dist/selftest/support/engine-cases.js +65 -0
  597. package/dist/selftest/support/engine-golden.d.ts +3 -0
  598. package/dist/selftest/support/engine-golden.js +66 -0
  599. package/dist/selftest/support/fixtures.d.ts +20 -0
  600. package/dist/selftest/support/hcs-probes.d.ts +17 -0
  601. package/dist/selftest/support/hcs-probes.js +41 -0
  602. package/dist/selftest/support/releases.js +1 -1
  603. package/dist/selftest/toolchains.test.js +21 -0
  604. package/dist/selftest/update-service.test.js +87 -3
  605. package/dist/selftest/vpn.test.d.ts +2 -0
  606. package/dist/selftest/vpn.test.js +412 -0
  607. package/dist/selftest/web.test.d.ts +2 -0
  608. package/dist/selftest/web.test.js +402 -0
  609. package/dist/shared/apps/catalogue.js +31 -0
  610. package/dist/shared/channel/index.d.ts +1 -0
  611. package/dist/shared/channel/index.js +1 -0
  612. package/dist/shared/channel/run-dir.d.ts +9 -1
  613. package/dist/shared/channel/run-dir.js +18 -1
  614. package/dist/shared/channel/schema.d.ts +53 -0
  615. package/dist/shared/channel/schema.js +38 -0
  616. package/dist/shared/channel/secrets.d.ts +29 -0
  617. package/dist/shared/channel/secrets.js +50 -0
  618. package/dist/shared/memory/index.d.ts +1 -0
  619. package/dist/shared/memory/index.js +1 -0
  620. package/dist/shared/memory/policy.d.ts +33 -0
  621. package/dist/shared/memory/policy.js +55 -0
  622. package/dist/shared/pty/output-filter.d.ts +14 -1
  623. package/dist/shared/pty/output-filter.js +22 -4
  624. package/dist/shared/pty/terminal.d.ts +4 -1
  625. package/dist/shared/pty/terminal.js +4 -2
  626. package/dist/shared/system.d.ts +1 -0
  627. package/dist/shared/system.js +1 -0
  628. package/dist/shared/vpn/download.d.ts +29 -0
  629. package/dist/shared/vpn/download.js +30 -0
  630. package/dist/shared/vpn/kill-switch.d.ts +18 -0
  631. package/dist/shared/vpn/kill-switch.js +81 -0
  632. package/dist/shared/vpn/ovpn.d.ts +23 -0
  633. package/dist/shared/vpn/ovpn.js +244 -0
  634. package/dist/shared/vpn/wireguard.d.ts +51 -0
  635. package/dist/shared/vpn/wireguard.js +227 -0
  636. package/dist/shared/web/index.d.ts +1 -0
  637. package/dist/shared/web/index.js +1 -0
  638. package/dist/shared/web/protocol.d.ts +61 -0
  639. package/dist/shared/web/protocol.js +35 -0
  640. package/dist/sync/sync-cycle.js +9 -5
  641. package/dist/sync/sync-state.d.ts +1 -0
  642. package/dist/sync/sync-state.js +1 -0
  643. package/dist/sync/watcher.d.ts +13 -0
  644. package/dist/sync/watcher.js +102 -3
  645. package/dist/web/index.html +14 -0
  646. package/dist/web/main-NRRS5O6Z.js +157 -0
  647. package/dist/web/main-T5DMCHYV.css +1 -0
  648. package/native/csharp/FolderSecurity.cs +29 -0
  649. package/native/csharp/HcsHost/AssemblyInfo.cs +14 -0
  650. package/native/csharp/HcsHost/Guard.cs +100 -0
  651. package/native/csharp/HcsHost/Hcs.cs +256 -0
  652. package/native/csharp/HcsHost/Json.cs +78 -0
  653. package/native/csharp/HcsHost/Program.cs +185 -0
  654. package/native/csharp/HcsHost/VirtualDisk.cs +95 -0
  655. package/native/csharp/HostTools/AssemblyInfo.cs +14 -0
  656. package/native/csharp/HostTools/MemoryStatus.cs +107 -0
  657. package/native/csharp/HostTools/Program.cs +58 -17
  658. package/native/scripts/check-contained.ps1 +28 -0
  659. package/native/scripts/contained-common.ps1 +241 -0
  660. package/native/scripts/dismount-contained.ps1 +66 -0
  661. package/native/scripts/memory-status.ps1 +34 -0
  662. package/native/scripts/mount-contained.ps1 +139 -0
  663. package/native/scripts/protect-data.ps1 +29 -0
  664. package/native/scripts/read-folder-sddl.ps1 +10 -0
  665. package/native/scripts/run-elevated.ps1 +17 -4
  666. package/native/scripts/set-folder-access.ps1 +49 -7
  667. package/native/scripts/stop-events.ps1 +23 -8
  668. package/node_modules/ws/LICENSE +20 -0
  669. package/node_modules/ws/README.md +548 -0
  670. package/node_modules/ws/browser.js +8 -0
  671. package/node_modules/ws/index.js +22 -0
  672. package/node_modules/ws/lib/buffer-util.js +131 -0
  673. package/node_modules/ws/lib/constants.js +19 -0
  674. package/node_modules/ws/lib/event-target.js +292 -0
  675. package/node_modules/ws/lib/extension.js +203 -0
  676. package/node_modules/ws/lib/limiter.js +55 -0
  677. package/node_modules/ws/lib/permessage-deflate.js +530 -0
  678. package/node_modules/ws/lib/receiver.js +743 -0
  679. package/node_modules/ws/lib/sender.js +607 -0
  680. package/node_modules/ws/lib/stream.js +161 -0
  681. package/node_modules/ws/lib/subprotocol.js +62 -0
  682. package/node_modules/ws/lib/validation.js +152 -0
  683. package/node_modules/ws/lib/websocket-server.js +562 -0
  684. package/node_modules/ws/lib/websocket.js +1421 -0
  685. package/node_modules/ws/package.json +74 -0
  686. package/node_modules/ws/wrapper.mjs +21 -0
  687. package/package.json +22 -5
  688. package/sandbox/csharp/EnvBroadcast.cs +33 -0
  689. package/sandbox/csharp/MemGov.cs +398 -0
  690. package/sandbox/csharp/PathSync.cs +90 -0
  691. package/sandbox/csharp/PtyHost.cs +111 -5
  692. package/sandbox/scripts/install-shell-path.ps1 +73 -0
  693. package/sandbox/scripts/set-machine-environment.ps1 +37 -4
  694. package/schemas/config.schema.json +136 -7
  695. package/schemas/sandbox-config.schema.json +17 -4
  696. package/dist/cli/commands/repair/checks.d.ts +0 -2
  697. package/dist/cli/commands/repair/checks.js +0 -246
  698. package/dist/cli/commands/sessions/control.d.ts +0 -4
  699. package/dist/cli/commands/sessions/control.js +0 -66
  700. package/dist/cli/commands/sessions/list.d.ts +0 -2
  701. package/dist/cli/commands/sessions/list.js +0 -45
  702. package/dist/cli/commands/sessions/status.d.ts +0 -2
  703. package/dist/cli/commands/sessions/status.js +0 -93
  704. package/dist/cli/commands/sessions/window.d.ts +0 -3
  705. package/dist/cli/commands/sessions/window.js +0 -18
  706. package/dist/cli/menu/pages/start-page.d.ts +0 -43
  707. package/dist/cli/menu/pages/start-page.js +0 -192
  708. package/dist/cli/tui/tab-bar.d.ts +0 -9
  709. package/dist/cli/tui/tab-bar.js +0 -33
@@ -15,26 +15,28 @@ export const AbsolutePathSchema = z
15
15
  .string()
16
16
  .max(1024)
17
17
  .refine((p) => path.isAbsolute(p), 'must be an absolute path');
18
- const RegistryEntrySchema = z.strictObject({
18
+ // Not strict: another copy or version of this tool may have written the file with more fields, and a registry that
19
+ // reads as nothing would make a running sandbox look like one that cannot take another folder.
20
+ const RegistryEntrySchema = z.object({
19
21
  name: IdSchema,
20
22
  host: AbsolutePathSchema,
21
23
  guest: z.string().max(1024),
22
24
  primary: z.boolean(),
23
- mechanism: z.enum(['launch', 'root', 'boot', 'wsb']),
25
+ mechanism: z.enum(['launch', 'root', 'boot', 'wsb']).catch('root'),
24
26
  registeredAt: z.string().max(64),
25
27
  });
26
- const RegistrySchema = z.strictObject({
28
+ const RegistrySchema = z.object({
27
29
  launchId: z.string().max(64),
28
30
  /** The running sandbox's protections (core/project-policy.ts), fixed at boot. */
29
31
  protections: z.record(z.string(), z.union([z.boolean(), z.string()])),
30
- roots: z.array(z.strictObject({ host: AbsolutePathSchema, guest: z.string().max(1024) })).max(64),
32
+ roots: z.array(z.object({ host: AbsolutePathSchema, guest: z.string().max(1024) })).max(64),
31
33
  projects: z.array(RegistryEntrySchema).max(1024),
32
34
  /** What the sandbox booted with that a joining project may also want (missing in registries of 1.4.0 and older). */
33
35
  atBoot: z
34
- .strictObject({
36
+ .object({
35
37
  memoryMb: z.number().int().positive().nullable(),
36
38
  mappings: z
37
- .array(z.strictObject({ host: z.string().max(1024), guest: z.string().max(1024), readOnly: z.boolean() }))
39
+ .array(z.object({ host: z.string().max(1024), guest: z.string().max(1024), readOnly: z.boolean() }))
38
40
  .max(1024),
39
41
  /** Boot settings turned on for a project mapped at boot (setting -> project): other projects share them. */
40
42
  widened: z.record(z.string().max(100), z.string().max(100)),
@@ -116,6 +118,72 @@ export class ProjectRegistry {
116
118
  rootHere(hostDir) {
117
119
  return projectForHostDir(this.read()?.roots ?? [], hostDir);
118
120
  }
121
+ /**
122
+ * The record rebuilt from the running sandbox's launch folder (host-only storage), for when run\projects.json is
123
+ * missing, cannot be read or belongs to an earlier sandbox: the launch folder, and every folder mapped for other
124
+ * projects at boot as a root. Saved and returned; null when the launch folder does not have what it takes.
125
+ */
126
+ rebuild(launchPath, launchId, protections) {
127
+ const session = readBounded(path.join(launchPath, 'session.json'), MAX_SESSION_BYTES);
128
+ const wsb = readBounded(path.join(launchPath, 'agent.wsb'), MAX_WSB_BYTES);
129
+ if (session === null || wsb === null)
130
+ return null;
131
+ let parsed;
132
+ try {
133
+ const result = LaunchSessionSchema.safeParse(JSON.parse(session));
134
+ if (!result.success || result.data.launchId !== launchId)
135
+ return null;
136
+ parsed = result.data;
137
+ }
138
+ catch {
139
+ return null;
140
+ }
141
+ const atBoot = parseWsbBoot(wsb);
142
+ const forProjects = new Set(parsed.roots.map((guest) => guest.toLowerCase()));
143
+ const roots = atBoot.mappings
144
+ .filter((m) => forProjects.has(m.guest.toLowerCase()) && path.isAbsolute(m.host))
145
+ .slice(0, 64)
146
+ .map((m) => ({ host: m.host, guest: m.guest }));
147
+ const registry = {
148
+ launchId,
149
+ protections,
150
+ roots,
151
+ projects: [
152
+ {
153
+ name: hubName(parsed.workspaceHost, []),
154
+ host: parsed.workspaceHost,
155
+ guest: parsed.workspace,
156
+ primary: true,
157
+ mechanism: 'launch',
158
+ registeredAt: new Date().toISOString(),
159
+ },
160
+ ],
161
+ atBoot,
162
+ };
163
+ this.save(registry);
164
+ return registry;
165
+ }
166
+ }
167
+ const MAX_SESSION_BYTES = 4 * 1024 * 1024;
168
+ const MAX_WSB_BYTES = 1024 * 1024;
169
+ /** What rebuild() needs from a launch folder's session.json (written on this PC by the launch). */
170
+ const LaunchSessionSchema = z.object({
171
+ launchId: z.string().max(64),
172
+ workspace: z.string().min(1).max(1024),
173
+ workspaceHost: AbsolutePathSchema,
174
+ roots: z.array(z.string().max(1024)).max(1024).default([]),
175
+ });
176
+ /** A file's text when it exists, is not a link and is at most `max` bytes; null otherwise. */
177
+ function readBounded(file, max) {
178
+ try {
179
+ const stat = fs.lstatSync(file);
180
+ if (!stat.isFile() || stat.size > max)
181
+ return null;
182
+ return fs.readFileSync(file, 'utf8');
183
+ }
184
+ catch {
185
+ return null;
186
+ }
119
187
  }
120
188
  /**
121
189
  * The projects of a sandbox another user started and shares: what that user's record lists, in the shape of a registry.
@@ -0,0 +1,2 @@
1
+ import { type ContainedDeps } from '../storage/index.js';
2
+ export declare function realContainedDeps(storageRoot: string, maxGb: number): ContainedDeps;
@@ -0,0 +1,17 @@
1
+ // The real wiring of contained storage on this PC: the permission-prompt scripts, protectPrivateFolder for new
2
+ // folders, your SID, and whether a sandbox runs. Lives here (not in host/storage) so storage never imports the
3
+ // sandbox or sharing folders, which import storage. The self-test never reaches a disk through it: the disk port
4
+ // refuses there.
5
+ import { ScriptDiskPort } from '../storage/index.js';
6
+ import { currentUserSid, protectPrivateFolder } from '../sharing/index.js';
7
+ import { isSandboxRunning } from './platform.js';
8
+ export function realContainedDeps(storageRoot, maxGb) {
9
+ return {
10
+ storageRoot,
11
+ maxGb,
12
+ protect: (dir) => protectPrivateFolder(dir),
13
+ userSid: currentUserSid,
14
+ port: new ScriptDiskPort(),
15
+ sandboxRunning: isSandboxRunning,
16
+ };
17
+ }
@@ -1,6 +1,8 @@
1
1
  export * from './platform.js';
2
2
  export * from './probe.js';
3
+ export * from './tasklist.js';
3
4
  export * from './host-claude.js';
4
5
  export * from './doctor.js';
5
6
  export * from './window.js';
6
7
  export * from './wsb-cli.js';
8
+ export * from './contained-deps.js';
@@ -1,6 +1,8 @@
1
1
  export * from './platform.js';
2
2
  export * from './probe.js';
3
+ export * from './tasklist.js';
3
4
  export * from './host-claude.js';
4
5
  export * from './doctor.js';
5
6
  export * from './window.js';
6
7
  export * from './wsb-cli.js';
8
+ export * from './contained-deps.js';
@@ -5,6 +5,8 @@ import type { SandboxOwner } from '../sharing/owner.js';
5
5
  */
6
6
  export declare function insideSandbox(): boolean;
7
7
  export declare const GUEST_DATA_DIR = "C:\\AgentData";
8
+ /** Whether a Windows Sandbox program is in this process list (tasklist /NH /FO CSV output). */
9
+ export declare function sandboxInTasklist(tasklist: string): boolean;
8
10
  export declare function isSandboxRunning(): boolean;
9
11
  export declare function sandboxFeatureInstalled(): boolean;
10
12
  /** `owner`: whose sandbox runs, when the caller knows (host/sharing); it makes the message say who started it. */
@@ -12,5 +14,7 @@ export declare function assertCanLaunch(owner?: SandboxOwner): void;
12
14
  /** cmd.exe expands %VAR% and ^ even inside quotes, and a quote ends them: such a path could run something else. */
13
15
  export declare function assertCmdSafePath(file: string): void;
14
16
  export declare function startSandbox(wsbPath: string): void;
17
+ /** After startSandbox: waits up to 20 seconds for the Windows Sandbox program to show up, or fails naming the .wsb. */
18
+ export declare function confirmSandboxStarted(wsbPath: string, waitMs?: number): Promise<void>;
15
19
  /** Runs a detached copy of this CLI (used for the background history/claude-mem sync watcher). */
16
20
  export declare function spawnDetached(entry: string, args: string[]): void;
@@ -2,9 +2,13 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { spawn, spawnSync } from 'node:child_process';
4
4
  import { SYSTEM } from '../../shared/system.js';
5
+ import { readTasklist } from './tasklist.js';
5
6
  import { refuseInSelfTest } from '../test-guard.js';
6
- import { fail, fileExists, isWin } from '../../core/util/index.js';
7
+ import { fail, fileExists, isWin, sleep } from '../../core/util/index.js';
7
8
  import { launchBlocked } from '../sharing/rules.js';
9
+ /** The longest a Windows helper program (tasklist, cmd start) may take before it counts as stuck. */
10
+ const HELPER_TIMEOUT_MS = 15000;
11
+ const START_WAIT_MS = 20000;
8
12
  const SANDBOX_PROCESSES = ['WindowsSandboxClient.exe', 'WindowsSandboxRemoteSession.exe', 'WindowsSandbox.exe'];
9
13
  /**
10
14
  * Running INSIDE a Windows Sandbox this tool started (its launch folder and data folder are mapped in): then the CLI
@@ -17,14 +21,17 @@ export function insideSandbox() {
17
21
  fs.existsSync('C:\\AgentData\\run'));
18
22
  }
19
23
  export const GUEST_DATA_DIR = 'C:\\AgentData';
24
+ /** Whether a Windows Sandbox program is in this process list (tasklist /NH /FO CSV output). */
25
+ export function sandboxInTasklist(tasklist) {
26
+ const out = tasklist.toLowerCase();
27
+ return SANDBOX_PROCESSES.some((image) => out.includes('"' + image.toLowerCase() + '"'));
28
+ }
20
29
  export function isSandboxRunning() {
21
30
  if (!isWin)
22
31
  return false;
23
32
  if (insideSandbox())
24
33
  return true;
25
- const result = spawnSync(SYSTEM.tasklist(), ['/NH', '/FO', 'CSV'], { encoding: 'utf8', windowsHide: true });
26
- const out = (result.stdout ?? '').toLowerCase();
27
- return SANDBOX_PROCESSES.some((image) => out.includes('"' + image.toLowerCase() + '"'));
34
+ return sandboxInTasklist(readTasklist());
28
35
  }
29
36
  export function sandboxFeatureInstalled() {
30
37
  return isWin && fileExists(path.join(process.env.WINDIR ?? 'C:\\Windows', 'System32', 'WindowsSandbox.exe'));
@@ -55,10 +62,22 @@ export function startSandbox(wsbPath) {
55
62
  const result = spawnSync(SYSTEM.cmd(), ['/d', '/c', 'start', '""', '"' + wsbPath + '"'], {
56
63
  stdio: 'inherit',
57
64
  windowsVerbatimArguments: true,
65
+ timeout: HELPER_TIMEOUT_MS,
58
66
  });
59
67
  if (result.error)
60
68
  throw result.error;
61
69
  }
70
+ /** After startSandbox: waits up to 20 seconds for the Windows Sandbox program to show up, or fails naming the .wsb. */
71
+ export async function confirmSandboxStarted(wsbPath, waitMs = START_WAIT_MS) {
72
+ const deadline = Date.now() + waitMs;
73
+ while (!isSandboxRunning()) {
74
+ if (Date.now() >= deadline)
75
+ fail('Windows Sandbox did not start within ' + Math.round(waitMs / 1000) + ' seconds.', 'Open ' +
76
+ wsbPath +
77
+ ' yourself to see the message Windows gives, or run sandbox doctor to check the Windows Sandbox feature.');
78
+ await sleep(1000);
79
+ }
80
+ }
62
81
  /** Runs a detached copy of this CLI (used for the background history/claude-mem sync watcher). */
63
82
  export function spawnDetached(entry, args) {
64
83
  refuseInSelfTest('start background programs');
@@ -0,0 +1,13 @@
1
+ /** Runs tasklist: the real one, or what a test put in its place. */
2
+ export interface TasklistRunners {
3
+ sync(): string;
4
+ async(): Promise<string>;
5
+ }
6
+ /** Replaces how tasklist runs (tests count the calls); no argument puts the real one back. */
7
+ export declare function useTasklistRunners(replacement?: TasklistRunners): void;
8
+ /** While set, a synchronous read returns this copy (undefined: none yet, run tasklist). Null removes it. */
9
+ export declare function useTasklistCache(read: (() => string | undefined) | null): void;
10
+ /** The process list now: the cached copy when the menu keeps one, else a run of tasklist the caller waits for. */
11
+ export declare function readTasklist(): string;
12
+ /** The process list from a run of tasklist that does not block the program (the menu's background refresh). */
13
+ export declare function readTasklistAsync(): Promise<string>;
@@ -0,0 +1,47 @@
1
+ // The process list (`tasklist /NH /FO CSV`) that "is the sandbox running?" and "whose is it?" come from. Commands
2
+ // ask it synchronously. The menu cannot wait for a child process on every key, so it keeps a copy fresh in the
3
+ // background (readTasklistAsync) and installs it with useTasklistCache: until then, and after it is removed, every
4
+ // question runs tasklist itself.
5
+ import { spawn, spawnSync } from 'node:child_process';
6
+ import { SYSTEM } from '../../shared/system.js';
7
+ /** The longest tasklist may take before it counts as stuck. */
8
+ const TASKLIST_TIMEOUT_MS = 15000;
9
+ const ARGS = ['/NH', '/FO', 'CSV'];
10
+ const REAL_RUNNERS = {
11
+ sync: () => spawnSync(SYSTEM.tasklist(), ARGS, { encoding: 'utf8', windowsHide: true, timeout: TASKLIST_TIMEOUT_MS }).stdout ??
12
+ '',
13
+ async: () => new Promise((resolve) => {
14
+ let out = '';
15
+ const child = spawn(SYSTEM.tasklist(), ARGS, { windowsHide: true, stdio: ['ignore', 'pipe', 'ignore'] });
16
+ const timer = setTimeout(() => child.kill(), TASKLIST_TIMEOUT_MS);
17
+ child.stdout.setEncoding('utf8');
18
+ child.stdout.on('data', (chunk) => (out += chunk));
19
+ // A tasklist that cannot start or is killed counts as an empty list, like the synchronous one.
20
+ child.on('error', () => {
21
+ clearTimeout(timer);
22
+ resolve('');
23
+ });
24
+ child.on('close', () => {
25
+ clearTimeout(timer);
26
+ resolve(out);
27
+ });
28
+ }),
29
+ };
30
+ let runners = REAL_RUNNERS;
31
+ let cache = null;
32
+ /** Replaces how tasklist runs (tests count the calls); no argument puts the real one back. */
33
+ export function useTasklistRunners(replacement = REAL_RUNNERS) {
34
+ runners = replacement;
35
+ }
36
+ /** While set, a synchronous read returns this copy (undefined: none yet, run tasklist). Null removes it. */
37
+ export function useTasklistCache(read) {
38
+ cache = read;
39
+ }
40
+ /** The process list now: the cached copy when the menu keeps one, else a run of tasklist the caller waits for. */
41
+ export function readTasklist() {
42
+ return cache?.() ?? runners.sync();
43
+ }
44
+ /** The process list from a run of tasklist that does not block the program (the menu's background refresh). */
45
+ export function readTasklistAsync() {
46
+ return runners.async();
47
+ }
@@ -0,0 +1,2 @@
1
+ export { SecretStore, type SecretBox } from './secret-store.js';
2
+ export { clearSecrets, withoutSecrets, writeSecrets } from './launch-secrets.js';
@@ -0,0 +1,2 @@
1
+ export { SecretStore } from './secret-store.js';
2
+ export { clearSecrets, withoutSecrets, writeSecrets } from './launch-secrets.js';
@@ -0,0 +1,17 @@
1
+ import { type SecretsFile } from '../../shared/channel/index.js';
2
+ import type { GuestRequest } from '../../core/types.js';
3
+ /** Writes <data>\secrets\<id>.json (nothing at all when there is nothing secret to hand over). */
4
+ export declare function writeSecrets(dataPath: string, id: string, secrets: SecretsFile): string | null;
5
+ /**
6
+ * Removes whatever one-shot files are left (the sandbox did not start, or did not get to read them) and, from older
7
+ * versions, a login copy in a launch folder. Called before a launch writes new ones and when the sandbox stops.
8
+ */
9
+ export declare function clearSecrets(storageRoot: string, dataPath: string): number;
10
+ /**
11
+ * A request with every agent's environment taken out (those values may be keys) and the values to hand over in the
12
+ * secrets file of that request. Requests that carry none come back untouched.
13
+ */
14
+ export declare function withoutSecrets(request: GuestRequest): {
15
+ request: GuestRequest;
16
+ secrets: SecretsFile | null;
17
+ };
@@ -0,0 +1,94 @@
1
+ // The one-shot secrets file: written before the sandbox starts (or with a request), read and deleted by the sandbox at
2
+ // once. See shared/channel/secrets.ts for what it holds and why it is not in session.json or the launch folder.
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { RunDir } from '../../shared/channel/index.js';
6
+ import { writeJsonAtomic } from '../../shared/io/index.js';
7
+ import { assertNoLinks } from '../../core/util/index.js';
8
+ /** Writes <data>\secrets\<id>.json (nothing at all when there is nothing secret to hand over). */
9
+ export function writeSecrets(dataPath, id, secrets) {
10
+ const empty = !Object.keys(secrets.harnessEnvironment ?? {}).length &&
11
+ !Object.keys(secrets.harnessSpecEnvironment ?? {}).length &&
12
+ !Object.keys(secrets.projectHarnessEnvironment ?? {}).length &&
13
+ !secrets.claudeCredentials &&
14
+ !secrets.vpn &&
15
+ !secrets.wireguardConfig;
16
+ if (empty)
17
+ return null;
18
+ const run = new RunDir(dataPath);
19
+ assertNoLinks(dataPath, run.secretsDir);
20
+ const file = run.secretFile(id);
21
+ writeJsonAtomic(file, secrets);
22
+ return file;
23
+ }
24
+ /**
25
+ * Removes whatever one-shot files are left (the sandbox did not start, or did not get to read them) and, from older
26
+ * versions, a login copy in a launch folder. Called before a launch writes new ones and when the sandbox stops.
27
+ */
28
+ export function clearSecrets(storageRoot, dataPath) {
29
+ let removed = 0;
30
+ const secrets = new RunDir(dataPath).secretsDir;
31
+ try {
32
+ assertNoLinks(dataPath, secrets);
33
+ for (const name of fs.readdirSync(secrets)) {
34
+ fs.rmSync(path.join(secrets, name), { recursive: true, force: true });
35
+ removed++;
36
+ }
37
+ }
38
+ catch {
39
+ // No such folder, or a link planted there: nothing to remove.
40
+ }
41
+ const launches = path.join(storageRoot, 'launches');
42
+ try {
43
+ for (const launch of fs.readdirSync(launches)) {
44
+ const old = path.join(launches, launch, 'claude-profile', '.credentials.json');
45
+ if (fs.existsSync(old)) {
46
+ fs.rmSync(old, { force: true });
47
+ removed++;
48
+ }
49
+ }
50
+ }
51
+ catch {
52
+ // No launches yet.
53
+ }
54
+ return removed;
55
+ }
56
+ const blank = (h) => ({ ...h, environment: {} });
57
+ const hasValues = (e) => Object.keys(e).length > 0;
58
+ /**
59
+ * A request with every agent's environment taken out (those values may be keys) and the values to hand over in the
60
+ * secrets file of that request. Requests that carry none come back untouched.
61
+ */
62
+ export function withoutSecrets(request) {
63
+ if (request.kind !== 'session' && request.kind !== 'project')
64
+ return { request, secrets: null };
65
+ const project = request.project;
66
+ const spec = request.kind === 'session' ? request.harnessSpec : undefined;
67
+ const projectEnv = Object.fromEntries(Object.entries(project?.harnesses ?? {}).filter(([, h]) => hasValues(h.environment)));
68
+ const specEnv = spec && hasValues(spec.environment) ? spec.environment : undefined;
69
+ if (!specEnv && !Object.keys(projectEnv).length)
70
+ return { request, secrets: null };
71
+ const cleaned = {
72
+ ...request,
73
+ ...(project
74
+ ? {
75
+ project: {
76
+ ...project,
77
+ harnesses: Object.fromEntries(Object.entries(project.harnesses).map(([n, h]) => [n, blank(h)])),
78
+ },
79
+ }
80
+ : {}),
81
+ ...(spec ? { harnessSpec: blank(spec) } : {}),
82
+ };
83
+ return {
84
+ request: cleaned,
85
+ secrets: {
86
+ ...(specEnv ? { harnessSpecEnvironment: specEnv } : {}),
87
+ ...(Object.keys(projectEnv).length
88
+ ? {
89
+ projectHarnessEnvironment: Object.fromEntries(Object.entries(projectEnv).map(([n, h]) => [n, h.environment])),
90
+ }
91
+ : {}),
92
+ },
93
+ };
94
+ }
@@ -0,0 +1,25 @@
1
+ /** Something that turns bytes into a sealed string and back. */
2
+ export interface SecretBox {
3
+ readonly kind: string;
4
+ seal(plain: Buffer): string;
5
+ open(sealed: string): Buffer;
6
+ }
7
+ /** Seals and opens text and JSON with one box. The sealed form says which box made it. */
8
+ export declare class SecretStore {
9
+ private readonly box;
10
+ constructor(box: SecretBox);
11
+ /** Windows DPAPI, current user. */
12
+ static dpapi(): SecretStore;
13
+ /** The test stand-in (not secure). */
14
+ static memory(): SecretStore;
15
+ /** What the program uses: DPAPI, except during the self-test (it never spawns Windows for this). */
16
+ static standard(): SecretStore;
17
+ /** True when `value` looks like something seal() made (any box). */
18
+ static isSealed(value: unknown): value is string;
19
+ seal(text: string): string;
20
+ open(sealed: string): string;
21
+ sealBytes(plain: Buffer): string;
22
+ openBytes(sealed: string): Buffer;
23
+ sealJson(value: unknown): string;
24
+ openJson(sealed: string): unknown;
25
+ }
@@ -0,0 +1,89 @@
1
+ // Encryption at rest for what must not sit in plain files (saved logins, the VPN login). The real box is Windows DPAPI
2
+ // for the current user (native\scripts\protect-data.ps1: data on standard input, never on a command line); the memory
3
+ // box is the self-test's stand-in and is not secure. A sealed value is a short string: "<kind>:<base64>".
4
+ import { spawnSync } from 'node:child_process';
5
+ import { fail } from '../../core/util/index.js';
6
+ import { SYSTEM } from '../../shared/system.js';
7
+ import { selfTestRunning } from '../../shared/test-guard.js';
8
+ import { nativeScript } from '../native.js';
9
+ const TIMEOUT_MS = 60000;
10
+ /** DPAPI for the current Windows user, through powershell.exe 5.1. */
11
+ class DpapiBox {
12
+ kind = 'dpapi1';
13
+ seal(plain) {
14
+ return this.run('protect', plain.toString('base64'));
15
+ }
16
+ open(sealed) {
17
+ return Buffer.from(this.run('unprotect', sealed), 'base64');
18
+ }
19
+ run(mode, input) {
20
+ const result = spawnSync(SYSTEM.powershell(), nativeScript('protect-data.ps1', ['-Mode', mode]), {
21
+ input,
22
+ encoding: 'utf8',
23
+ windowsHide: true,
24
+ timeout: TIMEOUT_MS,
25
+ });
26
+ if (result.status !== 0 || result.error)
27
+ fail('Windows could not ' +
28
+ (mode === 'protect' ? 'encrypt' : 'decrypt') +
29
+ ' a saved secret: ' +
30
+ (result.stderr || result.error?.message || 'no answer').trim().slice(0, 300), mode === 'protect'
31
+ ? 'Check that powershell.exe runs for your user.'
32
+ : 'It can only be opened by the Windows user that saved it, on the PC that saved it. Save it again.');
33
+ return result.stdout.trim();
34
+ }
35
+ }
36
+ /** A reversible stand-in for tests: it only proves the callers seal and open, not that anything is secret. */
37
+ class MemoryBox {
38
+ kind = 'mem1';
39
+ seal(plain) {
40
+ return Buffer.from(plain.toString('base64')).toString('base64');
41
+ }
42
+ open(sealed) {
43
+ return Buffer.from(Buffer.from(sealed, 'base64').toString('utf8'), 'base64');
44
+ }
45
+ }
46
+ /** Seals and opens text and JSON with one box. The sealed form says which box made it. */
47
+ export class SecretStore {
48
+ box;
49
+ constructor(box) {
50
+ this.box = box;
51
+ }
52
+ /** Windows DPAPI, current user. */
53
+ static dpapi() {
54
+ return new SecretStore(new DpapiBox());
55
+ }
56
+ /** The test stand-in (not secure). */
57
+ static memory() {
58
+ return new SecretStore(new MemoryBox());
59
+ }
60
+ /** What the program uses: DPAPI, except during the self-test (it never spawns Windows for this). */
61
+ static standard() {
62
+ return selfTestRunning() ? SecretStore.memory() : SecretStore.dpapi();
63
+ }
64
+ /** True when `value` looks like something seal() made (any box). */
65
+ static isSealed(value) {
66
+ return typeof value === 'string' && /^(dpapi1|mem1):[A-Za-z0-9+/=]+$/.test(value);
67
+ }
68
+ seal(text) {
69
+ return this.box.kind + ':' + this.box.seal(Buffer.from(text, 'utf8'));
70
+ }
71
+ open(sealed) {
72
+ return this.openBytes(sealed).toString('utf8');
73
+ }
74
+ sealBytes(plain) {
75
+ return this.box.kind + ':' + this.box.seal(plain);
76
+ }
77
+ openBytes(sealed) {
78
+ const at = sealed.indexOf(':');
79
+ if (at < 0 || sealed.slice(0, at) !== this.box.kind)
80
+ fail('A saved secret was made on another system or with another store.', 'Save it again.');
81
+ return this.box.open(sealed.slice(at + 1));
82
+ }
83
+ sealJson(value) {
84
+ return this.seal(JSON.stringify(value));
85
+ }
86
+ openJson(sealed) {
87
+ return JSON.parse(this.open(sealed));
88
+ }
89
+ }
@@ -21,10 +21,24 @@ export declare function sharingAclPlan(o: {
21
21
  on: boolean;
22
22
  }): AclChange[];
23
23
  /**
24
- * Applies the changes with native\scripts\set-folder-access.ps1 (Get-Acl / Set-Acl, refusing links). Throws with the
25
- * script's reason when a change fails. The self-test guard is in applyAcl; the self-test calls this only on its temp
24
+ * Applies the changes with native\scripts\set-folder-access.ps1 (refusing links; writing nothing when an entry would
25
+ * change nothing, and a folder's own entry without touching what is inside it). Throws with the script's reason when a
26
+ * change fails or takes over 30 seconds. The self-test guard is in applyAcl; the self-test calls this only on its temp
26
27
  * folders.
27
28
  */
28
29
  export declare function runFolderAccess(changes: readonly AclChange[]): void;
29
30
  /** Applies sharing changes on this PC (refused inside the self-test). */
30
31
  export declare function applyAcl(changes: readonly AclChange[]): void;
32
+ /** Makes an existing folder private (see protectPrivateFolder) without the self-test guard: for temp folders only. */
33
+ export declare function runPrivateFolder(dir: string, options?: PrivateOptions): void;
34
+ export interface PrivateOptions {
35
+ /** The folder holds files and every one of them has to be walked: wait up to 30 minutes instead of 30 seconds. */
36
+ readonly walkAll?: boolean;
37
+ }
38
+ /**
39
+ * Makes an existing folder (not a link) private: inheritance off, full control for you, SYSTEM and Administrators
40
+ * only, inherited by what is created in it. Nothing is written when it already is; an empty folder is changed without
41
+ * walking inside it. A folder with files is walked (minutes for a large one), so it stops after 30 seconds unless the
42
+ * caller asks for `walkAll` (only an explicit repair does, after saying so). Launch paths never do.
43
+ */
44
+ export declare function protectPrivateFolder(dir: string, options?: PrivateOptions): void;
@@ -32,23 +32,23 @@ export function sharingAclPlan(o) {
32
32
  entry(path.join(o.dataPath, 'run'), 'Modify', 'inherit'),
33
33
  ];
34
34
  }
35
- /**
36
- * Applies the changes with native\scripts\set-folder-access.ps1 (Get-Acl / Set-Acl, refusing links). Throws with the
37
- * script's reason when a change fails. The self-test guard is in applyAcl; the self-test calls this only on its temp
38
- * folders.
39
- */
40
- export function runFolderAccess(changes) {
41
- if (changes.length === 0)
42
- return;
35
+ const ACL_TIMEOUT_MS = 30000;
36
+ /** Making a folder that holds files private walks all of it: a few hundred thousand files take minutes. */
37
+ const WALK_TIMEOUT_MS = 30 * 60000;
38
+ /** One run of native\scripts\set-folder-access.ps1 over `entries` (the JSON's "changes"); throws a UserError. */
39
+ function runScript(entries, timeoutMs = ACL_TIMEOUT_MS) {
43
40
  const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-sandbox-acl-'));
44
41
  const file = path.join(dir, 'changes.json');
45
42
  try {
46
- fs.writeFileSync(file, JSON.stringify({ changes }, null, 2), 'utf8');
43
+ fs.writeFileSync(file, JSON.stringify({ changes: entries }, null, 2), 'utf8');
47
44
  const run = spawnSync(SYSTEM.powershell(), nativeScript('set-folder-access.ps1', ['-Json', file]), {
48
45
  encoding: 'utf8',
49
46
  windowsHide: true,
50
- timeout: 120000,
47
+ timeout: timeoutMs,
51
48
  });
49
+ const timedOut = run.error?.code === 'ETIMEDOUT';
50
+ if (timedOut)
51
+ fail('Changing the folder permissions took longer than ' + timeoutMs / 1000 + ' seconds and was stopped.', 'Close programs that scan or lock the folders (virus scanners, file explorers) and try again.');
52
52
  if (run.status !== 0 || run.error) {
53
53
  const reason = (run.stderr || run.stdout || run.error?.message || 'no output').trim();
54
54
  fail('Could not change the folder permissions: ' + reason, 'Check that the folders are not links and that you can change their permissions, then try again.');
@@ -58,8 +58,33 @@ export function runFolderAccess(changes) {
58
58
  fs.rmSync(dir, { recursive: true, force: true });
59
59
  }
60
60
  }
61
+ /**
62
+ * Applies the changes with native\scripts\set-folder-access.ps1 (refusing links; writing nothing when an entry would
63
+ * change nothing, and a folder's own entry without touching what is inside it). Throws with the script's reason when a
64
+ * change fails or takes over 30 seconds. The self-test guard is in applyAcl; the self-test calls this only on its temp
65
+ * folders.
66
+ */
67
+ export function runFolderAccess(changes) {
68
+ if (changes.length === 0)
69
+ return;
70
+ runScript(changes);
71
+ }
61
72
  /** Applies sharing changes on this PC (refused inside the self-test). */
62
73
  export function applyAcl(changes) {
63
74
  refuseInSelfTest('change folder permissions');
64
75
  runFolderAccess(changes);
65
76
  }
77
+ /** Makes an existing folder private (see protectPrivateFolder) without the self-test guard: for temp folders only. */
78
+ export function runPrivateFolder(dir, options = {}) {
79
+ runScript([{ op: 'private', path: dir }], options.walkAll ? WALK_TIMEOUT_MS : ACL_TIMEOUT_MS);
80
+ }
81
+ /**
82
+ * Makes an existing folder (not a link) private: inheritance off, full control for you, SYSTEM and Administrators
83
+ * only, inherited by what is created in it. Nothing is written when it already is; an empty folder is changed without
84
+ * walking inside it. A folder with files is walked (minutes for a large one), so it stops after 30 seconds unless the
85
+ * caller asks for `walkAll` (only an explicit repair does, after saying so). Launch paths never do.
86
+ */
87
+ export function protectPrivateFolder(dir, options = {}) {
88
+ refuseInSelfTest('change folder permissions');
89
+ runPrivateFolder(dir, options);
90
+ }
@@ -3,13 +3,14 @@ import os from 'node:os';
3
3
  import { spawnSync } from 'node:child_process';
4
4
  import { SYSTEM } from '../../shared/system.js';
5
5
  import { insideSandbox } from '../sandbox/platform.js';
6
+ import { readTasklist } from '../sandbox/tasklist.js';
6
7
  import { activeDir } from './machine-paths.js';
7
8
  import { ActiveRecords } from './active-record.js';
8
9
  import { parseTasklist, whoOwnsSandbox } from './owner.js';
10
+ const HELPER_TIMEOUT_MS = 15000;
9
11
  /** The rows of `tasklist /NH /FO CSV`: every process of every session (standard users may see these). */
10
12
  export function listProcesses() {
11
- const run = spawnSync(SYSTEM.tasklist(), ['/NH', '/FO', 'CSV'], { encoding: 'utf8', windowsHide: true });
12
- return parseTasklist(run.stdout ?? '');
13
+ return parseTasklist(readTasklist());
13
14
  }
14
15
  /** The Windows session this process runs in (0 = services, 1 = the first signed-in user ...), or null when unknown. */
15
16
  export function sessionOf(rows, pid = process.pid) {
@@ -17,7 +18,11 @@ export function sessionOf(rows, pid = process.pid) {
17
18
  }
18
19
  /** This user's SID, from `whoami /user`: `"DOMAIN\name","S-1-5-21-..."`. */
19
20
  export function currentUserSid() {
20
- const run = spawnSync(SYSTEM.whoami(), ['/user', '/fo', 'csv', '/nh'], { encoding: 'utf8', windowsHide: true });
21
+ const run = spawnSync(SYSTEM.whoami(), ['/user', '/fo', 'csv', '/nh'], {
22
+ encoding: 'utf8',
23
+ windowsHide: true,
24
+ timeout: HELPER_TIMEOUT_MS,
25
+ });
21
26
  const sid = /"(S-1-[0-9-]+)"\s*$/.exec((run.stdout ?? '').trim())?.[1];
22
27
  if (!sid)
23
28
  throw new Error('Could not find out who you are (whoami /user gave: ' + (run.stdout || run.stderr) + ').');