docs(phase-14): plan selective analysis and byte cache
This commit is contained in:
@@ -111,6 +111,20 @@ Plans:
|
||||
|
||||
**Depends on:** Phase 13
|
||||
**Requirements:** ANALYZE-01, ANALYZE-02, ANALYZE-03, ANALYZE-04, ANALYZE-05, ANALYZE-06, ANALYZE-07, CACHE-03, CACHE-04, CACHE-05
|
||||
**Plans:** 0/9 plans complete
|
||||
**Execution waves:** Wave 0: 14-01; Wave 1: 14-02 after 14-01; Wave 2: 14-03 after 14-02; Wave 3: 14-04 after 14-02 and 14-03; Wave 4: 14-05 after 14-03 and 14-04; Wave 5: 14-06 after 14-03 and 14-05; Wave 6: 14-07 after 14-04 and 14-05; Wave 7: 14-08 after 14-03 and 14-07; Wave 8: 14-09 after 14-01 through 14-08.
|
||||
|
||||
Plans:
|
||||
|
||||
- [ ] 14-01-PLAN.md — Create red backend/frontend tests for analysis scopes, estimates, cache invariants, queue states, and security negatives.
|
||||
- [ ] 14-02-PLAN.md — Add durable cache/job/settings schema plus version-key and settings helpers.
|
||||
- [ ] 14-03-PLAN.md — Implement owner-scoped byte cache service, quota accounting, pinning, eviction, and cache settings/status API.
|
||||
- [ ] 14-04-PLAN.md — Implement estimate/enqueue/status/cancel/skip/retry analysis APIs with idempotent job creation.
|
||||
- [ ] 14-05-PLAN.md — Implement Celery-backed cloud analysis processing, cache hydration, extraction, classification, and cancellation.
|
||||
- [ ] 14-06-PLAN.md — Route existing cloud open/preview/download byte hydration through the bounded cache lifecycle.
|
||||
- [ ] 14-07-PLAN.md — Wire shared-browser analysis actions, estimates, aggregate progress, expandable queue, and controls.
|
||||
- [ ] 14-08-PLAN.md — Add Settings controls for cache limit, progress detail, and failure behavior.
|
||||
- [ ] 14-09-PLAN.md — Run closeout docs, versions, full test/security gates, validation, commit, and push.
|
||||
|
||||
**Success Criteria:**
|
||||
|
||||
|
||||
+16
-16
@@ -2,17 +2,17 @@
|
||||
gsd_state_version: 1.0
|
||||
milestone: v0.3
|
||||
milestone_name: Reimagining Cloud Storage integration
|
||||
current_phase: 13
|
||||
current_phase_name: virtual-local-cloud-operations
|
||||
status: complete
|
||||
stopped_at: Phase 14 context gathered
|
||||
last_updated: "2026-06-23T12:04:31.598Z"
|
||||
current_phase: 14
|
||||
current_phase_name: selective-analysis-and-byte-cache
|
||||
status: planned
|
||||
stopped_at: Phase 14 planned
|
||||
last_updated: "2026-06-23T00:00:00.000Z"
|
||||
last_activity: 2026-06-23
|
||||
last_activity_desc: Phase 13 complete, v0.3.0 shipped
|
||||
progress:
|
||||
total_phases: 6
|
||||
completed_phases: 3
|
||||
total_plans: 21
|
||||
total_plans: 30
|
||||
completed_plans: 21
|
||||
percent: 50
|
||||
---
|
||||
@@ -20,15 +20,15 @@ progress:
|
||||
# Project State
|
||||
|
||||
**Project:** DocuVault
|
||||
**Status:** Phase 13 complete — ready to begin Phase 14
|
||||
**Status:** Phase 14 planned — ready to execute Plan 14-01
|
||||
**Last Updated:** 2026-06-23
|
||||
|
||||
## Current Position
|
||||
|
||||
Phase: 13 (virtual-local-cloud-operations) — COMPLETE
|
||||
Plan: 11 of 11
|
||||
Status: Phase 13 complete. Next: Phase 14 (Selective Analysis and Byte Cache)
|
||||
Last activity: 2026-06-23 — Phase 13 complete, v0.3.0 shipped
|
||||
Phase: 14 (selective-analysis-and-byte-cache) — PLANNED
|
||||
Plan: 0 of 9
|
||||
Status: Phase 14 planned. Next: execute 14-01 red contract tests
|
||||
Last activity: 2026-06-23 — Phase 14 plan files created
|
||||
|
||||
## Phase Status
|
||||
|
||||
@@ -37,7 +37,7 @@ Last activity: 2026-06-23 — Phase 13 complete, v0.3.0 shipped
|
||||
| 12. Cloud Resource Foundation | CONN-04, CLOUD-01, CLOUD-08, CACHE-01, CACHE-02, SYNC-01 | **Complete** |
|
||||
| 12.1 Fix Nextcloud Root Listing and Sync Visibility | CONN-04, CLOUD-01, CACHE-01, SYNC-01 | **Complete** |
|
||||
| 13. Virtual-Local Cloud Operations | CONN-01..03, CLOUD-02..07, CLOUD-09 | **Complete** |
|
||||
| 14. Selective Analysis and Byte Cache | ANALYZE-01..07, CACHE-03..05 | **Not started** |
|
||||
| 14. Selective Analysis and Byte Cache | ANALYZE-01..07, CACHE-03..05 | **Planned** |
|
||||
| 15. Unified Smart Search | SEARCH-01..07 | **Not started** |
|
||||
| 16. Change Tracking and Reliability | SYNC-02..04 | **Not started** |
|
||||
|
||||
@@ -91,7 +91,7 @@ Last activity: 2026-06-23 — Phase 13 complete, v0.3.0 shipped
|
||||
- v0.2 completed: UI overhaul, admin panel rearchitecture, responsive layout, codebase quality (2026-06-17)
|
||||
- v0.2 archived to `.planning/milestones/v0.2-ROADMAP.md`
|
||||
- v0.3 in progress: Phase 12 (cloud resource foundation) complete 2026-06-21; Phase 12.1 (Nextcloud fix) complete; Phase 13 (virtual-local cloud operations) complete 2026-06-23 — v0.3.0 shipped
|
||||
- Phase 14 (selective analysis and byte cache) is next
|
||||
- Phase 14 (selective analysis and byte cache) planned 2026-06-23
|
||||
|
||||
### Open Questions
|
||||
|
||||
@@ -103,16 +103,16 @@ None.
|
||||
|
||||
## Session Continuity
|
||||
|
||||
**Stopped at:** Phase 14 context gathered
|
||||
**Stopped at:** Phase 14 planned
|
||||
|
||||
_Updated at each phase transition._
|
||||
|
||||
| Field | Value |
|
||||
|---|---|
|
||||
| Last session | 2026-06-23T12:04:31.592Z |
|
||||
| Next action | Begin Phase 14 (Selective Analysis and Byte Cache) |
|
||||
| Next action | Execute 14-01 red contract tests |
|
||||
| Pending decisions | None |
|
||||
| Resume file | .planning/phases/14-selective-analysis-and-byte-cache/14-CONTEXT.md |
|
||||
| Resume file | .planning/phases/14-selective-analysis-and-byte-cache/14-01-PLAN.md |
|
||||
|
||||
## Decisions
|
||||
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
---
|
||||
phase: "14"
|
||||
plan: "01"
|
||||
type: execute
|
||||
wave: 0
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- backend/tests/test_cloud_analysis_contract.py
|
||||
- backend/tests/test_cloud_cache.py
|
||||
- backend/tests/test_cloud_analysis_api.py
|
||||
- frontend/src/components/storage/__tests__/StorageBrowser.analysis-queue.test.js
|
||||
- frontend/src/stores/__tests__/cloudConnections.analysis.test.js
|
||||
autonomous: true
|
||||
requirements:
|
||||
- ANALYZE-01
|
||||
- ANALYZE-02
|
||||
- ANALYZE-03
|
||||
- ANALYZE-04
|
||||
- ANALYZE-05
|
||||
- ANALYZE-06
|
||||
- ANALYZE-07
|
||||
- CACHE-03
|
||||
- CACHE-04
|
||||
- CACHE-05
|
||||
---
|
||||
|
||||
<objective>
|
||||
Create the Phase 14 executable test contract before implementation. Establish red backend and frontend tests for analysis scope selection, estimates, duplicate-version skips, cache ownership/quota semantics, cancellation/retry controls, and the shared-browser queue surface.
|
||||
|
||||
Scope fence: add tests and fixtures only. Do not implement production code in this plan except minimal test helpers/fakes.
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/REQUIREMENTS.md
|
||||
@.planning/phases/14-selective-analysis-and-byte-cache/14-CONTEXT.md
|
||||
@.planning/phases/14-selective-analysis-and-byte-cache/14-RESEARCH.md
|
||||
@.planning/phases/14-selective-analysis-and-byte-cache/14-PATTERNS.md
|
||||
@backend/tests/test_cloud_items.py
|
||||
@backend/tests/test_cloud_security.py
|
||||
@frontend/src/components/storage/__tests__/StorageBrowser.cloud-queue.test.js
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Add backend red tests for analysis and cache contracts</name>
|
||||
<files>backend/tests/test_cloud_analysis_contract.py, backend/tests/test_cloud_cache.py, backend/tests/test_cloud_analysis_api.py</files>
|
||||
<read_first>
|
||||
- backend/tests/test_cloud_items.py
|
||||
- backend/tests/test_cloud_security.py
|
||||
- backend/tests/test_cloud_mutations.py
|
||||
- backend/db/models.py
|
||||
</read_first>
|
||||
<action>
|
||||
Add focused tests using fake cloud items/connections and fake provider adapters. Cover individual-file, selection, folder, and connection estimate/enqueue requests; whole-connection estimate requirement; recursive folder choice; unsupported item reporting; duplicate unchanged version skip without provider byte fetch; owner/admin-negative access; cache entry ownership; cache object key secrecy; quota increment/decrement expectations; active pin eviction protection; retry and cancel status transitions. Mark these tests red against missing modules/endpoints rather than weakening assertions.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- Tests name the exact ANALYZE/CACHE requirements they protect.
|
||||
- Tests assert provider bytes are not downloaded during estimate or duplicate-current checks.
|
||||
- Tests assert provider mutation methods are never invoked by analysis paths.
|
||||
- Running the new backend tests fails for missing Phase 14 implementation, not syntax/import errors in the tests themselves once modules exist.
|
||||
</acceptance_criteria>
|
||||
<verify><automated>cd backend && pytest -q tests/test_cloud_analysis_contract.py tests/test_cloud_cache.py tests/test_cloud_analysis_api.py</automated></verify>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Add frontend red tests for shared-browser analysis UX</name>
|
||||
<files>frontend/src/components/storage/__tests__/StorageBrowser.analysis-queue.test.js, frontend/src/stores/__tests__/cloudConnections.analysis.test.js</files>
|
||||
<read_first>
|
||||
- frontend/src/components/storage/StorageBrowser.vue
|
||||
- frontend/src/views/CloudFolderView.vue
|
||||
- frontend/src/stores/cloudConnections.js
|
||||
- frontend/src/components/storage/__tests__/StorageBrowser.cloud-queue.test.js
|
||||
</read_first>
|
||||
<action>
|
||||
Add tests proving row-level file analysis action, toolbar analysis for multi-select/folder/current connection, estimate modal thresholds, aggregate progress, expandable item list, simplified vs detailed labels, retry/skip/cancel controls, and Settings-backed default failure behavior. Tests must assert that `CloudFolderView` passes props and handles emits without owning layout, and that no parallel file grid is introduced.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- Tests fail because analysis UI/store code is absent, not because of brittle selectors.
|
||||
- Shared browser remains the component under test for browser layout and controls.
|
||||
- Store tests cover status translation and API client calls without using localStorage/sessionStorage for credentials.
|
||||
</acceptance_criteria>
|
||||
<verify><automated>cd frontend && npm run test -- StorageBrowser.analysis-queue.test.js cloudConnections.analysis.test.js</automated></verify>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<threat_model>
|
||||
| Threat ID | Threat | Required test evidence |
|
||||
|-----------|--------|------------------------|
|
||||
| T-14-01 | Analysis IDOR | Foreign user cannot estimate/enqueue/status/cancel/retry another user's connection or item |
|
||||
| T-14-02 | Credential/object-key disclosure | API/audit responses never include credentials, raw provider URLs, or MinIO object keys |
|
||||
| T-14-03 | Hidden provider mutation | Fake adapter mutation method counters remain zero during analysis |
|
||||
| T-14-04 | Hidden byte download | Estimate and already-current checks do not call provider byte fetch |
|
||||
| T-14-05 | Cache quota corruption | Tests require atomic quota increment on retain and decrement on eviction |
|
||||
</threat_model>
|
||||
|
||||
<verification>
|
||||
1. `cd backend && pytest -q tests/test_cloud_analysis_contract.py tests/test_cloud_cache.py tests/test_cloud_analysis_api.py`
|
||||
2. `cd frontend && npm run test -- StorageBrowser.analysis-queue.test.js cloudConnections.analysis.test.js`
|
||||
3. Confirm failures are expected missing-implementation failures only.
|
||||
</verification>
|
||||
|
||||
<output>Create `.planning/phases/14-selective-analysis-and-byte-cache/14-01-SUMMARY.md` when complete.</output>
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
---
|
||||
phase: "14"
|
||||
plan: "02"
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on:
|
||||
- "14-01"
|
||||
files_modified:
|
||||
- backend/migrations/versions/0007_cloud_analysis_cache.py
|
||||
- backend/db/models.py
|
||||
- backend/services/cloud_analysis_versioning.py
|
||||
- backend/services/cloud_analysis_settings.py
|
||||
- backend/tests/test_cloud_analysis_contract.py
|
||||
- backend/tests/test_cloud_cache.py
|
||||
autonomous: true
|
||||
requirements:
|
||||
- ANALYZE-04
|
||||
- ANALYZE-06
|
||||
- CACHE-04
|
||||
- CACHE-05
|
||||
---
|
||||
|
||||
<objective>
|
||||
Add durable Phase 14 schema and shared helpers for cache entries, analysis jobs, per-item status, version-key idempotency, and user/tier-ready analysis settings.
|
||||
|
||||
Scope fence: no provider byte download, Celery processing, or frontend UI in this plan.
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
@.planning/phases/14-selective-analysis-and-byte-cache/14-RESEARCH.md
|
||||
@.planning/phases/14-selective-analysis-and-byte-cache/14-PATTERNS.md
|
||||
@backend/db/models.py
|
||||
@backend/migrations/versions/0006_cloud_resource_foundation.py
|
||||
@backend/services/cloud_items.py
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Add migration and ORM models</name>
|
||||
<files>backend/migrations/versions/0007_cloud_analysis_cache.py, backend/db/models.py</files>
|
||||
<read_first>
|
||||
- backend/migrations/versions/0006_cloud_resource_foundation.py
|
||||
- backend/db/models.py
|
||||
</read_first>
|
||||
<action>
|
||||
Create the next Alembic revision for `cloud_byte_cache_entries`, `cloud_analysis_jobs`, `cloud_analysis_job_items`, and either owner-scoped analysis settings or extensions to the existing settings model. Include strict user/connection/item foreign keys, unique cache version key constraints, LRU eviction indexes, status fields, controlled error fields, aggregate counters, and reversible downgrade. Models must mirror the migration and preserve the existing `CloudItem` identity model.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- Cache entries are scoped by user, connection, cloud item, and version key.
|
||||
- Job and job-item rows can represent file, selection, folder, and connection analysis.
|
||||
- Settings support progress detail, failure behavior, and tier-capped cache limit preference.
|
||||
- Downgrade drops only Phase 14 objects.
|
||||
</acceptance_criteria>
|
||||
<verify><automated>cd backend && pytest -q tests/test_cloud_cache.py -k "schema or model"</automated></verify>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Add version-key and settings helpers</name>
|
||||
<files>backend/services/cloud_analysis_versioning.py, backend/services/cloud_analysis_settings.py, backend/tests/test_cloud_analysis_contract.py, backend/tests/test_cloud_cache.py</files>
|
||||
<read_first>
|
||||
- backend/services/cloud_items.py
|
||||
- backend/db/models.py
|
||||
- .planning/phases/14-selective-analysis-and-byte-cache/14-PATTERNS.md
|
||||
</read_first>
|
||||
<action>
|
||||
Implement one shared version-key helper using version, etag, fallback metadata fingerprint, and optional post-hydration content hash. Implement settings helpers that return defaults, validate enum values, enforce cache limit bounds, and leave a clean tier/admin maximum seam. Services raise `ValueError` or domain exceptions only.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- Duplicate-current and cache lookup code can consume one canonical version key.
|
||||
- Content hash is never required before bytes are hydrated.
|
||||
- Invalid setting values are rejected by service validation.
|
||||
- `rg "HTTPException" backend/services/cloud_analysis_versioning.py backend/services/cloud_analysis_settings.py` returns no matches.
|
||||
</acceptance_criteria>
|
||||
<verify><automated>cd backend && pytest -q tests/test_cloud_analysis_contract.py tests/test_cloud_cache.py -k "version_key or settings"</automated></verify>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
1. `cd backend && pytest -q tests/test_cloud_analysis_contract.py tests/test_cloud_cache.py`
|
||||
2. Run migration upgrade/downgrade against the PostgreSQL integration environment.
|
||||
3. `rg "HTTPException" backend/services/cloud_analysis_versioning.py backend/services/cloud_analysis_settings.py`
|
||||
</verification>
|
||||
|
||||
<output>Create `.planning/phases/14-selective-analysis-and-byte-cache/14-02-SUMMARY.md` when complete.</output>
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
---
|
||||
phase: "14"
|
||||
plan: "03"
|
||||
type: execute
|
||||
wave: 2
|
||||
depends_on:
|
||||
- "14-02"
|
||||
files_modified:
|
||||
- backend/services/cloud_byte_cache.py
|
||||
- backend/api/cloud/cache.py
|
||||
- backend/api/cloud/schemas.py
|
||||
- backend/api/cloud/__init__.py
|
||||
- backend/tests/test_cloud_cache.py
|
||||
- backend/tests/test_cloud_security.py
|
||||
autonomous: true
|
||||
requirements:
|
||||
- CACHE-03
|
||||
- CACHE-04
|
||||
- CACHE-05
|
||||
---
|
||||
|
||||
<objective>
|
||||
Implement the owner-scoped byte cache service and read/control API: cache lookup, retain, pin/release, per-user LRU eviction, quota accounting, settings update, and metadata-safe cache status responses.
|
||||
|
||||
Scope fence: do not wire analysis workers or open/preview hydration yet. This plan builds the cache primitive those paths will call.
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
@.planning/phases/14-selective-analysis-and-byte-cache/14-RESEARCH.md
|
||||
@.planning/phases/14-selective-analysis-and-byte-cache/14-PATTERNS.md
|
||||
@backend/storage/minio_backend.py
|
||||
@backend/services/cloud_items.py
|
||||
@backend/db/models.py
|
||||
@backend/api/cloud/schemas.py
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Build cache service with quota and pinning semantics</name>
|
||||
<files>backend/services/cloud_byte_cache.py, backend/tests/test_cloud_cache.py</files>
|
||||
<read_first>
|
||||
- backend/storage/minio_backend.py
|
||||
- backend/services/quota.py
|
||||
- backend/db/models.py
|
||||
- backend/tests/test_quota.py
|
||||
</read_first>
|
||||
<action>
|
||||
Add cache service functions to resolve owned cache entries, reserve quota atomically before retaining bytes, store bytes using UUID/private object keys, record metadata, reuse matching non-evicted version entries, pin/release active job or preview use, update last access, evict inactive LRU entries per user limit, decrement quota when retained bytes are evicted, and delete MinIO objects best-effort after DB state is consistent. Protect entries with `pin_count > 0` or `active_job_count > 0`.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- Cache retention increments quota and eviction decrements quota with atomic quota helpers.
|
||||
- Eviction never selects another user's entry and never evicts pinned/active entries.
|
||||
- Object keys are generated UUID/private keys and never include provider filenames.
|
||||
- Service functions raise domain errors or `ValueError`, never `HTTPException`.
|
||||
</acceptance_criteria>
|
||||
<verify><automated>cd backend && pytest -q tests/test_cloud_cache.py</automated></verify>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Add cache settings/status API</name>
|
||||
<files>backend/api/cloud/cache.py, backend/api/cloud/schemas.py, backend/api/cloud/__init__.py, backend/tests/test_cloud_cache.py, backend/tests/test_cloud_security.py</files>
|
||||
<read_first>
|
||||
- backend/api/cloud/connections.py
|
||||
- backend/api/cloud/operations.py
|
||||
- backend/api/cloud/schemas.py
|
||||
- backend/tests/test_cloud_security.py
|
||||
</read_first>
|
||||
<action>
|
||||
Add credential-free endpoints for current cache usage/settings and updating the user's preferred cache limit/progress/failure settings. Use explicit Pydantic fields only. Return aggregate bytes/counts and tier cap, not object keys. Enforce `get_regular_user`, owner scope, and rate limiting consistent with existing cloud routes.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- Admin users are blocked.
|
||||
- Responses contain no `object_key`, credentials, raw provider URLs, or extracted text.
|
||||
- Invalid cache limits above the tier/admin cap return a controlled validation response.
|
||||
- Security tests cover foreign user and admin-negative cases.
|
||||
</acceptance_criteria>
|
||||
<verify><automated>cd backend && pytest -q tests/test_cloud_cache.py tests/test_cloud_security.py -k "cache"</automated></verify>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<threat_model>
|
||||
| Threat ID | Threat | Mitigation |
|
||||
|-----------|--------|------------|
|
||||
| T-14-06 | Cross-user cache access | All cache entry queries include user_id and connection_id; negative tests |
|
||||
| T-14-07 | Quota race | Existing atomic quota update helpers required for retain/evict deltas |
|
||||
| T-14-08 | Object key leakage | API schemas omit object_key and tests assert absence |
|
||||
| T-14-09 | Active work eviction | Pin/active counters in selection predicate and regression tests |
|
||||
</threat_model>
|
||||
|
||||
<verification>
|
||||
1. `cd backend && pytest -q tests/test_cloud_cache.py`
|
||||
2. `cd backend && pytest -q tests/test_cloud_security.py -k "cache"`
|
||||
3. `rg "object_key|credentials_enc" backend/api/cloud/cache.py backend/api/cloud/schemas.py`
|
||||
</verification>
|
||||
|
||||
<output>Create `.planning/phases/14-selective-analysis-and-byte-cache/14-03-SUMMARY.md` when complete.</output>
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
phase: "14"
|
||||
plan: "04"
|
||||
type: execute
|
||||
wave: 3
|
||||
depends_on:
|
||||
- "14-02"
|
||||
- "14-03"
|
||||
files_modified:
|
||||
- backend/services/cloud_analysis.py
|
||||
- backend/api/cloud/analysis.py
|
||||
- backend/api/cloud/schemas.py
|
||||
- backend/api/cloud/__init__.py
|
||||
- backend/tests/test_cloud_analysis_api.py
|
||||
- backend/tests/test_cloud_analysis_contract.py
|
||||
- backend/tests/test_cloud_security.py
|
||||
autonomous: true
|
||||
requirements:
|
||||
- ANALYZE-01
|
||||
- ANALYZE-02
|
||||
- ANALYZE-03
|
||||
- ANALYZE-05
|
||||
- ANALYZE-06
|
||||
- ANALYZE-07
|
||||
---
|
||||
|
||||
<objective>
|
||||
Implement Phase 14 analysis estimate, enqueue, status, cancellation, skip, and retry APIs backed by durable job rows and idempotency checks.
|
||||
|
||||
Scope fence: enqueue and control jobs only. Actual provider byte hydration/extraction/classification is Plan 05.
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
@.planning/phases/14-selective-analysis-and-byte-cache/14-CONTEXT.md
|
||||
@.planning/phases/14-selective-analysis-and-byte-cache/14-PATTERNS.md
|
||||
@backend/services/cloud_items.py
|
||||
@backend/services/cloud_analysis_versioning.py
|
||||
@backend/services/cloud_analysis_settings.py
|
||||
@backend/api/cloud/operations.py
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Add analysis orchestration service</name>
|
||||
<files>backend/services/cloud_analysis.py, backend/tests/test_cloud_analysis_contract.py</files>
|
||||
<read_first>
|
||||
- backend/services/cloud_items.py
|
||||
- backend/services/cloud_analysis_versioning.py
|
||||
- backend/db/models.py
|
||||
</read_first>
|
||||
<action>
|
||||
Implement owner-scoped functions for estimating file/selection/folder/connection scopes, expanding known folder descendants from metadata where available, reporting partial estimates when provider expansion is incomplete, creating analysis jobs and job items, skipping unsupported/current items, and rejecting duplicate active jobs for the same user/item/version. Folder analysis must preserve current-only vs recursive choice; whole-connection analysis is recursive. Estimates never download bytes.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- File, selection, folder, and connection scope requests create correct job metadata.
|
||||
- Whole-connection jobs require estimate acknowledgement unless trivially small by configured thresholds.
|
||||
- Current unchanged items are marked `already_current` and do not enqueue byte work.
|
||||
- Provider mutation methods are never called.
|
||||
</acceptance_criteria>
|
||||
<verify><automated>cd backend && pytest -q tests/test_cloud_analysis_contract.py</automated></verify>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Add analysis API routes and typed schemas</name>
|
||||
<files>backend/api/cloud/analysis.py, backend/api/cloud/schemas.py, backend/api/cloud/__init__.py, backend/tests/test_cloud_analysis_api.py, backend/tests/test_cloud_security.py</files>
|
||||
<read_first>
|
||||
- backend/api/cloud/operations.py
|
||||
- backend/api/cloud/schemas.py
|
||||
- backend/tests/test_cloud_security.py
|
||||
</read_first>
|
||||
<action>
|
||||
Add routes under `/api/cloud/connections/{connection_id}/analysis` for estimate, enqueue/start, job status/list, cancel item, cancel batch, skip failed/queued item, and retry failed item. Use explicit request schemas and credential-free response schemas. Convert service domain errors into typed JSON bodies with stable `kind`/`reason` fields.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- Routes use `get_regular_user` and owner-scoped connection/item resolution.
|
||||
- Status responses expose aggregate and per-item state without credentials, object keys, provider URLs, or raw provider errors.
|
||||
- Retry creates a fresh item attempt from the beginning.
|
||||
- Cancel queued work immediately and marks running work cancellation-requested for worker cooperation.
|
||||
</acceptance_criteria>
|
||||
<verify><automated>cd backend && pytest -q tests/test_cloud_analysis_api.py tests/test_cloud_security.py -k "analysis"</automated></verify>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
1. `cd backend && pytest -q tests/test_cloud_analysis_contract.py tests/test_cloud_analysis_api.py`
|
||||
2. `cd backend && pytest -q tests/test_cloud_security.py -k "analysis"`
|
||||
3. Confirm `rg "download|get_object|put_object" backend/services/cloud_analysis.py backend/api/cloud/analysis.py` has no estimate-time byte fetch.
|
||||
</verification>
|
||||
|
||||
<output>Create `.planning/phases/14-selective-analysis-and-byte-cache/14-04-SUMMARY.md` when complete.</output>
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
---
|
||||
phase: "14"
|
||||
plan: "05"
|
||||
type: execute
|
||||
wave: 4
|
||||
depends_on:
|
||||
- "14-03"
|
||||
- "14-04"
|
||||
files_modified:
|
||||
- backend/tasks/cloud_analysis_tasks.py
|
||||
- backend/celery_app.py
|
||||
- backend/services/cloud_analysis_processing.py
|
||||
- backend/services/cloud_byte_cache.py
|
||||
- backend/services/classifier.py
|
||||
- backend/tests/test_cloud_analysis_contract.py
|
||||
- backend/tests/test_cloud_cache.py
|
||||
autonomous: true
|
||||
requirements:
|
||||
- ANALYZE-04
|
||||
- ANALYZE-05
|
||||
- ANALYZE-06
|
||||
- ANALYZE-07
|
||||
- CACHE-03
|
||||
- CACHE-04
|
||||
---
|
||||
|
||||
<objective>
|
||||
Implement Celery-backed cloud analysis processing: hydrate bytes on demand, retain/reuse cache entries, extract text, classify topics onto `CloudItem`, update per-item and aggregate states, and honor cancellation/retry semantics.
|
||||
|
||||
Scope fence: do not build frontend controls in this plan.
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
@.planning/phases/14-selective-analysis-and-byte-cache/14-PATTERNS.md
|
||||
@backend/tasks/cloud_tasks.py
|
||||
@backend/tasks/document_tasks.py
|
||||
@backend/services/extractor.py
|
||||
@backend/services/classifier.py
|
||||
@backend/storage/cloud_backend_factory.py
|
||||
@backend/services/cloud_byte_cache.py
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Add processing service for one job item</name>
|
||||
<files>backend/services/cloud_analysis_processing.py, backend/services/cloud_byte_cache.py, backend/tests/test_cloud_analysis_contract.py, backend/tests/test_cloud_cache.py</files>
|
||||
<read_first>
|
||||
- backend/services/extractor.py
|
||||
- backend/services/classifier.py
|
||||
- backend/services/cloud_byte_cache.py
|
||||
- backend/services/cloud_analysis_versioning.py
|
||||
</read_first>
|
||||
<action>
|
||||
Implement a service that processes a single job item by revalidating owner/connection/item, checking cancellation, checking version-key currentness, reusing or hydrating cache bytes, extracting text, persisting `CloudItem.extracted_text`, classifying topics through existing classifier logic adapted for cloud items, updating status to indexed/failed/cancelled/stale, and releasing cache pins. Compute content hash only while bytes are already available. Never create a local `Document` row and never call provider mutation methods.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- Status transitions include downloading, extracting, classifying, indexed, cancelled, failed, stale.
|
||||
- Unchanged version skips processing before provider byte fetch.
|
||||
- Provider byte fetch occurs only for actionable analysis/open/preview work.
|
||||
- Cache pins are released on success, failure, and cancellation.
|
||||
</acceptance_criteria>
|
||||
<verify><automated>cd backend && pytest -q tests/test_cloud_analysis_contract.py tests/test_cloud_cache.py -k "processing or idempotent or cancellation"</automated></verify>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Add Celery task and retry harness</name>
|
||||
<files>backend/tasks/cloud_analysis_tasks.py, backend/celery_app.py, backend/tests/test_cloud_analysis_contract.py</files>
|
||||
<read_first>
|
||||
- backend/tasks/cloud_tasks.py
|
||||
- backend/tasks/document_tasks.py
|
||||
- backend/celery_app.py
|
||||
</read_first>
|
||||
<action>
|
||||
Add sync Celery tasks that bridge to async processing with the existing sentinel retry pattern. Task payloads include job id/item id only. Decrypt credentials inside the worker after owner revalidation. Support bounded transient provider/classifier retry, terminal auth failures, max-retry final failure status, and cooperative cancellation checks between stages.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- Celery broker payload contains no credentials, provider URLs, filenames, or bytes.
|
||||
- `self.retry()` is raised only in the outer sync task layer.
|
||||
- Max retry writes controlled failure status.
|
||||
- Aggregate job counters update after item transitions.
|
||||
</acceptance_criteria>
|
||||
<verify><automated>cd backend && pytest -q tests/test_cloud_analysis_contract.py -k "celery or retry or broker"</automated></verify>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<threat_model>
|
||||
| Threat ID | Threat | Mitigation |
|
||||
|-----------|--------|------------|
|
||||
| T-14-10 | Credentials in broker payload | IDs only in Celery task args; decrypt in worker |
|
||||
| T-14-11 | Provider file mutation | Processing service uses content-read adapter path only and tests fake mutation counters |
|
||||
| T-14-12 | Cache pin leak | finally block releases pins; tests cover failure/cancel paths |
|
||||
| T-14-13 | Stale result presented as current | Final version/fingerprint comparison marks item stale if provider metadata changed |
|
||||
</threat_model>
|
||||
|
||||
<verification>
|
||||
1. `cd backend && pytest -q tests/test_cloud_analysis_contract.py tests/test_cloud_cache.py`
|
||||
2. `rg "credentials|credentials_enc|file_bytes" backend/tasks/cloud_analysis_tasks.py` and confirm no broker payload exposure.
|
||||
3. `rg "Document\\(" backend/services/cloud_analysis_processing.py backend/tasks/cloud_analysis_tasks.py` returns no local import creation.
|
||||
</verification>
|
||||
|
||||
<output>Create `.planning/phases/14-selective-analysis-and-byte-cache/14-05-SUMMARY.md` when complete.</output>
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
---
|
||||
phase: "14"
|
||||
plan: "06"
|
||||
type: execute
|
||||
wave: 5
|
||||
depends_on:
|
||||
- "14-03"
|
||||
- "14-05"
|
||||
files_modified:
|
||||
- backend/api/cloud/operations.py
|
||||
- backend/services/cloud_byte_cache.py
|
||||
- backend/api/cloud/schemas.py
|
||||
- backend/tests/test_cloud_cache.py
|
||||
- backend/tests/test_cloud_security.py
|
||||
- frontend/src/views/__tests__/CloudFolderOpenPreview.test.js
|
||||
autonomous: true
|
||||
requirements:
|
||||
- CACHE-03
|
||||
- CACHE-04
|
||||
- CACHE-05
|
||||
---
|
||||
|
||||
<objective>
|
||||
Route cloud open/preview byte hydration through the Phase 14 byte cache so opening and previewing use the same bounded, owner-scoped, quota-counted cache lifecycle as analysis.
|
||||
|
||||
Scope fence: do not change the shared browser analysis queue; this plan only updates existing content routes and their tests.
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
@.planning/phases/13-virtual-local-cloud-operations/13-CONTEXT.md
|
||||
@.planning/phases/14-selective-analysis-and-byte-cache/14-PATTERNS.md
|
||||
@backend/api/cloud/operations.py
|
||||
@backend/services/cloud_byte_cache.py
|
||||
@frontend/src/views/CloudFolderView.vue
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Update backend open/preview/download routes to use cache leases</name>
|
||||
<files>backend/api/cloud/operations.py, backend/services/cloud_byte_cache.py, backend/tests/test_cloud_cache.py, backend/tests/test_cloud_security.py</files>
|
||||
<read_first>
|
||||
- backend/api/cloud/operations.py
|
||||
- backend/services/cloud_byte_cache.py
|
||||
- backend/storage/cloud_backend_factory.py
|
||||
</read_first>
|
||||
<action>
|
||||
Modify authorized cloud content routes so provider bytes are hydrated into the cache on demand, pinned during active streaming/preview, last-accessed timestamp is updated, and eviction runs after release when needed. Preserve binary-only preview enforcement and no raw provider URL exposure. Existing download fallback remains authorized through DocuVault, not a provider URL.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- Preview/open/download never serve bytes without owner-scoped connection/item resolution.
|
||||
- Cache hits avoid provider byte fetch.
|
||||
- Active preview/download cache entries are not evicted mid-response.
|
||||
- Responses still omit object keys, credentials, and raw provider URLs.
|
||||
</acceptance_criteria>
|
||||
<verify><automated>cd backend && pytest -q tests/test_cloud_cache.py tests/test_cloud_security.py -k "preview or download or cache"</automated></verify>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Preserve frontend open/preview behavior against cached backend</name>
|
||||
<files>frontend/src/views/__tests__/CloudFolderOpenPreview.test.js</files>
|
||||
<read_first>
|
||||
- frontend/src/views/CloudFolderView.vue
|
||||
- frontend/src/api/cloud.js
|
||||
- frontend/src/views/__tests__/CloudFolderOpenPreview.test.js
|
||||
</read_first>
|
||||
<action>
|
||||
Update frontend tests only if route response metadata changes. Preserve the invariant that `CloudFolderView` calls `api.openCloudFile`/`previewCloudFile` and never opens provider URLs directly. Add assertions that cache-related response fields, if any, do not leak object keys.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- Existing open/preview tests remain green.
|
||||
- No browser-to-provider URL path is introduced.
|
||||
- Cache semantics remain backend-owned and do not require frontend object-key knowledge.
|
||||
</acceptance_criteria>
|
||||
<verify><automated>cd frontend && npm run test -- CloudFolderOpenPreview.test.js</automated></verify>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
1. `cd backend && pytest -q tests/test_cloud_cache.py tests/test_cloud_security.py -k "cache or preview or download"`
|
||||
2. `cd frontend && npm run test -- CloudFolderOpenPreview.test.js`
|
||||
3. `rg "window.open|provider_url|object_key" frontend/src/views/CloudFolderView.vue frontend/src/api/cloud.js backend/api/cloud/operations.py`
|
||||
</verification>
|
||||
|
||||
<output>Create `.planning/phases/14-selective-analysis-and-byte-cache/14-06-SUMMARY.md` when complete.</output>
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
phase: "14"
|
||||
plan: "07"
|
||||
type: execute
|
||||
wave: 6
|
||||
depends_on:
|
||||
- "14-04"
|
||||
- "14-05"
|
||||
files_modified:
|
||||
- frontend/src/api/cloud.js
|
||||
- frontend/src/stores/cloudConnections.js
|
||||
- frontend/src/views/CloudFolderView.vue
|
||||
- frontend/src/components/storage/StorageBrowser.vue
|
||||
- frontend/src/components/storage/__tests__/StorageBrowser.analysis-queue.test.js
|
||||
- frontend/src/stores/__tests__/cloudConnections.analysis.test.js
|
||||
- frontend/src/views/__tests__/CloudFolderRenderedFlow.test.js
|
||||
autonomous: true
|
||||
requirements:
|
||||
- ANALYZE-01
|
||||
- ANALYZE-02
|
||||
- ANALYZE-03
|
||||
- ANALYZE-04
|
||||
- ANALYZE-05
|
||||
- ANALYZE-06
|
||||
---
|
||||
|
||||
<objective>
|
||||
Implement the shared-browser Phase 14 analysis experience: row action, toolbar actions, estimate dialog, aggregate progress, expandable queue, and per-item/batch controls using the backend analysis API.
|
||||
|
||||
Scope fence: do not build Settings controls in this plan beyond consuming already-returned settings values.
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
@.planning/phases/14-selective-analysis-and-byte-cache/14-CONTEXT.md
|
||||
@.planning/phases/14-selective-analysis-and-byte-cache/14-PATTERNS.md
|
||||
@frontend/src/components/storage/StorageBrowser.vue
|
||||
@frontend/src/views/CloudFolderView.vue
|
||||
@frontend/src/stores/cloudConnections.js
|
||||
@frontend/src/api/cloud.js
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Add API/store analysis queue surface</name>
|
||||
<files>frontend/src/api/cloud.js, frontend/src/stores/cloudConnections.js, frontend/src/stores/__tests__/cloudConnections.analysis.test.js</files>
|
||||
<read_first>
|
||||
- frontend/src/api/cloud.js
|
||||
- frontend/src/stores/cloudConnections.js
|
||||
- frontend/src/stores/__tests__/cloudConnections.test.js
|
||||
</read_first>
|
||||
<action>
|
||||
Add API helpers for estimate, start, list/status, cancel batch, cancel item, skip item, and retry item. Extend the store with analysis jobs, aggregate queue state, status label mapping, simplified/detailed progress mode, and failure behavior. Keep tokens in Pinia memory only and never persist queue credentials or provider refs outside route/session semantics already allowed.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- Store translates backend statuses in one place.
|
||||
- API helpers use connection UUID and opaque provider item ids.
|
||||
- Tests cover current/already-indexed, failed, cancelled, retry, and aggregate states.
|
||||
</acceptance_criteria>
|
||||
<verify><automated>cd frontend && npm run test -- cloudConnections.analysis.test.js</automated></verify>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Extend StorageBrowser and CloudFolderView</name>
|
||||
<files>frontend/src/components/storage/StorageBrowser.vue, frontend/src/views/CloudFolderView.vue, frontend/src/components/storage/__tests__/StorageBrowser.analysis-queue.test.js, frontend/src/views/__tests__/CloudFolderRenderedFlow.test.js</files>
|
||||
<read_first>
|
||||
- frontend/src/components/storage/StorageBrowser.vue
|
||||
- frontend/src/views/CloudFolderView.vue
|
||||
- frontend/src/components/storage/__tests__/StorageBrowser.cloud-queue.test.js
|
||||
- frontend/src/views/__tests__/CloudFolderRenderedFlow.test.js
|
||||
</read_first>
|
||||
<action>
|
||||
Add file-row analyze action, toolbar actions for selected items/current folder/current connection, folder current-only vs recursive prompt, estimate review dialog, aggregate analysis progress, expandable item queue, retry/skip/cancel controls, and cancel-all. `StorageBrowser` emits actions; `CloudFolderView` handles API/store calls and refresh behavior. Use icons/tooltips consistent with existing AppIcon patterns and keep text compact enough for mobile.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- No parallel file grid or cloud-only browser component is introduced.
|
||||
- Individual file, multi-select, folder, and connection analysis can be initiated.
|
||||
- Whole connection and thresholded large scopes show estimate before start.
|
||||
- Aggregate and per-item statuses render with accessible controls.
|
||||
</acceptance_criteria>
|
||||
<verify><automated>cd frontend && npm run test -- StorageBrowser.analysis-queue.test.js CloudFolderRenderedFlow.test.js</automated></verify>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
1. `cd frontend && npm run test -- StorageBrowser.analysis-queue.test.js cloudConnections.analysis.test.js CloudFolderRenderedFlow.test.js`
|
||||
2. `rg "analysis" frontend/src/components/storage frontend/src/views/CloudFolderView.vue frontend/src/stores/cloudConnections.js`
|
||||
3. Rendered smoke check in browser if the dev server is available.
|
||||
</verification>
|
||||
|
||||
<output>Create `.planning/phases/14-selective-analysis-and-byte-cache/14-07-SUMMARY.md` when complete.</output>
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
---
|
||||
phase: "14"
|
||||
plan: "08"
|
||||
type: execute
|
||||
wave: 7
|
||||
depends_on:
|
||||
- "14-03"
|
||||
- "14-07"
|
||||
files_modified:
|
||||
- frontend/src/views/SettingsView.vue
|
||||
- frontend/src/components/settings/SettingsCloudTab.vue
|
||||
- frontend/src/components/settings/__tests__/SettingsCloudTab.test.js
|
||||
- frontend/src/components/settings/__tests__/SettingsCloudTab.health.test.js
|
||||
- frontend/src/stores/cloudConnections.js
|
||||
- frontend/src/api/cloud.js
|
||||
- backend/tests/test_cloud_cache.py
|
||||
autonomous: true
|
||||
requirements:
|
||||
- ANALYZE-04
|
||||
- ANALYZE-05
|
||||
- CACHE-04
|
||||
---
|
||||
|
||||
<objective>
|
||||
Expose Phase 14 user settings for cache limit, progress detail, and default failure behavior in Settings, backed by the cache/settings API and tier-bound validation.
|
||||
|
||||
Scope fence: do not change backend cache internals except fixing issues found by Settings integration tests.
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
@.planning/phases/14-selective-analysis-and-byte-cache/14-CONTEXT.md
|
||||
@frontend/src/views/SettingsView.vue
|
||||
@frontend/src/components/settings/SettingsCloudTab.vue
|
||||
@frontend/src/stores/cloudConnections.js
|
||||
@backend/api/cloud/cache.py
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Add Settings API/store wiring</name>
|
||||
<files>frontend/src/api/cloud.js, frontend/src/stores/cloudConnections.js, frontend/src/stores/__tests__/cloudConnections.analysis.test.js</files>
|
||||
<read_first>
|
||||
- frontend/src/api/cloud.js
|
||||
- frontend/src/stores/cloudConnections.js
|
||||
- backend/api/cloud/cache.py
|
||||
</read_first>
|
||||
<action>
|
||||
Add client/store methods to load and update cache/settings state. Store tier cap, current usage, preferred limit, progress detail mode, and default failure behavior. Handle validation errors without clearing existing settings.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- Store keeps settings in memory and never browser-stores credentials.
|
||||
- Invalid cache limit responses surface controlled messages.
|
||||
- Updated progress/failure settings affect analysis queue label/control behavior.
|
||||
</acceptance_criteria>
|
||||
<verify><automated>cd frontend && npm run test -- cloudConnections.analysis.test.js</automated></verify>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Add Settings Cloud tab controls</name>
|
||||
<files>frontend/src/components/settings/SettingsCloudTab.vue, frontend/src/components/settings/__tests__/SettingsCloudTab.test.js, frontend/src/components/settings/__tests__/SettingsCloudTab.health.test.js</files>
|
||||
<read_first>
|
||||
- frontend/src/components/settings/SettingsCloudTab.vue
|
||||
- frontend/src/components/settings/__tests__/SettingsCloudTab.test.js
|
||||
</read_first>
|
||||
<action>
|
||||
Add compact controls for cache limit up to tier maximum, simplified vs detailed analysis progress, and pause-batch vs continue-item failure behavior. Keep the existing connection health/test/reconnect UX intact. Use form controls appropriate to settings: slider/number for bytes, segmented/select controls for modes, and clear validation text.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- Settings fit existing Cloud tab layout without nested cards.
|
||||
- Existing health/reconnect tests still pass.
|
||||
- Accessibility labels identify each control.
|
||||
- No visible explanatory tutorial copy is added beyond concise labels and validation messages.
|
||||
</acceptance_criteria>
|
||||
<verify><automated>cd frontend && npm run test -- SettingsCloudTab.test.js SettingsCloudTab.health.test.js</automated></verify>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
1. `cd frontend && npm run test -- SettingsCloudTab.test.js SettingsCloudTab.health.test.js cloudConnections.analysis.test.js`
|
||||
2. `cd backend && pytest -q tests/test_cloud_cache.py -k "settings"`
|
||||
3. Render Settings at mobile and desktop widths if a dev server is available.
|
||||
</verification>
|
||||
|
||||
<output>Create `.planning/phases/14-selective-analysis-and-byte-cache/14-08-SUMMARY.md` when complete.</output>
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
---
|
||||
phase: "14"
|
||||
plan: "09"
|
||||
type: execute
|
||||
wave: 8
|
||||
depends_on:
|
||||
- "14-01"
|
||||
- "14-02"
|
||||
- "14-03"
|
||||
- "14-04"
|
||||
- "14-05"
|
||||
- "14-06"
|
||||
- "14-07"
|
||||
- "14-08"
|
||||
files_modified:
|
||||
- AGENTS.md
|
||||
- README.md
|
||||
- SECURITY.md
|
||||
- backend/main.py
|
||||
- frontend/package.json
|
||||
- .planning/ROADMAP.md
|
||||
- .planning/STATE.md
|
||||
- .planning/phases/14-selective-analysis-and-byte-cache/14-VALIDATION.md
|
||||
- .planning/phases/14-selective-analysis-and-byte-cache/14-SECURITY.md
|
||||
autonomous: true
|
||||
requirements:
|
||||
- ANALYZE-01
|
||||
- ANALYZE-02
|
||||
- ANALYZE-03
|
||||
- ANALYZE-04
|
||||
- ANALYZE-05
|
||||
- ANALYZE-06
|
||||
- ANALYZE-07
|
||||
- CACHE-03
|
||||
- CACHE-04
|
||||
- CACHE-05
|
||||
---
|
||||
|
||||
<objective>
|
||||
Close Phase 14 with documentation, version bump, full verification gates, security evidence, and an atomic commit/push once all implementation plans pass.
|
||||
|
||||
Scope fence: do not add new feature behavior here except small fixes required by gate failures.
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
@AGENTS.md
|
||||
@README.md
|
||||
@SECURITY.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/14-selective-analysis-and-byte-cache/14-CONTEXT.md
|
||||
@.planning/phases/14-selective-analysis-and-byte-cache/14-PATTERNS.md
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Update docs, versions, roadmap, and closeout artifacts</name>
|
||||
<files>AGENTS.md, README.md, SECURITY.md, backend/main.py, frontend/package.json, .planning/ROADMAP.md, .planning/STATE.md, .planning/phases/14-selective-analysis-and-byte-cache/14-VALIDATION.md, .planning/phases/14-selective-analysis-and-byte-cache/14-SECURITY.md</files>
|
||||
<read_first>
|
||||
- AGENTS.md
|
||||
- README.md
|
||||
- SECURITY.md
|
||||
- backend/main.py
|
||||
- frontend/package.json
|
||||
</read_first>
|
||||
<action>
|
||||
Update current-state docs for Phase 14 completion, shared module maps for new analysis/cache services and routes, README feature/API/settings documentation, SECURITY threat register and gate evidence, ROADMAP plan checkboxes, and STATE next action. Apply the project version bump rule after Phase 14 completion using `backend/main.py` and `frontend/package.json` as sources of truth.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- Docs describe selective analysis, byte cache, settings, API surface, and alpha/non-public status accurately.
|
||||
- No secrets or provider item names from live data are included.
|
||||
- ROADMAP marks Phase 14 complete and Phase 15 next.
|
||||
- Version numbers are consistent across backend/frontend/docs.
|
||||
</acceptance_criteria>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Run full gates and commit/push</name>
|
||||
<files>all changed files</files>
|
||||
<read_first>
|
||||
- AGENTS.md testing, security, and git protocols
|
||||
- .planning/phases/14-selective-analysis-and-byte-cache/14-SECURITY.md
|
||||
</read_first>
|
||||
<action>
|
||||
Run focused Phase 14 tests, full backend suite, full frontend suite, `docker compose config --quiet`, Bandit, npm audit, Python dependency audit if local tooling supports Python 3.12, and an executable secret scan (`gitleaks` or `trufflehog`). Fix root-cause failures within scope. Commit and push the Phase 14 closeout only after gates pass or accepted pre-existing/tooling gaps are documented.
|
||||
</action>
|
||||
<acceptance_criteria>
|
||||
- Backend and frontend tests pass with zero Phase 14 failures.
|
||||
- Security scans report zero new high/critical issues.
|
||||
- Secret scan reports no new secrets.
|
||||
- Atomic commit uses the project commit format and is pushed.
|
||||
</acceptance_criteria>
|
||||
<verify><automated>docker compose config --quiet</automated></verify>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
1. `cd backend && pytest -q`
|
||||
2. `cd frontend && npm run test`
|
||||
3. `python3 -m bandit -r backend/ --exclude backend/tests`
|
||||
4. `cd frontend && npm audit --audit-level=high`
|
||||
5. `docker compose config --quiet`
|
||||
6. Run available secret scan and document pre-existing findings only.
|
||||
</verification>
|
||||
|
||||
<output>Create `.planning/phases/14-selective-analysis-and-byte-cache/14-09-SUMMARY.md` and mark Phase 14 complete when all gates pass.</output>
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
# Phase 14 Patterns
|
||||
|
||||
## Shared Boundaries
|
||||
|
||||
- `StorageBrowser.vue` remains the only file browser. Analysis actions, aggregate progress, and expandable queue UI belong there.
|
||||
- `CloudFolderView.vue` remains a thin data provider. It calls the store/API helpers and refreshes browse state; it does not own browser layout or queue rendering.
|
||||
- Backend routers translate typed request/response schemas and HTTP status codes only. Service modules own analysis, cache, quota, and idempotency behavior and must not raise `HTTPException`.
|
||||
- Cloud provider credentials are decrypted only inside route/task provider boundaries. Celery payloads contain IDs and control flags only.
|
||||
|
||||
## Status Vocabulary
|
||||
|
||||
Durable internal item statuses:
|
||||
|
||||
- `queued`
|
||||
- `downloading`
|
||||
- `extracting`
|
||||
- `classifying`
|
||||
- `indexed`
|
||||
- `already_current`
|
||||
- `cancelled`
|
||||
- `failed`
|
||||
- `unsupported`
|
||||
- `stale`
|
||||
|
||||
UI label mapping:
|
||||
|
||||
- simple default: waiting, working, done, skipped, failed
|
||||
- detailed setting: queued, downloading, extracting, classifying, indexed, cancelled, failed
|
||||
|
||||
Do not let frontend components invent a second status translation. Put API-to-UI translation in the Pinia store or a shared formatter/helper.
|
||||
|
||||
## Version Keys
|
||||
|
||||
Create one shared helper for cloud analysis version keys. All estimate, enqueue, duplicate-check, cache lookup, and worker paths must call it.
|
||||
|
||||
Precedence:
|
||||
|
||||
1. `version`
|
||||
2. `etag`
|
||||
3. metadata fingerprint from provider item id, size, modified time, content type
|
||||
4. content hash as an additional post-hydration fact, never as a pre-download requirement
|
||||
|
||||
## Cache Lifecycle
|
||||
|
||||
1. Resolve owner and item.
|
||||
2. Compute version key.
|
||||
3. Reuse non-evicted matching cache entry if present.
|
||||
4. Otherwise hydrate provider bytes through the mutable/content adapter boundary.
|
||||
5. Store bytes under a UUID/private MinIO key.
|
||||
6. Atomically increment user quota by retained size.
|
||||
7. Pin for active job or preview.
|
||||
8. Release pin when finished.
|
||||
9. Evict inactive LRU entries when the user's configured limit or quota pressure requires it.
|
||||
|
||||
Eviction failure must not hide successful analysis. It should surface controlled warning state and leave quota/cache metadata consistent.
|
||||
|
||||
## Estimate Semantics
|
||||
|
||||
Small file jobs may start directly. Folder and connection jobs estimate first when thresholds are crossed, and whole-connection analysis always estimates unless trivially small.
|
||||
|
||||
Estimate responses include:
|
||||
|
||||
- supported file count
|
||||
- provider-reported byte total
|
||||
- unsupported/skipped item count
|
||||
- whether recursion applies
|
||||
- whether the estimate is complete or partial
|
||||
|
||||
The estimate endpoint must never download bytes.
|
||||
|
||||
## Error and Control Semantics
|
||||
|
||||
- Batch failure behavior defaults to `pause_batch`.
|
||||
- `continue_item` pauses only the failed item and keeps later queued items running.
|
||||
- Per-item retry restarts the full item.
|
||||
- Per-item skip/cancel affects that item only.
|
||||
- Batch cancel cancels queued items and requests cooperative cancellation for running work.
|
||||
- Typed error bodies use controlled `kind` and `reason` fields, matching the Phase 13 mutation response style.
|
||||
|
||||
## Test Pattern
|
||||
|
||||
Each implementation plan starts with focused red tests for its slice, then implementation, then targeted verification.
|
||||
|
||||
Required negative coverage by the end of the phase:
|
||||
|
||||
- foreign user cannot estimate, enqueue, read status, cancel, retry, or read cache metadata
|
||||
- admin cannot access cloud analysis/cache routes
|
||||
- cache object keys and credentials never appear in responses or audit logs
|
||||
- unchanged etag/version skips duplicate analysis without byte download
|
||||
- cached bytes count against quota while retained and decrement after eviction
|
||||
- active jobs/previews are not evicted
|
||||
- folder/connection analysis does not mutate provider files
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
# Phase 14 Research: Selective Analysis and Byte Cache
|
||||
|
||||
**Phase:** 14 - Selective Analysis and Byte Cache
|
||||
**Prepared:** 2026-06-23
|
||||
**Status:** Ready for execution planning
|
||||
|
||||
## Scope Boundary
|
||||
|
||||
Phase 14 adds controlled analysis of provider-owned cloud files and a bounded private byte cache. It does not import cloud files into local `documents`, does not implement unified search, and does not implement provider delta feeds beyond version/fingerprint checks needed to avoid duplicate or stale analysis.
|
||||
|
||||
The existing system already provides the correct foundation:
|
||||
|
||||
- `CloudItem` stores owner, connection, provider item id, parent, kind, content type, size, etag/version, extracted text, analysis status, semantic status, and topic links without a local `Document`.
|
||||
- `CloudFolderView` remains a route/store data provider; `StorageBrowser` owns the shared local/cloud browser surface.
|
||||
- `cloud_tasks.py` and `document_tasks.py` show the accepted Celery sync-to-async bridge and retry sentinel pattern.
|
||||
- `MinIOBackend` already generates UUID-based private object keys and is the right precedent for temporary cached cloud bytes.
|
||||
|
||||
## Recommended Schema Additions
|
||||
|
||||
Add a new migration after the current head with owner-scoped tables rather than overloading local `documents`.
|
||||
|
||||
### `cloud_byte_cache_entries`
|
||||
|
||||
Purpose: track retained cloud bytes in MinIO and make eviction/quota decisions without exposing provider credentials or paths.
|
||||
|
||||
Suggested fields:
|
||||
|
||||
- `id` UUID primary key
|
||||
- `user_id` FK users, required
|
||||
- `connection_id` FK cloud_connections, required
|
||||
- `cloud_item_id` FK cloud_items, required
|
||||
- `provider_item_id` text, required snapshot for audit/debugging without joins
|
||||
- `version_key` text, required, derived from etag/version/fallback fingerprint/content hash
|
||||
- `object_key` text, required, UUID/private key only
|
||||
- `content_type` text nullable
|
||||
- `size_bytes` bigint required
|
||||
- `content_hash` text nullable, computed only when bytes are already hydrated
|
||||
- `pin_count` integer required default 0
|
||||
- `active_job_count` integer required default 0
|
||||
- `last_accessed_at`, `created_at`, `updated_at`, `evicted_at`
|
||||
- unique `(user_id, connection_id, cloud_item_id, version_key)`
|
||||
- indexes on `(user_id, evicted_at, last_accessed_at)` and `(user_id, pin_count, active_job_count, last_accessed_at)`
|
||||
|
||||
### `cloud_analysis_jobs`
|
||||
|
||||
Purpose: represent user-visible batches for file, selection, folder, or connection analysis.
|
||||
|
||||
Suggested fields:
|
||||
|
||||
- `id` UUID primary key
|
||||
- `user_id`, `connection_id`
|
||||
- `scope_kind`: `file`, `selection`, `folder`, `connection`
|
||||
- `scope_ref` nullable provider item id or root sentinel
|
||||
- `recursive` boolean
|
||||
- `status`: `queued`, `running`, `paused`, `completed`, `cancelled`, `failed`
|
||||
- aggregate counts: total, queued, downloading, extracting, classifying, indexed, skipped, cancelled, failed, unsupported
|
||||
- aggregate provider bytes estimate
|
||||
- `failure_behavior`: `pause_batch` or `continue_item`
|
||||
- timestamps
|
||||
|
||||
### `cloud_analysis_job_items`
|
||||
|
||||
Purpose: drive idempotent per-item processing and precise user controls.
|
||||
|
||||
Suggested fields:
|
||||
|
||||
- `id`, `job_id`, `user_id`, `connection_id`, `cloud_item_id`
|
||||
- `provider_item_id`, `version_key`, `fingerprint`
|
||||
- `status`: `queued`, `downloading`, `extracting`, `classifying`, `indexed`, `already_current`, `cancelled`, `failed`, `unsupported`, `stale`
|
||||
- `error_code`, `error_message` controlled strings only
|
||||
- `cache_entry_id` nullable
|
||||
- timestamps and retry counter
|
||||
- unique `(job_id, cloud_item_id)`
|
||||
- index `(user_id, cloud_item_id, version_key)` for duplicate/current checks
|
||||
|
||||
### User Settings
|
||||
|
||||
Prefer explicit columns or a small owner-scoped settings table for:
|
||||
|
||||
- `analysis_progress_detail`: `simple` default, `detailed` optional
|
||||
- `analysis_failure_behavior`: `pause_batch` default, `continue_item` optional
|
||||
- `cloud_cache_limit_bytes`: user preference capped by tier/admin maximum
|
||||
|
||||
If the project already has a settings table at implementation time, extend it rather than creating a second settings authority.
|
||||
|
||||
## Version and Fingerprint Rules
|
||||
|
||||
Use this precedence for idempotency:
|
||||
|
||||
1. Provider `version` when available.
|
||||
2. Provider `etag` when available.
|
||||
3. Fallback metadata fingerprint: provider item id, provider size, modified time, content type.
|
||||
4. Content hash only after bytes are already hydrated for analysis/open/preview.
|
||||
|
||||
Never download bytes solely to compute a hash.
|
||||
|
||||
## Byte Cache Rules
|
||||
|
||||
- Cache bytes only for active open, preview, or analysis work.
|
||||
- Cached bytes count against `quotas.used_bytes` while retained.
|
||||
- Quota changes must use the project's existing atomic update pattern.
|
||||
- Eviction may delete only inactive entries with `pin_count == 0`, `active_job_count == 0`, and no active preview lease.
|
||||
- Eviction must be per-user LRU and must never delete another user's entries.
|
||||
- MinIO object keys must remain private UUID keys; provider filenames stay in metadata only.
|
||||
|
||||
## Job Execution Rules
|
||||
|
||||
- API requests enqueue jobs; Celery workers expand folders/connections and process items.
|
||||
- Worker broker payloads include only IDs and control flags; credentials are decrypted inside the worker.
|
||||
- Processing an unchanged cloud item reports `already_current` without provider byte download.
|
||||
- Retry restarts the whole item from the beginning.
|
||||
- Cancellation is cooperative: queued work is cancelled immediately, running download/extract/classify checks cancellation between stages and finishes safely if it cannot interrupt.
|
||||
- If provider metadata changes during analysis, finish the job safely, compare final version/fingerprint, and mark the result stale rather than mutating the provider item.
|
||||
|
||||
## Frontend Rules
|
||||
|
||||
- Add analysis actions to `StorageBrowser` row actions and toolbar.
|
||||
- `CloudFolderView` only maps route/store/API state and handles emitted events.
|
||||
- Use an aggregate indicator plus expandable item list.
|
||||
- Simplified progress labels are default; detailed labels are exposed from Settings.
|
||||
- The analysis queue can reuse the existing upload queue interaction pattern, but it must be a distinct queue model because controls and statuses differ.
|
||||
|
||||
## Security Notes
|
||||
|
||||
- Admins remain blocked by `get_regular_user`.
|
||||
- All analysis/cache routes must resolve `(current_user.id, connection_id, provider_item_id/cloud_item_id)` before taking action.
|
||||
- Responses never include credentials, raw provider URLs, MinIO object keys, extracted text beyond explicitly authorized analysis/search surfaces, or provider error payloads.
|
||||
- Audit logs contain metadata only: connection id, provider item id, cloud item id, action/status, count/byte totals where needed.
|
||||
|
||||
Reference in New Issue
Block a user