Moves phases 08–11 execution artifacts from .planning/phases/ to .planning/milestones/v0.2-phases/ to keep .planning/phases/ clean for the next milestone. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
6.5 KiB
phase, plan, subsystem, tags, dependency_graph, tech_stack, key_files, decisions, metrics
| phase | plan | subsystem | tags | dependency_graph | tech_stack | key_files | decisions | metrics | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 08-stack-upgrade-backend-decomposition | 01 | backend-tests |
|
|
|
|
|
|
Phase 8 Plan 01: Wave 0 xfail Stubs for CR-01/CR-02/CR-03 Summary
One-liner: Three xfail(strict=False) tests locking session-revocation contracts for change_password, enable_totp, and disable_totp — all xpassed since backend is already complete.
What Was Built
Created backend/tests/test_auth.py with three Wave 0 test stubs:
| Test | Requirement | Status |
|---|---|---|
test_change_password_revokes_other_sessions |
CR-01 | xpassed |
test_enable_totp_revokes_other_sessions |
CR-02 | xpassed |
test_disable_totp_revokes_other_sessions |
CR-03 | xpassed |
All three tests pass when run with --runxfail (backend already implements the behavior per RESEARCH.md §Wave 1). They show XPASS in normal mode since strict=False.
Test Infrastructure
Fixtures used:
revoke_client(new, defined in test_auth.py): AsyncClient with FakeRedis, fixedUser-Agent: docuvault-test/1.0, DB overridedb_session(from conftest.py): in-memory SQLite session
Helper functions:
_register_user(client, handle, email)— register + assert 201_login_session(client, email)— login + return (access_token, refresh_cookie)_try_refresh(client, refresh_token)— POST /api/auth/refresh + return status code
xfail decorator reason string: "Wave 0 stub — promoted to passing in 08-03"
Pytest Collection Count
- Pre-change baseline: 0 tests in
test_auth.py(file did not exist) - Post-change: 3 tests collected
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] FakeRedis not set on app.state.redis
- Found during: Task 1 implementation
- Issue: The plan's existing
authed_clientfixture pattern required FakeRedis injection onapp.state.redis. Without it, endpoints that callrequest.app.state.redis.set(...)(change_password, enable_totp, disable_totp) would fail. - Fix: Created dedicated
revoke_clientfixture with FakeRedis injection, matching the pattern fromtest_auth_api.py. - Files modified:
backend/tests/test_auth.py
2. [Rule 1 - Bug] Token fingerprint mismatch on API calls
- Found during: Task 1 — first test run
- Issue: The access token's
fgpclaim is bound to the User-Agent at login time. The plan suggested using distinct User-Agents for session A and B to ensure separate DB rows, but this caused fingerprint mismatch when using token_a in subsequent API calls with a different User-Agent. - Fix: Used a single fixed User-Agent (
"docuvault-test/1.0") for therevoke_clientfixture. Two sequential logins always create two separate RefreshToken rows regardless of User-Agent. - Files modified:
backend/tests/test_auth.py
3. [Rule 1 - Bug] TOTP replay prevention blocks second session login in CR-03
- Found during: Task 1 — second test run
- Issue: The FakeRedis stores TOTP used-code keys with a 90s TTL. When
_login_with_totp()was called twice in the same 30-second TOTP window,pyotp.TOTP(secret).now()returned the same code which was already marked used in FakeRedis. - Fix: Patched
services.auth.verify_totpto returnTruefor the TOTP login calls in CR-03. The test focuses on session revocation, not TOTP validation. - Files modified:
backend/tests/test_auth.py
4. [Rule 1 - Bug] Celery broker connection attempt on revoked token
- Found during: Task 1 — third test run
- Issue: When
_try_refreshis called with session B's revoked token,rotate_refresh_tokentriggers the family-revocation path which callssend_security_alert_email.delay(...). This attempted a real Redis/Celery broker connection (not available in unit tests). - Fix: Patched
tasks.email_tasksviapatch.dict("sys.modules", {...})inside_try_refresh, matching the pattern fromtest_task2_auth_service.py. - Files modified:
backend/tests/test_auth.py
Verification
3 xpassed, 10 warnings in 2.02s
Full backend suite before this plan (pre-existing): 1 failed (test_extract_docx — ModuleNotFoundError: docx not installed locally), 402 passed
Full backend suite after this plan: same baseline + 3 xpassed new tests added.
The pre-existing test_extractor.py::test_extract_docx failure is a ModuleNotFoundError: No module named 'docx' — the python-docx package is only installed inside Docker, not in the local Python environment. This is out-of-scope and was pre-existing before Plan 08-01.
Threat Flags
None — this plan only adds tests, no new network endpoints, auth paths, file access patterns, or schema changes.
Known Stubs
None — the test bodies contain full assertion logic, not pass placeholders.
Self-Check: PASSED
backend/tests/test_auth.pycreated and contains 3 test functions- All three function names match the exact names specified in the plan
grep -c "pytest.mark.xfail" backend/tests/test_auth.py= 4 (3 decorators + 1 in docstring, baseline was 0)- Commit
f750d30exists:git log --oneline | grep f750d30 - Tests show XPASS status (strict=False xfail)
- No new failures in the full suite