cloacina 0.6.0

A Rust library for resilient task execution and orchestration.
Documentation
/*
 *  Copyright 2025-2026 Colliery Software
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

//! Domain models for package signatures.
//!
//! Package signatures provide cryptographic proof that a workflow package
//! was signed by a specific key. Signatures are Ed25519 signatures over
//! the SHA256 hash of the package binary.

use crate::database::universal_types::{UniversalTimestamp, UniversalUuid};
use serde::{Deserialize, Serialize};

/// Domain model for a package signature.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PackageSignature {
    pub id: UniversalUuid,
    /// SHA256 hex hash of the package binary
    pub package_hash: String,
    /// SHA256 hex fingerprint of the signing key
    pub key_fingerprint: String,
    /// Ed25519 signature (64 bytes)
    pub signature: Vec<u8>,
    pub signed_at: UniversalTimestamp,
    /// Organization id this signature is scoped to. NULL on rows that
    /// pre-date the column (CLOACI-I-0103). Server-side verification rejects
    /// NULL when `--require-signatures` is on.
    pub org_id: Option<UniversalUuid>,
}

/// Model for creating a new package signature.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NewPackageSignature {
    pub package_hash: String,
    pub key_fingerprint: String,
    pub signature: Vec<u8>,
    pub org_id: Option<UniversalUuid>,
}

impl NewPackageSignature {
    pub fn new(package_hash: String, key_fingerprint: String, signature: Vec<u8>) -> Self {
        Self {
            package_hash,
            key_fingerprint,
            signature,
            org_id: None,
        }
    }

    pub fn with_org_id(mut self, org_id: UniversalUuid) -> Self {
        self.org_id = Some(org_id);
        self
    }
}

/// Result of signature verification.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SignatureVerification {
    /// Whether the signature is valid
    pub is_valid: bool,
    /// The fingerprint of the key that signed the package
    pub signer_fingerprint: String,
    /// When the package was signed
    pub signed_at: UniversalTimestamp,
    /// Name of the signing key (if known)
    pub signer_name: Option<String>,
}