-- AZ-534 (Epic AZ-529): TOTP-based 2FA at credential login.
--
-- mfa_secret holds the base32 TOTP shared secret encrypted at rest via the
-- ASP.NET Core IDataProtector ("Azaion.Mfa.Secret" purpose). The column type
-- stays text because the protected payload is base64.
--
-- mfa_recovery_codes is a JSONB array of objects { hash: <argon2id>, used_at: <ts|null> }.
-- One-time-use is enforced by setting used_at on consumption; the row is rewritten
-- transactionally with the rest of the login.
--
-- mfa_last_used_window prevents replay of a TOTP code within its 30-second
-- step. We persist the last accepted RFC 6238 time-step counter (long); a
-- re-presented code matches that counter and is rejected.

ALTER TABLE public.users
    ADD COLUMN IF NOT EXISTS mfa_enabled          boolean   NOT NULL DEFAULT false,
    ADD COLUMN IF NOT EXISTS mfa_secret           text      NULL,
    ADD COLUMN IF NOT EXISTS mfa_recovery_codes   jsonb     NULL,
    ADD COLUMN IF NOT EXISTS mfa_enrolled_at      timestamp NULL,
    ADD COLUMN IF NOT EXISTS mfa_last_used_window bigint    NULL;

-- AZ-534 — pin the authentication-methods-reference (RFC 8176) to the session
-- so refresh-token rotations (AZ-531) inherit the original auth strength. A user
-- who logs in with MFA stays "amr=[pwd,mfa]" for the entire refresh chain even if
-- they later disable MFA; conversely, enabling MFA mid-session does NOT silently
-- upgrade the in-flight session.
ALTER TABLE public.sessions
    ADD COLUMN IF NOT EXISTS mfa_authenticated boolean NOT NULL DEFAULT false;
