15 lines
793 B
SQL
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)
|
|
);
|