//! Unified error type for the idfoto-core crate. //! //! Every fallible function in this crate returns [`Result`], which is an alias //! for `std::result::Result`. Using a single error enum keeps the //! public API surface predictable and makes error handling in callers (CLI, WASM //! bindings, mobile FFI) straightforward. use thiserror::Error; /// All errors that can originate from idfoto-core operations. /// /// Variants are ordered roughly by the pipeline stage where they occur: /// KDF -> encryption -> decryption -> format parsing -> entry lookup -> image /// steganography -> serialization -> device keys. #[derive(Debug, Error)] pub enum IdfotoError { /// The Argon2id key derivation failed. This typically means invalid KDF /// parameters were supplied (e.g., memory cost below Argon2's minimum). #[error("key derivation failed: {0}")] Kdf(String), /// XChaCha20-Poly1305 encryption failed. In practice this is extremely rare /// -- the only realistic cause is an internal library error, since the cipher /// accepts arbitrary-length plaintext. #[error("encryption failed: {0}")] Encrypt(String), /// Authenticated decryption failed. This means either the wrong master key /// was used (wrong passphrase or wrong reference image) or the ciphertext /// was tampered with / corrupted in transit or at rest. The error message is /// intentionally vague to avoid leaking information about which factor was /// wrong (passphrase vs. image). #[error("decryption failed: wrong key or corrupted data")] Decrypt, /// The binary ciphertext blob does not match the expected format (e.g., /// too short to contain the version byte + nonce + tag, or an unrecognized /// version byte). This usually indicates file corruption or a version /// mismatch between the writer and reader. #[error("invalid vault format: {0}")] Format(String), /// A vault entry was looked up by ID but does not exist in the manifest. /// The string payload is the missing entry ID. #[error("entry not found: {0}")] EntryNotFound(String), /// A general error from the image steganography subsystem (imgsecret). /// Covers issues like failing to decode the carrier JPEG or failing to /// encode the output JPEG after modification. #[error("imgsecret: {0}")] ImgSecret(String), /// The carrier image is too small to hold the embedded secret with /// sufficient redundancy. The embed region (central 70% of the image) /// must contain at least `BLOCKS_PER_COPY * MIN_COPIES` 8x8 blocks. #[error("image too small: need at least {min_width}x{min_height}, got {actual_width}x{actual_height}")] ImageTooSmall { min_width: u32, min_height: u32, actual_width: u32, actual_height: u32, }, /// Secret extraction from a JPEG failed. This can mean: /// - The image never had a secret embedded in it. /// - The image was recompressed below Q85, destroying the QIM watermarks. /// - The image was cropped beyond the 15% crumple zone. /// - Majority-vote confidence fell below the 60% threshold on one or more bits. #[error("extraction failed: no valid secret found in image")] ExtractionFailed, /// JSON serialization or deserialization of an entry or manifest failed. /// Wraps [`serde_json::Error`] transparently via `#[from]`. #[error("json error: {0}")] Json(#[from] serde_json::Error), /// An error related to device ed25519 key operations. Device keys are /// separate from the vault KDF -- revoking a device does not require /// rotating the passphrase or reference image. #[error("device key error: {0}")] DeviceKey(String), } /// Crate-wide result alias, reducing boilerplate in function signatures. pub type Result = std::result::Result;