---
phase: "12.1"
plan: "04"
type: execute
wave: 4
depends_on:
- "12.1-01"
- "12.1-02"
- "12.1-03"
files_modified:
- backend/tests/test_nextcloud_live.py
- backend/tests/fixtures/cloud/nextcloud_expected_root.json
- backend/pytest.ini
- frontend/src/views/__tests__/CloudFolderRenderedFlow.test.js
- .planning/phases/12.1-fix-nextcloud-root-listing-and-sync-visibility/12.1-VALIDATION.md
- backend/main.py
- frontend/package.json
- frontend/package-lock.json
- AGENTS.md
- README.md
- RUNBOOK.md
- SECURITY.md
autonomous: false
requirements:
- CONN-04
- CLOUD-01
- CACHE-01
- SYNC-01
must_haves:
truths:
- "An opt-in read-only live test browses the configured Nextcloud root through the owner-scoped connection-ID DocuVault API as testuser@docuvault.example"
- "Live execution never prints secrets, the full URL, or unexpected provider names and never downloads/mutates provider data"
- "Live validation has a nonblocking sanitized diagnostic mode and a separate exact acceptance mode enabled only by an owner-confirmed tracked manifest"
- "Mocked and live evidence together prove folders/files, kind, provider identity, freshness, zero-byte, and owner isolation"
- "Full tests, security/dependency/secret gates, docs, version, atomic commit, and push complete before Phase 12.1 closes"
artifacts:
- path: "backend/tests/test_nextcloud_live.py"
provides: "Opt-in sanitized live Nextcloud adapter and connection-ID API smoke"
contains: "test_nextcloud_root_diagnostic"
- path: "backend/tests/fixtures/cloud/nextcloud_expected_root.json"
provides: "Owner-confirmed, non-secret exact root name/kind acceptance manifest"
contains: "owner_confirmed"
- path: ".planning/phases/12.1-fix-nextcloud-root-listing-and-sync-visibility/12.1-VALIDATION.md"
provides: "Nyquist matrix and live/mock/security evidence"
contains: "7 of 10"
- path: "SECURITY.md"
provides: "Phase 12.1 threat and gate evidence without secrets/provider content"
contains: "Phase 12.1"
key_links:
- from: "NEXTCLOUD_URL/NEXTCLOUD_USER/NEXTCLOUD_APP_PASSWORD"
to: "backend/tests/test_nextcloud_live.py"
via: "ignored environment read in process memory only"
pattern: 'os\.environ|getenv'
- from: "testuser@docuvault.example"
to: "GET /api/cloud/connections/{connection_id}/items"
via: "isolated test DB user, encrypted connection, authenticated API request"
pattern: 'testuser@docuvault\.example'
- from: "supplied expected manifest"
to: "exact live signoff"
via: "explicit discrepancy reconciliation gate"
pattern: 'Documents|Reasons to use Nextcloud\.pdf'
---
Prove the repaired flow against the designated test account without risking credentials or provider data, reconcile the known manifest discrepancy before exact-name acceptance, then close Phase 12.1 with full validation, security, documentation, versioning, commit, and push protocol.
The live test is intentionally opt-in and read-only. Missing credentials skip with a prerequisite message; a manifest discrepancy blocks exact-name signoff rather than mutating the provider or silently changing expectations.
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
@$HOME/.claude/get-shit-done/templates/summary.md
@.planning/phases/12.1-fix-nextcloud-root-listing-and-sync-visibility/12.1-CONTEXT.md
@.planning/phases/12.1-fix-nextcloud-root-listing-and-sync-visibility/12.1-RESEARCH.md
@.planning/phases/12.1-fix-nextcloud-root-listing-and-sync-visibility/12.1-PATTERNS.md
@.planning/phases/12-cloud-resource-foundation/12-VALIDATION.md
@.planning/phases/12-cloud-resource-foundation/12-SECURITY.md
@.planning/phases/12-cloud-resource-foundation/12-VERIFICATION.md
@AGENTS.md
Task 1: Build and run the nonblocking sanitized live diagnostic
backend/tests/test_nextcloud_live.py, backend/pytest.ini, .planning/phases/12.1-fix-nextcloud-root-listing-and-sync-visibility/12.1-VALIDATION.md
- .planning/phases/12.1-fix-nextcloud-root-listing-and-sync-visibility/12.1-CONTEXT.md — credentials, user, expected manifest, and read-only rules
- .planning/phases/12.1-fix-nextcloud-root-listing-and-sync-visibility/12.1-RESEARCH.md — sanitized 207/10/7-of-10 probe evidence
- backend/tests/conftest.py — isolated DB/auth fixture conventions
- backend/tests/test_cloud.py — connection creation and connection-ID browse patterns
- backend/tests/test_cloud_security.py — owner/admin/credential/no-byte assertions
- backend/storage/cloud_utils.py — credential encryption and URL validation
Add a `live_nextcloud` pytest marker excluded from ordinary test runs unless explicitly selected. Read only `NEXTCLOUD_URL`, `NEXTCLOUD_USER`, and `NEXTCLOUD_APP_PASSWORD` from the ignored environment at runtime; if any are absent, skip with a generic prerequisite message naming variable keys only. Never load or print `.env`, and never place values in parametrization IDs, assertion diffs, exceptions, snapshots, logs, artifacts, or command lines.
Create `test_nextcloud_adapter_read_only_root_metadata`, `test_nextcloud_root_diagnostic`, and an authenticated `test_nextcloud_connection_id_browse_as_designated_user`. In an isolated test database, provision/resolve the regular DocuVault user exactly `testuser@docuvault.example`, encrypt the live connection credentials through production helpers, then browse root through `GET /api/cloud/connections/{connection_id}/items`; also assert foreign-user/admin denial. The test may issue metadata-only DAV requests required for listing. Install a request guard that rejects byte GET/media and PUT/POST/PATCH/MKCOL/MOVE/COPY/DELETE methods before network dispatch; assert quota and MinIO/object storage are unchanged.
In diagnostic mode compare in memory against the ten owner-supplied candidate names, but do not assert exact equality and do not claim acceptance. Emit only total count, expected-match count, missing supplied names, unexpected count, completion state, and kind counts; never emit unexpected names. The diagnostic must exit successfully when transport/security/read-only invariants pass even if the candidate manifest is 7/10, while recording `manifest_status: unconfirmed`. Catch/redact transport errors into stable codes so neither full URL nor credentials enter pytest output. Assert captured logs/output contain none of the secret values or full URL.
Record the contract, commands, skip behavior, sanitized result fields, and threat references in 12.1-VALIDATION.md. Do not record unexpected live names.
- ordinary pytest does not contact Nextcloud and missing variables produce an explicit safe skip
- selected live tests authenticate only as the designated regular app user and use connection-ID browse
- network guard permits metadata listing but rejects download and every mutation method
- output contains no credential, full URL, raw response body, or unexpected provider name
- manifest mismatch is diagnostic-only and nonblocking before owner confirmation
cd backend && pytest -q tests/test_nextcloud_live.py -m live_nextcloud
The opt-in diagnostic safely proves connectivity/listing invariants and reports sanitized drift without claiming exact acceptance.
Task 2: Reconcile the known 7-of-10 fixture discrepancy before exact signoff
backend/tests/fixtures/cloud/nextcloud_expected_root.json, backend/tests/test_nextcloud_live.py, .planning/phases/12.1-fix-nextcloud-root-listing-and-sync-visibility/12.1-VALIDATION.md
- .planning/phases/12.1-fix-nextcloud-root-listing-and-sync-visibility/12.1-RESEARCH.md — three supplied names not exactly matched in sanitized probe
- backend/tests/test_nextcloud_live.py — supplied expected manifest and safe mismatch report
Run the live smoke and inspect only its sanitized count/missing-expected output. The prior probe found 10 children but only 7 exact supplied-name matches; therefore do not declare the ten-name assertion accepted merely because item count is 10. If the same mismatch remains, stop and ask the project owner to compare the three supplied expected names (`Manual Nextcloud.png`, `Nextcloud Intro.mp4`, `Template credits.md`) with the Nextcloud UI and state which source is authoritative. Do not reveal the three unexpected provider names and do not rename/delete/upload anything.
After explicit owner confirmation, store the authoritative names and kinds in tracked `backend/tests/fixtures/cloud/nextcloud_expected_root.json` with no URL, username, credential, provider ID, timestamp, or unexpected-name discovery data; include `owner_confirmed: true` and a short non-secret provenance note. Only then add/enable `test_nextcloud_expected_root_manifest`, loading that fixture. If the original supplied expectation is authoritative, leave its names unchanged and treat the provider account as requiring external fixture correction. Re-run until exact set equality and exact kind equality pass. Record the owner-confirmed disposition and only sanitized counts in 12.1-VALIDATION.md.
- exact-name signoff is blocked while only 7/10 supplied names match
- no unexpected provider names are printed or persisted during reconciliation
- any expected-manifest change has explicit owner confirmation, not inference from live output
- final live result is exact set and kind equality, not count-only acceptance
- provider content remains unchanged
cd backend && pytest -q tests/test_nextcloud_live.py -m live_nextcloud -k expected_root_manifest
The owner has reconciled the fixture discrepancy and the live account passes exact root-name and kind acceptance without provider mutation.
Task 3: Run full regression, security, environment, and rendered-flow gates
frontend/src/views/__tests__/CloudFolderRenderedFlow.test.js, .planning/phases/12.1-fix-nextcloud-root-listing-and-sync-visibility/12.1-VALIDATION.md, SECURITY.md, RUNBOOK.md
- AGENTS.md — mandatory tests, security checks, environment contract, and deployment exclusions
- .planning/phases/12-cloud-resource-foundation/12-VALIDATION.md — baseline Nyquist matrix and commands
- .planning/phases/12-cloud-resource-foundation/12-SECURITY.md — inherited threat evidence
- SECURITY.md — project security evidence format
- RUNBOOK.md — operational cloud/migration guidance
Add an executable Vue Test Utils rendered-flow test `CloudFolderRenderedFlow.test.js` that mounts the real CloudFolderView with StorageBrowser/BreadcrumbBar (stubbing only network/router boundaries), renders mixed root folders/files, clicks a folder whose opaque reference contains reserved characters, navigates back via lineage breadcrumbs, and renders refreshing/warning/fresh server states while cached rows remain visible. Run it in the normal Vitest command. Use the live account only for the separate sanitized API smoke; do not place provider names or credentials in rendered snapshots.
Run `bandit -r backend/`, `pip audit`, `npm audit --audit-level=high`, security-invariant tests, and `gitleaks detect --source . --no-banner --redact` as the concrete repository/history secret scanner (install the pinned approved binary before execution if absent; absence blocks the gate). Also run `git ls-files '.env' '.env.*'` and require only approved example files. Verify no new high/critical findings, no tracked `.env`, no secret values in current history/diff, no raw provider URL/error leakage, no admin/foreign-user access, and no provider byte/mutation/quota activity. Resolve introduced findings without skips, suppressions, or broad exception swallowing. Update validation/security/runbook evidence with commands and sanitized outcomes only.
- four-provider focused contract, live exact acceptance, full suites, and build pass
- Compose config resolves every required variable non-empty without printing values
- Bandit and pip/npm audits have zero introduced high/critical findings
- secret scan and git diff contain no credentials/full live URL
- rendered root/nested/freshness behavior matches API truth and uses StorageBrowser
docker compose config --quiet && gitleaks detect --source . --no-banner --redact && test -z "$(git ls-files '.env' '.env.*' | grep -v '^\.env\.example$')" && cd backend && pytest -q tests/test_cloud_provider_contract.py tests/test_cloud_backends.py tests/test_webdav_backend.py tests/test_cloud_items.py tests/test_cloud.py tests/test_cloud_security.py && pytest -q tests/test_nextcloud_live.py -m live_nextcloud && pytest -v && bandit -r . && pip audit && cd ../frontend && npm test -- --run src/views/__tests__/CloudFolderRenderedFlow.test.js && npm test && npm run build && npm audit --audit-level=high
Automated, live, rendered, security, dependency, secret, and environment gates pass with sanitized evidence.
Task 4: Close documentation, version, commit, and push protocol
backend/main.py, frontend/package.json, frontend/package-lock.json, AGENTS.md, README.md, RUNBOOK.md, SECURITY.md, .planning/phases/12.1-fix-nextcloud-root-listing-and-sync-visibility/12.1-VALIDATION.md
- backend/main.py — backend version source of truth
- frontend/package.json — frontend version source of truth
- frontend/package-lock.json — lockfile root/package version entries
- AGENTS.md — current state, shared module map, documentation/version/Git protocols
- README.md — cloud browse feature and environment documentation
- .planning/ROADMAP.md — Phase 12.1 boundary and Phase 13/14 exclusions
Update AGENTS.md current state to Phase 12.1 complete and add any new canonical listing/freshness helper to the backend shared-module map with a no-duplication rule. Update README with truthful provider-neutral browse behavior and opt-in live test variable names only; never add values. Update RUNBOOK with safe live-smoke invocation, redaction expectations, warning semantics, and fixture-reconciliation procedure. Update SECURITY.md and 12.1-VALIDATION.md with final evidence and inherited controls.
Increment the current backend/frontend patch version exactly once for Plan 04 in backend/main.py, frontend/package.json, and both relevant package-lock entries; earlier plans have already performed their own required per-plan bumps. Use source values at execution time and keep all versions identical. Do not claim Phase 13 mutations or Phase 14 byte cache behavior.
Run a dedicated security agent on Plan 04's diff and resolve or escalate every finding. Re-run focused/full tests, rendered test, gitleaks, build, security gates, and `docker compose config --quiet` after docs/version changes. Review `git diff --check`, `git status`, and staged diff for secrets/unrelated user changes. Stage only Plan 04 live-test/fixture/rendered-test/planning/docs/version files explicitly, commit atomically as `test(12.1): verify live cloud browse integration`, and push immediately. Never amend or accumulate Plans 01-03, stage `.env`, or overwrite unrelated work.
- AGENTS/README/RUNBOOK/SECURITY describe shipped behavior and explicit Phase 13/14 exclusions
- documentation names environment keys only and contains no credential, full URL, or unexpected live provider name
- backend/package/lock versions match after one patch bump
- final test/build/security/config gates remain green
- Plan 04 has its own atomic commit and push without unrelated files or `.env`; Plans 01-03 remain separate commits
docker compose config --quiet && git diff --check && cd backend && pytest -v && cd ../frontend && npm test && npm run build && npm audit --audit-level=high
Phase 12.1 is documented, versioned, fully verified, atomically committed, and pushed with no secret or scope leakage.
| Threat ID | Threat | Mitigation and evidence |
|-----------|--------|-------------------------|
| T-12.1-16 | Live credentials/full URL leak through pytest/logs | Runtime env only, generic failures, capture assertions, no values in IDs/commands/artifacts |
| T-12.1-17 | Live smoke mutates/downloads user data | Network method guard; metadata-only requests; no-byte/no-quota assertions |
| T-12.1-18 | Live connection crosses user/admin boundary | Designated regular user plus foreign/admin negatives through connection-ID API |
| T-12.1-19 | Count-only test accepts wrong root | Exact set and kind equality; blocking 7/10 reconciliation checkpoint |
| T-12.1-20 | Unexpected provider names become persisted sensitive metadata | Unexpected count only; no names in output/docs/fixtures |
| T-12.1-SC | Supply-chain or committed-secret regression | Bandit, pip/npm audits, secret scan, staged diff review before commit/push |
1. Ordinary tests skip live access safely; selected live tests use only the three named environment keys.
2. Live adapter and connection-ID API smoke pass as the designated user with exact names/kinds after explicit discrepancy reconciliation.
3. Network guard and DB assertions prove no provider mutation, download, MinIO, or quota change.
4. Shared four-provider, backend/frontend full, build, security, audit, secret, and Compose gates pass.
5. Docs/version are synchronized; atomic commit and push succeed without `.env` or unrelated changes.
- The connected Nextcloud root is visible through DocuVault and matches an owner-confirmed exact manifest.
- The test design validates all providers through one contract while preserving provider-specific fixtures and pagination.
- Freshness is truthful from adapter completion through API, store, and rendered browser.
- Credentials/provider data remain private and provider content remains untouched.
- Phase 12.1 closes without importing Phase 13 mutations or Phase 14 byte caching.