refactor(rate-limit): limit recipients as well as requesters - #37
Closed
johnhooks wants to merge 1 commit into
Closed
refactor(rate-limit): limit recipients as well as requesters#37johnhooks wants to merge 1 commit into
johnhooks wants to merge 1 commit into
Conversation
Rebuild throttling around two independent dimensions. HttpRateLimit counts who is asking (per IP and per subject, fixed clock-aligned windows); OutboundEmailRateLimiter counts who receives security email, one bucket shared by every send path, over layered 5min/hour/day ceilings. - Reserve-before-send with refunds: slots are claimed before the WorkOS call and handed back when the response shows no mail went out, closing the check-then-act gap under concurrent requests. - Addresses are canonicalized (tags, gmail dots) so variants share one counter, and subjects are hashed so no plaintext PII is stored. - Counters live in the object cache (atomic incr) with a transient fallback; window epoch is part of the key so expiry is arithmetic. - Client IP comes from REMOTE_ADDR unless an operator names a proxy header; list values are read right-most-public. - Injected Clock (frozen in tests via a Codeception module) replaces time() so window rollover is testable. - Limits are class constants beside the endpoints that own them; the only settings left are the email ceilings and the proxy header.
johnhooks
force-pushed
the
refactor/rate-limiter
branch
from
August 4, 2026 01:41
1cfe043 to
746b8c6
Compare
Collaborator
Author
|
Closed in favor of #39 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rate limiting rebuilt as a shared module. Requests were already throttled per endpoint; this adds the missing dimension, a cap on security email per recipient mailbox, shared across every path that can send one.
Changes
RateLimit\RateLimiter: fixed clock-aligned windows, counters in the object cache (atomicincr) with transient fallback, subjects hashed into keys.OutboundEmailRateLimiter: one bucket for all send paths, layered 5 min / hour / day ceilings, addresses canonicalized so mailbox variants share a counter.Http\ClientIp:REMOTE_ADDRunless an operator names a proxy header; list values read right-most-public.Time\Clockinjected everywhere; tests freeze and step it instead of using relative timestamps.WORKOS_CLIENT_IP_HEADER.Enumeration-safe routes keep their uniform responses; refused sends are skipped silently. Details in
docs/rate-limiting.md.