feat(admin): reset an active rate limit for a user or key, audited #332
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/BUNYIP-316-admin-rate-limit-reset"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Add POST /v1/admin/rate-limits/reset (AdminUser-guarded) taking { action, key }, the exact identifiers the BUNYIP-315 list surfaces, and clear that one active throttle so the affected user can act again immediately.
Dispatch on action: the email_verification / email_change pseudo-actions are backed by row counts rather than the rate_limits table, so key is the user id and the reset deletes that user's in-window email_verification_tokens / email_change_requests rows (new TokenRepository::delete_recent_* methods), dropping the count below the shared resend threshold; every other action is a rate_limits table row cleared via RateLimitRepository::reset and must resolve to a known RateLimitConfig preset (a typo'd action is a clean 400, not a silent no-op).
Record a new AuditAction::AdminRateLimitReset (as_str mapping + admin-severity classification) carrying the acting admin, the reset action + key, and the resolved target user where the key maps to one. The reset dispatch lives in a thin apply_rate_limit_reset helper so the HTTP handler stays an audit wrapper and the behaviour is integration-testable against a real pool. DB-backed tests prove a throttled user is un-throttled after reset for both a rate_limits action (login) and the email-verification limiter, and that bad input is rejected; they skip when DATABASE_URL is unset, matching the existing admin handler test pattern.
#BUNYIP-316
Add POST /v1/admin/rate-limits/reset (AdminUser-guarded) taking { action, key }, the exact identifiers the BUNYIP-315 list surfaces, and clear that one active throttle so the affected user can act again immediately. Dispatch on action: the email_verification / email_change pseudo-actions are backed by row counts rather than the rate_limits table, so key is the user id and the reset deletes that user's in-window email_verification_tokens / email_change_requests rows (new TokenRepository::delete_recent_* methods), dropping the count below the shared resend threshold; every other action is a rate_limits table row cleared via RateLimitRepository::reset and must resolve to a known RateLimitConfig preset (a typo'd action is a clean 400, not a silent no-op). Record a new AuditAction::AdminRateLimitReset (as_str mapping + admin-severity classification) carrying the acting admin, the reset action + key, and the resolved target user where the key maps to one. The reset dispatch lives in a thin apply_rate_limit_reset helper so the HTTP handler stays an audit wrapper and the behaviour is integration-testable against a real pool. DB-backed tests prove a throttled user is un-throttled after reset for both a rate_limits action (login) and the email-verification limiter, and that bad input is rejected; they skip when DATABASE_URL is unset, matching the existing admin handler test pattern. #BUNYIP-316