57ecab8571
## Problem Entering a 2FA code right after it rotates fails with "Invalid OTP". A tolerance window was configured (`TOTP_DEFAULT_CONFIGURATION.window`) but never applied: `TotpStrategy` validated its options with Zod and then discarded them, and `validate()` called the global otplib `authenticator`, which defaults to `window: 0`. Only the current 30-second code was ever accepted, and clock drift between the device and the server made it feel even stricter. ## Changes - `TotpStrategy` now clones the otplib authenticator with the validated options (window, step, digits, algorithm, encoding, epoch) and uses that instance for both `initiate` and `validate`, so the configured tolerance actually applies. - Default window set to 1: the previous and next codes are accepted alongside the current one, so a code stays valid for up to 30 extra seconds after rotation and forward clock skew is tolerated. This follows the RFC 6238 recommendation of one time step, kept deliberately tight since `getAuthTokensFromOTP` has no rate limiting beyond the optional captcha guard. - Replaced the placeholder strategy tests with deterministic assertions using fixed epochs: previous and next tokens accepted within the window, a token two steps old rejected, and no-window strategies still reject the previous token. ## Testing - All 2FA module unit tests pass (105), including 19 for the strategy. - `lint:diff-with-main` and `typecheck` pass for twenty-server. --- _Generated by [Claude Code](https://claude.ai/code/session_01Va3ESUmkp14Wu65sAXkL7k)_ <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/23632?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->