feat(desktop,trpc,host-service): cloud workspaces backed by Blaxel sandboxes

Merged
SA
3mo ago
+9503-158

Cloud workspaces: one workspace is one Blaxel sandbox running host-service, reachable from the desktop app.

This was a five-PR stack (#6489, #6497, #6500, #6503, #6505) that has been collapsed into this one — same commits, rebased onto current main. The others are closed as superseded, not abandoned.

What it does

Create a cloud workspace from the app, get a sandbox with the repo cloned and an agent already authenticated, and drive it from the sidebar with the affordances a local workspace has: PR badges, agent status, rename, ordering, delete.

The parts worth reviewing

A sandbox is one repo, one project, one workspace, fixed at provision. machineOnlyProcedure refuses project/workspace CRUD inside one, whoever asks — agent, CLI or shell — because "add a project" produces state the cloud side can't see or clean up. The boot-time sweeps that repair a long-lived machine's accumulated state don't run there either: a sandbox is provisioned fresh, so they can only invent (the main-workspace sweep was adding a phantom second workspace before this).

The cloud row owns the workspace name. host-service's copy is ignored. Two sources of truth for a name was the original bug behind the rename flicker.

Agent credentials never enter a sandbox. The provider's egress proxy substitutes them at the edge from a {{SECRET:...}} routing rule; the sandbox env holds only a placeholder. An agent can use the key and can't read it.

A sandbox's host-service trusts the edge — please read this one. EdgeGuardedHostAuthProvider accepts every request. The gate is the private preview: the edge turns away anything without a preview token, and only our API can mint one. Keeping the PSK as a second layer was considered and rejected — one secret baked into every sandbox is a cross-tenant credential, and every sandbox hands an agent a shell that can read its own env. A second factor each tenant can read isn't one; it just makes the posture look deeper than it is. Consequence: public: false on the preview is now a security-critical setting.

Cloud-workspace env vars are required, not defaulted. A misconfigured deployment fails at boot instead of quietly degrading. Anyone with an existing root .env needs the four new keys from .env.example before the API will start.

Notes for review

  • Migration is 0078, regenerated on top of 0077. As 0074 its timestamp was earlier than main's own 0074, so drizzle would have skipped it silently and forever — the table would never have been created in production.
  • Additive migration (one enum, one table, FKs only on the new table). Nothing alters an existing column.
  • Creation is gated to @superset.sh accounts while the path is unproven.
  • docs/cloud-sandbox-mismatches.md is the running list of places a sandbox doesn't behave like a machine someone owns; docs/cloud-sandbox-considerations.md is what's still owed before non-internal users.

Known gaps

  • The GitHub token in a sandbox's .git/config is a write-scoped credential readable by anything inside. Needs a decision: strip the remote plus a credential broker, or a long-lived credential.
  • Pin is hidden for cloud rows — the Pinned section builds from local host data and would render the sandbox's stale name.
  • No drag-ordering for cloud rows yet, and no reaper for rows stuck in provisioning.
  • Untested: sandbox sleep/wake with a host-service restart, disk durability, token refresh after backgrounding.

Summary by CodeRabbit

  • New Features
    • Added cloud workspace creation, provisioning, repository bootstrapping, and branch selection.
    • Cloud workspaces now appear in the dashboard sidebar with preview access.
    • Added cloud workspace rename and deletion support.
    • Added sandbox-aware connectivity, event updates, credential handling, and GitHub repository access.
  • Bug Fixes
    • Workspace names now update immediately while renaming.
    • Improved readiness, access retries, and cleanup behavior.
  • Documentation
    • Added guidance on cloud sandbox limitations, security, lifecycle, and setup.