Files
codex/codex-rs/keyring-store/src/error_kind.rs
T
Celia Chen 2347a61d0d Add bounded credential-storage telemetry helpers (#47901)
## What changed

- Add `StorageTelemetry` to record operation counts, durations, secure-store outcomes, and file fallback reasons using bounded labels. Emit fallback warnings without credential payloads or error text.
- Add task-local client attribution with explicit propagation across task boundaries.
- Preserve typed keyring error causes through `std::io::Error` and the local secrets backend, classifying supported native failures without parsing error messages.
- Remove service names, account names, value lengths, and error text from keyring trace logs.

## Testing

Add tests for buffered metric emission, fallback outcomes, exclusion of sensitive error contents, client attribution isolation, and typed native error classification.

GitOrigin-RevId: 18e7201566a3b09061a6014fd6bd90eae96e3fc2
2026-09-24 18:08:31 +00:00

52 lines
2.1 KiB
Rust

//! Maps reliable native failures to portable IO kinds without examining error messages.
//! Ambiguous keyring errors stay Other: NoStorageAccess alone does not prove a locked store.
use crate::CredentialStoreError;
use std::error::Error;
use std::io::ErrorKind;
pub(super) fn classify(error: &CredentialStoreError) -> ErrorKind {
let mut cause: Option<&(dyn Error + 'static)> = Some(error);
while let Some(error) = cause {
if let Some(error) = error.downcast_ref::<std::io::Error>() {
return error.kind();
}
if let Some(error) = error.downcast_ref::<std::sync::Arc<std::io::Error>>() {
return error.kind();
}
#[cfg(target_os = "macos")]
if let Some(error) = error.downcast_ref::<security_framework::base::Error>() {
return match error.code() {
-25291 => ErrorKind::NotConnected, // errSecNotAvailable
-25292 | -25293 => ErrorKind::PermissionDenied, // errSecReadOnly / errSecAuthFailed
-4 => ErrorKind::Unsupported, // errSecUnimplemented
_ => ErrorKind::Other,
};
}
#[cfg(target_os = "linux")]
if let Some(error) = error.downcast_ref::<secret_service::Error>() {
match error {
secret_service::Error::Locked => return ErrorKind::WouldBlock,
secret_service::Error::Unavailable => return ErrorKind::NotConnected,
_ => {}
}
}
#[cfg(target_os = "windows")]
if let Some(error) = error.downcast_ref::<keyring::windows::Error>() {
return match error.0 {
1312 => ErrorKind::NotConnected, // ERROR_NO_SUCH_LOGON_SESSION
5 => ErrorKind::PermissionDenied, // ERROR_ACCESS_DENIED
50 => ErrorKind::Unsupported, // ERROR_NOT_SUPPORTED
1460 => ErrorKind::TimedOut, // ERROR_TIMEOUT
_ => ErrorKind::Other,
};
}
cause = error.source();
}
ErrorKind::Other
}
#[cfg(test)]
#[path = "error_kind_tests.rs"]
mod tests;