# Phase 5: Cloud Storage Backends - Discussion Log > **Audit trail only.** Do not use as input to planning, research, or execution agents. > Decisions are captured in CONTEXT.md — this log preserves the alternatives considered. **Date:** 2026-05-28 **Phase:** 5-cloud-storage-backends **Areas discussed:** Backend scope, OAuth flow & token refresh, Storage selection UX, Cloud document retrieval --- ## Backend Scope | Option | Description | Selected | |--------|-------------|----------| | All 4 in one phase | OneDrive, Google Drive, Nextcloud, WebDAV all in Phase 5 | ✓ | | WebDAV + Nextcloud first | Ship simpler (credential-based) backends first; OAuth providers in Phase 6 | | | Just one provider as MVP | One end-to-end provider to prove the pattern, others follow | | **User's choice:** All 4 in one phase **Notes:** User wants the full feature set shipped together. --- ## OAuth Flow & Token Refresh ### OAuth callback architecture | Option | Description | Selected | |--------|-------------|----------| | FastAPI handles it, then redirects to Vue | Backend exchanges code for tokens, saves encrypted creds, redirects browser to Vue with success/error query param | ✓ | | Vue intercepts the callback | Frontend catches redirect, POSTs code to FastAPI — auth code briefly in frontend | | | You decide | Claude chooses | | **User's choice:** FastAPI handles it, then redirects to Vue **Notes:** Keeps tokens entirely server-side; consistent with existing auth architecture. ### Token refresh strategy | Option | Description | Selected | |--------|-------------|----------| | On-demand refresh | Catch 401, refresh silently, retry — transparent to user | ✓ (via Other) | | Proactive Celery beat refresh | Background task refreshes before expiry | | | Fail and prompt re-auth | Mark REQUIRES_REAUTH on expiry, no silent refresh | | **User's choice:** Automatic refresh (on-demand, transparent). Also explicitly requested disconnect per-connection + "Disconnect all" option. **Notes:** Falls back to REQUIRES_REAUTH only on `invalid_grant` (refresh token itself revoked). ### Nextcloud/WebDAV credential method | Option | Description | Selected | |--------|-------------|----------| | URL + username + app password | App passwords revocable individually — recommended | ✓ (via Other) | | URL + username + real password | Simpler; revocation requires changing entire account password | | | You decide | Claude picks | | **User's choice:** Show both options in the UI with explanations and trade-offs; recommend app passwords. Backend stores whichever the user picks. **Notes:** Both use HTTP Basic Auth at the protocol level. UI copy explains the difference. --- ## Storage Selection UX ### Sidebar cloud folder tree depth | Option | Description | Selected | |--------|-------------|----------| | Lazy-load one level at a time | Expand a node → fetch its children from cloud API | ✓ | | Show only root of each provider | Single node per provider, click opens full-screen cloud browser | | | Pre-fetch 2 levels deep on connect | Eager fetch on connect; faster browsing, stale quickly | | **User's choice:** Lazy-load one level at a time **Notes:** Cloud providers appear as top-level sidebar nodes alongside local MinIO folders, matching a Windows Explorer / Nextcloud-style file manager layout. ### Upload destination | Option | Description | Selected | |--------|-------------|----------| | Follows the active folder | Upload goes to the backend of the folder the user is viewing | ✓ | | Default backend in settings | Global setting overridden per-upload | | | Per-upload choice at upload time | Dropdown on every upload dialog | | **User's choice:** Follows the active folder (context-driven) **Notes:** No explicit setting needed — the active folder's backend determines the destination. ### Existing document migration | Option | Description | Selected | |--------|-------------|----------| | Stay in MinIO — no migration | Existing docs unaffected; local and cloud coexist | ✓ | | Optional migration | Post-connect prompt to migrate existing docs | | | You decide | | | **User's choice:** Stay in MinIO — no migration **Notes:** CLOUD-03 satisfied by coexistence without migration. ### Cloud provider management location | Option | Description | Selected | |--------|-------------|----------| | Existing SettingsView, new "Cloud Storage" tab | Add tab to SettingsView alongside existing tabs | ✓ | | Dedicated /cloud-storage route | New full-page view | | | Sidebar action on cloud provider node | Gear icon → management popover | | **User's choice:** New "Cloud Storage" tab in SettingsView --- ## Cloud Document Retrieval ### Upload path for cloud backends | Option | Description | Selected | |--------|-------------|----------| | FastAPI intermediary | File bytes go through FastAPI → cloud provider API | ✓ | | Cloud-native resumable upload URLs | Provider-specific upload session URL generated and sent to browser | | | You decide | | | **User's choice:** FastAPI intermediary for cloud uploads **Notes:** Presigned-PUT-URL flow stays MinIO-only. Cloud backends' `generate_presigned_put_url` raises `NotImplementedError`. ### Download/preview path | Option | Description | Selected | |--------|-------------|----------| | Same /api/documents/{id}/content proxy | Backend resolves StorageBackend from document.storage_backend | ✓ | | Separate /api/documents/{id}/cloud-content | Parallel endpoint for cloud docs | | | Temporary cloud provider URL (redirect) | Return provider's signed download URL to browser — exposes cloud URLs | | **User's choice:** Same proxy endpoint **Notes:** Frontend remains storage-backend-agnostic. ### Cloud folder tree freshness | Option | Description | Selected | |--------|-------------|----------| | Live calls + 60s in-memory TTL cache | Per-folder cache keyed by user+provider+path; 60s TTL | ✓ | | Live calls only, no cache | Always fresh; no protection against rapid UI interactions | | | You decide | | | **User's choice:** Live calls + 60s in-memory TTL cache **Notes:** User raised valid concern about cloud API rate limits and potential throttling. Claude explained: human-paced browsing is well within all provider limits (Google Drive: 12k req/100s per user); TTL cache protects against collapse/re-expand patterns. No DB sync needed. --- ## Claude's Discretion - Python OAuth library choice (Google: `google-auth-oauthlib`; Microsoft: `msal`) - WebDAV Python library choice (`webdavclient3` vs. `aiohttp` with manual PROPFIND) - TTL cache implementation (`cachetools.TTLCache` vs. dict + timestamp) - OAuth state store implementation (Redis / short-lived DB row / signed JWT) ## Deferred Ideas - Document migration between backends (local → cloud) - Cloud-native resumable upload URLs (performance optimization) - Shared/team cloud storage - Cloud folder tree DB sync / offline cache - Email notifications on REQUIRES_REAUTH