## Why
The `cargo-deny` job on `main` began failing after
[RUSTSEC-2026-0194](https://rustsec.org/advisories/RUSTSEC-2026-0194)
and
[RUSTSEC-2026-0195](https://rustsec.org/advisories/RUSTSEC-2026-0195)
flagged the workspace `quick-xml 0.38.4`. Both denial-of-service issues
are fixed in `quick-xml 0.41.0`.
A `quick-xml 0.39.4` copy must temporarily remain because the latest
`plist` and `wayland-scanner` releases have not adopted 0.41 yet.
Neither retained path accepts attacker-controlled XML at runtime:
`plist` does not exercise the affected APIs, and `wayland-scanner`
parses trusted protocol definitions at build time. Compatible upstream
bumps are already open in
[rust-plist#191](https://github.com/ebarnard/rust-plist/pull/191) and
[wayland-rs#938](https://github.com/Smithay/wayland-rs/pull/938).
## What changed
- Upgrade the workspace `quick-xml` dependency used by `codex-protocol`
to 0.41.0.
- Refresh `Cargo.lock` and `MODULE.bazel.lock`; this also updates
`plist` to 1.9.0 and `wayland-scanner` to 0.31.10.
- Add synchronized, temporary `cargo-deny` and `cargo-audit` exceptions
for the trusted `quick-xml 0.39.4` paths, with both upstream releases
recorded as the removal condition.
## Testing
- `cargo deny check`
- `just test -p codex-protocol` (238 tests)
- `just bazel-lock-check`
## Why
Amazon Bedrock's static catalog derives its GPT model definitions from
bundled OpenAI model metadata. The GPT-5.6 variants introduced in #30285
clone GPT-5.5, which carries an `availability_nux`; because app-server
forwards that metadata through `model/list`, clients can show GPT-5.5
launch copy for a GPT-5.6 Bedrock model.
`upgrade` is also model-catalog availability metadata and should not be
inherited by provider-specific Bedrock models.
## What changed
- Clear `availability_nux` and `upgrade` when constructing static
Bedrock GPT models.
- Add a regression test asserting that every static Bedrock model omits
both fields.
## Testing
- `just test -p codex-model-provider`
## Why
Codex telemetry pipeline needs a per-request TTFT value. The existing
`codex.turn_ttft` is recorded once per turn, so it cannot represent
later inference requests in the same turn and can miss the beginning of
hidden reasoning.
This restores the low-volume per-request signal proposed in
https://github.com/bk-nvidia/codex/pull/3 without bringing back
per-WebSocket-event TRACE logging.
## What changed
- start a timer when each mapped Responses stream begins
- latch the timer on the first `response.output_item.added`, including
an empty hidden-reasoning item
- attach `ttft_ms` to the existing `codex.sse_event` /
`response.completed` telemetry record
- cover the new completion field with an integration test
## Semantics
The value is per inference request, not per turn. It measures
mapped-stream-to-first-output-item latency, matching the
customer-proposed metric. For HTTP, the stream is already established
before timing begins, so request setup and response-header latency are
excluded.
`response.output_item.added` is a client-visible proxy for the start of
hidden reasoning; this does not claim access to the server's internal
first raw-token timestamp.
## Validation
- `just test -p codex-otel` (47 passed)
- `just test -p codex-core process_sse_emits_completed_telemetry` (1
passed after the final timer-placement change)
- attempted `just test -p codex-core`: 2,855 passed and 53 failed
because of unrelated local-environment failures (missing
`test_stdio_server` fixture binary, shell startup noise, and
timing-sensitive tests); the focused telemetry test passed in that run
as well
## Why
[#30867](https://github.com/openai/codex/pull/30867) makes
`submit_inter_agent_communication` the common outbound sink for
multi-agent v2 communications. This follow-up uses that single point to
log every communication lifecycle without requiring new hooks as spawn,
messaging, follow-up, or result paths evolve.
For each communication, the logs need to identify its type, sender and
receiver threads, and content, while correlating the successful send
with receipt by the destination mailbox. The logging path must not query
externally supplied time providers because those calls can be expensive
for app-server clients.
## What changed
- Added structured `INFO` events on the OpenTelemetry-exported
`codex_otel.agent_communication` target for `spawn`, `message`,
`followup`, and `result` communications.
- Logged successful sends from `submit_inter_agent_communication` with
the communication kind, sender and receiver thread IDs, content, and
submission ID.
- Logged receives after the communication has been enqueued in the
receiver mailbox, using the same submission ID.
- Avoided time-provider calls and other asynchronous work in the logging
path.
- Narrowed ordinary spawn and send-input APIs to `Vec<UserInput>` so
`Op::InterAgentCommunication` cannot bypass the context-bearing
centralized path.
The refactor does not change submission IDs, capacity checks, last-task
bookkeeping, mailbox ordering, protocol types, rollout data, or
model-visible context.
## Event shape
Illustrative JSON representation of the two independently emitted
records:
```json
[
{
"event.name": "codex.agent_communication",
"communication_id": "019f20e1-40d1-7890-a123-456789abcdef",
"kind": "spawn",
"state": "send",
"sender_thread_id": "019f20df-fbe1-7890-a123-456789abcdef",
"receiver_thread_id": "019f20e1-3f79-7890-a123-456789abcdef",
"content": "inspect the repository"
},
{
"event.name": "codex.agent_communication",
"communication_id": "019f20e1-40d1-7890-a123-456789abcdef",
"state": "receive"
}
]
```
Consumers join the receive record to the send record by
`communication_id` for the immutable communication metadata.
## Testing
- Extended the existing end-to-end multi-agent v2 spawn test to verify
content, both thread IDs, and a correlated send/receive submission ID.
- Re-ran focused control and handler coverage for direct messages,
follow-up tasks, and completion results.
## Why
Multi-agent v2 communications currently use separate outbound paths:
direct messages, follow-up tasks, and completion results go through
`send_inter_agent_communication`, while a spawn's initial message goes
through the generic input submission path. That split makes it difficult
to add complete communication lifecycle logging in one place.
This refactor makes `submit_inter_agent_communication` the common sink
for those paths, preparing the follow-up observability work discussed in
[#30516](https://github.com/openai/codex/pull/30516).
## What changed
- Routed all current outbound `InterAgentCommunication` paths in
`AgentControl`—direct messages, follow-up tasks, completion results, and
multi-agent v2 spawn initial messages—through
`submit_inter_agent_communication`.
- Centralized the actual submission and last-task-message bookkeeping
there, providing one place for the follow-up PR to instrument
communication creation and successful enqueue.
- Left non-communication input handling and the multi-agent v1 spawn
flow unchanged.
## Testing
- `just test -p codex-core 'agent::control::tests::'` (51 passed)
- `just test -p codex-core
'suite::subagent_notifications::encrypted_multi_agent_v2_spawn_sends_agent_message_to_child'`
(passed)
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/30867).
* #30872
* __->__ #30867
## Summary
- require a Pong within 60 seconds for established Noise Rendezvous
WebSockets on both the harness and executor
- bound steady-state WebSocket writes and harness event delivery so
backpressure cannot mask the deadline
- classify executor disconnects with bounded reasons and feed them into
the existing reconnect metric and structured log
- cover silent peers, responsive peers, continuous non-Pong traffic, and
local application backpressure
## Why
The existing periodic Pings did not track Pongs, so a half-open or
blackholed connection could remain stuck until the operating system's
TCP timeout. This adds the smallest explicit liveness contract without
new spans, RTT histograms, feature flags, or TCP diagnostics.
## Testing
- `just test -p codex-exec-server` on devbox `richard-6` — 300 passed, 2
skipped
- `just fix -p codex-exec-server`
- `just fmt`
- independent correctness, performance/security, and YAGNI reviews — no
findings
## Summary
The TUI biosafety block still included obsolete copy telling approved
researchers they may be able to apply for Trusted Access.
Remove that sentence and update the UI snapshot to match the approved
wording.
## Summary
Disable Nagle unconditionally for both exec-server Rendezvous WebSocket
connections.
- pass `disable_nagle=true` at the executor and harness connection call
sites
- keep the existing signed URL, protocol, and connection flow unchanged
- add no feature flag, rollout schema, path variant, or
experiment-specific telemetry
The companion internal PR enables `TCP_NODELAY` on accepted Rendezvous
sockets: https://github.com/openai/openai/pull/1082463
## Why
Rendezvous carries small, latency-sensitive relay and JSON-RPC frames.
Three staging runs of 30 steady-state `process/read` calls per
configuration measured p50 improving from 139.1 ms to 81.5 ms and p95
from 162.0 ms to 95.8 ms with Nagle disabled.
The expected packet overhead is small at the current connection scale.
We will use existing latency, error, packet, and CPU monitoring and
revert normally if production regresses.
## Rollout and rollback
The client and accepted-socket changes can deploy independently. New
connections receive the setting as each side deploys. Rollback is a
normal code revert; there is no persisted assignment or gate state to
unwind.
## Validation
- `just test -p codex-exec-server --lib`: 164 passed
- `just fix -p codex-exec-server`: passed
- `just fmt`: passed
- independent final review found no actionable issue