From c293b3cd4027775d7580cafd5108a0b22ca7381b Mon Sep 17 00:00:00 2001 From: Kalvin C Date: Fri, 7 Aug 2026 08:42:01 -0700 Subject: [PATCH] fix(agent): resolve oauth cache home cross-platform (#5151) ## Summary - resolve the OAuth cache home directory with the repository's platform-aware `dirs` convention - preserve the existing `.config/buzz-agent/oauth` cache layout on macOS and Linux - make the cache-path regression assertion portable across path separators ## Problem `buzz-agent` read only `$HOME` when constructing the OAuth token cache path. Packaged Windows processes do not guarantee that Unix variable, so OAuth source construction failed with `oauth cache: $HOME not set` even though Windows had a valid user profile. ## Validation Independent reviewers validated exact commit `836d820483b141b7291170cb33535ac7cb49b2eb` on Windows/MSVC with `HOME` unset and `USERPROFILE` present: - `cargo +1.94.1 clippy -p buzz-agent --all-targets --locked -- -D warnings` - `cargo +1.94.1 fmt --all -- --check` - `git diff --check f53bbd1..836d820` - `auth::` tests: 11/11 passed with `HOME` unset - full package lib target: 396 passed / 2 failed; identical-base controls classified both as pre-existing Windows failures The changed regression fails on the base with `$HOME not set` and passes on this branch. `dirs 6.0.0` was already locked by other workspace crates; the lockfile change adds only the `buzz-agent` dependency edge. Signed-off-by: Kalvin C --- Cargo.lock | 1 + crates/buzz-agent/Cargo.toml | 1 + crates/buzz-agent/src/auth.rs | 28 +++++++++++++++------------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 73ecb249d..83d2b9e3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -862,6 +862,7 @@ dependencies = [ "async-trait", "axum", "base64 0.22.1", + "dirs", "getrandom 0.4.3", "hex", "nix 0.31.3", diff --git a/crates/buzz-agent/Cargo.toml b/crates/buzz-agent/Cargo.toml index 7889ad34a..f1a108904 100644 --- a/crates/buzz-agent/Cargo.toml +++ b/crates/buzz-agent/Cargo.toml @@ -43,6 +43,7 @@ hex = { workspace = true } sha2 = { workspace = true } urlencoding = "2" webbrowser = "1" +dirs = "6" [target.'cfg(unix)'.dependencies] nix = { version = "0.31", default-features = false, features = ["signal", "process"] } diff --git a/crates/buzz-agent/src/auth.rs b/crates/buzz-agent/src/auth.rs index 34974fbf0..3f43925de 100644 --- a/crates/buzz-agent/src/auth.rs +++ b/crates/buzz-agent/src/auth.rs @@ -453,15 +453,12 @@ fn cache_path_for(cfg: &PkceOAuthConfig) -> Result { let dir = match &cfg.cache_dir_override { Some(p) => p.join(&cfg.cache_namespace), - None => { - let home = std::env::var("HOME") - .map_err(|_| AgentError::Llm("oauth cache: $HOME not set".into()))?; - PathBuf::from(home) - .join(".config") - .join("buzz-agent") - .join("oauth") - .join(&cfg.cache_namespace) - } + None => dirs::home_dir() + .ok_or_else(|| AgentError::Llm("oauth cache: home directory not found".into()))? + .join(".config") + .join("buzz-agent") + .join("oauth") + .join(&cfg.cache_namespace), }; Ok(dir.join(format!("{hash}.json"))) } @@ -683,8 +680,7 @@ mod tests { } #[test] - fn cache_path_includes_namespace_and_hash() { - // HOME is required; cargo test runs set it. + fn cache_path_uses_platform_home_directory() { let cfg = PkceOAuthConfig { discovery_url: "https://example.com/.well-known".into(), client_id: "abc".into(), @@ -693,8 +689,14 @@ mod tests { cache_dir_override: None, }; let p = cache_path_for(&cfg).unwrap(); - assert!(p.to_string_lossy().contains("/buzz-agent/oauth/demo/")); - assert!(p.extension().and_then(|s| s.to_str()) == Some("json")); + let expected_dir = dirs::home_dir() + .unwrap() + .join(".config") + .join("buzz-agent") + .join("oauth") + .join("demo"); + assert_eq!(p.parent(), Some(expected_dir.as_path())); + assert_eq!(p.extension().and_then(|s| s.to_str()), Some("json")); } #[test]