PC3 Phase 3.3 fix: RATE_LIMIT_ENABLED flag so the smoke suite isn't throttled
Every checkpoint smoke test registers users against one backend from one client IP, so the per-IP auth limit tripped mid-suite (main_menu_full_flow -> 2/12). Add RATE_LIMIT_ENABLED (default true); run_checkpoint_tests.py sets it false for its backend. test_rate_limit.py forces it on in-fixture so the limiter is still really tested. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015jtxAiu5dAW4WxCNdGkrkJ
This commit is contained in:
@@ -75,6 +75,10 @@ class Settings(BaseSettings):
|
||||
# CORS
|
||||
CORS_ORIGINS: str = "http://localhost:8080,http://localhost:3000"
|
||||
|
||||
# Per-IP auth rate limiting (app/rate_limit.py). Disabled by the
|
||||
# checkpoint smoke suite, which runs every test from one client IP.
|
||||
RATE_LIMIT_ENABLED: bool = True
|
||||
|
||||
# File uploads
|
||||
UPLOAD_DIR: str = "uploads"
|
||||
MAX_UPLOAD_SIZE_MB: int = 100
|
||||
|
||||
@@ -14,6 +14,8 @@ from collections import defaultdict, deque
|
||||
|
||||
from fastapi import HTTPException, Request, status
|
||||
|
||||
from app.config import settings
|
||||
|
||||
|
||||
class SlidingWindowLimiter:
|
||||
def __init__(self, max_hits: int, window_seconds: float) -> None:
|
||||
@@ -54,7 +56,15 @@ _auth_limiter = SlidingWindowLimiter(max_hits=10, window_seconds=60)
|
||||
|
||||
|
||||
async def auth_rate_limit(request: Request) -> None:
|
||||
"""FastAPI dependency: rate-limit auth attempts per client IP."""
|
||||
"""FastAPI dependency: rate-limit auth attempts per client IP.
|
||||
|
||||
A no-op when ``RATE_LIMIT_ENABLED`` is false -- the checkpoint smoke
|
||||
suite runs every test against one backend from one client IP, so the
|
||||
per-IP cap would trip mid-suite. The dedicated ``test_rate_limit``
|
||||
module exercises the real behaviour regardless of this flag.
|
||||
"""
|
||||
if not settings.RATE_LIMIT_ENABLED:
|
||||
return
|
||||
_auth_limiter.check(f"auth:{_client_key(request)}")
|
||||
|
||||
|
||||
|
||||
@@ -4,16 +4,21 @@ import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from app import rate_limit
|
||||
from app.config import settings
|
||||
from app.main import app
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _clean_limiter():
|
||||
# This module tests the limiter itself, so start each test from empty
|
||||
# and don't let conftest's between-test reset interfere mid-test.
|
||||
# This module tests the limiter itself: force it on (the checkpoint
|
||||
# runner disables it suite-wide via RATE_LIMIT_ENABLED) and start each
|
||||
# test from an empty window.
|
||||
prev = settings.RATE_LIMIT_ENABLED
|
||||
settings.RATE_LIMIT_ENABLED = True
|
||||
rate_limit.reset_all()
|
||||
yield
|
||||
rate_limit.reset_all()
|
||||
settings.RATE_LIMIT_ENABLED = prev
|
||||
|
||||
|
||||
def test_login_is_limited_after_the_threshold():
|
||||
|
||||
@@ -90,6 +90,10 @@ def main():
|
||||
db_url = f"postgresql+asyncpg://agp_user:agp_password@localhost:{args.postgres_port}/agp_db"
|
||||
backend_env = os.environ.copy()
|
||||
backend_env["DATABASE_URL"] = db_url
|
||||
# Every smoke test registers users against this one backend from one
|
||||
# client IP; the per-IP auth rate limit would trip mid-suite.
|
||||
# test_rate_limit.py exercises the limiter itself regardless.
|
||||
backend_env["RATE_LIMIT_ENABLED"] = "false"
|
||||
|
||||
print("\n=== Backend: alembic upgrade head ===")
|
||||
r = run([sys.executable, "-m", "alembic", "upgrade", "head"], cwd=BACKEND, env=backend_env)
|
||||
|
||||
Reference in New Issue
Block a user