diff --git a/codex-rs/login/src/auth/storage.rs b/codex-rs/login/src/auth/storage.rs index f6cacfdc7a..55a7b843d7 100644 --- a/codex-rs/login/src/auth/storage.rs +++ b/codex-rs/login/src/auth/storage.rs @@ -27,9 +27,10 @@ pub use codex_config::types::AuthKeyringBackendKind; use codex_keyring_store::DefaultKeyringStore; use codex_keyring_store::KeyringStore; use codex_protocol::account::PlanType as AccountPlanType; -use codex_secrets::LocalSecretsBackend; use codex_secrets::SecretName; use codex_secrets::SecretScope; +use codex_secrets::SecretsBackendKind; +use codex_secrets::SecretsManager; use once_cell::sync::Lazy; /// Expected structure for $CODEX_HOME/auth.json. @@ -258,18 +259,30 @@ impl AuthStorageBackend for DirectKeyringAuthStorage { } } -#[derive(Clone, Debug)] +#[derive(Clone)] struct SecretsKeyringAuthStorage { codex_home: PathBuf, - secrets_backend: LocalSecretsBackend, + secrets_manager: SecretsManager, +} + +impl Debug for SecretsKeyringAuthStorage { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("SecretsKeyringAuthStorage") + .field("codex_home", &self.codex_home) + .finish_non_exhaustive() + } } impl SecretsKeyringAuthStorage { fn new(codex_home: PathBuf, keyring_store: Arc) -> Self { - let secrets_backend = LocalSecretsBackend::new(codex_home.clone(), keyring_store); + let secrets_manager = SecretsManager::new_with_keyring_store( + codex_home.clone(), + SecretsBackendKind::Local, + keyring_store, + ); Self { codex_home, - secrets_backend, + secrets_manager, } } } @@ -277,7 +290,7 @@ impl SecretsKeyringAuthStorage { impl AuthStorageBackend for SecretsKeyringAuthStorage { fn load(&self) -> std::io::Result> { match self - .secrets_backend + .secrets_manager .get(&SecretScope::Global, &CLI_AUTH_SECRET_NAME) .map_err(|err| { std::io::Error::other(format!( @@ -295,7 +308,7 @@ impl AuthStorageBackend for SecretsKeyringAuthStorage { fn save(&self, auth: &AuthDotJson) -> std::io::Result<()> { let serialized = serde_json::to_string(auth).map_err(std::io::Error::other)?; - self.secrets_backend + self.secrets_manager .set(&SecretScope::Global, &CLI_AUTH_SECRET_NAME, &serialized) .map_err(|err| { let message = @@ -311,7 +324,7 @@ impl AuthStorageBackend for SecretsKeyringAuthStorage { fn delete(&self) -> std::io::Result { let keyring_removed = self - .secrets_backend + .secrets_manager .delete(&SecretScope::Global, &CLI_AUTH_SECRET_NAME) .map_err(|err| { std::io::Error::other(format!( diff --git a/codex-rs/login/src/auth/storage_tests.rs b/codex-rs/login/src/auth/storage_tests.rs index dcb9c349a3..12a78246c8 100644 --- a/codex-rs/login/src/auth/storage_tests.rs +++ b/codex-rs/login/src/auth/storage_tests.rs @@ -2,8 +2,9 @@ use super::*; use crate::token_data::IdTokenInfo; use anyhow::Context; use base64::Engine; -use codex_secrets::LocalSecretsBackend; use codex_secrets::SecretScope; +use codex_secrets::SecretsBackendKind; +use codex_secrets::SecretsManager; use codex_secrets::compute_keyring_account; use pretty_assertions::assert_eq; use serde_json::json; @@ -198,9 +199,12 @@ fn seed_secrets_backend_and_fallback_auth_file_for_delete( codex_home: &Path, auth: &AuthDotJson, ) -> anyhow::Result { - let backend = - LocalSecretsBackend::new(codex_home.to_path_buf(), Arc::new(mock_keyring.clone())); - backend.set( + let manager = SecretsManager::new_with_keyring_store( + codex_home.to_path_buf(), + SecretsBackendKind::Local, + Arc::new(mock_keyring.clone()), + ); + manager.set( &SecretScope::Global, &CLI_AUTH_SECRET_NAME, &serde_json::to_string(auth)?, @@ -215,9 +219,12 @@ fn seed_secrets_backend_with_auth( codex_home: &Path, auth: &AuthDotJson, ) -> anyhow::Result<()> { - let backend = - LocalSecretsBackend::new(codex_home.to_path_buf(), Arc::new(mock_keyring.clone())); - backend.set( + let manager = SecretsManager::new_with_keyring_store( + codex_home.to_path_buf(), + SecretsBackendKind::Local, + Arc::new(mock_keyring.clone()), + ); + manager.set( &SecretScope::Global, &CLI_AUTH_SECRET_NAME, &serde_json::to_string(auth)?, @@ -230,9 +237,12 @@ fn assert_keyring_saved_auth_and_removed_fallback( codex_home: &Path, expected: &AuthDotJson, ) -> anyhow::Result<()> { - let backend = - LocalSecretsBackend::new(codex_home.to_path_buf(), Arc::new(mock_keyring.clone())); - let saved_value = backend + let manager = SecretsManager::new_with_keyring_store( + codex_home.to_path_buf(), + SecretsBackendKind::Local, + Arc::new(mock_keyring.clone()), + ); + let saved_value = manager .get(&SecretScope::Global, &CLI_AUTH_SECRET_NAME)? .context("encrypted auth entry should exist")?; let expected_serialized = serde_json::to_string(expected)?; diff --git a/codex-rs/rmcp-client/src/oauth.rs b/codex-rs/rmcp-client/src/oauth.rs index 2a87883123..b27e280c15 100644 --- a/codex-rs/rmcp-client/src/oauth.rs +++ b/codex-rs/rmcp-client/src/oauth.rs @@ -21,9 +21,10 @@ use anyhow::Error; use anyhow::Result; use codex_config::types::AuthKeyringBackendKind; use codex_config::types::OAuthCredentialsStoreMode; -use codex_secrets::LocalSecretsBackend; use codex_secrets::SecretName; use codex_secrets::SecretScope; +use codex_secrets::SecretsBackendKind; +use codex_secrets::SecretsManager; use oauth2::AccessToken; use oauth2::RefreshToken; use oauth2::Scope; @@ -219,10 +220,13 @@ fn load_oauth_tokens_from_secrets_keyring( url: &str, ) -> Result> { let codex_home = find_codex_home()?; - let backend = - LocalSecretsBackend::new(codex_home.to_path_buf(), Arc::new(keyring_store.clone())); + let manager = SecretsManager::new_with_keyring_store( + codex_home.to_path_buf(), + SecretsBackendKind::Local, + Arc::new(keyring_store.clone()), + ); let secret_name = compute_secret_name(server_name, url)?; - match backend + match manager .get(&SecretScope::Global, &secret_name) .context("failed to load MCP OAuth tokens from encrypted storage")? { @@ -309,10 +313,13 @@ fn save_oauth_tokens_to_secrets_keyring( ) -> Result<()> { let serialized = serde_json::to_string(tokens).context("failed to serialize OAuth tokens")?; let codex_home = find_codex_home()?; - let backend = - LocalSecretsBackend::new(codex_home.to_path_buf(), Arc::new(keyring_store.clone())); + let manager = SecretsManager::new_with_keyring_store( + codex_home.to_path_buf(), + SecretsBackendKind::Local, + Arc::new(keyring_store.clone()), + ); let secret_name = compute_secret_name(server_name, &tokens.url)?; - backend + manager .set(&SecretScope::Global, &secret_name, &serialized) .context("failed to write OAuth tokens to encrypted storage")?; @@ -417,10 +424,13 @@ fn delete_oauth_tokens_from_secrets_keyring( url: &str, ) -> Result { let codex_home = find_codex_home()?; - let backend = - LocalSecretsBackend::new(codex_home.to_path_buf(), Arc::new(keyring_store.clone())); + let manager = SecretsManager::new_with_keyring_store( + codex_home.to_path_buf(), + SecretsBackendKind::Local, + Arc::new(keyring_store.clone()), + ); let secret_name = compute_secret_name(server_name, url)?; - let secrets_removed = backend + let secrets_removed = manager .delete(&SecretScope::Global, &secret_name) .context("failed to delete OAuth tokens from encrypted storage")?; Ok(secrets_removed) @@ -977,9 +987,13 @@ mod tests { &tokens, )?; - let backend = LocalSecretsBackend::new(env.path().to_path_buf(), Arc::new(store.clone())); + let manager = SecretsManager::new_with_keyring_store( + env.path().to_path_buf(), + SecretsBackendKind::Local, + Arc::new(store.clone()), + ); let secret_name = super::compute_secret_name(&tokens.server_name, &tokens.url)?; - let stored = backend + let stored = manager .get(&SecretScope::Global, &secret_name)? .expect("tokens should be saved to encrypted storage"); assert_eq!(serde_json::from_str::(&stored)?, tokens); @@ -1082,10 +1096,14 @@ mod tests { &tokens.url, )?; - let backend = LocalSecretsBackend::new(env.path().to_path_buf(), Arc::new(store.clone())); + let manager = SecretsManager::new_with_keyring_store( + env.path().to_path_buf(), + SecretsBackendKind::Local, + Arc::new(store.clone()), + ); let secret_name = super::compute_secret_name(&tokens.server_name, &tokens.url)?; assert!(removed); - assert!(backend.get(&SecretScope::Global, &secret_name)?.is_none()); + assert!(manager.get(&SecretScope::Global, &secret_name)?.is_none()); assert_eq!(store.saved_value(&key), Some(serialized)); assert!(!super::fallback_file_path()?.exists()); Ok(())