Skip to content

fix: the browser's approval reaches onboard on Windows (1.7.1) - #167

Merged
bitpshr merged 4 commits into
mainfrom
paul/windows-loopback-fix
Oct 22, 2026
Merged

bitpshr merged 4 commits into
mainfrom
paul/windows-loopback-fix

Conversation

@bitpshr

@bitpshr bitpshr commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary

On Windows, about 1 in 10 onboard Authorize clicks never reaches the CLI. The page creates and copies a key, but the redirect to localhost doesn't arrive, and most people then make a key by hand. I reproduced it on a windows-latest runner (Chrome 155, Edge 155) with the released 1.7.0. The listener onboard borrowed from auth login loses the callback in four ways:

  • It listens only on the first address localhost resolves to. If another program already holds [::1]:8484, it quietly takes 127.0.0.1:8484. Browsers dial [::1] first, so the redirect goes to that program.
  • Two sign-ins (say from another shell, user or sandbox) end up on one port, one per address. The approval goes to the older one.
  • A callback carrying another sign-in's state, such as an old tab from an earlier connect, ends the sign-in that's waiting. The right tab then gets "connection refused".
  • Agents that run commands in a Windows Job Object kill the background sign-in when they end the job. Codex does this when a command is interrupted or times out.

It also waits on one connection at a time with no time limit, and gives up after 8 that aren't the callback.

So onboard now has its own listener in workflow/loopback.rs:

  • It listens on 127.0.0.1 and [::1], on the first registered port where neither is taken.
  • It reads each connection on its own, with a 10 s limit, to the end of its headers.
  • A callback for another sign-in gets the error page ("This approval is from an earlier sign-in…"), and the wait goes on.
  • An error callback without a state no longer ends the sign-in. Neither the approval page's Deny nor the server's error redirects ever send one, so it could only come from some other page or program, which could end the sign-in or put its own text in the agent's reply. It gets the error page like any other callback that isn't ours.

On Windows the worker leaves the agent's Job Object when the job allows it.

Token storage, the redirect URIs and the worker's replies are unchanged. auth login still uses the generated listener. A CLI can't replace that flow today, so the new module is written so auth login can switch to it later.

The Windows smoke test now holds [::1]:8484 with another program before it starts, checks that the sign-in moved to 8483, and sends Deny with its state the way the page does. Bumps the version to 1.7.1, and rustls-webpki to 0.103.16: audit now flags 0.103.15 (RUSTSEC-2026-0382), on main too.

Testing

  • Windows probe on a windows-latest runner: 40 scenarios with real Chrome and Edge, before and after.
    • 1.7.0 misses the callback with another program on [::1]:8484, with an older sign-in waiting, with an old tab approved first, after the agent terminates its job, and after 8 empty connections. One idle connection held it for 10 s.
    • This branch gets it through in every case.
    • The one exception is a job that forbids breaking away; no process can leave one.
  • cargo test: the new listener tests and the 25 onboard integration tests pass on macOS. The Windows code type-checks for x86_64-pc-windows-msvc.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unexpected binding failures can still leave an IPv4-only listener while another program owns the matching IPv6 port, allowing browser callbacks to reach the wrong program.

1 open issue
What changed in this PR

This PR improves browser approval delivery for onboard, replacing its generated callback listener while leaving auth login unchanged.

Changes:

  • Adds dual-loopback binding, concurrent request reads, and stale-callback handling.
  • Lets Windows sign-in workers leave Job Objects when permitted and extends the Windows smoke test.
  • Releases version 1.7.1 and updates rustls-webpki to 0.103.16.
File Description
cli/​elevenlabs/​workflow/​onboard/​session.rs Adds Windows worker breakaway with fallback.
cli/​elevenlabs/​workflow/​onboard/​auth.rs Routes onboarding through the new sign-in implementation.
cli/​elevenlabs/​workflow/​mod.rs Registers the loopback module.
cli/​elevenlabs/​workflow/​loopback.rs Implements callback handling, token exchange, and regression tests.
Cargo.toml Bumps the CLI version to 1.7.1.
Cargo.lock Updates CLI and rustls-webpki versions.
.github/​workflows/​windows-smoke.yml Checks port fallback when IPv6 port 8484 is occupied.

Review effort: Balanced

Comment thread cli/elevenlabs/workflow/loopback.rs Outdated
@bitpshr
bitpshr added this pull request to stack #172 October 22, 2026 12:56
@PaulAsjes
PaulAsjes requested a balanced review from Copilot October 22, 2026 14:39

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The replacement OAuth flow and Windows Job Object handling require final human validation of platform-specific authentication behavior.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@bitpshr
bitpshr merged commit ef42456 into main Oct 22, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants