windows-development-sandbox 1.5.0 → 1.7.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 (448) hide show
  1. package/README.md +1 -0
  2. package/config.example.json +17 -1
  3. package/dist/cli/args.d.ts +13 -2
  4. package/dist/cli/args.js +95 -24
  5. package/dist/cli/commands/accounts.js +45 -17
  6. package/dist/cli/commands/context.d.ts +2 -0
  7. package/dist/cli/commands/context.js +9 -2
  8. package/dist/cli/commands/data/clean.js +32 -9
  9. package/dist/cli/commands/index.d.ts +1 -0
  10. package/dist/cli/commands/index.js +1 -0
  11. package/dist/cli/commands/launch/add-root.d.ts +3 -2
  12. package/dist/cli/commands/launch/add-root.js +11 -10
  13. package/dist/cli/commands/launch/launch.js +57 -4
  14. package/dist/cli/commands/launch/prepare.js +3 -1
  15. package/dist/cli/commands/maintenance/audit.js +1 -1
  16. package/dist/cli/commands/maintenance/clean.d.ts +1 -1
  17. package/dist/cli/commands/maintenance/clean.js +17 -3
  18. package/dist/cli/commands/maintenance/config.d.ts +1 -1
  19. package/dist/cli/commands/maintenance/config.js +112 -10
  20. package/dist/cli/commands/maintenance/doctor.d.ts +1 -1
  21. package/dist/cli/commands/maintenance/doctor.js +2 -4
  22. package/dist/cli/commands/maintenance/migrate.d.ts +2 -1
  23. package/dist/cli/commands/maintenance/migrate.js +19 -4
  24. package/dist/cli/commands/maintenance/sync.js +2 -0
  25. package/dist/cli/commands/maintenance/update.d.ts +2 -0
  26. package/dist/cli/commands/maintenance/update.js +27 -4
  27. package/dist/cli/commands/projects/here.js +12 -7
  28. package/dist/cli/commands/projects/projects.js +26 -17
  29. package/dist/cli/commands/registry.js +7 -0
  30. package/dist/cli/commands/repair/checks/agents.d.ts +2 -0
  31. package/dist/cli/commands/repair/checks/agents.js +70 -0
  32. package/dist/cli/commands/repair/checks/common.d.ts +8 -0
  33. package/dist/cli/commands/repair/checks/common.js +22 -0
  34. package/dist/cli/commands/repair/checks/data.d.ts +2 -0
  35. package/dist/cli/commands/repair/checks/data.js +241 -0
  36. package/dist/cli/commands/repair/checks/index.d.ts +2 -0
  37. package/dist/cli/commands/repair/checks/index.js +20 -0
  38. package/dist/cli/commands/repair/checks/install.d.ts +5 -0
  39. package/dist/cli/commands/repair/checks/install.js +318 -0
  40. package/dist/cli/commands/repair/checks/machine.d.ts +2 -0
  41. package/dist/cli/commands/repair/checks/machine.js +232 -0
  42. package/dist/cli/commands/repair/checks/network.d.ts +6 -0
  43. package/dist/cli/commands/repair/checks/network.js +60 -0
  44. package/dist/cli/commands/repair/checks/pc.d.ts +4 -0
  45. package/dist/cli/commands/repair/checks/pc.js +55 -0
  46. package/dist/cli/commands/repair/checks/sandbox.d.ts +2 -0
  47. package/dist/cli/commands/repair/checks/sandbox.js +267 -0
  48. package/dist/cli/commands/repair/checks/settings.d.ts +2 -0
  49. package/dist/cli/commands/repair/checks/settings.js +169 -0
  50. package/dist/cli/commands/repair/checks/vpn.d.ts +2 -0
  51. package/dist/cli/commands/repair/checks/vpn.js +53 -0
  52. package/dist/cli/commands/repair/engine.d.ts +32 -0
  53. package/dist/cli/commands/repair/engine.js +127 -0
  54. package/dist/cli/commands/repair/env.d.ts +7 -0
  55. package/dist/cli/commands/repair/env.js +49 -0
  56. package/dist/cli/commands/repair/index.d.ts +1 -9
  57. package/dist/cli/commands/repair/index.js +2 -54
  58. package/dist/cli/commands/repair/log.d.ts +17 -0
  59. package/dist/cli/commands/repair/log.js +82 -0
  60. package/dist/cli/commands/repair/printer.d.ts +32 -0
  61. package/dist/cli/commands/repair/printer.js +132 -0
  62. package/dist/cli/commands/repair/run.d.ts +33 -0
  63. package/dist/cli/commands/repair/run.js +133 -0
  64. package/dist/cli/commands/repair/types.d.ts +97 -9
  65. package/dist/cli/commands/repair/types.js +11 -7
  66. package/dist/cli/commands/resume.js +2 -2
  67. package/dist/cli/commands/sessions/list.js +5 -2
  68. package/dist/cli/commands/sessions/status.d.ts +2 -0
  69. package/dist/cli/commands/sessions/status.js +27 -6
  70. package/dist/cli/commands/setup/index.d.ts +5 -0
  71. package/dist/cli/commands/setup/index.js +25 -1
  72. package/dist/cli/commands/storage/index.d.ts +2 -0
  73. package/dist/cli/commands/storage/index.js +2 -0
  74. package/dist/cli/commands/storage/offer.d.ts +3 -0
  75. package/dist/cli/commands/storage/offer.js +85 -0
  76. package/dist/cli/commands/storage/storage.d.ts +8 -0
  77. package/dist/cli/commands/storage/storage.js +171 -0
  78. package/dist/cli/commands/user-config.js +1 -1
  79. package/dist/cli/commands/vpn.d.ts +4 -0
  80. package/dist/cli/commands/vpn.js +75 -0
  81. package/dist/cli/commands/web.d.ts +4 -0
  82. package/dist/cli/commands/web.js +95 -0
  83. package/dist/cli/history.js +1 -1
  84. package/dist/cli/index.js +46 -3
  85. package/dist/cli/manifest.d.ts +303 -29
  86. package/dist/cli/manifest.js +173 -43
  87. package/dist/cli/menu/add-agent.d.ts +47 -0
  88. package/dist/cli/menu/add-agent.js +168 -0
  89. package/dist/cli/menu/apps.d.ts +31 -2
  90. package/dist/cli/menu/apps.js +44 -5
  91. package/dist/cli/menu/command-fields.d.ts +18 -0
  92. package/dist/cli/menu/command-fields.js +61 -0
  93. package/dist/cli/menu/command-form.d.ts +22 -0
  94. package/dist/cli/menu/command-form.js +169 -46
  95. package/dist/cli/menu/data-folder.d.ts +18 -0
  96. package/dist/cli/menu/data-folder.js +99 -0
  97. package/dist/cli/menu/menu.d.ts +1 -1
  98. package/dist/cli/menu/menu.js +11 -8
  99. package/dist/cli/menu/pages/accounts-page.js +55 -24
  100. package/dist/cli/menu/pages/agents-page.d.ts +66 -0
  101. package/dist/cli/menu/pages/agents-page.js +338 -0
  102. package/dist/cli/menu/pages/apps-page.js +1 -2
  103. package/dist/cli/menu/pages/list-page.d.ts +16 -3
  104. package/dist/cli/menu/pages/list-page.js +40 -8
  105. package/dist/cli/menu/pages/maintenance-page.d.ts +9 -0
  106. package/dist/cli/menu/pages/maintenance-page.js +161 -72
  107. package/dist/cli/menu/pages/sandbox-page.d.ts +3 -0
  108. package/dist/cli/menu/pages/sandbox-page.js +132 -43
  109. package/dist/cli/menu/pages/sessions-page.d.ts +4 -0
  110. package/dist/cli/menu/pages/sessions-page.js +41 -25
  111. package/dist/cli/menu/pages/settings-page.d.ts +8 -4
  112. package/dist/cli/menu/pages/settings-page.js +36 -13
  113. package/dist/cli/menu/settings/categories.d.ts +2 -0
  114. package/dist/cli/menu/settings/categories.js +19 -44
  115. package/dist/cli/menu/settings/collections/collection-editor.d.ts +7 -1
  116. package/dist/cli/menu/settings/collections/collection-editor.js +12 -8
  117. package/dist/cli/menu/settings/collections/map-editor.js +5 -1
  118. package/dist/cli/menu/settings/collections/object-list-editor.js +2 -2
  119. package/dist/cli/menu/settings/collections/object-map-editor.js +2 -2
  120. package/dist/cli/menu/settings/collections/string-list-editor.d.ts +11 -1
  121. package/dist/cli/menu/settings/collections/string-list-editor.js +23 -0
  122. package/dist/cli/menu/settings/index.d.ts +1 -1
  123. package/dist/cli/menu/settings/index.js +1 -1
  124. package/dist/cli/menu/settings/object-editor.d.ts +5 -1
  125. package/dist/cli/menu/settings/object-editor.js +15 -4
  126. package/dist/cli/menu/settings/path-kind.d.ts +20 -0
  127. package/dist/cli/menu/settings/path-kind.js +44 -0
  128. package/dist/cli/menu/settings/schema-node.d.ts +9 -0
  129. package/dist/cli/menu/settings/schema-node.js +26 -0
  130. package/dist/cli/menu/settings/value-editor.d.ts +5 -0
  131. package/dist/cli/menu/settings/value-editor.js +51 -18
  132. package/dist/cli/menu/several.js +7 -5
  133. package/dist/cli/menu/shell.d.ts +37 -10
  134. package/dist/cli/menu/shell.js +90 -10
  135. package/dist/cli/menu/vpn-login.d.ts +16 -0
  136. package/dist/cli/menu/vpn-login.js +66 -0
  137. package/dist/cli/output/print.d.ts +2 -0
  138. package/dist/cli/output/print.js +8 -1
  139. package/dist/cli/services/accounts-service.d.ts +2 -0
  140. package/dist/cli/services/accounts-service.js +2 -2
  141. package/dist/cli/services/health-service.d.ts +0 -6
  142. package/dist/cli/services/health-service.js +5 -42
  143. package/dist/cli/services/index.d.ts +3 -1
  144. package/dist/cli/services/index.js +3 -1
  145. package/dist/cli/services/migrate-service.js +1 -1
  146. package/dist/cli/services/update-service.d.ts +2 -0
  147. package/dist/cli/services/update-service.js +13 -6
  148. package/dist/cli/services/vpn-service.d.ts +28 -0
  149. package/dist/cli/services/vpn-service.js +46 -0
  150. package/dist/cli/services/web-service.d.ts +22 -0
  151. package/dist/cli/services/web-service.js +111 -0
  152. package/dist/cli/tui/app.d.ts +6 -3
  153. package/dist/cli/tui/app.js +12 -5
  154. package/dist/cli/tui/dialogs/path-listing.d.ts +43 -0
  155. package/dist/cli/tui/dialogs/path-listing.js +127 -0
  156. package/dist/cli/tui/dialogs/path-picker.d.ts +67 -0
  157. package/dist/cli/tui/dialogs/path-picker.js +423 -0
  158. package/dist/cli/tui/dialogs/text-screen.d.ts +6 -0
  159. package/dist/cli/tui/dialogs/text-screen.js +10 -3
  160. package/dist/cli/tui/frame.d.ts +7 -10
  161. package/dist/cli/tui/frame.js +19 -10
  162. package/dist/cli/tui/index.d.ts +4 -3
  163. package/dist/cli/tui/index.js +2 -1
  164. package/dist/cli/tui/list/list-screen.d.ts +14 -2
  165. package/dist/cli/tui/list/list-screen.js +68 -32
  166. package/dist/cli/tui/list/list-types.d.ts +8 -4
  167. package/dist/cli/tui/nav.d.ts +29 -0
  168. package/dist/cli/tui/nav.js +67 -0
  169. package/dist/cli/validate.d.ts +1 -1
  170. package/dist/cli/validate.js +3 -3
  171. package/dist/cli/version.d.ts +2 -0
  172. package/dist/cli/version.js +11 -0
  173. package/dist/core/config/defaults.js +5 -1
  174. package/dist/core/config/loader.js +12 -2
  175. package/dist/core/local-config/overrides.js +1 -0
  176. package/dist/core/prompt.d.ts +19 -0
  177. package/dist/core/prompt.js +43 -3
  178. package/dist/core/schema/common.d.ts +6 -0
  179. package/dist/core/schema/common.js +8 -0
  180. package/dist/core/schema/config.d.ts +23 -0
  181. package/dist/core/schema/config.js +10 -1
  182. package/dist/core/schema/harness.d.ts +1 -0
  183. package/dist/core/schema/harness.js +8 -2
  184. package/dist/core/schema/index.d.ts +3 -1
  185. package/dist/core/schema/index.js +3 -1
  186. package/dist/core/schema/profile.d.ts +1 -0
  187. package/dist/core/schema/profile.js +3 -0
  188. package/dist/core/schema/redact.d.ts +13 -0
  189. package/dist/core/schema/redact.js +75 -0
  190. package/dist/core/schema/sandbox.js +1 -0
  191. package/dist/core/schema/vpn.d.ts +17 -0
  192. package/dist/core/schema/vpn.js +22 -0
  193. package/dist/core/schema/web.d.ts +6 -0
  194. package/dist/core/schema/web.js +14 -0
  195. package/dist/core/types.d.ts +26 -0
  196. package/dist/guest/agents/agent-files.d.ts +49 -0
  197. package/dist/guest/agents/agent-files.js +63 -0
  198. package/dist/guest/agents/agent-installer.js +2 -9
  199. package/dist/guest/agents/local-state.d.ts +12 -0
  200. package/dist/guest/agents/local-state.js +198 -0
  201. package/dist/guest/agents/sbx-agent.d.ts +2 -0
  202. package/dist/guest/agents/sbx-agent.js +35 -0
  203. package/dist/guest/boot/boot.d.ts +4 -0
  204. package/dist/guest/boot/boot.js +50 -11
  205. package/dist/guest/daemon/daemon.js +4 -1
  206. package/dist/guest/daemon/exec.js +2 -1
  207. package/dist/guest/daemon/idle-shutdown.js +2 -0
  208. package/dist/guest/daemon/sessions.js +4 -1
  209. package/dist/guest/entries/agent.d.ts +1 -0
  210. package/dist/guest/entries/agent.js +10 -0
  211. package/dist/guest/entries/daemon.js +2 -0
  212. package/dist/guest/runtime/csc.d.ts +1 -0
  213. package/dist/guest/runtime/csc.js +1 -0
  214. package/dist/guest/runtime/secrets.d.ts +12 -0
  215. package/dist/guest/runtime/secrets.js +63 -0
  216. package/dist/guest/setup/claude-profile.d.ts +2 -1
  217. package/dist/guest/setup/claude-profile.js +12 -1
  218. package/dist/guest/setup/environment.d.ts +6 -0
  219. package/dist/guest/setup/environment.js +56 -6
  220. package/dist/guest/setup/path-plan.d.ts +32 -0
  221. package/dist/guest/setup/path-plan.js +67 -0
  222. package/dist/guest/setup/shell-path.d.ts +1 -0
  223. package/dist/guest/setup/shell-path.js +22 -0
  224. package/dist/guest/toolchains/languages/python.js +1 -1
  225. package/dist/guest/toolchains/runtimes.js +2 -2
  226. package/dist/guest/vpn/index.d.ts +1 -0
  227. package/dist/guest/vpn/index.js +1 -0
  228. package/dist/guest/vpn/openvpn.d.ts +9 -0
  229. package/dist/guest/vpn/openvpn.js +47 -0
  230. package/dist/guest/vpn/tunnel.d.ts +17 -0
  231. package/dist/guest/vpn/tunnel.js +78 -0
  232. package/dist/guest/vpn/vpn.d.ts +6 -0
  233. package/dist/guest/vpn/vpn.js +126 -0
  234. package/dist/host/channel/attach.d.ts +3 -1
  235. package/dist/host/channel/attach.js +1 -1
  236. package/dist/host/channel/channel.d.ts +7 -0
  237. package/dist/host/channel/channel.js +26 -2
  238. package/dist/host/health/acl-read.d.ts +17 -0
  239. package/dist/host/health/acl-read.js +45 -0
  240. package/dist/host/health/config-backup.d.ts +11 -0
  241. package/dist/host/health/config-backup.js +73 -0
  242. package/dist/host/health/index.d.ts +6 -0
  243. package/dist/host/health/index.js +7 -0
  244. package/dist/host/health/install-state.d.ts +33 -0
  245. package/dist/host/health/install-state.js +110 -0
  246. package/dist/host/health/path-copies.d.ts +32 -0
  247. package/dist/host/health/path-copies.js +82 -0
  248. package/dist/host/health/stale.d.ts +45 -0
  249. package/dist/host/health/stale.js +120 -0
  250. package/dist/host/health/system.d.ts +37 -0
  251. package/dist/host/health/system.js +87 -0
  252. package/dist/host/install/copies.d.ts +13 -0
  253. package/dist/host/install/copies.js +63 -0
  254. package/dist/host/install/index.d.ts +1 -0
  255. package/dist/host/install/index.js +1 -0
  256. package/dist/host/launch/generate.js +25 -1
  257. package/dist/host/launch/session-file.js +4 -1
  258. package/dist/host/launch/stage.js +1 -1
  259. package/dist/host/migrate/backup.js +3 -0
  260. package/dist/host/migrate/migrations/config-file.d.ts +2 -0
  261. package/dist/host/migrate/migrations/config-file.js +7 -0
  262. package/dist/host/migrate/migrations/follow-machine-storage.js +9 -1
  263. package/dist/host/migrate/migrations/pin-storage-root.d.ts +4 -0
  264. package/dist/host/migrate/migrations/pin-storage-root.js +46 -0
  265. package/dist/host/migrate/migrations/unpin-config-defaults.js +4 -1
  266. package/dist/host/migrate/registry.js +2 -1
  267. package/dist/host/profile/accounts.d.ts +25 -1
  268. package/dist/host/profile/accounts.js +96 -13
  269. package/dist/host/profile/agent-accounts.d.ts +5 -1
  270. package/dist/host/profile/agent-accounts.js +35 -5
  271. package/dist/host/profile/index.d.ts +2 -1
  272. package/dist/host/profile/index.js +1 -0
  273. package/dist/host/profile/plugin-share.d.ts +26 -0
  274. package/dist/host/profile/plugin-share.js +146 -0
  275. package/dist/host/projects/join.d.ts +7 -1
  276. package/dist/host/projects/join.js +21 -4
  277. package/dist/host/projects/registry.d.ts +16 -10
  278. package/dist/host/projects/registry.js +74 -6
  279. package/dist/host/sandbox/platform.d.ts +2 -0
  280. package/dist/host/sandbox/platform.js +21 -2
  281. package/dist/host/secrets/index.d.ts +2 -0
  282. package/dist/host/secrets/index.js +2 -0
  283. package/dist/host/secrets/launch-secrets.d.ts +17 -0
  284. package/dist/host/secrets/launch-secrets.js +93 -0
  285. package/dist/host/secrets/secret-store.d.ts +25 -0
  286. package/dist/host/secrets/secret-store.js +89 -0
  287. package/dist/host/sharing/acl.d.ts +16 -2
  288. package/dist/host/sharing/acl.js +35 -10
  289. package/dist/host/sharing/current.js +11 -2
  290. package/dist/host/sharing/doctor.d.ts +2 -0
  291. package/dist/host/sharing/doctor.js +44 -0
  292. package/dist/host/sharing/group-access.d.ts +6 -0
  293. package/dist/host/sharing/group-access.js +24 -0
  294. package/dist/host/sharing/index.d.ts +2 -1
  295. package/dist/host/sharing/index.js +2 -1
  296. package/dist/host/sharing/lifecycle.d.ts +8 -2
  297. package/dist/host/sharing/lifecycle.js +16 -7
  298. package/dist/host/storage/cleanup.d.ts +2 -0
  299. package/dist/host/storage/cleanup.js +2 -1
  300. package/dist/host/storage/history.d.ts +21 -0
  301. package/dist/host/storage/history.js +49 -0
  302. package/dist/host/storage/index.d.ts +4 -0
  303. package/dist/host/storage/index.js +4 -0
  304. package/dist/host/storage/move.d.ts +95 -0
  305. package/dist/host/storage/move.js +384 -0
  306. package/dist/host/storage/offer.d.ts +11 -0
  307. package/dist/host/storage/offer.js +36 -0
  308. package/dist/host/storage/root.d.ts +18 -0
  309. package/dist/host/storage/root.js +77 -0
  310. package/dist/host/tools/windows-terminal.d.ts +2 -0
  311. package/dist/host/tools/windows-terminal.js +23 -5
  312. package/dist/host/update/index.d.ts +1 -1
  313. package/dist/host/update/index.js +1 -1
  314. package/dist/host/update/notice.d.ts +2 -0
  315. package/dist/host/update/notice.js +13 -1
  316. package/dist/host/update/update-state.d.ts +6 -0
  317. package/dist/host/update/update-state.js +2 -0
  318. package/dist/host/update/updater.d.ts +19 -0
  319. package/dist/host/update/updater.js +88 -12
  320. package/dist/host/vpn/index.d.ts +4 -0
  321. package/dist/host/vpn/index.js +4 -0
  322. package/dist/host/vpn/login.d.ts +24 -0
  323. package/dist/host/vpn/login.js +79 -0
  324. package/dist/host/vpn/nordvpn.d.ts +21 -0
  325. package/dist/host/vpn/nordvpn.js +77 -0
  326. package/dist/host/vpn/prepare.d.ts +17 -0
  327. package/dist/host/vpn/prepare.js +77 -0
  328. package/dist/host/vpn/status.d.ts +12 -0
  329. package/dist/host/vpn/status.js +53 -0
  330. package/dist/host/web/auth.d.ts +38 -0
  331. package/dist/host/web/auth.js +96 -0
  332. package/dist/host/web/backend.d.ts +14 -0
  333. package/dist/host/web/backend.js +1 -0
  334. package/dist/host/web/bridge.d.ts +27 -0
  335. package/dist/host/web/bridge.js +144 -0
  336. package/dist/host/web/browser.d.ts +1 -0
  337. package/dist/host/web/browser.js +10 -0
  338. package/dist/host/web/control.d.ts +17 -0
  339. package/dist/host/web/control.js +67 -0
  340. package/dist/host/web/index.d.ts +9 -0
  341. package/dist/host/web/index.js +8 -0
  342. package/dist/host/web/runner.d.ts +14 -0
  343. package/dist/host/web/runner.js +45 -0
  344. package/dist/host/web/server.d.ts +40 -0
  345. package/dist/host/web/server.js +218 -0
  346. package/dist/host/web/state.d.ts +20 -0
  347. package/dist/host/web/state.js +41 -0
  348. package/dist/host/web/static-files.d.ts +13 -0
  349. package/dist/host/web/static-files.js +57 -0
  350. package/dist/runtime/agent.js +27614 -0
  351. package/dist/runtime/daemon.js +1012 -618
  352. package/dist/runtime/db.js +236 -106
  353. package/dist/runtime/main.js +1093 -250
  354. package/dist/runtime/netproxy.js +102 -3
  355. package/dist/runtime/view.js +102 -3
  356. package/dist/selftest/accounts.test.js +40 -0
  357. package/dist/selftest/agent-paths.test.d.ts +2 -0
  358. package/dist/selftest/agent-paths.test.js +115 -0
  359. package/dist/selftest/channel.test.js +5 -0
  360. package/dist/selftest/cli.test.js +34 -4
  361. package/dist/selftest/credentials.test.d.ts +2 -0
  362. package/dist/selftest/credentials.test.js +198 -0
  363. package/dist/selftest/generate.test.js +1 -1
  364. package/dist/selftest/health.test.d.ts +2 -0
  365. package/dist/selftest/health.test.js +470 -0
  366. package/dist/selftest/host-sim.test.js +2 -0
  367. package/dist/selftest/index.js +19 -0
  368. package/dist/selftest/layout.test.js +2 -0
  369. package/dist/selftest/menu-screens.d.ts +7 -0
  370. package/dist/selftest/menu-screens.js +65 -16
  371. package/dist/selftest/menu.test.js +574 -21
  372. package/dist/selftest/migrate.test.js +1 -1
  373. package/dist/selftest/personalization.test.js +3 -1
  374. package/dist/selftest/projects.test.js +39 -1
  375. package/dist/selftest/shared-use.test.js +64 -2
  376. package/dist/selftest/sharing.test.js +50 -1
  377. package/dist/selftest/storage.test.d.ts +2 -0
  378. package/dist/selftest/storage.test.js +363 -0
  379. package/dist/selftest/support/fixtures.d.ts +14 -0
  380. package/dist/selftest/support/releases.js +1 -1
  381. package/dist/selftest/toolchains.test.js +21 -0
  382. package/dist/selftest/update-service.test.js +87 -3
  383. package/dist/selftest/vpn.test.d.ts +2 -0
  384. package/dist/selftest/vpn.test.js +279 -0
  385. package/dist/selftest/web.test.d.ts +2 -0
  386. package/dist/selftest/web.test.js +304 -0
  387. package/dist/shared/apps/catalogue.js +31 -0
  388. package/dist/shared/channel/index.d.ts +1 -0
  389. package/dist/shared/channel/index.js +1 -0
  390. package/dist/shared/channel/run-dir.d.ts +6 -1
  391. package/dist/shared/channel/run-dir.js +12 -1
  392. package/dist/shared/channel/schema.d.ts +19 -0
  393. package/dist/shared/channel/schema.js +11 -0
  394. package/dist/shared/channel/secrets.d.ts +28 -0
  395. package/dist/shared/channel/secrets.js +44 -0
  396. package/dist/shared/vpn/download.d.ts +13 -0
  397. package/dist/shared/vpn/download.js +14 -0
  398. package/dist/shared/vpn/kill-switch.d.ts +18 -0
  399. package/dist/shared/vpn/kill-switch.js +81 -0
  400. package/dist/shared/vpn/ovpn.d.ts +23 -0
  401. package/dist/shared/vpn/ovpn.js +244 -0
  402. package/dist/shared/web/index.d.ts +1 -0
  403. package/dist/shared/web/index.js +1 -0
  404. package/dist/shared/web/protocol.d.ts +61 -0
  405. package/dist/shared/web/protocol.js +35 -0
  406. package/dist/sync/sync-cycle.js +5 -1
  407. package/dist/sync/sync-state.d.ts +1 -0
  408. package/dist/sync/sync-state.js +1 -0
  409. package/dist/sync/watcher.js +10 -0
  410. package/dist/web/index.html +13 -0
  411. package/dist/web/main-CXESL347.js +45 -0
  412. package/dist/web/main-VLR7DVQ4.css +1 -0
  413. package/native/csharp/FolderSecurity.cs +29 -0
  414. package/native/scripts/protect-data.ps1 +29 -0
  415. package/native/scripts/read-folder-sddl.ps1 +10 -0
  416. package/native/scripts/set-folder-access.ps1 +49 -7
  417. package/node_modules/ws/LICENSE +20 -0
  418. package/node_modules/ws/README.md +548 -0
  419. package/node_modules/ws/browser.js +8 -0
  420. package/node_modules/ws/index.js +22 -0
  421. package/node_modules/ws/lib/buffer-util.js +131 -0
  422. package/node_modules/ws/lib/constants.js +19 -0
  423. package/node_modules/ws/lib/event-target.js +292 -0
  424. package/node_modules/ws/lib/extension.js +203 -0
  425. package/node_modules/ws/lib/limiter.js +55 -0
  426. package/node_modules/ws/lib/permessage-deflate.js +530 -0
  427. package/node_modules/ws/lib/receiver.js +743 -0
  428. package/node_modules/ws/lib/sender.js +607 -0
  429. package/node_modules/ws/lib/stream.js +161 -0
  430. package/node_modules/ws/lib/subprotocol.js +62 -0
  431. package/node_modules/ws/lib/validation.js +152 -0
  432. package/node_modules/ws/lib/websocket-server.js +562 -0
  433. package/node_modules/ws/lib/websocket.js +1421 -0
  434. package/node_modules/ws/package.json +74 -0
  435. package/node_modules/ws/wrapper.mjs +21 -0
  436. package/package.json +15 -5
  437. package/sandbox/csharp/EnvBroadcast.cs +33 -0
  438. package/sandbox/csharp/PathSync.cs +90 -0
  439. package/sandbox/scripts/install-shell-path.ps1 +73 -0
  440. package/sandbox/scripts/set-machine-environment.ps1 +37 -4
  441. package/schemas/config.schema.json +79 -4
  442. package/schemas/sandbox-config.schema.json +14 -1
  443. package/dist/cli/commands/repair/checks.d.ts +0 -2
  444. package/dist/cli/commands/repair/checks.js +0 -246
  445. package/dist/cli/menu/pages/start-page.d.ts +0 -43
  446. package/dist/cli/menu/pages/start-page.js +0 -192
  447. package/dist/cli/tui/tab-bar.d.ts +0 -9
  448. package/dist/cli/tui/tab-bar.js +0 -33
@@ -0,0 +1,55 @@
1
+ // This PC: Windows itself, what Windows Sandbox needs of it, and whether Windows wants a restart. The hardware and
2
+ // edition answers come from the same look `sandbox setup` takes (once per run).
3
+ import { isWin } from '../../../../core/util/index.js';
4
+ import { updateRestartPending } from '../../../../host/life/index.js';
5
+ import { buildChecks } from '../../setup/checks.js';
6
+ import { ok } from './common.js';
7
+ const STATUS = { ok: 'ok', warn: 'warn', action: 'needs-you' };
8
+ /** One line of the setup checklist as a check. */
9
+ export function fromFacts(id, group, setupName, name = setupName) {
10
+ return {
11
+ id,
12
+ group,
13
+ name,
14
+ timeoutMs: 60_000,
15
+ run: (env) => {
16
+ const row = buildChecks(env.facts()).find((c) => c.name === setupName);
17
+ if (!row)
18
+ return { status: 'skipped', detail: 'no answer for "' + setupName + '"' };
19
+ return { status: STATUS[row.status], detail: row.detail };
20
+ },
21
+ };
22
+ }
23
+ export const PC_CHECKS = [
24
+ {
25
+ id: 'pc-windows',
26
+ group: 'This PC',
27
+ name: 'Windows',
28
+ run: () => isWin
29
+ ? ok('Windows ' + process.arch)
30
+ : {
31
+ status: 'needs-you',
32
+ detail: 'this is not Windows',
33
+ means: 'Windows Sandbox only runs on Windows.',
34
+ fix: 'Run sandbox on a Windows 10/11 Pro, Enterprise or Education PC.',
35
+ },
36
+ },
37
+ fromFacts('pc-edition', 'This PC', 'Windows edition', 'Windows edition'),
38
+ fromFacts('pc-virtualization', 'This PC', 'CPU virtualization', 'CPU virtualization'),
39
+ fromFacts('pc-memory', 'This PC', 'Memory', 'Memory'),
40
+ fromFacts('pc-node', 'This PC', 'Node.js', 'Node.js'),
41
+ {
42
+ id: 'pc-restart-pending',
43
+ group: 'This PC',
44
+ name: 'Windows restart',
45
+ timeoutMs: 40_000,
46
+ run: () => updateRestartPending()
47
+ ? {
48
+ status: 'warn',
49
+ detail: 'Windows is waiting for a restart',
50
+ means: 'Windows may restart on its own and close a running sandbox.',
51
+ fix: 'Restart Windows when it suits you, or pause Windows updates while you work.',
52
+ }
53
+ : ok('no restart pending'),
54
+ },
55
+ ];
@@ -0,0 +1,2 @@
1
+ import type { Check } from '../types.js';
2
+ export declare const SANDBOX_CHECKS: Check[];
@@ -0,0 +1,267 @@
1
+ // The sandbox: Windows Sandbox itself, whether one runs, and what a closed or crashed one leaves behind (run files,
2
+ // hidden windows, background watchers, old launch folders), plus the helper programs this tool builds or downloads
3
+ // on the PC.
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ import { dirExists, fileExists, isLink } from '../../../../core/util/index.js';
7
+ import { SandboxChannel } from '../../../../host/channel/index.js';
8
+ import { orphanWatchers, runStateProblems, staleLaunchFolders, watcherRecords } from '../../../../host/health/index.js';
9
+ import { hostToolsExe } from '../../../../host/native.js';
10
+ import { sandboxFeatureInstalled } from '../../../../host/sandbox/index.js';
11
+ import { assertTestWritable, refuseInSelfTest } from '../../../../host/test-guard.js';
12
+ import { conptyDir, terminalDir, terminalExe } from '../../../../host/tools/index.js';
13
+ import { RunDir } from '../../../../shared/channel/index.js';
14
+ import { safeRemove } from '../../../../shared/io/index.js';
15
+ import { removeTree } from '../../data/remove.js';
16
+ import { deadPidFiles } from '../finders.js';
17
+ import { fromFacts } from './pc.js';
18
+ import { ok, plural, rel } from './common.js';
19
+ const LAUNCH_DAYS = 7;
20
+ const hiddenWindowsFile = (env) => path.join(env.storageRoot, 'run', 'hidden-windows.json');
21
+ export const SANDBOX_CHECKS = [
22
+ {
23
+ id: 'sandbox-exe',
24
+ group: 'Sandbox',
25
+ name: 'WindowsSandbox.exe',
26
+ run: () => sandboxFeatureInstalled()
27
+ ? ok('present')
28
+ : {
29
+ status: 'needs-you',
30
+ detail: 'WindowsSandbox.exe is not in Windows\\System32',
31
+ means: 'Windows Sandbox is not turned on (it appears after the restart that follows turning it on).',
32
+ fix: 'Run: sandbox setup (it checks this PC and offers to turn it on).',
33
+ },
34
+ },
35
+ fromFacts('sandbox-feature', 'Sandbox', 'Windows Sandbox feature', 'Windows Sandbox feature'),
36
+ {
37
+ id: 'sandbox-running',
38
+ group: 'Sandbox',
39
+ name: 'Running sandbox',
40
+ run: (env) => {
41
+ if (!env.running)
42
+ return ok('none running');
43
+ const run = new RunDir(env.dataPath);
44
+ const known = fs.existsSync(run.sandboxFile) || run.listSessions().length > 0;
45
+ if (known)
46
+ return ok('one is running, with its status in your data folder; fixes that touch its folders wait');
47
+ return {
48
+ status: 'warn',
49
+ detail: 'a Windows Sandbox is running, but nothing of yours is in the data folder',
50
+ means: 'It was started by another user, by hand, or its status files were removed. Windows allows only one at a time.',
51
+ fix: 'Close its window (or run sandbox stop) before starting yours.',
52
+ };
53
+ },
54
+ },
55
+ {
56
+ id: 'sandbox-run-state',
57
+ group: 'Sandbox',
58
+ name: 'Sandbox run state',
59
+ run: (env) => {
60
+ const run = new RunDir(env.dataPath);
61
+ if (env.running)
62
+ return ok('a sandbox is running; its state is in use');
63
+ if (isLink(run.root))
64
+ return {
65
+ status: 'needs-you',
66
+ detail: 'the run folder is a link',
67
+ means: 'It could lead anywhere on this PC; it is never followed.',
68
+ plan: 'remove the link itself',
69
+ };
70
+ const problems = runStateProblems(env.dataPath);
71
+ if (!problems.any)
72
+ return ok('clean');
73
+ const what = [
74
+ problems.sessions ? plural(problems.sessions, 'session') + ' still marked running' : '',
75
+ problems.requests ? plural(problems.requests, 'request') + ' never answered' : '',
76
+ problems.unfinishedBoot ? 'a start that stopped while ' + problems.unfinishedBoot : '',
77
+ ].filter(Boolean);
78
+ return {
79
+ status: 'needs-you',
80
+ detail: 'no sandbox is running, but ' + what.join(', '),
81
+ means: 'sandbox status and attach would show sessions that are not there.',
82
+ plan: 'clear the run state of the closed sandbox (' + what.length + ' item' + (what.length === 1 ? '' : 's') + ')',
83
+ lines: what,
84
+ };
85
+ },
86
+ fix: (env) => {
87
+ new SandboxChannel(env.dataPath, () => env.running).reset();
88
+ return { done: 'cleared the run state of the closed sandbox' };
89
+ },
90
+ },
91
+ {
92
+ id: 'sandbox-hidden-windows',
93
+ group: 'Sandbox',
94
+ name: 'Hidden-window list',
95
+ run: (env) => {
96
+ const file = hiddenWindowsFile(env);
97
+ if (!fs.existsSync(file) && !isLink(file))
98
+ return ok('clean');
99
+ if (env.running)
100
+ return ok('a sandbox is running; kept');
101
+ return {
102
+ status: 'needs-you',
103
+ detail: 'a list of hidden windows from a sandbox that is no longer running',
104
+ plan: 'remove the saved hidden-window list',
105
+ };
106
+ },
107
+ fix: (env) => {
108
+ const file = hiddenWindowsFile(env);
109
+ assertTestWritable(file);
110
+ fs.rmSync(file, { force: true });
111
+ return { done: 'removed the saved hidden-window list' };
112
+ },
113
+ },
114
+ {
115
+ id: 'sandbox-watcher-records',
116
+ group: 'Sandbox',
117
+ name: 'Sync watcher records',
118
+ run: (env) => {
119
+ const dead = deadPidFiles(path.join(env.storageRoot, 'run'), (pid) => env.system.pidAlive(pid));
120
+ if (!dead.length)
121
+ return ok('no stale records');
122
+ return {
123
+ status: 'needs-you',
124
+ detail: plural(dead.length, 'record') + ' of a history sync watcher that is no longer running',
125
+ plan: 'remove ' + plural(dead.length, 'stale watcher record') + ' (the next start begins a new watcher)',
126
+ data: dead,
127
+ };
128
+ },
129
+ fix: (_env, finding) => {
130
+ const dead = Array.isArray(finding.data) ? finding.data : [];
131
+ for (const f of dead) {
132
+ assertTestWritable(f);
133
+ fs.rmSync(f, { force: true });
134
+ }
135
+ return { done: 'removed ' + plural(dead.length, 'stale watcher record') };
136
+ },
137
+ },
138
+ {
139
+ id: 'sandbox-orphan-watchers',
140
+ group: 'Sandbox',
141
+ name: 'Background watchers',
142
+ timeoutMs: 40_000,
143
+ run: (env) => {
144
+ const infos = watcherRecords(env.storageRoot, env.now());
145
+ const rows = infos.length && !env.running ? env.system.processes() : [];
146
+ const image = (pid) => rows.find((r) => r.pid === pid)?.image ?? null;
147
+ const orphans = orphanWatchers(infos, { running: env.running, alive: (pid) => env.system.pidAlive(pid), image });
148
+ if (!orphans.length)
149
+ return ok(infos.length ? 'every watcher has a sandbox to watch' : 'none running');
150
+ return {
151
+ status: 'needs-you',
152
+ detail: plural(orphans.length, 'background history watcher') + ' running with no sandbox',
153
+ means: 'They use memory and keep files open until stopped.',
154
+ plan: 'stop ' + plural(orphans.length, 'orphaned watcher') + ' (history already synced stays)',
155
+ lines: orphans.map((o) => 'process ' + o.pid + ' (' + rel(env.storageRoot, o.file) + ')'),
156
+ data: orphans.map((o) => ({ pid: o.pid, file: o.file })),
157
+ };
158
+ },
159
+ fix: (env, finding) => {
160
+ const list = Array.isArray(finding.data) ? finding.data : [];
161
+ for (const w of list) {
162
+ env.system.stop(w.pid);
163
+ assertTestWritable(w.file);
164
+ fs.rmSync(w.file, { force: true });
165
+ }
166
+ return { done: 'stopped ' + plural(list.length, 'orphaned watcher') };
167
+ },
168
+ },
169
+ {
170
+ id: 'sandbox-launch-folders',
171
+ group: 'Sandbox',
172
+ name: 'Old launch folders',
173
+ needsIdle: 'fix',
174
+ run: (env) => {
175
+ const old = staleLaunchFolders(env.storageRoot, LAUNCH_DAYS, env.now());
176
+ if (!old.length)
177
+ return ok('none older than ' + LAUNCH_DAYS + ' days');
178
+ return {
179
+ status: 'needs-you',
180
+ detail: plural(old.length, 'launch folder') + ' older than ' + LAUNCH_DAYS + ' days',
181
+ means: 'Each belongs to a start that is long over; they only use disk space.',
182
+ plan: 'remove ' + plural(old.length, 'old launch folder'),
183
+ lines: old.map((o) => rel(env.storageRoot, o.path) + ' (' + o.ageDays + ' days)'),
184
+ data: old.map((o) => o.path),
185
+ };
186
+ },
187
+ fix: (env, finding) => {
188
+ const old = Array.isArray(finding.data) ? finding.data : [];
189
+ for (const p of old)
190
+ safeRemove(p, env.storageRoot);
191
+ return { done: 'removed ' + plural(old.length, 'old launch folder') };
192
+ },
193
+ },
194
+ {
195
+ id: 'sandbox-hosttools',
196
+ group: 'Sandbox',
197
+ name: 'HostTools.exe',
198
+ timeoutMs: 150_000,
199
+ run: (env) => {
200
+ const bin = path.join(env.storageRoot, 'bin');
201
+ const built = dirExists(bin) && fs.readdirSync(bin).some((n) => /^HostTools-[0-9a-f]+\.exe$/i.test(n));
202
+ if (built)
203
+ return ok('built in ' + bin);
204
+ return {
205
+ status: 'warn',
206
+ detail: 'HostTools.exe is not built yet',
207
+ means: 'It keeps this PC awake and edits your PATH; it is built the first time one is needed, and until then a slower PowerShell fallback runs.',
208
+ plan: 'build HostTools.exe now',
209
+ };
210
+ },
211
+ fix: (env) => {
212
+ refuseInSelfTest('build HostTools.exe');
213
+ const exe = hostToolsExe(env.storageRoot);
214
+ if (!exe)
215
+ throw new Error('it could not be built (is the .NET Framework compiler csc.exe missing?)');
216
+ return { done: 'built ' + exe };
217
+ },
218
+ },
219
+ {
220
+ id: 'sandbox-conpty',
221
+ group: 'Sandbox',
222
+ name: 'Pseudo console (conpty)',
223
+ needsIdle: 'fix',
224
+ run: (env) => {
225
+ const dir = conptyDir(env.dataPath);
226
+ if (!dirExists(dir))
227
+ return ok('not downloaded yet (the next start downloads it)');
228
+ if (fileExists(path.join(dir, 'conpty.dll')) && fileExists(path.join(dir, 'OpenConsole.exe')))
229
+ return ok('downloaded');
230
+ return {
231
+ status: 'warn',
232
+ detail: 'the conpty download is incomplete',
233
+ means: 'Agent terminals would use the older Windows console and can garble after a resize.',
234
+ plan: 'remove the incomplete download (the next start downloads it again)',
235
+ data: dir,
236
+ };
237
+ },
238
+ fix: (env, finding) => {
239
+ removeTree(String(finding.data), env.dataPath);
240
+ return { done: 'removed the incomplete conpty download' };
241
+ },
242
+ },
243
+ {
244
+ id: 'sandbox-terminal',
245
+ group: 'Sandbox',
246
+ name: 'Windows Terminal download',
247
+ needsIdle: 'fix',
248
+ run: (env) => {
249
+ const dir = terminalDir(env.dataPath);
250
+ if (!dirExists(dir))
251
+ return ok('not downloaded yet (the next start downloads it)');
252
+ if (fileExists(terminalExe(env.dataPath)))
253
+ return ok('downloaded');
254
+ return {
255
+ status: 'warn',
256
+ detail: 'the Windows Terminal download is incomplete',
257
+ means: 'The sandbox window falls back to a plain console.',
258
+ plan: 'remove the incomplete download (the next start downloads it again)',
259
+ data: dir,
260
+ };
261
+ },
262
+ fix: (env, finding) => {
263
+ removeTree(String(finding.data), env.dataPath);
264
+ return { done: 'removed the incomplete Windows Terminal download' };
265
+ },
266
+ },
267
+ ];
@@ -0,0 +1,2 @@
1
+ import type { Check } from '../types.js';
2
+ export declare const SETTINGS_CHECKS: Check[];
@@ -0,0 +1,169 @@
1
+ // Settings: does config.json load, are the updates to your saved settings done, and are the project files you approved
2
+ // still the ones you approved. A settings file that does not load can be put back from the copy an update saved
3
+ // (the broken one is kept beside it).
4
+ import crypto from 'node:crypto';
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import { DEFAULTS, mergeConfig, validateConfig } from '../../../../core/config/index.js';
8
+ import { trustStorePath } from '../../../../core/local-config/index.js';
9
+ import { errMsg, readJsonc, tryReadJson } from '../../../../core/util/index.js';
10
+ import { configBackups, lineDiff } from '../../../../host/health/index.js';
11
+ import { assertTestWritable } from '../../../../host/test-guard.js';
12
+ import { MigrateService } from '../../../services/migrate-service.js';
13
+ import { ok, plural } from './common.js';
14
+ const MAX_PROJECT_FILE_BYTES = 1024 * 1024;
15
+ /** The newest saved copy of the settings file that itself loads. */
16
+ function goodBackup(env) {
17
+ return (configBackups(env.storageRoot, env.configFile).find((b) => {
18
+ try {
19
+ validateConfig(mergeConfig(DEFAULTS, readJsonc(b.copy)), b.copy);
20
+ return true;
21
+ }
22
+ catch {
23
+ return false;
24
+ }
25
+ }) ?? null);
26
+ }
27
+ const messageOf = (e) => e.message.split('\n')[0] + (e.fix ? ' ' + e.fix : '');
28
+ /** The files in <storage>\trusted-configs.json whose approval no longer matches the file (hash differs). */
29
+ function changedApprovals(storageRoot) {
30
+ const store = tryReadJson(trustStorePath(storageRoot));
31
+ if (!store || typeof store !== 'object')
32
+ return [];
33
+ const changed = [];
34
+ for (const [file, hash] of Object.entries(store)) {
35
+ if (typeof hash !== 'string' || !path.isAbsolute(file))
36
+ continue;
37
+ try {
38
+ const stat = fs.statSync(file);
39
+ if (!stat.isFile() || stat.size > MAX_PROJECT_FILE_BYTES)
40
+ continue;
41
+ if (crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex') !== hash)
42
+ changed.push(file);
43
+ }
44
+ catch {
45
+ // the project is gone or not readable: nothing to compare
46
+ }
47
+ }
48
+ return changed;
49
+ }
50
+ export const SETTINGS_CHECKS = [
51
+ {
52
+ id: 'settings-config',
53
+ group: 'Settings',
54
+ name: 'Settings file',
55
+ run: (env) => {
56
+ const error = env.configError;
57
+ if (!error)
58
+ return ok(env.ctx.loaded.configPath
59
+ ? env.ctx.loaded.configPath + ' is valid'
60
+ : 'no settings file; the built-in defaults apply');
61
+ const base = {
62
+ status: 'needs-you',
63
+ detail: messageOf(error),
64
+ means: 'Every command that reads your settings stops until this is fixed (built-in defaults were used for the other checks).',
65
+ };
66
+ let backup = null;
67
+ try {
68
+ backup = fs.existsSync(env.configFile) ? goodBackup(env) : null;
69
+ }
70
+ catch (e) {
71
+ return {
72
+ ...base,
73
+ fix: 'Fix ' + env.configFile + ' by hand (the backups could not be read: ' + errMsg(e) + ').',
74
+ };
75
+ }
76
+ if (!backup)
77
+ return {
78
+ ...base,
79
+ fix: 'Open ' + env.configFile + ' and correct what is listed, or delete it to start again with the defaults.',
80
+ };
81
+ const diff = lineDiff(fs.readFileSync(env.configFile, 'utf8'), fs.readFileSync(backup.copy, 'utf8'));
82
+ return {
83
+ ...base,
84
+ plan: 'put back the settings saved before the update ' +
85
+ backup.label +
86
+ ' (your current file is kept as config.json.broken-...)',
87
+ lines: [
88
+ 'Changes from your file (-) to the saved copy (+):',
89
+ ...(diff.length ? diff : ['(the files read the same)']),
90
+ ],
91
+ data: backup.copy,
92
+ };
93
+ },
94
+ fix: (env, finding) => {
95
+ const copy = String(finding.data);
96
+ assertTestWritable(env.configFile);
97
+ const kept = env.configFile + '.broken-' + new Date(env.now()).toISOString().replace(/\D/g, '').slice(0, 14);
98
+ fs.copyFileSync(env.configFile, kept);
99
+ fs.copyFileSync(copy, env.configFile);
100
+ // The engine looks again after the fix; the config is read from the file, not from the earlier error.
101
+ env.configError = null;
102
+ try {
103
+ validateConfig(mergeConfig(DEFAULTS, readJsonc(env.configFile)), env.configFile);
104
+ }
105
+ catch (e) {
106
+ env.configError = e;
107
+ }
108
+ return {
109
+ done: 'put the saved settings back in ' + env.configFile + '; the broken file is kept as ' + path.basename(kept),
110
+ };
111
+ },
112
+ },
113
+ {
114
+ id: 'settings-updates',
115
+ group: 'Settings',
116
+ name: 'Saved settings up to date',
117
+ run: (env) => {
118
+ const service = new MigrateService({ storageRoot: env.storageRoot, userDir: env.userDir, configPath: env.ctx.loaded.configPath }, undefined, env.migrations, () => env.running);
119
+ let pending;
120
+ try {
121
+ pending = service.plan();
122
+ }
123
+ catch (e) {
124
+ return {
125
+ status: 'needs-you',
126
+ detail: errMsg(e),
127
+ means: 'The record of which updates ran is damaged, so none can be applied.',
128
+ };
129
+ }
130
+ if (!pending.length)
131
+ return ok('nothing waits');
132
+ return {
133
+ status: 'needs-you',
134
+ detail: plural(pending.length, 'change') + ' to your saved settings wait',
135
+ means: 'This version expects your settings in a newer form.',
136
+ plan: 'bring your saved settings up to date (a backup is made first)',
137
+ lines: pending,
138
+ };
139
+ },
140
+ fix: async (env) => {
141
+ const service = new MigrateService({ storageRoot: env.storageRoot, userDir: env.userDir, configPath: env.ctx.loaded.configPath }, undefined, env.migrations, () => env.running);
142
+ const notes = [];
143
+ const result = await service.run((line) => notes.push(line));
144
+ return {
145
+ done: (result.applied.length ? 'applied ' + result.applied.join(', ') : 'applied nothing') +
146
+ (result.postponed.length ? '; ' + result.postponed.join(', ') + ' wait until no sandbox runs' : ''),
147
+ };
148
+ },
149
+ },
150
+ {
151
+ id: 'settings-approvals',
152
+ group: 'Settings',
153
+ name: 'Approved project files',
154
+ run: (env) => {
155
+ const changed = changedApprovals(env.storageRoot);
156
+ if (!changed.length)
157
+ return ok('every project file you approved is unchanged');
158
+ return {
159
+ status: 'warn',
160
+ detail: plural(changed.length, 'project file') +
161
+ ' changed since you approved ' +
162
+ (changed.length === 1 ? 'it' : 'them'),
163
+ means: 'Its settings are ignored until you approve the new version; the next launch in that project asks again.',
164
+ fix: 'Nothing to repair. Read the changes, then run sandbox in that project and answer the question (or sandbox config check).',
165
+ lines: changed,
166
+ };
167
+ },
168
+ },
169
+ ];
@@ -0,0 +1,2 @@
1
+ import type { Check } from '../types.js';
2
+ export declare const VPN_CHECKS: Check[];
@@ -0,0 +1,53 @@
1
+ // The VPN, when it is on: is the login saved and readable, can the OpenVPN download be reached. Not shown when the
2
+ // VPN is off. (That the storage folder is private is checked with the data folder.)
3
+ import { VpnLogin } from '../../../../host/vpn/index.js';
4
+ import { OPENVPN_MSI } from '../../../../shared/vpn/download.js';
5
+ import { ok } from './common.js';
6
+ const REACH_MS = 6000;
7
+ const vpnOn = (env) => env.ctx.loaded.config.vpn.enabled;
8
+ export const VPN_CHECKS = [
9
+ {
10
+ id: 'vpn-login',
11
+ group: 'Network',
12
+ name: 'VPN login',
13
+ checking: 'the saved VPN login',
14
+ applies: vpnOn,
15
+ run: (env) => {
16
+ const { provider } = env.ctx.loaded.config.vpn;
17
+ const state = new VpnLogin(env.storageRoot).state(provider);
18
+ if (state === 'saved')
19
+ return ok('saved, encrypted, and this Windows user can read it');
20
+ return state === 'none'
21
+ ? {
22
+ status: 'needs-you',
23
+ detail: 'the VPN is on but no login is saved',
24
+ means: 'The sandbox cannot start its VPN, so a launch stops.',
25
+ fix: 'Run sandbox vpn login (or turn the VPN off: sandbox config set vpn.enabled false).',
26
+ }
27
+ : {
28
+ status: 'needs-you',
29
+ detail: 'a login is saved but this Windows user cannot decrypt it',
30
+ means: 'It was saved by another Windows user or on another PC, so the VPN cannot start.',
31
+ fix: 'Save it again: sandbox vpn login',
32
+ };
33
+ },
34
+ },
35
+ {
36
+ id: 'vpn-download',
37
+ group: 'Network',
38
+ name: 'OpenVPN download',
39
+ checking: 'whether the OpenVPN download can be reached',
40
+ applies: vpnOn,
41
+ timeoutMs: REACH_MS + 4000,
42
+ run: async (env) => {
43
+ if (await env.system.reachable(OPENVPN_MSI.base, REACH_MS))
44
+ return ok('swupdate.openvpn.org answers');
45
+ return {
46
+ status: 'warn',
47
+ detail: 'swupdate.openvpn.org did not answer within ' + REACH_MS / 1000 + ' seconds',
48
+ means: 'The sandbox downloads OpenVPN there at its first VPN start (it is kept afterwards).',
49
+ fix: 'Check your internet connection or proxy, then run this again.',
50
+ };
51
+ },
52
+ },
53
+ ];
@@ -0,0 +1,32 @@
1
+ import { type Check, type CheckResult, type RepairEnv, type Summary } from './types.js';
2
+ export declare const DEFAULT_TIMEOUT_MS = 20000;
3
+ export declare const FIX_TIMEOUT_MS = 120000;
4
+ /** What the output hooks into: each step, as it happens. */
5
+ export interface RunHooks {
6
+ lookStart?: (check: Check) => void;
7
+ lookEnd?: (result: CheckResult) => void;
8
+ fixStart?: (result: CheckResult) => void;
9
+ fixEnd?: (result: CheckResult) => void;
10
+ }
11
+ /** Resolves with `work`, or rejects with TimedOut after `ms` (a check that blocks the process cannot be stopped). */
12
+ export declare function withTimeout<T>(work: () => T | Promise<T>, ms: number): Promise<T>;
13
+ /** The checks in the order they are shown: by group, then as listed. */
14
+ export declare function inGroupOrder(checks: readonly Check[]): Check[];
15
+ export declare function summarize(results: readonly CheckResult[]): Summary;
16
+ export declare class HealthRun {
17
+ private readonly env;
18
+ private readonly hooks;
19
+ private readonly limits;
20
+ private readonly findings;
21
+ private readonly checks;
22
+ constructor(checks: readonly Check[], env: RepairEnv, hooks?: RunHooks, limits?: {
23
+ lookMs?: number;
24
+ fixMs?: number;
25
+ });
26
+ /** Runs every check without changing anything. */
27
+ look(): Promise<CheckResult[]>;
28
+ /** Applies the fix of every result repair can mend (or only those in `only`), then looks again. */
29
+ fix(results: readonly CheckResult[], only?: readonly string[]): Promise<CheckResult[]>;
30
+ private lookAt;
31
+ private fixOne;
32
+ }