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.
- package/README.md +1 -0
- package/config.example.json +17 -1
- package/dist/cli/args.d.ts +13 -2
- package/dist/cli/args.js +95 -24
- package/dist/cli/commands/accounts.js +45 -17
- package/dist/cli/commands/context.d.ts +2 -0
- package/dist/cli/commands/context.js +9 -2
- package/dist/cli/commands/data/clean.js +32 -9
- package/dist/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.js +1 -0
- package/dist/cli/commands/launch/add-root.d.ts +3 -2
- package/dist/cli/commands/launch/add-root.js +11 -10
- package/dist/cli/commands/launch/launch.js +57 -4
- package/dist/cli/commands/launch/prepare.js +3 -1
- package/dist/cli/commands/maintenance/audit.js +1 -1
- package/dist/cli/commands/maintenance/clean.d.ts +1 -1
- package/dist/cli/commands/maintenance/clean.js +17 -3
- package/dist/cli/commands/maintenance/config.d.ts +1 -1
- package/dist/cli/commands/maintenance/config.js +112 -10
- package/dist/cli/commands/maintenance/doctor.d.ts +1 -1
- package/dist/cli/commands/maintenance/doctor.js +2 -4
- package/dist/cli/commands/maintenance/migrate.d.ts +2 -1
- package/dist/cli/commands/maintenance/migrate.js +19 -4
- package/dist/cli/commands/maintenance/sync.js +2 -0
- package/dist/cli/commands/maintenance/update.d.ts +2 -0
- package/dist/cli/commands/maintenance/update.js +27 -4
- package/dist/cli/commands/projects/here.js +12 -7
- package/dist/cli/commands/projects/projects.js +26 -17
- package/dist/cli/commands/registry.js +7 -0
- package/dist/cli/commands/repair/checks/agents.d.ts +2 -0
- package/dist/cli/commands/repair/checks/agents.js +70 -0
- package/dist/cli/commands/repair/checks/common.d.ts +8 -0
- package/dist/cli/commands/repair/checks/common.js +22 -0
- package/dist/cli/commands/repair/checks/data.d.ts +2 -0
- package/dist/cli/commands/repair/checks/data.js +241 -0
- package/dist/cli/commands/repair/checks/index.d.ts +2 -0
- package/dist/cli/commands/repair/checks/index.js +20 -0
- package/dist/cli/commands/repair/checks/install.d.ts +5 -0
- package/dist/cli/commands/repair/checks/install.js +318 -0
- package/dist/cli/commands/repair/checks/machine.d.ts +2 -0
- package/dist/cli/commands/repair/checks/machine.js +232 -0
- package/dist/cli/commands/repair/checks/network.d.ts +6 -0
- package/dist/cli/commands/repair/checks/network.js +60 -0
- package/dist/cli/commands/repair/checks/pc.d.ts +4 -0
- package/dist/cli/commands/repair/checks/pc.js +55 -0
- package/dist/cli/commands/repair/checks/sandbox.d.ts +2 -0
- package/dist/cli/commands/repair/checks/sandbox.js +267 -0
- package/dist/cli/commands/repair/checks/settings.d.ts +2 -0
- package/dist/cli/commands/repair/checks/settings.js +169 -0
- package/dist/cli/commands/repair/checks/vpn.d.ts +2 -0
- package/dist/cli/commands/repair/checks/vpn.js +53 -0
- package/dist/cli/commands/repair/engine.d.ts +32 -0
- package/dist/cli/commands/repair/engine.js +127 -0
- package/dist/cli/commands/repair/env.d.ts +7 -0
- package/dist/cli/commands/repair/env.js +49 -0
- package/dist/cli/commands/repair/index.d.ts +1 -9
- package/dist/cli/commands/repair/index.js +2 -54
- package/dist/cli/commands/repair/log.d.ts +17 -0
- package/dist/cli/commands/repair/log.js +82 -0
- package/dist/cli/commands/repair/printer.d.ts +32 -0
- package/dist/cli/commands/repair/printer.js +132 -0
- package/dist/cli/commands/repair/run.d.ts +33 -0
- package/dist/cli/commands/repair/run.js +133 -0
- package/dist/cli/commands/repair/types.d.ts +97 -9
- package/dist/cli/commands/repair/types.js +11 -7
- package/dist/cli/commands/resume.js +2 -2
- package/dist/cli/commands/sessions/list.js +5 -2
- package/dist/cli/commands/sessions/status.d.ts +2 -0
- package/dist/cli/commands/sessions/status.js +27 -6
- package/dist/cli/commands/setup/index.d.ts +5 -0
- package/dist/cli/commands/setup/index.js +25 -1
- package/dist/cli/commands/storage/index.d.ts +2 -0
- package/dist/cli/commands/storage/index.js +2 -0
- package/dist/cli/commands/storage/offer.d.ts +3 -0
- package/dist/cli/commands/storage/offer.js +85 -0
- package/dist/cli/commands/storage/storage.d.ts +8 -0
- package/dist/cli/commands/storage/storage.js +171 -0
- package/dist/cli/commands/user-config.js +1 -1
- package/dist/cli/commands/vpn.d.ts +4 -0
- package/dist/cli/commands/vpn.js +75 -0
- package/dist/cli/commands/web.d.ts +4 -0
- package/dist/cli/commands/web.js +95 -0
- package/dist/cli/history.js +1 -1
- package/dist/cli/index.js +46 -3
- package/dist/cli/manifest.d.ts +303 -29
- package/dist/cli/manifest.js +173 -43
- package/dist/cli/menu/add-agent.d.ts +47 -0
- package/dist/cli/menu/add-agent.js +168 -0
- package/dist/cli/menu/apps.d.ts +31 -2
- package/dist/cli/menu/apps.js +44 -5
- package/dist/cli/menu/command-fields.d.ts +18 -0
- package/dist/cli/menu/command-fields.js +61 -0
- package/dist/cli/menu/command-form.d.ts +22 -0
- package/dist/cli/menu/command-form.js +169 -46
- package/dist/cli/menu/data-folder.d.ts +18 -0
- package/dist/cli/menu/data-folder.js +99 -0
- package/dist/cli/menu/menu.d.ts +1 -1
- package/dist/cli/menu/menu.js +11 -8
- package/dist/cli/menu/pages/accounts-page.js +55 -24
- package/dist/cli/menu/pages/agents-page.d.ts +66 -0
- package/dist/cli/menu/pages/agents-page.js +338 -0
- package/dist/cli/menu/pages/apps-page.js +1 -2
- package/dist/cli/menu/pages/list-page.d.ts +16 -3
- package/dist/cli/menu/pages/list-page.js +40 -8
- package/dist/cli/menu/pages/maintenance-page.d.ts +9 -0
- package/dist/cli/menu/pages/maintenance-page.js +161 -72
- package/dist/cli/menu/pages/sandbox-page.d.ts +3 -0
- package/dist/cli/menu/pages/sandbox-page.js +132 -43
- package/dist/cli/menu/pages/sessions-page.d.ts +4 -0
- package/dist/cli/menu/pages/sessions-page.js +41 -25
- package/dist/cli/menu/pages/settings-page.d.ts +8 -4
- package/dist/cli/menu/pages/settings-page.js +36 -13
- package/dist/cli/menu/settings/categories.d.ts +2 -0
- package/dist/cli/menu/settings/categories.js +19 -44
- package/dist/cli/menu/settings/collections/collection-editor.d.ts +7 -1
- package/dist/cli/menu/settings/collections/collection-editor.js +12 -8
- package/dist/cli/menu/settings/collections/map-editor.js +5 -1
- package/dist/cli/menu/settings/collections/object-list-editor.js +2 -2
- package/dist/cli/menu/settings/collections/object-map-editor.js +2 -2
- package/dist/cli/menu/settings/collections/string-list-editor.d.ts +11 -1
- package/dist/cli/menu/settings/collections/string-list-editor.js +23 -0
- package/dist/cli/menu/settings/index.d.ts +1 -1
- package/dist/cli/menu/settings/index.js +1 -1
- package/dist/cli/menu/settings/object-editor.d.ts +5 -1
- package/dist/cli/menu/settings/object-editor.js +15 -4
- package/dist/cli/menu/settings/path-kind.d.ts +20 -0
- package/dist/cli/menu/settings/path-kind.js +44 -0
- package/dist/cli/menu/settings/schema-node.d.ts +9 -0
- package/dist/cli/menu/settings/schema-node.js +26 -0
- package/dist/cli/menu/settings/value-editor.d.ts +5 -0
- package/dist/cli/menu/settings/value-editor.js +51 -18
- package/dist/cli/menu/several.js +7 -5
- package/dist/cli/menu/shell.d.ts +37 -10
- package/dist/cli/menu/shell.js +90 -10
- package/dist/cli/menu/vpn-login.d.ts +16 -0
- package/dist/cli/menu/vpn-login.js +66 -0
- package/dist/cli/output/print.d.ts +2 -0
- package/dist/cli/output/print.js +8 -1
- package/dist/cli/services/accounts-service.d.ts +2 -0
- package/dist/cli/services/accounts-service.js +2 -2
- package/dist/cli/services/health-service.d.ts +0 -6
- package/dist/cli/services/health-service.js +5 -42
- package/dist/cli/services/index.d.ts +3 -1
- package/dist/cli/services/index.js +3 -1
- package/dist/cli/services/migrate-service.js +1 -1
- package/dist/cli/services/update-service.d.ts +2 -0
- package/dist/cli/services/update-service.js +13 -6
- package/dist/cli/services/vpn-service.d.ts +28 -0
- package/dist/cli/services/vpn-service.js +46 -0
- package/dist/cli/services/web-service.d.ts +22 -0
- package/dist/cli/services/web-service.js +111 -0
- package/dist/cli/tui/app.d.ts +6 -3
- package/dist/cli/tui/app.js +12 -5
- package/dist/cli/tui/dialogs/path-listing.d.ts +43 -0
- package/dist/cli/tui/dialogs/path-listing.js +127 -0
- package/dist/cli/tui/dialogs/path-picker.d.ts +67 -0
- package/dist/cli/tui/dialogs/path-picker.js +423 -0
- package/dist/cli/tui/dialogs/text-screen.d.ts +6 -0
- package/dist/cli/tui/dialogs/text-screen.js +10 -3
- package/dist/cli/tui/frame.d.ts +7 -10
- package/dist/cli/tui/frame.js +19 -10
- package/dist/cli/tui/index.d.ts +4 -3
- package/dist/cli/tui/index.js +2 -1
- package/dist/cli/tui/list/list-screen.d.ts +14 -2
- package/dist/cli/tui/list/list-screen.js +68 -32
- package/dist/cli/tui/list/list-types.d.ts +8 -4
- package/dist/cli/tui/nav.d.ts +29 -0
- package/dist/cli/tui/nav.js +67 -0
- package/dist/cli/validate.d.ts +1 -1
- package/dist/cli/validate.js +3 -3
- package/dist/cli/version.d.ts +2 -0
- package/dist/cli/version.js +11 -0
- package/dist/core/config/defaults.js +5 -1
- package/dist/core/config/loader.js +12 -2
- package/dist/core/local-config/overrides.js +1 -0
- package/dist/core/prompt.d.ts +19 -0
- package/dist/core/prompt.js +43 -3
- package/dist/core/schema/common.d.ts +6 -0
- package/dist/core/schema/common.js +8 -0
- package/dist/core/schema/config.d.ts +23 -0
- package/dist/core/schema/config.js +10 -1
- package/dist/core/schema/harness.d.ts +1 -0
- package/dist/core/schema/harness.js +8 -2
- package/dist/core/schema/index.d.ts +3 -1
- package/dist/core/schema/index.js +3 -1
- package/dist/core/schema/profile.d.ts +1 -0
- package/dist/core/schema/profile.js +3 -0
- package/dist/core/schema/redact.d.ts +13 -0
- package/dist/core/schema/redact.js +75 -0
- package/dist/core/schema/sandbox.js +1 -0
- package/dist/core/schema/vpn.d.ts +17 -0
- package/dist/core/schema/vpn.js +22 -0
- package/dist/core/schema/web.d.ts +6 -0
- package/dist/core/schema/web.js +14 -0
- package/dist/core/types.d.ts +26 -0
- package/dist/guest/agents/agent-files.d.ts +49 -0
- package/dist/guest/agents/agent-files.js +63 -0
- package/dist/guest/agents/agent-installer.js +2 -9
- package/dist/guest/agents/local-state.d.ts +12 -0
- package/dist/guest/agents/local-state.js +198 -0
- package/dist/guest/agents/sbx-agent.d.ts +2 -0
- package/dist/guest/agents/sbx-agent.js +35 -0
- package/dist/guest/boot/boot.d.ts +4 -0
- package/dist/guest/boot/boot.js +50 -11
- package/dist/guest/daemon/daemon.js +4 -1
- package/dist/guest/daemon/exec.js +2 -1
- package/dist/guest/daemon/idle-shutdown.js +2 -0
- package/dist/guest/daemon/sessions.js +4 -1
- package/dist/guest/entries/agent.d.ts +1 -0
- package/dist/guest/entries/agent.js +10 -0
- package/dist/guest/entries/daemon.js +2 -0
- package/dist/guest/runtime/csc.d.ts +1 -0
- package/dist/guest/runtime/csc.js +1 -0
- package/dist/guest/runtime/secrets.d.ts +12 -0
- package/dist/guest/runtime/secrets.js +63 -0
- package/dist/guest/setup/claude-profile.d.ts +2 -1
- package/dist/guest/setup/claude-profile.js +12 -1
- package/dist/guest/setup/environment.d.ts +6 -0
- package/dist/guest/setup/environment.js +56 -6
- package/dist/guest/setup/path-plan.d.ts +32 -0
- package/dist/guest/setup/path-plan.js +67 -0
- package/dist/guest/setup/shell-path.d.ts +1 -0
- package/dist/guest/setup/shell-path.js +22 -0
- package/dist/guest/toolchains/languages/python.js +1 -1
- package/dist/guest/toolchains/runtimes.js +2 -2
- package/dist/guest/vpn/index.d.ts +1 -0
- package/dist/guest/vpn/index.js +1 -0
- package/dist/guest/vpn/openvpn.d.ts +9 -0
- package/dist/guest/vpn/openvpn.js +47 -0
- package/dist/guest/vpn/tunnel.d.ts +17 -0
- package/dist/guest/vpn/tunnel.js +78 -0
- package/dist/guest/vpn/vpn.d.ts +6 -0
- package/dist/guest/vpn/vpn.js +126 -0
- package/dist/host/channel/attach.d.ts +3 -1
- package/dist/host/channel/attach.js +1 -1
- package/dist/host/channel/channel.d.ts +7 -0
- package/dist/host/channel/channel.js +26 -2
- package/dist/host/health/acl-read.d.ts +17 -0
- package/dist/host/health/acl-read.js +45 -0
- package/dist/host/health/config-backup.d.ts +11 -0
- package/dist/host/health/config-backup.js +73 -0
- package/dist/host/health/index.d.ts +6 -0
- package/dist/host/health/index.js +7 -0
- package/dist/host/health/install-state.d.ts +33 -0
- package/dist/host/health/install-state.js +110 -0
- package/dist/host/health/path-copies.d.ts +32 -0
- package/dist/host/health/path-copies.js +82 -0
- package/dist/host/health/stale.d.ts +45 -0
- package/dist/host/health/stale.js +120 -0
- package/dist/host/health/system.d.ts +37 -0
- package/dist/host/health/system.js +87 -0
- package/dist/host/install/copies.d.ts +13 -0
- package/dist/host/install/copies.js +63 -0
- package/dist/host/install/index.d.ts +1 -0
- package/dist/host/install/index.js +1 -0
- package/dist/host/launch/generate.js +25 -1
- package/dist/host/launch/session-file.js +4 -1
- package/dist/host/launch/stage.js +1 -1
- package/dist/host/migrate/backup.js +3 -0
- package/dist/host/migrate/migrations/config-file.d.ts +2 -0
- package/dist/host/migrate/migrations/config-file.js +7 -0
- package/dist/host/migrate/migrations/follow-machine-storage.js +9 -1
- package/dist/host/migrate/migrations/pin-storage-root.d.ts +4 -0
- package/dist/host/migrate/migrations/pin-storage-root.js +46 -0
- package/dist/host/migrate/migrations/unpin-config-defaults.js +4 -1
- package/dist/host/migrate/registry.js +2 -1
- package/dist/host/profile/accounts.d.ts +25 -1
- package/dist/host/profile/accounts.js +96 -13
- package/dist/host/profile/agent-accounts.d.ts +5 -1
- package/dist/host/profile/agent-accounts.js +35 -5
- package/dist/host/profile/index.d.ts +2 -1
- package/dist/host/profile/index.js +1 -0
- package/dist/host/profile/plugin-share.d.ts +26 -0
- package/dist/host/profile/plugin-share.js +146 -0
- package/dist/host/projects/join.d.ts +7 -1
- package/dist/host/projects/join.js +21 -4
- package/dist/host/projects/registry.d.ts +16 -10
- package/dist/host/projects/registry.js +74 -6
- package/dist/host/sandbox/platform.d.ts +2 -0
- package/dist/host/sandbox/platform.js +21 -2
- package/dist/host/secrets/index.d.ts +2 -0
- package/dist/host/secrets/index.js +2 -0
- package/dist/host/secrets/launch-secrets.d.ts +17 -0
- package/dist/host/secrets/launch-secrets.js +93 -0
- package/dist/host/secrets/secret-store.d.ts +25 -0
- package/dist/host/secrets/secret-store.js +89 -0
- package/dist/host/sharing/acl.d.ts +16 -2
- package/dist/host/sharing/acl.js +35 -10
- package/dist/host/sharing/current.js +11 -2
- package/dist/host/sharing/doctor.d.ts +2 -0
- package/dist/host/sharing/doctor.js +44 -0
- package/dist/host/sharing/group-access.d.ts +6 -0
- package/dist/host/sharing/group-access.js +24 -0
- package/dist/host/sharing/index.d.ts +2 -1
- package/dist/host/sharing/index.js +2 -1
- package/dist/host/sharing/lifecycle.d.ts +8 -2
- package/dist/host/sharing/lifecycle.js +16 -7
- package/dist/host/storage/cleanup.d.ts +2 -0
- package/dist/host/storage/cleanup.js +2 -1
- package/dist/host/storage/history.d.ts +21 -0
- package/dist/host/storage/history.js +49 -0
- package/dist/host/storage/index.d.ts +4 -0
- package/dist/host/storage/index.js +4 -0
- package/dist/host/storage/move.d.ts +95 -0
- package/dist/host/storage/move.js +384 -0
- package/dist/host/storage/offer.d.ts +11 -0
- package/dist/host/storage/offer.js +36 -0
- package/dist/host/storage/root.d.ts +18 -0
- package/dist/host/storage/root.js +77 -0
- package/dist/host/tools/windows-terminal.d.ts +2 -0
- package/dist/host/tools/windows-terminal.js +23 -5
- package/dist/host/update/index.d.ts +1 -1
- package/dist/host/update/index.js +1 -1
- package/dist/host/update/notice.d.ts +2 -0
- package/dist/host/update/notice.js +13 -1
- package/dist/host/update/update-state.d.ts +6 -0
- package/dist/host/update/update-state.js +2 -0
- package/dist/host/update/updater.d.ts +19 -0
- package/dist/host/update/updater.js +88 -12
- package/dist/host/vpn/index.d.ts +4 -0
- package/dist/host/vpn/index.js +4 -0
- package/dist/host/vpn/login.d.ts +24 -0
- package/dist/host/vpn/login.js +79 -0
- package/dist/host/vpn/nordvpn.d.ts +21 -0
- package/dist/host/vpn/nordvpn.js +77 -0
- package/dist/host/vpn/prepare.d.ts +17 -0
- package/dist/host/vpn/prepare.js +77 -0
- package/dist/host/vpn/status.d.ts +12 -0
- package/dist/host/vpn/status.js +53 -0
- package/dist/host/web/auth.d.ts +38 -0
- package/dist/host/web/auth.js +96 -0
- package/dist/host/web/backend.d.ts +14 -0
- package/dist/host/web/backend.js +1 -0
- package/dist/host/web/bridge.d.ts +27 -0
- package/dist/host/web/bridge.js +144 -0
- package/dist/host/web/browser.d.ts +1 -0
- package/dist/host/web/browser.js +10 -0
- package/dist/host/web/control.d.ts +17 -0
- package/dist/host/web/control.js +67 -0
- package/dist/host/web/index.d.ts +9 -0
- package/dist/host/web/index.js +8 -0
- package/dist/host/web/runner.d.ts +14 -0
- package/dist/host/web/runner.js +45 -0
- package/dist/host/web/server.d.ts +40 -0
- package/dist/host/web/server.js +218 -0
- package/dist/host/web/state.d.ts +20 -0
- package/dist/host/web/state.js +41 -0
- package/dist/host/web/static-files.d.ts +13 -0
- package/dist/host/web/static-files.js +57 -0
- package/dist/runtime/agent.js +27614 -0
- package/dist/runtime/daemon.js +1012 -618
- package/dist/runtime/db.js +236 -106
- package/dist/runtime/main.js +1093 -250
- package/dist/runtime/netproxy.js +102 -3
- package/dist/runtime/view.js +102 -3
- package/dist/selftest/accounts.test.js +40 -0
- package/dist/selftest/agent-paths.test.d.ts +2 -0
- package/dist/selftest/agent-paths.test.js +115 -0
- package/dist/selftest/channel.test.js +5 -0
- package/dist/selftest/cli.test.js +34 -4
- package/dist/selftest/credentials.test.d.ts +2 -0
- package/dist/selftest/credentials.test.js +198 -0
- package/dist/selftest/generate.test.js +1 -1
- package/dist/selftest/health.test.d.ts +2 -0
- package/dist/selftest/health.test.js +470 -0
- package/dist/selftest/host-sim.test.js +2 -0
- package/dist/selftest/index.js +19 -0
- package/dist/selftest/layout.test.js +2 -0
- package/dist/selftest/menu-screens.d.ts +7 -0
- package/dist/selftest/menu-screens.js +65 -16
- package/dist/selftest/menu.test.js +574 -21
- package/dist/selftest/migrate.test.js +1 -1
- package/dist/selftest/personalization.test.js +3 -1
- package/dist/selftest/projects.test.js +39 -1
- package/dist/selftest/shared-use.test.js +64 -2
- package/dist/selftest/sharing.test.js +50 -1
- package/dist/selftest/storage.test.d.ts +2 -0
- package/dist/selftest/storage.test.js +363 -0
- package/dist/selftest/support/fixtures.d.ts +14 -0
- package/dist/selftest/support/releases.js +1 -1
- package/dist/selftest/toolchains.test.js +21 -0
- package/dist/selftest/update-service.test.js +87 -3
- package/dist/selftest/vpn.test.d.ts +2 -0
- package/dist/selftest/vpn.test.js +279 -0
- package/dist/selftest/web.test.d.ts +2 -0
- package/dist/selftest/web.test.js +304 -0
- package/dist/shared/apps/catalogue.js +31 -0
- package/dist/shared/channel/index.d.ts +1 -0
- package/dist/shared/channel/index.js +1 -0
- package/dist/shared/channel/run-dir.d.ts +6 -1
- package/dist/shared/channel/run-dir.js +12 -1
- package/dist/shared/channel/schema.d.ts +19 -0
- package/dist/shared/channel/schema.js +11 -0
- package/dist/shared/channel/secrets.d.ts +28 -0
- package/dist/shared/channel/secrets.js +44 -0
- package/dist/shared/vpn/download.d.ts +13 -0
- package/dist/shared/vpn/download.js +14 -0
- package/dist/shared/vpn/kill-switch.d.ts +18 -0
- package/dist/shared/vpn/kill-switch.js +81 -0
- package/dist/shared/vpn/ovpn.d.ts +23 -0
- package/dist/shared/vpn/ovpn.js +244 -0
- package/dist/shared/web/index.d.ts +1 -0
- package/dist/shared/web/index.js +1 -0
- package/dist/shared/web/protocol.d.ts +61 -0
- package/dist/shared/web/protocol.js +35 -0
- package/dist/sync/sync-cycle.js +5 -1
- package/dist/sync/sync-state.d.ts +1 -0
- package/dist/sync/sync-state.js +1 -0
- package/dist/sync/watcher.js +10 -0
- package/dist/web/index.html +13 -0
- package/dist/web/main-CXESL347.js +45 -0
- package/dist/web/main-VLR7DVQ4.css +1 -0
- package/native/csharp/FolderSecurity.cs +29 -0
- package/native/scripts/protect-data.ps1 +29 -0
- package/native/scripts/read-folder-sddl.ps1 +10 -0
- package/native/scripts/set-folder-access.ps1 +49 -7
- package/node_modules/ws/LICENSE +20 -0
- package/node_modules/ws/README.md +548 -0
- package/node_modules/ws/browser.js +8 -0
- package/node_modules/ws/index.js +22 -0
- package/node_modules/ws/lib/buffer-util.js +131 -0
- package/node_modules/ws/lib/constants.js +19 -0
- package/node_modules/ws/lib/event-target.js +292 -0
- package/node_modules/ws/lib/extension.js +203 -0
- package/node_modules/ws/lib/limiter.js +55 -0
- package/node_modules/ws/lib/permessage-deflate.js +530 -0
- package/node_modules/ws/lib/receiver.js +743 -0
- package/node_modules/ws/lib/sender.js +607 -0
- package/node_modules/ws/lib/stream.js +161 -0
- package/node_modules/ws/lib/subprotocol.js +62 -0
- package/node_modules/ws/lib/validation.js +152 -0
- package/node_modules/ws/lib/websocket-server.js +562 -0
- package/node_modules/ws/lib/websocket.js +1421 -0
- package/node_modules/ws/package.json +74 -0
- package/node_modules/ws/wrapper.mjs +21 -0
- package/package.json +15 -5
- package/sandbox/csharp/EnvBroadcast.cs +33 -0
- package/sandbox/csharp/PathSync.cs +90 -0
- package/sandbox/scripts/install-shell-path.ps1 +73 -0
- package/sandbox/scripts/set-machine-environment.ps1 +37 -4
- package/schemas/config.schema.json +79 -4
- package/schemas/sandbox-config.schema.json +14 -1
- package/dist/cli/commands/repair/checks.d.ts +0 -2
- package/dist/cli/commands/repair/checks.js +0 -246
- package/dist/cli/menu/pages/start-page.d.ts +0 -43
- package/dist/cli/menu/pages/start-page.js +0 -192
- package/dist/cli/tui/tab-bar.d.ts +0 -9
- package/dist/cli/tui/tab-bar.js +0 -33
|
@@ -2,16 +2,18 @@
|
|
|
2
2
|
// (cli/manifest.ts) drives both the flags and the menu.
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
-
import { buildProgram, parseCli } from '../cli/args.js';
|
|
5
|
+
import { buildProgram, friendlyError, parseCli } from '../cli/args.js';
|
|
6
|
+
import { askRequired } from '../core/prompt.js';
|
|
6
7
|
import { COMMANDS } from '../cli/manifest.js';
|
|
7
8
|
import { commandLine, readHistory, recordHistory } from '../cli/history.js';
|
|
8
9
|
import { splitArgs } from '../cli/args.js';
|
|
9
10
|
import { optionProblem } from '../cli/menu/index.js';
|
|
10
11
|
import { cleanTargetOf } from '../cli/commands/data/collect.js';
|
|
11
12
|
import { ago, colorEnabled, shorten } from '../cli/output/index.js';
|
|
13
|
+
import { versionText } from '../cli/version.js';
|
|
12
14
|
import { hoistConfig, withoutConfig } from '../cli/argv.js';
|
|
13
15
|
import { closest, validNodeSpec, validPythonSpec } from '../cli/validate.js';
|
|
14
|
-
import { CATEGORIES, editConfigText, SchemaNode } from '../cli/menu/settings/index.js';
|
|
16
|
+
import { CATEGORIES, editConfigText, SchemaNode, SETTINGS_ELSEWHERE } from '../cli/menu/settings/index.js';
|
|
15
17
|
import { Frame, ListScreen, Text, TextScreen } from '../cli/tui/index.js';
|
|
16
18
|
import { ConfigSchema, LocalOverridesSchema } from '../core/schema/index.js';
|
|
17
19
|
export const cliSuite = {
|
|
@@ -25,6 +27,12 @@ export const cliSuite = {
|
|
|
25
27
|
const packageJson = JSON.parse(fs.readFileSync(path.join(t.packageRoot, 'package.json'), 'utf8'));
|
|
26
28
|
t.check(program.version() === packageJson.version &&
|
|
27
29
|
program.commands.find((c) => c.name() === 'launch').options.some((o) => o.long === '--terminal'), '--version is the package version and manifest options exist in the parser');
|
|
30
|
+
t.check(versionText(['--version'], t.packageRoot)?.startsWith(packageJson.version + ' (') === true &&
|
|
31
|
+
versionText(['-v'], t.packageRoot)?.includes(t.packageRoot) === true &&
|
|
32
|
+
versionText(['--version', '--short'], t.packageRoot) === packageJson.version &&
|
|
33
|
+
versionText(['status'], t.packageRoot) === null &&
|
|
34
|
+
versionText(['--short'], t.packageRoot) === null &&
|
|
35
|
+
versionText(['--version', 'x'], t.packageRoot) === null, '--version says where it runs from; --version --short is the plain number the updater compares');
|
|
28
36
|
const start = parseCli(['start', '--headless']);
|
|
29
37
|
const clean = parseCli(['data', 'clean', 'tools/go', 'logs', '--yes']);
|
|
30
38
|
t.equal([
|
|
@@ -113,8 +121,8 @@ export const cliSuite = {
|
|
|
113
121
|
const userLeaves = userSchema.leaves();
|
|
114
122
|
const uncategorised = [...userSchema.children(), ...projectSchema.children()]
|
|
115
123
|
.map(([name]) => name)
|
|
116
|
-
.filter((name) => !CATEGORIES.some((c) => c.keys.includes(name)));
|
|
117
|
-
t.equal(uncategorised, [], 'settings screen: every top-level setting belongs to a category');
|
|
124
|
+
.filter((name) => !CATEGORIES.some((c) => c.keys.includes(name)) && !SETTINGS_ELSEWHERE.includes(name));
|
|
125
|
+
t.equal(uncategorised, [], 'settings screen: every top-level setting belongs to a category (or to the Apps section)');
|
|
118
126
|
t.equal(userLeaves.filter((l) => l.node.editor === 'json').map((l) => l.key.join('.')), [], 'settings screen: no setting falls back to typing JSON');
|
|
119
127
|
const harness = userSchema.child('harnesses').element;
|
|
120
128
|
t.check(String(harness.check(harness.initial())).includes('npmPackage') &&
|
|
@@ -155,5 +163,27 @@ export const cliSuite = {
|
|
|
155
163
|
typed.handle(key('backspace'));
|
|
156
164
|
typed.handle(key('8', '8'));
|
|
157
165
|
t.equal([refused, typed.handle(key('return'))], [undefined, { done: '8' }], 'text field: an invalid value is not accepted, a valid one is');
|
|
166
|
+
t.section('command line: grouped help, did you mean, choices, --agent, required questions');
|
|
167
|
+
const rootHelp = buildProgram(() => undefined).helpInformation();
|
|
168
|
+
const headings = ['Agents:', 'Sessions:', 'Projects & accounts:', 'Data:', 'Web:', 'Health:', 'Advanced:'];
|
|
169
|
+
const at = headings.map((h) => rootHelp.indexOf('\n' + h + '\n'));
|
|
170
|
+
t.check(at.every((i, n) => i >= 0 && (n === 0 || i > at[n - 1])), 'root help: the command groups come in the order Agents, Sessions, Projects & accounts, Data, Web, Health, Advanced');
|
|
171
|
+
t.check(!/^\s+(self-test|host-claude)\b/m.test(rootHelp) &&
|
|
172
|
+
!buildProgram(() => undefined)
|
|
173
|
+
.commands.find((c) => c.name() === 'status')
|
|
174
|
+
.helpInformation()
|
|
175
|
+
.includes('--config'), 'self-test and host-claude are hidden, and --config is not in a command help');
|
|
176
|
+
t.check(friendlyError("error: unknown command 'statu'\n(Did you mean status?)\n").includes('Did you mean: sandbox status?') && closest('cluade', ['claude', 'codex', 'status']) === 'claude', 'an unknown command says "Did you mean: sandbox status?"; a mistyped agent finds the closest');
|
|
177
|
+
await t.throws(() => parseCli(['data', 'bogus']), 'Allowed choices are show, clean', 'a typo in an action lists the valid ones');
|
|
178
|
+
t.check(parseCli(['data', 'info']).positionals[0] === 'info', 'an old spelling that is not listed is still accepted');
|
|
179
|
+
t.equal([
|
|
180
|
+
parseCli(['launch', '--agent', 'codex']).harness,
|
|
181
|
+
parseCli(['launch', '--harness', 'codex']).harness,
|
|
182
|
+
parseCli(['restart', '--agent', 'claude']).harness,
|
|
183
|
+
parseCli(['account', 'list', '--agent', 'codex']).accountAgent,
|
|
184
|
+
parseCli(['--agent', 'reviewer', '-p', 'hi'], true).passthrough,
|
|
185
|
+
], ['codex', 'codex', 'claude', 'codex', ['--agent', 'reviewer', '-p', 'hi']], '--agent names the agent (--harness still works); sandbox claude leaves --agent to Claude');
|
|
186
|
+
if (!process.stdin.isTTY)
|
|
187
|
+
await t.throws(() => askRequired('Delete it?'), 'Add --yes to answer yes.', 'a required question with no terminal fails and names --yes');
|
|
158
188
|
},
|
|
159
189
|
};
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
// Credentials: what is encrypted at rest, what never lands in session.json or the launch folder, what the one-shot
|
|
2
|
+
// secrets file carries, and that printed settings show *** for secrets.
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { DEFAULTS } from '../core/config/index.js';
|
|
6
|
+
import { ConfigSchema, HarnessSchema, redactSecrets, scrubSecrets, secretPaths } from '../core/schema/index.js';
|
|
7
|
+
import { SchemaNode } from '../cli/menu/settings/index.js';
|
|
8
|
+
import { SandboxChannel } from '../host/channel/index.js';
|
|
9
|
+
import { AccountStore, AgentAccountStore } from '../host/profile/index.js';
|
|
10
|
+
import { clearSecrets, SecretStore, withoutSecrets } from '../host/secrets/index.js';
|
|
11
|
+
import { sharingAclPlan } from '../host/sharing/index.js';
|
|
12
|
+
import { RunDir } from '../shared/channel/index.js';
|
|
13
|
+
import { mergeRequestSecrets } from '../shared/channel/secrets.js';
|
|
14
|
+
const API_KEY = 'sk-planted-ENV-7f3a9c1d';
|
|
15
|
+
const LOGIN = 'login-planted-4b2e';
|
|
16
|
+
/** Every file under `dir` that contains `needle` (text or not), so a planted secret cannot hide in a corner. */
|
|
17
|
+
function filesContaining(dir, needle) {
|
|
18
|
+
const found = [];
|
|
19
|
+
const walk = (d) => {
|
|
20
|
+
for (const entry of fs.readdirSync(d, { withFileTypes: true })) {
|
|
21
|
+
const file = path.join(d, entry.name);
|
|
22
|
+
if (entry.isDirectory())
|
|
23
|
+
walk(file);
|
|
24
|
+
else if (entry.isFile() && fs.statSync(file).size < 20 * 1024 * 1024 && fs.readFileSync(file).includes(needle))
|
|
25
|
+
found.push(path.relative(dir, file));
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
walk(dir);
|
|
29
|
+
return found;
|
|
30
|
+
}
|
|
31
|
+
export const credentialsSuite = {
|
|
32
|
+
name: 'credentials',
|
|
33
|
+
title: 'secrets: encrypted at rest, kept out of session.json and the launch folder, hidden when printed',
|
|
34
|
+
timeoutMs: 240000,
|
|
35
|
+
run: async (t, f) => {
|
|
36
|
+
t.section('the secret store');
|
|
37
|
+
const memory = SecretStore.memory();
|
|
38
|
+
const sealed = memory.sealJson({ a: 1, key: API_KEY });
|
|
39
|
+
t.check(SecretStore.isSealed(sealed) && !sealed.includes(API_KEY) && !sealed.includes('"a"'), 'a sealed value is one short opaque string');
|
|
40
|
+
t.equal(memory.openJson(sealed), { a: 1, key: API_KEY }, 'it opens again');
|
|
41
|
+
await t.throws(() => SecretStore.dpapi().open(sealed), 'another system', 'a value sealed by another kind of store is refused, never guessed at');
|
|
42
|
+
if (process.platform === 'win32') {
|
|
43
|
+
const dpapi = SecretStore.dpapi();
|
|
44
|
+
const real = dpapi.seal(API_KEY);
|
|
45
|
+
t.check(real.startsWith('dpapi1:') && !real.includes(API_KEY) && dpapi.open(real) === API_KEY, 'Windows DPAPI (through powershell.exe, nothing on a command line) seals and opens a value');
|
|
46
|
+
await t.throws(() => dpapi.open('dpapi1:AAAA'), 'could not decrypt', 'a value Windows cannot open fails with a message that says what to do');
|
|
47
|
+
}
|
|
48
|
+
else
|
|
49
|
+
t.skip('DPAPI needs Windows');
|
|
50
|
+
t.section('saved Claude logins are encrypted at rest');
|
|
51
|
+
const storage = t.at('cred-storage');
|
|
52
|
+
const dataA = path.join(storage, 'data', 'x');
|
|
53
|
+
const claudeDir = path.join(dataA, 'state', 'claude');
|
|
54
|
+
t.write(path.join(claudeDir, '.credentials.json'), '{"claudeAiOauth":{"refreshToken":"' + LOGIN + '-1"}}');
|
|
55
|
+
t.write(path.join(claudeDir, '.claude.json'), '{"oauthAccount":{"emailAddress":"me@example.com"}}');
|
|
56
|
+
const accounts = new AccountStore(storage);
|
|
57
|
+
accounts.save(dataA, 'personal', null);
|
|
58
|
+
const saved = fs.readFileSync(path.join(storage, 'accounts', 'personal.json'), 'utf8');
|
|
59
|
+
t.check(!saved.includes(LOGIN) && saved.includes('me@example.com') && saved.includes('"sealed"'), 'the file shows the name, date and e-mail only; the tokens are sealed');
|
|
60
|
+
t.check(accounts.list(dataA)[0]?.email === 'me@example.com' && accounts.meta('personal')?.name === 'personal', 'listing needs no decryption');
|
|
61
|
+
t.includes(JSON.stringify(accounts.read('personal')?.credentials), LOGIN + '-1', 'reading an account opens it (when switching)');
|
|
62
|
+
t.write(path.join(storage, 'accounts', 'old.json'), JSON.stringify({
|
|
63
|
+
name: 'old',
|
|
64
|
+
savedAt: '2026-01-01T00:00:00.000Z',
|
|
65
|
+
email: null,
|
|
66
|
+
credentials: { claudeAiOauth: { refreshToken: LOGIN + '-legacy' } },
|
|
67
|
+
oauthAccount: {},
|
|
68
|
+
}));
|
|
69
|
+
const migrated = new AccountStore(storage).list(dataA);
|
|
70
|
+
t.check(migrated.some((a) => a.name === 'old') &&
|
|
71
|
+
!fs.readFileSync(path.join(storage, 'accounts', 'old.json'), 'utf8').includes(LOGIN), 'an account saved plain by an older version is encrypted the first time accounts are listed, and the plain text is gone');
|
|
72
|
+
t.includes(JSON.stringify(new AccountStore(storage).read('old')?.credentials), LOGIN + '-legacy', 'and it still opens');
|
|
73
|
+
new AccountStore(storage).activate(dataA, 'old');
|
|
74
|
+
t.includes(fs.readFileSync(path.join(claudeDir, '.credentials.json'), 'utf8'), LOGIN + '-legacy', 'switching decrypts it into the sandbox state');
|
|
75
|
+
t.section('other agents: login files are encrypted at rest');
|
|
76
|
+
const codexHome = t.at('cred-codex-home');
|
|
77
|
+
t.write(path.join(codexHome, 'auth.json'), '{"token":"' + LOGIN + '-codex"}');
|
|
78
|
+
const agent = new AgentAccountStore(storage, 'codex', ['auth.json']);
|
|
79
|
+
agent.save(dataA, 'main', codexHome, true);
|
|
80
|
+
const folder = path.join(storage, 'accounts', 'codex', 'main');
|
|
81
|
+
t.check(fs.existsSync(path.join(folder, 'auth.json.sealed')) &&
|
|
82
|
+
!fs.existsSync(path.join(folder, 'auth.json')) &&
|
|
83
|
+
filesContaining(folder, LOGIN).length === 0, 'the login file is stored sealed, never as it was');
|
|
84
|
+
const restored = t.at('cred-codex-to');
|
|
85
|
+
agent.activate(dataA, 'main', restored);
|
|
86
|
+
t.equal(fs.readFileSync(path.join(restored, 'auth.json'), 'utf8'), '{"token":"' + LOGIN + '-codex"}', 'switching puts the original file back');
|
|
87
|
+
t.write(path.join(storage, 'accounts', 'codex', 'older', 'auth.json'), '{"token":"' + LOGIN + '-older"}');
|
|
88
|
+
t.write(path.join(storage, 'accounts', 'codex', 'older', 'meta.json'), JSON.stringify({ name: 'older', savedAt: '2026-01-01T00:00:00.000Z' }));
|
|
89
|
+
agent.list(dataA);
|
|
90
|
+
t.check(filesContaining(path.join(storage, 'accounts', 'codex', 'older'), LOGIN).length === 0 &&
|
|
91
|
+
fs.existsSync(path.join(storage, 'accounts', 'codex', 'older', 'auth.json.sealed')), 'a copy saved plain by an older version is encrypted when the accounts are listed');
|
|
92
|
+
t.section('the agent environment and the Claude login stay out of the launch folder');
|
|
93
|
+
t.write(path.join(f.hostProfile, '.credentials.json'), '{"token":"' + LOGIN + '-host"}');
|
|
94
|
+
const config = f.makeConfig();
|
|
95
|
+
config.harnesses.claude.environment = { ANTHROPIC_API_KEY: API_KEY, DISABLE_AUTOUPDATER: '1' };
|
|
96
|
+
config.claudeProfile.copyCredentials = true;
|
|
97
|
+
const run = await f.run({}, config);
|
|
98
|
+
const gen = f.generate(run);
|
|
99
|
+
const session = fs.readFileSync(gen.sessionPath, 'utf8');
|
|
100
|
+
t.check(!session.includes(API_KEY) && !session.includes(LOGIN), 'session.json holds neither the API key nor the Claude login');
|
|
101
|
+
t.equal(filesContaining(gen.launchPath, API_KEY).concat(filesContaining(gen.launchPath, LOGIN + '-host')), [], 'nothing in the launch folder holds them either (it is mapped into the sandbox and kept for days)');
|
|
102
|
+
t.equal(f.readJson(gen.sessionPath).harness.environment, {}, "the booted agent's environment in session.json is empty");
|
|
103
|
+
const dir = new RunDir(run.dataPath);
|
|
104
|
+
const handed = f.readJson(dir.secretFile(gen.launchId));
|
|
105
|
+
t.check(handed.harnessEnvironment?.ANTHROPIC_API_KEY === API_KEY &&
|
|
106
|
+
handed.claudeCredentials?.includes(LOGIN + '-host') === true, 'both are in the one-shot file in <data>\\secrets for the sandbox to read and delete', JSON.stringify(handed));
|
|
107
|
+
t.check(path.relative(dir.root, dir.secretsDir).startsWith('..'), 'the one-shot folder is next to run, not in it: other users of a shared sandbox may change run');
|
|
108
|
+
const plan = sharingAclPlan({
|
|
109
|
+
storageUserDir: storage,
|
|
110
|
+
dataPath: path.join(storage, 'data', 'testdata'),
|
|
111
|
+
groupSid: 'S-1-5-32-545',
|
|
112
|
+
on: true,
|
|
113
|
+
});
|
|
114
|
+
t.check(plan.filter((c) => c.rights === 'Modify').every((c) => path.basename(c.path) === 'run') &&
|
|
115
|
+
!plan.some((c) => c.path.includes('secrets')), 'sharing opens only run for writing, never the secrets folder');
|
|
116
|
+
t.write(path.join(storage, 'launches', 'older', 'claude-profile', '.credentials.json'), '{"x":1}');
|
|
117
|
+
t.check(clearSecrets(storage, run.dataPath) >= 2 &&
|
|
118
|
+
!fs.existsSync(dir.secretFile(gen.launchId)) &&
|
|
119
|
+
!fs.existsSync(path.join(storage, 'launches', 'older', 'claude-profile', '.credentials.json')), 'what the sandbox never read, and a login left in an old launch folder, is removed (at launch and when the sandbox stops)');
|
|
120
|
+
t.write(path.join(f.hostProfile, '.credentials.json'), '{ "token": "secret" }');
|
|
121
|
+
t.section('requests carry no environment values');
|
|
122
|
+
const request = {
|
|
123
|
+
kind: 'session',
|
|
124
|
+
id: 'req1',
|
|
125
|
+
harness: 'codex',
|
|
126
|
+
args: [],
|
|
127
|
+
cwd: 'C:\\Workspace\\x',
|
|
128
|
+
harnessSpec: { ...config.harnesses.claude, environment: { OPENAI_API_KEY: API_KEY } },
|
|
129
|
+
project: {
|
|
130
|
+
name: 'other',
|
|
131
|
+
workspace: 'C:\\Workspace\\other',
|
|
132
|
+
workspaceHost: 'C:\\other',
|
|
133
|
+
toolchains: DEFAULTS.toolchains,
|
|
134
|
+
versions: run.versions,
|
|
135
|
+
databases: [],
|
|
136
|
+
harnesses: { codex: { ...config.harnesses.claude, environment: { OTHER_KEY: API_KEY + '-2' } } },
|
|
137
|
+
hooks: false,
|
|
138
|
+
},
|
|
139
|
+
createdAt: new Date().toISOString(),
|
|
140
|
+
};
|
|
141
|
+
const stripped = withoutSecrets(request);
|
|
142
|
+
t.check(!JSON.stringify(stripped.request).includes(API_KEY) &&
|
|
143
|
+
stripped.secrets?.harnessSpecEnvironment?.OPENAI_API_KEY === API_KEY &&
|
|
144
|
+
stripped.secrets?.projectHarnessEnvironment?.codex?.OTHER_KEY === API_KEY + '-2', 'withoutSecrets takes the values out of the agent and the project agents');
|
|
145
|
+
t.equal(mergeRequestSecrets(stripped.request, stripped.secrets ?? {}), request, 'the sandbox puts them back, exactly, in memory');
|
|
146
|
+
t.equal(withoutSecrets({ kind: 'ping', id: 'p', createdAt: 'now' }).secrets, null, 'other requests are untouched');
|
|
147
|
+
const sent = new SandboxChannel(run.dataPath, () => true);
|
|
148
|
+
sent.requestSession('codex', [], 'C:\\Workspace\\x', { harnessSpec: request.harnessSpec });
|
|
149
|
+
const requestFiles = fs.readdirSync(dir.requestsDir);
|
|
150
|
+
t.check(requestFiles.length === 1 &&
|
|
151
|
+
filesContaining(dir.root, API_KEY).length === 0 &&
|
|
152
|
+
filesContaining(dir.secretsDir, API_KEY).length === 1, 'the host channel writes the request without the value (nothing in run holds it) and the value into its own one-shot file');
|
|
153
|
+
clearSecrets(storage, run.dataPath);
|
|
154
|
+
t.section('network.proxy takes no login');
|
|
155
|
+
const withProxy = (proxy) => ConfigSchema.safeParse({ ...DEFAULTS, network: { ...DEFAULTS.network, proxy } });
|
|
156
|
+
t.check(withProxy('http://proxy.corp:8080').success && withProxy('').success, 'a proxy address without a login is accepted');
|
|
157
|
+
const refused = withProxy('http://user:pass@proxy.corp:8080');
|
|
158
|
+
t.check(!refused.success && JSON.stringify(refused.error?.issues).includes('no user name or password'), 'a user name and password in the address is refused, with a plain reason');
|
|
159
|
+
t.check(!withProxy('https://token@proxy.corp').success, 'a lone token in front of @ is refused too');
|
|
160
|
+
t.section('secrets print as ***');
|
|
161
|
+
t.check(secretPaths().some((p) => p.join('.') === 'harnesses.*.environment.*'), 'agent environment values are marked secret in the schema');
|
|
162
|
+
t.check(new SchemaNode(HarnessSchema).child('environment')?.element?.secret === true, 'the settings screen knows them as secret too (hidden input, *** in lists)');
|
|
163
|
+
const planted = structuredClone(config);
|
|
164
|
+
const shown = redactSecrets(planted);
|
|
165
|
+
t.check(shown.harnesses.claude.environment.ANTHROPIC_API_KEY === '***' &&
|
|
166
|
+
shown.harnesses.claude.environment.DISABLE_AUTOUPDATER === '***' &&
|
|
167
|
+
planted.harnesses.claude.environment.ANTHROPIC_API_KEY === API_KEY &&
|
|
168
|
+
shown.harnesses.codex.arguments.length === planted.harnesses.codex.arguments.length, 'redactSecrets hides every environment value and leaves the rest and the original alone');
|
|
169
|
+
t.excludes(scrubSecrets(JSON.stringify({ anything: 'x ' + API_KEY + ' y' }), planted), API_KEY, 'scrubSecrets removes a secret from any text built from a config');
|
|
170
|
+
const home = t.dir('cred-cli', 'home');
|
|
171
|
+
const cliConfig = t.writeJson(t.at('cred-cli', 'config.json'), {
|
|
172
|
+
storage: { root: t.dir('cred-cli', 'storage') },
|
|
173
|
+
personalization: { enabled: false },
|
|
174
|
+
provisioning: { terminal: { enabled: false } },
|
|
175
|
+
harnesses: {
|
|
176
|
+
planted: { npmPackage: 'planted', npmBin: 'planted', arguments: [], environment: { PLANTED_KEY: API_KEY } },
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
const baseEnv = Object.fromEntries(Object.entries(process.env).filter(([k]) => !['AGENT_SANDBOX_CONFIG', 'AGENT_WORKSPACE'].includes(k)));
|
|
180
|
+
const env = {
|
|
181
|
+
...baseEnv,
|
|
182
|
+
AGENT_SANDBOX_HOME: home,
|
|
183
|
+
AGENT_LAUNCH_DIR: t.at('cred-cli', 'no-launch'),
|
|
184
|
+
AGENT_DATA_DIR: t.at('cred-cli', 'no-data'),
|
|
185
|
+
NO_COLOR: '1',
|
|
186
|
+
AGENT_SANDBOX_HOST_ONLY: '1',
|
|
187
|
+
};
|
|
188
|
+
for (const args of [
|
|
189
|
+
['config', 'show'],
|
|
190
|
+
['doctor', '--json'],
|
|
191
|
+
['vpn', 'status', '--json'],
|
|
192
|
+
['status', '--json'],
|
|
193
|
+
]) {
|
|
194
|
+
const out = await f.runBin('agent-sandbox', [...args, '--config', cliConfig], { cwd: f.workA, env });
|
|
195
|
+
t.check(!out.out.includes(API_KEY) && (args[0] !== 'config' || out.out.includes('***')), 'sandbox ' + args.join(' ') + ' never prints the planted key' + (args[0] === 'config' ? ' (it shows ***)' : ''), out.out.slice(0, 400));
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
};
|
|
@@ -38,7 +38,7 @@ export const generateSuite = {
|
|
|
38
38
|
'sandbox/csharp/LinkGate.cs',
|
|
39
39
|
];
|
|
40
40
|
const missing = expectedFiles.filter((file) => !fs.existsSync(path.join(gen.launchPath, file)));
|
|
41
|
-
t.check(missing.length === 0 && fs.readdirSync(path.join(gen.launchPath, 'runtime')).length ===
|
|
41
|
+
t.check(missing.length === 0 && fs.readdirSync(path.join(gen.launchPath, 'runtime')).length === 7, 'the launch folder has the runtime (7 self-contained files), the C# sources and the boot scripts', missing.join(', '));
|
|
42
42
|
const logon = fs.readFileSync(path.join(gen.launchPath, 'sandbox', 'boot', 'logon.cmd'), 'utf8');
|
|
43
43
|
t.check(logon.indexOf('trust.cmd') < logon.indexOf('wt.exe') &&
|
|
44
44
|
logon.includes('tools\\terminal\\wt.exe') &&
|