Skip to content

Vpc dogfood fixes - #11674

Merged
lawrencecchen merged 6 commits into
manaflow-ai:mainfrom
JacobZwang:vpc-dogfood-fixes
Sep 2, 2026
Merged

lawrencecchen merged 6 commits into
manaflow-ai:mainfrom
JacobZwang:vpc-dogfood-fixes

Conversation

@JacobZwang

@JacobZwang JacobZwang commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • What changed?
  • Why?

Testing

  • How did you test this change?
  • What did you verify manually?

Demo Video

For UI or behavior changes, include a short demo video (GitHub upload, Loom, or other direct link).

  • Video URL or attachment:

Review Trigger (Copy/Paste as PR comment)

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

Checklist

  • I tested the change locally
  • I added or updated tests for behavior changes
  • I updated docs/changelog if needed
  • I requested bot reviews after my latest commit (copy/paste block above or equivalent)
  • All code review bot comments are resolved
  • All human review comments are resolved

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


Summary by cubic

Fixes several VPC dogfooding issues: cloud terminal surfaces now resolve correctly, VPC machines connect over IPv4, and first-time links allow time for enrollment.

Bug Fixes

  • Cloud terminal resolution now requests the workspace tree over the raw command bridge and treats invalid_terminal_id as a fallback trigger.
  • VPC route prefers IPv4 over IPv6 because the tunnel routes the v4 prefix as a subnet and reaches new machines immediately.
  • First-link timeout is extended to 240s to cover enrollment; the first approval poll happens immediately instead of after a full interval.
  • Port links now use the machine's private IP directly (with IPv6 bracketed) instead of the .internal hostname.

Written for commit 95a2dfb. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Port links now open directly through the machine’s private address, including IPv6 support.
    • Freestyle connections prefer private IPv4 routes for improved tunnel reliability.
  • Bug Fixes

    • Cloud machine enrollment now allows more time for approval and responds faster initially.
    • Improved compatibility with legacy workspace and terminal-resource connections.
    • Port links avoid unreliable proxy routing where applicable.
    • Linked titles now use standard text color while remaining underlined.
  • UI Changes

    • Removed the memory-size selector from the New Machine sheet.

JacobZwang and others added 6 commits September 2, 2026 04:47
Asserts that a machine on a dual-stack VPC is dialed at its private IPv4,
not its private IPv6. Fails against the current IPv6-first ordering.

The tunnel routes the VPC's v4 prefix as a subnet, so it reaches any member
as soon as that member exists. Its v6 path does not pick up members created
after the tunnel came up, so a machine created into an established tunnel
blackholes on its private v6 while answering on its private v4 — both work
VM-to-VM inside the VPC, which is what made this look like a daemon fault
rather than a routing one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Reorders the private-network branch of freestyleCmuxRemoteRoute to prefer
IPv4 over IPv6. The public fallback stays IPv6 — Freestyle allocates no
public IPv4 at all — and private still never falls back to public.

Every machine created after the WireGuard tunnel came up spent the full
60s connect timeout and surfaced as "Command timed out" / stuck at
"connecting", while machines predating the tunnel connected in seconds.
The daemon was healthy in both cases: it listens on *:1337, and the new
machine answered on its private v4 and was reachable over both v4 and v6
from inside the VPC. Only the Mac's v6 path to it was dropped, because the
tunnel routes the VPC's v4 prefix as a subnet but does not extend its v6
path to members added after setup.

Preferring v4 also matches the app's own preferredPrivateAddress (v4 then
v6), so the address shown and copied in the sidebar is now the same one
the daemon is dialed on.

Verified against the machine that had been timing out: it now links in
4.2s where it previously failed at 60s.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Cloud terminals failed with "cmux-tui did not report the new terminal"
on every create. The terminal itself was fine — the daemon created it and
returned a well-formed result; what failed was mapping it to a surface.

Both resolver paths were dead:

- resolve-terminal takes a terminal *host* id (UUIDv4 hex, per
  spec/sdk-schema.json). The app only ever holds a public `term_…`
  resource id, whose hex is not a UUIDv4, and no command maps one to the
  other. The daemon answered `invalid_terminal_id`, which was classified
  as a hard failure, so the caller fail-closed instead of falling back.
- The compatibility tree it should have fallen back to was requested as a
  bare `list-workspaces` subcommand. The resource CLI reads that leading
  word as a resource scope and rejects it with `unknown resource scope
  "list-workspaces"`, so the fallback could never run either.

The daemon does still serve list-workspaces over the raw command bridge,
and its tabs carry `terminal_resource_id` beside `surface` — exactly the
join the existing legacy parser already performs. So: request the tree
over that bridge, and treat `invalid_terminal_id` as the id-space
mismatch it is, routing to the tree rather than failing.

Verified against a live daemon: the tree resolves every public terminal
id to its surface. Tests fail without these two changes (both new tests
red, 21 green with them).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A freshly created machine hung at "connecting" for a minute, failed, and
then connected instantly on a manual retry.

The retry succeeded because by then the Mac was enrolled. Enrollment
itself had completed during the failed attempt — just after the link had
been timed out and its client killed. It cannot be done up front: the
control plane only approves an invitation the client has already claimed
(approveCmuxTuiEnrollment looks for it in `remote enroll pending`), so
claiming and approving necessarily race inside the connect window. Each
approval poll is a control-plane round trip that shells into the machine
twice, and on a machine that just booted those execs are slow enough to
blow the 60s budget.

So a first link, which must also carry enrollment, gets its own longer
budget; an already-enrolled link keeps the 60s one, where the daemon
accepts immediately and anything slower is a broken route rather than a
slow one. The approval loop also stops sleeping a full poll interval
before its first attempt, since the client claims its invitation as soon
as it is spawned.

Verified by clearing this Mac's saved fingerprint and restarting, which
forces the real invitation + approval path: connect to connected in 1.5s,
fingerprint re-saved, terminal created.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 2, 2026

Copy link
Copy Markdown

@JacobZwang is attempting to deploy a commit to the Manaflow Team on Vercel.

A member of the Team first needs to authorize it.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@lawrencecchen
lawrencecchen merged commit 5f1df81 into manaflow-ai:main Sep 2, 2026
5 of 12 checks passed
@coderabbitai

coderabbitai Bot commented Sep 2, 2026 •

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Team

Run ID: 036fc81d-f83f-4d9d-9e95-de5f4bd59a93

📥 Commits

Reviewing files that changed from the base of the PR and between d18aa5f and 95a2dfb.

📒 Files selected for processing (13)
  • Packages/macOS/CmuxFoundation/Sources/CmuxFoundation/CmuxInternalHostnames.swift
  • Packages/macOS/CmuxFoundation/Tests/CmuxFoundationTests/CmuxInternalHostnamesTests.swift
  • Sources/Cloud/CloudMachineLinkManager.swift
  • Sources/Cloud/CloudTreeNode.swift
  • Sources/Cloud/CloudTreeRowContentView.swift
  • Sources/Cloud/CloudTuiCommandLine.swift
  • Sources/Cloud/NewMachineSheet.swift
  • Sources/Surfaces/CmuxTuiSnapshotParser.swift
  • Sources/Surfaces/CmuxTuiSurfaceProvider+ManualMirror.swift
  • Sources/Surfaces/CmuxTuiSurfaceProviders.swift
  • cmuxTests/CloudManualMirrorTransportTests.swift
  • web/services/vms/drivers/freestyle.ts
  • web/tests/vm-freestyle-provider.test.ts

📝 Walkthrough

Walkthrough

Cloud port links now use direct private-address URLs. Forwarded-port panes bypass the control-plane proxy. Compatibility fallback detection and workspace requests use updated command paths. Enrollment timing and Freestyle route address selection were also updated.

Changes

Cloud connectivity updates

Layer / File(s) Summary
Direct URL contract
Packages/macOS/CmuxFoundation/Sources/CmuxFoundation/CmuxInternalHostnames.swift, Packages/macOS/CmuxFoundation/Tests/CmuxFoundationTests/CmuxInternalHostnamesTests.swift, Sources/Cloud/CloudTreeNode.swift
Added directPortURL(privateAddress:port:) with IPv6 bracketing. Cloud port URLs now use raw private addresses for non-local machines. Tests cover IPv4 and IPv6 output.
Forwarded-port URL flow
Sources/Surfaces/CmuxTuiSnapshotParser.swift, Sources/Surfaces/CmuxTuiSurfaceProviders.swift, Sources/Cloud/CloudTreeRowContentView.swift
Forwarded-port resources carry direct URLs and materialize browser panes without the endpoint()/openPort proxy path. Linked titles retain underlines without accent coloring.
Compatibility command and resolver fallback
Sources/Cloud/CloudTuiCommandLine.swift, Sources/Surfaces/CmuxTuiSurfaceProvider+ManualMirror.swift, cmuxTests/CloudManualMirrorTransportTests.swift
Legacy workspace discovery uses the raw command bridge. invalid_terminal_id and operation.unsupported responses trigger compatibility fallback. Tests cover supported and unrelated errors.
Enrollment connection timing
Sources/Cloud/CloudMachineLinkManager.swift
Invitation-based links use a 240-second timeout. Existing links use 60 seconds. Approval polling starts after 250 milliseconds and then uses 2-second intervals.
Freestyle route selection
web/services/vms/drivers/freestyle.ts, web/tests/vm-freestyle-provider.test.ts
Freestyle prefers private IPv4 routes and falls back to private IPv6 routes. Tests cover both address types.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CloudTuiSurfaceProviders
  participant CmuxInternalHostnames
  participant CmuxTuiSnapshotParser
  participant SurfacePaneFactory
  CloudTuiSurfaceProviders->>CmuxInternalHostnames: Build directPortURL from preferredPrivateAddress
  CloudTuiSurfaceProviders->>CmuxTuiSnapshotParser: Pass directURL to portBrowser
  CmuxTuiSnapshotParser-->>CloudTuiSurfaceProviders: Return resource with URL
  CloudTuiSurfaceProviders->>SurfacePaneFactory: Materialize browser pane from direct URL
Loading

Suggested reviewers: austinywang, lawrencecchen

✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

rustybret pushed a commit to rustybret/bmux that referenced this pull request Sep 2, 2026
5f1df81 Vpc dogfood fixes (manaflow-ai#11674)
c7bbfae cloud: one devbox snapshot per Freestyle size; the plan's memory picks the size (manaflow-ai#11664)
d18aa5f Merge pull request manaflow-ai#11670 from manaflow-ai/issue-remote-decode-errors
cd7d971 Admin Pro roster loads on page render and streams the scans (manaflow-ai#11668)
da8befc fix(remote): terminate reader on malformed JSON
8a93998 test(remote): cover malformed JSON cancellation
ce4cd50 fix(relay): stop when process file setup fails (manaflow-ai#11491)
e3b14a1 fix(cloud): Cmd+T on a cloud pane selects the new remote terminal (manaflow-ai#11612)
d90d8b8 Send Durable Object errors to Sentry (manaflow-ai#11657)
1a86aca Admin Pro roster: bounded team lookups, truncation flag, scan sequence guard (manaflow-ai#11662)
f277fe6 Merge pull request manaflow-ai#11643 from manaflow-ai/fix-11492-clone-killer
65c0c60 fix(test): make scoped attach killer mutable
8cdf1ce Cloud sidebar port links: direct private IPs, white link styling, reconnect-logic merge fix (manaflow-ai#11647)
6d1ca7e fix(tui): narrow workspace registry APIs (manaflow-ai#11498)
9f7ba2d Admin page: list every Pro user, team, and pending grant (manaflow-ai#11645)
23a5485 fix(relay): pin PTY cwd to validated descriptor (manaflow-ai#11417)
3214964 fix(relay): own the grep pattern before spawning the runner task (manaflow-ai#11653)
400d306 Fix devcontainer SSH TTY flag placement (manaflow-ai#9772)
613870c web: answer Stack Auth throttles on iroh routes with 429, add a Stack throttle circuit (manaflow-ai#11633)
f6be8ff web: resolve unoffered Cloud VM sizes to the plan machine instead of 400 (manaflow-ai#11644)
6d67bc5 Kill unvisited subtrees when the SSH auth cleanup deadline expires (manaflow-ai#11584)
790a7d8 Admin Pro access page: grant users, teams, and emails, manual downgrade (manaflow-ai#11605)
9bf04a3 fix(web): render the coderouter dashboard at request time (manaflow-ai#11632)
bcc362c test(cmux-tui): cover scoped attach PTY lifecycle (manaflow-ai#11492)
51a9495 Fix main CI after the Blaxel removal and non-root daemon landing (manaflow-ai#11586)
accfbdf Harden cmux-tui executable resolution before spawn (manaflow-ai#11427)
05c631d web: skip irrelevant Vercel builds and defer old changelog pages (manaflow-ai#11413)
40fd841 fix: render cloud VM terminals through native Ghostty manual I/O (manaflow-ai#11523)
1dd28a9 cloud: Freestyle devbox snapshot on the public platform (ubuntu user, base toolchain, Blaxel desktop), promote script, manifest as source of truth (manaflow-ai#11601)
4940db8 Pricing: Pro $50, Team $60, plan machine 5 vCPU / 20 GB / 200 GB, 50 VMs per seat (manaflow-ai#11610)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants