chore: add a separate reject-policy flag for skill approvals (#14271)

## Summary
- add `skill_approval` to `RejectConfig` and the app-server v2
`AskForApproval::Reject` payload so skill-script prompts can be
configured independently from sandbox and rule-based prompts
- update Unix shell escalation to reject prompts based on the actual
decision source, keeping prefix rules tied to `rules`, unmatched command
fallbacks tied to `sandbox_approval`, and skill scripts tied to
`skill_approval`
- regenerate the affected protocol/config schemas and expand
unit/integration coverage for the new flag and skill approval behavior
This commit is contained in:
Celia Chen
2026-03-10 16:58:23 -07:00
committed by Michael Bolin
parent 83b22bb612
commit c1a424691f
29 changed files with 346 additions and 12 deletions

View File

@@ -533,6 +533,9 @@ pub struct RejectConfig {
pub sandbox_approval: bool,
/// Reject prompts triggered by execpolicy `prompt` rules.
pub rules: bool,
/// Reject approval prompts triggered by skill script execution.
#[serde(default)]
pub skill_approval: bool,
/// Reject approval prompts related to built-in permission requests.
#[serde(default)]
pub request_permissions: bool,
@@ -549,6 +552,10 @@ impl RejectConfig {
self.rules
}
pub const fn rejects_skill_approval(self) -> bool {
self.skill_approval
}
pub const fn rejects_request_permissions(self) -> bool {
self.request_permissions
}
@@ -3457,6 +3464,7 @@ mod tests {
RejectConfig {
sandbox_approval: false,
rules: false,
skill_approval: false,
request_permissions: false,
mcp_elicitations: true,
}
@@ -3466,6 +3474,7 @@ mod tests {
!RejectConfig {
sandbox_approval: false,
rules: false,
skill_approval: false,
request_permissions: false,
mcp_elicitations: false,
}
@@ -3473,12 +3482,37 @@ mod tests {
);
}
#[test]
fn reject_config_skill_approval_flag_is_field_driven() {
assert!(
RejectConfig {
sandbox_approval: false,
rules: false,
skill_approval: true,
request_permissions: false,
mcp_elicitations: false,
}
.rejects_skill_approval()
);
assert!(
!RejectConfig {
sandbox_approval: false,
rules: false,
skill_approval: false,
request_permissions: false,
mcp_elicitations: false,
}
.rejects_skill_approval()
);
}
#[test]
fn reject_config_request_permissions_flag_is_field_driven() {
assert!(
RejectConfig {
sandbox_approval: false,
rules: false,
skill_approval: false,
request_permissions: true,
mcp_elicitations: false,
}
@@ -3488,6 +3522,7 @@ mod tests {
!RejectConfig {
sandbox_approval: false,
rules: false,
skill_approval: false,
request_permissions: false,
mcp_elicitations: false,
}
@@ -3496,7 +3531,7 @@ mod tests {
}
#[test]
fn reject_config_defaults_missing_request_permissions_to_false() {
fn reject_config_defaults_missing_optional_flags_to_false() {
let decoded = serde_json::from_value::<RejectConfig>(serde_json::json!({
"sandbox_approval": true,
"rules": false,
@@ -3509,6 +3544,7 @@ mod tests {
RejectConfig {
sandbox_approval: true,
rules: false,
skill_approval: false,
request_permissions: false,
mcp_elicitations: true,
}