mirror of
https://github.com/openai/codex.git
synced 2026-10-24 18:18:41 +00:00
permissions: make SessionConfigured profile-only
This commit is contained in:
@@ -3538,7 +3538,7 @@ pub struct SessionNetworkProxyRuntime {
|
||||
pub socks_addr: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, TS)]
|
||||
#[derive(Debug, Clone, Serialize, JsonSchema, TS)]
|
||||
pub struct SessionConfiguredEvent {
|
||||
pub session_id: ThreadId,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
@@ -3566,16 +3566,8 @@ pub struct SessionConfiguredEvent {
|
||||
#[serde(default)]
|
||||
pub approvals_reviewer: ApprovalsReviewer,
|
||||
|
||||
/// Legacy sandbox projection for commands executed in the system.
|
||||
///
|
||||
/// Consumers should prefer `permission_profile` when it is present. This
|
||||
/// field remains available as a compatibility fallback for older emitters
|
||||
/// and sessions that only expose legacy sandbox state.
|
||||
pub sandbox_policy: SandboxPolicy,
|
||||
|
||||
/// Canonical effective permissions for commands executed in the session.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub permission_profile: Option<PermissionProfile>,
|
||||
pub permission_profile: PermissionProfile,
|
||||
|
||||
/// Working directory that should be treated as the *root* of the
|
||||
/// session.
|
||||
@@ -3606,6 +3598,67 @@ pub struct SessionConfiguredEvent {
|
||||
pub rollout_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for SessionConfiguredEvent {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
struct Wire {
|
||||
session_id: ThreadId,
|
||||
forked_from_id: Option<ThreadId>,
|
||||
#[serde(default)]
|
||||
thread_name: Option<String>,
|
||||
model: String,
|
||||
model_provider_id: String,
|
||||
service_tier: Option<ServiceTier>,
|
||||
approval_policy: AskForApproval,
|
||||
#[serde(default)]
|
||||
approvals_reviewer: ApprovalsReviewer,
|
||||
sandbox_policy: Option<SandboxPolicy>,
|
||||
permission_profile: Option<PermissionProfile>,
|
||||
cwd: AbsolutePathBuf,
|
||||
reasoning_effort: Option<ReasoningEffortConfig>,
|
||||
history_log_id: u64,
|
||||
history_entry_count: usize,
|
||||
initial_messages: Option<Vec<EventMsg>>,
|
||||
network_proxy: Option<SessionNetworkProxyRuntime>,
|
||||
rollout_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
let wire = Wire::deserialize(deserializer)?;
|
||||
let permission_profile = match (wire.permission_profile, wire.sandbox_policy) {
|
||||
(Some(permission_profile), _) => permission_profile,
|
||||
(None, Some(sandbox_policy)) => PermissionProfile::from_legacy_sandbox_policy_for_cwd(
|
||||
&sandbox_policy,
|
||||
wire.cwd.as_path(),
|
||||
),
|
||||
(None, None) => {
|
||||
return Err(serde::de::Error::missing_field("permission_profile"));
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
session_id: wire.session_id,
|
||||
forked_from_id: wire.forked_from_id,
|
||||
thread_name: wire.thread_name,
|
||||
model: wire.model,
|
||||
model_provider_id: wire.model_provider_id,
|
||||
service_tier: wire.service_tier,
|
||||
approval_policy: wire.approval_policy,
|
||||
approvals_reviewer: wire.approvals_reviewer,
|
||||
permission_profile,
|
||||
cwd: wire.cwd,
|
||||
reasoning_effort: wire.reasoning_effort,
|
||||
history_log_id: wire.history_log_id,
|
||||
history_entry_count: wire.history_entry_count,
|
||||
initial_messages: wire.initial_messages,
|
||||
network_proxy: wire.network_proxy,
|
||||
rollout_path: wire.rollout_path,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, TS)]
|
||||
pub struct ThreadNameUpdatedEvent {
|
||||
pub thread_id: ThreadId,
|
||||
@@ -5085,6 +5138,7 @@ mod tests {
|
||||
fn serialize_event() -> Result<()> {
|
||||
let conversation_id = ThreadId::from_string("67e55044-10b1-426f-9247-bb680e5fe0c8")?;
|
||||
let rollout_file = NamedTempFile::new()?;
|
||||
let permission_profile = PermissionProfile::read_only();
|
||||
let event = Event {
|
||||
id: "1234".to_string(),
|
||||
msg: EventMsg::SessionConfigured(SessionConfiguredEvent {
|
||||
@@ -5096,8 +5150,7 @@ mod tests {
|
||||
service_tier: None,
|
||||
approval_policy: AskForApproval::Never,
|
||||
approvals_reviewer: ApprovalsReviewer::User,
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: None,
|
||||
permission_profile: permission_profile.clone(),
|
||||
cwd: test_path_buf("/home/user/project").abs(),
|
||||
reasoning_effort: Some(ReasoningEffortConfig::default()),
|
||||
history_log_id: 0,
|
||||
@@ -5117,9 +5170,7 @@ mod tests {
|
||||
"model_provider_id": "openai",
|
||||
"approval_policy": "never",
|
||||
"approvals_reviewer": "user",
|
||||
"sandbox_policy": {
|
||||
"type": "read-only"
|
||||
},
|
||||
"permission_profile": permission_profile,
|
||||
"cwd": test_path_buf("/home/user/project"),
|
||||
"reasoning_effort": "medium",
|
||||
"history_log_id": 0,
|
||||
@@ -5131,6 +5182,28 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_legacy_session_configured_event_uses_sandbox_policy() -> Result<()> {
|
||||
let cwd = test_path_buf("/home/user/project");
|
||||
let value = json!({
|
||||
"session_id": "67e55044-10b1-426f-9247-bb680e5fe0c8",
|
||||
"model": "codex-mini-latest",
|
||||
"model_provider_id": "openai",
|
||||
"approval_policy": "never",
|
||||
"approvals_reviewer": "user",
|
||||
"sandbox_policy": {
|
||||
"type": "read-only"
|
||||
},
|
||||
"cwd": cwd,
|
||||
"history_log_id": 0,
|
||||
"history_entry_count": 0,
|
||||
});
|
||||
|
||||
let event: SessionConfiguredEvent = serde_json::from_value(value)?;
|
||||
assert_eq!(event.permission_profile, PermissionProfile::read_only());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_u8_as_base64_serialization_and_deserialization() -> Result<()> {
|
||||
let event = ExecCommandOutputDeltaEvent {
|
||||
|
||||
Reference in New Issue
Block a user