# Rustelo Configuration Settings Reference

## Overview

This document provides a comprehensive reference for all configuration settings available in Rustelo applications. It covers standard configuration schemas, environment variables, feature flags, and best practices for configuration management.

## Quick Reference

### Configuration Files Hierarchy

```
config/
├── template.toml          # Framework defaults
├── development.toml       # Development environment  
├── staging.toml          # Staging environment
├── production.toml       # Production environment
├── local.toml           # Local overrides (git-ignored)
└── features/            # Feature-specific configs
    ├── auth.toml
    ├── analytics.toml
    ├── content-db.toml
    └── metrics.toml
```

### Environment Variables

| Variable | Description | Default | Example |
|----------|-------------|---------|---------|
| `RUSTELO_ENV` | Environment name | `development` | `production` |
| `RUSTELO_CONFIG_PATH` | Config directory path | `config` | `/app/config` |
| `DATABASE_URL` | Database connection string | - | `postgresql://localhost:5432/app` |
| `SERVER_HOST` | Server bind address | `127.0.0.1` | `0.0.0.0` |
| `SERVER_PORT` | Server port | `3030` | `80` |
| `SECRET_KEY` | Application secret key | - | `base64-encoded-key` |
| `SITE_CONTENT_PATH` | Content directory | `content` | `/app/content` |
| `SITE_PUBLIC_PATH` | Public assets directory | `public` | `/app/public` |

## Standard Configuration Schema

### Complete Application Configuration

```toml
# config/template.toml - Framework defaults

[server]
host = "127.0.0.1"
port = 3030
debug = true
max_connections = 1000
timeout_seconds = 30
enable_compression = true
enable_cors = true

[database]
url = "postgresql://localhost:5432/rustelo_dev"
max_connections = 10
min_connections = 1
connect_timeout = 30
idle_timeout = 600
max_lifetime = 1800
enable_logging = false

[session]
secret = "change-this-in-production"
cookie_name = "rustelo_session"
cookie_secure = false
cookie_http_only = true
cookie_same_site = "lax"
max_age = 3600

[cors]
allowed_origins = ["http://localhost:3030", "http://127.0.0.1:3030"]
allowed_methods = ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
allowed_headers = ["Content-Type", "Authorization", "X-Requested-With"]
allow_credentials = true
max_age = 3600

[static_files]
assets_dir = "public"
site_root = "target/site"
site_pkg_dir = "pkg"
enable_etag = true
cache_control = "public, max-age=86400"

[server_dirs]
public_dir = "public"
uploads_dir = "uploads"
logs_dir = "logs"
temp_dir = "tmp"
cache_dir = "cache"
config_dir = "config"
data_dir = "data"
backup_dir = "backups"
template_dir = "templates"

[security]
enable_csrf = true
csrf_token_name = "csrf_token"
rate_limit_requests = 100
rate_limit_window = 60
bcrypt_cost = 12
enable_helmet = true

[content]
root_path = "content"
locales_path = "site/i18n/locales"
ftl_path = "site/i18n/locales"
emergency_path = "public/tmp"
themes_path = "site/themes"
menus_path = "site/menus"
footer_path = "site/footer"
templates_path = "site/templates"
public_path = "public"
enable_caching = true
cache_ttl_seconds = 3600

[logging]
level = "info"
format = "json"
output = "stdout"
file_path = "logs/app.log"
max_size_mb = 100
max_files = 10
enable_access_logs = true
access_log_format = "combined"

[app]
name = "Rustelo Application"
version = "0.1.0"
description = "A modern web application built with Rustelo"
enable_metrics = false
enable_health_check = true
enable_ready_check = true

[cache]
enabled = true
default_ttl_seconds = 3600
max_entries = 10000
cleanup_interval_seconds = 300

[features]
# Feature flags - can be overridden by feature-specific configs
auth = false
content_db = false
email = false
tls = false
metrics = false
crypto = false
```

## Environment-Specific Configurations

### Development Configuration

```toml
# config/development.toml

[server]
debug = true
port = 3030
enable_cors = true

[database]
url = "postgresql://localhost:5432/rustelo_dev"
enable_logging = true

[logging]
level = "debug"
enable_access_logs = true

[security]
enable_csrf = false  # Easier development
rate_limit_requests = 1000  # More lenient

[content]
enable_caching = false  # Always fresh content in dev

[features]
metrics = true  # Enable development metrics
```

### Staging Configuration

```toml
# config/staging.toml

[server]
host = "0.0.0.0"
port = 3030
debug = true  # Still debugging in staging

[database]
url = "postgresql://staging-db:5432/rustelo_staging"
max_connections = 20

[session]
cookie_secure = true  # HTTPS in staging
max_age = 7200  # Shorter sessions

[logging]
level = "info"
format = "json"
file_path = "logs/staging.log"

[security]
enable_csrf = true
rate_limit_requests = 200

[features]
auth = true
email = true
metrics = true
```

### Production Configuration

```toml
# config/production.toml

[server]
host = "0.0.0.0"
port = 80
debug = false  # No debug in production
max_connections = 2000
timeout_seconds = 60

[database]
max_connections = 50
min_connections = 10
connect_timeout = 10
idle_timeout = 300

[session]
cookie_secure = true
cookie_same_site = "strict"
max_age = 86400  # 24 hours

[logging]
level = "warn"
format = "json"
output = "file"
file_path = "logs/production.log"
max_size_mb = 500
max_files = 30

[security]
enable_csrf = true
rate_limit_requests = 60
bcrypt_cost = 14  # Higher cost in production

[content]
enable_caching = true
cache_ttl_seconds = 7200  # Longer cache in prod

[cache]
max_entries = 50000  # More cache in production
default_ttl_seconds = 7200

[features]
auth = true
content_db = true
email = true
tls = true
metrics = true
crypto = true
```

## Feature-Specific Configurations

### Authentication Feature

```toml
# config/features/auth.toml

[auth]
jwt_secret = "your-jwt-secret-key"
jwt_algorithm = "HS256"
jwt_expiry_hours = 24
jwt_refresh_hours = 168  # 7 days
enable_refresh_tokens = true
enable_2fa = false
password_min_length = 8
password_require_special = true
session_timeout_minutes = 60
max_failed_attempts = 5
lockout_duration_minutes = 15

[oauth]
enabled = false

[oauth.google]
client_id = ""
client_secret = ""
redirect_uri = "/auth/google/callback"
scopes = ["email", "profile"]

[oauth.github]
client_id = ""
client_secret = ""
redirect_uri = "/auth/github/callback"
scopes = ["user:email"]

[totp]
enabled = false
issuer = "Rustelo App"
digits = 6
period = 30
algorithm = "SHA1"
```

### Analytics Feature

```toml
# config/features/analytics.toml

[analytics]
enabled = true
endpoint = "/analytics"
batch_size = 100
flush_interval_seconds = 60
retention_days = 90
enable_realtime = true
enable_user_tracking = true
enable_page_views = true
enable_custom_events = true
enable_performance_metrics = true

[analytics.storage]
type = "file"  # "file", "database", "s3"
path = "data/analytics"
compression = "gzip"
max_file_size_mb = 100

[analytics.privacy]
anonymize_ip = true
respect_dnt = true  # Do Not Track header
cookie_consent_required = true
data_retention_days = 365

[analytics.exports]
enabled = true
formats = ["json", "csv"]
endpoint = "/analytics/export"
auth_required = true
```

### Content Database Feature

```toml
# config/features/content-db.toml

[content_db]
enabled = true
table_prefix = "content_"
enable_versioning = true
max_versions = 10
enable_soft_delete = true
enable_full_text_search = true
search_language = "english"

[content_db.cache]
enabled = true
ttl_seconds = 3600
max_entries = 5000
invalidate_on_write = true

[content_db.migrations]
auto_migrate = true
migration_dir = "migrations/content"
backup_before_migrate = true

[content_db.indexes]
enable_search_index = true
enable_tag_index = true
enable_date_index = true
enable_author_index = true

[content_db.permissions]
enable_rbac = false
default_role = "viewer"
admin_role = "admin"
editor_role = "editor"
```

### Email Feature

```toml
# config/features/email.toml

[email]
enabled = false
provider = "smtp"  # "smtp", "sendgrid", "ses", "console"
from_email = "noreply@yourapp.com"
from_name = "Your App"
reply_to = ""
template_dir = "templates/email"

[email.smtp]
host = "smtp.gmail.com"
port = 587
username = ""
password = ""
use_tls = false
use_starttls = true
timeout_seconds = 30
pool_size = 10

[email.sendgrid]
api_key = ""
endpoint = "https://api.sendgrid.com/v3/mail/send"
template_id = ""
categories = ["transactional"]

[email.aws_ses]
region = "us-east-1"
access_key_id = ""
secret_access_key = ""
configuration_set = ""

[email.templates]
welcome = "welcome.html"
password_reset = "password_reset.html"
verification = "verification.html"
notification = "notification.html"

[email.queue]
enabled = true
max_retries = 3
retry_delay_seconds = 300
dead_letter_queue = true
```

### Metrics Feature

```toml
# config/features/metrics.toml

[metrics]
enabled = true
endpoint = "/metrics"
namespace = "rustelo"
enable_process_metrics = true
enable_runtime_metrics = true
enable_custom_metrics = true
enable_histogram = true
enable_summary = true
collection_interval_seconds = 15

[metrics.prometheus]
enabled = true
registry = "default"
push_gateway_url = ""
job_name = "rustelo-app"
instance = ""

[metrics.statsd]
enabled = false
host = "localhost"
port = 8125
prefix = "rustelo"
sample_rate = 1.0

[metrics.custom]
# Custom application metrics
http_request_duration = true
database_connection_pool = true
cache_hit_ratio = true
user_session_count = true
content_view_count = true
api_response_times = true
error_rate = true

[metrics.alerts]
enabled = false
high_cpu_threshold = 80.0
high_memory_threshold = 85.0
high_response_time_ms = 5000
high_error_rate_percent = 5.0
```

### TLS Feature

```toml
# config/features/tls.toml

[tls]
enabled = true
cert_file = "certs/server.crt"
key_file = "certs/server.key"
ca_file = "certs/ca.crt"
protocols = ["TLSv1.2", "TLSv1.3"]
ciphers = "ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20:!aNULL:!MD5:!DSS"

[tls.auto_cert]
enabled = false
provider = "letsencrypt"  # "letsencrypt", "buypass"
email = "admin@yourapp.com"
domains = ["yourapp.com", "www.yourapp.com"]
challenge = "http01"  # "http01", "dns01"
key_type = "ecdsa"  # "rsa", "ecdsa"

[tls.acme]
directory_url = "https://acme-v02.api.letsencrypt.org/directory"
key_file = "certs/account.key"
cert_cache_dir = "certs/cache"
renew_days_before = 30

[tls.security]
enable_hsts = true
hsts_max_age = 31536000  # 1 year
hsts_include_subdomains = true
hsts_preload = false
enable_ocsp_stapling = true
session_cache_size = 1024
session_timeout = 300
```

### Crypto Feature

```toml
# config/features/crypto.toml

[crypto]
enabled = true
algorithm = "AES-256-GCM"
key_derivation = "PBKDF2"
key_iterations = 100000
salt_length = 32
iv_length = 12
tag_length = 16

[crypto.keys]
master_key = ""  # Base64 encoded key
key_rotation_days = 90
old_keys_retention_days = 180
auto_rotate = false

[crypto.encryption]
encrypt_config = true
encrypt_sessions = true
encrypt_cookies = true
encrypt_database_fields = ["password", "api_key", "secret"]

[crypto.hashing]
password_algorithm = "bcrypt"
bcrypt_cost = 12
enable_pepper = true
pepper_key = ""

[crypto.signing]
jwt_algorithm = "RS256"
private_key_file = "keys/jwt-private.pem"
public_key_file = "keys/jwt-public.pem"
key_size = 2048
```

## Environment Variable Overrides

### Server Configuration

```bash
# Server settings
export SERVER_HOST="0.0.0.0"
export SERVER_PORT="8080"
export SERVER_DEBUG="false"
export SERVER_MAX_CONNECTIONS="500"
export SERVER_TIMEOUT_SECONDS="60"

# Database
export DATABASE_URL="postgresql://user:pass@localhost:5432/app"
export DATABASE_MAX_CONNECTIONS="20"
export DATABASE_CONNECT_TIMEOUT="10"

# Security
export SECRET_KEY="base64-encoded-secret-key"
export JWT_SECRET="jwt-secret-key"
export BCRYPT_COST="12"

# Content paths
export SITE_CONTENT_PATH="/app/content"
export SITE_PUBLIC_PATH="/app/public" 
export SITE_LOCALES_PATH="/app/locales"

# Feature toggles
export ENABLE_AUTH="true"
export ENABLE_METRICS="true"
export ENABLE_TLS="false"

# Logging
export LOG_LEVEL="info"
export LOG_FORMAT="json"
export LOG_FILE="/var/log/rustelo.log"

# Environment
export RUSTELO_ENV="production"
export RUSTELO_CONFIG_PATH="/app/config"
```

### Container Environment

```bash
# Docker/Kubernetes environment variables
export KUBERNETES_SERVICE_HOST="kubernetes.default.svc"
export KUBERNETES_SERVICE_PORT="443"
export POD_NAME="rustelo-app-7f9b6d5c4-xyz12"
export NODE_NAME="worker-node-1"
export POD_IP="10.244.0.15"
export HOST_IP="192.168.1.100"

# Service discovery
export REDIS_URL="redis://redis-service:6379"
export ELASTICSEARCH_URL="http://elasticsearch:9200"
export PROMETHEUS_URL="http://prometheus:9090"

# External services
export SMTP_HOST="smtp.sendgrid.net"
export SMTP_USERNAME="apikey"
export SMTP_PASSWORD="your-sendgrid-api-key"

export S3_BUCKET="your-app-bucket"
export S3_REGION="us-west-2"
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
```

## Build-Time Configuration

### Cargo Features

Configure features in `Cargo.toml`:

```toml
[features]
default = ["content-static"]

# Core features
content-static = []
content-db = ["sqlx", "sqlx-postgres"]

# Authentication features
auth = ["jsonwebtoken", "bcrypt"]
auth-oauth = ["auth", "oauth2"]
auth-2fa = ["auth", "totp"]

# Infrastructure features
email = ["lettre"]
email-smtp = ["email"]
email-sendgrid = ["email", "reqwest"]

# Monitoring features
metrics = ["prometheus"]
metrics-statsd = ["metrics", "cadence"]

# Security features
tls = ["rustls"]
crypto = ["aes-gcm", "pbkdf2"]

# Development features
dev-tools = ["tracing-subscriber", "console-subscriber"]
testing = ["tokio-test", "tempfile"]

# Full feature set
full = [
    "content-db", 
    "auth", 
    "auth-oauth", 
    "auth-2fa",
    "email", 
    "email-smtp",
    "metrics", 
    "tls", 
    "crypto",
    "dev-tools"
]
```

### Build.rs Constants Generation

```rust
// build.rs
fn main() -> Result<(), Box<dyn Error>> {
    let out_dir = env::var("OUT_DIR")?;
    let manifest_dir = env::var("CARGO_MANIFEST_DIR")?;
    
    // Generate feature constants
    generate_feature_constants(&out_dir)?;
    
    // Generate environment constants
    generate_env_constants(&out_dir)?;
    
    // Generate config constants from resolved configuration
    let config = MyResolver::resolve_for_build(Path::new(&manifest_dir))?;
    MyResolver::generate_build_artifacts(&config, Path::new(&out_dir))?;
    
    Ok(())
}
```

### Generated Constants Usage

```rust
// Include generated constants
include!(concat!(env!("OUT_DIR"), "/config_constants.rs"));
include!(concat!(env!("OUT_DIR"), "/feature_constants.rs"));

// Usage in application code
#[component]
pub fn AppInfo() -> impl IntoView {
    view! {
        <div>
            <h1>{APP_NAME}</h1>
            <p>"Version: " {APP_VERSION}</p>
            <p>"Environment: " {APP_ENVIRONMENT}</p>
            <p>"Features: " {get_enabled_features().join(", ")}</p>
        </div>
    }
}

// Server configuration
pub fn create_server() -> Result<Server, ServerError> {
    let server = Server::bind(&format!("{}:{}", SERVER_HOST, SERVER_PORT))?;
    
    if has_tls_feature() {
        server = server.tls(get_tls_config()?);
    }
    
    if has_metrics_feature() {
        server = server.metrics(get_metrics_config());
    }
    
    Ok(server)
}
```

## Configuration Validation

### Validation Rules

```rust
impl Validatable for AppConfig {
    type Error = ConfigError;
    
    fn validate(&self) -> Result<(), Self::Error> {
        // Server validation
        self.validate_server_config()?;
        
        // Database validation
        self.validate_database_config()?;
        
        // Security validation
        self.validate_security_config()?;
        
        // Feature validation
        self.validate_feature_config()?;
        
        // Cross-validation
        self.validate_cross_dependencies()?;
        
        Ok(())
    }
    
    fn warnings(&self) -> Vec<String> {
        let mut warnings = Vec::new();
        
        // Performance warnings
        if self.server.debug && self.app.environment == "production" {
            warnings.push("Debug mode enabled in production".to_string());
        }
        
        if !self.cache.enabled && self.app.environment == "production" {
            warnings.push("Caching disabled in production".to_string());
        }
        
        // Security warnings
        if self.session.cookie_secure == false && self.server.port == 443 {
            warnings.push("Insecure cookies on HTTPS port".to_string());
        }
        
        if self.security.bcrypt_cost < 12 {
            warnings.push("BCrypt cost below recommended minimum".to_string());
        }
        
        warnings
    }
}
```

### Specific Validation Methods

```rust
impl AppConfig {
    fn validate_server_config(&self) -> Result<(), ConfigError> {
        if self.server.host.is_empty() {
            return Err(ConfigError::ValidationError("Server host cannot be empty".into()));
        }
        
        if self.server.port == 0 || self.server.port > 65535 {
            return Err(ConfigError::ValidationError("Invalid port number".into()));
        }
        
        if self.server.max_connections == 0 {
            return Err(ConfigError::ValidationError("Max connections must be > 0".into()));
        }
        
        Ok(())
    }
    
    fn validate_database_config(&self) -> Result<(), ConfigError> {
        if self.database.url.is_empty() {
            return Err(ConfigError::ValidationError("Database URL cannot be empty".into()));
        }
        
        if !self.database.url.starts_with("postgresql://") && 
           !self.database.url.starts_with("sqlite://") {
            return Err(ConfigError::ValidationError("Unsupported database URL scheme".into()));
        }
        
        if self.database.max_connections == 0 {
            return Err(ConfigError::ValidationError("Database max connections must be > 0".into()));
        }
        
        Ok(())
    }
    
    fn validate_security_config(&self) -> Result<(), ConfigError> {
        if self.session.secret.len() < 32 {
            return Err(ConfigError::ValidationError("Session secret too short (min 32 chars)".into()));
        }
        
        if self.security.bcrypt_cost < 10 || self.security.bcrypt_cost > 15 {
            return Err(ConfigError::ValidationError("BCrypt cost should be 10-15".into()));
        }
        
        if self.security.rate_limit_requests == 0 {
            return Err(ConfigError::ValidationError("Rate limit requests must be > 0".into()));
        }
        
        Ok(())
    }
    
    fn validate_cross_dependencies(&self) -> Result<(), ConfigError> {
        // TLS validation
        if self.features.tls && self.server.port != 443 {
            return Err(ConfigError::ValidationError(
                "TLS enabled but server not on port 443".into()
            ));
        }
        
        // Auth feature dependencies
        if self.features.auth && self.session.secret == "change-this-in-production" {
            return Err(ConfigError::ValidationError(
                "Default session secret with auth enabled".into()
            ));
        }
        
        // Content DB validation
        if self.features.content_db && self.database.url.starts_with("sqlite://") {
            return Err(ConfigError::ValidationError(
                "Content DB feature requires PostgreSQL".into()
            ));
        }
        
        Ok(())
    }
}
```

## Testing Configuration

### Test Configuration Files

```toml
# config/test.toml
[server]
host = "127.0.0.1"
port = 0  # Random port for testing
debug = true

[database]
url = "sqlite::memory:"  # In-memory database
max_connections = 1

[session]
secret = "test-secret-key-for-testing-only"
max_age = 300  # Short sessions for tests

[logging]
level = "error"  # Quiet logs in tests
output = "stdout"

[cache]
enabled = false  # No caching in tests

[features]
auth = true
metrics = false
email = false
```

### Test Utilities

```rust
#[cfg(test)]
mod test_utils {
    use super::*;
    
    pub fn create_test_config() -> AppConfig {
        let mut config = AppConfig::default();
        config.server.port = 0; // Random port
        config.database.url = "sqlite::memory:".to_string();
        config.session.secret = "test-secret".to_string();
        config.logging.level = LogLevel::Error;
        config
    }
    
    pub fn create_mock_resolver(config: AppConfig) -> MockResolver {
        MockResolver { config }
    }
    
    pub struct MockResolver {
        config: AppConfig,
    }
    
    impl ConfigResolver for MockResolver {
        type Config = AppConfig;
        type Error = ConfigError;
        
        fn resolve(&mut self) -> Result<Self::Config, Self::Error> {
            Ok(self.config.clone())
        }
        
        fn resolve_section<T>(&mut self, _section: &str) -> Result<T, Self::Error> {
            // Mock implementation for testing
            unimplemented!()
        }
    }
}
```

## Troubleshooting

### Common Configuration Issues

1. **Configuration File Not Found**
```
Error: Configuration file not found: config/production.toml
Solution: Ensure RUSTELO_ENV matches available config files
```

2. **Parse Error**
```
Error: TOML parse error at line 15: expected '=', found ':'
Solution: Check TOML syntax, ensure proper key = value format
```

3. **Validation Error**
```
Error: Server port must be greater than 0
Solution: Check server.port value in configuration
```

4. **Environment Override Not Working**
```
Issue: Environment variables not overriding config file values
Solution: Ensure env var names match expected format (SERVER_HOST, not server_host)
```

5. **WASM Constants Not Generated**
```
Issue: Constants not available in WASM code
Solution: Check build.rs includes generate_build_artifacts call
```

### Debug Configuration Loading

```rust
pub fn debug_config_resolution() {
    let mut resolver = MyResolver::new(PathBuf::from(".")).unwrap();
    
    println!("Configuration layers:");
    for (i, layer) in resolver.get_layers().iter().enumerate() {
        println!("  {}: {} (precedence: {})", 
                i, layer.description(), layer.precedence());
    }
    
    match resolver.resolve() {
        Ok(config) => {
            println!("Resolved configuration:");
            println!("{:#?}", config);
        }
        Err(e) => {
            eprintln!("Configuration error: {}", e);
        }
    }
}
```

### Configuration Schema Validation

```bash
# Generate JSON schema for validation
cargo run --bin generate-config-schema > config-schema.json

# Validate configuration file
jsonschema -i config/production.toml config-schema.json
```

This reference guide provides comprehensive documentation for all configuration aspects in Rustelo applications, from basic settings to advanced feature configurations and troubleshooting guidance.
