Files
codex/codex-rs/codex-api/src/auth.rs
T
Adam Perry @ OpenAI 5a56caf18c [codex] Remove async_trait from first-party code (#27475)
## Why

First-party async traits should expose their `Send` contracts explicitly
without requiring `async_trait`. This completes the migration pattern
established in #27303 and #27304.

## What changed

- Replaced the remaining first-party `async_trait` traits with native
return-position `impl Future + Send` where statically dispatched and
explicit boxed `Send` futures where object safety is required.
- Kept implementations behavior-preserving, outlining existing async
bodies into inherent methods where that keeps the diff reviewable.
- Removed all direct first-party `async-trait` dependencies and the
workspace dependency declaration.
- Added a cargo-deny policy that permits `async-trait` only through the
remaining transitive wrapper crates.
- Updated `rand` from 0.8.5 to 0.8.6 to resolve RUSTSEC-2026-0097 and
keep the full cargo-deny check passing.

## Validation

- `just test -p codex-exec-server`: 216 passed, 2 skipped.
- `just test -p codex-model-provider`: 39 passed.
- `just test -p codex-core` and `just test`: changed tests passed;
remaining failures are environment-sensitive suites unrelated to this
migration.
- `cargo deny check`
- `just fix`
- `just fmt`
- `cargo shear`
- `just bazel-lock-check`
2026-06-11 18:16:39 -07:00

87 lines
2.9 KiB
Rust

use codex_client::Request;
use codex_client::TransportError;
use http::HeaderMap;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
/// Error returned while applying authentication to an outbound request.
#[derive(Debug, thiserror::Error)]
pub enum AuthError {
#[error("request auth build error: {0}")]
Build(String),
#[error("transient auth error: {0}")]
Transient(String),
}
impl From<AuthError> for TransportError {
fn from(error: AuthError) -> Self {
match error {
AuthError::Build(message) => TransportError::Build(message),
AuthError::Transient(message) => TransportError::Network(message),
}
}
}
/// Applies authentication to API requests.
///
/// Header-only providers can implement `add_auth_headers`; providers that sign
/// complete requests can override `apply_auth`.
pub trait AuthProvider: Send + Sync {
/// Adds any auth headers that are available without request body access.
///
/// Implementations should be cheap and non-blocking. This method is also
/// used by telemetry and non-HTTP request paths.
fn add_auth_headers(&self, headers: &mut HeaderMap);
/// Returns any auth headers that are available without request body access.
fn to_auth_headers(&self) -> HeaderMap {
let mut headers = HeaderMap::new();
self.add_auth_headers(&mut headers);
headers
}
/// Applies auth to a complete outbound request and returns the request to send.
///
/// The input `request` is moved into this method. Implementations may mutate
/// the owned request, or replace it entirely, before returning.
///
/// Header-only auth providers can rely on the default implementation.
/// Request-signing providers can override this to inspect the final URL,
/// headers, and body bytes before the transport sends the request.
///
/// Callers must always use the returned request as authoritative.
/// If this returns [`AuthError`], the request should not be sent.
fn apply_auth(&self, request: Request) -> AuthProviderFuture<'_> {
Box::pin(async move {
let mut request = request;
self.add_auth_headers(&mut request.headers);
Ok(request)
})
}
}
pub type AuthProviderFuture<'a> =
Pin<Box<dyn Future<Output = Result<Request, AuthError>> + Send + 'a>>;
/// Shared auth handle passed through API clients.
pub type SharedAuthProvider = Arc<dyn AuthProvider>;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct AuthHeaderTelemetry {
pub attached: bool,
pub name: Option<&'static str>,
}
pub fn auth_header_telemetry(auth: &dyn AuthProvider) -> AuthHeaderTelemetry {
let mut headers = HeaderMap::new();
auth.add_auth_headers(&mut headers);
let name = headers
.contains_key(http::header::AUTHORIZATION)
.then_some("authorization");
AuthHeaderTelemetry {
attached: name.is_some(),
name,
}
}