Skip to content

fix(cloud): refuse auth and placement denials on first Cloud send (W2-01) - #30776

Closed
teamleaderleo wants to merge 7 commits into
feat-cmux-nextfrom
w2-01-cloud-denied-ensure-fail-closed
Closed

teamleaderleo wants to merge 7 commits into
feat-cmux-nextfrom
w2-01-cloud-denied-ensure-fail-closed

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

W2-01 — Preserve platform authorization and placement during first Cloud send

Part of zero-setup Cloud inquiry W2-01 and Cloud owner #5846.

Problem

A first personal-repository Cloud send calls POST /v1/workspaces/{workspace}/machine. Previously the client made_no_machine treated HTTP 401/403, arbitrary 404, and workspace_machine.not_admitted as an invitation to try a different App-created Cloud machine. This turned explicit identity, resource, or capacity refusals into a second machine-creation attempt.

The backend WorkspaceMachines.ts emits workspace_machine.not_admitted when its durable placement reserves no machine due to budget, cap, or no matching offer. The successful fix for the specific development no-offers cause, platform #397 (merged 22cc687df1f6ebd96bf3394357aebc4e2c10192d), now accepts the Freestyle provider's memoryPause:false offers. Deploy/live verification is still required before declaring development hot start healthy.

Change (two Rust files)

  • An empty platform token skips the call entirely and keeps the existing legacy App-create fallback (a platform request was never attempted).
  • A real HTTP 401/403, regardless of error code, stops the send with the platform refusal.
  • A typed 404, such as a missing chosen Cloud environment/snapshot, also stops the send. Generic endpoint-absent 404 (empty or not_found code) still falls back for older platform endpoints.
  • workspace_machine.not_admitted now stops the send; no alternate machine creation may evade the denied admission decision.
  • workspace_machine.unconfigured remains the intentional compatibility fallback for deployments without a configured workspace-machine base.

Regression cases

Extended the existing fake-platform plan_makes_a_personal_repository_sends_machine_through_the_platform test:

  • generic 404 and empty local token still return the App-create path;
  • HTTP 401, 403, 401/403 with fallback-looking codes, typed 404, and 503 workspace_machine.not_admitted return a refused result with no new_name;
  • keeps the existing same-key pinned machine retry test.

Status / ownership

Draft / HOLD pending exact-head review, CI, and confirmation of the platform #397 deployment/provider readback. No local Rust toolchain is installed in this execution environment, so no local cargo test is claimed. CI workflows were queued at the last check. No machine, credential, production deployment, or existing owner branch was changed.

This PR works on a separate branch from the Cloud seed integration #30655, which touches the same test/source files for a different behavior; rebase and inspect exact-head diffs before landing. The environment editor #30359 still needs to forward selected environment on first send; a focused W2-01 review note covers intentional environment-vs-fallback cases.

Remaining acceptance

Run cargo test -p cmux-tui start_chat, lint and an authorized DEV probe: after platform #397 is deployed, request a personal GitHub workspace machine, verify the real provider returns offers and the first task runs in its seeded directory. Avoid interpreting merged source as proof of deployment. If compatibility for a temporary no-offers failure is needed, introduce an explicit server provider_unavailable error rather than reusing an admission refusal.

@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Nov 1, 2026
@teamleaderleo teamleaderleo changed the title fix(cloud): preserve platform auth denials during first-send fallback (W2-01) fix(cloud): refuse auth and placement denials on first Cloud send (W2-01) Nov 1, 2026
@blacksmith-sh

blacksmith-sh Bot commented Nov 1, 2026

Copy link
Copy Markdown

Found 3 test failures on Blacksmith runners:

Failures

Test View Logs
nightly must build and hand off the macOS 26 helper and Xcode 26.5 app before publishin
g/
nightly must build and hand off the macOS 26 helper and Xcode 26.5 app before publishin
g
View Logs
test_helper_never_takes_a_hosted_mac_and_skips_compile_on_hit (main.WorkflowTests.t
est_helper_never_takes_a_hosted_mac_and_skips_compile_on_hit)/
test_helper_never_takes_a_hosted_mac_and_skips_compile_on_hit (main.WorkflowTests.t
est_helper_never_takes_a_hosted_mac_and_skips_compile_on_hit)
View Logs
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)/
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)
View Logs

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

@github-actions

github-actions Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

web and size checks: green

@teamleaderleo
teamleaderleo force-pushed the w2-01-cloud-denied-ensure-fail-closed branch from a549503 to 4465ee3 Compare November 2, 2026 01:02
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by an agent session · session

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Closing this draft under the connector-draft cleanup. Its own body holds landing pending deployment and live provider readback for cmux-platform #397. That PR is merged, but its available receipts establish source review and CI, not a deployed provider returning offers or a successful first task in its seeded directory. Clearing that hold would claim evidence we do not have.

The authorization/admission fix remains useful and is preserved on this branch, rebased onto feat-cmux-next at 4465ee37bbb6c15531ead7829f2661796a581d38. Reopen when the Cloud owner can link the deployed revision, real provider-offer readback, and successful first-send outcome, then finish exact-head tests and review. The focused fleet run was submitted as 41370328283; no passing result is claimed.

Independent router review at the rebased head also found that the typed-404 protection is incomplete: machine_join::known_code() reduces unknown wire error codes (including the test's machine.snapshot.not_found) to the empty string, which made_no_machine() treats as a compatibility fallback. The test injects an already-decoded error, so it misses this path. A replacement needs to preserve the presence of an unknown typed code through HTTP decoding and cover that path. The review was not posted because this session's GitHub quota refused the write.

Outstanding acceptance belongs with W2-01 / #5944 and Cloud owner #5846.

Copy link
Copy Markdown
Collaborator Author

W2-01 closure follow-up — exact CI failure and decoder gap (source + logs reviewed)

I checked the closure comment, the rebased head 4465ee37bbb6c15531ead7829f2661796a581d38, focused run 41370328283, the machine_join fake HTTP tests, and current feat-cmux-next source. No code or deployment changed; this PR stays closed under its owner's HOLD.

The focused run's red was a test-invocation error, not a Rust assertion failure. The run's checks job (125040050286) set FAST_CHECKS_COMMAND=cargo test -p cmux-tui --lib link::start_chat_cli and FAST_CHECKS_DIRECTORY=.. Cargo immediately answered:

error: could not find `Cargo.toml` in .../.fast-checks-checkout or any parent directory
FAST_CHECKS_RECEIPT ... "exit_code": 101

Zero Rust tests executed in that run. The correct directory is cmux-tui/, or use cargo test --manifest-path cmux-tui/Cargo.toml -p cmux-tui --lib link::start_chat_cli from the repo root. The repository's cmux-tui/AGENTS.md recommends its hosted verifier, e.g. ./scripts/verify-cmux-tui-hosted.sh --filter plan_makes_a_personal_repository_sends_machine_through_the_platform, from a trusted checkout of the exact pushed SHA. GitHub PR workflows for the rebased head mostly report success, but those are not the missing targeted Rust test receipt.

The reported typed-404 hole is real. machine_join.rs call_with_timeout extracts the server's error code and calls known_code. known_code and its allowlist collapse unknown present codes to "", identical to a response with no code. The closed PR's made_no_machine treats HTTP 404 + "" as an absent endpoint and falls back to App create. The fake EnsureCall regression injected machine.snapshot.not_found after decoding and so missed this path.

Minimal reviewed follow-up: preserve the distinction unknown present server code vs absent/generic code, while keeping the existing safe allowlist for displayed error codes. For example, decode any non-empty unrecognized code to a fixed static sentinel like "platform.unknown_error_code" (avoid reflecting arbitrary server text into CLI diagnostics), leave None/"" as blank, retain recognized generic not_found, and preserve 401/403 precedence. Add an HTTP loopback fixture using existing cli/machine_join/tests.rs fake(handler): POST ensure returning (a) bare 404, (b) 404 with {"code":"not_found"}, (c) 404 with {"code":"machine.snapshot.not_found"}, (d) 404 with an unknown future code. Confirm only (a)/(b) are eligible for the compatibility fallback, (c)/(d) are refused. Recheck callsites of known_code before making this a shared decoder behavior.

Landing gate: retain the closure's explicit requirements—owner links a deployed platform revision and real provider-offer readback, records one successful repository-seeded first-send outcome, and obtains exact-head focused Rust tests + review. Platform #397 has a merge/CI SHIP, but this source inspection found no complete provider-and-repository first-send readback. Recent Cloud item-14 run has successful no-folder Cloud replies while repo actions remain blocked by approvals; these are distinct outcomes.

The original W2-01 finding also identified repo/environment affinity on reused machines; that product decision remains separate from this narrow authorization repair.

Ownership: existing PR owner/session remains named in comment 6566587273. This comment does not reopen the held PR, push to the owned branch, or request new coordinator dispatch.

Copy link
Copy Markdown
Collaborator Author

W2-01 backend follow-through: cmux-platform PR #513 now implements the admission distinction on the platform while this cmux client PR stays closed.

The platform's POST /v1/workspaces/:workspace/machine now distinguishes:

  • full machine slots → workspace_machine.machine_slots_full (503);
  • unavailable spending allowance → workspace_machine.usage_unavailable (503);
  • raced placement reservation → workspace_machine.admission_changed (503), same-key retryable;
  • no compatible provider offer → retains workspace_machine.not_admitted (503), on purpose, because existing cmux clients currently use that exact code for the legacy creation fallback. The internal placement decision still identifies no_compatible_offer for a future negotiated client contract.

This removes the quota/spend admission ambiguity at the source and preserves old-client no-offer recovery, independent of #30776's unshipped decoder patch. Tests cover all four cases; platform CI run 41429797088 and 41430264286 passed on their earlier exact heads. The final compatibility head 598bb53c37314ff8c95ad3838f3118ca2d65f909 is being checked separately.

The client-side unknown-typed-404 decoder issue and the live repository-seeded first-task readback remain separate. No merge/deploy here, and this closed branch is untouched.

This branch was previously deployed

3 inactive deployments
artifacts — 4465ee37 Deployed Nov 2, 2026 by teamleaderleo via publish tree-addressed cmux-tui #98125
sentry-dsyms — 4465ee37 Deployed Nov 2, 2026 by teamleaderleo via upload cmux-tui dSYMs to Sentry #98125
ci-routing-agent — 4465ee37 Deployed Nov 2, 2026 by teamleaderleo via cmux-tui tree preflight #98125
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant