mirror of
https://github.com/openai/codex.git
synced 2026-11-11 14:32:25 +00:00
Propagate response tickets to Guardian reviews (#42758)
## What changed - Request and parse server-issued Guardian tickets for eligible Codex backend responses. - Scope each ticket to the response that produced a Guardian review or classifier request, including HTTP and WebSocket retries, without adding it to model-visible or persisted context. - Validate ticket shape, reserve its metadata keys, redact it from debug and request-body logging, and attach it only at the Guardian transport boundary. ## Testing - Cover ticket parsing, endpoint and authentication routing, retry scoping, classifier retries, and redaction for compressed and uncompressed requests. GitOrigin-RevId: 6219dd15c9f19ed3387de516aac1b8e7c9cdb0e3
This commit is contained in:
1 parent
97e46694e1
commit
cc4b8bdeb8
32 files changed
+562
-44
No files matched your search
@@ -9,6 +9,8 @@ use crate::telemetry::SseTelemetry;
|
||||
use codex_client::ByteStream;
|
||||
use codex_client::StreamResponse;
|
||||
use codex_protocol::ResponseUsageMetadata;
|
||||
use codex_protocol::guardian_ticket::GUARDIAN_TICKET_HEADER;
|
||||
use codex_protocol::guardian_ticket::GuardianTicket;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::protocol::MisalignmentErrorDetails;
|
||||
use codex_protocol::protocol::ModelVerification;
|
||||
@@ -406,8 +408,18 @@ pub fn process_responses_event(
|
||||
}
|
||||
}
|
||||
"response.created" => {
|
||||
if event.response.is_some() {
|
||||
return Ok(Some(ResponseEvent::Created {}));
|
||||
if let Some(response) = event.response {
|
||||
let guardian_ticket = response
|
||||
.get("headers")
|
||||
.and_then(Value::as_object)
|
||||
.and_then(|headers| {
|
||||
headers
|
||||
.iter()
|
||||
.find(|(name, _)| name.eq_ignore_ascii_case(GUARDIAN_TICKET_HEADER))
|
||||
})
|
||||
.and_then(|(_, value)| value.as_str())
|
||||
.and_then(GuardianTicket::from_server);
|
||||
return Ok(Some(ResponseEvent::Created { guardian_ticket }));
|
||||
}
|
||||
}
|
||||
"response.failed" => {
|
||||
@@ -1396,7 +1408,7 @@ mod tests {
|
||||
}
|
||||
|
||||
fn is_created(ev: &ResponseEvent) -> bool {
|
||||
matches!(ev, ResponseEvent::Created)
|
||||
matches!(ev, ResponseEvent::Created { .. })
|
||||
}
|
||||
fn is_output(ev: &ResponseEvent) -> bool {
|
||||
matches!(ev, ResponseEvent::OutputItemDone(_))
|
||||
@@ -1578,7 +1590,7 @@ mod tests {
|
||||
.await;
|
||||
|
||||
assert_eq!(events.len(), 2);
|
||||
assert_matches!(&events[0], ResponseEvent::Created);
|
||||
assert_matches!(&events[0], ResponseEvent::Created { .. });
|
||||
assert_matches!(
|
||||
&events[1],
|
||||
ResponseEvent::Completed {
|
||||
@@ -1616,7 +1628,12 @@ mod tests {
|
||||
&events[0],
|
||||
ResponseEvent::ServerModel(model) if model == CYBER_RESTRICTED_MODEL_FOR_TESTS
|
||||
);
|
||||
assert_matches!(&events[1], ResponseEvent::Created);
|
||||
assert_matches!(
|
||||
&events[1],
|
||||
ResponseEvent::Created {
|
||||
guardian_ticket: None
|
||||
}
|
||||
);
|
||||
assert_matches!(
|
||||
&events[2],
|
||||
ResponseEvent::Completed {
|
||||
@@ -1738,7 +1755,7 @@ mod tests {
|
||||
.await;
|
||||
|
||||
assert_eq!(events.len(), 7);
|
||||
assert_matches!(&events[0], ResponseEvent::Created);
|
||||
assert_matches!(&events[0], ResponseEvent::Created { .. });
|
||||
assert_matches!(
|
||||
&events[1],
|
||||
ResponseEvent::SafetyBuffering(buffering)
|
||||
|
||||
Reference in new issue
Block a user