docs(06-01): complete Wave 0 Nyquist scaffold plan summary
- 13 xfail stubs: 5 for D-01/D-02 (logging), 8 for D-11/D-12+A1 (rate limiting) - load_tests package skeleton (D-04/D-05/D-06) excluded from pytest - Package legitimacy decisions recorded (structlog + locust both approved) - Full suite: 344 passed, 20 xfailed, 1 pre-existing failure, 0 regressions
This commit is contained in:
@@ -0,0 +1,127 @@
|
|||||||
|
---
|
||||||
|
phase: 06-performance-production-hardening
|
||||||
|
plan: "01"
|
||||||
|
subsystem: observability/rate-limiting/load-testing
|
||||||
|
tags: [wave-0, xfail-scaffold, structured-logging, rate-limiting, locust, nyquist]
|
||||||
|
dependency_graph:
|
||||||
|
requires: []
|
||||||
|
provides:
|
||||||
|
- "backend/tests/test_logging.py — 5 xfail stubs for D-01/D-02"
|
||||||
|
- "backend/tests/test_rate_limiting.py — 8 xfail stubs for D-11/D-12 + A1 gate"
|
||||||
|
- "backend/load_tests/__init__.py — pytest exclusion marker"
|
||||||
|
- "backend/load_tests/locustfile.py — Locust HttpUser skeleton"
|
||||||
|
affects: []
|
||||||
|
tech_stack:
|
||||||
|
added: []
|
||||||
|
patterns:
|
||||||
|
- "xfail(strict=False) Wave 0 scaffold — all stubs single-line body pytest.xfail('not implemented yet')"
|
||||||
|
- "Locust HttpUser skeleton with NotImplementedError bodies and env-var credential pickup"
|
||||||
|
- "Empty __init__.py package marker excludes load_tests from pytest discovery"
|
||||||
|
key_files:
|
||||||
|
created:
|
||||||
|
- backend/tests/test_logging.py
|
||||||
|
- backend/tests/test_rate_limiting.py
|
||||||
|
- backend/load_tests/__init__.py
|
||||||
|
- backend/load_tests/locustfile.py
|
||||||
|
modified: []
|
||||||
|
decisions:
|
||||||
|
- "structlog 25.5.0 — approved by user as legitimate (hynek/structlog, CPython core contributor author). Will be added to backend/requirements.txt in plan 06-02."
|
||||||
|
- "locust 2.34.0 — approved by user as legitimate (locustio/locust, 10+ year history, multi-million monthly downloads). Will be added to backend/requirements-dev.txt in plan 06-03 (dev-only, NOT in requirements.txt)."
|
||||||
|
- "load_tests excluded from pytest via testpaths=tests in pytest.ini — no conftest exclusion needed; locustfile.py filename does not match test_*.py pattern"
|
||||||
|
metrics:
|
||||||
|
duration: "~60s"
|
||||||
|
completed: "2026-06-03"
|
||||||
|
tasks_completed: 5
|
||||||
|
files_created: 4
|
||||||
|
files_modified: 0
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 06 Plan 01: Wave 0 Nyquist Scaffold Summary
|
||||||
|
|
||||||
|
Wave 0 xfail test scaffold for Phase 6 structured logging (D-01/D-02), trusted-proxy rate limiting (D-11), per-account rate limiting (D-12), and Locust load-test skeleton (D-04/D-05/D-06).
|
||||||
|
|
||||||
|
## What Was Built
|
||||||
|
|
||||||
|
**backend/tests/test_logging.py** — 5 xfail stubs for D-01/D-02:
|
||||||
|
1. `test_setup_logging_emits_json_when_LOG_JSON_true` — JSON renderer through ProcessorFormatter
|
||||||
|
2. `test_correlation_id_middleware_binds_contextvar` — CorrelationIDMiddleware binds to structlog contextvars
|
||||||
|
3. `test_correlation_id_response_header_present` — X-Correlation-ID header on every response
|
||||||
|
4. `test_contextvars_cleared_between_requests` — Pitfall 2 guard: no context bleed between requests
|
||||||
|
5. `test_uvicorn_access_log_suppressed` — uvicorn.access propagate=False
|
||||||
|
|
||||||
|
**backend/tests/test_rate_limiting.py** — 8 xfail stubs for D-11/D-12 + A1 verification:
|
||||||
|
1. `test_get_client_ip_untrusted_returns_direct_peer` — untrusted peer ignores XFF
|
||||||
|
2. `test_get_client_ip_trusted_proxy_reads_xff_leftmost` — trusted peer reads leftmost XFF
|
||||||
|
3. `test_get_client_ip_trusted_proxy_no_xff_falls_back` — trusted peer with no XFF falls back to peer IP
|
||||||
|
4. `test_get_client_ip_invalid_peer_returns_none_or_string` — None client returns None safely
|
||||||
|
5. `test_account_limiter_key_uses_user_id` — key_func returns str(user.id)
|
||||||
|
6. `test_account_limiter_key_falls_back_to_ip_when_no_user` — no user on request.state → IP fallback, no crash
|
||||||
|
7. `test_account_limiter_key_ordering_assumption` — **A1 gate**: verifies slowapi reads request.state.current_user correctly before counting
|
||||||
|
8. `test_authenticated_endpoint_429_after_100_per_minute` — full integration 429 check
|
||||||
|
|
||||||
|
**backend/load_tests/__init__.py** — empty package marker (56 bytes)
|
||||||
|
|
||||||
|
**backend/load_tests/locustfile.py** — DocuVaultUser skeleton:
|
||||||
|
- `on_start`, `_auth_headers`, `list_documents`, `upload_document`, `refresh_token` stubs (all raise NotImplementedError)
|
||||||
|
- `check_sla` SLA listener registered via `@events.quitting.add_listener`
|
||||||
|
- Credentials from `LOAD_TEST_EMAIL`/`LOAD_TEST_PASSWORD` env vars only
|
||||||
|
- Zero application imports
|
||||||
|
|
||||||
|
## Test Suite Results
|
||||||
|
|
||||||
|
| Metric | Baseline | After Plan 06-01 | Delta |
|
||||||
|
|--------|----------|------------------|-------|
|
||||||
|
| Passed | 344 | 344 | 0 |
|
||||||
|
| Failed | 1 (pre-existing) | 1 (pre-existing) | 0 |
|
||||||
|
| Skipped | 5 | 5 | 0 |
|
||||||
|
| XFailed | 7 | 20 | +13 |
|
||||||
|
|
||||||
|
- 5 new XFAIL in `test_logging.py`
|
||||||
|
- 8 new XFAIL in `test_rate_limiting.py`
|
||||||
|
- Zero regressions
|
||||||
|
- Pre-existing failure: `test_extractor.py::test_extract_docx` (ModuleNotFoundError — carried over from 6.2)
|
||||||
|
|
||||||
|
## Package Legitimacy Decision (verbatim from checkpoint)
|
||||||
|
|
||||||
|
**structlog 25.5.0** — APPROVED
|
||||||
|
- PyPI: https://pypi.org/project/structlog/
|
||||||
|
- Author: Hynek Schlawack (CPython core contributor)
|
||||||
|
- Homepage: https://github.com/hynek/structlog
|
||||||
|
- Action: add to `backend/requirements.txt` in plan 06-02
|
||||||
|
|
||||||
|
**locust 2.34.0** — APPROVED (dev-only)
|
||||||
|
- PyPI: https://pypi.org/project/locust/
|
||||||
|
- Project: locustio/locust, 10+ years of releases, multi-million monthly downloads
|
||||||
|
- Action: add to `backend/requirements-dev.txt` in plan 06-03 (NOT in requirements.txt)
|
||||||
|
|
||||||
|
## Commits
|
||||||
|
|
||||||
|
| Task | Commit | Description |
|
||||||
|
|------|--------|-------------|
|
||||||
|
| 2 | e1f8874 | test(06-01): add 5 xfail stubs for structured logging (D-01/D-02) |
|
||||||
|
| 3 | 56d9da7 | test(06-01): add 8 xfail stubs for rate limiting (D-11/D-12 + A1) |
|
||||||
|
| 4 | 594eb46 | feat(06-01): add backend/load_tests/ package skeleton with Locust stub (D-04/D-05/D-06) |
|
||||||
|
| 5 | (verification only — no files changed) | Full suite regression check |
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
None — plan executed exactly as written.
|
||||||
|
|
||||||
|
## Notes for Downstream Plans
|
||||||
|
|
||||||
|
- **06-02 (structured logging):** Must turn the 5 `test_logging.py` stubs green. Install `structlog` in requirements.txt.
|
||||||
|
- **06-03 (Locust implementation):** Must fill in `DocuVaultUser` method bodies and `check_sla`. Install `locust` in requirements-dev.txt.
|
||||||
|
- **06-04 (rate limiting):** Must turn the 8 `test_rate_limiting.py` stubs green. The A1 verification test (`test_account_limiter_key_ordering_assumption`) must be promoted to PASS before applying `@account_limiter.limit("100/minute")` to all document/cloud endpoints — this test is the explicit gate that turns assumption A1 into a fact.
|
||||||
|
- **pytest discovery:** `testpaths = tests` in `pytest.ini` already excludes `backend/load_tests/`; no additional configuration needed.
|
||||||
|
|
||||||
|
## Self-Check: PASSED
|
||||||
|
|
||||||
|
All files created and all commits present:
|
||||||
|
- FOUND: backend/tests/test_logging.py
|
||||||
|
- FOUND: backend/tests/test_rate_limiting.py
|
||||||
|
- FOUND: backend/load_tests/__init__.py
|
||||||
|
- FOUND: backend/load_tests/locustfile.py
|
||||||
|
- FOUND: 06-01-SUMMARY.md
|
||||||
|
- FOUND: commit e1f8874 (test_logging.py)
|
||||||
|
- FOUND: commit 56d9da7 (test_rate_limiting.py)
|
||||||
|
- FOUND: commit 594eb46 (load_tests/ skeleton)
|
||||||
Reference in New Issue
Block a user