-- web_sessions: browser "passwordless re-login". The opaque cookie token is
-- never stored; id holds its SHA-256, so a DB leak yields no usable cookie.
-- refresh_token is AES-256-GCM ciphertext (key lives in the container env, not
-- the DB). 7-day sliding window: every refresh rotates the token and pushes
-- expires_at forward; idle sessions are reaped by DeleteExpiredWebSessions.

-- name: CreateWebSession :exec
INSERT INTO web_sessions (id, user_id, refresh_token, device_name, user_agent, created_at, last_used_at, expires_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?);

-- name: GetWebSession :one
SELECT id, user_id, refresh_token, device_name, user_agent, created_at, last_used_at, expires_at, kind, scope, granted_by, stepped_up_at
FROM web_sessions
WHERE id = ?;

-- SetSessionSteppedUp stamps the moment this session last passed step-up re-auth;
-- sensitive actions within the freshness window then skip re-auth (AUTH.md 6).
-- name: SetSessionSteppedUp :exec
UPDATE web_sessions
SET stepped_up_at = ?
WHERE id = ?;

-- name: RotateWebSession :exec
UPDATE web_sessions
SET refresh_token = ?, last_used_at = ?, expires_at = ?
WHERE id = ?;

-- name: SetWebSessionDevice :exec
UPDATE web_sessions
SET device_name = ?
WHERE id = ?;

-- name: DeleteWebSession :exec
DELETE FROM web_sessions
WHERE id = ?;

-- name: DeleteExpiredWebSessions :execrows
DELETE FROM web_sessions
WHERE expires_at < ?;

-- CreateSelfSession inserts a cdrop self-signed session (kind self/guest) that has
-- no IdP refresh_token (stored empty): refresh mints a fresh access token straight
-- from this row without touching the IdP. Used by QR scan-login (AUTH.md 4).
-- name: CreateSelfSession :exec
INSERT INTO web_sessions (id, user_id, refresh_token, device_name, user_agent, kind, scope, granted_by, created_at, last_used_at, expires_at)
VALUES (?, ?, '', ?, ?, ?, ?, ?, ?, ?, ?);

-- SlideWebSession pushes a session's sliding window forward without rotating any
-- token. Self/guest sessions use it on refresh (they have no refresh_token to
-- rotate); oidc sessions keep using RotateWebSession.
-- name: SlideWebSession :exec
UPDATE web_sessions
SET last_used_at = ?, expires_at = ?
WHERE id = ?;

-- ListWebSessionsByUser lists a user's sessions for the management UI (revoke
-- borrowed / guest devices). granted_by ties a scan-approved session to its
-- approver for cascade revocation.
-- name: ListWebSessionsByUser :many
SELECT id, user_id, device_name, user_agent, created_at, last_used_at, expires_at, kind, scope, granted_by
FROM web_sessions
WHERE user_id = ?
ORDER BY last_used_at DESC;

-- DeleteWebSessionForUser drops one session scoped to its owner, so a user can
-- only revoke their own.
-- name: DeleteWebSessionForUser :execrows
DELETE FROM web_sessions
WHERE id = ? AND user_id = ?;
