7e62868fea
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
7.4 KiB
7.4 KiB
phase, slug, status, nyquist_compliant, wave_0_complete, created
| phase | slug | status | nyquist_compliant | wave_0_complete | created |
|---|---|---|---|---|---|
| 02 | users-authentication | validated | true | true | 2026-05-31 |
Phase 02 — Validation Strategy
Nyquist validation audit — reconstructed from PLAN/SUMMARY artifacts (State B).
Test Infrastructure
| Property | Value |
|---|---|
| Backend framework | pytest (pytest-asyncio, httpx.AsyncClient) |
| Backend config | backend/pytest.ini |
| Backend quick run | cd backend && python -m pytest tests/test_auth_api.py tests/test_auth_totp.py tests/test_admin_api.py -v |
| Backend full suite | cd backend && python -m pytest -v |
| Frontend framework | Vitest |
| Frontend config | frontend/vitest.config.js |
| Frontend run | cd frontend && npx vitest run |
Per-Task Verification Map
| Task ID | Plan | Wave | Requirement | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|---|---|---|---|---|---|---|---|---|
| 02-01-T1 | 01 | 1 | AUTH-01, AUTH-02 | Argon2 hash, JWT lifecycle, BackupCode model | Unit | pytest tests/test_task1_models_config.py tests/test_task2_auth_service.py -v |
✅ | ✅ green |
| 02-01-T2 | 01 | 1 | AUTH-07, SEC-06 | Refresh family revocation, constant-time backup code verify | Integration | pytest tests/test_task2_auth_service.py -v |
✅ | ✅ green |
| 02-01-T3 | 01 | 1 | AUTH-01, AUTH-02 | get_current_user raises 401 on bad token; get_current_admin raises 403 | Integration | pytest tests/test_auth_deps.py -v |
✅ | ✅ green |
| 02-02-T1 | 02 | 2 | AUTH-01, AUTH-02, AUTH-04 | Register/login/refresh/logout/me/change-password endpoints | Integration | pytest tests/test_auth_api.py -v |
✅ | ✅ green |
| 02-02-T1 | 02 | 2 | SEC-01 | Origin validation middleware rejects cross-origin POST with 403 | Integration | pytest tests/test_auth_api.py::test_origin_rejected -v |
✅ | ✅ green |
| 02-02-T1 | 02 | 2 | SEC-02 | Per-account rate limit: 11th login attempt returns 429 | Integration | pytest tests/test_auth_api.py::test_per_account_rate_limit -v |
✅ | ✅ green |
| 02-02-T1 | 02 | 2 | SEC-05 | CSP + X-Frame-Options + X-Content-Type-Options on all responses | Integration | pytest tests/test_security_headers.py -v |
✅ | ✅ green |
| 02-02-T2 | 02 | 2 | AUTH-01, AUTH-04 | useAuthStore never writes to localStorage; login() passes backup_code | Unit (Vitest) | cd frontend && npx vitest run src/stores/__tests__/auth.test.js |
✅ | ✅ green |
| 02-03-T1 | 03 | 3 | AUTH-03 | TOTP setup returns provisioning_uri; enable rate-limited 10/min | Integration | pytest tests/test_auth_totp.py -v |
✅ | ✅ green |
| 02-03-T1 | 03 | 3 | AUTH-05 | Password reset confirm returns 200 with no access_token (no auto-login) | Integration | pytest tests/test_auth_totp.py::test_password_reset_confirm_valid_no_autologin -v |
✅ | ✅ green |
| 02-03-T1 | 03 | 3 | AUTH-06 | logout-all revokes all refresh tokens | Integration | pytest tests/test_auth_totp.py::test_logout_all_revokes_tokens -v |
✅ | ✅ green |
| 02-03-T1 | 03 | 3 | AUTH-08 | TOTP replay: same code rejected within 90-second window | Integration | pytest tests/test_totp_replay.py -v |
✅ | ✅ green |
| 02-03-T1 | 03 | 3 | SEC-03 | Constant-time comparison: hmac.compare_digest used; verify_password/backup_code reject wrong inputs | Unit | pytest tests/test_constant_time_auth.py -v |
✅ | ✅ green |
| 02-03-T2 | 03 | 3 | AUTH-01 | PasswordStrengthBar: correct 0-4 score (length + char types) | Unit (Vitest) | cd frontend && npx vitest run src/components/auth/__tests__/PasswordStrengthBar.test.js |
✅ | ✅ green |
| 02-04-T1 | 04 | 4 | ADMIN-01 | Admin-created users have password_must_change=True | Integration | pytest tests/test_admin_api.py::test_create_user_sets_password_must_change -v |
✅ | ✅ green |
| 02-04-T1 | 04 | 4 | ADMIN-02 | Deactivate/reactivate user + sole-admin guard | Integration | pytest tests/test_admin_api.py::test_deactivate_user tests/test_admin_api.py::test_cannot_deactivate_only_admin -v |
✅ | ✅ green |
| 02-04-T1 | 04 | 4 | ADMIN-03 | Admin password reset sends email via Celery; no impersonation | Integration | pytest tests/test_admin_api.py::test_password_reset_initiates_email -v |
✅ | ✅ green |
| 02-04-T1 | 04 | 4 | ADMIN-04 | Quota update with warning when limit < used_bytes | Integration | pytest tests/test_admin_api.py::test_quota_below_usage_warning -v |
✅ | ✅ green |
| 02-04-T1 | 04 | 4 | ADMIN-05 | AI provider/model assignment per user | Integration | pytest tests/test_admin_api.py::test_update_ai_config -v |
✅ | ✅ green |
| 02-04-T1 | 04 | 4 | ADMIN-07 | No impersonation endpoint exists (404/422) | Integration | pytest tests/test_admin_api.py::test_admin_impersonation_not_found -v |
✅ | ✅ green |
| 02-04-T1 | 04 | 4 | SEC-07 | get_current_admin enforced: non-admin gets 403 | Integration | pytest tests/test_admin_api.py::test_list_users_requires_admin -v |
✅ | ✅ green |
| 02-04-T2 | 04 | 4 | SEC-07 | Admin responses never include password_hash | Integration | pytest tests/test_admin_api.py::test_admin_response_no_password_hash -v |
✅ | ✅ green |
| 02-05-T2 | 05 | 5 | ADMIN-01..03 | AdminUsersTab: onMount fetch, deactivate call, empty state | Unit (Vitest) | cd frontend && npx vitest run src/components/admin/__tests__/AdminUsersTab.test.js |
✅ | ✅ green |
| 02-05-T2 | 05 | 5 | ADMIN-04 | AdminQuotasTab: save call, below-usage warning displayed | Unit (Vitest) | cd frontend && npx vitest run src/components/admin/__tests__/AdminQuotasTab.test.js |
✅ | ✅ green |
| 02-05-T2 | 05 | 5 | ADMIN-05 | AdminAiConfigTab: save call, 1.5s Saved confirmation | Unit (Vitest) | cd frontend && npx vitest run src/components/admin/__tests__/AdminAiConfigTab.test.js |
✅ | ✅ green |
Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky
Manual-Only Verifications
| Behavior | Requirement | Why Manual | Test Instructions |
|---|---|---|---|
| TOTP QR code renders and scans correctly | AUTH-03 | Requires a physical authenticator app (Google Auth / Authy) | 1. Register + login; 2. GET /api/auth/totp/setup; 3. Open provisioning_uri in authenticator app; 4. Verify 6-digit code is accepted by POST /api/auth/totp/enable |
| Email delivery (SMTP) | AUTH-05, ADMIN-03 | Requires live SMTP server | Configure SMTP_* env vars; trigger password reset; verify email arrives with correct reset link |
| Admin panel browser rendering | ADMIN-01..05 | Vue component visual contract | Start dev server; log in as admin; verify all three tabs render correctly per UI-SPEC |
| httpOnly cookie SameSite=Strict | SEC-01 | Browser DevTools required | Log in via browser; open DevTools → Application → Cookies; verify refresh_token is HttpOnly + SameSite=Strict |
Validation Audit 2026-05-31
| Metric | Count |
|---|---|
| Gaps found | 6 (1 MISSING backend, 2 PARTIAL backend, 3 MISSING frontend) |
| Resolved | 6 |
| Escalated | 0 |
| New test files | 8 |
| Total tests added | 60 (14 backend + 46 frontend) |
Validation Sign-Off
- All tasks have automated verify or Manual-Only justification
- Sampling continuity: no 3 consecutive tasks without automated verify
- Wave 0 covers all MISSING references (gaps filled by audit)
- No watch-mode flags
nyquist_compliant: trueset in frontmatter
Approval: 2026-05-31