1pub mod clone_suite;
17pub mod bloat_suite;
18pub mod noise_suite;
19pub mod adversarial_orchestrator;
20pub mod stress_harness;
21
22pub use clone_suite::{CloneSuite, CloneTestConfig, CloneResult};
23pub use bloat_suite::{BloatSuite, BloatTestConfig, BloatResult};
24pub use noise_suite::{NoiseSuite, NoiseTestConfig, NoiseResult};
25pub use adversarial_orchestrator::{AdversarialOrchestrator, AdversarialConfig};
26pub use stress_harness::{StressHarness, StressResult};
27
28use anyhow::Result;
29use serde::{Deserialize, Serialize};
30use std::collections::HashMap;
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct AdversarialAuditResult {
35 pub clone_results: CloneResult,
36 pub bloat_results: BloatResult,
37 pub noise_results: NoiseResult,
38 pub overall_metrics: OverallMetrics,
39 pub gate_validation: GateValidation,
40 pub stress_profile: StressProfile,
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize)]
45pub struct OverallMetrics {
46 pub span_coverage_pct: f32,
47 pub sla_recall_at_50: f32,
48 pub p99_latency_ms: f32,
49 pub p95_latency_ms: f32,
50 pub degradation_factor: f32,
51 pub robustness_score: f32,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct GateValidation {
57 pub span_coverage_gate: bool, pub sla_recall_gate: bool, pub latency_stability_gate: bool, pub overall_pass: bool,
61 pub violations: Vec<String>,
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize)]
66pub struct StressProfile {
67 pub memory_peak_mb: f32,
68 pub cpu_utilization_pct: f32,
69 pub disk_io_ops_per_sec: f32,
70 pub network_bandwidth_mbps: f32,
71 pub gc_pressure_score: f32,
72 pub resource_exhaustion_risk: RiskLevel,
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
76pub enum RiskLevel {
77 Low,
78 Medium,
79 High,
80 Critical,
81}
82
83pub fn validate_adversarial_gates(result: &AdversarialAuditResult) -> Result<bool> {
85 const SPAN_COVERAGE_THRESHOLD: f32 = 100.0;
86 const LATENCY_STABILITY_RATIO: f32 = 2.0;
87 const MIN_SLA_RECALL: f32 = 0.50; let mut violations = Vec::new();
90 let metrics = &result.overall_metrics;
91
92 let span_gate = metrics.span_coverage_pct >= SPAN_COVERAGE_THRESHOLD;
94 if !span_gate {
95 violations.push(format!(
96 "Span coverage gate failed: {:.1}% < {:.1}% required",
97 metrics.span_coverage_pct, SPAN_COVERAGE_THRESHOLD
98 ));
99 }
100
101 let sla_recall_gate = metrics.sla_recall_at_50 >= MIN_SLA_RECALL;
103 if !sla_recall_gate {
104 violations.push(format!(
105 "SLA-Recall@50 gate failed: {:.3} < {:.3} required",
106 metrics.sla_recall_at_50, MIN_SLA_RECALL
107 ));
108 }
109
110 let latency_ratio = metrics.p99_latency_ms / metrics.p95_latency_ms;
112 let latency_gate = latency_ratio <= LATENCY_STABILITY_RATIO;
113 if !latency_gate {
114 violations.push(format!(
115 "Latency stability gate failed: p99/p95 = {:.2} > {:.1} allowed",
116 latency_ratio, LATENCY_STABILITY_RATIO
117 ));
118 }
119
120 let overall_pass = span_gate && sla_recall_gate && latency_gate;
121
122 if !overall_pass {
123 tracing::warn!(
124 "Adversarial audit gate failures: {}",
125 violations.join("; ")
126 );
127 }
128
129 Ok(overall_pass)
130}
131
132pub fn calculate_robustness_score(result: &AdversarialAuditResult) -> f32 {
134 let metrics = &result.overall_metrics;
135
136 let span_score = (metrics.span_coverage_pct / 100.0).min(1.0);
138 let recall_score = metrics.sla_recall_at_50.min(1.0);
139 let stability_score = (2.0 / (metrics.p99_latency_ms / metrics.p95_latency_ms)).min(1.0);
140 let degradation_score = (2.0 / (1.0 + metrics.degradation_factor)).min(1.0);
141
142 let robustness = (span_score * recall_score * stability_score * degradation_score).powf(0.25);
144
145 (robustness * 100.0).round() / 100.0
146}
147
148#[cfg(test)]
149mod tests {
150 use super::*;
151
152 #[test]
153 fn test_adversarial_gate_validation() {
154 let passing_result = AdversarialAuditResult {
155 clone_results: CloneResult::default(),
156 bloat_results: BloatResult::default(),
157 noise_results: NoiseResult::default(),
158 overall_metrics: OverallMetrics {
159 span_coverage_pct: 100.0,
160 sla_recall_at_50: 0.52,
161 p99_latency_ms: 190.0,
162 p95_latency_ms: 140.0, degradation_factor: 1.15,
164 robustness_score: 0.85,
165 },
166 gate_validation: GateValidation {
167 span_coverage_gate: true,
168 sla_recall_gate: true,
169 latency_stability_gate: true,
170 overall_pass: true,
171 violations: vec![],
172 },
173 stress_profile: StressProfile {
174 memory_peak_mb: 2048.0,
175 cpu_utilization_pct: 75.0,
176 disk_io_ops_per_sec: 1250.0,
177 network_bandwidth_mbps: 15.0,
178 gc_pressure_score: 0.3,
179 resource_exhaustion_risk: RiskLevel::Low,
180 },
181 };
182
183 assert!(validate_adversarial_gates(&passing_result).unwrap());
184 }
185
186 #[test]
187 fn test_failing_span_coverage_gate() {
188 let mut failing_result = AdversarialAuditResult {
189 clone_results: CloneResult::default(),
190 bloat_results: BloatResult::default(),
191 noise_results: NoiseResult::default(),
192 overall_metrics: OverallMetrics {
193 span_coverage_pct: 97.5, sla_recall_at_50: 0.52,
195 p99_latency_ms: 180.0,
196 p95_latency_ms: 130.0,
197 degradation_factor: 1.10,
198 robustness_score: 0.80,
199 },
200 gate_validation: GateValidation {
201 span_coverage_gate: false,
202 sla_recall_gate: true,
203 latency_stability_gate: true,
204 overall_pass: false,
205 violations: vec!["Span coverage insufficient".to_string()],
206 },
207 stress_profile: StressProfile {
208 memory_peak_mb: 1800.0,
209 cpu_utilization_pct: 70.0,
210 disk_io_ops_per_sec: 1100.0,
211 network_bandwidth_mbps: 12.0,
212 gc_pressure_score: 0.25,
213 resource_exhaustion_risk: RiskLevel::Low,
214 },
215 };
216
217 assert!(!validate_adversarial_gates(&failing_result).unwrap());
218 }
219
220 #[test]
221 fn test_robustness_score_calculation() {
222 let result = AdversarialAuditResult {
223 clone_results: CloneResult::default(),
224 bloat_results: BloatResult::default(),
225 noise_results: NoiseResult::default(),
226 overall_metrics: OverallMetrics {
227 span_coverage_pct: 100.0,
228 sla_recall_at_50: 0.52,
229 p99_latency_ms: 180.0,
230 p95_latency_ms: 140.0,
231 degradation_factor: 1.2,
232 robustness_score: 0.0, },
234 gate_validation: GateValidation {
235 span_coverage_gate: true,
236 sla_recall_gate: true,
237 latency_stability_gate: true,
238 overall_pass: true,
239 violations: vec![],
240 },
241 stress_profile: StressProfile {
242 memory_peak_mb: 2000.0,
243 cpu_utilization_pct: 72.0,
244 disk_io_ops_per_sec: 1200.0,
245 network_bandwidth_mbps: 14.0,
246 gc_pressure_score: 0.28,
247 resource_exhaustion_risk: RiskLevel::Low,
248 },
249 };
250
251 let score = calculate_robustness_score(&result);
252 assert!(score > 0.7); assert!(score <= 1.0); }
255}