# Phase 13: Virtual-Local Cloud Operations - Context **Gathered:** 2026-06-22 **Status:** Ready for planning ## Phase Boundary Deliver owner-authorized connection maintenance and the main cloud file-management operations through the same shared browser interactions used for local files: test/reconnect/disconnect, open/preview, upload, create folder, rename, move within one connection, and delete. Mutations must respect normalized provider capabilities, promptly reconcile metadata, refresh affected listings, and emit metadata-only audit events. Phase 14 owns temporary byte-cache lifecycle and analysis; permanent cloud-to-local import remains future requirement `IMPORT-01`. ## Implementation Decisions ### Shared open, preview, and upload experience - **D-01:** Cloud open, preview, and upload must feel the same as local storage and reuse the same shared components, progress presentation, and interaction paths. `CloudFolderView` remains a thin data provider; cloud-specific transport does not justify parallel UI. - **D-02:** Preview stays inside DocuVault and must not trigger a browser-to-device download. Unsupported preview formats fall back to an ownership-checked authorized download; provider credentials and raw provider URLs are never exposed. - **D-03:** A same-name upload opens a conflict dialog and never overwrites silently. The available decisions are Keep both with a renamed item, Replace where supported, Skip, and Cancel all. - **D-04:** Multi-file uploads run as a sequential queue. A conflict or error pauses the whole queue for user input without losing remaining items. Conflict actions are Keep both, Replace, Skip, and Cancel all; error actions are Retry, Skip, and Cancel all. Retry/Keep both/Replace/Skip resume the queue, while Cancel all stops it. ### Naming and concurrency conflicts - **D-05:** Create-folder and rename collisions automatically choose a non-conflicting human-readable counter name: `Report (1).pdf`, `Report (2).pdf`, or `Projects (1)` for folders. - **D-06:** If a concurrent client takes the candidate name between checking and mutation, retry with the next counter within a small bounded number of attempts. - **D-07:** Rename, move, or delete must not operate on stale metadata when the item changed externally. Stop the mutation, refresh the affected folder, explain what changed, and ask the user to retry. ### Move and delete safeguards - **D-08:** Moving cloud items matches local storage: support both drag-to-folder and the shared folder picker. Destinations are restricted to the same cloud connection; cross-provider transfer remains out of scope. - **D-09:** Invalid folder destinations, including the folder itself and its descendants, are disabled before submission and independently rejected by the backend. - **D-10:** Delete confirmation is context-sensitive. Files receive a standard confirmation; folders clearly warn that nested contents are included. - **D-11:** Prefer the provider's trash/recycle-bin operation when supported. When only permanent deletion is available, the confirmation must say so explicitly. ### Connection health and recovery - **D-12:** Connection health appears in both places users need it: compact status plus Reconnect in the cloud browser, and full diagnostics plus Test/Reconnect controls in Settings. - **D-13:** Test automatically after connect/reconnect and after credential-related failures, and allow an explicit Test action. Do not probe the provider on every folder navigation. - **D-14:** A successful reconnect keeps cached metadata visible as stale, invalidates provider/listing/capability caches, and immediately refreshes the current folder. - **D-15:** A timeout or temporarily unreachable provider is an unhealthy connection state only. Preserve credentials and cached metadata, show an actionable warning, and allow retry/reconnect; never delete data because of transient failure. - **D-16:** Explicit user-initiated Disconnect requires confirmation, removes credentials and connection-scoped cloud metadata, and leaves all provider files untouched. Phase 13 has no byte cache to migrate. ### Codex's Discretion - Choose exact accessible dialog wording, progress labels, icons, and controlled provider-error translations while preserving the decisions above. - Choose the bounded retry count for automatic collision suffixing and safe provider-specific mechanics for trash versus permanent delete. - Choose endpoint shapes and service decomposition consistent with the existing owner-scoped cloud API, canonical adapter, reconciliation service, and shared frontend architecture. ## Canonical References **Downstream agents MUST read these before planning or implementing.** ### Milestone and prior phase contracts - `.planning/ROADMAP.md` — Phase 13 goal, requirements, success criteria, and Phase 14 boundary. - `.planning/REQUIREMENTS.md` — canonical CONN-01 through CONN-03 and CLOUD-02 through CLOUD-07/CLOUD-09 requirements; `IMPORT-01` remains future scope. - `.planning/PROJECT.md` — virtual-local storage model, privacy boundary, and shared-component direction. - `.planning/phases/12-cloud-resource-foundation/12-CONTEXT.md` — normalized capability, shared browser, freshness, metadata, and no-byte browse decisions inherited by this phase. - `.planning/phases/12.1-fix-nextcloud-root-listing-and-sync-visibility/12.1-CONTEXT.md` — truthful listing/freshness and provider-neutral correctness constraints. - `AGENTS.md` — non-negotiable architecture, security, testing, documentation, environment, and Git rules. ### Backend cloud contracts - `backend/storage/cloud_base.py` — canonical normalized actions, capability states, cloud resources/listings, and read-only adapter to extend for Phase 13 mutations. - `backend/storage/google_drive_backend.py` — Google Drive provider integration and operation semantics. - `backend/storage/onedrive_backend.py` — OneDrive/Graph provider integration and token lifecycle. - `backend/storage/nextcloud_backend.py` — Nextcloud adapter behavior. - `backend/storage/webdav_backend.py` — WebDAV behavior and SSRF/path safety boundary. - `backend/services/cloud_items.py` — sole metadata reconciliation entry point and stable item identity behavior. - `backend/api/cloud/browse.py` — owner-scoped connection-ID browse path, cache/freshness response, and capability serialization. - `backend/api/cloud/connections.py` — connect, health check, credential update, display-name rename, and disconnect behavior. - `backend/api/cloud/schemas.py` — credential-free whitelisted cloud response types. ### Shared frontend and verification - `frontend/src/components/storage/StorageBrowser.vue` — single local/cloud browser and existing shared upload, rename, move, delete, drag/drop, and capability UI. - `frontend/src/views/CloudFolderView.vue` — thin cloud data-provider integration and current upload/open placeholders. - `frontend/src/views/FileManagerView.vue` — canonical local interaction behavior that cloud operations must match. - `frontend/src/stores/cloudConnections.js` — connection and browse state, capabilities, freshness, and session-only navigation state. - `frontend/src/api/cloud.js` — cloud connection/browse API client surface to extend. - `backend/tests/test_cloud_backends.py` — provider contract test patterns. - `backend/tests/test_cloud.py` — connection and browse API integration patterns. - `backend/tests/test_cloud_security.py` — owner/admin/credential/SSRF/no-byte negative contract. - `frontend/src/components/storage/__tests__/StorageBrowser.capabilities.test.js` — shared capability rendering and interaction coverage. - `frontend/src/views/__tests__/CloudFolderRenderedFlow.test.js` — rendered shared-browser cloud flow coverage. ## Existing Code Insights ### Reusable Assets - `StorageBrowser.vue`: already owns the local/cloud rows, drop zone, upload progress, inline folder rename, move picker, drag-to-move, delete actions, and capability-aware controls; Phase 13 should extend its generic events rather than add cloud-only layout. - `CloudFolderView.vue`: already maps normalized `kind`, opaque `provider_item_id`, explicit breadcrumbs, upload queue state, and browse refresh; replace placeholders with thin API/store handlers. - `CloudResourceAdapter` and `CloudCapability`: already define normalized action vocabulary and provider-neutral capability reporting; mutation operations should extend this contract without provider-specific API branches. - `resolve_owned_connection`, `upsert_cloud_item`, and `reconcile_cloud_listing`: existing owner-scoped service primitives and the single metadata reconciliation path. ### Established Patterns - Views own stores and route state; `StorageBrowser` owns interaction/layout and emits events; providers never update `cloud_items` directly. - Cloud navigation and mutations use connection UUID plus opaque `provider_item_id`; provider IDs are never parsed into paths. - Cached metadata remains usable through provider failures, and freshness comes from the backend rather than inferred client-side. - Credentials are decrypted only at the provider/task boundary and never enter responses, broker payloads, logs, snapshots, or browser storage. ### Integration Points - Add provider-neutral mutation methods and normalized conflict/error results to the cloud adapter layer, then implement them for Google Drive, OneDrive, Nextcloud, and WebDAV. - Add owner-scoped schemas, service orchestration, connection-ID mutation/open endpoints, cache invalidation, reconciliation, and metadata-only auditing under `backend/api/cloud/` and `backend/services/`. - Feed shared operation events, sequential upload queue resolution, connection health, and mutation refresh results through `CloudFolderView`/the Pinia store into `StorageBrowser`. - Extend provider contract, API/security integration, store/view/component, and rendered-flow tests; preserve explicit unsupported-capability coverage. ## Specific Ideas - The intended rule is literal: if local and cloud operations look the same to the user, they are the same component and interaction in code. - Upload conflict resolution is queue-level: the current item blocks later items until the user resumes or cancels all. - Automatic collision names place the counter before the file extension. - Reconnect should feel non-destructive: stale metadata stays visible while DocuVault revalidates it. ## Deferred Ideas - Phase 14 must place bytes used for in-app cloud preview into DocuVault's temporary cache and remove them through normal cache eviction/clearing; preview must not become a browser-to-device download. - Future `IMPORT-01`: on explicit disconnect, convert cached/downloaded cloud files into local DocuVault documents under a folder named after the connection's current display name, preserve the cloud hierarchy, continue counting those bytes toward quota, and leave provider files untouched. This is a permanent import capability and remains outside Phase 13 and the current v0.3 scope. --- *Phase: 13-virtual-local-cloud-operations* *Context gathered: 2026-06-22*