Skip to main content

aa_core/
evaluators.rs

1//! Test-only [`PolicyEvaluator`](crate::policy::PolicyEvaluator) implementations.
2//!
3//! [`DenyAllEvaluator`] and [`PermitAllEvaluator`] let downstream crates
4//! write unit tests without building a real policy document or parser.
5//! Gated on the `test-utils` feature.
6
7/// Test-only policy evaluator that denies every action unconditionally.
8///
9/// Use `DenyAllEvaluator` in unit tests that need to assert denial paths
10/// without building a real policy document.
11#[cfg(all(feature = "alloc", feature = "test-utils"))]
12pub struct DenyAllEvaluator;
13
14#[cfg(all(feature = "alloc", feature = "test-utils"))]
15impl crate::policy::PolicyEvaluator for DenyAllEvaluator {
16    fn evaluate(
17        &self,
18        _ctx: &crate::AgentContext,
19        _action: &crate::policy::GovernanceAction,
20    ) -> crate::policy::PolicyResult {
21        crate::policy::PolicyResult::Deny {
22            reason: alloc::string::String::from("denied by DenyAllEvaluator"),
23        }
24    }
25
26    fn load_policy(&mut self, _policy: &crate::policy::PolicyDocument) -> Result<(), crate::policy::PolicyError> {
27        Ok(())
28    }
29
30    fn validate_policy(
31        &self,
32        _policy: &crate::policy::PolicyDocument,
33    ) -> Result<(), alloc::vec::Vec<crate::policy::PolicyError>> {
34        Ok(())
35    }
36}
37
38/// Test-only policy evaluator that permits every action unconditionally.
39///
40/// Use `PermitAllEvaluator` in unit tests that need a `PolicyEvaluator`
41/// but whose assertion target is not policy logic itself.
42#[cfg(all(feature = "alloc", feature = "test-utils"))]
43pub struct PermitAllEvaluator;
44
45#[cfg(all(feature = "alloc", feature = "test-utils"))]
46impl crate::policy::PolicyEvaluator for PermitAllEvaluator {
47    fn evaluate(
48        &self,
49        _ctx: &crate::AgentContext,
50        _action: &crate::policy::GovernanceAction,
51    ) -> crate::policy::PolicyResult {
52        crate::policy::PolicyResult::Allow
53    }
54
55    fn load_policy(&mut self, _policy: &crate::policy::PolicyDocument) -> Result<(), crate::policy::PolicyError> {
56        Ok(())
57    }
58
59    fn validate_policy(
60        &self,
61        _policy: &crate::policy::PolicyDocument,
62    ) -> Result<(), alloc::vec::Vec<crate::policy::PolicyError>> {
63        Ok(())
64    }
65}
66
67#[cfg(test)]
68#[cfg(all(feature = "alloc", feature = "test-utils"))]
69mod tests {
70    use super::*;
71    use crate::{
72        identity::{AgentId, SessionId},
73        policy::{GovernanceAction, PolicyEvaluator, PolicyResult},
74        AgentContext,
75    };
76
77    fn make_ctx() -> AgentContext {
78        AgentContext {
79            agent_id: AgentId::from_bytes([0u8; 16]),
80            session_id: SessionId::from_bytes([1u8; 16]),
81            pid: 42,
82            started_at: crate::time::Timestamp::from_nanos(0),
83            metadata: alloc::collections::BTreeMap::new(),
84            governance_level: crate::GovernanceLevel::default(),
85            parent_agent_id: None,
86            team_id: None,
87            depth: 0,
88            delegation_reason: None,
89            spawned_by_tool: None,
90            root_agent_id: None,
91        }
92    }
93
94    fn make_action() -> GovernanceAction {
95        GovernanceAction::ToolCall {
96            name: alloc::string::String::from("list_files"),
97            args: alloc::string::String::from("{}"),
98        }
99    }
100
101    #[test]
102    fn permit_all_returns_allow_for_every_action() {
103        let ctx = make_ctx();
104        let evaluator = PermitAllEvaluator;
105        assert_eq!(evaluator.evaluate(&ctx, &make_action()), PolicyResult::Allow);
106        assert_eq!(
107            evaluator.evaluate(
108                &ctx,
109                &GovernanceAction::FileAccess {
110                    path: alloc::string::String::from("/tmp"),
111                    mode: crate::policy::FileMode::Read,
112                }
113            ),
114            PolicyResult::Allow
115        );
116    }
117
118    #[test]
119    fn deny_all_returns_deny_for_every_action() {
120        let ctx = make_ctx();
121        let evaluator = DenyAllEvaluator;
122        let result = evaluator.evaluate(&ctx, &make_action());
123        assert!(matches!(result, PolicyResult::Deny { .. }));
124    }
125
126    #[test]
127    fn evaluators_are_object_safe() {
128        // Compile-time check: both types can be used as trait objects.
129        let _: &dyn PolicyEvaluator = &PermitAllEvaluator;
130        let _: &dyn PolicyEvaluator = &DenyAllEvaluator;
131    }
132}