Files
Felis/internal/store/migrations/0022_otp_failure_budget.sql
T

15 lines
793 B
SQL

-- Account-level budget on wrong one-time codes. The per-code attempts cap
-- (email_otps.attempts) resets whenever a new code is minted, and the public
-- login door lets anyone mint one per minute, so on its own it allows about
-- 7,200 guesses a day against one account. This row survives supersede: it
-- counts every wrong code for a (user, purpose) inside a fixed window, and once
-- the budget is spent that door refuses even the right code until the window
-- ends (internal/api otpFailureBudget / otpFailureWindow).
CREATE TABLE otp_failure_windows (
user_id text NOT NULL REFERENCES users(id) ON DELETE CASCADE,
purpose text NOT NULL,
window_start timestamptz NOT NULL,
failures int NOT NULL DEFAULT 0,
PRIMARY KEY (user_id, purpose)
);