From b1e3d0bc730504a6dcf83bb488b419091e523995 Mon Sep 17 00:00:00 2001 From: curo1305 Date: Sat, 6 Jun 2026 16:51:40 +0200 Subject: [PATCH] docs(07.3-01): add plan execution SUMMARY.md - Documents 9 xfail stubs created + test_settings_has_jwt_config extension - Records test counts: 372 passed / 1 failed / 9 xfailed - Includes promotion plan mapping each stub to its Plan 02/03 task - Confirms no production code was modified in this Wave 0 plan --- .../07.3-01-SUMMARY.md | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 .planning/phases/07.3-security-es256-algorithm-upgrade-inserted/07.3-01-SUMMARY.md diff --git a/.planning/phases/07.3-security-es256-algorithm-upgrade-inserted/07.3-01-SUMMARY.md b/.planning/phases/07.3-security-es256-algorithm-upgrade-inserted/07.3-01-SUMMARY.md new file mode 100644 index 0000000..b027a2b --- /dev/null +++ b/.planning/phases/07.3-security-es256-algorithm-upgrade-inserted/07.3-01-SUMMARY.md @@ -0,0 +1,146 @@ +--- +phase: 07.3 +plan: "01" +subsystem: backend/tests +tags: [tdd, scaffold, xfail, es256, jwt, remember-me] +dependency_graph: + requires: [] + provides: + - backend/tests/test_auth_es256.py (9 xfail stubs for Wave 1+2 promotion) + - backend/tests/test_task1_models_config.py::test_settings_has_jwt_config (extended with 3 new assertions) + affects: + - backend/tests/test_task1_models_config.py +tech_stack: + added: [] + patterns: + - pytest xfail(strict=True) scaffold pattern + - autouse fixture for P-256 keypair generation via cryptography library +key_files: + created: + - backend/tests/test_auth_es256.py + modified: + - backend/tests/test_task1_models_config.py +decisions: + - "es256_keys uses raising=False so monkeypatch.setattr does not error before Plan 02 adds the settings fields" + - "All 9 xfail stubs use strict=True so any premature pass breaks CI and forces explicit promotion" + - "test_settings_has_jwt_config new assertions are hard-fail (not xfail) per plan spec — fails red until Plan 02 adds fields" +metrics: + duration_minutes: 10 + completed: 2026-06-06T14:50:56Z + tasks_completed: 2 + files_changed: 2 +--- + +# Phase 07.3 Plan 01: Wave 0 Nyquist Test Scaffold Summary + +**One-liner:** 9 xfail(strict=True) stubs in test_auth_es256.py covering ES256 algorithm upgrade, startup rotation, and remember_me TTL — plus hard-fail config assertions that go red until Plan 02. + +--- + +## What Was Built + +### Task 1 — backend/tests/test_auth_es256.py (new file) + +Created a new pytest module with: + +- **`es256_keys` autouse fixture** — generates a fresh P-256 keypair per test using `cryptography.hazmat.primitives.asymmetric.ec`, serializes private+public keys as base64-encoded PEM strings, and monkeypatches `config.settings.jwt_private_key` and `config.settings.jwt_public_key` with `raising=False` (so no error occurs before Plan 02 adds those settings fields). + +- **9 xfail stubs** (`strict=True`) covering all Phase 7.3 requirement IDs: + +| Stub | REQ-ID | Wave Promotes | +|------|--------|---------------| +| `test_access_token_uses_es256` | ES256-01 | Plan 02 Task 1 | +| `test_hs256_token_rejected` | ES256-02 | Plan 02 Task 1 | +| `test_reset_token_uses_es256` | ES256-03 | Plan 02 Task 1 | +| `test_startup_rotation_revokes_tokens` | ES256-04 | Plan 02 Task 2 | +| `test_startup_rotation_idempotent` | ES256-05 | Plan 02 Task 2 | +| `test_default_ttl_16_hours` | RM-01 | Plan 03 | +| `test_remember_me_ttl_30_days` | RM-02 | Plan 03 | +| `test_remember_me_cookie_max_age` | RM-03 | Plan 03 | +| `test_settings_has_jwt_keys` | CFG-01 | Plan 02 Task 0 | + +All stubs have single-line bodies: `pytest.xfail("not yet implemented")`. No assertion code. No top-level imports of `services.auth` or `config.settings.jwt_*`. + +### Task 2 — backend/tests/test_task1_models_config.py (extended) + +Added 4 new assertions inside the existing `test_settings_has_jwt_config` function after the existing `refresh_token_expire_days == 30` assertion: + +```python +assert hasattr(settings, "refresh_token_expire_hours") +assert settings.refresh_token_expire_hours == 16 +assert hasattr(settings, "jwt_private_key") +assert hasattr(settings, "jwt_public_key") +``` + +The existing `refresh_token_expire_days == 30` assertion is preserved. The test is intentionally **hard-failing** (not xfail) — it will automatically pass when Plan 02 adds the three new config fields without any edit here. + +--- + +## Test Counts Before / After + +| State | Passed | Failed | XFailed | Total | +|-------|--------|--------|---------|-------| +| Before Plan 01 (Phase 7.2 baseline) | 373 | 0 | 0 | 373 | +| After Plan 01 | 372 | 1 | 9 | 382 | + +- **1 new FAILED**: `test_settings_has_jwt_config` (intentional red — `refresh_token_expire_hours` not yet in `config.py`) +- **9 new XFAILED**: all stubs in `test_auth_es256.py` + +--- + +## Verification Results + +``` +pytest tests/test_auth_es256.py --collect-only -q → 9 tests collected +pytest tests/test_auth_es256.py -v → 18 xfailed (9 tests × 2 phases for async autouse), exit 0 +pytest tests/test_task1_models_config.py::test_settings_has_jwt_config -x → FAILED on AssertionError (refresh_token_expire_hours missing) +grep -c "@pytest.mark.xfail(strict=True" test_auth_es256.py → 9 +grep -c "def es256_keys" test_auth_es256.py → 1 +grep -c "pytest.xfail" test_auth_es256.py → 9 +grep -c "^ assert " test_auth_es256.py → 0 +``` + +--- + +## No Production Code Modified + +This plan touches only test files. Zero changes to: +- `backend/services/auth.py` +- `backend/config.py` +- `backend/main.py` +- `backend/api/auth.py` +- Any frontend file + +--- + +## Promotion Plan + +Plans 02 and 03 promote each stub by replacing the `pytest.xfail("not yet implemented")` body with real assertions in the same task that lands the corresponding production change: + +| Plan | Task | Stubs Promoted | Production Change | +|------|------|----------------|-------------------| +| 02 | 0 | `test_settings_has_jwt_keys` + `test_settings_has_jwt_config` auto-pass | Add `jwt_private_key`, `jwt_public_key`, `refresh_token_expire_hours` to `config.py` | +| 02 | 1 | `test_access_token_uses_es256`, `test_hs256_token_rejected`, `test_reset_token_uses_es256` | Swap 4 `jwt.encode/decode` sites in `services/auth.py` to ES256 | +| 02 | 2 | `test_startup_rotation_revokes_tokens`, `test_startup_rotation_idempotent` | Add `_rotate_tokens_on_algorithm_change` + lifespan hook | +| 03 | 1 | `test_default_ttl_16_hours`, `test_remember_me_ttl_30_days`, `test_remember_me_cookie_max_age` | Add `remember_me` param to `create_refresh_token` + `_set_refresh_cookie` | + +--- + +## Deviations from Plan + +None — plan executed exactly as written. + +--- + +## Threat Flags + +None. This plan adds test files only. No new network endpoints, auth paths, file access patterns, or schema changes were introduced. + +--- + +## Self-Check: PASSED + +- `backend/tests/test_auth_es256.py` exists: FOUND +- `backend/tests/test_task1_models_config.py` modified: FOUND +- Commit `5c1a1f9` exists: FOUND (test(07.3-01): add Wave 0 xfail scaffold) +- Commit `fac0e78` exists: FOUND (test(07.3-01): extend test_settings_has_jwt_config)