Plans 01–11, CONTEXT, PATTERNS, RESEARCH, REVIEW-FIX, and updated SUMMARY and CONTEXT for the virtual-local-cloud-operations phase. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
28 KiB
Phase 13: Virtual-Local Cloud Operations - Pattern Map
Mapped: 2026-06-22
Files analyzed: 33 likely new/modified files
Analogs found: 33 / 33 (6 are composite/no-exact)
Inherited phase rules that stay locked
- Keep
StorageBrowser.vueas the only file browser. Cloud behavior extends emitted events and props; it does not fork layout. See [AGENTS.md], Phase 12 patterns, and [frontend/src/components/storage/StorageBrowser.vue]. - Keep cloud routing owner-scoped by connection UUID plus opaque
provider_item_id; never parse provider refs on the client. Primary analogs: [backend/api/cloud/browse.py:183], [frontend/src/views/CloudFolderView.vue:42], [frontend/src/components/cloud/CloudFolderTreeItem.vue:42]. - Keep metadata reconciliation centralized in
reconcile_cloud_listing/apply_listing_and_finalize; provider adapters never writecloud_itemsrows directly. Primary analogs: [backend/services/cloud_items.py:163], [backend/services/cloud_items.py:271]. - Keep service-layer exception discipline: services raise domain errors /
ValueError, routers translate toHTTPException. Primary analogs: [AGENTS.md], [backend/services/cloud_items.py:1]. - Keep audit writes metadata-only and in the caller’s transaction. Primary analog: [backend/services/audit.py:27].
File Classification
| Likely file | Role | Data flow | Closest analog | Match |
|---|---|---|---|---|
backend/api/cloud/operations.py |
route | request-response + file-I/O + CRUD | backend/api/cloud/browse.py, backend/api/documents/content.py, backend/api/documents/upload.py, backend/api/folders.py |
composite |
backend/api/cloud/connections.py |
route | request-response | itself + backend/tasks/cloud_tasks.py |
exact |
backend/api/cloud/schemas.py |
schema | transform | itself | exact |
backend/services/cloud_operations.py |
service | CRUD + transform | backend/services/cloud_items.py + backend/services/audit.py |
composite |
backend/services/cloud_items.py |
service | CRUD + batch reconcile | itself | exact |
backend/storage/cloud_base.py |
contract | transform | itself | exact |
backend/storage/cloud_backend_factory.py |
factory | request-response | itself | exact |
backend/storage/google_drive_backend.py |
provider | file-I/O + CRUD | itself | exact |
backend/storage/onedrive_backend.py |
provider | file-I/O + CRUD | itself | exact |
backend/storage/webdav_backend.py |
provider | file-I/O + CRUD | itself | exact |
backend/storage/nextcloud_backend.py |
provider | file-I/O | itself + webdav_backend.py |
exact |
backend/tasks/cloud_tasks.py |
task | event-driven + batch | itself | exact |
frontend/src/api/cloud.js |
API client | request-response | itself + frontend/src/api/documents.js |
exact |
frontend/src/stores/cloudConnections.js |
store | state transform | itself | exact |
frontend/src/views/CloudFolderView.vue |
thin view | request-response + queue orchestration | itself + frontend/src/views/FileManagerView.vue |
exact |
frontend/src/components/storage/StorageBrowser.vue |
smart component | CRUD UI + queue UI | itself | exact |
frontend/src/components/settings/SettingsCloudTab.vue |
smart component | request-response | itself | exact |
frontend/src/components/cloud/CloudCredentialModal.vue |
modal/form | request-response | itself | exact |
backend/tests/test_cloud.py |
integration test | request-response | itself | exact |
backend/tests/test_cloud_security.py |
security-negative test | request-response | itself | exact |
backend/tests/test_cloud_backends.py |
provider unit/contract test | file-I/O | itself | exact |
backend/tests/test_cloud_provider_contract.py |
provider contract test | transform | itself | exact |
backend/tests/test_cloud_items.py |
service/task test | CRUD + batch | itself | exact |
backend/tests/test_cloud_mutations.py |
integration/contract test | CRUD + file-I/O | test_cloud.py + test_cloud_security.py + test_cloud_items.py |
composite |
backend/tests/test_cloud_reconnect.py |
integration/security test | request-response + task | test_cloud.py + test_cloud_items.py |
composite |
backend/tests/test_cloud_audit.py |
integration test | transform | backend/tests/test_audit.py + backend/tests/test_cloud.py |
partial |
frontend/src/views/__tests__/CloudFolderView.test.js |
view unit test | request-response | itself | exact |
frontend/src/views/__tests__/CloudFolderRenderedFlow.test.js |
rendered-flow test | request-response | itself | exact |
frontend/src/components/storage/__tests__/StorageBrowser.capabilities.test.js |
component unit test | CRUD UI | itself | exact |
frontend/src/components/storage/__tests__/StorageBrowser.cloud-queue.test.js |
component unit test | queue UI | StorageBrowser.capabilities.test.js + FileManagerView.vue upload flow |
composite |
frontend/src/views/__tests__/CloudFolderOpenPreview.test.js |
rendered-flow test | request-response + preview | CloudFolderRenderedFlow.test.js + document content helpers |
composite |
frontend/src/stores/__tests__/cloudConnections.test.js |
store unit test | state transform | itself | exact |
frontend/src/components/settings/__tests__/SettingsCloudTab.test.js |
component unit test | request-response | itself | exact |
frontend/src/components/settings/__tests__/SettingsCloudTab.health.test.js |
component unit test | health/reconnect UI | SettingsCloudTab.test.js + store freshness tests |
partial |
Pattern Assignments
backend/api/cloud/operations.py
Primary analogs
- Route/dependency skeleton: [backend/api/cloud/browse.py:19-42], [backend/api/cloud/browse.py:183-214]
- Connection settings/test/update/disconnect patterns: [backend/api/cloud/connections.py:368-434], [backend/api/cloud/connections.py:492-579], [backend/api/cloud/connections.py:604-635]
- Authorized byte streaming and cloud-error translation: [backend/api/documents/content.py:50-103]
- Multipart upload proxy pattern: [backend/api/documents/upload.py:122-198]
- Local create/rename/delete/move handler shape: [backend/api/folders.py:122-160], [backend/api/folders.py:232-265], [backend/api/folders.py:268-351], [backend/api/folders.py:357-375]
Copy these conventions
- Use
get_regular_user,get_db,account_limiter, andrequest.state.current_user = current_userexactly like cloud browse/connections. - Resolve ownership through
resolve_owned_connection(...)before any provider action. - Translate provider/service failures to controlled
HTTPExceptionmessages like document content/upload already do; do not surface raw provider text. - For open/preview/download, copy the
StreamingResponse+CloudConnectionErrormapping fromcontent.py, but key authorization off cloud connection/item ownership instead ofDocument. - For upload/create/rename/move/delete, keep router bodies thin: validate request shape, call service, return whitelisted schema, write no inline reconciliation logic.
No exact analog
- There is no existing single cloud route file that combines owner-scoped connection actions with content proxying and normalized mutation results. Keep the file shaped like
browse.py, but borrow handler bodies from the document/folder routers above.
backend/api/cloud/connections.py
Primary analogs
- WebDAV connect and health-check flow: [backend/api/cloud/connections.py:368-434]
- Credential update flow: [backend/api/cloud/connections.py:492-579]
- Display-name rename: [backend/api/cloud/connections.py:582-601]
- Disconnect confirmation target: [backend/api/cloud/connections.py:604-635]
Copy these conventions
- Keep
_get_owned_connection(...)for owner checks. - Keep URL validation before backend construction.
- Keep audit writes adjacent to the successful state change.
- If reconnect/test routes are added, model them after
connect_webdav+update_webdav_credentials: validate, health-check, persist, audit, commit.
Phase 13-specific caution
- The current OAuth callback always inserts a new row (
_upsert_cloud_connection = _insert_cloud_connection) at [backend/api/cloud/connections.py:128-129]. Do not copy that behavior for reconnect; Phase 13 needs connection-row preservation.
backend/api/cloud/schemas.py
Primary analog
- Current cloud whitelist schemas: [backend/api/cloud/schemas.py:17-86]
Copy these conventions
- Add only explicit allowlist response/request models.
- Keep validators at schema level for user-submitted fields, as in
ConnectionRenameRequest. - Keep credentials, provider URLs, and raw provider payloads out of every schema.
No exact analog
- There is no current normalized mutation-result schema. Add new result types beside
CloudBrowseResponse, not in routers.
backend/services/cloud_operations.py
Primary analogs
- Owner resolution / stable identity / folder freshness: [backend/services/cloud_items.py:38-62], [backend/services/cloud_items.py:97-159], [backend/services/cloud_items.py:271-342]
- Metadata-only audit helper: [backend/services/audit.py:27-58]
- Background refresh orchestration: [backend/tasks/cloud_tasks.py:50-163]
Copy these conventions
- Accept UUIDs/strings the same way
cloud_items.pydoes. - Raise domain errors or
ValueError, neverHTTPException. - Reconcile and finalize folder state before returning success.
- Write audit rows through
write_audit_log(...), letting the caller own the transaction.
No exact analog
- There is no existing service that turns provider mutation outcomes into normalized API results. Treat this as the new orchestration seam; do not push that logic into routers or providers.
backend/services/cloud_items.py
Primary analog
- Keep using the current service itself.
Copy these conventions
- Owner resolution: [backend/services/cloud_items.py:38-62]
- Stable upsert-by-
(connection_id, provider_item_id): [backend/services/cloud_items.py:97-159] - Complete-vs-incomplete reconciliation: [backend/services/cloud_items.py:163-213]
- Single freshness gate: [backend/services/cloud_items.py:271-342]
- Controlled folder-state updates: [backend/services/cloud_items.py:345-384]
Planner note
- Any mutation service should feed its authoritative provider result back through these primitives instead of adding direct ORM writes elsewhere.
backend/storage/cloud_base.py
Primary analog
- Keep extending the current contract file itself: [backend/storage/cloud_base.py:27-245]
Copy these conventions
- Stable action vocabulary and reason codes live here, not in routers or Vue.
- Immutable normalized dataclasses (
CloudCapability,CloudResource,CloudListing) are the pattern to follow for new mutation result types. - Keep provider-specific branching out of the shared contract.
No exact analog
- There is no Phase-13 mutation result/value type yet. New normalized result dataclasses belong here.
backend/storage/cloud_backend_factory.py
Primary analog
- Current factory and adapter assertion: [backend/storage/cloud_backend_factory.py:7-66]
Copy these conventions
- Keep lazy imports.
- Keep Nextcloud URL normalization in the factory boundary.
- If a mutable-adapter subclass is introduced, assert the interface here instead of switching on provider names in routers.
backend/storage/google_drive_backend.py
Primary analog
- Existing upload/download/delete/list/capability patterns: [backend/storage/google_drive_backend.py:140-172], [backend/storage/google_drive_backend.py:174-207], [backend/storage/google_drive_backend.py:257-272], [backend/storage/google_drive_backend.py:276-417]
Copy these conventions
- Wrap SDK calls in
asyncio.to_thread(). - Centralize provider error classification in helper methods like
_handle_http_error(...). - Normalize provider metadata into
CloudResourceobjects. - Keep the backend stateless: it may return refreshed credentials or typed errors, but must not write DB state directly.
backend/storage/onedrive_backend.py
Primary analog
- Existing token lifecycle + upload/download/delete/list/capabilities: [backend/storage/onedrive_backend.py:83-154], [backend/storage/onedrive_backend.py:158-218], [backend/storage/onedrive_backend.py:220-245], [backend/storage/onedrive_backend.py:280-409]
Copy these conventions
- Refresh token on demand inside the backend boundary.
- Keep Graph HTTP async with
httpx. - Keep
CloudConnectionErrorunified across providers.
Gap to flag
- There is no persistence pattern yet for refreshed OneDrive credentials; Phase 13 must add one above the backend, not inside it.
backend/storage/webdav_backend.py
Primary analog
- Existing SSRF, PUT/GET/DELETE, list-folder, and capability patterns: [backend/storage/webdav_backend.py:66-137], [backend/storage/webdav_backend.py:139-174], [backend/storage/webdav_backend.py:222-237], [backend/storage/webdav_backend.py:241-370]
Copy these conventions
- Re-run
validate_cloud_url(...)before every outbound request. - Keep basename/path-traversal protection when building destination names.
- Keep WebDAV-specific overwrite/conflict semantics inside this provider file.
backend/storage/nextcloud_backend.py
Primary analog
- Minimal specialization over WebDAV: [backend/storage/nextcloud_backend.py:38-90]
Copy these conventions
- Keep Nextcloud as a tiny specialization, not a parallel backend.
- If Phase 13 needs Nextcloud-specific mutation quirks, implement them as narrow overrides that preserve the public contract.
backend/tasks/cloud_tasks.py
Primary analog
- Current refresh worker: [backend/tasks/cloud_tasks.py:50-163], [backend/tasks/cloud_tasks.py:175-216]
Copy these conventions
- Revalidate ownership inside the worker.
- Decrypt credentials inside the worker, never in broker payload.
- Use sentinel exceptions to separate retryable provider failures from terminal auth failures.
- Reuse this task model if reconnect or stale-metadata recovery needs post-success refresh.
frontend/src/api/cloud.js
Primary analogs
- Existing connection browse/config/update methods: [frontend/src/api/cloud.js:11-18], [frontend/src/api/cloud.js:36-50], [frontend/src/api/cloud.js:73-88]
- Cloud upload helper shape: [frontend/src/api/documents.js:48-54]
Copy these conventions
- Keep all Phase 13 cloud endpoints behind this domain module.
- Keep connection UUID and encoded
parent_refhandling here. - Add new
open/preview/upload/create/rename/move/delete/test/reconnecthelpers here instead of calling raw URLs from views/components.
frontend/src/stores/cloudConnections.js
Primary analog
- Current store state and reset/mapping helpers: [frontend/src/stores/cloudConnections.js:33-138]
Copy these conventions
- Keep server state translation centralized in the store.
- Keep sessionStorage limited to folder refs only.
- Reset browse state on connection switch.
No exact analog
- There is no queue/conflict/resume state machine yet. Add it here only if it is shared across cloud views/settings; otherwise keep queue orchestration in
CloudFolderView.
frontend/src/views/CloudFolderView.vue
Primary analogs
- Existing cloud thin-view contract: [frontend/src/views/CloudFolderView.vue:1-20], [frontend/src/views/CloudFolderView.vue:125-170]
- Local upload / create / rename / move / delete orchestration: [frontend/src/views/FileManagerView.vue:1-30], [frontend/src/views/FileManagerView.vue:103-182]
Copy these conventions
- Keep the view thin: store/router/API orchestration only.
- Pass everything into
StorageBrowser; do not add layout or grid logic here. - Reuse the local upload queue orchestration style from
FileManagerView, but Phase 13 needs sequential pause/resume instead of the current all-at-oncePromise.allSettled(...)placeholder at [frontend/src/views/CloudFolderView.vue:172-181]. - Use toasts and success/error handling the same way
FileManagerViewdoes.
frontend/src/components/storage/StorageBrowser.vue
Primary analog
- Extend the current shared component itself: [frontend/src/components/storage/StorageBrowser.vue:140-275], [frontend/src/components/storage/StorageBrowser.vue:424-681]
Copy these conventions
- Props/events are the contract; keep new behavior behind emitted events and prop-driven state.
- Capability-aware buttons and notices stay in this component: [frontend/src/components/storage/StorageBrowser.vue:360-418], [frontend/src/components/storage/StorageBrowser.vue:495-530].
- New folder / rename inline patterns already exist here: [frontend/src/components/storage/StorageBrowser.vue:118-135], [frontend/src/components/storage/StorageBrowser.vue:157-166], [frontend/src/components/storage/StorageBrowser.vue:543-593].
- File move picker and drag-to-move patterns already exist here: [frontend/src/components/storage/StorageBrowser.vue:253-344], [frontend/src/components/storage/StorageBrowser.vue:595-621].
Gap to flag
- There is no existing conflict dialog / paused upload queue UI. That is a real no-analog area inside the shared browser and should be added here rather than in a cloud-only component.
frontend/src/components/settings/SettingsCloudTab.vue
Primary analog
- Existing settings actions and confirm flows: [frontend/src/components/settings/SettingsCloudTab.vue:21-102], [frontend/src/components/settings/SettingsCloudTab.vue:104-170], [frontend/src/components/settings/SettingsCloudTab.vue:293-359]
Copy these conventions
- Keep provider rows, inline status badges, and destructive confirms in one shared settings tab.
- Add Test/Reconnect controls beside existing Connect/Edit/Remove actions; do not create a parallel health screen.
- Keep OAuth initiation in the component and store mutation calls behind the store/API layer.
frontend/src/components/cloud/CloudCredentialModal.vue
Primary analog
- Existing submit branching for create vs edit: [frontend/src/components/cloud/CloudCredentialModal.vue:301-323]
Copy these conventions
- Keep credential edits inside the modal for WebDAV/Nextcloud.
- If Phase 13 adds explicit “Test connection” before save, hang it off the same API module and modal state machine instead of duplicating form state elsewhere.
backend/tests/test_cloud.py
Primary analog
- Current integration coverage for connect/upload/status/browse/rename/refresh: [backend/tests/test_cloud.py:30-65], [backend/tests/test_cloud.py:473-527], [backend/tests/test_cloud.py:532-655], [backend/tests/test_cloud.py:998-1315]
Copy these conventions
- Use the shared auth helper pattern and
async_client. - Patch provider/network boundaries, not route internals, where possible.
- Assert both HTTP contract and DB side effects.
backend/tests/test_cloud_security.py
Primary analog
- Current security-negative suite: [backend/tests/test_cloud_security.py:37-117], [backend/tests/test_cloud_security.py:122-340]
Copy these conventions
- Add Phase 13 wrong-owner/admin/credential/no-byte/cross-connection negatives here.
- Keep raw-provider-error sanitization assertions here, not only in happy-path integration tests.
backend/tests/test_cloud_backends.py
Primary analog
- Provider backend behavior tests: [backend/tests/test_cloud_backends.py:334-420] and the rest of the file’s provider sections
Copy these conventions
- Provider-specific fixtures, normalized assertions.
- Explicit “never download/mutate while browsing” checks.
- Keep backend tests provider-neutral where possible and provider-specific only where semantics differ.
backend/tests/test_cloud_provider_contract.py
Primary analog
- Canonical signature/identity/pagination/no-byte contract: [backend/tests/test_cloud_provider_contract.py:201-276], [backend/tests/test_cloud_provider_contract.py:376-536], [backend/tests/test_cloud_provider_contract.py:659-727]
Copy these conventions
- Any new mutable adapter methods should get the same style of canonical contract tests: signature, normalized result, trusted caller identity, no forbidden side effects.
backend/tests/test_cloud_items.py
Primary analog
- Owner-scoped service and folder-state tests: [backend/tests/test_cloud_items.py:368-529], [backend/tests/test_cloud_items.py:545-859]
Copy these conventions
- Mutation reconciliation tests belong here: stable UUID across rename/move, complete/incomplete behavior, freshness truth, no quota mutation.
backend/tests/test_cloud_mutations.py
Closest analogs
- API behavior: [backend/tests/test_cloud.py:473-527], [backend/tests/test_cloud.py:1112-1249]
- Security negatives: [backend/tests/test_cloud_security.py:122-340]
- Reconciliation truth: [backend/tests/test_cloud_items.py:411-499], [backend/tests/test_cloud_items.py:743-859]
No exact analog
- There is no existing end-to-end mutation suite for cloud items. Build it as a new file, but follow the helper/fixture style of
test_cloud.py.
backend/tests/test_cloud_reconnect.py
Closest analogs
- Connection lifecycle/status: [backend/tests/test_cloud.py:532-655]
- Worker/freshness behavior: [backend/tests/test_cloud.py:1251-1315], [backend/tests/test_cloud_items.py:545-609]
No exact analog
- There is no dedicated reconnect/token-persistence suite today.
backend/tests/test_cloud_audit.py
Closest analogs
- Audit helper behavior: [backend/services/audit.py:27-58]
- Inline audit assertions in cloud routes: [backend/api/cloud/connections.py:351-359], [backend/api/cloud/connections.py:422-430], [backend/api/cloud/connections.py:567-575], [backend/api/cloud/connections.py:624-632]
No exact analog
- There is no cloud-mutation audit suite today; create one that asserts metadata-only payloads and same-transaction persistence.
frontend/src/views/__tests__/CloudFolderView.test.js
Primary analog
- Existing thin-view cloud tests: [frontend/src/views/tests/CloudFolderView.test.js:73-294]
Copy these conventions
- Stub
StorageBrowserwhen the test is about view orchestration only. - Assert route params, API calls, and props passed to the browser.
frontend/src/views/__tests__/CloudFolderRenderedFlow.test.js
Primary analog
- Existing real-browser rendered flow: [frontend/src/views/tests/CloudFolderRenderedFlow.test.js:1-260]
Copy these conventions
- Render the real
StorageBrowserwhen testing end-to-end view/browser interactions. - Keep only router/API boundaries mocked.
frontend/src/components/storage/__tests__/StorageBrowser.capabilities.test.js
Primary analog
- Current accessibility and unsupported-capability suite: [frontend/src/components/storage/tests/StorageBrowser.capabilities.test.js:47-257]
Copy these conventions
- Assert emitted events,
aria-disabled, notices, and touch-target classes from the real component. - Extend this file for new capability buttons only; do not hide cloud actions based on mode.
frontend/src/components/storage/__tests__/StorageBrowser.cloud-queue.test.js
Closest analogs
- Capability interaction assertions: [frontend/src/components/storage/tests/StorageBrowser.capabilities.test.js:89-190]
- Local upload queue behavior source: [frontend/src/views/FileManagerView.vue:103-128]
No exact analog
- There is no existing paused sequential queue test file. Create it as a dedicated component suite around the shared browser’s new queue/conflict UI.
frontend/src/views/__tests__/CloudFolderOpenPreview.test.js
Closest analogs
- Rendered cloud flow: [frontend/src/views/tests/CloudFolderRenderedFlow.test.js:170-260]
- Authorized document content fetch helper: [frontend/src/api/documents.js:60-81]
No exact analog
- There is no cloud open/preview rendered-flow test today.
frontend/src/stores/__tests__/cloudConnections.test.js
Primary analog
- Existing store tests for selection, freshness, session state: [frontend/src/stores/tests/cloudConnections.test.js:28-237]
Copy these conventions
- Keep pure store tests focused on mapping and reset behavior.
- If queue state or health-state translation lives in the store, test it here once.
frontend/src/components/settings/__tests__/SettingsCloudTab.test.js
Primary analog
- Existing settings-tab tests: [frontend/src/components/settings/tests/SettingsCloudTab.test.js:1-132]
Copy these conventions
- Mock the store and API module, not network.
- Keep component tests structural and action-trigger oriented.
frontend/src/components/settings/__tests__/SettingsCloudTab.health.test.js
Closest analogs
- Existing settings tab structure: [frontend/src/components/settings/tests/SettingsCloudTab.test.js:51-132]
- Store freshness/health state assertions: [frontend/src/stores/tests/cloudConnections.test.js:160-237]
No exact analog
- There is no dedicated health/test/reconnect settings suite yet.
Shared Patterns to Reuse Everywhere
Authentication / ownership
- Regular-user-only dependency: [backend/api/cloud/browse.py:29-31], [backend/api/cloud/connections.py:25-27], [backend/api/documents/content.py:24-26]
- Owner resolution before resource work: [backend/api/cloud/browse.py:205-214], [backend/api/cloud/connections.py:132-141], [backend/services/cloud_items.py:38-62]
Router shape
- Thin routers with typed bodies +
account_limiter: [backend/api/cloud/connections.py:281-304], [backend/api/cloud/browse.py:183-200], [backend/api/folders.py:122-149] - Response shaping through explicit Pydantic schemas or dict helpers, never raw ORM/provider payloads: [backend/api/cloud/browse.py:64-97], [backend/api/cloud/schemas.py:17-67]
Error translation
CloudConnectionErrorbecomes controlled reconnect guidance: [backend/api/documents/upload.py:160-175], [backend/api/documents/content.py:61-76]- Incomplete/stale provider state becomes controlled warning, not fake success: [backend/services/cloud_items.py:319-342], [backend/api/cloud/browse.py:296-307]
Audit
- Use
write_audit_log(...)after successful state change, inside caller-owned transaction: [backend/services/audit.py:27-58]
Provider boundary
- Providers normalize data and keep SDK/HTTP details private: [backend/storage/google_drive_backend.py:276-362], [backend/storage/onedrive_backend.py:300-386], [backend/storage/webdav_backend.py:241-332]
- Factories own provider construction and URL normalization: [backend/storage/cloud_backend_factory.py:7-66]
Frontend architecture
- Thin view -> shared browser: [frontend/src/views/CloudFolderView.vue:1-20], [frontend/src/views/FileManagerView.vue:1-30]
- Shared browser owns interaction/layout/state: [frontend/src/components/storage/StorageBrowser.vue:424-681]
- Settings tab owns connection controls, not provider-specific subviews: [frontend/src/components/settings/SettingsCloudTab.vue:21-214]
Testing
- Integration tests assert API contract plus DB side effect: [backend/tests/test_cloud.py:532-655], [backend/tests/test_cloud.py:1112-1249]
- Security tests assert absence of leaks and forbidden side effects: [backend/tests/test_cloud_security.py:197-301]
- View tests stub the browser for orchestration-only checks; rendered-flow tests use the real browser: [frontend/src/views/tests/CloudFolderView.test.js:51-101], [frontend/src/views/tests/CloudFolderRenderedFlow.test.js:170-205]
No-Analog / planner watchlist
- Provider-neutral mutation result dataclasses do not exist yet. Add them in
backend/storage/cloud_base.py; do not leak provider payloads. - OAuth reconnect that patches an existing connection row does not exist yet. Current callback flow inserts a new row.
- Shared paused upload queue UI for cloud conflicts/errors does not exist yet. Add it in
StorageBrowser.vue, not a cloud-only component. - Authorized cloud-item preview/open endpoints do not exist yet. Reuse document content streaming patterns, but this is a new endpoint family.
- Dedicated reconnect/audit/open-preview test suites do not exist yet; create them instead of overloading unrelated files.
Recommended implementation order from pattern proximity
- Extend
cloud_base.py+ provider backends + factory. - Add
cloud_operations.pyand keep all reconciliation throughcloud_items.py. - Add
api/cloud/operations.py, then minimally extendconnections.py/schemas.py. - Extend
api/cloud.js+cloudConnections.js+CloudFolderView.vue. - Extend
StorageBrowser.vueandSettingsCloudTab.vue. - Add the missing dedicated backend/frontend test files before broad polish.