From 80757345abbd61600c677cd5f19b183904df59d3 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 29 Apr 2026 07:11:13 +0000 Subject: [PATCH 1/4] refactor(sync): use shared atomic_write in OfflineQueue::save OfflineQueue::save had its own copy of the temp-file + rename + cleanup-on-failure dance, even though the storage::atomic_write helper is pub(crate) and already used by AppConfig::save_to_file and google_tasks. Replace the inline implementation with a call to atomic_write so the crate has one canonical atomic write path. https://claude.ai/code/session_01Vk2NBZGFP3YVshDj1CwDjt --- crates/onyx-core/src/sync.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/crates/onyx-core/src/sync.rs b/crates/onyx-core/src/sync.rs index 6bb626d..7d50be7 100644 --- a/crates/onyx-core/src/sync.rs +++ b/crates/onyx-core/src/sync.rs @@ -341,13 +341,7 @@ impl OfflineQueue { return Ok(()); } let content = serde_json::to_string_pretty(self)?; - // Atomic write: write to temp then rename - let temp_path = workspace_path.join(".syncqueue.json.tmp"); - std::fs::write(&temp_path, &content)?; - if let Err(e) = std::fs::rename(&temp_path, &queue_path) { - let _ = std::fs::remove_file(&temp_path); - return Err(e.into()); - } + atomic_write(&queue_path, content.as_bytes())?; Ok(()) } From 6c0d7257dfafe65849f4e2d295696aecc6bb7144 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 29 Apr 2026 07:11:29 +0000 Subject: [PATCH 2/4] refactor(sync): use shared atomic_write in SyncState::save SyncState::save duplicated the temp+rename+cleanup-on-failure pattern that storage::atomic_write already provides. Replace the inline implementation with a call to atomic_write, completing the consolidation begun for AppConfig::save_to_file and OfflineQueue::save. https://claude.ai/code/session_01Vk2NBZGFP3YVshDj1CwDjt --- crates/onyx-core/src/sync.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/crates/onyx-core/src/sync.rs b/crates/onyx-core/src/sync.rs index 7d50be7..307337e 100644 --- a/crates/onyx-core/src/sync.rs +++ b/crates/onyx-core/src/sync.rs @@ -528,14 +528,7 @@ impl SyncState { pub fn save(&self, workspace_path: &Path) -> Result<()> { let state_path = workspace_path.join(".syncstate.json"); let content = serde_json::to_string_pretty(self)?; - // Atomic write: write to temp file then rename to prevent corruption on crash - let temp_path = workspace_path.join(".syncstate.json.tmp"); - std::fs::write(&temp_path, &content)?; - if let Err(e) = std::fs::rename(&temp_path, &state_path) { - // Clean up temp file on rename failure to prevent accumulation - let _ = std::fs::remove_file(&temp_path); - return Err(e.into()); - } + atomic_write(&state_path, content.as_bytes())?; Ok(()) } From 01bd4672c189f1d03137e1d72c5496e61252d69f Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 29 Apr 2026 07:12:29 +0000 Subject: [PATCH 3/4] refactor(tauri): drop redundant handle clone in start_watcher start_watcher takes handle: tauri::AppHandle by value, then immediately did let handle = handle.clone() before moving it into the file-watcher closure. The intermediate clone has no purpose: the parameter is unused outside the closure, so the move can take it directly. https://claude.ai/code/session_01Vk2NBZGFP3YVshDj1CwDjt --- apps/tauri/src-tauri/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/tauri/src-tauri/src/lib.rs b/apps/tauri/src-tauri/src/lib.rs index eae1c25..a15ecbb 100644 --- a/apps/tauri/src-tauri/src/lib.rs +++ b/apps/tauri/src-tauri/src/lib.rs @@ -1203,7 +1203,6 @@ fn start_watcher(handle: tauri::AppHandle, path: PathBuf) { if let Ok(mut w) = WATCHER.lock() { *w = None; } - let handle = handle.clone(); let debouncer = new_debouncer( std::time::Duration::from_millis(500), move |events: Result, notify::Error>| { From 0672290c4bf4a611b389c4349fdb69bc199daf46 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 29 Apr 2026 07:12:42 +0000 Subject: [PATCH 4/4] docs(audit): log 2026-04-29 findings https://claude.ai/code/session_01Vk2NBZGFP3YVshDj1CwDjt --- Audit.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Audit.md b/Audit.md index 8831902..eb5cab9 100644 --- a/Audit.md +++ b/Audit.md @@ -1,5 +1,13 @@ # Audit Log +## 2026-04-29 + +Found and fixed 3 issues: + +1. **Code quality: duplicated atomic-write in `OfflineQueue::save`** (sync.rs:332) — the function maintained its own copy of the temp-file + rename + cleanup-on-failure dance even though `storage::atomic_write` is `pub(crate)` and was already shared by `AppConfig::save_to_file` (fixed 04-25) and `google_tasks.rs`. Replaced the inline implementation with a call to `crate::storage::atomic_write`. +2. **Code quality: duplicated atomic-write in `SyncState::save`** (sync.rs:534) — same pattern as `OfflineQueue::save`. Replaced with a call to `atomic_write`, completing the consolidation of every per-call atomic write into a single shared helper. +3. **Code quality: redundant clone in `start_watcher`** (tauri/lib.rs:1206) — `start_watcher(handle: tauri::AppHandle, ...)` took `handle` by value, then immediately did `let handle = handle.clone();` before moving it into the file-watcher closure. The parameter was unused outside the closure, so the intermediate clone was pure waste. Removed it. + ## 2026-04-27 Found and fixed 3 issues: