scalo 2.10.12

Self-regulating runtime for Rust data-plane services. Backpressure, load shedding and adaptive scaling are on by default.
// Project:   scalo
// File:      src/deployment/error.rs
// Purpose:   Deployment validation error types
// Language:  Rust
//
// License:   Apache-2.0
// Copyright: (c) 2026 HYPERI PTY LIMITED

//! Deployment validation error types.

use thiserror::Error;

/// A single contract mismatch between app defaults and deployment artifact.
#[derive(Debug, Clone)]
pub struct ContractMismatch {
    /// What was checked (e.g., "service.port", "EXPOSE port").
    pub field: String,
    /// Expected value (from app config).
    pub expected: String,
    /// Actual value (from deployment artifact).
    pub actual: String,
}

impl std::fmt::Display for ContractMismatch {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}: expected '{}', got '{}'",
            self.field, self.expected, self.actual
        )
    }
}

/// Errors from deployment validation and generation.
#[derive(Debug, Error)]
pub enum DeploymentError {
    /// Failed to read a deployment artifact file.
    #[error("failed to read {path}: {source}")]
    ReadFile {
        path: String,
        #[source]
        source: std::io::Error,
    },

    /// Failed to write a deployment artifact file.
    #[error("failed to write {path}: {source}")]
    WriteFile {
        path: String,
        #[source]
        source: std::io::Error,
    },

    /// Failed to create a directory.
    #[error("failed to create directory {path}: {source}")]
    CreateDir {
        path: String,
        #[source]
        source: std::io::Error,
    },

    /// Failed to parse YAML.
    #[error("failed to parse YAML in {path}: {source}")]
    ParseYaml {
        path: String,
        #[source]
        source: serde_yaml_ng::Error,
    },

    /// File not found.
    #[error("file not found: {0}")]
    NotFound(String),

    /// Failed to serialise an artefact (schema / capability catalog).
    #[error("failed to serialise {what}: {message}")]
    Serialise {
        /// What was being serialised (e.g. "config-schema.json").
        what: String,
        /// Underlying serialisation error message.
        message: String,
    },

    /// A committed config artefact drifted from the freshly-generated output.
    #[error("config artefact drift in {path}:\n{detail}")]
    Drift {
        /// The artefact path that drifted.
        path: String,
        /// Human-readable drift detail + remediation hint.
        detail: String,
    },
}