Skip to main content

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, &current_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}