1use crate::runtime::RunPolicy;
2
3#[must_use]
5pub fn is_id_allowed(id: &str, allowed: Option<&[String]>, excluded: Option<&[String]>) -> bool {
6 if let Some(allowed) = allowed {
7 if !allowed.iter().any(|value| value == id) {
8 return false;
9 }
10 }
11 if let Some(excluded) = excluded {
12 if excluded.iter().any(|value| value == id) {
13 return false;
14 }
15 }
16 true
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum ScopeDomain {
22 Tool,
23 Skill,
24 Agent,
25}
26
27#[must_use]
29pub fn is_scope_allowed(policy: Option<&RunPolicy>, id: &str, domain: ScopeDomain) -> bool {
30 let (allowed, excluded) = match domain {
31 ScopeDomain::Tool => (
32 policy.and_then(RunPolicy::allowed_tools),
33 policy.and_then(RunPolicy::excluded_tools),
34 ),
35 ScopeDomain::Skill => (
36 policy.and_then(RunPolicy::allowed_skills),
37 policy.and_then(RunPolicy::excluded_skills),
38 ),
39 ScopeDomain::Agent => (
40 policy.and_then(RunPolicy::allowed_agents),
41 policy.and_then(RunPolicy::excluded_agents),
42 ),
43 };
44 is_id_allowed(id, allowed, excluded)
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50
51 #[test]
52 fn is_id_allowed_uses_allow_and_exclude_lists() {
53 let allowed = vec!["a".to_string(), "b".to_string()];
54 let excluded = vec!["b".to_string()];
55 assert!(is_id_allowed("a", Some(&allowed), Some(&excluded)));
56 assert!(!is_id_allowed("b", Some(&allowed), Some(&excluded)));
57 assert!(!is_id_allowed("c", Some(&allowed), Some(&excluded)));
58 }
59
60 #[test]
61 fn is_scope_allowed_reads_tool_filters_from_policy() {
62 let mut policy = RunPolicy::new();
63 policy.set_allowed_tools_if_absent(Some(&["a".to_string(), "b".to_string()]));
64 policy.set_excluded_tools_if_absent(Some(&["b".to_string()]));
65
66 assert!(is_scope_allowed(Some(&policy), "a", ScopeDomain::Tool));
67 assert!(!is_scope_allowed(Some(&policy), "b", ScopeDomain::Tool));
68 assert!(!is_scope_allowed(Some(&policy), "c", ScopeDomain::Tool));
69 }
70}