1use serde::{Deserialize, Serialize};
5use zeph_tools::AutonomyLevel;
6use zeph_tools::PreExecutionVerifierConfig;
7use zeph_tools::TrustLevel;
8
9use crate::defaults::default_true;
10
11#[derive(Debug, Clone, Deserialize, Serialize)]
15pub struct ScannerConfig {
16 #[serde(default = "default_true")]
22 pub injection_patterns: bool,
23 #[serde(default)]
28 pub capability_escalation_check: bool,
29}
30
31impl Default for ScannerConfig {
32 fn default() -> Self {
33 Self {
34 injection_patterns: true,
35 capability_escalation_check: false,
36 }
37 }
38}
39use crate::rate_limit::RateLimitConfig;
40use crate::sanitizer::{
41 CausalIpiConfig, ContentIsolationConfig, ExfiltrationGuardConfig, MemoryWriteValidationConfig,
42 PiiFilterConfig, ResponseVerificationConfig,
43};
44
45#[cfg(feature = "guardrail")]
46use crate::sanitizer::GuardrailConfig;
47
48fn default_trust_default_level() -> TrustLevel {
49 TrustLevel::Quarantined
50}
51
52fn default_trust_local_level() -> TrustLevel {
53 TrustLevel::Trusted
54}
55
56fn default_trust_hash_mismatch_level() -> TrustLevel {
57 TrustLevel::Quarantined
58}
59
60fn default_llm_timeout() -> u64 {
61 120
62}
63
64fn default_embedding_timeout() -> u64 {
65 30
66}
67
68fn default_a2a_timeout() -> u64 {
69 30
70}
71
72fn default_max_parallel_tools() -> usize {
73 8
74}
75
76fn default_llm_request_timeout() -> u64 {
77 600
78}
79
80#[derive(Debug, Clone, Deserialize, Serialize)]
81pub struct TrustConfig {
82 #[serde(default = "default_trust_default_level")]
83 pub default_level: TrustLevel,
84 #[serde(default = "default_trust_local_level")]
85 pub local_level: TrustLevel,
86 #[serde(default = "default_trust_hash_mismatch_level")]
87 pub hash_mismatch_level: TrustLevel,
88 #[serde(default = "default_true")]
96 pub scan_on_load: bool,
97 #[serde(default)]
99 pub scanner: ScannerConfig,
100}
101
102impl Default for TrustConfig {
103 fn default() -> Self {
104 Self {
105 default_level: default_trust_default_level(),
106 local_level: default_trust_local_level(),
107 hash_mismatch_level: default_trust_hash_mismatch_level(),
108 scan_on_load: true,
109 scanner: ScannerConfig::default(),
110 }
111 }
112}
113
114#[derive(Debug, Clone, Deserialize, Serialize)]
115pub struct SecurityConfig {
116 #[serde(default = "default_true")]
117 pub redact_secrets: bool,
118 #[serde(default)]
119 pub autonomy_level: AutonomyLevel,
120 #[serde(default)]
121 pub content_isolation: ContentIsolationConfig,
122 #[serde(default)]
123 pub exfiltration_guard: ExfiltrationGuardConfig,
124 #[serde(default)]
126 pub memory_validation: MemoryWriteValidationConfig,
127 #[serde(default)]
129 pub pii_filter: PiiFilterConfig,
130 #[serde(default)]
132 pub rate_limit: RateLimitConfig,
133 #[serde(default)]
135 pub pre_execution_verify: PreExecutionVerifierConfig,
136 #[cfg(feature = "guardrail")]
138 #[serde(default)]
139 pub guardrail: GuardrailConfig,
140 #[serde(default)]
142 pub response_verification: ResponseVerificationConfig,
143 #[serde(default)]
145 pub causal_ipi: CausalIpiConfig,
146}
147
148impl Default for SecurityConfig {
149 fn default() -> Self {
150 Self {
151 redact_secrets: true,
152 autonomy_level: AutonomyLevel::default(),
153 content_isolation: ContentIsolationConfig::default(),
154 exfiltration_guard: ExfiltrationGuardConfig::default(),
155 memory_validation: MemoryWriteValidationConfig::default(),
156 pii_filter: PiiFilterConfig::default(),
157 rate_limit: RateLimitConfig::default(),
158 pre_execution_verify: PreExecutionVerifierConfig::default(),
159 #[cfg(feature = "guardrail")]
160 guardrail: GuardrailConfig::default(),
161 response_verification: ResponseVerificationConfig::default(),
162 causal_ipi: CausalIpiConfig::default(),
163 }
164 }
165}
166
167#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
168pub struct TimeoutConfig {
169 #[serde(default = "default_llm_timeout")]
170 pub llm_seconds: u64,
171 #[serde(default = "default_llm_request_timeout")]
172 pub llm_request_timeout_secs: u64,
173 #[serde(default = "default_embedding_timeout")]
174 pub embedding_seconds: u64,
175 #[serde(default = "default_a2a_timeout")]
176 pub a2a_seconds: u64,
177 #[serde(default = "default_max_parallel_tools")]
178 pub max_parallel_tools: usize,
179}
180
181impl Default for TimeoutConfig {
182 fn default() -> Self {
183 Self {
184 llm_seconds: default_llm_timeout(),
185 llm_request_timeout_secs: default_llm_request_timeout(),
186 embedding_seconds: default_embedding_timeout(),
187 a2a_seconds: default_a2a_timeout(),
188 max_parallel_tools: default_max_parallel_tools(),
189 }
190 }
191}
192
193#[cfg(test)]
194mod tests {
195 use super::*;
196
197 #[test]
198 fn trust_config_default_has_scan_on_load_true() {
199 let config = TrustConfig::default();
200 assert!(config.scan_on_load);
201 }
202
203 #[test]
204 fn trust_config_serde_roundtrip_with_scan_on_load() {
205 let config = TrustConfig {
206 default_level: TrustLevel::Quarantined,
207 local_level: TrustLevel::Trusted,
208 hash_mismatch_level: TrustLevel::Quarantined,
209 scan_on_load: false,
210 scanner: ScannerConfig::default(),
211 };
212 let toml = toml::to_string(&config).expect("serialize");
213 let deserialized: TrustConfig = toml::from_str(&toml).expect("deserialize");
214 assert!(!deserialized.scan_on_load);
215 }
216
217 #[test]
218 fn trust_config_missing_scan_on_load_defaults_to_true() {
219 let toml = r#"
220default_level = "quarantined"
221local_level = "trusted"
222hash_mismatch_level = "quarantined"
223"#;
224 let config: TrustConfig = toml::from_str(toml).expect("deserialize");
225 assert!(
226 config.scan_on_load,
227 "missing scan_on_load must default to true"
228 );
229 }
230
231 #[test]
232 fn scanner_config_defaults() {
233 let cfg = ScannerConfig::default();
234 assert!(cfg.injection_patterns);
235 assert!(!cfg.capability_escalation_check);
236 }
237
238 #[test]
239 fn scanner_config_serde_roundtrip() {
240 let cfg = ScannerConfig {
241 injection_patterns: false,
242 capability_escalation_check: true,
243 };
244 let toml = toml::to_string(&cfg).expect("serialize");
245 let back: ScannerConfig = toml::from_str(&toml).expect("deserialize");
246 assert!(!back.injection_patterns);
247 assert!(back.capability_escalation_check);
248 }
249
250 #[test]
251 fn trust_config_scanner_defaults_when_missing() {
252 let toml = r#"
253default_level = "quarantined"
254local_level = "trusted"
255hash_mismatch_level = "quarantined"
256"#;
257 let config: TrustConfig = toml::from_str(toml).expect("deserialize");
258 assert!(config.scanner.injection_patterns);
259 assert!(!config.scanner.capability_escalation_check);
260 }
261}