"""Rate-limit in-proces cu fereastra glisanta. Fara dependinta externa. Folosit de POST /signup cu cheia = IP client. Configurabil prin AUTOPASS_signup_rate_max / AUTOPASS_signup_rate_window_s (config.py). """ from __future__ import annotations import time # ip/key -> lista de timestamps (time.monotonic) ale cererilor din fereastra activa _hits: dict[str, list[float]] = {} def check_rate_limit(key: str, max_hits: int, window_s: int) -> bool: """Fereastra glisanta: returneaza True daca cererea e permisa, False la depasire. Curata timestamp-urile expirate la fiecare apel (O(n) per cheie, acceptabil pentru trafic de signup). Thread-safety: GIL Python protejeaza list ops simple; suficient pentru un singur proces uvicorn. Cheile fara timestamp-uri valide sunt sterse din `_hits` (nu doar golite), altfel dictionarul creste monoton pe viata procesului odata ce cheia devine IP-uri reale de internet (F5). Foloseste `.get` in loc de acces direct pe dict pentru a nu reintroduce o cheie doar prin citire. """ now = time.monotonic() cutoff = now - window_s filtered = [t for t in _hits.get(key, []) if t > cutoff] if len(filtered) >= max_hits: if filtered: _hits[key] = filtered else: _hits.pop(key, None) return False filtered.append(now) _hits[key] = filtered return True