diff --git a/backend/api/cloud/operations.py b/backend/api/cloud/operations.py index f4680ef..74a2eef 100644 --- a/backend/api/cloud/operations.py +++ b/backend/api/cloud/operations.py @@ -892,6 +892,24 @@ async def delete_cloud_item( if kind == MUT_KIND_DELETED: # Success: reconcile before returning (T-13-29) + # CR-04: Soft-delete the CloudItem row so that queries filtering on + # deleted_at.is_(None) (upload conflict check, preview, download) no longer + # "see" the deleted file. Without this, the row persists until the next full + # provider re-list, causing false conflict hits on immediate re-upload. + from datetime import datetime, timezone + from sqlalchemy import update as sa_update + + await session.execute( + sa_update(CloudItem) + .where( + CloudItem.connection_id == connection_id, + CloudItem.provider_item_id == item_id, + CloudItem.user_id == current_user.id, + CloudItem.deleted_at.is_(None), + ) + .values(deleted_at=datetime.now(timezone.utc)) + ) + # Invalidate parent folder so next browse reflects the deletion invalidate_parent = item_parent_ref if item_parent_ref is not None else "" await update_folder_state(