Integrate runtime authentication into model requests (#57171)

## What changed

- Add opt-in runtime authentication through `ModelClient::with_runtime_auth`, requiring the provider and runtime manager to share the selected OpenAI credentials.
- Keep runtime identity, credentials, routing, and transport selection consistent for each request and its retries, signing a fresh assertion for each attempt.
- Apply authentication asynchronously to WebSocket handshakes, replace stale authentication headers, and reconnect when the runtime changes.
- Reject account, organization, or project selectors that conflict with the registered runtime, and preserve gateway OAuth composition.

## Testing

Add coverage for dual-header and assertion-only authentication, HTTP retries, runtime replacement and account switches, stale WebSocket headers, selector mismatches, gateway OAuth failures, transport revocation, and Realtime compatibility.

GitOrigin-RevId: 45b9efc2c80481406a0f6f6396a8cdd21d933c12
This commit is contained in:
cooper-oai
2026-10-26 18:06:07 +00:00
committed by copyberry
parent 2d4c131524
commit cf29971d93
29 changed files with 1192 additions and 207 deletions
@@ -464,9 +464,8 @@ impl ResponsesWebsocketClient {
.websocket_url_for_path("/responses")
.map_err(|err| ApiError::Stream(format!("failed to build websocket URL: {err}")))?;
let mut headers =
merge_request_headers(&self.provider.headers, extra_headers, default_headers);
self.auth.add_auth_headers(&mut headers)?;
let headers = merge_request_headers(&self.provider.headers, extra_headers, default_headers);
let headers = self.auth.apply_auth_headers(headers).await?;
let connector = WebSocketConnector::new(http_client_factory)
.map_err(|err| ApiError::Stream(format!("failed to configure websocket TLS: {err}")))?;
@@ -33,9 +33,8 @@ impl ResponsesWebsocketClient {
.provider
.websocket_url_for_path("/responses")
.map_err(|err| ApiError::Stream(format!("failed to build websocket URL: {err}")))?;
let mut headers =
merge_request_headers(&self.provider.headers, extra_headers, default_headers);
self.auth.add_auth_headers(&mut headers)?;
let headers = merge_request_headers(&self.provider.headers, extra_headers, default_headers);
let headers = self.auth.apply_auth_headers(headers).await?;
let (stream, _status, server_reasoning_included, server_model) =
connect_websocket(ws_url, headers, connector, turn_state).await?;
Ok(ResponsesWebsocketConnection::new(