# Remember-Me Multi-Device Tokens Design (2026-02-28)

## Context
After the security changes on 2026-02-26, remember-me uses a single `users.remember_token` value. This breaks multi-browser usage because each login overwrites the previous token. The goal is to allow unlimited concurrent remember-me sessions across devices and browsers, with retention cleanup for tokens older than 6 months.

## Goals
- Allow unlimited concurrent remember-me sessions per user.
- Store only hashed tokens in the database.
- Keep existing cookie security attributes (`Secure`, `HttpOnly`, `SameSite=Lax`).
- Clean up tokens older than 6 months.

## Non-Goals
- Reworking the entire authentication system.
- Introducing refresh-token or JWT flows.

## Data Model
Add a new table `users_remember_tokens`:
- `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY
- `user_id` INT UNSIGNED NOT NULL, indexed
- `token_hash` CHAR(64) NOT NULL, unique
- `created_at` DATETIME NOT NULL
- `last_used_at` DATETIME NULL
- `user_agent` VARCHAR(255) NULL
- `ip` VARCHAR(45) NULL

Rationale:
- Store only `token_hash` (SHA-256 of raw token) to avoid storing bearer tokens in plain text.
- Use `last_used_at` for retention and auditing. If null, fall back to `created_at`.

## Login Flow
1. When user logs in with "Zapamiêtaj mnie":
   - Generate random token (64 hex).
   - Store `hash = sha256(token)` in `users_remember_tokens` with metadata and timestamps.
   - Set cookie to the raw token with expiry +1 year and existing security attributes.
2. When user logs in without "Zapamiêtaj mnie":
   - Do not create a token.
   - Existing cookie is cleared.

## Auto-Login Flow
1. If no session and cookie exists:
   - Hash cookie value with SHA-256.
   - Look up `users_remember_tokens` by `token_hash`.
   - If found, load user, set session, update `last_used_at`.
   - If not found, clear cookie.

## Retention
- Delete tokens older than 6 months based on `last_used_at` (or `created_at` if `last_used_at` is null).
- Trigger cleanup during login and auto-login paths to avoid extra jobs.

## Error Handling
- Missing or invalid token in DB results in clearing the cookie and continuing to login screen.
- No user row for token is treated as invalid and cleaned.

## Testing
- Integration test: login with remember-me sets cookie and inserts token row.
- Integration test: auto-login succeeds from cookie after session is cleared.
- Retention test: tokens older than 6 months are removed on login.
