test(auth): stop pinning the MFA burst to its size #508

Merged
Claude-Run merged 1 commit from fix/PMS-753-mfa-burst-test-flake into main 2026-08-09 21:49:20 +02:00
Member

concurrent_wrong_mfa_codes_all_count fired 20 concurrent wrong second-factor codes and asserted mfa_failed_attempts >= 20. That holds only when all 20 racers clear the lockout gate before the third failure commits. The gate is checked before any code is verified, so a racer arriving after the lockout arms gets RateLimited and returns without spending a guess or ticking the counter (src/modules/auth/service.rs:670). Which racers land on each side is pure scheduling, so the assertion was load-dependent: integration.yml run #3783 recorded 17.

Assert the invariant PMS-693 actually protects instead: the counter equals the number of attempts that reached the verifier. Each racer now reports its error variant, Unauthorized counts as evaluated, RateLimited counts as refused, and an Ok still fails the test. A stale-read regression leaves 20 evaluated failures against a counter of 1 and fails the equality, so the original defect stays pinned. The lockout only arms at 3, so the burst always reaches the threshold and the trailing 21st-attempt probe stays deterministic.

Verified by reproduction: under nproc busy loops the old assertion failed 9 of 10 runs with counts of 16 to 18, matching CI; the new one passed 10 of 10 under the same load and 15 of 15 idle.

#PMS-753

`concurrent_wrong_mfa_codes_all_count` fired 20 concurrent wrong second-factor codes and asserted `mfa_failed_attempts >= 20`. That holds only when all 20 racers clear the lockout gate before the third failure commits. The gate is checked before any code is verified, so a racer arriving after the lockout arms gets `RateLimited` and returns without spending a guess or ticking the counter (src/modules/auth/service.rs:670). Which racers land on each side is pure scheduling, so the assertion was load-dependent: integration.yml run #3783 recorded 17. Assert the invariant PMS-693 actually protects instead: the counter equals the number of attempts that reached the verifier. Each racer now reports its error variant, `Unauthorized` counts as evaluated, `RateLimited` counts as refused, and an `Ok` still fails the test. A stale-read regression leaves 20 evaluated failures against a counter of 1 and fails the equality, so the original defect stays pinned. The lockout only arms at 3, so the burst always reaches the threshold and the trailing 21st-attempt probe stays deterministic. Verified by reproduction: under `nproc` busy loops the old assertion failed 9 of 10 runs with counts of 16 to 18, matching CI; the new one passed 10 of 10 under the same load and 15 of 15 idle. #PMS-753
test(auth): stop pinning the MFA burst to its size
All checks were successful
E2E / Playwright against staging (pull_request) Successful in 2m9s
Integration / integration tests (pull_request) Successful in 4m31s
Check / fmt + clippy + build + tests (pull_request) Successful in 4m48s
Create release / Gate (release-branch merges only) (pull_request) Successful in 1s
Create release / Create release from merged PR (pull_request) Has been skipped
8e1dcb9470
`concurrent_wrong_mfa_codes_all_count` fired 20 concurrent wrong second-factor codes and asserted `mfa_failed_attempts >= 20`. That holds only when all 20 racers clear the lockout gate before the third failure commits. The gate is checked before any code is verified, so a racer arriving after the lockout arms gets `RateLimited` and returns without spending a guess or ticking the counter (src/modules/auth/service.rs:670). Which racers land on each side is pure scheduling, so the assertion was load-dependent: integration.yml run #3783 recorded 17.

Assert the invariant PMS-693 actually protects instead: the counter equals the number of attempts that reached the verifier. Each racer now reports its error variant, `Unauthorized` counts as evaluated, `RateLimited` counts as refused, and an `Ok` still fails the test. A stale-read regression leaves 20 evaluated failures against a counter of 1 and fails the equality, so the original defect stays pinned. The lockout only arms at 3, so the burst always reaches the threshold and the trailing 21st-attempt probe stays deterministic.

Verified by reproduction: under `nproc` busy loops the old assertion failed 9 of 10 runs with counts of 16 to 18, matching CI; the new one passed 10 of 10 under the same load and 15 of 15 idle.

#PMS-753
Claude-Run deleted branch fix/PMS-753-mfa-burst-test-flake 2026-08-09 21:49:21 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-server!508
No description provided.