---
status: diagnosed
phase: 05-cloud-storage-backends
source:
  - 05-09-SUMMARY.md
  - 05-10-SUMMARY.md
  - 05-11-SUMMARY.md
mode: gap-reverification
started: 2026-05-30T10:00:00Z
updated: 2026-05-30T11:00:00Z
---

## Current Test
<!-- OVERWRITE each test - shows where we are -->

[testing complete]

## Tests

### 1. OAuth initiate — Google Drive redirect
expected: |
  In Settings → Cloud Storage tab, clicking "Connect" on the Google Drive row now
  uses an authenticated fetch (with Bearer token) to POST/GET /api/cloud/oauth/initiate/google_drive.
  The backend returns JSON {"url": "https://accounts.google.com/..."} (not a 302 redirect).
  The frontend then sets window.location.href to that URL, redirecting the browser to Google's
  OAuth consent screen. No 401 "Not authenticated" error occurs.
result: pass
note: "Google Drive redirect works. OneDrive redirect does NOT work — logged as additional gap below."

### 2. Disconnect confirmation fits within row
expected: |
  Clicking "Remove" (or "Disconnect") on an active cloud provider connection shows an inline
  confirmation message within the same provider row. The confirmation text ("Do you really
  want to remove…") is fully visible — no overflow off-screen, no horizontal scrollbar,
  no text cut off. The text wraps gracefully if it's long.
result: pass

### 3. Edit button on ERROR-state provider rows
expected: |
  A cloud provider connection in "ERROR" state (failed auth, bad credentials) shows both
  an "Edit" button and a "Remove" button in its row — matching the ACTIVE state layout.
  Clicking "Edit" opens the credential modal pre-populated with the stored server URL
  and username. The password field is empty (not returned from backend for security).
result: pass

### 4. Nextcloud custom endpoint preserved on re-edit
expected: |
  When editing a Nextcloud or WebDAV connection that was originally saved with a custom
  WebDAV path (not the auto-constructed /remote.php/dav/files/{username}/ default), the
  edit modal opens with the Advanced section already expanded and the custom endpoint field
  pre-populated with the exact stored URL. No data is silently discarded.
result: pass

### 5. Cloud document — open, re-analyze, edit
expected: |
  For a document stored on a cloud backend (e.g. Nextcloud or WebDAV):
  (a) Open/Preview: clicking the document opens a preview or download without a 401 error.
      Content is fetched via authenticated proxy, not a bare unauthenticated URL.
  (b) Re-analyze: triggering re-analysis on the document successfully extracts text
      from the cloud-stored file (not from MinIO where the file doesn't exist).
  (c) Edit/rename: if a rename or folder-move UI exists, it completes via PATCH endpoint
      without a 404 "endpoint not found" error.
result: issue
reported: "Nothing from a to c works and the drag and drop box for upload disappeared."
severity: blocker

### 6. Admin hard-delete user with password confirmation
expected: |
  In Admin → Users tab, each non-admin user row has a "Delete" button alongside the
  existing "Deactivate" button.
  Clicking "Delete" opens an inline confirmation panel (within the row, not a modal)
  with an admin password field. Submitting with the wrong admin password is rejected
  with an error message. Submitting with the correct admin password permanently removes
  the user and closes the panel. The user no longer appears in the list.
result: pass

## Summary

total: 6
passed: 5
issues: 1
pending: 0
skipped: 0
blocked: 0

## Gaps

- truth: "Clicking Connect on OneDrive should redirect the browser to Microsoft's OAuth consent screen via authenticated fetch"
  status: failed
  reason: "User reported: Microsoft/OneDrive redirect does not work (Google Drive works)"
  severity: major
  test: 1-onedrive
  root_cause: "Frontend and backend code are symmetric for both providers — the authenticated-fetch fix WAS applied to both. Most likely cause: ONEDRIVE_CLIENT_ID / ONEDRIVE_CLIENT_SECRET env vars are not configured. With empty credentials, msal.ConfidentialClientApplication raises an error or returns a malformed URL → backend returns 500 → frontend shows error toast. Google Drive credentials ARE configured, OneDrive are not."
  artifacts:
    - path: "backend/config.py"
      issue: "onedrive_client_id / onedrive_client_secret default to empty string; no validation that they are set before attempting OAuth flow"
    - path: "backend/api/cloud.py"
      issue: "oauth_initiate (lines 370-384): no pre-check for empty credentials before calling msal — a missing-config error looks identical to a code bug to the user"
  missing:
    - "Add a pre-flight config check in oauth_initiate: if provider == 'onedrive' and not settings.onedrive_client_id, raise HTTPException(400, detail='OneDrive credentials not configured') before touching MSAL"
    - "Configure ONEDRIVE_CLIENT_ID, ONEDRIVE_CLIENT_SECRET, ONEDRIVE_TENANT_ID in .env if OneDrive integration is needed"

- truth: "Opening, re-analyzing, and editing a document stored on a cloud backend should work correctly via the backend proxy"
  status: failed
  reason: "User reported: Nothing from a to c works."
  severity: blocker
  test: 5
  root_cause: "Code fixes from 05-09 ARE in place in all files (confirmed by code review): fetchDocumentContent() with Bearer token in client.js, Blob URL in DocumentPreviewModal.vue + DocumentView.vue, PATCH endpoint in documents.py, cloud-aware re-analyze in document_tasks.py. Most likely runtime cause: (1) Celery worker was NOT restarted after 05-09 changes — celery has no --reload flag in docker-compose.yml so old MinIO-hardcoded task code runs until worker is restarted. (2) Preview/open: uvicorn has --reload so content endpoint is current, but the document being tested may have been uploaded before 05-09 with a bad object_key stored in DB, OR the CloudConnection status is not ACTIVE."
  artifacts:
    - path: "docker-compose.yml"
      issue: "celery-worker has no --reload; code changes to document_tasks.py require manual worker restart (docker compose restart celery-worker)"
    - path: "backend/tasks/document_tasks.py"
      issue: "Cloud-aware routing is present and correct — but only if the worker has reloaded the new code"
    - path: "backend/api/documents.py"
      issue: "stream_document_content: if CloudConnection status != ACTIVE, returns 503; if cloud backend get_object raises non-CloudConnectionError exception, returns 500 without a user-friendly message"
  missing:
    - "Restart celery-worker container: docker compose restart celery-worker"
    - "Verify the test document's storage_backend field is set correctly (not 'minio') and object_key matches what the cloud backend expects"
    - "Add user-friendly error in stream_document_content: catch Exception broadly and surface a 502 'Cloud backend unreachable' rather than 500"

- truth: "Drag-and-drop upload box should be visible wherever the user expects to upload files"
  status: failed
  reason: "User reported: the drag and drop box for upload disappeared."
  severity: blocker
  test: 5-regression
  root_cause: "DropZone IS present unconditionally in FileManagerView (line 37) and CloudFolderView (line 30). It is ABSENT from CloudStorageView (/cloud — the new overview page added in commit 5250895). The sidebar 'Cloud Storage' link was changed from /settings to /cloud in the same commit. User navigating via sidebar 'Cloud Storage' now lands on CloudStorageView which has no upload zone, explaining why the DropZone 'disappeared'."
  artifacts:
    - path: "frontend/src/views/CloudStorageView.vue"
      issue: "No DropZone component — shows cloud connections list only"
    - path: "frontend/src/components/layout/AppSidebar.vue"
      issue: "Cloud Storage sidebar link changed to /cloud (commit 5250895) which routes to DropZone-less CloudStorageView"
  missing:
    - "Add DropZone + UploadProgress to CloudStorageView so users can upload without first navigating into a specific cloud folder"
    - "OR add a note/CTA in CloudStorageView directing users to navigate into a folder to upload"
