mirror of
https://github.com/block/buzz.git
synced 2026-10-27 12:40:30 +00:00
fix(desktop): show OpenAI-compatible endpoint settings in the baked-env UI (#8117)
## Summary `is_safe_to_reveal` (`desktop/src-tauri/src/managed_agents/env_vars.rs`) is the single default-deny allowlist for showing baked env values. It lists `DATABRICKS_HOST`/`DATABRICKS_MODEL`/`DATABRICKS_MODEL_FILTER` but not their OpenAI-compatible counterparts, so a build that bakes `OPENAI_COMPAT_BASE_URL`, `OPENAI_COMPAT_MODEL`, `OPENAI_COMPAT_API` shows them as `••••••`. Adds those three non-secret settings to the allowlist: an endpoint URL, a model id, and an `auto|chat|responses` enum. **No secret is revealed: `OPENAI_COMPAT_API_KEY` is deliberately not added and remains masked.** ### Related issue None found. ### Testing - New test `baked_env_openai_compat_endpoint_is_unmasked_but_key_stays_masked` covers the three revealed settings and asserts the API key stays masked; `baked_env_allowlist_is_case_insensitive` extended. - `cargo test --lib baked_env` in `desktop/src-tauri`: 11 passed. `cargo fmt` clean. - Not exercised in the running desktop UI. Signed-off-by: Tom Bedor <tbedor@squareup.com> Co-authored-by: Tom Bedor <tbedor@squareup.com>
This commit is contained in:
@@ -714,6 +714,31 @@ fn baked_env_thinking_summary_is_unmasked() {
|
||||
assert!(!summary.masked);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn baked_env_openai_compat_endpoint_is_unmasked_but_key_stays_masked() {
|
||||
// The OpenAI-compatible endpoint, model id, and API flavor are
|
||||
// non-secret defaults; the API key next to them is a credential.
|
||||
let entries = baked_env_from_map(&[
|
||||
("OPENAI_COMPAT_BASE_URL", "https://llm.example/v1"),
|
||||
("OPENAI_COMPAT_MODEL", "balanced"),
|
||||
("OPENAI_COMPAT_API", "chat"),
|
||||
("OPENAI_COMPAT_API_KEY", "placeholder"),
|
||||
]);
|
||||
assert_eq!(entries.len(), 4);
|
||||
let find = |k: &str| entries.iter().find(|e| e.key == k).unwrap();
|
||||
assert_eq!(
|
||||
find("OPENAI_COMPAT_BASE_URL").value,
|
||||
"https://llm.example/v1"
|
||||
);
|
||||
assert!(!find("OPENAI_COMPAT_BASE_URL").masked);
|
||||
assert_eq!(find("OPENAI_COMPAT_MODEL").value, "balanced");
|
||||
assert!(!find("OPENAI_COMPAT_MODEL").masked);
|
||||
assert_eq!(find("OPENAI_COMPAT_API").value, "chat");
|
||||
assert!(!find("OPENAI_COMPAT_API").masked);
|
||||
assert!(find("OPENAI_COMPAT_API_KEY").masked);
|
||||
assert_eq!(find("OPENAI_COMPAT_API_KEY").value, "••••••");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn baked_env_allowlist_is_case_insensitive() {
|
||||
// Known-safe keys — case-insensitive match must allow them.
|
||||
@@ -729,6 +754,11 @@ fn baked_env_allowlist_is_case_insensitive() {
|
||||
assert!(super::is_safe_to_reveal("DATABRICKS_HOST"));
|
||||
assert!(super::is_safe_to_reveal("databricks_model"));
|
||||
assert!(super::is_safe_to_reveal("DATABRICKS_MODEL"));
|
||||
assert!(super::is_safe_to_reveal("openai_compat_base_url"));
|
||||
assert!(super::is_safe_to_reveal("OPENAI_COMPAT_BASE_URL"));
|
||||
assert!(super::is_safe_to_reveal("OPENAI_COMPAT_MODEL"));
|
||||
assert!(super::is_safe_to_reveal("OPENAI_COMPAT_API"));
|
||||
assert!(!super::is_safe_to_reveal("OPENAI_COMPAT_API_KEY"));
|
||||
// Keys NOT in the allowlist — masked regardless of naming pattern.
|
||||
assert!(!super::is_safe_to_reveal("my_api_key"));
|
||||
assert!(!super::is_safe_to_reveal("GITHUB_TOKEN"));
|
||||
|
||||
@@ -181,6 +181,9 @@ pub fn validate_user_env_keys(env_vars: &BTreeMap<String, String>) -> Result<(),
|
||||
/// - `BUZZ_AGENT_THINKING_EFFORT` — non-secret enum (none/minimal/low/medium/high/xhigh/max)
|
||||
/// - `BUZZ_AGENT_THINKING_SUMMARY` — non-secret enum (auto/concise/detailed)
|
||||
/// - `DATABRICKS_HOST`, `DATABRICKS_MODEL`, `DATABRICKS_MODEL_FILTER` — Block non-secret defaults
|
||||
/// - `OPENAI_COMPAT_BASE_URL`, `OPENAI_COMPAT_MODEL`, `OPENAI_COMPAT_API` — OpenAI-compatible
|
||||
/// endpoint, model id, and API flavor (`auto|chat|responses`); the key itself
|
||||
/// (`OPENAI_COMPAT_API_KEY`) is not listed and stays masked
|
||||
pub(crate) fn is_safe_to_reveal(key: &str) -> bool {
|
||||
const SAFE_KEYS: &[&str] = &[
|
||||
"BUZZ_AGENT_PROVIDER",
|
||||
@@ -190,6 +193,9 @@ pub(crate) fn is_safe_to_reveal(key: &str) -> bool {
|
||||
"DATABRICKS_HOST",
|
||||
"DATABRICKS_MODEL",
|
||||
"DATABRICKS_MODEL_FILTER",
|
||||
"OPENAI_COMPAT_BASE_URL",
|
||||
"OPENAI_COMPAT_MODEL",
|
||||
"OPENAI_COMPAT_API",
|
||||
];
|
||||
let upper = key.to_ascii_uppercase();
|
||||
SAFE_KEYS.iter().any(|safe| upper == *safe)
|
||||
|
||||
Reference in New Issue
Block a user