docs(14-09): Phase 14 closeout — docs, version bump v0.3.0→v0.4.0, security evidence

- CLAUDE.md/AGENTS.md: update current-state line to v0.4.0 Phase 14 complete;
  add Phase 14 shared module map entries (cloud_cache, cloud_analysis,
  cloud_analysis_processing, cloud_analysis_tasks, analysis router, cache API);
  add Phase 14 non-negotiable rules (hydrate_and_cache_bytes single entry point,
  IDs-only broker payload, object_key/credentials_enc excluded at schema level)
- README.md: bump to v0.4.0; add Selective cloud analysis and Cloud byte cache
  features; add Analysis API table (Phase 14 endpoints)
- SECURITY.md: add Phase 14 threat register (T-14-01..T-14-15) with evidence,
  security gate results, and accepted risks
- backend/main.py: bump FastAPI version to 0.4.0
- frontend/package.json: bump version to 0.4.0
- ROADMAP.md: mark Phase 14 complete (9/9 plans), plan 14-09 checked off
- 14-VALIDATION.md: gate evidence, requirement coverage, acceptance criteria check
- 14-SECURITY.md: security evidence summary and gate checklist

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
curo1305
2026-06-23 20:05:49 +02:00
co-authored by Claude Sonnet 4.6
parent 2d697a6036
commit 90e1b525f1
9 changed files with 287 additions and 18 deletions
+23 -6
View File
@@ -4,7 +4,7 @@
DocuVault is a multi-user SaaS document management platform built on FastAPI (Python) + Vue 3. It handles document upload, text extraction (PDF/DOCX/image/text), AI-based topic classification, per-user isolated storage, folder organization, document sharing, and pluggable cloud storage backends (OneDrive, Google Drive, Nextcloud, WebDAV).
**Current state:** v0.2.5 — Phase 12.1 Plan 03 complete (2026-06-22). Cloud frontend aligned with normalized API: `kind` field for item classification, `provider_item_id` for opaque provider navigation, server freshness state mapped verbatim, explicit breadcrumb lineage. Phase 12.1 in progress. Not cleared for public internet deployment.
**Current state:** v0.4.0 — Phase 14 complete (2026-06-23). Selective cloud analysis with per-file/selection/folder/connection scope, byte cache with LRU eviction and ownership-scoped pinning, Celery-backed processing pipeline (download/extract/classify), authorized open/preview/download routed through the durable cache, frontend analysis queue with per-item controls, and cache/settings controls in Settings. 856 backend + 471 frontend tests pass. Not cleared for public internet deployment.
## Stack
@@ -42,9 +42,18 @@ Before adding a helper, check if it belongs in an existing shared module:
| `backend/storage/exceptions.py` | `CloudConnectionError` — single canonical definition; all files import from here |
| `backend/ai/utils.py` | `strip_code_fences`, `parse_classification`, `parse_suggestions` — AI response parsing shared by all providers |
| `backend/services/auth.py` | `validate_password_strength(password)` — raises `ValueError`; routers catch and re-raise as `HTTPException` |
| `backend/storage/cloud_base.py` | `CloudResourceAdapter`, `CloudListing`, `CloudResource`, `CloudCapability` — Phase 12 browse contract |
| `backend/services/cloud_items.py` | `resolve_owned_connection`, `upsert_cloud_item`, `reconcile_cloud_listing` — owner-scoped metadata service |
| `backend/api/cloud/schemas.py` | `CloudBrowseResponse`, `CloudItemOut`, `FolderFreshnessOut` — credential-free response schemas |
| `backend/storage/cloud_base.py` | `CloudResourceAdapter`, `CloudListing`, `CloudResource`, `CloudCapability`, `CloudMutableAdapter` — Phase 12/13 browse+mutation contract; all 4 providers implement both |
| `backend/storage/cloud_utils.py` | `validate_cloud_url`, `normalize_nextcloud_url`, `encrypt_credentials`, `decrypt_credentials` |
| `backend/services/cloud_items.py` | `resolve_owned_connection`, `upsert_cloud_item`, `reconcile_cloud_listing`, `get_or_create_folder_state`, `apply_listing_and_finalize`, `ListingResult` — owner-scoped cloud metadata service |
| `backend/services/cloud_operations.py` | `keep_both_name`, `run_health_check`, `run_reconnect`, `run_upload`, `run_create_folder`, `run_rename`, `run_move`, `run_delete` — all mutation orchestration with stale guard, reconciliation, and metadata-only audit |
| `backend/services/cloud_cache.py` | `compute_version_key`, `create_cache_entry`, `evict_lru_entries`, `retain_or_reuse_cache_entry`, `pin_cache_entry`, `release_cache_entry`, `hydrate_and_cache_bytes` — Phase 14 byte cache lifecycle (CACHE-03/CACHE-04/CACHE-05) |
| `backend/services/cloud_analysis.py` | `estimate_scope`, `enqueue_analysis_job`, `get_analysis_job`, `cancel_job`, `cancel_job_item`, `skip_job_item`, `retry_job_item`, `check_scan_quota` — Phase 14 analysis orchestration (ANALYZE-01..07) |
| `backend/services/cloud_analysis_processing.py` | `process_job_item`, `ProcessingResult` — single-item pipeline: stale guard, cache hydration, extraction, classification, cooperative cancellation |
| `backend/tasks/cloud_analysis_tasks.py` | `process_cloud_analysis_item` — Celery task, ID-only broker payload, bounded retry (30s/90s/270s) |
| `backend/api/cloud/schemas.py` | `CloudBrowseResponse`, `CloudItemOut`, `FolderFreshnessOut`, `CloudMutationResult`, `CloudUploadResult`, `AnalysisEstimateOut`, `AnalysisJobOut`, `CacheStatusOut` — credential-free response schemas |
| `backend/api/cloud/analysis.py` | Analysis router aggregator — `/api/cloud/analysis/*` namespace |
| `backend/api/cloud/operations.py` | Cloud mutation routes (Phase 13) and authorized open/preview/download (Phase 13/14) |
| `backend/api/cloud/cache.py` | `GET /analysis/cache`, `PATCH /analysis/cache/settings` — aggregate cache status/settings, no object_key |
**Rules:**
- No router may define `_ip()`, `_get_ip()`, or any other local variant of `get_client_ip`. Import from `deps.utils`.
@@ -54,6 +63,14 @@ Before adding a helper, check if it belongs in an existing shared module:
- Service layer raises `ValueError` (or domain exceptions), never `HTTPException`. Only the router layer raises `HTTPException`.
- Cloud browse responses must use `api/cloud/schemas.py` whitelisted types — never return raw ORM objects.
- `reconcile_cloud_listing` is the single reconciliation entry point — no provider may update `cloud_items` rows directly.
- `NextcloudBackend` must NOT override `list_folder` — it inherits the canonical `WebDAVBackend` implementation.
- No caller of `adapter.list_folder` may independently call `update_folder_state(refresh_state="fresh")`. Use `apply_listing_and_finalize` from `services.cloud_items`.
- Phase 13/14 mutation responses use `JSONResponse` (not `HTTPException`) so `kind`/`reason` appear at response top level.
- All cloud mutation orchestration routes through `services.cloud_operations` — never inline in the router.
- All byte cache lifecycle calls route through `hydrate_and_cache_bytes` in `services.cloud_cache` — never call `adapter.get_object` directly in open/preview/download routes.
- `process_cloud_analysis_item` Celery task accepts UUIDs only — credentials decrypted inside the worker after revalidation (no credentials in broker payload).
- `CacheStatusOut` and `AnalysisJobOut` never include `object_key` or `credentials_enc` — enforced at schema level.
- `testCloudConnection` is an explicit user-initiated action only — never called as a side effect of folder navigation (D-13).
### Frontend: shared module map
@@ -127,9 +144,9 @@ Before any GSD workflow or agent edits project files, create or switch into a de
/gsd:progress — check status and advance workflow
```
### Current state: v0.2.1 — Phase 12 gap-closure complete (2026-06-20)
### Current state: v0.4.0 — Phase 14 complete (2026-06-23)
Phase 12 gap-closure: migration-gated Compose startup (migrate service, service_completed_successfully dependency gate on backend/worker/beat), 0005→0006 upgrade regression tests (test_migration_0006.py), RUNBOOK migration ops section. Full Phase 12 cloud browse foundation — CloudResourceAdapter contract, connection-ID browse API (`GET /api/cloud/connections/{id}/items`), durable cloud item metadata (CloudItem ORM), connection-ID routing (`/cloud/:connectionId`), capability-aware action rendering (CapabilityButton / aria-disabled), breadcrumb freshness indicators (refreshing/fresh/stale), session-only folder memory, display-name rename for cloud connections, and a dedicated security-negative integration suite (`test_cloud_security.py`). Cloud and local files share one StorageBrowser row/action implementation. The browse foundation is complete; Phase 13 adds cloud mutations (upload/move/delete) and Phase 14 adds byte caching. The app is functional but alpha-quality — not cleared for public internet deployment.
Phase 14 complete (2026-06-23): Selective cloud analysis with per-file, selection, folder, and connection scopes; scope estimates from durable metadata only (zero provider bytes during estimate); idempotent analysis jobs with already-current/unsupported detection; Celery processing pipeline (download → extract → classify) with cooperative cancellation, stale guard, bounded retry, and cache pinning in finally block; durable byte cache (CloudByteCacheEntry) with LRU eviction, per-user quota accounting, and ownership-scoped pinning; open/preview/download routed through the byte cache lifecycle; frontend analysis queue with per-item cancel/retry/skip and aggregate progress indicator; Settings controls for cache limit, progress detail, and failure behavior. 856 backend + 471 frontend tests pass. Not cleared for public internet deployment.
## Development Setup