use serde::{Deserialize, Serialize};
use zeph_tools::AutonomyLevel;
use zeph_tools::PreExecutionVerifierConfig;
use zeph_tools::SkillTrustLevel;
use crate::defaults::default_true;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ScannerConfig {
#[serde(default = "default_true")]
pub injection_patterns: bool,
#[serde(default)]
pub capability_escalation_check: bool,
}
impl Default for ScannerConfig {
fn default() -> Self {
Self {
injection_patterns: true,
capability_escalation_check: false,
}
}
}
use crate::rate_limit::RateLimitConfig;
use crate::sanitizer::GuardrailConfig;
use crate::sanitizer::{
CausalIpiConfig, ContentIsolationConfig, ExfiltrationGuardConfig, MemoryWriteValidationConfig,
PiiFilterConfig, ResponseVerificationConfig,
};
fn default_trust_default_level() -> SkillTrustLevel {
SkillTrustLevel::Quarantined
}
fn default_trust_local_level() -> SkillTrustLevel {
SkillTrustLevel::Trusted
}
fn default_trust_hash_mismatch_level() -> SkillTrustLevel {
SkillTrustLevel::Quarantined
}
fn default_llm_timeout() -> u64 {
120
}
fn default_embedding_timeout() -> u64 {
30
}
fn default_a2a_timeout() -> u64 {
30
}
fn default_max_parallel_tools() -> usize {
8
}
fn default_llm_request_timeout() -> u64 {
600
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct TrustConfig {
#[serde(default = "default_trust_default_level")]
pub default_level: SkillTrustLevel,
#[serde(default = "default_trust_local_level")]
pub local_level: SkillTrustLevel,
#[serde(default = "default_trust_hash_mismatch_level")]
pub hash_mismatch_level: SkillTrustLevel,
#[serde(default = "default_true")]
pub scan_on_load: bool,
#[serde(default)]
pub scanner: ScannerConfig,
}
impl Default for TrustConfig {
fn default() -> Self {
Self {
default_level: default_trust_default_level(),
local_level: default_trust_local_level(),
hash_mismatch_level: default_trust_hash_mismatch_level(),
scan_on_load: true,
scanner: ScannerConfig::default(),
}
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct SecurityConfig {
#[serde(default = "default_true")]
pub redact_secrets: bool,
#[serde(default)]
pub autonomy_level: AutonomyLevel,
#[serde(default)]
pub content_isolation: ContentIsolationConfig,
#[serde(default)]
pub exfiltration_guard: ExfiltrationGuardConfig,
#[serde(default)]
pub memory_validation: MemoryWriteValidationConfig,
#[serde(default)]
pub pii_filter: PiiFilterConfig,
#[serde(default)]
pub rate_limit: RateLimitConfig,
#[serde(default)]
pub pre_execution_verify: PreExecutionVerifierConfig,
#[serde(default)]
pub guardrail: GuardrailConfig,
#[serde(default)]
pub response_verification: ResponseVerificationConfig,
#[serde(default)]
pub causal_ipi: CausalIpiConfig,
}
impl Default for SecurityConfig {
fn default() -> Self {
Self {
redact_secrets: true,
autonomy_level: AutonomyLevel::default(),
content_isolation: ContentIsolationConfig::default(),
exfiltration_guard: ExfiltrationGuardConfig::default(),
memory_validation: MemoryWriteValidationConfig::default(),
pii_filter: PiiFilterConfig::default(),
rate_limit: RateLimitConfig::default(),
pre_execution_verify: PreExecutionVerifierConfig::default(),
guardrail: GuardrailConfig::default(),
response_verification: ResponseVerificationConfig::default(),
causal_ipi: CausalIpiConfig::default(),
}
}
}
#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
pub struct TimeoutConfig {
#[serde(default = "default_llm_timeout")]
pub llm_seconds: u64,
#[serde(default = "default_llm_request_timeout")]
pub llm_request_timeout_secs: u64,
#[serde(default = "default_embedding_timeout")]
pub embedding_seconds: u64,
#[serde(default = "default_a2a_timeout")]
pub a2a_seconds: u64,
#[serde(default = "default_max_parallel_tools")]
pub max_parallel_tools: usize,
}
impl Default for TimeoutConfig {
fn default() -> Self {
Self {
llm_seconds: default_llm_timeout(),
llm_request_timeout_secs: default_llm_request_timeout(),
embedding_seconds: default_embedding_timeout(),
a2a_seconds: default_a2a_timeout(),
max_parallel_tools: default_max_parallel_tools(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn trust_config_default_has_scan_on_load_true() {
let config = TrustConfig::default();
assert!(config.scan_on_load);
}
#[test]
fn trust_config_serde_roundtrip_with_scan_on_load() {
let config = TrustConfig {
default_level: SkillTrustLevel::Quarantined,
local_level: SkillTrustLevel::Trusted,
hash_mismatch_level: SkillTrustLevel::Quarantined,
scan_on_load: false,
scanner: ScannerConfig::default(),
};
let toml = toml::to_string(&config).expect("serialize");
let deserialized: TrustConfig = toml::from_str(&toml).expect("deserialize");
assert!(!deserialized.scan_on_load);
}
#[test]
fn trust_config_missing_scan_on_load_defaults_to_true() {
let toml = r#"
default_level = "quarantined"
local_level = "trusted"
hash_mismatch_level = "quarantined"
"#;
let config: TrustConfig = toml::from_str(toml).expect("deserialize");
assert!(
config.scan_on_load,
"missing scan_on_load must default to true"
);
}
#[test]
fn scanner_config_defaults() {
let cfg = ScannerConfig::default();
assert!(cfg.injection_patterns);
assert!(!cfg.capability_escalation_check);
}
#[test]
fn scanner_config_serde_roundtrip() {
let cfg = ScannerConfig {
injection_patterns: false,
capability_escalation_check: true,
};
let toml = toml::to_string(&cfg).expect("serialize");
let back: ScannerConfig = toml::from_str(&toml).expect("deserialize");
assert!(!back.injection_patterns);
assert!(back.capability_escalation_check);
}
#[test]
fn trust_config_scanner_defaults_when_missing() {
let toml = r#"
default_level = "quarantined"
local_level = "trusted"
hash_mismatch_level = "quarantined"
"#;
let config: TrustConfig = toml::from_str(toml).expect("deserialize");
assert!(config.scanner.injection_patterns);
assert!(!config.scanner.capability_escalation_check);
}
}