# Phase 12.1: Fix Nextcloud Root Listing and Sync Visibility - Context **Gathered:** 2026-06-22 **Status:** Ready for planning **Source:** User-reported integration failure and test-account manifest ## Phase Boundary Diagnose and fix the cloud browse path that can report a successful/fresh synchronization while showing no provider files or folders. Prove the repair against the configured Nextcloud test account and add provider-neutral listing contracts for Nextcloud, generic WebDAV, Google Drive, and OneDrive. This phase repairs browse/list correctness and truthful freshness; cloud mutations remain Phase 13 scope. ## Implementation Decisions ### Live Nextcloud acceptance contract - D-01: The ignored repository `.env` provides the opt-in live-test variables `NEXTCLOUD_URL`, `NEXTCLOUD_USER`, and `NEXTCLOUD_APP_PASSWORD`; credentials must never be printed, logged, committed, placed in test IDs, or copied into planning artifacts. - D-02: The DocuVault application identity used for the live integration flow is `testuser@docuvault.example`. - D-03: A successful root browse must expose exactly these expected entry names, with folder/file kind checked separately: `Documents`, `docuvault`, `Photos`, `Templates`, `Nextcloud.png`, `Nextcloud Intro.mp4`, `Manual Nextcloud.png`, `Readme.md`, `Reasons to use Nextcloud.pdf`, `Template credits.md`. - D-04: Live provider tests are opt-in, read-only, and skip with an explicit prerequisite message when credentials are absent. They may list metadata but must not upload, create, rename, move, delete, download bytes, or change quota. ### Provider-wide correctness - D-05: The fix must establish one provider-neutral listing correctness contract for Nextcloud, generic WebDAV, Google Drive, and OneDrive rather than adding a Nextcloud-only API or UI path. - D-06: Every adapter contract test must prove normalized child identity, parent reference, name, file/folder kind, metadata completeness, pagination/completeness semantics, and zero byte-download/mutation calls. - D-07: A refresh may transition to `fresh` only after a valid listing has been normalized and reconciled. Empty listings are valid only when the provider positively returned an empty collection; parser/transport/root-resolution ambiguity must become a controlled warning/error, not “synced”. - D-08: Cached metadata remains visible during refresh and after provider failure. A failed or ambiguous refresh must not delete cached children or claim a successful empty root. ### Security and architecture - D-09: Preserve owner and connection scoping at every API/service boundary; the live connection belongs only to the designated regular test user and admin access remains blocked. - D-10: Provider credentials are decrypted only at the provider/task boundary and never enter broker payloads, API responses, browser storage, logs, snapshots, fixtures, or committed files. - D-11: All outbound WebDAV/Nextcloud requests continue through canonical SSRF validation; redirects and resolved addresses must not bypass the allowlist/private-address controls. - D-12: `CloudResourceAdapter`, `reconcile_cloud_listing`, the connection-ID browse API, and `StorageBrowser.vue` remain the shared contracts. No parallel provider-specific browser, reconciliation path, or response schema may be introduced. ### Claude's Discretion - Exact fixture organization and helper names. - Whether listing validation is represented as a result type, domain exception, or validated `CloudListing` constructor, provided controlled errors and existing shared contracts are preserved. - Whether the live test calls the adapter directly, the refresh task, or both, provided there is at least one end-to-end connection-ID browse assertion through DocuVault. ## Canonical References ### Phase 12 architecture and validation - `.planning/phases/12-cloud-resource-foundation/12-CONTEXT.md` — locked cloud resource architecture decisions. - `.planning/phases/12-cloud-resource-foundation/12-VALIDATION.md` — existing provider, browse, security, and no-byte verification map. - `.planning/phases/12-cloud-resource-foundation/12-SECURITY.md` — Phase 12 threat model and security evidence. - `AGENTS.md` — non-negotiable shared-module, testing, security, environment, documentation, and Git rules. ### Shared cloud implementation - `backend/storage/cloud_base.py` — normalized resource/listing/capability contract. - `backend/storage/nextcloud_backend.py` — Nextcloud listing implementation. - `backend/storage/webdav_backend.py` — generic WebDAV listing implementation. - `backend/storage/google_drive_backend.py` — Google Drive listing implementation. - `backend/storage/onedrive_backend.py` — OneDrive listing implementation. - `backend/services/cloud_items.py` — sole metadata reconciliation entry point. - `backend/tasks/cloud_tasks.py` — background refresh and freshness transitions. - `backend/api/cloud/browse.py` — owner-scoped connection-ID cached-first browse API. ### Existing verification - `backend/tests/test_cloud_backends.py` — provider normalization contract fixtures. - `backend/tests/test_cloud_items.py` — reconciliation, refresh, retention, and no-byte tests. - `backend/tests/test_cloud.py` — connection and browse API integration tests. - `backend/tests/test_cloud_security.py` — owner/admin/credential/SSRF/no-byte negative suite. ## Specific Ideas - The observed symptom is internally contradictory: the UI says synchronization succeeded, yet the connected Nextcloud root renders no folders or files. - The expected manifest intentionally includes both folders and files, names with spaces, multiple extensions, and mixed media/document types; it should catch root self-entry filtering, href decoding, and kind-normalization defects. - The eventual test output should report only sanitized status, entry counts, and expected/missing/unexpected basenames. ## Deferred Ideas - Upload, create-folder, rename, move, and delete behavior remain Phase 13. - Byte download/cache and document analysis remain Phase 14. - Production monitoring beyond truthful per-folder freshness remains Phase 16. --- *Phase: 12.1-fix-nextcloud-root-listing-and-sync-visibility* *Context gathered: 2026-06-22*