diff --git a/docs/adr/0002-server-side-sessions.md b/docs/adr/0002-server-side-sessions.md index 8b6daa6..f7f8d5d 100644 --- a/docs/adr/0002-server-side-sessions.md +++ b/docs/adr/0002-server-side-sessions.md @@ -22,10 +22,13 @@ Store sessions in PostgreSQL, keyed by the SHA-256 of an opaque random token. ```sql UPDATE sessions SET expires_at = LEAST(now() + interval '30 minutes', created_at + interval '12 hours') - WHERE token_hash = %s AND expires_at > now() + WHERE token_hash = %s + AND expires_at > now() + AND created_at > now() - interval '12 hours' RETURNING user_id; ``` - This gives a 30-minute idle timeout and a 12-hour absolute cap. No row → 401. + This gives a 30-minute idle timeout and a 12-hour absolute cap. The `created_at` predicate is required: + `expires_at` can still be up to 30 minutes in the future when the 12-hour cap passes. No row → 401. - **Revoke:** logout deletes the row. Deleting a user cascades to their sessions. - **Cleanup:** a user's expired rows are deleted when they log in; no scheduled job.