- Shipped
- August 4, 2026 at 4:40 AM UTC
- Author
- kamo
- Commit
- 519edba
Review of the **************** path after removing the duplicate idle stack turned up four real defects: - sessionMonitor.start() left its 3s bootstrap setTimeout untracked, so a start/stop/start sequence spawned a second polling interval that stop() could never clear. The timeout id is now tracked and cancelled. - On orgs with sessionTimeoutMinutes <= 5 the Redis TTL never exceeds the 300s warning threshold, so the proactive-extend branch never ran and ACTIVE users were shown the timeout popup on every check. The warning path now extends instead of warning when the user has been active within 2 minutes. - check() dereferenced this.config after awaits; stop() racing a slow request threw inside the interval. Config is re-checked after every await. - clientActivity wrote localStorage on every mousemove (synchronous writes at pointer frequency, each firing storage events in all sibling tabs). Persists are now throttled to 5s; the in-memory timestamp stays exact. Also: handleExtended now always closes the warning on extension — the old 'TTL > 300' condition stranded the popup on orgs whose whole timeout is <= 5 minutes. Regression tests cover the lifecycle and both popup rules.