sentinel_config/
agents.rs

1//! Agent configuration types
2//!
3//! This module contains configuration types for external processing agents
4//! (WAF, auth, rate limiting, custom logic).
5
6use serde::{Deserialize, Serialize};
7use std::path::PathBuf;
8use validator::Validate;
9
10use sentinel_common::types::CircuitBreakerConfig;
11
12use crate::routes::FailureMode;
13
14// ============================================================================
15// Body Streaming Mode
16// ============================================================================
17
18/// Body streaming mode for agent processing
19///
20/// Controls how request/response bodies are sent to agents:
21/// - `Buffer`: Collect entire body before sending (default, backwards compatible)
22/// - `Stream`: Send chunks as they arrive (lower latency, lower memory)
23/// - `Hybrid`: Buffer small bodies, stream large ones
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
25#[serde(rename_all = "snake_case")]
26#[derive(Default)]
27pub enum BodyStreamingMode {
28    /// Buffer entire body before sending to agent (default)
29    ///
30    /// - Simpler agent implementation
31    /// - Higher memory usage for large bodies
32    /// - Agent sees complete body for decisions
33    #[default]
34    Buffer,
35
36    /// Stream body chunks as they arrive
37    ///
38    /// - Lower latency and memory usage
39    /// - Agent must handle partial data
40    /// - Supports progressive decisions
41    Stream,
42
43    /// Hybrid: buffer up to threshold, then stream
44    ///
45    /// - Best of both worlds for mixed workloads
46    /// - Small bodies buffered for simplicity
47    /// - Large bodies streamed for efficiency
48    Hybrid {
49        /// Buffer threshold in bytes (default: 64KB)
50        #[serde(default = "default_hybrid_threshold")]
51        buffer_threshold: usize,
52    },
53}
54
55fn default_hybrid_threshold() -> usize {
56    64 * 1024 // 64KB
57}
58
59// ============================================================================
60// Agent Configuration
61// ============================================================================
62
63/// Agent configuration
64#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
65pub struct AgentConfig {
66    /// Unique agent identifier
67    pub id: String,
68
69    /// Agent type
70    #[serde(rename = "type")]
71    pub agent_type: AgentType,
72
73    /// Transport configuration
74    pub transport: AgentTransport,
75
76    /// Events this agent handles
77    pub events: Vec<AgentEvent>,
78
79    /// Timeout for agent calls
80    #[serde(default = "default_agent_timeout")]
81    pub timeout_ms: u64,
82
83    /// Failure mode when agent is unavailable
84    #[serde(default)]
85    pub failure_mode: FailureMode,
86
87    /// Circuit breaker configuration
88    #[serde(default)]
89    pub circuit_breaker: Option<CircuitBreakerConfig>,
90
91    /// Maximum request body to send
92    pub max_request_body_bytes: Option<usize>,
93
94    /// Maximum response body to send
95    pub max_response_body_bytes: Option<usize>,
96
97    /// Request body streaming mode
98    ///
99    /// Controls how request bodies are sent to this agent:
100    /// - `buffer`: Collect entire body before sending (default)
101    /// - `stream`: Send chunks as they arrive
102    /// - `hybrid`: Buffer small bodies, stream large ones
103    #[serde(default)]
104    pub request_body_mode: BodyStreamingMode,
105
106    /// Response body streaming mode
107    ///
108    /// Controls how response bodies are sent to this agent.
109    /// Same options as request_body_mode.
110    #[serde(default)]
111    pub response_body_mode: BodyStreamingMode,
112
113    /// Timeout per body chunk when streaming (milliseconds)
114    ///
115    /// Only applies when using `stream` or `hybrid` mode.
116    /// Default: 5000ms (5 seconds)
117    #[serde(default = "default_chunk_timeout")]
118    pub chunk_timeout_ms: u64,
119
120    /// Agent-specific configuration
121    ///
122    /// This configuration is passed to the agent via the Configure event
123    /// when the agent connects. The structure depends on the agent type.
124    #[serde(default, skip_serializing_if = "Option::is_none")]
125    pub config: Option<serde_json::Value>,
126
127    /// Maximum concurrent calls to this agent
128    ///
129    /// Limits the number of simultaneous requests that can be processed by this agent.
130    /// This provides per-agent queue isolation to prevent a slow agent from affecting
131    /// other agents (noisy neighbor problem).
132    ///
133    /// Default: 100 concurrent calls per agent
134    #[serde(default = "default_max_concurrent_calls")]
135    pub max_concurrent_calls: usize,
136}
137
138fn default_chunk_timeout() -> u64 {
139    5000 // 5 seconds
140}
141
142fn default_max_concurrent_calls() -> usize {
143    100 // Per-agent concurrency limit
144}
145
146// ============================================================================
147// Agent Type
148// ============================================================================
149
150/// Agent type
151#[derive(Debug, Clone, Serialize, Deserialize)]
152#[serde(rename_all = "snake_case")]
153pub enum AgentType {
154    Waf,
155    Auth,
156    RateLimit,
157    Custom(String),
158}
159
160// ============================================================================
161// Agent Transport
162// ============================================================================
163
164/// Agent transport configuration
165#[derive(Debug, Clone, Serialize, Deserialize)]
166#[serde(rename_all = "snake_case")]
167pub enum AgentTransport {
168    /// Unix domain socket
169    UnixSocket { path: PathBuf },
170
171    /// gRPC over TCP
172    Grpc {
173        address: String,
174        tls: Option<AgentTlsConfig>,
175    },
176
177    /// HTTP REST API
178    Http {
179        url: String,
180        tls: Option<AgentTlsConfig>,
181    },
182}
183
184/// Agent TLS configuration
185#[derive(Debug, Clone, Serialize, Deserialize)]
186pub struct AgentTlsConfig {
187    /// Skip certificate verification
188    #[serde(default)]
189    pub insecure_skip_verify: bool,
190
191    /// CA certificate
192    pub ca_cert: Option<PathBuf>,
193
194    /// Client certificate for mTLS
195    pub client_cert: Option<PathBuf>,
196
197    /// Client key for mTLS
198    pub client_key: Option<PathBuf>,
199}
200
201// ============================================================================
202// Agent Events
203// ============================================================================
204
205/// Agent events
206#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
207#[serde(rename_all = "snake_case")]
208pub enum AgentEvent {
209    RequestHeaders,
210    RequestBody,
211    ResponseHeaders,
212    ResponseBody,
213    Log,
214    /// WebSocket frame inspection (after upgrade)
215    WebSocketFrame,
216}
217
218// ============================================================================
219// Default Value Functions
220// ============================================================================
221
222fn default_agent_timeout() -> u64 {
223    1000
224}