Cloud workspaces v2: the box as a bundle, multi-repository environments, brokered credentials
Ten PRs into sandbox-v2, each reviewed by CI and boot tests, merged here as one review point. Records: plans/20260913-sandbox-layout-decisions.md (every decision and who made it), plans/20260913-sandbox-implementation-checklist.md (every item with its evidence), plans/20260914-multi-repo-environments.md.
What changes
- The box.
packages/sandbox: the image, a content-addressed bundle oncdn.superset.sh(runner, steps, assets by sha),superset-boot(root →ubuntu), boot stamps, a start hook the runner sequences and host-service runs. A box updates itself on the next boot when its environment's bundle sha changes; a release publishes, pins, and the box fetches exactly the changed steps. - Credentials. Every outbound credential is a firewall header rule the box never sees (Anthropic, OpenAI, GitHub installation token scoped to the workspace's repositories); the environment's variables are pushed live into host-service and inherited by terminals and host-service's own spawns.
- Environments. Repositories per environment (ordered, the first is what the workspace opens on), config location (
.superset/config.jsonof one of them), organization or personal scope. A lone repository is/workspace; several sit at/workspace/<name>. A promoted environment's repositories are fixed (promote again to change). Desktop dialog with Skip & save / Start agent (onboarding agent), repository and base-branch pills on the new-workspace form; mobile reads the same rows. - Gate. Per-port tickets for host-service and the desktop stream (
apps/gatewas already on main). - Schema. One migration,
0115_cloud_environments_repositories, additive with no backfills: the environment scope enum,environment_repositories(environment, repository) andcloud_workspace_repositories(workspace, repository, path) join tables with cascading foreign keys, andbundle_sha,hooks_repository_id,scope,created_by_user_idon environments. Review page: https://app.superset.sh/page/sandbox-v2-migrations-mhf14m
Flagging and blast radius (audited for this PR)
- Every
cloudWorkspace.*andenvironment.*procedure callsassertCloudAccess, which evaluates thecloud-workspacesPostHog flag server-side. CLI and MCP are unchanged by this branch and go through that gate. - Desktop: the sidebar Cloud section, the Cloud host in the device picker and
useCloudWorkspacescheck the same flag; the environment queries on the new-workspace form fire only once the Cloud host is selected. Mobile's cloud lists check the flag. - Code that runs for everyone and what it does without the flag: host-service's terminal env merges an empty managed set; the API samples exactly one Sentry transaction by name (
cloud-workspace.provision), everything else stays untraced; the pty socket path only changes whenSUPERSET_RUN_DIRis set (sandbox); boot stamps are a timestamp record; thestarthook key is parsed and otherwise ignored; the draft store gains a defaulted field. - With the flag on but the server refusing (email outside the flag's condition): the sidebar section renders empty, the environments page shows its error state, the new-workspace form toasts "add an environment". No path found that throws into a render.
- Two pre-existing gaps closed in this branch's last commit: the Settings Environments entry was gated on the v2-app variant rather than the cloud flag, and mobile's environments query was not flag-gated.
Deployment order
Merging deploys the API and runs the migrations. Cloud creates for flagged users then need the new image in the production registry and sandbox:release --production for the internal environment; until then a flagged create fails cleanly (the workspace shows failed). Existing production cloud workspaces from the previous layout are not guaranteed to wake on the new runner; recreate them. Nothing here affects users without the flag.
Owed after deploy
-
Confirm the
cloud-workspace.provisiontransaction arrives in Sentry on the first production create (the API's Sentry is production-only, and #7388 saw no spans from this app). -
Multi-repository workspaces opening at
/workspacewith a repository picker in the sidebar: a recorded TODO inplans/20260914-multi-repo-environments.md. -
A redesign of
.superset/config.jsonfor cloud (the flatstartandportskeys today): recorded TODO.
Verified (dev, real boxes)
Create, boot, checkout (one and several repositories), private repositories through the firewall with no token on the box, gh inside host-service, stop and wake, update-on-boot with a rollback, the environment dialog and form over CDP, the dev release of the internal golden (twice, on both layouts), the GitHub connect flow in dev. boot-twice and runner-check on every runner change.
https://claude.ai/code/session_01FK6rLzBEUiHHXZWNmpQ2BP
Summary by cubic
Cloud workspaces now boot from a self-updating v2 box and content-addressed bundle instead of the old single-repository sandbox, enabling multi-repository environments, brokered credentials, and personal GitHub access for commits, pushes, and pull requests.
What changed
- Environments support multiple repositories, organization or personal scope, config-repository start hooks, editing, onboarding agents, and immutable repository sets after promotion.
- Personal environments are enforced server-side; update calls no longer accept
sourceReforbundleSha. - Brokered Anthropic, OpenAI, and GitHub access via firewall rules; environment variables stay in host-service memory and reach terminals and host-service processes.
- Added GitHub Connections with encrypted token storage, refresh, disconnect, and installation-token fallback when personal OAuth is unavailable; a transient refresh failure no longer removes the connection.
- The cloud flag now gates the Settings cloud sections, search, and mobile's environments query; environment rows without repositories no longer throw into a render.
- Added separate gate tickets and diagnostics for host-service and the websockify desktop stream, plus repository and branch selection on desktop and mobile.
- Sandbox releases run from CI via a
production-releasedispatch; the image push handles its own registry login. - Added migrations 0115 and 0116 for environment repositories and GitHub user connections.
Rollout
- Deploy the API, run both migrations, publish the production image, and run
sandbox:release --productionvia the workflow'sproduction-releasedispatch; flagged creates fail cleanly until the image and bundle are available. - Set
GH_APP_CLIENT_IDandGH_APP_CLIENT_SECRETto enable personal GitHub connections. - The rollout remains behind
cloud-workspaces; existing workspaces from the previous layout are not guaranteed to wake and should be recreated.
Summary by CodeRabbit
-
New Features
- Create and edit environments with repository selection, visibility controls, configuration locations, and optional agent setup.
- Cloud workspaces support multiple repositories, improved branch selection, and workspace-specific pull requests.
- Connect personal GitHub accounts for cloud workspace commits, pushes, and pull requests.
- Sandbox desktops now offer dedicated streaming with boot and readiness diagnostics.
- Added environment startup commands and refreshed sandbox tooling.
-
Bug Fixes
- Improved repository handling when environments have no connected repositories.
-
Documentation
- Expanded sandbox setup, release, troubleshooting, and acceptance documentation.