Files
kite/.planning/milestones/v0.2-phases/08-stack-upgrade-backend-decomposition/08-01-SUMMARY.md
T
curo1305andClaude Sonnet 4.6 123ae5b29b chore: archive v0.2 phase directories to milestones/v0.2-phases/
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>
2026-06-17 14:34:52 +02:00

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
tests
session-revocation
xfail
wave-0
cr-01
cr-02
cr-03
requires provides affects
behavioral contract for CR-01: change_password revokes other sessions
behavioral contract for CR-02: enable_totp revokes other sessions
behavioral contract for CR-03: disable_totp revokes other sessions
backend/tests/test_auth.py — new file
added patterns
xfail(strict=False) Wave 0 scaffold — tests pass now (xpassed), marker removed in 08-03
FakeRedis in-memory store for all auth/TOTP tests (established pattern)
cookies= kwarg for explicit refresh token injection bypassing path restriction
patch.dict(sys.modules) to prevent Celery broker connection on token replay
created modified
path description
backend/tests/test_auth.py Three xfail tests for CR-01/CR-02/CR-03 session revocation contracts
Used fixed User-Agent on revoke_client fixture to match fgp claim in access tokens
Used DB-direct TOTP enable for CR-03 test to avoid extraneous setup session token
Patched services.auth.verify_totp for CR-03 TOTP logins to bypass 90s replay prevention
Patched tasks.email_tasks via patch.dict(sys.modules) to avoid real Celery connection
duration completed tasks_completed tasks_total files_created files_modified
10m 8s 2026-06-08 1 1 1 0

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, fixed User-Agent: docuvault-test/1.0, DB override
  • db_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_client fixture pattern required FakeRedis injection on app.state.redis. Without it, endpoints that call request.app.state.redis.set(...) (change_password, enable_totp, disable_totp) would fail.
  • Fix: Created dedicated revoke_client fixture with FakeRedis injection, matching the pattern from test_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 fgp claim 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 the revoke_client fixture. 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_totp to return True for 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_refresh is called with session B's revoked token, rotate_refresh_token triggers the family-revocation path which calls send_security_alert_email.delay(...). This attempted a real Redis/Celery broker connection (not available in unit tests).
  • Fix: Patched tasks.email_tasks via patch.dict("sys.modules", {...}) inside _try_refresh, matching the pattern from test_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.py created 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 f750d30 exists: git log --oneline | grep f750d30
  • Tests show XPASS status (strict=False xfail)
  • No new failures in the full suite