permissions: expose active profile metadata

This commit is contained in:
Michael Bolin
2026-04-28 17:42:35 -07:00
parent 1211a90a35
commit afbc30db0e
41 changed files with 665 additions and 1138 deletions
+28
View File
@@ -317,6 +317,34 @@ pub enum PermissionProfile {
External { network: NetworkSandboxPolicy },
}
/// Metadata for the named permissions profile that produced the active
/// `PermissionProfile`.
///
/// The runtime must honor `PermissionProfile`; this sidecar exists so clients
/// can display stable profile identity without trying to reverse-engineer a
/// name from the compiled permissions.
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ActivePermissionProfile {
/// Profile identifier from `default_permissions`, such as `:workspace` or a
/// user-defined `[permissions.<id>]` profile.
pub id: String,
/// Optional parent profile identifier once permissions profiles support
/// inheritance. This is always `None` until that config feature exists.
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional)]
pub extends: Option<String>,
}
impl ActivePermissionProfile {
pub fn new(id: impl Into<String>) -> Self {
Self {
id: id.into(),
extends: None,
}
}
}
impl Default for PermissionProfile {
fn default() -> Self {
Self::Managed {
+11
View File
@@ -33,6 +33,7 @@ use crate::mcp::ResourceTemplate as McpResourceTemplate;
use crate::mcp::Tool as McpTool;
use crate::memory_citation::MemoryCitation;
use crate::message_history::HistoryEntry;
use crate::models::ActivePermissionProfile;
use crate::models::BaseInstructions;
use crate::models::ContentItem;
use crate::models::MessagePhase;
@@ -3508,6 +3509,12 @@ pub struct SessionConfiguredEvent {
/// Canonical effective permissions for commands executed in the session.
pub permission_profile: PermissionProfile,
/// Named profile that produced `permission_profile`, when the active
/// permissions came from `default_permissions`.
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional)]
pub active_permission_profile: Option<ActivePermissionProfile>,
/// Working directory that should be treated as the *root* of the
/// session.
pub cwd: AbsolutePathBuf,
@@ -3559,6 +3566,8 @@ impl<'de> Deserialize<'de> for SessionConfiguredEvent {
// and immediately project it into the canonical `permission_profile`.
sandbox_policy: Option<SandboxPolicy>,
permission_profile: Option<PermissionProfile>,
#[serde(default)]
active_permission_profile: Option<ActivePermissionProfile>,
cwd: AbsolutePathBuf,
reasoning_effort: Option<ReasoningEffortConfig>,
history_log_id: u64,
@@ -3590,6 +3599,7 @@ impl<'de> Deserialize<'de> for SessionConfiguredEvent {
approval_policy: wire.approval_policy,
approvals_reviewer: wire.approvals_reviewer,
permission_profile,
active_permission_profile: wire.active_permission_profile,
cwd: wire.cwd,
reasoning_effort: wire.reasoning_effort,
history_log_id: wire.history_log_id,
@@ -5102,6 +5112,7 @@ mod tests {
approval_policy: AskForApproval::Never,
approvals_reviewer: ApprovalsReviewer::User,
permission_profile: permission_profile.clone(),
active_permission_profile: None,
cwd: test_path_buf("/home/user/project").abs(),
reasoning_effort: Some(ReasoningEffortConfig::default()),
history_log_id: 0,