# Unified Configuration Guidelines

This document outlines the standardized approach for managing configuration across all components of the Cloud project. Adhering to these guidelines ensures consistency, maintainability, and ease of operation for all services.

## 1. Layered Configuration with `config-rs`

All components MUST use the `config-rs` crate for managing application settings. This allows for a robust, layered configuration system with clear precedence:

1.  **Defaults:** Sensible, hard-coded default values provided by the application. These are the lowest precedence.
2.  **Environment Variables:** Values loaded from environment variables. These override defaults.
3.  **Configuration Files:** Values loaded from a TOML configuration file. These override environment variables and defaults.
4.  **Command-Line Arguments:** Values provided via command-line arguments. These are the highest precedence and always override all other sources.

### Implementation Details:

*   **`ServerConfig::default()` as base:** Use `toml::to_string(&MyServerConfig::default())` to provide the base default configuration to `config-rs`. This ensures `Default` implementations are the source of truth for base settings.
*   **Workspace Dependency:** The `config` crate should be a `[workspace.dependencies]` entry in the component's `Cargo.toml`, and member crates should reference it with `config.workspace = true`.

## 2. Configuration File Format: TOML

All configuration files MUST be in the [TOML](https://toml.io/en/) format.

*   `config-rs` should be configured to read TOML files (`config::FileFormat::Toml`).
*   Configuration structs MUST derive `serde::Serialize` and `serde::Deserialize` to enable `config-rs` to populate them.

## 3. Command-Line Argument Overrides with `clap`

All components MUST use `clap::Parser` for parsing command-line arguments.

*   Critical configuration parameters MUST be exposed as CLI arguments.
*   CLI arguments are applied *after* `config-rs` has loaded all other configuration sources, ensuring they have the highest precedence. This typically involves manually setting fields in the deserialized configuration struct if `Option<T>` arguments are provided.

## 4. Consistent Environment Variable Prefixes

All components MUST use a consistent naming convention for environment variables.

*   **Prefix Format:** `UPPERCASE_COMPONENT_NAME_` (e.g., `CHAINFIRE_`, `FLAREDB_`, `IAM_`).
*   **Nested Fields:** Use double underscores (`__`) to represent nested fields in the configuration structure.
    *   Example: For `network.api_addr`, the environment variable would be `CHAINFIRE_NETWORK__API_ADDR`.
*   **Case Conversion:** Configure `config-rs` to convert environment variable names to `snake_case` to match Rust struct field names (`.convert_case(config::Case::Snake)`).

## 5. Configuration Struct Guidelines

*   **Top-Level `ServerConfig`:** Each executable component (e.g., `chainfire-server`, `flaredb-server`) should have a single top-level `ServerConfig` (or similar name) struct that encapsulates all its settings.
*   **Modularity:** Break down `ServerConfig` into smaller, logical sub-structs (e.g., `NodeConfig`, `NetworkConfig`, `StorageConfig`, `ClusterConfig`) to improve readability and maintainability.
*   **`Default` Implementation:** All configuration structs and their sub-structs MUST implement `Default` to provide sensible starting values.
*   **Doc Comments:** Use clear doc comments for all configuration fields, explaining their purpose and acceptable values.

## 6. TLS/mTLS Configuration (Security)

All services MUST support optional TLS configuration for production deployments. The TLS configuration pattern ensures consistent security across all components.

### Standard TLS Configuration Structure

```rust
use serde::{Deserialize, Serialize};

/// TLS configuration for gRPC servers
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TlsConfig {
    /// Path to server certificate file (PEM format)
    pub cert_file: String,

    /// Path to server private key file (PEM format)
    pub key_file: String,

    /// Path to CA certificate file for client verification (optional, enables mTLS)
    pub ca_file: Option<String>,

    /// Require client certificates (mTLS mode)
    #[serde(default)]
    pub require_client_cert: bool,
}
```

### Integration Pattern

Services should include `tls: Option<TlsConfig>` in their server configuration:

```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerSettings {
    /// Listen address
    pub addr: SocketAddr,

    /// TLS configuration (optional)
    pub tls: Option<TlsConfig>,
}
```

### Server Builder Pattern (tonic)

```rust
use tonic::transport::{Server, ServerTlsConfig, Identity, Certificate};

let mut server = Server::builder();

if let Some(tls_config) = &config.server.tls {
    let cert = tokio::fs::read(&tls_config.cert_file).await?;
    let key = tokio::fs::read(&tls_config.key_file).await?;
    let server_identity = Identity::from_pem(cert, key);

    let tls = if tls_config.require_client_cert {
        // mTLS: require and verify client certificates
        let ca_cert = tokio::fs::read(
            tls_config.ca_file.as_ref()
                .ok_or("ca_file required when require_client_cert=true")?
        ).await?;
        let ca = Certificate::from_pem(ca_cert);

        ServerTlsConfig::new()
            .identity(server_identity)
            .client_ca_root(ca)
    } else {
        // TLS only: no client certificate required
        ServerTlsConfig::new()
            .identity(server_identity)
    };

    server = server.tls_config(tls)?;
}

server.add_service(my_service).serve(config.server.addr).await?;
```

### TOML Configuration Example

```toml
[server]
addr = "0.0.0.0:50051"

[server.tls]
cert_file = "/etc/centra-cloud/certs/iam/server.crt"
key_file = "/etc/centra-cloud/certs/iam/server.key"
ca_file = "/etc/centra-cloud/certs/ca.crt"
require_client_cert = true  # Enable mTLS
```

### Certificate Management

- **Development:** Use `scripts/generate-dev-certs.sh` to create self-signed CA and service certificates
- **Production:** Integrate with external PKI or use cert-manager for automated rotation
- **Storage:** Certificates stored in `/etc/centra-cloud/certs/` (NixOS managed)
- **Permissions:** Private keys must be readable only by service user (chmod 600)

By following these guidelines, we aim to achieve a unified, operator-friendly, and robust configuration system across the entire Cloud project.
