Implemented write_audit_log calls for open_cloud_file, create_cloud_folder,
and rename_cloud_item in api/cloud/operations.py. Removed xfail markers from
test_cloud_audit.py. All 11 audit tests pass; 360 cloud tests pass total.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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
- 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
- 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
- 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)