4d7b4c83ab
Plans 05-01..05-08 cover all CLOUD-01..07 requirements plus SEC-09 (cloud credential cleanup on account deletion). Key design decisions: API layer owns D-05 token refresh + DB update via _call_cloud_op helper; backends are stateless signal-raisers. Vitest tests added for frontend store and SettingsCloudTab. RESEARCH.md open questions resolved. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.3 KiB
5.3 KiB
phase, slug, status, nyquist_compliant, wave_0_complete, created
| phase | slug | status | nyquist_compliant | wave_0_complete | created |
|---|---|---|---|---|---|
| 5 | 05-cloud-storage-backends | draft | false | false | 2026-05-28 |
Phase 5 — Validation Strategy
Per-phase validation contract for feedback sampling during execution.
Test Infrastructure
| Property | Value |
|---|---|
| Framework | pytest + pytest-asyncio (already in requirements.txt) |
| Config file | backend/pytest.ini (already exists) |
| Quick run command | cd backend && pytest tests/test_cloud.py -x -v |
| Full suite command | cd backend && pytest -v |
| Estimated runtime | ~30 seconds (quick) / ~90 seconds (full) |
Sampling Rate
- After every task commit: Run
cd backend && pytest tests/test_cloud.py -x -v - After every plan wave: Run
cd backend && pytest -v - Before
/gsd:verify-work: Full suite must be green - Max feedback latency: 90 seconds
Per-Task Verification Map
| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|---|---|---|---|---|---|---|---|---|---|
| 05-01-01 | 01 | 0 | CLOUD-01..07 | T-05-01 | Wave 0 stubs; all xfail | unit stub | pytest tests/test_cloud.py -x -v |
❌ Wave 0 | ⬜ pending |
| 05-01-02 | 01 | 0 | CLOUD-02 | T-05-02 | credentials_enc round-trip |
unit | pytest tests/test_cloud.py::test_credential_round_trip -x |
❌ Wave 0 | ⬜ pending |
| 05-02-01 | 02 | 1 | CLOUD-01 | T-05-03 | HKDF encrypt/decrypt round-trip | unit | pytest tests/test_cloud.py::test_credential_round_trip -x |
❌ Wave 0 | ⬜ pending |
| 05-02-02 | 02 | 1 | CLOUD-02, SEC-08 | T-05-04 | credentials_enc not in API response |
integration | pytest tests/test_cloud.py::test_credentials_enc_not_exposed -x |
❌ Wave 0 | ⬜ pending |
| 05-03-01 | 03 | 2 | CLOUD-01 | T-05-05 | OAuth callback validates state, rejects invalid state (400) | integration | pytest tests/test_cloud.py::test_oauth_callback_invalid_state -x |
❌ Wave 0 | ⬜ pending |
| 05-03-02 | 03 | 2 | CLOUD-01 | T-05-06 | SSRF: RFC-1918 and loopback blocked | unit | pytest tests/test_cloud.py::test_ssrf_validation -x |
❌ Wave 0 | ⬜ pending |
| 05-03-03 | 03 | 2 | CLOUD-01 | T-05-07 | WebDAV connection validated before save (D-08) | integration | pytest tests/test_cloud.py::test_webdav_connect_validates -x |
❌ Wave 0 | ⬜ pending |
| 05-04-01 | 04 | 3 | CLOUD-05 | T-05-08 | invalid_grant sets REQUIRES_REAUTH |
integration | pytest tests/test_cloud.py::test_invalid_grant_sets_requires_reauth -x |
❌ Wave 0 | ⬜ pending |
| 05-04-02 | 04 | 3 | CLOUD-06 | T-05-09 | Disconnect permanently deletes credentials_enc from DB |
integration | pytest tests/test_cloud.py::test_disconnect_deletes_credentials -x |
❌ Wave 0 | ⬜ pending |
| 05-05-01 | 05 | 4 | CLOUD-03 | T-05-10 | Cloud upload goes through FastAPI, not presigned URL | integration | pytest tests/test_cloud.py::test_cloud_upload_no_presigned -x |
❌ Wave 0 | ⬜ pending |
| 05-05-02 | 05 | 4 | CLOUD-07 | T-05-11 | StorageBackend factory returns correct type per storage_backend field |
unit | pytest tests/test_cloud.py::test_factory_returns_correct_backend -x |
❌ Wave 0 | ⬜ pending |
| 05-06-01 | 06 | 5 | CLOUD-04 | T-05-12 | Admin cannot see credentials_enc |
integration | pytest tests/test_cloud.py::test_admin_cannot_see_credentials -x |
❌ Wave 0 | ⬜ pending |
| 05-06-02 | 06 | 5 | CLOUD-01 | T-05-13 | Cross-user cloud connection access returns 404 | integration | pytest tests/test_cloud.py::test_cross_user_idor -x |
❌ Wave 0 | ⬜ pending |
Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky
Wave 0 Requirements
backend/tests/test_cloud.py— xfail stubs for all CLOUD-01..07 tests + SSRF + IDOR + admin-blockbackend/tests/conftest.py— new fixtures:mock_google_drive_creds,mock_onedrive_creds,mock_webdav_client,cloud_connection_factory
Existing test infrastructure (pytest, pytest-asyncio, httpx AsyncClient) covers all phase requirements — no new framework install needed.
Manual-Only Verifications
| Behavior | Requirement | Why Manual | Test Instructions |
|---|---|---|---|
| OAuth consent UI for Google Drive | CLOUD-01 | Requires real GCP app credentials + browser | Connect Google Drive from SettingsView Cloud Storage tab; verify OAuth consent screen appears; verify redirect back with success toast |
| OAuth consent UI for OneDrive | CLOUD-01 | Requires real Azure app registration + browser | Connect OneDrive from SettingsView; verify Microsoft OAuth consent; verify redirect back with success toast |
| Sidebar cloud node appearance | CLOUD-03 | Browser UI | After connecting a provider, verify it appears as a top-level sidebar node; expand to see cloud folders |
REQUIRES_REAUTH badge in UI |
CLOUD-05 | Simulated token revocation + browser | Manually set status='REQUIRES_REAUTH' in DB; verify SettingsView shows yellow badge + Reconnect button |
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 < 90s
nyquist_compliant: trueset in frontmatter
Approval: pending