test_quota_increment_atomic and test_quota_exceeded_response were marked
xfail for PostgreSQL but pass on SQLite — markers removed, tests now PASSED.
Concurrent race and delete decrement keep xfail; they require real PG locking.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add permission field (default "view") with field_validator to ShareCreate
- Add SharePermissionPatch model with same validator
- Wire body.permission into grant_share() Share constructor
- Add PATCH /{share_id} endpoint with IDOR protection (T-06.2-02-01)
- Promote 3 xfail stubs to real tests (create_with_permission, patch_permission, patch_idor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- test_share_default_permission_view: asserts permission='view' in POST
response and owner's GET /api/shares list (SHARE-03)
- test_share_indicator_in_owner_list: asserts is_shared flips True in
owner's GET /api/documents after sharing (SHARE-05)
All 14 phase tests now pass (9 shares + 5 audit).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
WR-01: extend nested metadata_ forbidden-key check to all 4 keys
WR-02: assert no forbidden fields in CSV export body (D-15)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add @pytest_asyncio.fixture second_auth_user with handle prefix 'user2_'
- Creates User + Quota row following the same pattern as auth_user
- Returns {user, token, headers} dict shape for use in sharing tests
Phase 1 moved from partial_phases to compliant_phases after
gsd-validate-phase 1 closed all 3 gaps. Audit status remains
gaps_found (3 blockers unchanged: SHARE-02/DOC-01, STORE-06/SEC-09,
ADMIN-06). Nyquist overall: partial (phases 3, 4 still draft; phase 2
missing).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
str(uuid) returns dashed format (xxxx-xxxx-…) which mismatches SQLite's
CHAR(32) storage (undashed hex). Replace with .replace('-', '') so the
WHERE clause matches in both SQLite (tests) and PostgreSQL (production).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add test_concurrent_put_objects to test_storage.py (STORE-07: verifies no
per-instance lock blocks concurrent MinIO workers via asyncio.gather)
- Remove @pytest.mark.xfail from test_confirm_endpoint; test now passes on
SQLite after uuid format fix in api/documents.py
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CR-01: add `except HTTPException: raise` before broad except in
stream_document_content — prevents 503 (reconnect prompt) from being
swallowed and replaced with misleading 502
CR-02: move pre-flight credential checks BEFORE Redis setex in
oauth_initiate — no orphan state tokens written for unconfigured providers;
also adds onedrive_tenant_id to OneDrive pre-flight condition (WR-02)
CR-03: add CLOUD_CREDS_KEY to celery-worker environment in docker-compose.yml
— worker cannot decrypt cloud credentials without this key; every cloud
document task was silently failing at runtime
WR-03: assert Redis store empty after 400 pre-flight responses in both
new tests — confirms no token leak on misconfigured-provider requests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- oauth_initiate: pre-flight check returns 400 with env-var hint when
GOOGLE_CLIENT_ID/SECRET or ONEDRIVE_CLIENT_ID/SECRET are not configured,
preventing opaque MSAL/OAuth library 500 errors on misconfigured servers
- stream_document_content: broad except-clause catches non-CloudConnectionError
exceptions and returns 502 with user-friendly message (was raw 500)
- docker-compose.yml: add volumes: - ./backend:/app to celery-worker so code
changes are picked up by docker compose restart without a rebuild
- CloudStorageView: upload hint paragraph directs users to navigate into a
cloud folder; no DropZone added (no folder context at overview level)
- 3 new backend tests pass; 2 existing tests patched with credential monkeypatch;
full suite: 293 passed, 0 new failures, 1 pre-existing (test_extract_docx)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add CloudStorageView (/cloud) and CloudFolderView (/cloud/:provider/:folderId).
Tree items filter to directories only (is_dir) to hide files in the nav tree.
CloudProviderTreeItem root click navigates to /cloud/{provider}/root instead
of /settings. AppSidebar Cloud Storage link upgraded to router-link with
active-class highlighting. Router registers both cloud routes with requiresAuth.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cloud.py: list_connections now decrypts and surfaces server_url +
connection_username for nextcloud/webdav providers; folder route uses
{folder_id:path} to handle slashes; translates "root" sentinel to "".
nextcloud_backend.py: skip parent directory entry in PROPFIND Depth:1 results.
webdav_backend.py: add cloud_folder + original_filename params to
upload_object so files land in the user's chosen folder with their real name.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Plan refinements: Vitest tests added to 09/10 must-haves, explicit
mock_flow two-tuple pattern in 10, test_admin_api.py fixture usage in 11.
New artifacts: UAT checklist, UI-SPEC, deferred-items, debug investigation
for cloud-doc-operations-fail.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CR-01: add Field(min_length=1) to UserDeleteConfirm.admin_password
CR-02: add folder ownership check in PATCH /documents/{id} — prevents IDOR
when folder_id belongs to another user
CR-03: add min_length=1, max_length=255, and path-separator validator to
DocumentPatch.filename — prevents empty and path-traversal filenames
CR-04: fetchDocumentContent now throws on non-ok responses instead of
silently returning the error Response
CR-05: object URL revoke in DocumentView uses pagehide + load events with
120s fallback instead of unreliable 60s blind timer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cloud-aware routing added in 05-09 checks doc.storage_backend; MagicMock
attribute is truthy and != 'minio', so the test was entering the cloud branch
without any mock for get_storage_backend_for_document. Regression: test passed
before 05-09 when _run() had no cloud routing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- UserDeleteConfirm Pydantic model + Argon2 password verification in delete_user
- adminDeleteUser(id, adminPassword) exported from client.js
- AdminUsersTab inline delete confirmation panel with password field
- Three new tests pass: 204/403/422 scenarios
- Full 21-test admin suite green; frontend build clean