Ruslan Nigmatullin
ruslan@openai.com
90d · built 2026-05-28
90-day totals
- Commits
- 53
- Grow
- 15.5
- Maintenance
- 11.0
- Fixes
- 0.6
- Total ETV
- 27.1
30-day trajectory
Last 30 days vs. the 30 days before. Up arrows on Growth and ETV mean improvement; up arrow on Fixes share means more time on fixes (worse).
Daily performance
Daily ETV, stacked by Growth, Maintenance and Fixes.
Work-mix over time
Share of Growth / Maintenance / Fixes over a rolling 7-day window. Reads as 'where is effort flowing right now'.
Bug flow over time
Monthly bug flow attributed to this developer. The left bar (red) is bug impact this dev authored that was addressed in the given month — combining bugs others fixed for them and bugs they fixed themselves. The right bar is fixes they personally shipped that month, split between self-fixes (overlap with the red bar) and fixes done for someone else. X-axis is fix-time, not introduction-time — the Navigara API attributes bugs backward to the author at the moment the fix lands.
- Self-fix share
- 51%
- Bugs you introduced
- 4.4
- Bugs you fixed
- 0.6
Repository spread
Where this developer's commits land. Concentrated work (top1 > 80%) vs polymath spread (top1 < 30%).
Most impactful commits
Top 20 by ETV in the 90-day window.
- 3.0ETVstate: pass state db handles through consumers (#20561) ## Why SQLite state was still being opened from consumer paths, including lazy `OnceCell`-backed thread-store call sites. That let one process construct multiple state DB connections for the same Codex home, which makes SQLite lock contention and `database is locked` failures much easier to hit. State DB lifetime should be chosen by main-like entrypoints and tests, then passed through explicitly. Consumers should use the supplied `Option<StateDbHandle>` or `StateDbHandle` and keep their existing filesystem fallback or error behavior when no handle is available. The startup path also needs to keep the rollout crate in charge of SQLite state initialization. Opening `codex_state::StateRuntime` directly bypasses rollout metadata backfill, so entrypoints should initialize through `codex_rollout::state_db` and receive a handle only after required rollout backfills have completed. ## What Changed - Initialize the state DB in main-like entrypoints for CLI, TUI, app-server, exec, MCP server, and the thread-manager sample. - Pass `Option<StateDbHandle>` through `ThreadManager`, `LocalThreadStore`, app-server processors, TUI app wiring, rollout listing/recording, personality migration, shell snapshot cleanup, session-name lookup, and memory/device-key consumers. - Remove the lazy local state DB wrapper from the thread store so non-test consumers use only the supplied handle or their existing fallback path. - Make `codex_rollout::state_db::init` the local state startup path: it opens/migrates SQLite, runs rollout metadata backfill when needed, waits for concurrent backfill workers up to a bounded timeout, verifies completion, and then returns the initialized handle. - Keep optional/non-owning SQLite helpers, such as remote TUI local reads, as open-only paths that do not run startup backfill. - Switch app-server startup from direct `codex_state::StateRuntime::init` to the rollout state initializer so app-server cannot skip rollout backfill. - Collapse split rollout lookup/list APIs so callers use the normal methods with an optional state handle instead of `_with_state_db` variants. - Restore `getConversationSummary(ThreadId)` to delegate through `ThreadStore::read_thread` instead of a LocalThreadStore-specific rollout path special case. - Keep DB-backed rollout path lookup keyed on the DB row and file existence, without imposing the filesystem filename convention on existing DB rows. - Verify readable DB-backed rollout paths against `session_meta.id` before returning them, so a stale SQLite row that points at another thread's JSONL falls back to filesystem search and read-repairs the DB row. - Keep `debug prompt-input` filesystem-only so a one-off debug command does not initialize or backfill SQLite state just to print prompt input. - Keep goal-session test Codex homes alive only in the goal-specific helper, rather than leaking tempdirs from the shared session test helper. - Update tests and call sites to pass explicit state handles where DB behavior is expected and explicit `None` where filesystem-only behavior is intended. ## Validation - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo check -p codex-rollout -p codex-thread-store -p codex-app-server -p codex-core -p codex-tui -p codex-exec -p codex-cli --tests` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-rollout state_db_` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-rollout find_thread_path` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-rollout find_thread_path -- --nocapture` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-rollout try_init_ -- --nocapture` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-rollout` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo clippy -p codex-rollout --lib -- -D warnings` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-thread-store read_thread_falls_back_when_sqlite_path_points_to_another_thread -- --nocapture` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-thread-store` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core shell_snapshot` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core --test all personality_migration` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core --test all rollout_list_find` - `RUST_MIN_STACK=8388608 CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core --test all rollout_list_find::find_prefers_sqlite_path_by_id -- --nocapture` - `RUST_MIN_STACK=8388608 CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core --test all rollout_list_find -- --nocapture` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core interrupt_accounts_active_goal_before_pausing` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-app-server get_auth_status -- --test-threads=1` - `CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-app-server --lib` - `CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo check -p codex-rollout -p codex-app-server --tests` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db just fix -p codex-rollout -p codex-thread-store -p codex-core -p codex-app-server -p codex-tui -p codex-exec -p codex-cli` - `CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db just fix -p codex-rollout -p codex-app-server` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db just fix -p codex-rollout` - `CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db just fix -p codex-core` - `just argument-comment-lint -p codex-core` - `just argument-comment-lint -p codex-rollout` Focused coverage added in `codex-rollout`: - `recorder::tests::state_db_init_backfills_before_returning` verifies the rollout metadata row exists before startup init returns. - `state_db::tests::try_init_waits_for_concurrent_startup_backfill` verifies startup waits for another worker to finish backfill instead of disabling the handle for the process. - `state_db::tests::try_init_times_out_waiting_for_stuck_startup_backfill` verifies startup does not hang indefinitely on a stuck backfill lease. - `tests::find_thread_path_accepts_existing_state_db_path_without_canonical_filename` verifies DB-backed lookup accepts valid existing rollout paths even when the filename does not include the thread UUID. - `tests::find_thread_path_falls_back_when_db_path_points_to_another_thread` verifies DB-backed lookup ignores a stale row whose existing path belongs to another thread and read-repairs the row after filesystem fallback. Focused coverage updated in `codex-core`: - `rollout_list_find::find_prefers_sqlite_path_by_id` now uses a DB-preferred rollout file with matching `session_meta.id`, so it still verifies that valid SQLite paths win without depending on stale/empty rollout contents. `cargo test -p codex-app-server thread_list_respects_search_term_filter -- --test-threads=1 --nocapture` was attempted locally but timed out waiting for the app-server test harness `initialize` response before reaching the changed thread-list code path. `bazel test //codex-rs/thread-store:thread-store-unit-tests --test_output=errors` was attempted locally after the thread-store fix, but this container failed before target analysis while fetching `v8+` through BuildBuddy/direct GitHub. The equivalent local crate coverage, including `cargo test -p codex-thread-store`, passes. A plain local `cargo check -p codex-rollout -p codex-app-server --tests` also requires system `libcap.pc` for `codex-linux-sandbox`; the follow-up app-server check above used `CODEX_SKIP_VENDORED_BWRAP=1` in this container.github.com-openai-codex · 4d201e34 · 2026-05-04
- 2.6ETVapp-server: Add transport for remote control (#15951)github.com-openai-codex · 73dab204 · 2026-04-06
- 2.0ETV[daemon] Add app-server daemon lifecycle management (#20718) ## Why Desktop and mobile Codex clients need a machine-readable way to bootstrap and manage `codex app-server` on remote machines reached over SSH. The same flow is also useful for bringing up app-server with `remote_control` enabled on a fresh developer machine and keeping that managed install current without requiring a human session. ## What changed - add the new experimental `codex-app-server-daemon` crate and wire it into `codex app-server daemon` lifecycle commands: `start`, `restart`, `stop`, `version`, and `bootstrap` - add explicit `enable-remote-control` and `disable-remote-control` commands that persist the launch setting and restart a running managed daemon so the change takes effect immediately - emit JSON success responses for daemon commands so remote callers can consume them directly - support a Unix-only pidfile-backed detached backend for lifecycle management - assume the standalone `install.sh` layout for daemon-managed binaries and always launch `CODEX_HOME/packages/standalone/current/codex` - add bootstrap support for the standalone managed install plus a detached hourly updater loop - harden lifecycle management around concurrent operations, pidfile ownership, stale state cleanup, updater ownership, managed-binary preflight, Unix-only rejection, forced shutdown after the graceful window, and updater process-group tracking/cleanup - document the experimental Unix-only support boundary plus the standalone bootstrap/update flow in `codex-rs/app-server-daemon/README.md` ## Verification - `cargo test -p codex-app-server-daemon -p codex-cli` - live pid validation on `cb4`: `bootstrap --remote-control`, `restart`, `version`, `stop` ## Follow-up - Add updater self-refresh so the long-lived `pid-update-loop` can replace its own executable image after installing a newer managed Codex binary.github.com-openai-codex · 0c8d4252 · 2026-05-08
- 1.7ETVapp-server: Add streaming and tty/pty capabilities to `command/exec` (#13640) * Add an ability to stream stdin, stdout, and stderr * Streaming of stdout and stderr has a configurable cap for total amount of transmitted bytes (with an ability to disable it) * Add support for overriding environment variables * Add an ability to terminate running applications (using `command/exec/terminate`) * Add TTY/PTY support, with an ability to resize the terminal (using `command/exec/resize`)github.com-openai-codex · e9bd8b20 · 2026-03-07
- 1.5ETVapp-server: add v2 filesystem APIs (#14245) Add a protocol-level filesystem surface to the v2 app-server so Codex clients can read and write files, inspect directories, and subscribe to path changes without relying on host-specific helpers. High-level changes: - define the new v2 fs/readFile, fs/writeFile, fs/createDirectory, fs/getMetadata, fs/readDirectory, fs/remove, fs/copy RPCs - implement the app-server handlers, including absolute-path validation, base64 file payloads, recursive copy/remove semantics - document the API, regenerate protocol schemas/types, and add end-to-end tests for filesystem operations, copy edge cases Testing plan: - validate protocol serialization and generated schema output for the new fs request, response, and notification types - run app-server integration coverage for file and directory CRUD paths, metadata/readDirectory responses, copy failure modes, and absolute-path validationgithub.com-openai-codex · f8f82bfc · 2026-03-13
- 1.3ETVapp-server: add codex-device-key crate (#18429) ## Why Device-key storage and signing are local security-sensitive operations with platform-specific behavior. Keeping the core API in `codex-device-key` keeps app-server focused on routing and business logic instead of owning key-management details. The crate keeps the signing surface intentionally narrow: callers can create a bound key, fetch its public key, or sign one of the structured payloads accepted by the crate. It does not expose a generic arbitrary-byte signing API. Key IDs cross into platform-specific labels, tags, and metadata paths, so externally supplied IDs are constrained to the same auditable namespace created by the crate: `dk_` followed by unpadded base64url for 32 bytes. Remote-control target paths are also tied to each signed payload shape so connection proofs cannot be reused for enrollment endpoints, or vice versa. ## What changed - Added the `codex-device-key` workspace crate. - Added account/client-bound key creation with stable `dk_` key IDs. - Added strict `key_id` validation before public-key lookup or signing reaches a provider. - Added public-key lookup and structured signing APIs. - Split remote-control client endpoint allowlists by connection vs enrollment payload shape. - Added validation for key bindings, accepted payload fields, token expiration, and payload/key binding mismatches. - Added flow-oriented docs on the validation helpers that gate provider signing. - Added protection policy and protection-class types without wiring a platform provider yet. - Added an unsupported default provider so platforms without an implementation fail explicitly instead of silently falling back to software-backed keys. - Updated Cargo and Bazel lock metadata for the new crate and non-platform-specific dependencies. ## Stack This is stacked on #18428. ## Validation - `cargo test -p codex-device-key` - Added unit coverage for strict `key_id` validation before provider use. - Added unit coverage that rejects remote-control paths from the wrong signed payload shape. - `just bazel-lock-update` - `just bazel-lock-check`github.com-openai-codex · 5bab04dc · 2026-04-21
- 1.2ETVcore: Make FileWatcher reusable (#15093) ### Summary Make `FileWatcher` a reusable core component which can be built upon. Extract skills-related logic into a separate `SkillWatcher`. Introduce a composable `ThrottledWatchReceiver` to throttle filesystem events, coalescing affected paths among them. ### Testing Updated existing unit tests.github.com-openai-codex · daf5e584 · 2026-03-24
- 1.0ETV[codex] Add unsandboxed process exec API (#19040) ## Why App-server clients sometimes need argv-based local process execution while sandbox policy is controlled outside Codex. Those environments can reject sandbox-disabling paths before a command ever starts, even when the caller intentionally wants unsandboxed execution. This PR adds a distinct `process/*` API for that use case instead of extending `command/exec` with another sandbox-disabling shape. Keeping the new surface separate also makes the future removal of `command/exec` simpler: clients that need explicit process lifecycle control can move to the newer handle-based API without depending on `command/exec` business logic. ## What changed - Added v2 process lifecycle methods: `process/spawn`, `process/writeStdin`, `process/resizePty`, and `process/kill`. - Added process notifications: `process/outputDelta` for streamed stdout/stderr chunks and `process/exited` for final exit status and buffered output. - Made `process/spawn` intentionally unsandboxed and omitted sandbox-selection fields such as `sandboxPolicy` and `permissionProfile`. - Added client-supplied, connection-scoped `processHandle` values for follow-up control requests and notification routing. - Supported cwd, environment overrides, PTY mode and size, stdin streaming, stdout/stderr streaming, per-stream output caps, and timeout controls. - Killed active process sessions when the originating app-server connection closes. - Wired the implementation through the modular `request_processors/` app-server layout, with process-handle request serialization for follow-up control calls. - Updated generated JSON/TypeScript schema fixtures and documented the new API in `codex-rs/app-server/README.md`. - Added v2 app-server integration coverage in `codex-rs/app-server/tests/suite/v2/process_exec.rs` for spawn acknowledgement before exit, buffered output caps, and process termination. ## Verification - `cargo test -p codex-app-server-protocol` - `cargo test -p codex-app-server` --------- Co-authored-by: Owen Lin <owen@openai.com>github.com-openai-codex · 4950e7d8 · 2026-05-04
- 1.0ETVapp-server: move transport into dedicated crate (#20545) ## Why `codex-app-server` currently owns both request-processing code and transport implementation details. Splitting the transport layer into its own crate makes that boundary explicit, reduces the amount of transport-specific dependency surface carried by `codex-app-server`, and gives future transport work a narrower place to evolve. ## What changed - Added `codex-app-server-transport` and moved the existing transport tree into it, including stdio, unix socket, websocket, remote-control transport, and websocket auth. - Moved shared transport-facing message types into the new crate so both the transport implementation and `codex-app-server` use the same definitions. - Kept processor-facing connection state and outbound routing in `codex-app-server`, with the routing tests moved next to that local wrapper. - Updated workspace metadata, Bazel crate metadata, and `codex-app-server` dependencies for the new crate boundary. ## Validation - `cargo metadata --locked --no-deps` - `git diff --check` - Attempted `cargo test -p codex-app-server-transport`, `cargo test -p codex-app-server`, `just fix -p codex-app-server-transport`, and `just fix -p codex-app-server`; all were blocked before compilation by the existing `packageproxy` resolution failure for locked `rustls-webpki = 0.103.13`. - Attempted Bazel build / lockfile validation; those were blocked by external fetch failures against BuildBuddy / GitHub while resolving `v8`.github.com-openai-codex · 41e171fc · 2026-05-01
- 0.9ETVuds: add async Unix socket crate (#18254) ## Summary - add a codex-uds crate with async UnixListener and UnixStream wrappers - expose helpers for private socket directory setup and stale socket path checks - migrate codex-stdio-to-uds onto codex-uds and Tokio-based stdio/socket relaying - update the CLI stdio-to-uds command path for the async runner ## Tests - cargo test -p codex-uds -p codex-stdio-to-uds - cargo test -p codex-cli - just fmt - just fix -p codex-uds - just fix -p codex-stdio-to-uds - just fix -p codex-cli - just bazel-lock-check - git diff --checkgithub.com-openai-codex · 97d4b425 · 2026-04-20
- 0.8ETVapp-server: add filesystem watch support (#14533) ### Summary Add the v2 app-server filesystem watch RPCs and notifications, wire them through the message processor, and implement connection-scoped watches with notify-backed change delivery. This also updates the schema fixtures, app-server documentation, and the v2 integration coverage for watch and unwatch behavior. This allows clients to efficiently watch for filesystem updates, e.g. to react on branch changes. ### Testing - exercise watch lifecycles for directory changes, atomic file replacement, missing-file targets, and unwatch cleanupgithub.com-openai-codex · 301b17c2 · 2026-03-24
- 0.8ETVapp-server: run initialized rpcs with keyed serialization (#17373) ## Why Initialized app-server RPCs no longer need to bottleneck behind one request processor path. Running them concurrently improves responsiveness, but several request families still mutate shared state or depend on ordered side effects. Those stateful families need an auditable serialization contract so concurrency does not reorder thread, config, auth, command, watcher, MCP, or similar state transitions. This PR keeps that boundary explicit: stateful work is serialized by the smallest useful key, while intentionally read-only or externally concurrent work remains unkeyed. In particular, `thread/list` and `thread/turns/list` explicitly have no serialization because they primarily read append-only rollout storage and should continue to be served concurrently. ## What changed - Adds `ClientRequest::serialization_scope()` in `app-server-protocol` and requires every client request definition to declare its serialization behavior. - Introduces keyed request scopes for thread, thread path, command exec process, fuzzy search session, fs watch, MCP OAuth, and global state buckets such as config, account auth, memory, and device keys. - Routes initialized app-server RPCs through per-key FIFO serialization while allowing unkeyed initialized requests to run concurrently. - Cancels in-flight initialized RPC work when the connection disconnects or the app-server exits so spawned request tasks do not outlive their session. - Adds focused coverage for representative keyed and unkeyed serialization scopes, including explicitly concurrent `thread/turns/list` behavior. ## Validation - Added protocol tests for representative keyed serialization scopes and intentionally unkeyed request families. - Added app-server request serialization tests covering per-key FIFO behavior, concurrent unkeyed execution, disconnect shutdown, and config read-after-write ordering. - Local focused protocol validation after the latest rebase is currently blocked by packageproxy failing to resolve locked `rustls-webpki 0.103.13`; CI is expected to provide the full validation signal.github.com-openai-codex · 0700f979 · 2026-04-28
- 0.7ETVapp-server: notify clients of remote-control status changes (#19919) ## Why Remote-control app-server enrollments have both an internal server id and the environment id exposed to remote-control clients. App-server clients need one current status snapshot that says whether remote control is usable and which environment id, if any, is exposed. A temporary websocket disconnect is not itself an identity change. Account changes, stale enrollment invalidation, successful re-enrollment, and missing ChatGPT auth are meaningful status changes. Disabled remote control remains `disabled` regardless of auth or SQLite state. SQLite startup failure disablement and enrollment persistence failures are handled in #20068; this PR reports the resulting effective status to clients. ## What changed - Adds v2 `remoteControl/status/changed` carrying `state` and `environmentId`. - Adds `RemoteControlConnectionState` values: `disabled`, `connecting`, `connected`, and `errored`. - Exposes remote-control status updates through `RemoteControlHandle` using a Tokio watch channel. - Always sends the current remote-control status snapshot to newly initialized app-server clients. - Broadcasts status changes to initialized app-server clients when state or environment id changes. - Treats missing ChatGPT auth as an `errored` status while leaving it retryable because auth can change at runtime. - Clears `environmentId` when enrollment is cleared for account changes, auth loss, stale backend invalidation, or disabled remote control. - Updates app-server protocol schema fixtures, generated TypeScript, app-server README, remote-control tests, and TUI exhaustive notification matches. ## Stack - Builds on #20068. ## Verification - `just write-app-server-schema` - `cargo test -p codex-app-server-protocol` - `cargo test -p codex-app-server transport::remote_control --lib` - `cargo check -p codex-tui` - `just fix -p codex-app-server-protocol` - `just fix -p codex-app-server` - `just fix -p codex-tui`github.com-openai-codex · c6465c1e · 2026-04-28
- 0.7ETVapp-server: add Unix socket transport (#18255) ## Summary - add unix:// app-server transport backed by the shared codex-uds crate - reuse the websocket connection loop for axum and tungstenite-backed streams - add codex app-server proxy to bridge stdio clients to the control socket - tolerate Windows UDS backends that report a missing rendezvous path as connection refused before binding ## Tests - cargo test -p codex-app-server control_socket_acceptor_forwards_websocket_text_messages_and_pings - cargo test -p codex-app-server - just fmt - just fix -p codex-app-server - git -c core.fsmonitor=false diff --checkgithub.com-openai-codex · 8a0ab3fc · 2026-04-23
- 0.7ETVutils/pty: add streaming spawn and terminal sizing primitives (#13695) Enhance pty utils: * Support closing stdin * Separate stderr and stdout streams to allow consumers differentiate them * Provide compatibility helper to merge both streams back into combined one * Support specifying terminal size for pty, including on-demand resizes while process is already running * Support terminating the process while still consuming its outputsgithub.com-openai-codex · 5b04cc65 · 2026-03-06
- 0.7ETVapp-server: implement device key v2 methods (#18430) ## Why The device-key protocol needs an app-server implementation that keeps local key operations behind the same request-processing boundary as other v2 APIs. app-server owns request dispatch, transport policy, documentation, and JSON-RPC error shaping. `codex-device-key` owns key binding, validation, platform provider selection, and signing mechanics. Keeping the adapter thin makes the boundary easier to review and avoids moving local key-management details into thread orchestration code. ## What changed - Added `DeviceKeyApi` as the app-server adapter around `DeviceKeyStore`. - Converted protocol protection policies, payload variants, algorithms, and protection classes to and from the device-key crate types. - Encoded SPKI public keys and DER signatures as base64 protocol fields. - Routed `device/key/create`, `device/key/public`, and `device/key/sign` through `MessageProcessor`. - Rejected remote transports before provider access while allowing local `stdio` and in-process callers to reach the device-key API. - Added stdio, in-process, and websocket tests for device-key validation and transport policy. - Documented the device-key methods in the app-server v2 method list. ## Test coverage - `device_key_create_rejects_empty_account_user_id` - `in_process_allows_device_key_requests_to_reach_device_key_api` - `device_key_methods_are_rejected_over_websocket` ## Stack This is PR 3 of 4 in the device-key app-server stack. It is stacked on #18429. ## Validation - `cargo test -p codex-app-server device_key` - `just fix -p codex-app-server`github.com-openai-codex · 69c3d122 · 2026-04-21
- 0.6ETVapp-server: persist device key bindings in sqlite (#19206) ## Why Device-key providers should only own platform key material. The account/client binding used to authorize a signing payload is app-server state, and keeping that state in provider-specific metadata makes the same check harder to audit and harder to share across platform implementations. Persisting the binding in the shared state database gives the device-key crate a platform-neutral source of truth before it asks a provider to sign. It also lets app-server move potentially blocking key operations off the main message processor path, which matters once providers may wait for OS authentication prompts. ## What changed - Add a `device_key_bindings` state migration plus `StateRuntime` helpers keyed by `key_id`. - Add an async `DeviceKeyBindingStore` abstraction to `codex-device-key` and use it from `DeviceKeyStore::create` and `DeviceKeyStore::sign`. - Keep provider calls behind async store methods and run the synchronous provider work through `spawn_blocking`. - Wire app-server device-key RPC handling to the SQLite-backed binding store and spawn response/error delivery tasks for device-key requests. - Run the turn-start tracing test on the existing larger current-thread test harness after the larger async surface made the default test stack too small locally. ## Validation - `cargo test -p codex-device-key` - `cargo test -p codex-state device_key` - `cargo test -p codex-state` - `cargo test -p codex-app-server device_key` - `cargo test -p codex-app-server message_processor::tracing_tests::turn_start_jsonrpc_span_parents_core_turn_spans` - `cargo test -p codex-app-server` - `just fix -p codex-device-key` - `just fix -p codex-state` - `just fix -p codex-app-server` - `just bazel-lock-update` - `just bazel-lock-check` - `git diff --check`github.com-openai-codex · 19badb0b · 2026-04-24
- 0.5ETVapp-server: Only unload threads which were unused for some time (#17398) Currently app-server may unload actively running threads once the last connection disconnects, which is not expected. Instead track when was the last active turn & when there were any subscribers the last time, also add 30 minute idleness/no subscribers timer to reduce the churn.github.com-openai-codex · a5507b59 · 2026-04-13
- 0.5ETVapp-server: switch remote control to protocol v3 segmentation (#20341) ## Why Remote-control protocol v3 makes segmentation an explicit wire-level feature. The app-server transport needs to support that protocol directly so large messages can be chunked, acknowledged, replayed, and reassembled consistently. ## What changed - Bump the remote-control websocket protocol version from `2` to `3`. - Add explicit client/server chunk envelope variants plus chunk-aware acknowledgements. - Split oversized outbound server messages into bounded transport chunks. - Reassemble ordered inbound client chunks with bounded memory usage and stream/client invalidation handling. - Track inbound chunk cursors and outbound ack cursors as `(seq_id, segment_id)` so duplicate chunks and partial replays behave correctly. - Add focused coverage for chunk splitting, reassembly, duplicate suppression, and stream replacement behavior. ## Validation - Added targeted unit coverage for segmented message handling in `remote_control`. - Local validation is currently blocked before compilation because `packageproxy` does not serve the locked `rustls-webpki 0.103.13` dependency required by the workspace.github.com-openai-codex · 972b8192 · 2026-05-01
- 0.4ETVdaemon: refresh updater after validated binary rollout (#21853) ## Why `bootstrap` starts a detached pid-backed updater loop, but before this change that updater could keep running an old executable image even after `install.sh` replaced the managed standalone binary under `CODEX_HOME`. That left the updater itself behind the binary it had just rolled out, especially when the app-server was stopped or when the managed binary changed without a version-string change. ## What changed - Track updater identity from the executable contents rather than only the reported CLI version. - Force the managed app-server restart path when the managed binary contents differ from the running updater image, then re-exec the updater from the managed binary once the rollout is in a safe state. - Distinguish a genuinely absent managed app-server from a managed process that exists but is not yet probeable, so self-refresh does not skip a required restart. - Keep the restart/re-exec decision under the daemon operation lock so `bootstrap` cannot race the handoff. - Update `app-server-daemon/README.md` to document the resulting standalone and out-of-band update behavior. ## Verification - `cargo test -p codex-app-server-daemon` - `just fix -p codex-app-server-daemon` Added focused unit coverage for: - content-based updater refresh decisions - safe updater re-exec outcomes across restart statesgithub.com-openai-codex · e3f481da · 2026-05-11