# Replace SD Qualifier dashboard refresh with SSE

Status: abandoned
Type: campaign
Updated: 2026-08-14
Next Action: none
Campaign ID: 001-replace-sd-qualifier-dashboard-refresh-with-sse
Campaign Number: 001
Outcome: Replace periodic dashboard refresh with server-sent events while preserving the durable-ledger source of truth and safe reconnect behavior.
Depends On: none
Decision: none
Detour For: none
Return To: none
Completion Gate: The dashboard receives live state changes without full-page reload, reconnects safely, retains ledger authority, and has recorded deployment and verification evidence.
Completion Evidence: none
Disposition: Historical request migrated after the dashboard SSE implementation was already deployed; available records do not satisfy the original request evidence well enough for a retroactive completed disposition.

## Request Context

Priority: 1
Target: `http://srv-rpi00.local/sd-qualifier/`
Repository: `PC-Redemption/sd-qualification`

## Goal

Make dashboard job and campaign statuses update through Server-Sent Events without reloading the document. Implement, deploy the web-only change, and verify the live result.

## Known starting point

- `qualification/static/qualification/progress.js` currently waits 30 seconds and calls `window.location.reload()` for `[data-dashboard-autorefresh]`.
- `qualification/templates/qualification/dashboard.html` enables that behavior.
- Campaign detail's existing 10-second JSON polling does not reload the page and is outside this request.
- The runtime is Django/Gunicorn/Uvicorn behind the Traefik Front Door, whose documented route preserves streaming.

Identify the current application checkout and deployed source once before editing, then stay in that checkout. Inspect other historical worktrees only if current source identity conflicts.

## Required result

- Remove the timed full-page reload.
- Add an authenticated, same-origin, read-only SSE endpoint that sends an initial dashboard snapshot and subsequent persisted status changes, with heartbeat and safe reconnect/resume behavior.
- Update every dashboard region that relied on reload for freshness. Prefer a server-rendered fragment so Django remains authoritative for status projection.
- Preserve focus, scroll position, open details, desktop/mobile layout, links, controls, authorization, and server-rendered initial/no-JavaScript behavior.
- Show a clear disconnected/stale state when SSE is unavailable; never fall back to automatic page reload.
- Do not issue controller commands, mutate campaign state, change firmware, touch media, or restart non-web services.

## Verify efficiently

- Run focused backend and frontend/static tests covering authentication, SSE headers/format, read-only behavior, DOM updates, and reconnect.
- Use Playwright in a fixture/candidate environment to prove a persisted status change updates the page without another document navigation.
- Deploy only the web/static surface through the existing application path. Verify through the real Front Door that the SSE connection works, application health remains good, and the page does not reload after more than 30 seconds.
- Do not run the full suite, create a PR, push, or create separate planning/evidence artifacts unless focused results, repository policy, or deployment mechanics require it.

Report the source commit, focused test results, deployed image/rollback identity, SSE route, live no-reload evidence, and services left untouched.
