feat(phase-4): complete UX redesign — FileManagerView, FolderTreeItem, test suite, and all Phase 4 fixes
Adds the unified file manager view (Windows Explorer-style), collapsible folder tree sidebar item, full vitest test suite (55 tests, 4 files), and commits all Phase 4 backend/frontend fixes that were staged but uncommitted. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -67,6 +67,103 @@ cd frontend && npm run dev
|
||||
cd backend && pytest -v
|
||||
```
|
||||
|
||||
## Testing Protocol (Non-Negotiable)
|
||||
|
||||
Every feature, function, and bug fix requires tests. No phase or plan may advance until all tests pass.
|
||||
|
||||
### Rules
|
||||
|
||||
- **Coverage**: Every new function, endpoint, and UI component must have at least one test — unit for isolated logic, integration for DB/service boundaries, E2E for critical user flows
|
||||
- **Gate**: `pytest -v` (backend) and frontend test suite must pass with zero failures before marking a plan complete or advancing to the next phase
|
||||
- **Bug fixes**: Must fix the root cause, not work around it. Maximum 50 lines of changed code per fix. If a fix requires more, it is scope-creep and must be broken into a separate plan
|
||||
- **No workarounds**: `# type: ignore`, `noqa`, skipping a test, or adding a `try/except` that silently swallows an error are prohibited as bug fixes
|
||||
- **Regression**: Any time a bug is fixed, a test must be added that would have caught it
|
||||
|
||||
### Test types per layer
|
||||
|
||||
| Layer | Required test type |
|
||||
|---|---|
|
||||
| Service / business logic | Unit tests with mocked dependencies |
|
||||
| DB queries / ORM | Integration tests against real PostgreSQL (not SQLite for quota/UUID tests) |
|
||||
| API endpoints | `httpx.AsyncClient` integration tests with real DB fixtures |
|
||||
| Auth flows | Full round-trip tests (register → login → TOTP → refresh → revoke) |
|
||||
| Security invariants | Dedicated negative tests (wrong owner → 403/404, admin → 403, replay → 401) |
|
||||
| Frontend | Vitest unit tests for stores/composables; Playwright or Cypress for critical flows |
|
||||
|
||||
---
|
||||
|
||||
## Security Protocol (Non-Negotiable)
|
||||
|
||||
A dedicated **security agent** runs after every plan execution and before any phase is marked complete. This agent has full read/write/edit access to the entire codebase and is the final gate before advancement.
|
||||
|
||||
### Security agent mandate
|
||||
|
||||
The security agent must check — and fix — every class of vulnerability listed below. It may not flag and defer; it must resolve or escalate blocking issues.
|
||||
|
||||
#### OWASP Top 10 + auth-specific
|
||||
|
||||
| Threat | Required mitigation |
|
||||
|---|---|
|
||||
| SQL injection | All queries via ORM or parameterized statements — zero raw string interpolation |
|
||||
| XSS | CSP headers, `httpOnly` cookies, no `innerHTML` with user data, Vue template auto-escaping never bypassed |
|
||||
| CSRF | `SameSite=Strict` cookie + `Origin`/`Referer` header validation on all state-changing endpoints |
|
||||
| Broken auth | Short-lived JWT (≤15 min), refresh rotation, family revocation on reuse, constant-time comparison |
|
||||
| IDOR / broken access control | Every resource endpoint asserts `resource.user_id == current_user.id`; admin blocked from document content |
|
||||
| Security misconfiguration | No debug mode in production, no stack traces in API responses, no default credentials |
|
||||
| Sensitive data exposure | Passwords hashed Argon2id, PII fields encrypted at rest, `credentials_enc` never in API responses |
|
||||
| Insecure deserialization | No `pickle`, no `eval`, no dynamic `__import__`; all user-supplied data validated via Pydantic |
|
||||
| Vulnerable dependencies | `pip audit` / `npm audit` run; critical/high CVEs blocked |
|
||||
| Insufficient logging | All auth events, quota violations, and admin actions written to audit log without document content |
|
||||
|
||||
#### Advanced threats
|
||||
|
||||
- **Path traversal**: All file path construction uses `os.path.basename` / `pathlib` — never joins user-supplied strings directly
|
||||
- **SSRF**: All outbound HTTP (HIBP, cloud OAuth) via an allowlisted client; user-supplied URLs for WebDAV/Nextcloud must pass hostname allowlist
|
||||
- **Timing attacks**: `hmac.compare_digest` / `secrets.compare_digest` for all token, TOTP, and backup-code comparison — no `==`
|
||||
- **Race conditions / TOCTOU**: Quota enforcement via single atomic `UPDATE … RETURNING` — never read-then-write in Python
|
||||
- **Mass assignment**: Pydantic models explicitly declare every accepted field; no `**kwargs` passthrough from request body to ORM
|
||||
- **Privilege escalation**: `get_regular_user` and `get_current_admin` deps checked on every endpoint; no role elevation path exists
|
||||
- **Token replay**: JTI stored in DB; used TOTP codes invalidated within the 90 s window; refresh token family revocation on reuse
|
||||
|
||||
#### Zero-day / defense-in-depth
|
||||
|
||||
- **Minimal attack surface**: Every endpoint that is not needed is absent — no commented-out code, no `TODO: remove` endpoints left alive
|
||||
- **Principle of least privilege**: `docuvault_app` DB role has DML only; `docuvault_migrate` has DDL; MinIO bucket policy denies public access
|
||||
- **Secrets in env only**: No credentials, API keys, or signing secrets in code, commits, or `.env` files checked in; `.gitignore` enforces this
|
||||
- **Dependency pinning**: `requirements.txt` and `package-lock.json` pin exact versions; no floating `>=` for security-critical packages (PyJWT, pwdlib, cryptography)
|
||||
- **Container hardening**: Non-root user in Dockerfile, read-only filesystem where possible, no `--privileged` containers
|
||||
- **Header hardening**: `X-Content-Type-Options: nosniff`, `X-Frame-Options: DENY`, `Referrer-Policy: strict-origin-when-cross-origin` on every response
|
||||
|
||||
### Database user table encryption
|
||||
|
||||
Sensitive user PII (email, display name) must be encrypted at the application layer before storage:
|
||||
|
||||
- Encryption: AES-256-GCM via `cryptography` library, per-row nonce, master key from env var
|
||||
- Key derivation: HKDF-SHA256 with `purpose=b"user-pii"` salt — same pattern as cloud credentials
|
||||
- Admin queries: never return plaintext PII for users other than the requesting user
|
||||
- Indexing: email lookup uses a deterministic HMAC-SHA256 index (`email_hmac` column) — the encrypted column is never used for WHERE clauses
|
||||
|
||||
### Login token hardening (state of the art)
|
||||
|
||||
- **Algorithm**: ES256 (ECDSA P-256) — asymmetric; the private key signs, the public key verifies; a leaked public key cannot forge tokens
|
||||
- **Access token TTL**: 15 minutes maximum
|
||||
- **Refresh token**: 30-day httpOnly Strict cookie; rotated on every use; reuse of a rotated token revokes entire family and fires a security alert email
|
||||
- **JTI claim**: Every token has a unique `jti`; revoked JTIs stored in Redis with TTL matching the token lifetime
|
||||
- **Token binding**: Access token embeds a `fgp` (fingerprint) claim = HMAC of `User-Agent + Accept-Language`; backend validates on every request
|
||||
- **Rotation on privilege change**: Password change, TOTP enroll/revoke, and account deactivation immediately revoke all active sessions
|
||||
|
||||
### Security gate checklist (must all pass before phase advances)
|
||||
|
||||
- [ ] `bandit -r backend/` — zero HIGH severity findings
|
||||
- [ ] `pip audit` — zero critical/high CVEs
|
||||
- [ ] `npm audit --audit-level=high` — zero high/critical vulnerabilities
|
||||
- [ ] All security-invariant tests pass (wrong owner, admin block, token replay, CSRF)
|
||||
- [ ] No new `# noqa: S` suppressions without a documented justification comment
|
||||
- [ ] Admin endpoints verified to never return `password_hash`, `credentials_enc`, or document content
|
||||
- [ ] No hardcoded secrets detected by `git secrets` / `trufflehog`
|
||||
|
||||
---
|
||||
|
||||
## Security Requirements (Non-Negotiable)
|
||||
|
||||
- Rate limiting on all auth endpoints (login, register, password reset, TOTP)
|
||||
|
||||
Reference in New Issue
Block a user