feat(desktop,cli): switch to let your cloud workspaces reach a host

Merged
HA
2d ago
+662-1

Stack: 3 of 3 — #9407 (DB) → #9408 (API + relay) → this PR. Merge after #9408, once the API is live.

Summary

  • Desktop: Settings → Hosts → [host] → Cloud workspaces switch, shown to the host's owner on every host they own. It sits behind a confirm dialog that spells out the risk. Nothing restarts.
  • CLI: from a cloud workspace, --host calls go to the relay with no bearer, so the firewall-added workspace credential is what gets checked. Before, it sent an empty Bearer , which the relay rejected and the CLI showed as "Session expired".

How It Works

  • The switch reads allowCloudWorkspaces from host.roster (defaults to false if the API is older) and writes it with host.setCloudWorkspaceAccess, then invalidates the roster.
  • It's owner-only, so the owner can open a machine they aren't sitting at. Non-owners don't see it.
  • The CLI only drops the Authorization header when the bearer is empty. That happens only in a cloud workspace.

Manual QA (dev desktop over CDP, real clicks)

  • Settings → Hosts → this host shows the "Cloud workspaces" section, switch off, for the owner
  • Toggle on → dialog → Allow → "Setting saved"; a box call now returns 200
  • Toggle off → dialog → Turn off → the next box call is refused (403)
  • Host-service processes kept running through both toggles (same pids, uptime kept counting)
  • Not verified: the desktop typecheck (killed by the sandbox memory guard; CI is the first run)

Testing

  • bun test in packages/cli (482, including a test that a cloud workspace's relay call carries no Authorization)
  • bun test for desktop settings routes (107)
  • bun run typecheck in packages/cli
  • bun run check:i18n (7 new strings, translated in all locales)

Compatibility

  • Reads a new output field and calls a new procedure, so it needs #9408 live first (packages/trpc/AGENTS.md rule 9).
  • The CLI change is safe against any relay: an older relay still answers 401.
  • Boxes on CLI 2.0.3 already work against the new relay, because an empty bearer is treated like none.

Rollback

Revert this PR. The switch disappears; hosts already opened stay open until the column is set back.


Summary by cubic

Lets host owners allow their cloud workspaces to reach a host they own, and fixes the CLI so those calls succeed instead of failing with "Session expired". The switch needs the merged #9408 API and relay live; older relays still answer 401, so the CLI change is safe on its own.

New Features

  • Settings → Hosts → [host] shows a "Cloud workspaces" switch for the host's owner, guarded by a confirm dialog that spells out the risk. It's discoverable via Settings search, surfaces the server's localized errors, keeps a steady dialog text while closing, and drops a pending confirmation when switching hosts or organizations.
  • The switch reads allowCloudWorkspaces from the roster and writes it via host.setCloudWorkspaceAccess; no host services restart.

Bug Fixes

  • When the bearer is empty (cloud workspaces carry no user token), --host calls no longer send an empty Bearer header, so the relay checks the firewall-added workspace credential instead of rejecting the request.

Summary by CodeRabbit

  • New Features
    • Host owners can manage whether cloud workspaces may access their host through the relay. Changes require confirmation, with loading, success, and error feedback.
    • Confirmation prompts explain that access can allow cloud workspaces to create workspaces, start agents, and run commands on the host.
    • Added searchable settings and localized interface text for this access control.
  • Bug Fixes
    • Remote host requests no longer send an empty authorization header.