184 lines
11 KiB
Markdown
184 lines
11 KiB
Markdown
---
|
|
gsd_state_version: 1.0
|
|
milestone: v0.3
|
|
milestone_name: Reimagining Cloud Storage integration
|
|
current_phase: 14.1
|
|
current_phase_name: cloud-local-file-parity-hardening
|
|
status: executing
|
|
stopped_at: Phase 14.1 UI-SPEC approved
|
|
last_updated: "2026-06-26T20:28:34.275Z"
|
|
last_activity: 2026-06-26
|
|
last_activity_desc: Phase 14.1 execution started
|
|
progress:
|
|
total_phases: 8
|
|
completed_phases: 4
|
|
total_plans: 35
|
|
completed_plans: 34
|
|
percent: 50
|
|
---
|
|
|
|
# Project State
|
|
|
|
**Project:** DocuVault
|
|
**Status:** Ready to execute
|
|
**Last Updated:** 2026-06-26
|
|
|
|
## Current Position
|
|
|
|
Phase: 14.1 (cloud-local-file-parity-hardening) — EXECUTING
|
|
Plan: 5 of 5
|
|
Status: Ready to execute
|
|
Last activity: 2026-06-26 — Phase 14.1 execution started
|
|
|
|
## Phase Status
|
|
|
|
| Phase | Requirements | Status |
|
|
|-------|-------------|--------|
|
|
| 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 | **Complete** |
|
|
| 14.1 Cloud/Local File Parity Hardening | CLOUD-02, ANALYZE-01..07, CACHE-03..05 | **Not started** |
|
|
| 14.2 Cross-Codebase Review and Cleanup | Cross-cutting quality gates | **Not started** |
|
|
| 15. Unified Smart Search | SEARCH-01..07 | **Not started** |
|
|
| 16. Change Tracking and Reliability | SYNC-02..04 | **Not started** |
|
|
|
|
## Performance Metrics
|
|
|
|
| Metric | Value |
|
|
|---|---|
|
|
| Phases complete | 4 / 8 |
|
|
| Requirements satisfied | 30 / 36 |
|
|
| Plans complete | 30 / 30 |
|
|
| Tests at milestone start | 277 |
|
|
| Phase 12.1 P01 | 823s | 4 tasks | 14 files |
|
|
| Phase 12.1 P02 | 2100s | 3 tasks | 13 files |
|
|
| Phase 12.1 P03 | 677s | 4 tasks | 11 files |
|
|
| Phase 12.1 P04 | 15m | 4 tasks | 10 files |
|
|
| Phase 13 P02 | 30m | 2 tasks | 6 files |
|
|
| Phase 13 P03 | 134s | 2 tasks | 8 files |
|
|
| Phase 13 P04 | 180m | 2 tasks | 7 files |
|
|
| Phase 13 P06 | 5m | 2 tasks | 3 files |
|
|
| Phase 13 P07 | 30m | 2 tasks | 5 files |
|
|
| Phase 13 P08 | 20m | 2 tasks | 2 files |
|
|
| Phase 13 P09 | 30m | 2 tasks | 3 files |
|
|
| Phase 13 P10 | 25m | 2 tasks | 6 files |
|
|
| Phase 13 P11 | 20m | 2 tasks | 6 files |
|
|
| Phase 14 P01 | 15m | 2 tasks | 5 files |
|
|
| Phase 14 P02 | 12m | 2 tasks | 5 files |
|
|
| Phase 14 P03 | 14m | - tasks | - files |
|
|
| Phase 14 P04 | 12m | 2 tasks | 4 files |
|
|
| Phase 14 P05 | 10m | 2 tasks | 4 files |
|
|
| Phase 14 P06 | 10m | 2 tasks | 5 files |
|
|
| Phase 14 P07 | 12m | 2 tasks | 4 files |
|
|
| Phase 14 P08 | 10m | 2 tasks | 3 files |
|
|
| Phase 14 P09 | 11m | 2 tasks | 9 files |
|
|
| Phase 14.1 P01 | 13m | 2 tasks | 4 files |
|
|
| Phase 14.1 P02 | 18m | 2 tasks | 5 files |
|
|
| Phase 14.1 P03 | 5m | 2 tasks | 6 files |
|
|
| Phase 14.1 P04 | 15m | 2 tasks | 5 files |
|
|
|
|
## Accumulated Context
|
|
|
|
### Key Decisions
|
|
|
|
*(Carries forward from v0.1 — see PROJECT.md for full decision log.)*
|
|
|
|
| Decision | Rationale |
|
|
|---|---|
|
|
| Options API preserved in v0.2 refactor | Composition API migration is scope-creep; refactor within Options API |
|
|
| Admin panel as standalone route subtree | AdminView as tabs-on-user-layout is architecturally wrong; v0.2 fixes this |
|
|
| No rewrites — refactor only | Preserve existing tests and behavior; change internal structure, not contracts |
|
|
| client.js barrel re-export pattern | Zero consumer churn; all 35+ import sites stay unchanged; mocks still work |
|
|
| Sub-routers carry NO prefix | Parent APIRouter prefix propagates — sub-routers with prefix cause double-segment URLs |
|
|
| AdminLayout as route component, not App.vue branch | Router resolves AdminLayout as the /admin component; its router-view renders children |
|
|
| to.matched.some() for requiresAdmin guard | Vue Router 4 does not inherit meta to children; direct to.meta check is a security regression |
|
|
| FastAPI 0.128+ empty-path sub-router restriction | `@router.get("")` on sub-router with empty include prefix fails; register root routes on parent aggregator |
|
|
| Vite 6 upgrade resolves 2 CVEs | CVE-2026-39363/39364 closed; npm audit now clean |
|
|
| Phase 13 mutation JSONResponse | Mutations return JSONResponse (not HTTPException) so kind/reason appear at response top level |
|
|
| Phase 13 cloud_operations.py orchestration | All mutation logic routes through services/cloud_operations.py — never inline in routers |
|
|
| testCloudConnection explicit-only | Never called as navigation side effect (D-13); only from user action or post-failure retest |
|
|
| v0.3.0 version bump | Phase 13 completion warrants minor version bump per CLAUDE.md versioning protocol |
|
|
| CloudItemDetailOut empty capabilities | Live capability resolution requires credential decryption — violates CACHE-03 metadata-only constraint; frontend infers actions from analysis_status + unsupported_analysis_reason |
|
|
| force=true bypasses already_current for supported items | Unsupported items remain unsupported regardless of force (ANALYZE-06, ANALYZE-07) |
|
|
| Single-item retry uses cloud_item_id | DocuVault UUID is stable across provider rename/move; provider_item_id could change (D-12) |
|
|
|
|
### Roadmap Evolution
|
|
|
|
- v0.1 completed: all 7 foundation phases + security hardening (2026-06-06)
|
|
- 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) complete 2026-06-23 — v0.4.0 shipped
|
|
- Phase 14.1 inserted after Phase 14: Cloud/Local File Parity Hardening (URGENT)
|
|
- Phase 14.2 inserted after Phase 14: Cross-Codebase Review and Cleanup (URGENT)
|
|
|
|
### Open Questions
|
|
|
|
None.
|
|
|
|
### Blockers
|
|
|
|
None.
|
|
|
|
## Session Continuity
|
|
|
|
**Stopped at:** Phase 14.1 Plan 02 complete — awaiting Plan 03 (frontend cloud detail view)
|
|
|
|
_Updated at each phase transition._
|
|
|
|
| Field | Value |
|
|
|---|---|
|
|
| Last session | 2026-06-26T20:28:34.269Z |
|
|
| Next action | Plan 14.1 |
|
|
| Pending decisions | None |
|
|
| Resume file | .planning/phases/14.1-cloud-local-file-parity-hardening/14.1-UI-SPEC.md |
|
|
|
|
## Decisions
|
|
|
|
- [Phase 12]: Remove NextcloudBackend.list_folder override — inherit canonical WebDAVBackend method
|
|
- [Phase 12]: OneDrive nextLink restricted to graph.microsoft.com host
|
|
- [Phase 12]: apply_listing_and_finalize is the single freshness gate — callers must not set refresh_state=fresh independently after list_folder
|
|
- [Phase 12.1 P03]: Named route objects used for all cloud folder navigation — Vue Router handles opaque ref encoding
|
|
- [Phase 12.1 P03]: Breadcrumb lineage maintained as explicit visited-node list — never reconstructed from provider_item_id
|
|
- [Phase 12.1 P03]: provider_item_id is canonical navigation reference; DocuVault id is row identity for Vue keys and metadata only
|
|
- [Phase 13 P03]: Backend-typed bodies required; frontend never guesses
|
|
- [Phase 13 P04]: file-open must call openCloudFile API; window.open() to provider URL is forbidden (D-02/T-13-07)
|
|
- [Phase 13 P10]: connectionHealth store translation is single source for browser compact status and Settings diagnostics (D-12)
|
|
- [Phase 13 P10]: testCloudConnection never called as side effect of folder browse navigation (D-13)
|
|
- [Phase 13 P04]: D-17: Google Drive OAuth uses drive scope (not drive.file) for Phase 13 full-access mutations
|
|
- [Phase 13 P07]: D-18: Preview is binary-only (PDF/images); Office/Workspace formats use typed unsupported_preview fallback to authorized download endpoint
|
|
- [Phase 13 P03]: Phase 13 mutation errors use JSONResponse (not HTTPException) so kind/reason appear at top level of response body, not nested under detail
|
|
- [Phase 13 P06]: upload_mutated folder state code: upload success marks parent folder as warning/upload_mutated for reconcile-before-return
|
|
- [Phase 13 P07]: CloudFolderView uses api.* barrel imports so vi.mock intercepts correctly
|
|
- [Phase 13 P07]: UploadProgress suppressed in cloud mode (v-if) — cloud queue dialogs replace it per D-03/D-04
|
|
- [Phase 13 P07]: StorageBrowser emits upload-queue-resolve with typed action; CloudFolderView handles all five resolution paths (keep_both/replace/skip/retry/cancel_all)
|
|
- [Phase 13 P08]: Rename collision surfaced to user (no auto-retry) — user chose name explicitly
|
|
- [Phase 13 P08]: Create-folder bounded retry up to 5 attempts with keep_both_name counter suffix D-05/D-06
|
|
- [Phase 13 P08]: Stale guard for create-folder and rename calls update_folder_state before returning typed stale body D-07
|
|
- [Phase 13 P08]: Reconcile-before-return for create-folder and rename: upsert_cloud_item + update_folder_state T-13-26
|
|
- [Phase 13 P09]: Move with descendant-chain walk + self-check + cross-connection check before provider submission
|
|
- [Phase 13 P09]: Stale move guard stops mutation, refreshes source folder state, returns typed stale result
|
|
- [Phase 13 P09]: Delete audit metadata: only kind/provider_item_id/display_name/is_folder — no bytes or credentials
|
|
- [Phase 13 P11]: Version bump to v0.3.0 on Phase 13 completion (minor bump for full phase per CLAUDE.md protocol)
|
|
- [Phase 14 P02]: compute_version_key defined in cloud_analysis_versioning.py and re-exported from cloud_cache.py — single import site for tests and callers
|
|
- [Phase 14 P02]: content_hash is optional post-hydration supplement, never a pre-download precondition (D-20)
|
|
- [Phase 14 P02]: evict_lru_entries stamps evicted_at only; caller owns MinIO deletion and quota decrement (separation of concerns)
|
|
- [Phase 14 P02]: user_analysis_settings is distinct from system_settings — single authority for per-user analysis preferences
|
|
- [Phase ?]: [Phase 14 P03]: retain_or_reuse_cache_entry reactivates evicted rows — unique constraint prevents duplicate insert for same version_key
|
|
- [Phase ?]: [Phase 14 P03]: api/cloud/analysis.py as aggregator router so Plan 01 RED tests can import before all routes implemented
|
|
- [Phase ?]: [Phase 14 P03]: CacheStatusOut enforces T-14-02/T-14-08 by design — object_key absent at type level
|
|
- [Phase ?]: Phase 14 P04: estimate_scope uses durable cloud_items metadata only (T-14-04)
|
|
- [Phase ?]: Phase 14 P04: live_metadata_changed flag bypasses already-current fallback when provider confirms etag changed
|
|
- [Phase ?]: Phase 14 P04: AnalysisJobOut per-stage counts always int (never None)
|
|
- [Phase 14 P06]: hydrate_and_cache_bytes is the single cache lifecycle entry point for preview/download — never inline adapter.get_object in open/preview/download routes
|
|
- [Phase 14 P06]: preview and download cache integration is backend-transparent — response shapes unchanged from Phase 13 (T-14-02)
|
|
- [Phase ?]: [Phase 14 P07]: analyze-file button in name cell not file-row-actions
|
|
- [Phase ?]: [Phase 14 P07]: translateAnalysisStatus is single status translation source in cloudConnections store
|
|
- [Phase ?]: [Phase 14 P08]: getCacheSettings corrected to /api/cloud/analysis/cache; tierCapBytes drives Settings cache limit max
|
|
- [Phase ?]: [Phase 14 P08]: Analysis Settings section in SettingsCloudTab - separate card with cache limit input, progress detail toggle, failure behavior toggle
|
|
- [Phase ?]: Phase 14 version bump: 0.3.0→0.4.0
|
|
- [Phase ?]: DocumentDetailSurface is shared detail surface for local+cloud
|
|
- [Phase ?]: cloud-file-detail route uses /item/ path segment to disambiguate from cloud-folder wildcard
|
|
- [Phase ?]: previewState inferred from content_type (empty capabilities={}; live resolution requires credentials per Plan 02)
|