Fixes finding 3 from the 2026-08-22 security audit: authStore.identify
had no counter, no backoff, and no lockout on failed attempts, and
logger.go wrote one unbuffered stderr line per attempt including the
caller's RemoteAddr. An unauthenticated attacker got unlimited digest
guesses at line rate and could drive synchronous stderr writes on the
shared Traefik ingress.
- Add per-source-IP failure throttling to identify, reusing the existing
in-process memoryStore (limits.go) as authStore's own dedicated
instance rather than a new dependency: authFailureLimit (20) failed
attempts per authFailureWindow (1 minute) throttles further attempts
from that IP outright, including a subsequently valid key, and resets
once the window elapses.
- clientIP reads r.RemoteAddr only, never a client-supplied header,
matching the same trust boundary the rest of this package already
assumes (routes_passthrough.go strips X-Forwarded-*/X-Auth-* before any
outbound request).
- Rate-limit logAuthEvent's failure line via authStore.shouldLogAuthFailure,
the identical technique limiter.logStoreError already applies to store
errors. Successful-auth logging stays unbounded (bounded by legitimate,
already-authenticated traffic elsewhere).