1use codex_client::Request;
2use codex_client::TransportError;
3use http::HeaderMap;
4use std::future::Future;
5use std::pin::Pin;
6use std::sync::Arc;
7
8#[derive(Debug, thiserror::Error)]
10pub enum AuthError {
11 #[error("request auth build error: {0}")]
12 Build(String),
13 #[error("transient auth error: {0}")]
14 Transient(String),
15}
16
17impl From<AuthError> for TransportError {
18 fn from(error: AuthError) -> Self {
19 match error {
20 AuthError::Build(message) => TransportError::Build(message),
21 AuthError::Transient(message) => TransportError::Network(message),
22 }
23 }
24}
25
26pub trait AuthProvider: Send + Sync {
31 fn add_auth_headers(&self, headers: &mut HeaderMap);
36
37 fn to_auth_headers(&self) -> HeaderMap {
39 let mut headers = HeaderMap::new();
40 self.add_auth_headers(&mut headers);
41 headers
42 }
43
44 fn apply_auth(&self, request: Request) -> AuthProviderFuture<'_> {
56 Box::pin(async move {
57 let mut request = request;
58 self.add_auth_headers(&mut request.headers);
59 Ok(request)
60 })
61 }
62}
63
64pub type AuthProviderFuture<'a> =
65 Pin<Box<dyn Future<Output = Result<Request, AuthError>> + Send + 'a>>;
66
67pub type SharedAuthProvider = Arc<dyn AuthProvider>;
69
70#[derive(Clone, Debug, PartialEq, Eq)]
71pub struct AgentIdentityTelemetry {
72 pub agent_id: String,
73 pub task_id: String,
74}
75
76#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
77pub struct AuthHeaderTelemetry {
78 pub attached: bool,
79 pub name: Option<&'static str>,
80}
81
82pub fn auth_header_telemetry(auth: &dyn AuthProvider) -> AuthHeaderTelemetry {
83 let mut headers = HeaderMap::new();
84 auth.add_auth_headers(&mut headers);
85 let name = headers
86 .contains_key(http::header::AUTHORIZATION)
87 .then_some("authorization");
88 AuthHeaderTelemetry {
89 attached: name.is_some(),
90 name,
91 }
92}