mirror of
https://github.com/openai/codex.git
synced 2026-11-10 08:43:33 +00:00
Expose uncompiled permission profile selection (#39752)
## What changed - Add `resolve_permission_profile_selection` to select the effective profile using configured defaults, managed requirements, and allowlists. - Return the merged configured and managed profile catalog without compiling platform-specific paths, leaving path interpretation to the executor. ## Testing - Verify that a managed default overrides a configured default while preserving Windows-style paths. - Verify that an allowlisted but undefined profile is rejected. GitOrigin-RevId: 0172193d48f0346522f931d3b806054895d199c0
This commit is contained in:
1 parent
a26d50852a
commit
85a1b0e33d
3 files changed
+138
No files matched your search
@@ -159,6 +159,7 @@ mod managed_features;
|
|||||||
mod network_proxy_spec;
|
mod network_proxy_spec;
|
||||||
mod otel;
|
mod otel;
|
||||||
mod permission_profile_catalog;
|
mod permission_profile_catalog;
|
||||||
|
mod permission_profile_selection;
|
||||||
mod permissions;
|
mod permissions;
|
||||||
mod requirements;
|
mod requirements;
|
||||||
mod resolved_permission_profile;
|
mod resolved_permission_profile;
|
||||||
@@ -182,6 +183,8 @@ pub use permission_profile_catalog::permission_profile_catalog;
|
|||||||
use permission_profile_catalog::permission_profile_catalog_from_permissions;
|
use permission_profile_catalog::permission_profile_catalog_from_permissions;
|
||||||
use permission_profile_catalog::permission_profile_is_allowed;
|
use permission_profile_catalog::permission_profile_is_allowed;
|
||||||
use permission_profile_catalog::validate_permission_profile_for_deny_read;
|
use permission_profile_catalog::validate_permission_profile_for_deny_read;
|
||||||
|
pub use permission_profile_selection::ResolvedPermissionProfileSelection;
|
||||||
|
pub use permission_profile_selection::resolve_permission_profile_selection;
|
||||||
pub(crate) use permissions::is_builtin_permission_profile_name;
|
pub(crate) use permissions::is_builtin_permission_profile_name;
|
||||||
pub(crate) use resolved_permission_profile::PermissionProfileState;
|
pub(crate) use resolved_permission_profile::PermissionProfileState;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
use codex_config::ConfigRequirementsToml;
|
||||||
|
use codex_config::permissions_toml::PermissionsToml;
|
||||||
|
|
||||||
|
/// A selected permission profile and its uncompiled configured and managed catalog.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct ResolvedPermissionProfileSelection<'a> {
|
||||||
|
/// The effective profile selected by configuration and managed requirements.
|
||||||
|
pub profile_id: Option<&'a str>,
|
||||||
|
/// Configured and managed named profiles, without platform-specific compilation.
|
||||||
|
pub profiles: Option<PermissionsToml>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolves the effective permission profile without interpreting profile paths.
|
||||||
|
///
|
||||||
|
/// Managed profiles and allowlists are applied using Core's normal selection rules,
|
||||||
|
/// while the merged profile catalog remains uncompiled for the executor to interpret.
|
||||||
|
pub fn resolve_permission_profile_selection<'a>(
|
||||||
|
configured_profiles: Option<&PermissionsToml>,
|
||||||
|
configured_default_profile_id: Option<&'a str>,
|
||||||
|
requirements: &'a ConfigRequirementsToml,
|
||||||
|
) -> std::io::Result<ResolvedPermissionProfileSelection<'a>> {
|
||||||
|
let selection = super::resolve_effective_permission_selection(
|
||||||
|
configured_profiles,
|
||||||
|
/*default_permissions_override*/ None,
|
||||||
|
/*persisted_profile_id*/ None,
|
||||||
|
configured_default_profile_id,
|
||||||
|
requirements,
|
||||||
|
&mut Vec::new(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(ResolvedPermissionProfileSelection {
|
||||||
|
profile_id: selection.selected_profile_id,
|
||||||
|
profiles: selection.profiles,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[path = "permission_profile_selection_tests.rs"]
|
||||||
|
mod tests;
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
use crate::config::ResolvedPermissionProfileSelection;
|
||||||
|
use crate::config::resolve_permission_profile_selection;
|
||||||
|
use codex_config::ConfigRequirementsToml;
|
||||||
|
use codex_config::permissions_toml::PermissionsToml;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn resolves_managed_profile_without_compiling_executor_paths() -> anyhow::Result<()> {
|
||||||
|
let configured_profiles = toml::from_str::<PermissionsToml>(
|
||||||
|
r#"
|
||||||
|
[configured-windows]
|
||||||
|
extends = ":workspace"
|
||||||
|
|
||||||
|
[configured-windows.workspace_roots]
|
||||||
|
'C:\Users\agent\workspace' = true
|
||||||
|
|
||||||
|
[configured-windows.filesystem]
|
||||||
|
'C:\Users\agent\workspace' = "write"
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
let requirements = toml::from_str::<ConfigRequirementsToml>(
|
||||||
|
r#"
|
||||||
|
default_permissions = "managed-windows"
|
||||||
|
|
||||||
|
[allowed_permission_profiles]
|
||||||
|
configured-windows = false
|
||||||
|
managed-windows = true
|
||||||
|
|
||||||
|
[permissions.managed-windows.workspace_roots]
|
||||||
|
'D:\Managed\workspace' = true
|
||||||
|
|
||||||
|
[permissions.managed-windows.filesystem]
|
||||||
|
'D:\Managed\workspace' = "read"
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
let expected_profiles = PermissionsToml {
|
||||||
|
entries: BTreeMap::from([
|
||||||
|
(
|
||||||
|
"configured-windows".to_string(),
|
||||||
|
configured_profiles.entries["configured-windows"].clone(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"managed-windows".to_string(),
|
||||||
|
requirements
|
||||||
|
.permissions
|
||||||
|
.as_ref()
|
||||||
|
.expect("managed profiles should deserialize")
|
||||||
|
.profiles["managed-windows"]
|
||||||
|
.clone(),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
};
|
||||||
|
|
||||||
|
let resolved = resolve_permission_profile_selection(
|
||||||
|
Some(&configured_profiles),
|
||||||
|
Some("configured-windows"),
|
||||||
|
&requirements,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
resolved,
|
||||||
|
ResolvedPermissionProfileSelection {
|
||||||
|
profile_id: Some("managed-windows"),
|
||||||
|
profiles: Some(expected_profiles),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rejects_undefined_allowlisted_permission_profile() -> anyhow::Result<()> {
|
||||||
|
let requirements = toml::from_str::<ConfigRequirementsToml>(
|
||||||
|
r#"
|
||||||
|
default_permissions = "missing-profile"
|
||||||
|
|
||||||
|
[allowed_permission_profiles]
|
||||||
|
missing-profile = true
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let error = resolve_permission_profile_selection(
|
||||||
|
/*configured_profiles*/ None,
|
||||||
|
/*configured_default_profile_id*/ None,
|
||||||
|
&requirements,
|
||||||
|
)
|
||||||
|
.expect_err("undefined allowlisted profiles should be rejected");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
error.to_string(),
|
||||||
|
"requirements.toml allowed_permission_profiles refers to undefined profile `missing-profile`"
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Reference in new issue
Block a user