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 <kalvinnchau@users.noreply.github.com>
This commit is contained in:
Kalvin C
2026-08-07 08:42:01 -07:00
committed by GitHub
parent cd2125c34b
commit c293b3cd40
3 changed files with 17 additions and 13 deletions
Generated
+1
View File
@@ -862,6 +862,7 @@ dependencies = [
"async-trait",
"axum",
"base64 0.22.1",
"dirs",
"getrandom 0.4.3",
"hex",
"nix 0.31.3",
+1
View File
@@ -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"] }
+15 -13
View File
@@ -453,15 +453,12 @@ fn cache_path_for(cfg: &PkceOAuthConfig) -> Result<PathBuf, AgentError> {
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]