rdmsm4x-changelog-20260903-2131-remote-control-403-stale-bridge-records
rdmsm4x-changelog-20260903-2131-remote-control-403-stale-bridge-records
[2026-09-03 21:31:34 EDT · rdmsm4x] · session 158c9525 (notes-republish-pending-changelog) · work window 20:51–21:31 EDT
Summary: /rc ("Remote Control") failed
with HTTP 403 in every resumed Claude Code conversation on
the fleet because the Remote Control server moved new sessions to an
"elevated" security tier this afternoon and refuses to re-attach the
older "standard" ones; cleared the stale reconnection records on five
Macs with a new script so resumes mint fresh sessions, proved the fix on
rdmsm4x, filed INC-20260903-03.
Scope
- Hosts changed: rdmsm4x (hub), rdmbair13m5, rdmbair15m5, rdmpw3265m, rdmpw3275m.
- Not changed: jdmbair13m5 (SSH
Permission denied (publickey), needs a console login first; script not installed there yet).
Root cause (verified)
- Symptom line in the transcript:
Remote Control disconnected — Remote Control server rejected the request (HTTP 403) — run /remote-control to retry. First seen 20:02:54 EDT; every/remote-controlretry repeated it. Fleet Macs all haveremoteControlAtStartup: true, so every resumed conversation failed. - Debug log of a resume
(
claude --resume <id> --debug-file …):[bridge:repl] Reattaching to persisted bridge session cse_… (fresh-mint fallback, restored_owner_match)→[code-session] /bridge failed 403: Permission denied(source=origin). The CLI then stops; the announced fresh-mint fallback does not fire on a 403. - API
GET /v1/code/sessions/<id>shows every session created before ~13:00 EDT atsecurity_tier: standardand every session created from at least 17:11 EDT atsecurity_tier: elevated.POST …/bridgeon an elevated session with only the OAuth bearer answerselevated session requires a trusted device(resource: untrusted_device); on a standard session it answers a barePermission denied. Claude Code presents a device attestation (DEVICE_ATTESTATION_STATUS_VERIFIED_KEYLESS_DEVICEin the event stream) so new sessions work. - Positive controls:
claude remote-controlin~/dev/fleetandclaude --remote-controlin~/devboth registered and connected at once (tier elevated). Account state is fine:claude auth statuslogged in, max plan, token valid, status.claude.com all operational. - Not the cause: OAuth scopes (unchanged, includes
user:sessions:claude_code), proxy/VPN (none), Claude Code release notes 2.1.253–2.1.260 (no Remote Control auth change).
Fix
- New
~/scripts/claude_rc_reset.zshv1.0.0 (sha25617e7fb3cce50fdca…), installed on the five reachable Macs and snapshotted to~/dev/fleet/tooling/host-scripts/<host>/.check: classifies every conversation that carries abridge-sessionrecord by asking the API for the session's tier (read-only).apply [<sid>…]: for idle conversations whose record isstandard, copies the transcript to~/.claude/backups/rc-reset-<stamp>/<project>/and appends Claude Code's own clear record{"type":"bridge-session","sessionId":…,"bridgeSessionId":"","lastSequenceNum":0}(the same line the CLI'sclearBridgeSession()writes), then re-reads the last record to verify. Running conversations are refused because the CLI rewrites the record every turn. Unknown API answers fail closed.after-exit <pid> <sid>: waits for a running conversation to exit, then clears it.CLAUDE_RC_RESET_ASSUME_STALE=1lets a watcher armed over SSH (no keychain) proceed on the caller's classification.- Over SSH the hub token is piped through stdin
(
T=$(cat); CLAUDE_RC_RESET_TOKEN="$T" …); the value is never printed.
- Proof on rdmsm4x: after clearing conversation 27c29282,
claude --resumelogged[remote-bridge] Created session cse_01DwcRJXGrHkhMne43Rm8EE8,v2 transport connected,Flushing 200 history events; the API reports that sessionelevated.
Numbers
| Host | records | cleared | still stale (running) | notes |
|---|---|---|---|---|
| rdmsm4x | 75 | 69 | 3 | 3 elevated kept; watchers on pids 3241, 59861, 91560 |
| rdmbair13m5 | 6 | 5 | 1 | watcher on pid 20323 |
| rdmbair15m5 | 27 | 25 | 2 | watchers on pids 72112, 31740 |
| rdmpw3265m | 10 | 10 | 0 | |
| rdmpw3275m | 22 | 22 | 0 | |
| jdmbair13m5 | ? | 0 | ? | unreachable |
Commands run (representative)
~/scripts/claude_rc_reset.zsh check
~/scripts/claude_rc_reset.zsh apply 27c29282 # test conversation
~/scripts/claude_rc_reset.zsh apply # all idle stale on the host
nohup ~/scripts/claude_rc_reset.zsh after-exit 3241 158c9525-… > ~/Library/Logs/claude-rc-reset/after-exit-3241.log &
printf '%s' "$TOK" | ssh <spoke> 'T=$(cat); CLAUDE_RC_RESET_TOKEN="$T" /Users/richh/scripts/claude_rc_reset.zsh apply'
Verification
checkafterapply: rdmsm4xstale=3(all three running), rdmbair13m5stale=1(running), rdmbair15m5stale=2(running), rdmpw3265mstale=0, rdmpw3275mstale=0.- Script sha256 matches on all five hosts
(
17e7fb3cce50fdca). - Watcher processes confirmed alive with the intended arguments on all
three hosts; logs show
waiting for pid …. - Spoke resume mint could NOT be exercised over SSH (Claude Code has
no usable login without the console keychain:
[bridge:repl] Skipping: bridge not enabled). The record clearing is verified there; the mint is proven on rdmsm4x only.
Outstanding (owner: Rich)
- Exit and resume the running conversations to pick up the fix: on
rdmsm4x the sessions named notes-republish-pending-changelog, dev-49,
dev-33; on rdmbair13m5 pid 20323; on rdmbair15m5 pids 72112 and 31740.
The watcher clears the record within seconds of the exit; the next
claude --resumestarts Remote Control fresh with history. - jdmbair13m5: log in at the console once, then from rdmsm4x:
ssh jdmbair13m5 'cat > /Users/richh/scripts/claude_rc_reset.zsh' < ~/scripts/claude_rc_reset.zshand runcheck/applywith the piped token as above. - The always-on
net.dataroo.claude-rcservice on rdmsm4x still serves standard-tier sessions and is connected (phone presence live at 21:00). Its children refreshed tokens after the tier change without dropping, so it was left alone. If it does drop:bash ~/scripts/claude_rc_service.sh restart. - Ticket INC-20260903-03 stays open until
checkreportsstale=0on all six hosts.
Traps met this session (recorded)
scp -q file host:scripts/xreturned 0 and wrote nothing on four spokes;ssh host 'cat > /abs/path' < fileplus a remoteshasumis the install method that verifies itself.- zsh does not word-split
set -- $pair; the first watcher launch started with one argument (memoryzsh-no-word-splitting). - The interactive shell here has
grepaliased to a missingugrepandNO_BARE_GLOB_QUALset; use/usr/bin/grepand explicit paths.
Backups / undo
- Every modified transcript has a same-name copy under
~/.claude/backups/rc-reset-<stamp>/<project>/on the host that was changed. Undo = copy it back (or delete the single appended last line). - No secrets in this record. The OAuth token was read from the login keychain into a shell variable and sent only as a request header.