Bind remote Cloud repository frames to the surface chat

Closed
TE
6d ago
+583-52

A linked Mac could send a Cloud repository action with any chat session, even when the frame named a different surface. Require remote list/add/attached/wait frames to name the session currently bound to their surface, using the same stored lookup as agent-session attach. Refused requests return remote_denied before repository work starts. Local CLI and agent credential behavior remain unchanged, and catalog sync remains unscoped.

Part of #30628. The peer-picked Cloud route is a separate follow-up; it must resolve a real machine surface and its session before advertising Add repository. Existing Cloud-button clients already send both fields.

Tests cover matching frames, a different/missing session, missing/unknown/unbound/malformed surfaces, a surface rebound to a new session, sync, and existing credential/revocation behavior. Validation: focused cmux-tui-core repository frame tests through cmux-ci (result follows).

Agent session: agent session


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


Summary by cubic

Binds Cloud repository actions to the chat session that legitimately owns them. Previously a linked Mac could send repository actions for any chat session; now mismatched frames are refused with remote_denied before any repository work starts, and agent tools fail closed when the proven caller is missing or different. Existing Cloud-button clients already send both the surface and session fields.

Session binding

  • The daemon reports the verified caller session ID in initialize, and the acpmux handshake verifies agent MCP tools run only for the proven session.
  • Agent tools receive ACPMUX_SESSION_ID so they always address the authenticated chat; repository tools fail closed when the proven caller is missing or mismatched, inviting a chat restart.
  • CLI repo requests attach a launch credential scoped to the same chat; local-user CLI access, agent credential behavior, and linked-Mac sync are unchanged.
  • Catalogs are not session-scoped, so cloud.repo.sync remains unrestricted.

Link validation and recovery

  • Every GitHub installation link is validated (strict HTTPS github.com, no credentials or non-default port) everywhere it's rendered; a trusted Mac-cached link wins over connector and seed responses, and unsafe links become seed.bad_request with no URL exposed.
  • Unlinked repo.needs_github connector errors now recover like connect; new seed.checkout_failed, seed.unknown_job, and seed.unavailable codes carry specific retry guidance.
  • cloud.repo.attached now returns running jobs in pending with phase and progress; successful clones retain optional LFS notes.