Commit Graph
9 Commits
Author SHA1 Message Date
curo1305 af0de30e93 fix(13): CR-04 soft-delete CloudItem row on successful cloud delete to prevent orphaned metadata 2026-06-23 00:29:11 +02:00
curo1305 405c7a6610 fix(13): CR-03 wrap post-upload DB block in try/except to handle provider-success/DB-fail divergence 2026-06-23 00:28:34 +02:00
curo1305 d4b2697109 fix(13): CR-01 use RFC 6266 filename*=UTF-8'' encoding in Content-Disposition to prevent header injection 2026-06-23 00:26:59 +02:00
curo1305 ebc74f4abe fix(13): CR-06 re-raise HTTPException in preview_cloud_file instead of masking as unsupported_preview 2026-06-23 00:26:23 +02:00
curo1305 508d27643b feat(13-09): move stale-guard, descendant safety, reconciliation, delete disclosure, and metadata-only auditing
Move endpoint (D-07, D-08, D-09, T-13-27, T-13-28, T-13-29):
- Descendant destination detection via cloud_items ancestor-chain walk (D-09)
- Stale provider result marks source folder non-fresh, returns typed stale body (D-07)
- Success: upsert_cloud_item with new parent_ref before returning
- Success: update_folder_state for both source and destination folders
- Success: write_audit_log 'cloud.item_moved' with metadata-only payload

Delete endpoint (D-10, D-11, T-13-29):
- Pre-fetch item kind for D-10 folder-vs-file disclosure
- Success: update_folder_state for parent folder before returning
- Success: write_audit_log 'cloud.item_deleted' with delete_kind metadata
- Response carries is_folder/item_kind for frontend disclosure
- Failed deletes never emit audit rows

Promote xfail markers in test_cloud_audit.py for move and delete audit rows
2026-06-22 20:02:09 +02:00
curo1305 aaa63c19e4 feat(13-08): implement create-folder and rename collision retry, stale guard, and reconciliation
- create_cloud_folder: bounded collision retry (up to 5 attempts) with keep_both_name counter suffix (D-05, D-06)
- create_cloud_folder: stale precondition marks parent folder non-fresh and returns typed stale result (D-07)
- rename_cloud_item: stale precondition marks parent folder non-fresh via folder state update (D-07)
- create_cloud_folder: reconcile-before-return upserts new folder in cloud_items and invalidates parent (T-13-26)
- rename_cloud_item: reconcile-before-return upserts renamed item and invalidates parent folder (T-13-26)
- Import upsert_cloud_item, update_folder_state, keep_both_name, CloudResource from service modules
2026-06-22 19:51:57 +02:00
curo1305 d959e0cf42 feat(13-06): emit metadata-only audit rows on authoritative upload success
- Write cloud.file_uploaded audit row in same transaction as reconciliation
- Audit payload is metadata-only: filename, size_bytes, connection_id, provider_item_id, parent_ref
- No provider URLs, tokens, bytes, or document text in audit metadata (T-13-02)
- Non-success paths (conflict, offline, reauth_required) bypass audit write (T-13-21)
- Import get_client_ip from deps.utils and write_audit_log from services.audit
2026-06-22 19:29:46 +02:00
curo1305 7ecbec7df9 feat(13-06): route upload success through centralized reconciliation before returning
- Upsert uploaded item into cloud_items for stable row identity and navigation
- Invalidate parent folder state (warning/upload_mutated) so next browse re-fetches
- Reconcile-before-return: session committed before response returned
- Failed/conflict uploads bypass reconciliation path (T-13-19)
2026-06-22 19:26:41 +02:00
curo1305 94a0617b9b feat(13-04): add authorized cloud content and mutation routes with typed bodies
- backend/api/cloud/operations.py: owner-scoped open, preview, download, create-folder,
  rename, move, delete, upload routes with typed kind/reason response bodies (D-02, D-03,
  D-05, D-07, D-08, D-09, D-10, D-11, D-18, T-13-01, T-13-14)
- backend/api/cloud/__init__.py: register operations_router on /api/cloud
- backend/api/cloud/connections.py: Google Drive OAuth scope broadened to 'drive' (D-17)
- backend/api/cloud/schemas.py: ConnectionHealthOut, ReconnectOut, ContentResultOut,
  MutationResultOut, CreateFolderRequest, RenameItemRequest, MoveItemRequest typed schemas
- frontend/src/api/cloud.js: centralized helpers for all Phase 13 routes
- backend/tests/test_cloud_mutations.py: mock adapter + settings key fixture; 21 tests pass
- backend/tests/test_cloud_audit.py: mark 6 RED audit tests as xfail (audit writes are
  T-13-05 scope for a later plan); update credential fixture to use settings key
2026-06-22 19:09:38 +02:00