tui: sync session permission profiles#18284
Conversation
dc15de8 to
ffac8a6
Compare
8b4d2a2 to
e5f2e57
Compare
## Why `Permissions` should not store a separate `PermissionProfile` that can drift from the constrained `SandboxPolicy` and network settings. The active profile needs to be derived from the same constrained values that already honor `requirements.toml`. ## What changed This adds derivation of the active `PermissionProfile` from the constrained runtime permission settings and exposes that derived value through config snapshots and thread state. The app-server can then report the active profile without introducing a second source of truth. ## Verification - `cargo test -p codex-core --test all permissions_messages -- --nocapture` - `cargo test -p codex-core --test all request_permissions -- --nocapture` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/18277). * #18288 * #18287 * #18286 * #18285 * #18284 * #18283 * #18282 * #18281 * #18280 * #18279 * #18278 * __->__ #18277
f8c3ebf to
c673808
Compare
37a49c3 to
d9bfa96
Compare
## Why `PermissionProfile` is becoming the canonical permissions shape shared by core and app-server. After app-server responses expose the active profile, clients need to be able to send that same shape back when starting, resuming, forking, or overriding a turn instead of translating through the legacy `sandbox`/`sandboxPolicy` shorthands. This still needs to preserve the existing requirements/platform enforcement model. A profile-shaped request can be downgraded or rejected by constraints, but the server should keep the user's elevated-access intent for project trust decisions. Turn-level profile overrides also need to retain existing read protections, including deny-read entries and bounded glob-scan metadata, so a permission override cannot accidentally drop configured protections such as `**/*.env = deny`. ## What changed - Adds optional `permissionProfile` request fields to `thread/start`, `thread/resume`, `thread/fork`, and `turn/start`. - Rejects ambiguous requests that specify both `permissionProfile` and the legacy `sandbox`/`sandboxPolicy` fields, including running-thread resume requests. - Converts profile-shaped overrides into core runtime filesystem/network permissions while continuing to derive the constrained legacy sandbox projection used by existing execution paths. - Preserves project-trust intent for profile overrides that are equivalent to workspace-write or full-access sandbox requests. - Preserves existing deny-read entries and `globScanMaxDepth` when applying turn-level `permissionProfile` overrides. - Updates app-server docs plus generated JSON/TypeScript schema fixtures and regression coverage. ## Verification - `cargo test -p codex-app-server-protocol schema_fixtures` - `cargo test -p codex-core session_configuration_apply_permission_profile_preserves_existing_deny_read_entries` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/18279). * #18288 * #18287 * #18286 * #18285 * #18284 * #18283 * #18282 * #18281 * #18280 * __->__ #18279
47f27ce to
50fffd0
Compare
|
[P1] Preserve runtime sandbox changes on embedded turns This issue still appears on the rebased stack, but Suggested small fix: when // config/chat sandbox setters, after the legacy sandbox_policy.set(...)
config.permissions.file_system_sandbox_policy =
FileSystemSandboxPolicy::from_legacy_sandbox_policy(
config.permissions.sandbox_policy.get(),
&config.cwd,
);
config.permissions.network_sandbox_policy =
NetworkSandboxPolicy::from(config.permissions.sandbox_policy.get());Then thread let permission_profile = if !app_server.is_remote()
&& self.runtime_sandbox_policy_override.is_some()
&& !matches!(sandbox_policy, SandboxPolicy::ExternalSandbox { .. })
{
Some(self.config.permissions.permission_profile())
} else {
None
};
|
|
[codex] Addressed on the current head ( |
Why
Once
SessionConfiguredcarries the activePermissionProfile, the TUI must treat that as authoritative session state. Otherwise the widget can keep stale local permission details after a session is configured or resumed.The TUI also keeps a local
Configcopy used for later operations, so session-sourced profiles and subsequent local sandbox changes need to keep the derived split runtime permissions in sync. Because this PR may land before the follow-up user-turn profile plumbing, embedded app-server turns also need a standalone path for carrying local runtime sandbox overrides.What changed
SessionConfigured.permission_profile, with the legacysandbox_policyas the fallback.permissionProfilefor embedded, non-ExternalSandbox turns when the TUI has a runtime sandbox override; remote and ExternalSandbox turns keep using the legacy sandbox field.Verification
cargo test -p codex-tui update_feature_flags_enabling_guardian_selects_auto_reviewcargo test -p codex-tui turn_start_permission_overrides_send_profiles_only_for_embedded_runtime_overridescargo test -p codex-tui permission_settings_synccargo test -p codex-tui session_configured_external_sandbox_keeps_external_runtime_policycargo test -p codex-tui session_configured_syncs_widget_config_permissions_and_cwdjust fix -p codex-tuiStack created with Sapling. Best reviewed with ReviewStack.