Share runtime authentication across requests and credential refreshes (#55413)

## What changed

Add `RuntimeAuthManager` to share one registered runtime per credential source and return request-scoped `RuntimeAuth` values that pair the runtime with its credentials and HTTP client factory.

- Preserve registration keys and idempotency IDs across retryable failures and refreshes that retain the credential source.
- Replace the runtime when the credential source changes, preserve existing request snapshots, and reject late registration responses for a previous source.
- Use bounded credential recovery for registration `401` responses and cache `403` denials until the credential source changes.
- Expose authenticated actor and agent host information on `RuntimeAgentInstance`.

## Testing

Add tests for concurrent registration sharing, retry identity preservation, network policy recovery, credential refresh and replacement, bounded recovery, cached denials, and credential changes during registration.

GitOrigin-RevId: ea1e6e10a5939e8c3f7c0c317ccf8a83522c635f
This commit is contained in:
cooper-oai
2026-10-20 00:48:09 +00:00
committed by copyberry
parent 1a35bc4ccb
commit 091008729d
10 changed files with 702 additions and 19 deletions
@@ -0,0 +1,44 @@
//! Credentials and transport selected with the runtime for one request.
use crate::RuntimeAgentInstance;
use codex_http_client::HttpClientFactory;
use codex_login::AuthChangeState;
use codex_login::CodexAuth;
use std::sync::Arc;
/// Request-scoped credentials and transport selected with their matching runtime.
#[derive(Clone)]
pub struct RuntimeAuth {
pub(crate) runtime: Arc<RuntimeAgentInstance>,
pub(crate) auth: CodexAuth,
pub(crate) http_client_factory: HttpClientFactory,
pub(crate) change_state: AuthChangeState,
}
impl std::fmt::Debug for RuntimeAuth {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RuntimeAuth")
.field("runtime", &self.runtime)
.field("auth_mode", &self.auth.api_auth_mode())
.field("change_state", &self.change_state)
.finish_non_exhaustive()
}
}
impl RuntimeAuth {
pub fn runtime(&self) -> &Arc<RuntimeAgentInstance> {
&self.runtime
}
pub fn auth(&self) -> &CodexAuth {
&self.auth
}
pub fn http_client_factory(&self) -> &HttpClientFactory {
&self.http_client_factory
}
pub fn change_state(&self) -> AuthChangeState {
self.change_state
}
}