fix(e2e): retry password-reset confirm past the per-IP rate limit #286

Merged
Claude-Run merged 1 commit from fix/BUNYIP-278-e2e-reset-confirm-rate-limit-retry into main 2026-06-30 06:40:54 +02:00
Member

The password-reset spec posted /v1/auth/password-reset/confirm exactly once and asserted ok(), with no tolerance for a 429. The confirm endpoint is throttled at 5/min per source IP (RateLimitConfig::LOGIN, keyed by IP in confirm_password_reset) - a bucket the whole suite shares because every spec hits the API from the same CI IP. On a busy run that window can already be full when this spec confirms, so bunyip answers 429 RATE_LIMITED and the spec hard-failed (run #1332). This is harness-timing fragility, not a product bug, and matches the login-rate-limit hardening already done for BUNYIP-267.

confirmReset now resubmits on a 429, honouring the Retry-After header (clamped to the 60s login window with a 1s cushion) for up to three attempts. The rate-limit check runs before the token is consumed, so the reset token survives a 429 and the same token is safe to resubmit. A Playwright-level retry cannot do this: it re-runs the whole register + reset-email flow and only adds load to the shared bucket. The spec is already test.slow(), giving the backoff room.

#BUNYIP-278

The password-reset spec posted /v1/auth/password-reset/confirm exactly once and asserted ok(), with no tolerance for a 429. The confirm endpoint is throttled at 5/min per source IP (RateLimitConfig::LOGIN, keyed by IP in confirm_password_reset) - a bucket the whole suite shares because every spec hits the API from the same CI IP. On a busy run that window can already be full when this spec confirms, so bunyip answers 429 RATE_LIMITED and the spec hard-failed (run #1332). This is harness-timing fragility, not a product bug, and matches the login-rate-limit hardening already done for BUNYIP-267. confirmReset now resubmits on a 429, honouring the Retry-After header (clamped to the 60s login window with a 1s cushion) for up to three attempts. The rate-limit check runs before the token is consumed, so the reset token survives a 429 and the same token is safe to resubmit. A Playwright-level retry cannot do this: it re-runs the whole register + reset-email flow and only adds load to the shared bucket. The spec is already test.slow(), giving the backoff room. #BUNYIP-278
fix(e2e): retry password-reset confirm past the per-IP rate limit
All checks were successful
E2E / Playwright against deployment (pull_request) Successful in 22s
Check / fmt + clippy + build + tests (pull_request) Successful in 11m0s
Create release / Create release from merged PR (pull_request) Has been skipped
1e77944630
The password-reset spec posted /v1/auth/password-reset/confirm exactly once and asserted ok(), with no tolerance for a 429. The confirm endpoint is throttled at 5/min per source IP (RateLimitConfig::LOGIN, keyed by IP in confirm_password_reset) - a bucket the whole suite shares because every spec hits the API from the same CI IP. On a busy run that window can already be full when this spec confirms, so bunyip answers 429 RATE_LIMITED and the spec hard-failed (run #1332). This is harness-timing fragility, not a product bug, and matches the login-rate-limit hardening already done for BUNYIP-267.

confirmReset now resubmits on a 429, honouring the Retry-After header (clamped to the 60s login window with a 1s cushion) for up to three attempts. The rate-limit check runs before the token is consumed, so the reset token survives a 429 and the same token is safe to resubmit. A Playwright-level retry cannot do this: it re-runs the whole register + reset-email flow and only adds load to the shared bucket. The spec is already test.slow(), giving the backoff room.

#BUNYIP-278
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/bunyip!286
No description provided.