feat(cloud): Internet Access… sets a Cloud machine's network level (full, trusted, none)

Merged
TE
6d ago
+1509-12

Leo, 2026-10-30: "How about more cmux-platform audits, improvements, features, fixes, optimizations, polish, plus the ui that gets people (or agents) using it"

Leo, 2026-10-29/30: "let's just get the cloud and its respective ui up to snuff" and "as well as the ui usability of the cloud stuff".

What this changes

Every Cloud machine made from the app, the CLI or an agent could reach the whole internet, and nothing outside the web dashboard could change that. The web control plane already has a per-machine egress policy (full / allowlist / none, presets, applied live through GET/PUT /api/vm/{id}/network), but no app, CLI or MCP client called it. Codex cloud, Claude Code on the web, Devin and Cursor all offer a short choice of access levels (research: manaflow-ai/cmuxterm-hq#5308, umbrella #5306).

This adds one action, Internet Access…, on a Cloud machine's menu (Connection folder), with CLI and MCP parity through the action catalog:

cmux cloud set-network-access --machine ID --access full|trusted|none [--json]
  • full: the whole internet.
  • trusted: GitHub, package registries and model providers, meaning every preset the server's catalog serves. The machine's own ranges and domains are kept.
  • none: no internet, apart from the server's required cmux domains.

The answer reports mode, network_access (custom for a hand-edited policy), applied and applied_error. Nothing is written when the policy is unchanged and already applied.

Risk

  • Agents may only narrow access. An agent run (MCP origin or a caller agent session) that would widen it (none → trusted → full, or a new preset) is refused with a message telling the person to do it from the menu. Covered by a test.
  • No default changes. Machines still start with full; the new-machine default is left as a [taste] question in hq#5308.
  • Legacy link only. On the app server link (CMUX_NEXT_CLOUD_LINK=app) the action refuses with the existing "not available" message, since that plane has no network policy yet.
  • Size. About 900 of the 1,361 lines are the 7 new strings in 21 locales across three xcstrings catalogs. The Swift is about 280 lines plus 174 lines of tests.
  • check-no-godfiles (warn-only) sees a few wiring lines added to CloudHandlers and ActionSurfaceCatalog; the logic lives in the new CloudNetworkAccessActions.

UI review

The only UI is one new row in the existing Cloud machine menu's Connection folder, with the existing globe symbol and the shared argument picker; no new component or spacing. Checked against design/ui-review-checklist.md (menu opens on the click, no new hover or highlight behaviour). Before/after menu stills follow in a comment.

Tests

Tests/CmuxNextAppTests/CloudNetworkAccessTests.swift: decoding and body round-trip, level mapping and detection, widening order, the descriptor and CLI name, a CLI run, unchanged vs failed apply, agent narrow-but-not-widen, invalid values.

Agent session: agent session

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Adds Internet Access… to a Cloud machine's menu so its outbound network level can be set as full, trusted, or none, with CLI and MCP parity.

  • full reaches the whole internet; trusted only GitHub, package registries, and model providers (the server's presets); none only hosts cmux itself needs.
  • Agents may only choose none; any other level is refused because the server's PUT is unconditional and a widening judged against a stale read could reopen access a person closed.
  • The machine's own allowed ranges and domains are kept; an unchanged, applied policy is not written again, and narrowing drops any portless whole-internet range (0.0.0.0/0, ::/0).
  • Same-machine runs serialize their read-then-write so a widening check never reads a stale policy; CLI and MCP calls wait for the server's answer.
  • The action refuses on the legacy app server link, which has no network policy yet.