Summary
Three defects around the device-login step in the installer. None is the "code expired instantly" bug originally suspected — that was investigated and disproven (measured 10 min 01.9 s against a 10-minute DEVICE_CODE_TTL; the poll loop and OAuth error mapping are spec-correct, including slow_down → interval += 5 per RFC 8628 §3.5). These are what the investigation turned up alongside it.
1. Any transient error aborts the entire install
internal/cli/auth.go:174-176 — the poll loop's default: branch is terminal. authorization_pending and slow_down are retried; anything else, including a transient network error, ends the run. One DNS hiccup inside a ten-minute window kills an installer run that had already completed steps a–c.
This is the real robustness gap: the failure window is long, human-paced, and the retry policy covers only the two OAuth states while treating infrastructure blips as fatal.
2. Sign-in is not retryable in place
A missed or expired code costs a full installer re-run — common.sh:212 is error() { …; exit 1; } and provision.sh:175 has no loop around the login call.
The pattern already exists in the same file: provision.sh:289 retries the name prompt three times, with a comment explaining why an empty read must not abort the install. The step with a hard ten-minute deadline got no such treatment. One in-place "press Enter for a fresh code" retry would remove the whole class.
3. The recovery advice contradicts itself
The CLI prints re-run tracebloc login`` (auth.go:171); the installer immediately overrides with `re-run the installer` (`provision.sh:175`). Under the installer the CLI's advice is actively wrong — a bare `tracebloc login` leaves steps e and f undone.
4. Copy: the message never says how long the code was valid
the sign-in code expired gives no duration. A user who stepped away for a few minutes reads a ten-minute timeout as an instant failure — which is exactly how this was first reported. Naming the window ("codes are valid for 10 minutes") turns a confusing failure into an obvious one.
Suggested scope
(1) and (2) are the substantive ones and belong together — retry transient errors inside the poll, and make the sign-in step retryable in place rather than fatal to the whole run. (3) and (4) are one-line copy fixes that can ride along.
Summary
Three defects around the device-login step in the installer. None is the "code expired instantly" bug originally suspected — that was investigated and disproven (measured 10 min 01.9 s against a 10-minute
DEVICE_CODE_TTL; the poll loop and OAuth error mapping are spec-correct, includingslow_down→interval += 5per RFC 8628 §3.5). These are what the investigation turned up alongside it.1. Any transient error aborts the entire install
internal/cli/auth.go:174-176— the poll loop'sdefault:branch is terminal.authorization_pendingandslow_downare retried; anything else, including a transient network error, ends the run. One DNS hiccup inside a ten-minute window kills an installer run that had already completed steps a–c.This is the real robustness gap: the failure window is long, human-paced, and the retry policy covers only the two OAuth states while treating infrastructure blips as fatal.
2. Sign-in is not retryable in place
A missed or expired code costs a full installer re-run —
common.sh:212iserror() { …; exit 1; }andprovision.sh:175has no loop around the login call.The pattern already exists in the same file:
provision.sh:289retries the name prompt three times, with a comment explaining why an empty read must not abort the install. The step with a hard ten-minute deadline got no such treatment. One in-place "press Enter for a fresh code" retry would remove the whole class.3. The recovery advice contradicts itself
The CLI prints
re-runtracebloc login`` (auth.go:171); the installer immediately overrides with `re-run the installer` (`provision.sh:175`). Under the installer the CLI's advice is actively wrong — a bare `tracebloc login` leaves steps e and f undone.4. Copy: the message never says how long the code was valid
the sign-in code expiredgives no duration. A user who stepped away for a few minutes reads a ten-minute timeout as an instant failure — which is exactly how this was first reported. Naming the window ("codes are valid for 10 minutes") turns a confusing failure into an obvious one.Suggested scope
(1) and (2) are the substantive ones and belong together — retry transient errors inside the poll, and make the sign-in step retryable in place rather than fatal to the whole run. (3) and (4) are one-line copy fixes that can ride along.