# 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
