Feature Owner: scorevi (Sean Patrick Caintic)
Module: Auth & Security
Priority: P1
Sprint #12: Partially Implemented (~60%)
Date: 2026-06-29
EXECUTIVE SUMMARY
What is this feature?
An idle timeout hook (useIdleTimeout) that tracks user activity and auto-signs out via Clerk after 20 minutes of inactivity, with a 2-minute warning. Includes cross-tab sync via localStorage and iOS Safari bfcache protection.
Why does it matter?
Without idle timeout, a user who leaves their session open on a shared/public computer exposes their account. For enterprise/edu settings with compliance requirements, this is a security gap.
What's the MVP scope?useIdleTimeout hook implemented in hooks/quest/useIdleTimeout.ts (130 lines). Used in LearnerLayoutClient and CreatorLayoutClient. NOT yet integrated into Admin, Agency, or Reviewer layouts. Cache-Control headers enforced in middleware.
1. USER PAIN POINT & SOLUTION
Current State (Without Feature)
A user signs in on a library computer, walks away, and the session remains active indefinitely. Anyone can access their dashboard, quests, or personal data.
Pain Point
Emotional: Anxiety about leaving a session exposed.
Functional: No automatic session termination. Manual sign-out is the only protection.
Business Impact: Compliance risk (especially for education/GDPR). Potential data breaches from unattended sessions.
Future State (With Feature)
After 20 minutes of inactivity, the user receives a warning. If they don't respond within 2 minutes, they are automatically signed out and redirected to /sign-in?reason=session_timeout.
Marketing Hook
"Your session is protected. Always."
2. 4D FRAMEWORK MAPPING
Diagnose
N/A — security infrastructure.
Design
N/A — security infrastructure.
Develop
N/A — security infrastructure.
Deliver
N/A — security infrastructure.
3. USER FLOWS
Entry Point
User signs in and begins interacting with the application. The idle timer starts tracking activity.
Success Criteria
After 20 minutes of inactivity, user is signed out and redirected to sign-in page with a timeout reason.
Main Flow (Happy Path)
User signs in and starts browsing. Timer resets on every mousemove, keydown, click, scroll, or touchstart.
After 18 minutes of inactivity (20 min - 2 min warning),
onWarningcallback fires.If no activity detected in the next 2 minutes,
handleTimeoutfires.signOut()is called via Clerk. On success, user is redirected to/sign-in?reason=session_timeout.
Edge Cases
Multiple tabs: One tab's activity resets the timer in all tabs via
localStorage.setItem("wyzquests_last_active")andstorageevent listener.SSR/storage quota error: localStorage write failure is silently caught.
Disabled state: Hook accepts
disabledprop (e.g., when unauthenticated).iOS Safari bfcache:
BfCacheGuardcomponent forces hard reload if page is restored from bfcache after sign-out.
Decision Points
IF
disabled === true→ hook does nothing.ELSE → start tracking activity, set timers.
4. INFORMATION ARCHITECTURE
Primary Information (Always visible)
Invisible in normal state. Warning toast/modal appears 2 minutes before timeout.
Secondary Information
Session timer (if made visible in future UI).
Actions
Primary CTA: Respond to warning (any activity resets timer).
Secondary Actions: N/A — timeout is automatic.
5. WIREFRAMES
[Excluded — existing implementation, no dedicated UI beyond optional warning toast]
6. WIREFLOWS
Excluded.
7. PROTOTYPE
[Excluded — existing implementation]
8. BACKEND SCHEMA
Database Tables
No dedicated table. Client-side only via React hook.
Client-Side State
Key | Storage | Purpose |
|---|---|---|
| localStorage | Cross-tab activity sync timestamp (ISO epoch) |
9. API ENDPOINTS
No dedicated API endpoints. Uses Clerk's signOut() client-side method.
10. DATA REQUIREMENTS
Frontend Needs
useIdleTimeouthook (hooks/quest/useIdleTimeout.ts, 130 lines).useClerk()forsignOut().useRouter()for redirect.
API Calls Frontend Will Make
Clerk
signOut()on timeout.
Caching Strategy
N/A.
11. PERFORMANCE CONSIDERATIONS
Database Optimization
N/A.
API Response Time
N/A — client-side only. Timer operations are O(1). Event listeners use { passive: true } for scroll/touch performance.
Who can access this feature?
Feature is integrated for learners and creators only (as of Sprint #12). Pending: admin, agency, reviewer layouts.
N/A — hook behavior, not authorization.
Data Validation
N/A.
13. ERROR HANDLING
Error | Response |
|---|---|
| Error logged to console. |
localStorage write fails (quota, SSR) | Silently caught — timer still works within current tab. |
Timer fires after component unmount |
|
14. TESTING CHECKLIST
Happy Path
□ After 20 min inactivity, user is signed out.
□ Warning fires at 18 min (2 min before timeout).
□ Any activity (mouse, keyboard, touch, scroll) resets timer.
□ Redirect URL includes ?reason=session_timeout.
Edge Cases
□ Activity in Tab A resets timer in Tab B (cross-tab sync).
□ disabled=true prevents all timer logic.
□ Sign-out failure is handled gracefully (no infinite loop).
□ Component unmounts cleanly (no lingering timers).
□ iOS Safari bfcache restore after timeout → forced reload.
15. OPEN QUESTIONS
Should
DEFAULT_TIMEOUT_MS(20 min) be configurable per role or agency?Should the warning modal require explicit "Stay Signed In" button click, or is any activity sufficient?
When will Admin/Agency/Reviewer layouts be integrated?
16. OUT OF SCOPE (v1.1+)
Server-side session expiration enforcement (currently client-only).
Force logout from admin panel (remote session termination).
Idle timeout configuration per agency/role.
17. SUCCESS METRICS
100% of learner and creator sessions auto-terminate after idle timeout.
0 false timeouts from legitimate cross-tab activity (cross-tab sync prevents this).
Integration into remaining layouts (Admin, Agency, Reviewer) is pending.
18. DEPENDENCIES
This feature depends on:
Clerk
signOut()function.BfCacheGuardcomponent (31 lines) for iOS Safari protection.middleware.tsCache-Control headers (no-store, no-cache, must-revalidate, proxy-revalidate).
These features depend on this:
None directly. Security hardening.
19. TIMELINE & OWNERSHIP
Status: ~60% implemented.
Implemented layouts:
app/learner/LearnerLayoutClient.tsx(line 59),app/creator/CreatorLayoutClient.tsx(line 53).Pending layouts:
AdminLayoutClient,AgencyLayoutClient,ReviewerLayoutClient.Owner: scorevi (Sean Patrick Caintic)
Document Version
1.0 - Initial version - 2026-06-29 08:03 UTC
1.1 (Current Version) - Added Document Version section and update author to have full name - 2026-06-29 08:37 UTC