kindly_guard_server/neutralizer/api.rs
1// Copyright 2025 Kindly Software Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//! Public API documentation for the neutralization system
15//!
16//! This module provides comprehensive documentation for all public APIs
17//! in the threat neutralization system.
18//!
19//! # Overview
20//!
21//! The neutralization system is designed to remediate security threats detected
22//! by the scanner. It provides a layered architecture with optional features
23//! like rate limiting, health monitoring, and distributed tracing.
24//!
25//! # Core Concepts
26//!
27//! - **Threat**: A security issue detected by the scanner
28//! - **Neutralization**: The process of remediating a threat
29//! - **Action**: The specific remediation applied (sanitize, parameterize, etc.)
30//! - **Confidence**: How certain the system is about the neutralization
31//!
32//! # Basic Usage
33//!
34//! ```no_run
35//! use kindly_guard_server::neutralizer::{
36//! create_neutralizer, NeutralizationConfig, ThreatNeutralizer,
37//! };
38//! use kindly_guard_server::scanner::{Threat, ThreatType, Severity, Location};
39//!
40//! #[tokio::main]
41//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
42//! // Create with default config
43//! let config = NeutralizationConfig::default();
44//! let neutralizer = create_neutralizer(&config, None);
45//!
46//! // Define a threat
47//! let threat = Threat {
48//! threat_type: ThreatType::SqlInjection,
49//! severity: Severity::High,
50//! location: Location::Text { offset: 0, length: 10 },
51//! description: "SQL injection detected".to_string(),
52//! remediation: None,
53//! };
54//!
55//! // Neutralize the threat
56//! let result = neutralizer.neutralize(&threat, "SELECT * FROM users").await?;
57//!
58//! // Check the result
59//! if let Some(safe_content) = result.sanitized_content {
60//! println!("Safe content: {}", safe_content);
61//! }
62//!
63//! Ok(())
64//! }
65//! ```
66
67use crate::scanner::{Threat, ThreatType};
68use anyhow::Result;
69use async_trait::async_trait;
70use std::sync::Arc;
71
72/// The main trait for threat neutralization.
73///
74/// This trait defines the interface that all neutralizers must implement.
75/// It provides methods for neutralizing individual threats and batches of threats.
76///
77/// # Implementation Notes
78///
79/// - Implementations must be thread-safe (`Send + Sync`)
80/// - Neutralization should be idempotent when possible
81/// - Errors should be returned rather than panicking
82///
83/// # Example Implementation
84///
85/// ```ignore
86/// struct MyNeutralizer {
87/// config: NeutralizationConfig,
88/// }
89///
90/// #[async_trait]
91/// impl ThreatNeutralizer for MyNeutralizer {
92/// async fn neutralize(&self, threat: &Threat, content: &str) -> Result<NeutralizeResult> {
93/// // Implementation here
94/// }
95///
96/// fn can_neutralize(&self, threat_type: &ThreatType) -> bool {
97/// // Check if this neutralizer handles the threat type
98/// }
99///
100/// fn get_capabilities(&self) -> NeutralizerCapabilities {
101/// // Return capabilities
102/// }
103/// }
104/// ```
105#[async_trait]
106pub trait ThreatNeutralizerApi: Send + Sync {
107 /// Neutralize a specific threat in content.
108 ///
109 /// This is the primary method for threat neutralization. It takes a threat
110 /// detected by the scanner and the content containing the threat, then
111 /// returns a result indicating what action was taken.
112 ///
113 /// # Arguments
114 ///
115 /// * `threat` - The threat to neutralize, as detected by the scanner
116 /// * `content` - The original content containing the threat
117 ///
118 /// # Returns
119 ///
120 /// Returns a `NeutralizeResult` containing:
121 /// - The action taken
122 /// - Optionally, the sanitized content
123 /// - Confidence score
124 /// - Processing time
125 /// - Optional correlation data
126 ///
127 /// # Errors
128 ///
129 /// Returns an error if:
130 /// - The threat type is not supported
131 /// - Neutralization fails due to invalid input
132 /// - System resources are exhausted
133 ///
134 /// # Example
135 ///
136 /// ```ignore
137 /// let threat = Threat {
138 /// threat_type: ThreatType::SqlInjection,
139 /// severity: Severity::High,
140 /// location: Location::Text { offset: 28, length: 15 },
141 /// description: "SQL injection in WHERE clause".to_string(),
142 /// remediation: Some("Use parameterized queries".to_string()),
143 /// };
144 ///
145 /// let result = neutralizer.neutralize(
146 /// &threat,
147 /// "SELECT * FROM users WHERE id='1' OR '1'='1'"
148 /// ).await?;
149 ///
150 /// assert_eq!(result.action_taken, NeutralizeAction::Parameterized);
151 /// assert_eq!(
152 /// result.sanitized_content,
153 /// Some("SELECT * FROM users WHERE id=$1 OR $2=$3".to_string())
154 /// );
155 /// ```
156 async fn neutralize(&self, threat: &Threat, content: &str) -> Result<super::NeutralizeResult>;
157
158 /// Check if this neutralizer can handle a specific threat type.
159 ///
160 /// This method allows callers to determine whether a neutralizer supports
161 /// a particular threat type before attempting neutralization.
162 ///
163 /// # Arguments
164 ///
165 /// * `threat_type` - The type of threat to check
166 ///
167 /// # Returns
168 ///
169 /// Returns `true` if this neutralizer can handle the threat type,
170 /// `false` otherwise.
171 ///
172 /// # Example
173 ///
174 /// ```ignore
175 /// if neutralizer.can_neutralize(&ThreatType::SqlInjection) {
176 /// // Proceed with neutralization
177 /// } else {
178 /// // Use a different neutralizer or skip
179 /// }
180 /// ```
181 fn can_neutralize(&self, threat_type: &ThreatType) -> bool;
182
183 /// Get the capabilities of this neutralizer.
184 ///
185 /// Returns detailed information about what this neutralizer can do,
186 /// including supported threat types, performance characteristics,
187 /// and optional features.
188 ///
189 /// # Returns
190 ///
191 /// A `NeutralizerCapabilities` struct containing:
192 /// - Whether real-time neutralization is supported
193 /// - Batch mode support
194 /// - Predictive capabilities
195 /// - Correlation support
196 /// - Rollback depth
197 /// - List of supported threat types
198 ///
199 /// # Example
200 ///
201 /// ```ignore
202 /// let caps = neutralizer.get_capabilities();
203 ///
204 /// if caps.batch_mode {
205 /// // Use batch neutralization for better performance
206 /// }
207 ///
208 /// println!("Supported threats: {:?}", caps.supported_threats);
209 /// ```
210 fn get_capabilities(&self) -> super::NeutralizerCapabilities;
211
212 /// Neutralize multiple threats in a single operation.
213 ///
214 /// This method provides efficient batch processing of multiple threats.
215 /// Threats are processed in order, with each neutralization applied to
216 /// the result of the previous one.
217 ///
218 /// # Arguments
219 ///
220 /// * `threats` - Slice of threats to neutralize, in order
221 /// * `content` - The original content containing the threats
222 ///
223 /// # Returns
224 ///
225 /// Returns a `BatchNeutralizeResult` containing:
226 /// - The final sanitized content after all neutralizations
227 /// - Individual results for each threat
228 ///
229 /// # Default Implementation
230 ///
231 /// The default implementation processes threats sequentially.
232 /// Implementations may override this for better performance.
233 ///
234 /// # Example
235 ///
236 /// ```ignore
237 /// let threats = vec![
238 /// sql_injection_threat,
239 /// unicode_threat,
240 /// path_traversal_threat,
241 /// ];
242 ///
243 /// let result = neutralizer.batch_neutralize(&threats, original_content).await?;
244 ///
245 /// println!("Final safe content: {}", result.final_content);
246 /// println!("Processed {} threats", result.individual_results.len());
247 /// ```
248 async fn batch_neutralize(
249 &self,
250 threats: &[Threat],
251 content: &str,
252 ) -> Result<super::BatchNeutralizeResult> {
253 // Default implementation - can be overridden
254 let mut results = Vec::new();
255 let mut current_content = content.to_string();
256
257 for threat in threats {
258 let result = self.neutralize(threat, ¤t_content).await?;
259 if let Some(ref sanitized) = result.sanitized_content {
260 current_content = sanitized.clone();
261 }
262 results.push(result);
263 }
264
265 Ok(super::BatchNeutralizeResult {
266 final_content: current_content,
267 individual_results: results,
268 })
269 }
270}
271
272/// Factory function to create a neutralizer with default settings.
273///
274/// This is the primary way to create a neutralizer instance. It automatically
275/// selects the appropriate implementation based on feature flags,
276/// and wraps the neutralizer with production-ready features.
277///
278/// # Arguments
279///
280/// * `config` - Neutralization configuration
281/// * `rate_limiter` - Optional rate limiter for throttling
282///
283/// # Returns
284///
285/// Returns an `Arc<dyn ThreatNeutralizer>` ready for use.
286///
287/// # Features Added
288///
289/// The returned neutralizer includes:
290/// - Recovery and resilience (if configured)
291/// - Rollback support (if `backup_originals` is true)
292/// - Rate limiting (if provided)
293/// - Health monitoring (always enabled)
294///
295/// # Example
296///
297/// ```ignore
298/// use kindly_guard_server::neutralizer::{
299/// create_neutralizer, NeutralizationConfig, NeutralizationMode,
300/// };
301///
302/// let config = NeutralizationConfig {
303/// mode: NeutralizationMode::Automatic,
304/// backup_originals: true,
305/// audit_all_actions: true,
306/// ..Default::default()
307/// };
308///
309/// let neutralizer = create_neutralizer(&config, None);
310/// ```
311pub fn create_neutralizer_api(
312 config: &super::NeutralizationConfig,
313 rate_limiter: Option<Arc<dyn crate::traits::RateLimiter>>,
314) -> Arc<dyn super::ThreatNeutralizer> {
315 super::create_neutralizer(config, rate_limiter)
316}
317
318/// Factory function to create a neutralizer with distributed tracing.
319///
320/// This extends `create_neutralizer` by adding distributed tracing capabilities
321/// for observability in production environments.
322///
323/// # Arguments
324///
325/// * `config` - Neutralization configuration
326/// * `rate_limiter` - Optional rate limiter for throttling
327/// * `tracing_provider` - Optional distributed tracing provider
328///
329/// # Returns
330///
331/// Returns an `Arc<dyn ThreatNeutralizer>` with all features including tracing.
332///
333/// # Example
334///
335/// ```ignore
336/// use kindly_guard_server::neutralizer::create_neutralizer_with_telemetry;
337/// use kindly_guard_server::telemetry::{
338/// DistributedTracingProvider, ProbabilitySampler, W3CTraceContextPropagator,
339/// };
340///
341/// // Set up tracing
342/// let tracing_provider = Arc::new(DistributedTracingProvider::new(
343/// base_provider,
344/// Arc::new(ProbabilitySampler::new(0.1)),
345/// Arc::new(W3CTraceContextPropagator),
346/// ));
347///
348/// // Create neutralizer with tracing
349/// let neutralizer = create_neutralizer_with_telemetry(
350/// &config,
351/// rate_limiter,
352/// Some(tracing_provider),
353/// );
354/// ```
355pub fn create_neutralizer_with_telemetry_api(
356 config: &super::NeutralizationConfig,
357 rate_limiter: Option<Arc<dyn crate::traits::RateLimiter>>,
358 tracing_provider: Option<Arc<crate::telemetry::DistributedTracingProvider>>,
359) -> Arc<dyn super::ThreatNeutralizer> {
360 super::create_neutralizer_with_telemetry(config, rate_limiter, tracing_provider)
361}
362
363// Re-export commonly used types for convenience
364pub use super::{
365 AttackPattern,
366 BatchNeutralizeResult,
367 BiDiReplacement,
368 CommandAction,
369 // Correlation types
370 CorrelationData,
371 HomographAction,
372 // Injection configuration
373 InjectionNeutralizationConfig,
374 NeutralizationConfig,
375 NeutralizationMode,
376 NeutralizeAction,
377 NeutralizeResult,
378 NeutralizerCapabilities,
379 PathAction,
380 PromptAction,
381 SqlAction,
382 // Unicode configuration
383 UnicodeNeutralizationConfig,
384 ZeroWidthAction,
385};
386
387/// Module containing detailed examples of neutralizer usage.
388pub mod examples {
389 /// Basic neutralization example.
390 ///
391 /// ```ignore
392 /// # use kindly_guard_server::neutralizer::*;
393 /// # use kindly_guard_server::scanner::*;
394 /// # async fn example() -> anyhow::Result<()> {
395 /// // Create neutralizer
396 /// let config = NeutralizationConfig::default();
397 /// let neutralizer = create_neutralizer(&config, None);
398 ///
399 /// // Create a threat
400 /// let threat = Threat {
401 /// threat_type: ThreatType::SqlInjection,
402 /// severity: Severity::High,
403 /// location: Location::Text { offset: 0, length: 20 },
404 /// description: "SQL injection".to_string(),
405 /// remediation: None,
406 /// };
407 ///
408 /// // Neutralize
409 /// let result = neutralizer.neutralize(&threat, "'; DROP TABLE users;").await?;
410 /// assert_eq!(result.action_taken, NeutralizeAction::Parameterized);
411 /// # Ok(())
412 /// # }
413 /// ```
414 pub const fn basic_example() {}
415
416 /// Batch neutralization example.
417 ///
418 /// ```ignore
419 /// # use kindly_guard_server::neutralizer::*;
420 /// # use kindly_guard_server::scanner::*;
421 /// # async fn example() -> anyhow::Result<()> {
422 /// let neutralizer = create_neutralizer(&Default::default(), None);
423 ///
424 /// let threats = vec![
425 /// // SQL injection
426 /// Threat {
427 /// threat_type: ThreatType::SqlInjection,
428 /// severity: Severity::High,
429 /// location: Location::Text { offset: 0, length: 10 },
430 /// description: "SQL injection".to_string(),
431 /// remediation: None,
432 /// },
433 /// // Unicode attack
434 /// Threat {
435 /// threat_type: ThreatType::UnicodeBiDi,
436 /// severity: Severity::Medium,
437 /// location: Location::Text { offset: 20, length: 5 },
438 /// description: "BiDi override".to_string(),
439 /// remediation: None,
440 /// },
441 /// ];
442 ///
443 /// let content = "SELECT * FROM users; Hello\u{202E}World";
444 /// let result = neutralizer.batch_neutralize(&threats, content).await?;
445 ///
446 /// println!("Safe content: {}", result.final_content);
447 /// # Ok(())
448 /// # }
449 /// ```
450 pub const fn batch_example() {}
451
452 /// Custom configuration example.
453 ///
454 /// ```ignore
455 /// # use kindly_guard_server::neutralizer::*;
456 /// let config = NeutralizationConfig {
457 /// mode: NeutralizationMode::Automatic,
458 /// backup_originals: true,
459 /// audit_all_actions: true,
460 /// unicode: UnicodeNeutralizationConfig {
461 /// bidi_replacement: BiDiReplacement::Marker,
462 /// zero_width_action: ZeroWidthAction::Remove,
463 /// homograph_action: HomographAction::Ascii,
464 /// },
465 /// injection: InjectionNeutralizationConfig {
466 /// sql_action: SqlAction::Parameterize,
467 /// command_action: CommandAction::Escape,
468 /// path_action: PathAction::Normalize,
469 /// prompt_action: PromptAction::Wrap,
470 /// },
471 /// recovery: None,
472 /// };
473 ///
474 /// let neutralizer = create_neutralizer(&config, None);
475 /// ```
476 pub const fn configuration_example() {}
477}