tirea_contract/
scope.rs

1use crate::runtime::RunPolicy;
2
3/// Check whether an identifier is allowed by optional allow/deny lists.
4#[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/// Scope domains carried in [`RunPolicy`].
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum ScopeDomain {
22    Tool,
23    Skill,
24    Agent,
25}
26
27/// Check whether an identifier is allowed by the typed policy for a scope domain.
28#[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}