Lock inactive dashboard sessions without losing drafts #463

Closed
opened 2026-08-10 07:30:50 +00:00 by timmy · 0 comments
Owner

Problem

Authenticated dashboard sessions remain usable for the full eight-hour absolute lifetime even after the operator leaves a phone or workstation unattended. Session persistence stores only absolute expiry, and browser polling does not distinguish real user activity.

Evidence on origin/main (9904f17):

  • src/dashboard_auth.py issues absolute-expiry sessions only.
  • src/session_store.py persists and validates expiry without last activity.
  • src/main.py accepts every active session for privileged routes.
  • frontend/session.js reacts to absolute expiry/revocation but has no inactivity lock.

No open/closed issue title or recent commit covers idle/inactivity locking; related #258, #309, #325, #337, #341, and #399 cover session creation, absolute expiry, revocation, fresh authorization, and offline lease behavior instead.

Vertical slice

Add a configurable, server-enforced idle deadline and a throttled browser activity heartbeat. Idle sessions return a distinct session_idle response and route to an unlock/sign-in screen without clearing account-bound drafts or queued work. Absolute expiry and revocation retain their existing private-data purge behavior.

Acceptance tests

  • A session with no explicit activity heartbeat becomes invalid at the configured idle boundary even if background API polling continues.
  • A CSRF-protected activity heartbeat extends the server-side deadline and is throttled in the browser.
  • Idle API responses use 401 with code=session_idle; browser navigation uses login?reason=session-idle.
  • Idle handling preserves drafts, Today/Later state, IndexedDB outboxes, and caches.
  • Successful sign-in resumes queued delivery through the existing flow.
  • Absolute expiry, selective/global revocation, and CSRF protections remain unchanged.
  • Existing session rows migrate safely.
## Problem Authenticated dashboard sessions remain usable for the full eight-hour absolute lifetime even after the operator leaves a phone or workstation unattended. Session persistence stores only absolute expiry, and browser polling does not distinguish real user activity. Evidence on `origin/main` (`9904f17`): - `src/dashboard_auth.py` issues absolute-expiry sessions only. - `src/session_store.py` persists and validates expiry without last activity. - `src/main.py` accepts every active session for privileged routes. - `frontend/session.js` reacts to absolute expiry/revocation but has no inactivity lock. No open/closed issue title or recent commit covers idle/inactivity locking; related #258, #309, #325, #337, #341, and #399 cover session creation, absolute expiry, revocation, fresh authorization, and offline lease behavior instead. ## Vertical slice Add a configurable, server-enforced idle deadline and a throttled browser activity heartbeat. Idle sessions return a distinct `session_idle` response and route to an unlock/sign-in screen **without clearing account-bound drafts or queued work**. Absolute expiry and revocation retain their existing private-data purge behavior. ## Acceptance tests - A session with no explicit activity heartbeat becomes invalid at the configured idle boundary even if background API polling continues. - A CSRF-protected activity heartbeat extends the server-side deadline and is throttled in the browser. - Idle API responses use `401` with `code=session_idle`; browser navigation uses `login?reason=session-idle`. - Idle handling preserves drafts, Today/Later state, IndexedDB outboxes, and caches. - Successful sign-in resumes queued delivery through the existing flow. - Absolute expiry, selective/global revocation, and CSRF protections remain unchanged. - Existing session rows migrate safely.
timmy self-assigned this 2026-08-10 07:30:50 +00:00
timmy closed this issue 2026-08-10 07:47:08 +00:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: stackchain/stackchain-dashboard#463
No description provided.