1use serde::{Deserialize, Serialize};
5use zeph_tools::AutonomyLevel;
6use zeph_tools::PreExecutionVerifierConfig;
7use zeph_tools::TrustLevel;
8
9use crate::defaults::default_true;
10use crate::rate_limit::RateLimitConfig;
11use crate::sanitizer::{
12 ContentIsolationConfig, ExfiltrationGuardConfig, MemoryWriteValidationConfig, PiiFilterConfig,
13 ResponseVerificationConfig,
14};
15
16#[cfg(feature = "guardrail")]
17use crate::sanitizer::GuardrailConfig;
18
19fn default_trust_default_level() -> TrustLevel {
20 TrustLevel::Quarantined
21}
22
23fn default_trust_local_level() -> TrustLevel {
24 TrustLevel::Trusted
25}
26
27fn default_trust_hash_mismatch_level() -> TrustLevel {
28 TrustLevel::Quarantined
29}
30
31fn default_llm_timeout() -> u64 {
32 120
33}
34
35fn default_embedding_timeout() -> u64 {
36 30
37}
38
39fn default_a2a_timeout() -> u64 {
40 30
41}
42
43fn default_max_parallel_tools() -> usize {
44 8
45}
46
47fn default_llm_request_timeout() -> u64 {
48 600
49}
50
51#[derive(Debug, Clone, Deserialize, Serialize)]
52pub struct TrustConfig {
53 #[serde(default = "default_trust_default_level")]
54 pub default_level: TrustLevel,
55 #[serde(default = "default_trust_local_level")]
56 pub local_level: TrustLevel,
57 #[serde(default = "default_trust_hash_mismatch_level")]
58 pub hash_mismatch_level: TrustLevel,
59 #[serde(default = "default_true")]
67 pub scan_on_load: bool,
68}
69
70impl Default for TrustConfig {
71 fn default() -> Self {
72 Self {
73 default_level: default_trust_default_level(),
74 local_level: default_trust_local_level(),
75 hash_mismatch_level: default_trust_hash_mismatch_level(),
76 scan_on_load: true,
77 }
78 }
79}
80
81#[derive(Debug, Clone, Deserialize, Serialize)]
82pub struct SecurityConfig {
83 #[serde(default = "default_true")]
84 pub redact_secrets: bool,
85 #[serde(default)]
86 pub autonomy_level: AutonomyLevel,
87 #[serde(default)]
88 pub content_isolation: ContentIsolationConfig,
89 #[serde(default)]
90 pub exfiltration_guard: ExfiltrationGuardConfig,
91 #[serde(default)]
93 pub memory_validation: MemoryWriteValidationConfig,
94 #[serde(default)]
96 pub pii_filter: PiiFilterConfig,
97 #[serde(default)]
99 pub rate_limit: RateLimitConfig,
100 #[serde(default)]
102 pub pre_execution_verify: PreExecutionVerifierConfig,
103 #[cfg(feature = "guardrail")]
105 #[serde(default)]
106 pub guardrail: GuardrailConfig,
107 #[serde(default)]
109 pub response_verification: ResponseVerificationConfig,
110}
111
112impl Default for SecurityConfig {
113 fn default() -> Self {
114 Self {
115 redact_secrets: true,
116 autonomy_level: AutonomyLevel::default(),
117 content_isolation: ContentIsolationConfig::default(),
118 exfiltration_guard: ExfiltrationGuardConfig::default(),
119 memory_validation: MemoryWriteValidationConfig::default(),
120 pii_filter: PiiFilterConfig::default(),
121 rate_limit: RateLimitConfig::default(),
122 pre_execution_verify: PreExecutionVerifierConfig::default(),
123 #[cfg(feature = "guardrail")]
124 guardrail: GuardrailConfig::default(),
125 response_verification: ResponseVerificationConfig::default(),
126 }
127 }
128}
129
130#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
131pub struct TimeoutConfig {
132 #[serde(default = "default_llm_timeout")]
133 pub llm_seconds: u64,
134 #[serde(default = "default_llm_request_timeout")]
135 pub llm_request_timeout_secs: u64,
136 #[serde(default = "default_embedding_timeout")]
137 pub embedding_seconds: u64,
138 #[serde(default = "default_a2a_timeout")]
139 pub a2a_seconds: u64,
140 #[serde(default = "default_max_parallel_tools")]
141 pub max_parallel_tools: usize,
142}
143
144impl Default for TimeoutConfig {
145 fn default() -> Self {
146 Self {
147 llm_seconds: default_llm_timeout(),
148 llm_request_timeout_secs: default_llm_request_timeout(),
149 embedding_seconds: default_embedding_timeout(),
150 a2a_seconds: default_a2a_timeout(),
151 max_parallel_tools: default_max_parallel_tools(),
152 }
153 }
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159
160 #[test]
161 fn trust_config_default_has_scan_on_load_true() {
162 let config = TrustConfig::default();
163 assert!(config.scan_on_load);
164 }
165
166 #[test]
167 fn trust_config_serde_roundtrip_with_scan_on_load() {
168 let config = TrustConfig {
169 default_level: TrustLevel::Quarantined,
170 local_level: TrustLevel::Trusted,
171 hash_mismatch_level: TrustLevel::Quarantined,
172 scan_on_load: false,
173 };
174 let toml = toml::to_string(&config).expect("serialize");
175 let deserialized: TrustConfig = toml::from_str(&toml).expect("deserialize");
176 assert!(!deserialized.scan_on_load);
177 }
178
179 #[test]
180 fn trust_config_missing_scan_on_load_defaults_to_true() {
181 let toml = r#"
182default_level = "quarantined"
183local_level = "trusted"
184hash_mismatch_level = "quarantined"
185"#;
186 let config: TrustConfig = toml::from_str(toml).expect("deserialize");
187 assert!(
188 config.scan_on_load,
189 "missing scan_on_load must default to true"
190 );
191 }
192}