#![allow(
clippy::doc_markdown,
clippy::struct_excessive_bools,
clippy::must_use_candidate,
clippy::missing_const_for_fn,
clippy::unreadable_literal,
clippy::unnecessary_self_imports,
clippy::return_self_not_must_use,
clippy::missing_errors_doc,
clippy::missing_panics_doc,
clippy::module_name_repetitions,
clippy::use_self,
clippy::derive_partial_eq_without_eq
)]
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct HttpValidationConfig {
pub mode: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct HttpCorsConfig {
pub enabled: bool,
#[serde(default)]
pub allowed_origins: Vec<String>,
#[serde(default)]
pub allowed_methods: Vec<String>,
#[serde(default)]
pub allowed_headers: Vec<String>,
#[serde(default = "default_cors_allow_credentials")]
pub allow_credentials: bool,
}
fn default_cors_allow_credentials() -> bool {
false
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct HttpConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub openapi_spec: Option<String>,
pub cors: Option<HttpCorsConfig>,
pub request_timeout_secs: u64,
pub validation: Option<HttpValidationConfig>,
pub aggregate_validation_errors: bool,
pub validate_responses: bool,
pub response_template_expand: bool,
pub validation_status: Option<u16>,
pub validation_overrides: HashMap<String, String>,
pub skip_admin_validation: bool,
pub auth: Option<AuthConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tls: Option<HttpTlsConfig>,
}
impl Default for HttpConfig {
fn default() -> Self {
Self {
enabled: true,
port: 3000,
host: "0.0.0.0".to_string(),
openapi_spec: None,
cors: Some(HttpCorsConfig {
enabled: true,
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!["content-type".to_string(), "authorization".to_string()],
allow_credentials: false, }),
request_timeout_secs: 30,
validation: Some(HttpValidationConfig {
mode: "enforce".to_string(),
}),
aggregate_validation_errors: true,
validate_responses: false,
response_template_expand: false,
validation_status: None,
validation_overrides: HashMap::new(),
skip_admin_validation: true,
auth: None,
tls: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct HttpTlsConfig {
pub enabled: bool,
pub cert_file: String,
pub key_file: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub ca_file: Option<String>,
#[serde(default = "default_tls_min_version")]
pub min_version: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub cipher_suites: Vec<String>,
#[serde(default)]
pub require_client_cert: bool,
#[serde(default = "default_mtls_mode")]
pub mtls_mode: String,
}
fn default_mtls_mode() -> String {
"off".to_string()
}
fn default_tls_min_version() -> String {
"1.2".to_string()
}
impl Default for HttpTlsConfig {
fn default() -> Self {
Self {
enabled: true,
cert_file: String::new(),
key_file: String::new(),
ca_file: None,
min_version: "1.2".to_string(),
cipher_suites: Vec::new(),
require_client_cert: false,
mtls_mode: "off".to_string(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct WebSocketConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub replay_file: Option<String>,
pub connection_timeout_secs: u64,
}
impl Default for WebSocketConfig {
fn default() -> Self {
Self {
enabled: true,
port: 3001,
host: "0.0.0.0".to_string(),
replay_file: None,
connection_timeout_secs: 300,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct GrpcConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub proto_dir: Option<String>,
pub tls: Option<TlsConfig>,
}
impl Default for GrpcConfig {
fn default() -> Self {
Self {
enabled: true,
port: 50051,
host: "0.0.0.0".to_string(),
proto_dir: None,
tls: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct GraphQLConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub schema_path: Option<String>,
pub handlers_dir: Option<String>,
pub playground_enabled: bool,
pub upstream_url: Option<String>,
pub introspection_enabled: bool,
}
impl Default for GraphQLConfig {
fn default() -> Self {
Self {
enabled: true,
port: 4000,
host: "0.0.0.0".to_string(),
schema_path: None,
handlers_dir: None,
playground_enabled: true,
upstream_url: None,
introspection_enabled: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct TlsConfig {
pub cert_path: String,
pub key_path: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct MqttConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub max_connections: usize,
pub max_packet_size: usize,
pub keep_alive_secs: u16,
pub fixtures_dir: Option<std::path::PathBuf>,
pub enable_retained_messages: bool,
pub max_retained_messages: usize,
}
impl Default for MqttConfig {
fn default() -> Self {
Self {
enabled: false,
port: 1883,
host: "0.0.0.0".to_string(),
max_connections: 1000,
max_packet_size: 268435456, keep_alive_secs: 60,
fixtures_dir: None,
enable_retained_messages: true,
max_retained_messages: 10000,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct SmtpConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub hostname: String,
pub fixtures_dir: Option<std::path::PathBuf>,
pub timeout_secs: u64,
pub max_connections: usize,
pub enable_mailbox: bool,
pub max_mailbox_messages: usize,
pub enable_starttls: bool,
pub tls_cert_path: Option<std::path::PathBuf>,
pub tls_key_path: Option<std::path::PathBuf>,
}
impl Default for SmtpConfig {
fn default() -> Self {
Self {
enabled: false,
port: 1025,
host: "0.0.0.0".to_string(),
hostname: "mockforge-smtp".to_string(),
fixtures_dir: Some(std::path::PathBuf::from("./fixtures/smtp")),
timeout_secs: 300,
max_connections: 10,
enable_mailbox: true,
max_mailbox_messages: 1000,
enable_starttls: false,
tls_cert_path: None,
tls_key_path: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct FtpConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub passive_ports: (u16, u16),
pub max_connections: usize,
pub timeout_secs: u64,
pub allow_anonymous: bool,
pub fixtures_dir: Option<std::path::PathBuf>,
pub virtual_root: std::path::PathBuf,
}
impl Default for FtpConfig {
fn default() -> Self {
Self {
enabled: false,
port: 2121,
host: "0.0.0.0".to_string(),
passive_ports: (50000, 51000),
max_connections: 100,
timeout_secs: 300,
allow_anonymous: true,
fixtures_dir: None,
virtual_root: std::path::PathBuf::from("/mockforge"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct KafkaConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub broker_id: i32,
pub max_connections: usize,
pub log_retention_ms: i64,
pub log_segment_bytes: i64,
pub fixtures_dir: Option<std::path::PathBuf>,
pub auto_create_topics: bool,
pub default_partitions: i32,
pub default_replication_factor: i16,
}
impl Default for KafkaConfig {
fn default() -> Self {
Self {
enabled: false,
port: 9092, host: "0.0.0.0".to_string(),
broker_id: 1,
max_connections: 1000,
log_retention_ms: 604800000, log_segment_bytes: 1073741824, fixtures_dir: None,
auto_create_topics: true,
default_partitions: 3,
default_replication_factor: 1,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct AmqpConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub max_connections: usize,
pub max_channels_per_connection: u16,
pub frame_max: u32,
pub heartbeat_interval: u16,
pub fixtures_dir: Option<std::path::PathBuf>,
pub virtual_hosts: Vec<String>,
pub tls_enabled: bool,
pub tls_port: u16,
pub tls_cert_path: Option<std::path::PathBuf>,
pub tls_key_path: Option<std::path::PathBuf>,
pub tls_ca_path: Option<std::path::PathBuf>,
pub tls_client_auth: bool,
}
impl Default for AmqpConfig {
fn default() -> Self {
Self {
enabled: false,
port: 5672, host: "0.0.0.0".to_string(),
max_connections: 1000,
max_channels_per_connection: 100,
frame_max: 131072, heartbeat_interval: 60,
fixtures_dir: None,
virtual_hosts: vec!["/".to_string()],
tls_enabled: false,
tls_port: 5671, tls_cert_path: None,
tls_key_path: None,
tls_ca_path: None,
tls_client_auth: false,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct TcpConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub max_connections: usize,
pub timeout_secs: u64,
pub fixtures_dir: Option<std::path::PathBuf>,
pub echo_mode: bool,
pub enable_tls: bool,
pub tls_cert_path: Option<std::path::PathBuf>,
pub tls_key_path: Option<std::path::PathBuf>,
}
impl Default for TcpConfig {
fn default() -> Self {
Self {
enabled: false,
port: 9999,
host: "0.0.0.0".to_string(),
max_connections: 1000,
timeout_secs: 300,
fixtures_dir: Some(std::path::PathBuf::from("./fixtures/tcp")),
echo_mode: true,
enable_tls: false,
tls_cert_path: None,
tls_key_path: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct AdminConfig {
pub enabled: bool,
pub port: u16,
pub host: String,
pub auth_required: bool,
pub username: Option<String>,
pub password: Option<String>,
pub mount_path: Option<String>,
pub api_enabled: bool,
pub prometheus_url: String,
}
impl Default for AdminConfig {
fn default() -> Self {
let default_host = if std::env::var("DOCKER_CONTAINER").is_ok()
|| std::env::var("container").is_ok()
|| std::path::Path::new("/.dockerenv").exists()
{
"0.0.0.0".to_string()
} else {
"127.0.0.1".to_string()
};
Self {
enabled: false,
port: 9080,
host: default_host,
auth_required: false,
username: None,
password: None,
mount_path: None,
api_enabled: true,
prometheus_url: "http://localhost:9090".to_string(),
}
}
}
#[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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ProtocolConfig {
pub enabled: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ProtocolsConfig {
pub http: ProtocolConfig,
pub graphql: ProtocolConfig,
pub grpc: ProtocolConfig,
pub websocket: ProtocolConfig,
pub smtp: ProtocolConfig,
pub mqtt: ProtocolConfig,
pub ftp: ProtocolConfig,
pub kafka: ProtocolConfig,
pub rabbitmq: ProtocolConfig,
pub amqp: ProtocolConfig,
pub tcp: ProtocolConfig,
}
impl Default for ProtocolsConfig {
fn default() -> Self {
Self {
http: ProtocolConfig { enabled: true },
graphql: ProtocolConfig { enabled: true },
grpc: ProtocolConfig { enabled: true },
websocket: ProtocolConfig { enabled: true },
smtp: ProtocolConfig { enabled: false },
mqtt: ProtocolConfig { enabled: true },
ftp: ProtocolConfig { enabled: false },
kafka: ProtocolConfig { enabled: false },
rabbitmq: ProtocolConfig { enabled: false },
amqp: ProtocolConfig { enabled: false },
tcp: ProtocolConfig { enabled: false },
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct AuthConfig {
pub jwt: Option<JwtConfig>,
pub oauth2: Option<OAuth2Config>,
pub basic_auth: Option<BasicAuthConfig>,
pub api_key: Option<ApiKeyConfig>,
pub require_auth: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct JwtConfig {
pub secret: Option<String>,
pub rsa_public_key: Option<String>,
pub ecdsa_public_key: Option<String>,
pub issuer: Option<String>,
pub audience: Option<String>,
pub algorithms: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct OAuth2Config {
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>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct BasicAuthConfig {
pub credentials: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ApiKeyConfig {
pub header_name: String,
pub query_name: Option<String>,
pub keys: Vec<String>,
}
impl Default for AuthConfig {
fn default() -> Self {
Self {
jwt: None,
oauth2: None,
basic_auth: None,
api_key: Some(ApiKeyConfig {
header_name: "X-API-Key".to_string(),
query_name: None,
keys: vec![],
}),
require_auth: false,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct RouteConfig {
pub path: String,
pub method: String,
pub request: Option<RouteRequestConfig>,
pub response: RouteResponseConfig,
#[serde(default)]
pub fault_injection: Option<RouteFaultInjectionConfig>,
#[serde(default)]
pub latency: Option<RouteLatencyConfig>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct RouteRequestConfig {
pub validation: Option<RouteValidationConfig>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct RouteResponseConfig {
pub status: u16,
#[serde(default)]
pub headers: HashMap<String, String>,
pub body: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct RouteValidationConfig {
pub schema: serde_json::Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct RouteFaultInjectionConfig {
pub enabled: bool,
pub probability: f64,
pub fault_types: Vec<RouteFaultType>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum RouteFaultType {
HttpError {
status_code: u16,
message: Option<String>,
},
ConnectionError {
message: Option<String>,
},
Timeout {
duration_ms: u64,
message: Option<String>,
},
PartialResponse {
truncate_percent: f64,
},
PayloadCorruption {
corruption_type: String,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct RouteLatencyConfig {
pub enabled: bool,
pub probability: f64,
pub fixed_delay_ms: Option<u64>,
pub random_delay_range_ms: Option<(u64, u64)>,
pub jitter_percent: f64,
#[serde(default)]
pub distribution: LatencyDistribution,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "snake_case")]
#[derive(Default)]
pub enum LatencyDistribution {
#[default]
Fixed,
Normal {
mean_ms: f64,
std_dev_ms: f64,
},
Exponential {
lambda: f64,
},
Uniform,
}
impl Default for RouteFaultInjectionConfig {
fn default() -> Self {
Self {
enabled: false,
probability: 0.0,
fault_types: Vec::new(),
}
}
}
impl Default for RouteLatencyConfig {
fn default() -> Self {
Self {
enabled: false,
probability: 1.0,
fixed_delay_ms: None,
random_delay_range_ms: None,
jitter_percent: 0.0,
distribution: LatencyDistribution::Fixed,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
#[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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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, 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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct BehavioralCloningConfig {
pub enabled: bool,
pub database_path: Option<String>,
pub enable_middleware: bool,
pub min_sequence_frequency: f64,
pub min_requests_per_trace: Option<i32>,
#[serde(default)]
pub flow_recording: FlowRecordingConfig,
#[serde(default)]
pub scenario_replay: ScenarioReplayConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct FlowRecordingConfig {
pub enabled: bool,
pub group_by: String,
pub time_window_seconds: u64,
}
impl Default for FlowRecordingConfig {
fn default() -> Self {
Self {
enabled: true,
group_by: "trace_id".to_string(),
time_window_seconds: 300, }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct ScenarioReplayConfig {
pub enabled: bool,
pub default_mode: String,
pub active_scenarios: Vec<String>,
}
impl Default for ScenarioReplayConfig {
fn default() -> Self {
Self {
enabled: true,
default_mode: "strict".to_string(),
active_scenarios: Vec::new(),
}
}
}
impl Default for BehavioralCloningConfig {
fn default() -> Self {
Self {
enabled: false,
database_path: None,
enable_middleware: false,
min_sequence_frequency: 0.1, min_requests_per_trace: None,
flow_recording: FlowRecordingConfig::default(),
scenario_replay: ScenarioReplayConfig::default(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct ConsumerContractsConfig {
pub enabled: bool,
pub auto_register: bool,
pub track_usage: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct ContractsConfig {
pub fitness_rules: Vec<FitnessRuleConfig>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct FitnessRuleConfig {
pub name: String,
pub scope: String,
#[serde(rename = "type")]
pub rule_type: FitnessRuleType,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_percent_increase: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_fields: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_depth: Option<u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "snake_case")]
pub enum FitnessRuleType {
ResponseSizeDelta,
NoNewRequiredFields,
FieldCount,
SchemaComplexity,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct DriftLearningConfig {
pub enabled: bool,
#[serde(default)]
pub mode: DriftLearningMode,
#[serde(default = "default_learning_sensitivity")]
pub sensitivity: f64,
#[serde(default = "default_learning_decay")]
pub decay: f64,
#[serde(default = "default_min_samples")]
pub min_samples: u64,
#[serde(default)]
pub persona_adaptation: bool,
#[serde(default)]
pub persona_learning: HashMap<String, bool>, #[serde(default)]
pub endpoint_learning: HashMap<String, bool>, }
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "snake_case")]
pub enum DriftLearningMode {
#[default]
Behavioral,
Statistical,
Hybrid,
}
fn default_learning_sensitivity() -> f64 {
0.2
}
fn default_learning_decay() -> f64 {
0.05
}
fn default_min_samples() -> u64 {
10
}
#[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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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 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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default, rename_all = "camelCase")]
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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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_false() -> bool {
false
}
fn default_cache_ttl() -> u64 {
3600
}
fn default_timeout() -> u64 {
30
}
fn default_max_retries() -> usize {
3
}
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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
#[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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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)]
#[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, Default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
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,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct IncidentStorageConfig {
pub use_cache: bool,
pub use_database: bool,
pub retention_days: u32,
}
impl Default for IncidentStorageConfig {
fn default() -> Self {
Self {
use_cache: true,
use_database: true,
retention_days: 90,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "snake_case")]
#[derive(Default)]
pub enum RealityLevel {
StaticStubs = 1,
LightSimulation = 2,
#[default]
ModerateRealism = 3,
HighRealism = 4,
ProductionChaos = 5,
}
impl RealityLevel {
pub fn value(&self) -> u8 {
*self as u8
}
pub fn name(&self) -> &'static str {
match self {
RealityLevel::StaticStubs => "Static Stubs",
RealityLevel::LightSimulation => "Light Simulation",
RealityLevel::ModerateRealism => "Moderate Realism",
RealityLevel::HighRealism => "High Realism",
RealityLevel::ProductionChaos => "Production Chaos",
}
}
pub fn description(&self) -> &'static str {
match self {
RealityLevel::StaticStubs => "Simple, instant responses with no chaos",
RealityLevel::LightSimulation => "Minimal latency, basic intelligence",
RealityLevel::ModerateRealism => "Some chaos, moderate latency, full intelligence",
RealityLevel::HighRealism => "Increased chaos, realistic latency, session state",
RealityLevel::ProductionChaos => {
"Maximum chaos, production-like latency, full features"
}
}
}
pub fn from_value(value: u8) -> Option<Self> {
match value {
1 => Some(RealityLevel::StaticStubs),
2 => Some(RealityLevel::LightSimulation),
3 => Some(RealityLevel::ModerateRealism),
4 => Some(RealityLevel::HighRealism),
5 => Some(RealityLevel::ProductionChaos),
_ => None,
}
}
pub fn all() -> Vec<Self> {
vec![
RealityLevel::StaticStubs,
RealityLevel::LightSimulation,
RealityLevel::ModerateRealism,
RealityLevel::HighRealism,
RealityLevel::ProductionChaos,
]
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(default)]
pub struct RealitySliderConfig {
pub level: RealityLevel,
pub enabled: bool,
}
impl Default for RealitySliderConfig {
fn default() -> Self {
Self {
level: RealityLevel::ModerateRealism,
enabled: true,
}
}
}