The latest CLI base moved the dotenv update helpers into TUI-local code and trimmed the ProvisionedApiKey test fixture shape. Mirror those changes in tui_app_server so the rebased app-side /api-provision stack builds cleanly again.
Validation:
- cargo test -p codex-app-server-protocol
- cargo test -p codex-tui-app-server
- cargo test -p codex-app-server --test all suite::v2::turn_interrupt::turn_interrupt_aborts_running_turn -- --exact --nocapture
- cargo test -p codex-app-server --test all suite::v2::account::login_account_ephemeral_api_key_succeeds_and_does_not_write_auth_json -- --exact
Known failing checks in this environment:
- cargo test -p codex-app-server (fails only websocket_transport_ctrl_c_* graceful-shutdown tests)
- cargo test -p codex-app-server --test all suite::v2::connection_handling_websocket_unix::websocket_transport_ctrl_c_waits_for_running_turn_before_exit -- --exact --nocapture
- cargo test -p codex-app-server --test all suite::v2::connection_handling_websocket_unix::websocket_transport_second_ctrl_c_forces_exit_while_turn_running -- --exact --nocapture
Co-authored-by: Codex <noreply@openai.com>
Wire the app-backed UI through a new internal ephemeral API-key login path so /api-provision can reuse the browser provisioning flow, persist OPENAI_API_KEY to .env, and hot-apply the key without writing auth.json.
Co-authored-by: Codex <noreply@openai.com>
(cherry picked from commit e7d7aebb48)
Use the Hydra-registered localhost:5000 redirect URI for project API key
creation, but fail fast on port conflicts instead of sending /cancel to a
potentially unrelated local service.
Validation:
- cargo test -p codex-login
- just fmt
- just fix -p codex-login
- just argument-comment-lint
Co-authored-by: Codex <noreply@openai.com>
Move the TUI slash command into the chatwidget module and rename the login helper module to match API provisioning behavior.
Co-authored-by: Codex <noreply@openai.com>
Move the reusable authorization-code callback server into codex-login::server, switch api-provision over to the shared PKCE/state/callback flow, and keep the TUI browser path alive even when auto-open fails.
Validation:
- cargo check -p codex-login --lib
- cargo fmt --all --manifest-path /home/dev-user/code/codex/codex-rs/Cargo.toml
- git diff --check
Co-authored-by: Codex <noreply@openai.com>
Skip redundant cargo-home cache saves in Windows test jobs to avoid post-test timeouts, and add the required argument comments in the login OAuth helper.
Co-authored-by: Codex <noreply@openai.com>
Skip /api-provision when the current Codex process already inherited
OPENAI_API_KEY, and otherwise persist the provisioned key to .env under
OPENAI_API_KEY instead of CODEX_API_KEY.
Validation:
- cargo test -p codex-login
- cargo test -p codex-tui
- just fix -p codex-login
- just fix -p codex-tui
- just fmt
Co-authored-by: Codex <noreply@openai.com>
Extract the browser-based provisioning flow from codex-login so the plain TUI can
reuse it. Add /api-provision to the CLI, persist CODEX_API_KEY to .env, and
hot-apply the key via ephemeral auth without touching auth.json.
Validation:
- cargo test -p codex-login
- cargo test -p codex-tui
- just fix -p codex-login
- just fix -p codex-tui
- just fmt
Co-authored-by: Codex <noreply@openai.com>
## Why
`SandboxCommand.program` represents an executable path, but keeping it
as `String` forced path-backed callers to run `to_string_lossy()` before
the sandbox layer ever touched the command. That loses fidelity earlier
than necessary and adds avoidable conversions in runtimes that already
have a `PathBuf`.
## What changed
- Changed `SandboxCommand.program` to `OsString`.
- Updated `SandboxManager::transform` to keep the program and argv in
`OsString` form until the `SandboxExecRequest` conversion boundary.
- Switched the path-backed `apply_patch` and `js_repl` runtimes to pass
`into_os_string()` instead of `to_string_lossy()`.
- Updated the remaining string-backed builders and tests to match the
new type while preserving the existing Linux helper `arg0` behavior.
## Verification
- `cargo test -p codex-sandboxing`
- `just argument-comment-lint -p codex-core -p codex-sandboxing`
- `cargo test -p codex-core` currently fails in unrelated existing
config tests: `config::tests::approvals_reviewer_*` and
`config::tests::smart_approvals_alias_*`
## Why
`token_data` is owned by `codex-login`, but `codex-core` was still
re-exporting it. That let callers pull auth token types through
`codex-core`, which keeps otherwise unrelated crates coupled to
`codex-core` and makes `codex-core` more of a build-graph bottleneck.
## What changed
- remove the `codex-core` re-export of `codex_login::token_data`
- update the remaining `codex-core` internals that used
`crate::token_data` to import `codex_login::token_data` directly
- update downstream callers in `codex-rs/chatgpt`,
`codex-rs/tui_app_server`, `codex-rs/app-server/tests/common`, and
`codex-rs/core/tests` to import `codex_login::token_data` directly
- add explicit `codex-login` workspace dependencies and refresh lock
metadata for crates that now depend on it directly
## Validation
- `cargo test -p codex-chatgpt --locked`
- `just argument-comment-lint`
- `just bazel-lock-update`
- `just bazel-lock-check`
## Notes
- attempted `cargo test -p codex-core --locked` and `cargo test -p
codex-core auth_refresh --locked`, but both ran out of disk while
linking `codex-core` test binaries in the local environment
## Problem
Codex already treated an existing top-level project `./.codex` directory
as protected, but there was a gap on first creation.
If `./.codex` did not exist yet, a turn could create files under it,
such as `./.codex/config.toml`, without going through the same approval
path as later modifications. That meant the initial write could bypass
the intended protection for project-local Codex state.
## What this changes
This PR closes that first-creation gap in the Unix enforcement layers:
- `codex-protocol`
- treat the top-level project `./.codex` path as a protected carveout
even when it does not exist yet
- avoid injecting the default carveout when the user already has an
explicit rule for that exact path
- macOS Seatbelt
- deny writes to both the exact protected path and anything beneath it,
so creating `./.codex` itself is blocked in addition to writes inside it
- Linux bubblewrap
- preserve the same protected-path behavior for first-time creation
under `./.codex`
- tests
- add protocol regressions for missing `./.codex` and explicit-rule
collisions
- add Unix sandbox coverage for blocking first-time `./.codex` creation
- tighten Seatbelt policy assertions around excluded subpaths
## Scope
This change is intentionally scoped to protecting the top-level project
`.codex` subtree from agent writes.
It does not make `.codex` unreadable, and it does not change the product
behavior around loading project skills from `.codex` when project config
is untrusted.
## Why this shape
The fix is pointed rather than broad:
- it preserves the current model of “project `.codex` is protected from
writes”
- it closes the security-relevant first-write hole
- it avoids folding a larger permissions-model redesign into this PR
## Validation
- `cargo test -p codex-protocol`
- `cargo test -p codex-sandboxing seatbelt`
- `cargo test -p codex-exec --test all
sandbox_blocks_first_time_dot_codex_creation -- --nocapture`
---------
Co-authored-by: Michael Bolin <mbolin@openai.com>
## Why
Skill metadata accepted a `permissions` block and stored the result on
`SkillMetadata`, but that data was never consumed by runtime behavior.
Leaving the dead parsing path in place makes it look like skills can
widen or otherwise influence execution permissions when, in practice,
declared skill permissions are ignored.
This change removes that misleading surface area so the skill metadata
model matches what the system actually uses.
## What changed
- removed `permission_profile` and `managed_network_override` from
`core-skills::SkillMetadata`
- stopped parsing `permissions` from skill metadata in
`core-skills/src/loader.rs`
- deleted the loader tests that only exercised the removed permissions
parsing path
- cleaned up dependent `SkillMetadata` constructors in tests and TUI
code that were only carrying `None` for those fields
## Testing
- `cargo test -p codex-core-skills`
- `cargo test -p codex-tui
submission_prefers_selected_duplicate_skill_path`
- `just argument-comment-lint`