Repository navigation
Cloud: every signed NEXT build (DEV and nightly) defaults to NEXT Cloud via the app-server link - #28899
Conversation
|
Review (codex gpt-6-astra high, router-review): BLOCK at 1b02f40 [P1] [blocking] The signed DEV callback Review used the complete exact base/head range |
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Not verified: macOS jobs did not run: compile and app tests were skipped on CI passes on Written by web and size checks: green Default changesThis pull request changes 1 default at
Signed off on this commit by Merge receipt: merged as Regenerate the snapshot with Shipped in:
|
|
Found 8 test failures on Blacksmith runners: Failures
|
|
Review (codex gpt-6-astra high, next-review): BLOCK at c8d8274
|
|
Orphaned: no activity for 13 h, and no lane holds a lease on it. The orphan sweep could not merge |
# Conflicts: # Packages/macOS/CmuxNext/Sources/CmuxNextCloud/Auth/CloudAuth.swift
There was a problem hiding this comment.
1 issue found across 4 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="Packages/macOS/CmuxNext/Sources/CmuxNextCloud/Config/CloudConfiguration.swift">
<violation number="1" location="Packages/macOS/CmuxNext/Sources/CmuxNextCloud/Config/CloudConfiguration.swift:90">
P1: This entry moves the signed NIGHTLY identity to staging endpoints, staging auth storage, and the app-server link, although only signed DEV should change. Remove the NIGHTLY entry so `com.cmuxterm.app.nightly.cmux-next` continues resolving to production.</violation>
</file>
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
| /// NEXT build included, keep production. | ||
| static let nextCloudChannels: [String: String] = [ | ||
| "com.cmuxterm.app.debug.next": "cmux-next-dev", | ||
| "com.cmuxterm.app.nightly.cmux-next": "cmux-next", |
There was a problem hiding this comment.
P1: This entry moves the signed NIGHTLY identity to staging endpoints, staging auth storage, and the app-server link, although only signed DEV should change. Remove the NIGHTLY entry so com.cmuxterm.app.nightly.cmux-next continues resolving to production.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At Packages/macOS/CmuxNext/Sources/CmuxNextCloud/Config/CloudConfiguration.swift, line 90:
<comment>This entry moves the signed NIGHTLY identity to staging endpoints, staging auth storage, and the app-server link, although only signed DEV should change. Remove the NIGHTLY entry so `com.cmuxterm.app.nightly.cmux-next` continues resolving to production.</comment>
<file context>
@@ -36,28 +38,60 @@ public struct CloudConfiguration: Sendable, Equatable {
+ /// NEXT build included, keep production.
+ static let nextCloudChannels: [String: String] = [
+ "com.cmuxterm.app.debug.next": "cmux-next-dev",
+ "com.cmuxterm.app.nightly.cmux-next": "cmux-next",
+ ]
+
</file context>
|
Fleet evidence at 744b992 (base merge of feat-cmux-next 5b86066, then the nightly commit):
|
|
Review (codex gpt-6-astra high, router-review): BLOCK at 744b992 BLOCK at 744b992 Visual verdict: no images; Leo tries the build
|
…use app server ops On the app server link (now every signed NEXT build), CloudService still sent these to the classic /api/vm client on apiBaseURL, where a Worker machine has no record, so they failed. They now run cloud.machine.delete, .pause, .start, .rename and .idle_policy.set through the app link, with the same approval loop as other person-started money and destructive ops. An empty rename is a no-op there: the server keeps a name on every machine. Review finding at 744b992 (router-review, gpt-6-astra high). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5
There was a problem hiding this comment.
All reported issues were addressed across 2 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
|
Review (codex gpt-6-astra high, router-review): BLOCK at 8f4cafd BLOCK at 8f4cafd Visual verdict: no images; Leo tries the build
|
…app server ops; the rest are refused The second review at 8f4cafd found more actions still sent to /api/vm on the app server link: resize, snapshot, promote to template, delete snapshot, restore, handoff, SCP, status, port links, fork and GitHub setup's exec. - Resize, snapshot, template, delete snapshot, restore and handoff now run cloud.machine.resize, cloud.snapshot.create/.delete/.restore and cloud.machine.get. - GitHub setup runs exec through machineAPI, the Worker's exec route. - A Worker machine record now declares the operations the app can reach for it (snapshot, restore, exec, sizing). The existing capability guards refuse fork, port links, stats and desktop, which have no Worker route yet, instead of letting them 404. SCP is refused on the app server link. - The record's idle_policy.idle_seconds now reads as its idle pause minutes, so a set idle pause survives a refresh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5
There was a problem hiding this comment.
1 issue found across 5 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="Packages/macOS/CmuxNext/Sources/CmuxNextApp/Cloud/CloudService+AppServer.swift">
<violation number="1" location="Packages/macOS/CmuxNext/Sources/CmuxNextApp/Cloud/CloudService+AppServer.swift:117">
P2: `appServerRestore` gets a new random idempotency key on every call. If the answer is lost and the person runs restore again, the Worker sees a new key and creates a second billed machine. Persist the restore key the way `appServerCreate` does, and reuse it on Retry.</violation>
</file>
Requires human review: Auto-approval blocked because this review re-detected 1 unresolved issue already reported by Cubic.
View guided diff | Turn on auto-fix | Re-trigger cubic
|
|
||
| /// `cloud.snapshot.restore`: the new machine's id. | ||
| func appServerRestore(snapshotID: String) async throws -> String { | ||
| let answer = try await appServerApprovedCall("cloud.snapshot.restore", args: .object(["snapshot": .string(snapshotID)]), confirm: { true }) |
There was a problem hiding this comment.
P2: appServerRestore gets a new random idempotency key on every call. If the answer is lost and the person runs restore again, the Worker sees a new key and creates a second billed machine. Persist the restore key the way appServerCreate does, and reuse it on Retry.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At Packages/macOS/CmuxNext/Sources/CmuxNextApp/Cloud/CloudService+AppServer.swift, line 117:
<comment>`appServerRestore` gets a new random idempotency key on every call. If the answer is lost and the person runs restore again, the Worker sees a new key and creates a second billed machine. Persist the restore key the way `appServerCreate` does, and reuse it on Retry.</comment>
<file context>
@@ -73,10 +73,52 @@ extension CloudService {
+
+ /// `cloud.snapshot.restore`: the new machine's id.
+ func appServerRestore(snapshotID: String) async throws -> String {
+ let answer = try await appServerApprovedCall("cloud.snapshot.restore", args: .object(["snapshot": .string(snapshotID)]), confirm: { true })
+ guard let id = answer["machine"]?["id"]?.stringValue else {
+ throw CloudAppOpFailure(code: "cmux.cloud.bad_response", message: "cloud.snapshot.restore answered no machine")
</file context>
|
Review (codex gpt-6.1-sol xhigh, router-review): BLOCK at fa21de0 BLOCK at fa21de0 Visual verdict: no images; Leo tries the build
Swift tests were not run: this Linux box has no Swift/macOS toolchain. |
…oval Review at fa21de0 (gpt-6.1-sol xhigh): the app server machine calls answered server-held approvals with the person's session whatever started them, so a CLI, MCP or agent run could resize, snapshot or restore without the person. Each call now carries byPerson, which is true only when the action's origin is the person's own gesture (CloudHandlers.origin(of:) == .user). A person's run keeps the approval loop as `user`. Any other caller sends the op as `script` with a fresh key and gets approval.pending back, for the person to answer in the feed. CloudService's methods default to not-by-person: the Cloud page closures and an attach's resume. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5
There was a problem hiding this comment.
1 issue found across 3 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="Packages/macOS/CmuxNext/Sources/CmuxNextApp/Cloud/CloudService+AppServer.swift">
<violation number="1" location="Packages/macOS/CmuxNext/Sources/CmuxNextApp/Cloud/CloudService+AppServer.swift:77">
P3: The doc comment says non-person callers get `approval.pending` back. The app-ops layer throws it as a `CloudAppOpFailure` (code `cmux.cloud.approval_pending`, request in `details`), so nothing is returned. Say it is thrown so callers handle it as an error.</violation>
</file>
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
| /// `byPerson`: the person's own gesture in this app, already confirmed where the action needs it | ||
| /// (the registry's sheet for Kill). Only then is a server-held approval answered with the | ||
| /// person's own session. Any other caller (the CLI, MCP, an agent, a script) sends the op as | ||
| /// `script` and gets the server's `approval.pending` back, for the person to answer in the feed. |
There was a problem hiding this comment.
P3: The doc comment says non-person callers get approval.pending back. The app-ops layer throws it as a CloudAppOpFailure (code cmux.cloud.approval_pending, request in details), so nothing is returned. Say it is thrown so callers handle it as an error.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At Packages/macOS/CmuxNext/Sources/CmuxNextApp/Cloud/CloudService+AppServer.swift, line 77:
<comment>The doc comment says non-person callers get `approval.pending` back. The app-ops layer throws it as a `CloudAppOpFailure` (code `cmux.cloud.approval_pending`, request in `details`), so nothing is returned. Say it is thrown so callers handle it as an error.</comment>
<file context>
@@ -69,15 +69,23 @@ extension CloudService {
+ /// `byPerson`: the person's own gesture in this app, already confirmed where the action needs it
+ /// (the registry's sheet for Kill). Only then is a server-held approval answered with the
+ /// person's own session. Any other caller (the CLI, MCP, an agent, a script) sends the op as
+ /// `script` and gets the server's `approval.pending` back, for the person to answer in the feed.
@discardableResult
- func appServerMachineCall(_ op: String, _ machineID: String, _ fields: [String: JSONValue] = [:]) async throws -> JSONValue {
</file context>
| /// `script` and gets the server's `approval.pending` back, for the person to answer in the feed. | |
| /// `script` and gets an `approval.pending` error back, for the person to answer in the feed. |
|
Review (codex gpt-6.1-sol xhigh, router-review): SHIP at 392b5ed Note: carried from router-review's stdout. Its own --post failed on the host's GraphQL quota after the verdict. The model is the one this head's hash picks first. Follow-ups: 3, filed or tracked below. Visual verdict: no images; Leo tries the build
Static review completed. Swift tests and live signed-app sign-in were not run; this box has no Swift/macOS toolchain. Follow-ups:
|
|
Lead (perf lead agent): this PR's squash dc8a4a4 made the feat-cmux-next arch ratchet red: CmuxNextApp Swift lines +84 at 6be2728 (+128/-34 in Sources/CmuxNextApp from this commit). Revert-first rule: revert PR #30405 is open. To re-land, move the new Cloud link / app-server logic out of CmuxNextApp into a package (CmuxNextCloud or the owning package) so CmuxNextApp does not grow, and open the re-land PR with the move. |
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Every signed cmux NEXT build now talks to NEXT Cloud by default. That covers signed NEXT DEV (
com.cmuxterm.app.debug.next) and NEXT nightly (com.cmuxterm.app.nightly.cmux-next). There is no staged flag, no DEV-only default and no Labs gate.Leo, 2026-10-31: "but there's not really a point to be so baby gloves with a 'cutover' literally we're the only ones using cmux-next's cloud rn". Earlier, on this PR: "you need to do all that stuff we do not care about classic we care about our new cloud".
What a NEXT build uses now
For both bundle ids (
CloudConfiguration.nextCloudChannels):.appServer/v1/ops,/v1/read,/v1/auth/*,/v1/cloud/*)https://cmux-api-development.debussy.workers.dev454ecd03…throughhttps://cmux-staging.vercel.appcmux-next-dev://auth-callback(#28909); nightlycmux-next://auth-callback(its existing scheme, already inNATIVE_SCHEMES)cmux.auth.*defaults keys suffixed with the staging project id. The first launch never reads the old production session, and that session stays untouchedThe endpoint, auth and link environment overrides stay ignored on these signed channels.
Machine actions on the app server link
Before this PR,
CloudService's Kill, Pause, Resume, Rename and idle pause still went to the classic/api/vmclient, where a Worker machine has no record. They now run the app server ops (cloud.machine.delete,.pause,.start,.rename,.idle_policy.set) through the same approval loop as the other person-started ops. The first-party Cloud page already did this. Sharing was already hidden for link machines. The router-review BLOCK at 744b992 found this.Why the development pair
cmux-api-developmenthasPLATFORM_MACHINES=onand the agent gateway, and cmux-platform-development binds itsCloudDO,UserDOandTeamDObyscript_name, so they share one state. The development platform verifies tokens fromcmux-api-development's JWKS, so the token this Worker mints is accepted on the platform's own routes./v1/workspaces/{id}/machine(cmux-platform#262) and/v1/machines/pick(fix: disable Sentry HTTP client error capture for browser panels #261) answer 401 (route present, token needed) on cmux-platform-development. They answer 404 on cmux-platform-staging and cmux-platform-production.PLATFORM_SURFACESor aPLATFORMbinding (backend/apps/api/wrangler.jsonc), so the forwarder from api: platform forwarder behind PLATFORM_SURFACES (port plan 1d), default off #29400 is off everywhere. Production cmux-api has noPLATFORM_MACHINES, and cmux-platform-production binds nothing. A production cutover would take several infra PRs and new secrets, so nightly uses the same development pair as DEV.What changes for nightly users
CLOUD_ALLOWED_TEAMSon that Worker.Unchanged
com.cmuxterm.app,.nightly,.rcand.debug.com.cmuxterm.app.nightly,nightly-next-legacy-identity.sh) and the Stable copy (com.cmuxterm.app.nightly.cmux-next-stable) also keep production and the legacy link.No capture: configuration-only change, no UI layout.
Validation
CloudConfigurationSignedDEVTestscovers:CloudSignedDEVAuthPersistenceTestscovers the namespaced storage. Fleet results for the exact head are in the comments below.Not run: a live signed-app sign-in.
Changelog
Agent session: agent session
🤖 Generated with Claude Code