Problem
The frontend now deduplicates completed upgrade reload handling, but the backend can still keep returning the last upgrade state as completed indefinitely from /api/v1/updates/status.
That makes clients responsible for remembering which completion they already handled. It also leaves stale operational state visible after the upgrade is already resolved.
Recommended backend hardening
Add a backend-side completion lifecycle so a completed upgrade does not remain an active status forever.
Reasonable implementation options:
-
Add an acknowledgment endpoint, for example POST /api/v1/updates/status/ack.
- Frontend calls it after observing
completed and scheduling its reset.
- Backend records that the completion was acknowledged by the client/session or clears the active status to
idle.
- Keep historical status available separately if needed.
-
Add a status TTL.
- Keep
completed visible for a short window, such as 5-15 minutes.
- After the TTL,
/api/v1/updates/status returns idle while preserving the last upgrade details in history/logs.
-
Prefer a stable upgrade_id.
- Each upgrade request should produce a durable ID.
- Status responses should include that ID so frontend and backend can reason about one specific upgrade completion instead of inferring identity from version/timestamps.
Acceptance criteria
/api/v1/updates/status does not return the same stale completed state forever.
- Completed upgrade state remains observable long enough for the frontend to react.
- The backend exposes a stable upgrade identity, preferably
upgrade_id, or otherwise enough fields for clients to distinguish separate upgrade attempts.
- Existing upgrade status tests cover completed-to-idle acknowledgment or TTL behavior.
- Frontend reload dedupe remains a defensive fallback, not the primary lifecycle mechanism.
Context
Frontend mitigation was added in branch bugfix/upgrade-frontend-reset: it stores the handled completed-upgrade key in sessionStorage so a persisted backend completed response cannot create a reload loop.
Problem
The frontend now deduplicates completed upgrade reload handling, but the backend can still keep returning the last upgrade state as
completedindefinitely from/api/v1/updates/status.That makes clients responsible for remembering which completion they already handled. It also leaves stale operational state visible after the upgrade is already resolved.
Recommended backend hardening
Add a backend-side completion lifecycle so a completed upgrade does not remain an active status forever.
Reasonable implementation options:
Add an acknowledgment endpoint, for example
POST /api/v1/updates/status/ack.completedand scheduling its reset.idle.Add a status TTL.
completedvisible for a short window, such as 5-15 minutes./api/v1/updates/statusreturnsidlewhile preserving the last upgrade details in history/logs.Prefer a stable
upgrade_id.Acceptance criteria
/api/v1/updates/statusdoes not return the same stalecompletedstate forever.upgrade_id, or otherwise enough fields for clients to distinguish separate upgrade attempts.Context
Frontend mitigation was added in branch
bugfix/upgrade-frontend-reset: it stores the handled completed-upgrade key insessionStorageso a persisted backendcompletedresponse cannot create a reload loop.