3 plans (Wave 0 test scaffolding, Wave 1 jti+NBF check, Wave 2 user_nbf writes), VALIDATION.md, RESEARCH.md with resolved open questions. Checker: 0 blockers, 1 warning resolved (RESEARCH.md open questions marked). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.0 KiB
5.0 KiB
phase, slug, status, nyquist_compliant, wave_0_complete, created
| phase | slug | status | nyquist_compliant | wave_0_complete | created |
|---|---|---|---|---|---|
| 7.2 | security-jti-claim-redis-access-token-revocation-inserted | draft | false | false | 2026-06-05 |
Phase 7.2 — Validation Strategy
Per-phase validation contract for feedback sampling during execution.
Test Infrastructure
| Property | Value |
|---|---|
| Framework | pytest + pytest-asyncio |
| Config file | backend/pytest.ini |
| Quick run command | pytest tests/test_auth_deps.py tests/test_auth_api.py tests/test_admin_api.py -v |
| Full suite command | cd backend && pytest -v |
| Estimated runtime | ~30 seconds |
Sampling Rate
- After every task commit: Run
pytest tests/test_auth_deps.py tests/test_auth_api.py tests/test_admin_api.py -v - After every plan wave: Run
cd backend && pytest -v - Before
/gsd:verify-work: Full suite must be green - Max feedback latency: ~30 seconds
Per-Task Verification Map
| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|---|---|---|---|---|---|---|---|---|---|
| jti-claim | 01 | 0 | SEC (JTI) | — | Every access token contains a jti UUID key |
unit | pytest tests/test_task2_auth_service.py -k jti -v |
❌ W0 | ⬜ pending |
| test-fakeredis | 01 | 0 | SEC (infra) | — | test_auth_deps.py test app has app.state.redis set |
unit | pytest tests/test_auth_deps.py -v |
❌ W0 | ⬜ pending |
| nbf-write-change-password | 02 | 1 | SEC (NBF-write) | T-7.2-01 | change_password writes user_nbf:{user_id} to Redis |
integration | pytest tests/test_auth_api.py -k nbf -v |
❌ W0 | ⬜ pending |
| nbf-write-enable-totp | 02 | 1 | SEC (NBF-write) | T-7.2-01 | enable_totp writes user_nbf:{user_id} to Redis |
integration | pytest tests/test_auth_api.py -k nbf -v |
❌ W0 | ⬜ pending |
| nbf-write-disable-totp | 02 | 1 | SEC (NBF-write) | T-7.2-01 | disable_totp writes user_nbf:{user_id} to Redis |
integration | pytest tests/test_auth_api.py -k nbf -v |
❌ W0 | ⬜ pending |
| nbf-write-deactivation | 03 | 1 | SEC (NBF-write) | T-7.2-01 | admin deactivation writes user_nbf:{user_id} to Redis |
integration | pytest tests/test_admin_api.py -k nbf -v |
❌ W0 | ⬜ pending |
| nbf-check-reject | 04 | 1 | SEC (NBF-check) | T-7.2-02 | Token with iat < user_nbf returns HTTP 401 |
integration | pytest tests/test_auth_deps.py -k nbf -v |
❌ W0 | ⬜ pending |
| nbf-check-allow | 04 | 1 | SEC (NBF-check) | T-7.2-03 | Token with iat > user_nbf is accepted |
integration | pytest tests/test_auth_deps.py -k nbf_after -v |
❌ W0 | ⬜ pending |
| nbf-fail-open | 04 | 1 | SEC (fail-open) | T-7.2-04 | Redis error in NBF check does not block request | unit | pytest tests/test_auth_deps.py -k failopen -v |
❌ W0 | ⬜ pending |
Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky
Wave 0 Requirements
backend/tests/test_task2_auth_service.py— add JTI presence test forcreate_access_tokenbackend/tests/test_auth_deps.py— addapp.state.redis = FakeRedis()tomake_test_app()or auth_client fixture; add NBF-check tests (iat < nbf → 401, iat > nbf → pass, Redis error → pass)backend/tests/test_auth_api.py— add NBF-write stub tests forchange_password,enable_totp,disable_totpbackend/tests/test_admin_api.py— add NBF-write stub test for deactivation handler
Existing 34+ auth tests in test_auth_deps.py and test_auth_api.py must remain green with zero regressions.
Manual-Only Verifications
| Behavior | Requirement | Why Manual | Test Instructions |
|---|---|---|---|
| Recovering session after password change | SEC (pitfall 3) | Requires live frontend + token refresh flow | 1. Login. 2. Change password via API. 3. Use old access token → expect 401. 4. Use refresh token → expect new access token with iat > nbf. 5. Confirm new token works. |
Threat Model
| Threat | STRIDE | Mitigation in this phase |
|---|---|---|
| T-7.2-01: Stolen access token replay after security event | EoP | user_nbf:{user_id} Redis key blocks all tokens with iat before the event |
| T-7.2-02: HTTPException swallowed by fail-open catch | EoP | Explicit except HTTPException: raise guard before broad except Exception in get_current_user |
| T-7.2-03: Wrong comparison direction in NBF check | EoP | payload["iat"] < nbf_timestamp — token issued BEFORE event → reject |
| T-7.2-04: Redis outage bypasses revocation check | DoS/EoP | Fail-open accepted (D-04); availability > revocation during outage — known trade-off |
Validation Sign-Off
- All tasks have
<automated>verify or Wave 0 dependencies - Sampling continuity: no 3 consecutive tasks without automated verify
- Wave 0 covers all MISSING references
- No watch-mode flags
- Feedback latency < 30s
nyquist_compliant: trueset in frontmatter
Approval: pending