You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(plugin-auth): count the per-number OTP send budget in the shared store (#4790) (#4806)
#2780's per-number OTP budget (60s cooldown + 5/hour) was shared across nodes
ONLY when a host supplied better-auth's `secondaryStorage`. Nothing in the
standard `serve` composition supplies one — and since #4788, AuthPlugin
deliberately does not derive it from the kernel cache either — so the budget
was counted per process: an N-node deployment granted one phone number N
cooldowns and N hourly caps, in paid SMS, with no signal that the declared
limit was not the enforced one (ADR-0049).
Same defect class as #4772's rate-limit counters, and now the same cure rather
than a second implementation of it. The lazy-resolution half of
`createLazyCacheRateLimitStorage` is extracted as `createLazyCounterStore()`:
resolve the `cache` service when a counter is CONSUMED (strictly after
`kernel:ready`, so plugin start order decides nothing), memoise the handle,
fall back to the bounded in-process store when there is genuinely no cache —
and say which of the two happened, once. The OTP guard reaches it through the
new `AuthManagerOptions.sharedCounterStore`, filled by AuthPlugin from the
same `resolveCache` closure the rate-limit counters use.
Deliberately NOT `secondaryStorage` (#4785): that also relocates the session of
record into the cache and silently disables the ADR-0069 D4 session controls. A
host-supplied `secondaryStorage` still wins for this budget, unchanged.
The cooldown / rolling-hour semantics are untouched — only where the timestamps
live changed. A fixed-window counter cannot express "N seconds since the last
send", and converting the hourly cap to one would admit a 2× burst across the
window boundary: trading one multiplication for another.
Claude-Session: https://claude.ai/code/session_015Br2xsJsczFsTR9bvbh2Ny
Co-authored-by: Claude <noreply@anthropic.com>
0 commit comments