Repository navigation
Cloud attach-endpoint: report vmKind (owner only for the caller's own personal VM) - #26222
Conversation
POST /api/vm/:id/attach-endpoint now answers vmKind: "owner" | "team" | null. "owner" only when the machine is on the caller's own personal account (owner_team_id is the caller's user id) and the caller created it. Every Stack team, a one-member team included, is "team", and so is a machine the caller can reach but did not create. A row with no usable billing owner is null. The Mac app drops its local sandbox for its own session only on "owner"; resolveVmGuestKind and its callers are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6
|
All contributors have signed the CLA ✍️ ✅ |
|
Owned by an agent session · session |
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Classify VM kind web/services/vms/vmKind.ts, web/tests/vm-attach-vm-kind.test.ts |
vmKindForCaller returns owner when the caller ID exactly matches the VM user ID and billing owner. It returns team for other cases with a nonblank billing owner, and null when the billing owner is blank. Tests cover these conditions. |
Include VM kind in attach results web/services/vms/workflows.ts, web/tests/vm-attach-vm-kind.test.ts, web/tests/vm-workflows.test.ts |
The cmux-remote, legacy attach, and shared attach results include the caller-specific vmKind. Endpoint tests cover personal and team VM cases, and workflow tests expect team in successful results. |
Priority:
Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Feature
Possibly related PRs
- manaflow-ai/cmux#26182: Both changes classify VMs as
ownerorteam. That PR records the kind for newly created Cloud VMs; this change includes it in attach responses.
Merge Risk: 
Minimal · up to cd4af
-
No merge-blocking risk was identified; the change is ready to merge.
Pre-merge checks: 
23 · 
2
-
Failed checks: 2 warnings Passed checks: 23 passed-
Full details: Cmux Cloud Persistent Session And Early Input
-
Explanation
PASS. The reviewed diff only adds
vmKindForCallerand appendsvmKindto existing attach results. It does not create a client, carrier, event socket, renderer, readiness gate, or input path. Existing access checks, provider attach calls, lease recording, and session flow remain unchanged. The added computation runs after the existing remote or websocket operation and does not weaken auth, idempotency, revision, or lease fences.
Full details: Cmux Swift Actor Isolation
-
Explanation
The pull request changes only four TypeScript files under web/services and web/tests. The authoritative diff contains no Swift files or production Swift changes, so it cannot introduce or worsen Swift 6 actor-isolation issues.
Full details: Cmux Browser Automation Off-Main
-
Explanation
PASS: The pull request changes only
web/services/vms/vmKind.ts,web/services/vms/workflows.ts, and related web tests. It does not changeSources/TerminalController.swiftorPackages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Wire/ControlCommandExecutionPolicy.swift. The diff adds no browser socket commands, WebKit waits, worker routing, or policy tests. The browser automation rule is not applicable.
Full details: Cmux Expensive Synchronous Load
-
Explanation
PASS: The pull request changes only TypeScript files under
web/and adds no Swift files or Swift call-site changes. Therefore it does not add or move an expensive synchronous agent-history load onto the main actor or an interactive Swift path.
Full details: Cmux Cache Substitution Correctness
-
Explanation
The pull request adds a per-request
vmKindForCallervalue to attach responses. It does not replace a fresh authoritative read with a cached or opportunistic value, and it does not change a persistence, history, undo, or snapshot path. The changed workflow still obtains the VM throughrequireAccessibleUserVm; the new value is computed from that row and is explicitly not stored.
Full details: Cmux No Hacky Sleeps
-
Explanation
PASS: The production diff only adds
vmKindForCallerand attaches its result to workflow responses. It adds nosleep, timer, polling, fixed delay, backoff, or wall-clock synchronization. The new test code uses async calls but adds no timing scaffolding. Existing timing code inworkflows.tsis unchanged.
Full details: Cmux Algorithmic Complexity
-
Explanation
PASS: The production changes add one constant-size identity check in
web/services/vms/vmKind.tsand addvmKindto endpoint result objects inweb/services/vms/workflows.ts. They do not scan scalable collections, sort/filter per event, perform in-memory joins, or introduce a slower algorithm on a 1000-record path. The added tests are test-only and are exempt by the rule.
Full details: Cmux Swift Concurrency
-
Explanation
The pull request changes only TypeScript service and test files under web/. The authoritative diff contains no Swift files or Swift code, so it does not introduce or expand any Swift concurrency pattern.
Full details: Cmux Swift `@Concurrent`
-
Explanation
PASS: The pull-request diff changes only TypeScript files under web/services and web/tests. It introduces no Swift functions, call sites, or actor-isolation changes, so the Swift
@concurrentcriteria do not apply.
Full details: Cmux Swiftpm Lockfiles
-
Explanation
The pull request changes only four TypeScript service and test files under web/. It does not change SwiftPM packages, Package.swift files, Package.resolved lockfiles, Xcode project references, .gitignore files, workflows, or dependencies. The SwiftPM lockfile policy is therefore not triggered.
Full details: Cmux User-Facing Error Privacy
-
Explanation
The production diff adds only
vmKindto successful attach API responses. The route returns this value throughjsonResponseatweb/app/api/vm/[id]/attach-endpoint/route.ts:87,111, and the macOS client calls that product API. The new values areowner,team, ornull, which do not expose implementation details. No user-facing error, alert, command output, or recovery copy changed. Provider-specific values appear only in developer comments and tests, which the rule allows.
Full details: Cmux Full Internationalization
-
Explanation
PASS. The diff adds only the machine-readable
vmKindAPI field and the exactowner/team/nullprotocol values. The attach route returns this field as JSON for Mac client logic. It adds no human-facing Swift or web text, metadata, or locale message keys. Protocol and machine-marker tokens are explicitly allowed by the internationalization rule.
Full details: Cmux Source Artifacts
-
Explanation
All four changed paths are intentional TypeScript source or test files:
web/services/vms/vmKind.ts,web/services/vms/workflows.ts, and the twoweb/testsfiles. The diff adds thevmKindForCallerimplementation, workflow wiring, and focused tests. No local output, generated logs, screenshots, recordings, temporary directories, caches, build artifacts, dependency checkouts, or broad scratch directories appear in the changed-file inventory.
-
Full details: Description check
-
Explanation
The description gives a detailed summary, implementation rule, production context, testing results, and risk analysis. However, it does not use the required Summary, Testing, Changelog, Proof, and Checklist sections. It also omits the required changelog entry, proof statement, and checklist status.
Resolution
Reformat the description using the repository template. Add ## Summary, ## Testing, ## Changelog, ## Proof, and ## Checklist sections. Move the existing content into the appropriate sections, add a present-tense changelog line or
none, state why visual proof is not applicable, and mark or explain each checklist item.
Full details: Docstring Coverage
-
Explanation
Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 9 functions across 4 files.
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
-
Finishing Touches: 💡 1
-
📝 Generate docstrings: 💡
-
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
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.
Comment @coderabbitai help to get the list of available commands.
A creator id that matches the caller only after trimming is not the caller, so it never gets "owner". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
…e-member team (#28479) * Cloud attach-endpoint vmKind: owner for the creator's machine on a one-member team The classic attach answer said `team` for every Stack team, including a personal Stack team whose only member is the creator. Accounts made with a personal team get every machine on that team, so the Mac app never sent `vm_kind: "owner"` and cmux-tui refused agent chats with agent_session.host_unverified on the classic route. vmKindForCaller now answers `owner` for a machine the caller created on a Stack team whose member list, read for this attach with the bounded listTeamMemberIdsWithTimeout (resolveVmGuestKind's read), is exactly the caller. A second member, a missing team, an unread, failed or timed-out list all answer `team`. The read runs only for that case and overlaps the endpoint open. Reverses the one-member choice of #26222. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-aa0f0a21b40fda1441b8 * test(vm-route-auth): type-safe team directory assertion Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-aa0f0a21b40fda1441b8 * test(vm-kind): a second member flips the same machine to team on the next attach Review note on #28479: test the transition with one directory, not two. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-aa0f0a21b40fda1441b8 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
What
POST /api/vm/:id/attach-endpointnow answers a top-levelvmKind: "owner" | "team" | nullon every transport (cmux-remote,websocket).The Mac app will use it to give up its local sandbox for the caller's own session only when the Cloud API says the machine is the caller's own personal machine. The guest has passwordless sudo, so no in-guest marker can be trusted for this. The app reads the field per link and never caches it; a missing, null or other value stays sandboxed. The app and acpmux sides are separate PRs.
The rule (strict)
New
vmKindForCaller(row, callerUserId)inweb/services/vms/vmKind.ts:"owner"only when the machine is on the caller's own personal account (owner_team_idequals the caller's user id, the synthetic personal team) and the caller created it (user_idequals the caller)."team"for every Stack team, a one-member team included, and for any machine the caller can reach but did not create. A team member attaching to a teammate's machine gets"team".nullwhen the row has no usable billing owner (blankowner_team_id). The access check already refuses such a row, so in practice clients seeownerorteam.resolveVmGuestKindand its callers (the guest's/etc/cmux/vm-kindvia/api/vm/reflection/kind) are unchanged. On main that function calls a one-member teamownerand re-asks every minute; the attach answer deliberately does not reuse it, so it can't turn intoownerfor a team.owner_team_idistext NOT NULL DEFAULT ''on main and feat-cmux-next alike, so "personal account" meansowner_team_id = user_idon both. There is no null case.Where production serves this
Both the stable app and the nightly-next app call
https://cmux.com/api/vm/:id/attach-endpoint:Packages/macOS/CmuxCloud/Sources/CmuxCloud/Environment/AuthEnvironment.swift:324-336, where a Release build is alwayshttps://cmux.com;Packages/macOS/CmuxNext/Sources/CmuxNextCloud/Config/CloudConfiguration.swift:69,95-99andAPI/CloudAPIClient.swift:117-122, where a Release build usesapiBaseURL=https://cmux.com.cmux.com is the Vercel
web/app.web/vercel.jsondeploysmainonly, and a live request answersserver: Vercel,x-matched-path: /api/vm/[id]/attach-endpoint. So this lands on main for production. A twin PR carries the same change to feat-cmux-next so the branches don't drift.Tests
web/tests/vm-attach-vm-kind.test.ts, throughopenVmCmuxRemoteandopenAttachEndpoint, plus the pure function:owner;team, for its creator too;team, neverowner;team;Three existing
vm-workflowsequality checks now expect the extra field.Linux CI: 14 related files, 325 pass and 0 fail; tsgo, eslint and complexity are clean.
Each test fails without its part of the change:
ownerfor any personal machine whoever calls, the "another account" tests fail (2);owner, the one-member test fails (1).Risk
The response gains a field; Swift decoders ignore unknown keys. A wrong
ownerwould let a session skip the local sandbox, so the rule fails closed: only the exact creator-on-personal-account case isowner.Agent session: agent session
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by CodeRabbit