-- ============================================================================ -- SECURE ACCESS TOKEN IMPROVEMENTS -- ============================================================================ -- 1. Mark email tokens as one-time-use (used_at timestamp) -- 2. Add cookie sessions table (separate, long-lived, revocable) -- 3. Add audit log table for token redemptions -- ============================================================================ -- Track when a one-time email link was redeemed ALTER TABLE file_access_tokens ADD COLUMN used_at DATETIME DEFAULT NULL; -- ============================================================================ -- COOKIE SESSIONS TABLE -- ============================================================================ -- Stores long-lived browser sessions granted after token redemption. -- Distinct from email tokens: email token is one-time, session is long-lived. -- ============================================================================ CREATE TABLE IF NOT EXISTS file_access_sessions ( id INTEGER PRIMARY KEY AUTOINCREMENT, request_id INTEGER NOT NULL, session_token TEXT NOT NULL UNIQUE, expires_at DATETIME NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, is_valid INTEGER NOT NULL DEFAULT 1, FOREIGN KEY (request_id) REFERENCES file_access_requests(id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS idx_file_access_sessions_token ON file_access_sessions(session_token); CREATE INDEX IF NOT EXISTS idx_file_access_sessions_expires ON file_access_sessions(expires_at); -- ============================================================================ -- TOKEN REDEMPTION AUDIT LOG -- ============================================================================ CREATE TABLE IF NOT EXISTS file_access_audit ( id INTEGER PRIMARY KEY AUTOINCREMENT, request_id INTEGER NOT NULL, event TEXT NOT NULL, -- 'redeemed', 'expired', 'invalid' ip TEXT, user_agent TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (request_id) REFERENCES file_access_requests(id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS idx_file_access_audit_request ON file_access_audit(request_id);