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>
Provider-neutral mutable-operation contracts exist before routes or UI are wired.
Providers can hand refreshed credentials upward without writing the database themselves.
Reconciliation and freshness remain centralized in `cloud_items.py` even for mutable work.
path
provides
backend/storage/cloud_base.py
Normalized mutable-operation result types, health states, and provider error vocabulary.
path
provides
backend/services/cloud_operations.py
Owner-scoped orchestration for reconnect, content, upload, and folder mutation work.
from
to
via
pattern
provider refresh outcomes
encrypted credential persistence
cloud_operations orchestration
credentials
from
to
via
pattern
mutable provider results
cloud_items reconciliation
single service-layer integration point
reconcile
Build the Phase 13 backend foundation: the mutable cloud contract, provider-factory assertions, and the service-layer orchestration seam that owns credential refresh handoff, stale classification, and centralized reconciliation.
Purpose: Create the backend contract layer every later Phase 13 route and provider change depends on.
Output: A provider-neutral mutable adapter interface and a single orchestration module.
Task 1: Extend the shared cloud contract for mutable operations and normalized outcomes
backend/storage/cloud_base.py, backend/storage/cloud_backend_factory.py, backend/tests/test_cloud_backends.py, backend/tests/test_cloud_provider_contract.py
- backend/storage/cloud_base.py
- backend/storage/cloud_backend_factory.py
- backend/tests/test_cloud_backends.py
- backend/tests/test_cloud_provider_contract.py
- .planning/phases/13-virtual-local-cloud-operations/13-RESEARCH.md
- Test 1: providers expose one mutable-operation contract with normalized success, conflict, stale, offline, and unsupported results
- Test 2: providers can hand refreshed credentials upward without persisting them directly
- Test 3: preview support is explicit and binary-only rather than inferred from provider MIME quirks
Extend `backend/storage/cloud_base.py` with the mutable-operation interface and normalized result dataclasses for health, reconnect, preview support, upload conflict, create/rename collision, move validation, delete disclosure, and unsupported-operation reporting. Keep `kind` and `reason` vocabulary centralized here so every provider and route shares the same typed contract. Update `backend/storage/cloud_backend_factory.py` to assert the new interface without introducing provider-name switches in routers or services.
- the provider contract suites from 13-01 pass for normalized signatures and result shapes
- binary-only preview support is explicit in the shared contract
- providers are not given permission to write audit rows or `cloud_items` directly
docker compose run --rm backend pytest -v tests/test_cloud_backends.py tests/test_cloud_provider_contract.py -x
The codebase now has one canonical mutable cloud contract for all later Phase 13 backend work.
Task 2: Create the cloud operations orchestration seam without breaking freshness ownership
backend/services/cloud_operations.py, backend/services/cloud_items.py, backend/tests/test_cloud_reconnect.py
- backend/services/cloud_items.py
- backend/tests/test_cloud_reconnect.py
- backend/services/audit.py
- .planning/phases/13-virtual-local-cloud-operations/13-CONTEXT.md
- Test 1: the orchestration layer resolves owned connections and classifies reauth versus transient offline states
- Test 2: refreshed credentials persist only above the provider boundary
- Test 3: reconnect and mutation work invalidate caches and route back through centralized reconciliation rather than direct ORM writes
Create `backend/services/cloud_operations.py` as the single service-layer seam for D-13 through D-16. It must resolve the owned connection, decrypt credentials only at the provider boundary, accept refreshed credentials back from providers for encrypted persistence, classify credential failures versus transient outages, and funnel listing invalidation or follow-up refresh through `cloud_items.py`. Keep service exceptions domain-specific or `ValueError` only; routers remain responsible for translating them to `HTTPException`.
- reconnect red tests pass at the orchestration layer
- persisted refreshed credentials are handled only in the service layer, never inside providers
- `cloud_items.py` remains the sole reconciliation and freshness authority
docker compose run --rm backend pytest -v tests/test_cloud_reconnect.py tests/test_cloud_provider_contract.py -x
The backend now has a single orchestration seam that later routes and providers can safely build on.
<threat_model>
Trust Boundaries
Boundary
Description
router/service → provider
Provider exceptions and refreshed credentials must be normalized before leaving the backend boundary.
service → database
Only orchestration code may persist refreshed credentials or trigger reconciliation.
STRIDE Threat Register
Threat ID
Category
Component
Disposition
Mitigation Plan
T-13-10
T
mutable contract layer
mitigate
Centralize kind/reason result vocabulary in cloud_base.py and verify with provider contract tests.
T-13-11
I
refreshed credentials
mitigate
Persist only encrypted credentials above the provider boundary; verify in reconnect tests.
T-13-12
T
reconciliation path
mitigate
Route all mutable follow-up work through cloud_items.py; forbid direct provider ORM writes.
</threat_model>
- Pass the provider contract and reconnect suites introduced in Wave 0.
- Confirm every backend verify command remains containerized.
- Confirm the orchestration seam is the only place where refreshed credentials can be persisted.
<success_criteria>
Mutable-operation contracts and the orchestration seam exist before route work begins.
Provider-level contract coverage now has a real shared interface to validate.
Freshness and reconciliation ownership remain centralized instead of fragmenting across routers or adapters.
</success_criteria>
Create `.planning/phases/13-virtual-local-cloud-operations/13-03-SUMMARY.md` when done