Problem
After PR #229 swapped the webui token from sessionStorage to localStorage, the dashboard loses a recovery affordance that was previously implicit in sessionStorage's tab-close lifetime.
Pre-PR behaviour: if the server-side ~/.claude/claudeclaw/web.token was rotated (operator deletes the file → daemon restart → getOrCreateWebToken at src/ui/auth.ts:22 mints a new one), the operator's next browser open found an empty sessionStorage, hit the "Web token required" banner, and pasted the fresh token. Recovery was automatic.
Post-PR behaviour: localStorage retains the stale token across browser restarts. The window.fetch wrapper in src/ui/page/script.ts blindly attaches the stale Authorization: Bearer …, the server responds 401 to every /api/* call, and nothing in the UI re-shows the banner or clears the bad token. The operator sees a permanently "Offline" dashboard with no in-UI recovery path — they have to either:
- Open DevTools and run
localStorage.removeItem("ccaw_web_token"), or
- Manually open the dashboard URL with a fresh
?token=… query param
Trigger frequency
Low today — rotation is a manual operator action (delete web.token + restart daemon). But it does happen, and the failure mode is silent until the operator notices the dashboard is broken.
Proposed fix
In the window.fetch wrapper around src/ui/page/script.ts:40-62, when a same-origin /api/* call returns 401:
if (isApi && res.status === 401) {
try { localStorage.removeItem("ccaw_web_token"); } catch (e) {}
showTokenBanner();
}
return res;
This restores the recovery affordance without giving up the persistence UX win from PR #229.
Scope
- Single-site change in the inline dashboard script.
- No server-side changes needed (the 401 response is already correct).
- No test coverage today for the inline script; manual smoke is: paste a bad token via
?token=BAD → confirm banner re-appears + Authorization header stops being sent on subsequent /api/ calls.
Out of scope
Related
Problem
After PR #229 swapped the webui token from sessionStorage to localStorage, the dashboard loses a recovery affordance that was previously implicit in sessionStorage's tab-close lifetime.
Pre-PR behaviour: if the server-side
~/.claude/claudeclaw/web.tokenwas rotated (operator deletes the file → daemon restart →getOrCreateWebTokenatsrc/ui/auth.ts:22mints a new one), the operator's next browser open found an empty sessionStorage, hit the "Web token required" banner, and pasted the fresh token. Recovery was automatic.Post-PR behaviour: localStorage retains the stale token across browser restarts. The
window.fetchwrapper insrc/ui/page/script.tsblindly attaches the staleAuthorization: Bearer …, the server responds 401 to every/api/*call, and nothing in the UI re-shows the banner or clears the bad token. The operator sees a permanently "Offline" dashboard with no in-UI recovery path — they have to either:localStorage.removeItem("ccaw_web_token"), or?token=…query paramTrigger frequency
Low today — rotation is a manual operator action (delete
web.token+ restart daemon). But it does happen, and the failure mode is silent until the operator notices the dashboard is broken.Proposed fix
In the
window.fetchwrapper aroundsrc/ui/page/script.ts:40-62, when a same-origin/api/*call returns401:This restores the recovery affordance without giving up the persistence UX win from PR #229.
Scope
?token=BAD→ confirm banner re-appears + Authorization header stops being sent on subsequent /api/ calls.Out of scope
Related