Stop retrying terminal runtime authentication denials (#60096)

## Why

Invalid assertions and paused or revoked runtime instances cannot recover through request retries or credential refresh. Permanent refresh-token failures also need to retain their sign-in error instead of becoming retryable stream errors.

## What changed

- Recognize terminal runtime denial codes in `401` and `403` response bodies and identity error headers, preserving HTTP diagnostics while stopping retries.
- Skip credential recovery for runtime denials in runtime-enabled model providers and backend requests, while preserving recovery for ordinary credential expiration.
- Propagate permanent refresh-token failures through runtime authentication as `RefreshTokenFailed` errors.

## Testing

Add coverage for body and header denials, preserved HTTP diagnostics, provider-scoped credential recovery, and cached permanent refresh failures. Complete-turn tests verify that runtime denials stop without retries or refreshes while expired credentials recover in both runtime authentication modes.

GitOrigin-RevId: 33f6f707454130e97e13f3b53e29d2c484602152
This commit is contained in:
cooper-oai
2026-11-07 09:48:46 +00:00
committed by copyberry
parent 4be90eb069
commit efdacaf46f
19 changed files with 574 additions and 34 deletions
+13 -7
View File
@@ -17,16 +17,22 @@ pub struct ResponseDebugContext {
}
pub fn extract_response_debug_context(transport: &TransportError) -> ResponseDebugContext {
match transport {
TransportError::Http {
headers: Some(headers),
..
} => extract_response_debug_context_from_headers(headers),
_ => ResponseDebugContext::default(),
}
}
pub fn extract_response_debug_context_from_headers(
headers: &http::HeaderMap,
) -> ResponseDebugContext {
let mut context = ResponseDebugContext::default();
let TransportError::Http { headers, .. } = transport else {
return context;
};
let extract_header = |name: &str| {
headers
.as_ref()
.and_then(|headers| headers.get(name))
.get(name)
.and_then(|value| value.to_str().ok())
.map(str::to_string)
};