Problem
handleAuthError() treats HTTP 503 exactly like an expired session and navigates the whole page to /login:
internal/webui/templates/scripts/dashboard_core.templ:247-254 — if (response.status === 401 || response.status === 503) { window.location.href = '/login'; }
Every dashboard fetch call site routes through this helper. But 503 is never an auth signal in this app — it is emitted for transient infrastructure states:
internal/webui/handlers/dashboard_handlers.go:116 — "Dashboard cache not ready" (webui just restarted, cache not yet warmed)
dashboard_handlers.go:1437 and 7 similar sites — "Backend service not available" (backend restart/outage; comments, acks, history, presets)
LoginPage does not redirect already-authenticated users back to the dashboard (internal/webui/handlers/handlers.go:405-415), so the user lands on a real login form while holding a perfectly valid session cookie.
Note the newer global fetch interceptor (dashboard_core.templ:257-281) got this right: it redirects on 401 only.
Impact
- Every webui deploy logs out every open dashboard: during cache warm-up, the first
loadDashboardData() poll gets a 503 and the page self-navigates to /login.
- Backend blips hit users at the worst moment: during a backend restart or overload — typically mid-incident — opening an alert modal or posting a comment 503s and throws the on-call engineer out of the dashboard to a login form. If the backend is still down, their re-login also fails, which reads as "wrong password" and adds confusion to an incident.
- Filter state in the URL is lost on the bounce (login redirects to
/dashboard).
Proposed approach
In internal/webui/templates/scripts/dashboard_core.templ (regenerate with make webui-templates):
- Restrict
handleAuthError() to response.status === 401, matching the fetch interceptor.
- Treat 503 as a transient failure at the call sites' existing error paths (they already keep current data and retry on the next poll cycle); optionally surface a small "backend temporarily unavailable" banner, but the minimal fix is just dropping 503 from the redirect condition.
Acceptance criteria
Problem
handleAuthError()treats HTTP 503 exactly like an expired session and navigates the whole page to/login:internal/webui/templates/scripts/dashboard_core.templ:247-254—if (response.status === 401 || response.status === 503) { window.location.href = '/login'; }Every dashboard fetch call site routes through this helper. But 503 is never an auth signal in this app — it is emitted for transient infrastructure states:
internal/webui/handlers/dashboard_handlers.go:116— "Dashboard cache not ready" (webui just restarted, cache not yet warmed)dashboard_handlers.go:1437and 7 similar sites — "Backend service not available" (backend restart/outage; comments, acks, history, presets)LoginPagedoes not redirect already-authenticated users back to the dashboard (internal/webui/handlers/handlers.go:405-415), so the user lands on a real login form while holding a perfectly valid session cookie.Note the newer global fetch interceptor (
dashboard_core.templ:257-281) got this right: it redirects on 401 only.Impact
loadDashboardData()poll gets a 503 and the page self-navigates to/login./dashboard).Proposed approach
In
internal/webui/templates/scripts/dashboard_core.templ(regenerate withmake webui-templates):handleAuthError()toresponse.status === 401, matching the fetch interceptor.Acceptance criteria
/login; data loads once the cache is ready./login.