fix(stalker): stop discovery when an abandoned auth outlives its drain

Cancellation is cooperative — the PWA fetch takes no signal and the Electron
main process runs its request to completion — so the bounded drain is a hope,
not a guarantee. An attempt still unsettled after its 65 s budget plus the
15 s drain may yet land a get_profile, which adopts the MAC's token
portal-side; advancing staked the next candidate's freshly issued session on
that never happening. The rejection now reports it and the candidate loop
stops, preferring a retryable "could not confirm" over a session that looks
established and dies later.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Fable 5 committed 2026-08-03 22:23:05 +02:00
1 parent a0bfc28dc7
commit 41e2a6a751
3 files changed
+97 -3

No files matched your search

+12
View File
@@ -382,6 +382,18 @@ dispatched — which the check cannot cover, but sequencing can: discovery
the next candidate, instead of racing it. The request cannot be un-sent, but
nothing forces us to have a competing session in flight while it lands.
**A drain that times out stops discovery.** Draining is bounded, and the bound
has to mean something: an attempt still unsettled after its own 65 s budget
plus the 15 s drain is one no transport can recall — the PWA `fetch()` takes no
signal at all, and the Electron main process runs its HTTP request to
completion. Advancing anyway would stake the next candidate's freshly issued
session on that request never landing. So the rejection carries
`abandonedInFlight` and the candidate loop returns instead of probing on,
preferring an honest "could not confirm this portal" the user can retry over a
session that looks established and dies later. It costs nothing in the normal
case: an aborted attempt settles as soon as its in-flight request errors out,
so the drain returns at once and the loop continues.
The budget itself covers the longest real flow: a status-2 portal costs four
sequential requests (handshake, profile, `do_auth`, profile retry) and the
Electron transport allows each 15 s, so a two-request budget would have failed