agentzero_core/security/
policy.rs1use std::str::FromStr;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum RiskTier {
5 P0Critical,
6 P1High,
7 P2Moderate,
8}
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum RiskDomain {
12 ToolExecution,
13 ProviderNetwork,
14 ChannelIngress,
15 RemoteMemory,
16 PrivacyRelay,
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub struct RequiredControls {
21 pub deny_by_default: bool,
22 pub requires_explicit_allowlist: bool,
23 pub requires_redaction: bool,
24 pub requires_timeout: bool,
25}
26
27impl FromStr for RiskDomain {
28 type Err = String;
29
30 fn from_str(value: &str) -> Result<Self, Self::Err> {
31 match value {
32 "tool_execution" => Ok(Self::ToolExecution),
33 "provider_network" => Ok(Self::ProviderNetwork),
34 "channel_ingress" => Ok(Self::ChannelIngress),
35 "remote_memory" => Ok(Self::RemoteMemory),
36 "privacy_relay" => Ok(Self::PrivacyRelay),
37 other => Err(format!("unsupported risk domain: {other}")),
38 }
39 }
40}
41
42pub fn baseline_version() -> &'static str {
43 "2026-02-27"
44}
45
46pub fn tier_for(domain: RiskDomain) -> RiskTier {
47 match domain {
48 RiskDomain::ToolExecution => RiskTier::P0Critical,
49 RiskDomain::ChannelIngress => RiskTier::P0Critical,
50 RiskDomain::ProviderNetwork => RiskTier::P1High,
51 RiskDomain::RemoteMemory => RiskTier::P1High,
52 RiskDomain::PrivacyRelay => RiskTier::P1High,
53 }
54}
55
56pub fn controls_for(domain: RiskDomain) -> RequiredControls {
57 match domain {
58 RiskDomain::ToolExecution => RequiredControls {
59 deny_by_default: true,
60 requires_explicit_allowlist: true,
61 requires_redaction: true,
62 requires_timeout: true,
63 },
64 RiskDomain::ChannelIngress => RequiredControls {
65 deny_by_default: true,
66 requires_explicit_allowlist: true,
67 requires_redaction: true,
68 requires_timeout: true,
69 },
70 RiskDomain::ProviderNetwork => RequiredControls {
71 deny_by_default: false,
72 requires_explicit_allowlist: false,
73 requires_redaction: true,
74 requires_timeout: true,
75 },
76 RiskDomain::RemoteMemory => RequiredControls {
77 deny_by_default: false,
78 requires_explicit_allowlist: false,
79 requires_redaction: true,
80 requires_timeout: true,
81 },
82 RiskDomain::PrivacyRelay => RequiredControls {
83 deny_by_default: true,
84 requires_explicit_allowlist: true,
85 requires_redaction: true,
86 requires_timeout: true,
87 },
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use super::{controls_for, tier_for, RiskDomain, RiskTier};
94 use std::str::FromStr;
95
96 #[test]
97 fn policy_marks_tool_execution_as_critical() {
98 assert_eq!(tier_for(RiskDomain::ToolExecution), RiskTier::P0Critical);
99 assert!(controls_for(RiskDomain::ToolExecution).deny_by_default);
100 }
101
102 #[test]
103 fn parsing_unknown_domain_fails() {
104 let parse = RiskDomain::from_str("unknown-domain");
105 assert!(parse.is_err());
106 }
107
108 #[test]
109 fn privacy_relay_domain_is_high_risk_with_deny_by_default() {
110 assert_eq!(tier_for(RiskDomain::PrivacyRelay), RiskTier::P1High);
111 let controls = controls_for(RiskDomain::PrivacyRelay);
112 assert!(controls.deny_by_default);
113 assert!(controls.requires_explicit_allowlist);
114 assert!(controls.requires_redaction);
115 assert!(controls.requires_timeout);
116 }
117
118 #[test]
119 fn privacy_relay_domain_parses_from_string() {
120 let domain = RiskDomain::from_str("privacy_relay").unwrap();
121 assert_eq!(domain, RiskDomain::PrivacyRelay);
122 }
123}