vauban-claim 0.1.0

Vauban Claim Algebra — reference implementation of draft-vauban-claim-algebra-00 (post-quantum claim sextuplet + 5 composition operators, canonical CBOR/JSON codec).
Documentation
//! Error types for encoding and composition.

use alloc::string::String;
use thiserror::Error;

/// Errors arising during canonical encoding or decoding.
#[derive(Debug, Error)]
pub enum EncodingError {
    /// CBOR serialisation failed.
    #[error("cbor serialisation failed: {0}")]
    CborSer(String),

    /// CBOR deserialisation failed.
    #[error("cbor deserialisation failed: {0}")]
    CborDe(String),

    /// JSON serialisation failed.
    #[error("json serialisation failed: {0}")]
    JsonSer(#[from] serde_json::Error),

    /// Encoded form contains a forbidden floating-point item (§ Numeric semantics).
    #[error("CBOR float encountered: floats MUST NOT appear in conformant Claims")]
    FloatForbidden,

    /// Map keys not in canonical order (RFC 8949 §4.2.1).
    #[error("non-canonical CBOR map key order")]
    NonCanonicalMapOrder,
}

/// Errors arising during composition (operator application or validity check).
#[derive(Debug, Error, PartialEq, Eq)]
pub enum CompositionError {
    /// Conjunction §6.1 C-1: subjects differ and no `linkage_proof` was provided.
    #[error("conjunction: subjects differ and no linkage proof supplied (C-1)")]
    SubjectMismatch,

    /// Conjunction §6.1 C-3: temporal windows do not intersect.
    #[error("conjunction: temporal windows do not intersect (C-3)")]
    TemporalDisjoint,

    /// Delegation §6.2 D-3: delegated scope exceeds parent scope.
    #[error("delegation: scope exceeds parent (D-2)")]
    ScopeOverflow,

    /// Delegation §6.2: cycle detected in the delegation chain.
    #[error("delegation: cycle detected — chain rejected per RFC 5280 §6.1.3")]
    DelegationCycle,

    /// Aggregation §6.3 G-1: two operands share an issuer key.
    #[error("aggregation: issuer-diversity violation (G-1)")]
    IssuerDuplicate,

    /// Aggregation §6.3: fewer than two operands.
    #[error("aggregation: at least 2 operands required")]
    AggregationTooFew,

    /// Restriction §6.4 R-1: new mask discloses fields not in the source mask.
    #[error("restriction: mask non-monotonic (R-1)")]
    MaskNonMonotonic,

    /// Restriction §6.4 M-1: `disclosed` and `committed` overlap in the new mask.
    #[error("restriction: disclosed ∩ committed ≠ ∅ (M-1)")]
    MaskDisjointnessViolation,

    /// Revocation §6.5 V-1: revoker is neither the original issuer nor a
    /// delegated authority.
    #[error("revocation: unauthorised revoker (V-1)")]
    UnauthorisedRevoker,

    /// Revocation §6.5: temporal frame already marks the source revoked.
    #[error("revocation: source already revoked (sticky)")]
    AlreadyRevoked,

    /// Generic structural validity violation (catch-all for invariant checks).
    #[error("structural invariant violated: {0}")]
    Invariant(&'static str),
}

/// Errors arising during TranscriptT1 operations.
#[derive(Debug, Error)]
pub enum TranscriptError {
    /// A required field is missing (e.g. subject.id both bytes and utf8 are None).
    #[error("transcript: missing field: {0}")]
    Missing(&'static str),

    /// CBOR encoding failed during transcript absorption.
    #[error("transcript: encoding failed: {0}")]
    Encoding(String),

    /// Transcript version mismatch — Claim's `transcript_version` does not match
    /// the verifier's expected version. Rejects downgrade attacks (§6 Q5).
    #[error("transcript: version mismatch: claim has {claim:?}, verifier expects {expected:?}")]
    VersionMismatch {
        /// The version tag found on the Claim.
        claim: alloc::string::String,
        /// The version tag required by the verifier.
        expected: alloc::string::String,
    },
}