hyperi-rustlib 2.8.2

There's plenty of sage advice out there about how to run Rust services in production at scale — config cascades, structured logging, masking secrets, multi-backend secrets management, Prometheus, OpenTelemetry, Kafka transports, tiered disk-spillover sinks, adaptive worker pools, graceful shutdown — but almost none of it as code you can just install and use. This is that code. Opinionated, drop-in, working out of the box. The patterns from blog posts, watercooler chats and beers with your Google mates as actual library — not a framework you assemble from twenty crates and 8 weeks of munging.
Documentation
// Project:   hyperi-rustlib
// File:      src/deployment/error.rs
// Purpose:   Deployment validation error types
// Language:  Rust
//
// License:   BUSL-1.1
// 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),
}