use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use super::auth::OAuth2Config;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(Default)]
pub struct DeceptiveDeployConfig {
pub enabled: bool,
pub cors: Option<ProductionCorsConfig>,
pub rate_limit: Option<ProductionRateLimitConfig>,
#[serde(default)]
pub headers: HashMap<String, String>,
pub oauth: Option<ProductionOAuthConfig>,
pub custom_domain: Option<String>,
pub auto_tunnel: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub canary: Option<crate::deceptive_canary::DeceptiveCanaryConfig>,
}
impl DeceptiveDeployConfig {
pub fn production_preset() -> Self {
let mut headers = HashMap::new();
headers.insert("X-API-Version".to_string(), "1.0".to_string());
headers.insert("X-Request-ID".to_string(), "{{uuid}}".to_string());
headers.insert("X-Powered-By".to_string(), "MockForge".to_string());
Self {
enabled: true,
cors: Some(ProductionCorsConfig {
allowed_origins: vec!["*".to_string()],
allowed_methods: vec![
"GET".to_string(),
"POST".to_string(),
"PUT".to_string(),
"DELETE".to_string(),
"PATCH".to_string(),
"OPTIONS".to_string(),
],
allowed_headers: vec!["*".to_string()],
allow_credentials: true,
}),
rate_limit: Some(ProductionRateLimitConfig {
requests_per_minute: 1000,
burst: 2000,
per_ip: true,
}),
headers,
oauth: None, custom_domain: None,
auto_tunnel: true,
canary: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ProductionCorsConfig {
#[serde(default)]
pub allowed_origins: Vec<String>,
#[serde(default)]
pub allowed_methods: Vec<String>,
#[serde(default)]
pub allowed_headers: Vec<String>,
pub allow_credentials: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ProductionRateLimitConfig {
pub requests_per_minute: u32,
pub burst: u32,
pub per_ip: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ProductionOAuthConfig {
pub client_id: String,
pub client_secret: String,
pub introspection_url: String,
pub auth_url: Option<String>,
pub token_url: Option<String>,
pub token_type_hint: Option<String>,
}
impl From<ProductionOAuthConfig> for OAuth2Config {
fn from(prod: ProductionOAuthConfig) -> Self {
OAuth2Config {
client_id: prod.client_id,
client_secret: prod.client_secret,
introspection_url: prod.introspection_url,
auth_url: prod.auth_url,
token_url: prod.token_url,
token_type_hint: prod.token_type_hint,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(Default)]
pub struct PerformanceConfig {
pub compression: CompressionConfig,
pub connection_pool: ConnectionPoolConfig,
pub request_limits: RequestLimitsConfig,
pub workers: WorkerConfig,
pub circuit_breaker: CircuitBreakerConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct CompressionConfig {
pub enabled: bool,
pub algorithm: String,
pub min_size: usize,
pub level: u32,
pub content_types: Vec<String>,
}
impl Default for CompressionConfig {
fn default() -> Self {
Self {
enabled: true,
algorithm: "gzip".to_string(),
min_size: 1024, level: 6,
content_types: vec![
"application/json".to_string(),
"application/xml".to_string(),
"text/plain".to_string(),
"text/html".to_string(),
"text/css".to_string(),
"application/javascript".to_string(),
],
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ConnectionPoolConfig {
pub max_idle_per_host: usize,
pub max_connections: usize,
pub idle_timeout_secs: u64,
pub acquire_timeout_ms: u64,
pub enabled: bool,
}
impl Default for ConnectionPoolConfig {
fn default() -> Self {
Self {
max_idle_per_host: 10,
max_connections: 100,
idle_timeout_secs: 90,
acquire_timeout_ms: 5000,
enabled: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct RequestLimitsConfig {
pub max_body_size: usize,
pub max_header_size: usize,
pub max_headers: usize,
pub max_uri_length: usize,
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub per_route_limits: HashMap<String, usize>,
}
impl Default for RequestLimitsConfig {
fn default() -> Self {
Self {
max_body_size: 10 * 1024 * 1024, max_header_size: 16 * 1024, max_headers: 100,
max_uri_length: 8192,
per_route_limits: HashMap::new(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct WorkerConfig {
pub threads: usize,
pub blocking_threads: usize,
pub stack_size: usize,
pub name_prefix: String,
}
impl Default for WorkerConfig {
fn default() -> Self {
Self {
threads: 0, blocking_threads: 512,
stack_size: 2 * 1024 * 1024, name_prefix: "mockforge-worker".to_string(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct CircuitBreakerConfig {
pub enabled: bool,
pub failure_threshold: u32,
pub success_threshold: u32,
pub half_open_timeout_secs: u64,
pub window_size: u32,
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub per_endpoint: HashMap<String, EndpointCircuitBreakerConfig>,
}
impl Default for CircuitBreakerConfig {
fn default() -> Self {
Self {
enabled: false,
failure_threshold: 5,
success_threshold: 2,
half_open_timeout_secs: 30,
window_size: 10,
per_endpoint: HashMap::new(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct EndpointCircuitBreakerConfig {
pub failure_threshold: u32,
pub success_threshold: u32,
pub half_open_timeout_secs: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ConfigHotReloadConfig {
pub enabled: bool,
pub check_interval_secs: u64,
pub debounce_delay_ms: u64,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub watch_paths: Vec<String>,
pub reload_on_spec_change: bool,
pub reload_on_fixture_change: bool,
pub reload_on_plugin_change: bool,
pub graceful_reload: bool,
pub graceful_timeout_secs: u64,
pub validate_before_reload: bool,
pub rollback_on_failure: bool,
}
impl Default for ConfigHotReloadConfig {
fn default() -> Self {
Self {
enabled: false,
check_interval_secs: 5,
debounce_delay_ms: 1000,
watch_paths: Vec::new(),
reload_on_spec_change: true,
reload_on_fixture_change: true,
reload_on_plugin_change: true,
graceful_reload: true,
graceful_timeout_secs: 30,
validate_before_reload: true,
rollback_on_failure: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
pub enum SecretBackendType {
#[default]
None,
Vault,
AwsSecretsManager,
AzureKeyVault,
GcpSecretManager,
Kubernetes,
EncryptedFile,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct SecretBackendConfig {
pub provider: SecretBackendType,
#[serde(skip_serializing_if = "Option::is_none")]
pub vault: Option<VaultConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub aws: Option<AwsSecretsConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub azure: Option<AzureKeyVaultConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub gcp: Option<GcpSecretManagerConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub kubernetes: Option<KubernetesSecretsConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub encrypted_file: Option<EncryptedFileConfig>,
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub mappings: HashMap<String, String>,
pub cache_ttl_secs: u64,
pub retry_attempts: u32,
pub retry_delay_ms: u64,
}
impl Default for SecretBackendConfig {
fn default() -> Self {
Self {
provider: SecretBackendType::None,
vault: None,
aws: None,
azure: None,
gcp: None,
kubernetes: None,
encrypted_file: None,
mappings: HashMap::new(),
cache_ttl_secs: 300, retry_attempts: 3,
retry_delay_ms: 1000,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct VaultConfig {
pub address: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub namespace: Option<String>,
pub auth_method: VaultAuthMethod,
#[serde(skip_serializing_if = "Option::is_none")]
pub token: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub role_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub secret_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub kubernetes_role: Option<String>,
pub mount_path: String,
pub path_prefix: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub ca_cert_path: Option<String>,
pub skip_verify: bool,
pub timeout_secs: u64,
}
impl Default for VaultConfig {
fn default() -> Self {
Self {
address: "http://127.0.0.1:8200".to_string(),
namespace: None,
auth_method: VaultAuthMethod::Token,
token: None,
role_id: None,
secret_id: None,
kubernetes_role: None,
mount_path: "secret".to_string(),
path_prefix: "mockforge".to_string(),
ca_cert_path: None,
skip_verify: false,
timeout_secs: 30,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
pub enum VaultAuthMethod {
#[default]
Token,
AppRole,
Kubernetes,
AwsIam,
GitHub,
Ldap,
Userpass,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct AwsSecretsConfig {
pub region: String,
pub prefix: String,
pub use_iam_role: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub access_key_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub secret_access_key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub endpoint_url: Option<String>,
}
impl Default for AwsSecretsConfig {
fn default() -> Self {
Self {
region: "us-east-1".to_string(),
prefix: "mockforge".to_string(),
use_iam_role: true,
access_key_id: None,
secret_access_key: None,
endpoint_url: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct AzureKeyVaultConfig {
pub vault_url: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub tenant_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub client_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub client_secret: Option<String>,
pub use_managed_identity: bool,
pub prefix: String,
}
impl Default for AzureKeyVaultConfig {
fn default() -> Self {
Self {
vault_url: String::new(),
tenant_id: None,
client_id: None,
client_secret: None,
use_managed_identity: true,
prefix: "mockforge".to_string(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct GcpSecretManagerConfig {
pub project_id: String,
pub prefix: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub credentials_file: Option<String>,
pub use_default_credentials: bool,
}
impl Default for GcpSecretManagerConfig {
fn default() -> Self {
Self {
project_id: String::new(),
prefix: "mockforge".to_string(),
credentials_file: None,
use_default_credentials: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct KubernetesSecretsConfig {
pub namespace: String,
pub prefix: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub label_selector: Option<String>,
pub in_cluster: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub kubeconfig_path: Option<String>,
}
impl Default for KubernetesSecretsConfig {
fn default() -> Self {
Self {
namespace: "default".to_string(),
prefix: "mockforge".to_string(),
label_selector: None,
in_cluster: true,
kubeconfig_path: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct EncryptedFileConfig {
pub file_path: String,
pub algorithm: String,
pub kdf: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub master_key_env: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub key_file: Option<String>,
}
impl Default for EncryptedFileConfig {
fn default() -> Self {
Self {
file_path: "secrets.enc".to_string(),
algorithm: "aes-256-gcm".to_string(),
kdf: "argon2id".to_string(),
master_key_env: Some("MOCKFORGE_MASTER_KEY".to_string()),
key_file: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct PluginResourceConfig {
pub enabled: bool,
pub max_memory_per_plugin: usize,
pub max_cpu_per_plugin: f64,
pub max_execution_time_ms: u64,
pub allow_network_access: bool,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub allowed_fs_paths: Vec<String>,
pub max_concurrent_executions: usize,
#[serde(skip_serializing_if = "Option::is_none")]
pub cache_dir: Option<String>,
pub debug_logging: bool,
pub max_module_size: usize,
pub max_table_elements: usize,
pub max_stack_size: usize,
}
impl Default for PluginResourceConfig {
fn default() -> Self {
Self {
enabled: true,
max_memory_per_plugin: 10 * 1024 * 1024, max_cpu_per_plugin: 0.5, max_execution_time_ms: 5000, allow_network_access: false,
allowed_fs_paths: Vec::new(),
max_concurrent_executions: 10,
cache_dir: None,
debug_logging: false,
max_module_size: 5 * 1024 * 1024, max_table_elements: 1000,
max_stack_size: 2 * 1024 * 1024, }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct LoggingConfig {
pub level: String,
pub json_format: bool,
pub file_path: Option<String>,
pub max_file_size_mb: u64,
pub max_files: u32,
}
impl Default for LoggingConfig {
fn default() -> Self {
Self {
level: "info".to_string(),
json_format: false,
file_path: None,
max_file_size_mb: 10,
max_files: 5,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default, rename_all = "camelCase")]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ChainingConfig {
pub enabled: bool,
pub max_chain_length: usize,
pub global_timeout_secs: u64,
pub enable_parallel_execution: bool,
}
impl Default for ChainingConfig {
fn default() -> Self {
Self {
enabled: false,
max_chain_length: 20,
global_timeout_secs: 300,
enable_parallel_execution: false,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct DataConfig {
pub default_rows: usize,
pub default_format: String,
pub locale: String,
pub templates: HashMap<String, String>,
pub rag: RagConfig,
#[serde(skip_serializing_if = "Option::is_none")]
pub persona_domain: Option<String>,
#[serde(default = "default_false")]
pub persona_consistency_enabled: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub persona_registry: Option<PersonaRegistryConfig>,
}
impl Default for DataConfig {
fn default() -> Self {
Self {
default_rows: 100,
default_format: "json".to_string(),
locale: "en".to_string(),
templates: HashMap::new(),
rag: RagConfig::default(),
persona_domain: None,
persona_consistency_enabled: false,
persona_registry: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct RagConfig {
pub enabled: bool,
#[serde(default)]
pub provider: String,
pub api_endpoint: Option<String>,
pub api_key: Option<String>,
pub model: Option<String>,
#[serde(default = "default_max_tokens")]
pub max_tokens: usize,
#[serde(default = "default_temperature")]
pub temperature: f64,
pub context_window: usize,
#[serde(default = "default_true")]
pub caching: bool,
#[serde(default = "default_cache_ttl")]
pub cache_ttl_secs: u64,
#[serde(default = "default_timeout")]
pub timeout_secs: u64,
#[serde(default = "default_max_retries")]
pub max_retries: usize,
}
fn default_max_tokens() -> usize {
1024
}
fn default_temperature() -> f64 {
0.7
}
fn default_true() -> bool {
true
}
fn default_cache_ttl() -> u64 {
3600
}
fn default_timeout() -> u64 {
30
}
fn default_max_retries() -> usize {
3
}
pub(crate) fn default_false() -> bool {
false
}
impl Default for RagConfig {
fn default() -> Self {
Self {
enabled: false,
provider: "openai".to_string(),
api_endpoint: None,
api_key: None,
model: Some("gpt-3.5-turbo".to_string()),
max_tokens: default_max_tokens(),
temperature: default_temperature(),
context_window: 4000,
caching: default_true(),
cache_ttl_secs: default_cache_ttl(),
timeout_secs: default_timeout(),
max_retries: default_max_retries(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(Default)]
pub struct PersonaRegistryConfig {
#[serde(default = "default_false")]
pub persistent: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub storage_path: Option<String>,
#[serde(default)]
pub default_traits: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct MockAIConfig {
pub enabled: bool,
pub intelligent_behavior: crate::intelligent_behavior::IntelligentBehaviorConfig,
pub auto_learn: bool,
pub mutation_detection: bool,
pub ai_validation_errors: bool,
pub intelligent_pagination: bool,
#[serde(default)]
pub enabled_endpoints: Vec<String>,
}
impl Default for MockAIConfig {
fn default() -> Self {
Self {
enabled: false,
intelligent_behavior: crate::intelligent_behavior::IntelligentBehaviorConfig::default(),
auto_learn: true,
mutation_detection: true,
ai_validation_errors: true,
intelligent_pagination: true,
enabled_endpoints: Vec::new(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct ObservabilityConfig {
pub prometheus: PrometheusConfig,
pub opentelemetry: Option<OpenTelemetryConfig>,
pub recorder: Option<RecorderConfig>,
pub chaos: Option<ChaosEngConfig>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
#[derive(Default)]
pub struct SecurityConfig {
pub monitoring: SecurityMonitoringConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(Default)]
pub struct SecurityMonitoringConfig {
pub siem: crate::security::siem::SiemConfig,
pub access_review: crate::security::access_review::AccessReviewConfig,
pub privileged_access: crate::security::privileged_access::PrivilegedAccessConfig,
pub change_management: crate::security::change_management::ChangeManagementConfig,
pub compliance_dashboard: crate::security::compliance_dashboard::ComplianceDashboardConfig,
pub risk_assessment: crate::security::risk_assessment::RiskAssessmentConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct PrometheusConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub path: String,
}
impl Default for PrometheusConfig {
fn default() -> Self {
Self {
enabled: true,
port: 9090,
host: "0.0.0.0".to_string(),
path: "/metrics".to_string(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct OpenTelemetryConfig {
pub enabled: bool,
pub service_name: String,
pub environment: String,
pub jaeger_endpoint: String,
pub otlp_endpoint: Option<String>,
pub protocol: String,
pub sampling_rate: f64,
}
impl Default for OpenTelemetryConfig {
fn default() -> Self {
Self {
enabled: false,
service_name: "mockforge".to_string(),
environment: "development".to_string(),
jaeger_endpoint: "http://localhost:14268/api/traces".to_string(),
otlp_endpoint: Some("http://localhost:4317".to_string()),
protocol: "grpc".to_string(),
sampling_rate: 1.0,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct RecorderConfig {
pub enabled: bool,
pub database_path: String,
pub api_enabled: bool,
pub api_port: Option<u16>,
pub max_requests: i64,
pub retention_days: i64,
pub record_http: bool,
pub record_grpc: bool,
pub record_websocket: bool,
pub record_graphql: bool,
#[serde(default = "default_true")]
pub record_proxy: bool,
}
impl Default for RecorderConfig {
fn default() -> Self {
Self {
enabled: false,
database_path: "./mockforge-recordings.db".to_string(),
api_enabled: true,
api_port: None,
max_requests: 10000,
retention_days: 7,
record_http: true,
record_grpc: true,
record_websocket: true,
record_graphql: true,
record_proxy: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ChaosEngConfig {
pub enabled: bool,
pub latency: Option<LatencyInjectionConfig>,
pub fault_injection: Option<FaultConfig>,
pub rate_limit: Option<RateLimitingConfig>,
pub traffic_shaping: Option<NetworkShapingConfig>,
pub scenario: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct LatencyInjectionConfig {
pub enabled: bool,
pub fixed_delay_ms: Option<u64>,
pub random_delay_range_ms: Option<(u64, u64)>,
pub jitter_percent: f64,
pub probability: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct FaultConfig {
pub enabled: bool,
pub http_errors: Vec<u16>,
pub http_error_probability: f64,
pub connection_errors: bool,
pub connection_error_probability: f64,
pub timeout_errors: bool,
pub timeout_ms: u64,
pub timeout_probability: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct RateLimitingConfig {
pub enabled: bool,
pub requests_per_second: u32,
pub burst_size: u32,
pub per_ip: bool,
pub per_endpoint: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct NetworkShapingConfig {
pub enabled: bool,
pub bandwidth_limit_bps: u64,
pub packet_loss_percent: f64,
pub max_connections: u32,
}