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
//! Typed builder for `Claim`.

use alloc::collections::BTreeMap;
use alloc::string::String;

use crate::claim::Claim;
use crate::composition::CompositionRecord;
use crate::error::CompositionError;
use crate::primitives::{
    anchor::Anchor, evidence::Evidence, predicate::Predicate,
    revelation_mask::RevelationMask, subject::Subject, temporal::TemporalFrame,
};

/// Typed builder for atomic Claims.
///
/// Composition records are produced by the operators in
/// [`crate::composition::ClaimComposition`], not by this builder.
#[derive(Debug, Default, Clone)]
pub struct ClaimBuilder {
    subject: Option<Subject>,
    predicate: Option<Predicate>,
    evidence: Option<Evidence>,
    temporal_frame: Option<TemporalFrame>,
    revelation_mask: Option<RevelationMask>,
    anchor: Option<Anchor>,
    composition: Option<CompositionRecord>,
    extensions: Option<BTreeMap<String, serde_json::Value>>,
}

impl ClaimBuilder {
    /// Create a new empty builder.
    pub fn new() -> Self {
        Self::default()
    }

    /// Set the subject.
    pub fn subject(mut self, s: Subject) -> Self {
        self.subject = Some(s);
        self
    }

    /// Set the predicate.
    pub fn predicate(mut self, p: Predicate) -> Self {
        self.predicate = Some(p);
        self
    }

    /// Set the evidence.
    pub fn evidence(mut self, e: Evidence) -> Self {
        self.evidence = Some(e);
        self
    }

    /// Set the temporal frame.
    pub fn temporal_frame(mut self, t: TemporalFrame) -> Self {
        self.temporal_frame = Some(t);
        self
    }

    /// Set the revelation mask.
    pub fn revelation_mask(mut self, m: RevelationMask) -> Self {
        self.revelation_mask = Some(m);
        self
    }

    /// Set the anchor list.
    pub fn anchor(mut self, a: Anchor) -> Self {
        self.anchor = Some(a);
        self
    }

    /// Attach a composition record (typically used by operator constructors).
    pub fn composition(mut self, c: CompositionRecord) -> Self {
        self.composition = Some(c);
        self
    }

    /// Attach forward-compatible extensions.
    pub fn extensions(mut self, ext: BTreeMap<String, serde_json::Value>) -> Self {
        self.extensions = Some(ext);
        self
    }

    /// Finalise and validate the Claim.
    pub fn build(self) -> Result<Claim, CompositionError> {
        let claim = Claim {
            subject: self
                .subject
                .ok_or(CompositionError::Invariant("subject is required"))?,
            predicate: self
                .predicate
                .ok_or(CompositionError::Invariant("predicate is required"))?,
            evidence: self
                .evidence
                .ok_or(CompositionError::Invariant("evidence is required"))?,
            temporal_frame: self
                .temporal_frame
                .ok_or(CompositionError::Invariant("temporal_frame is required"))?,
            revelation_mask: self
                .revelation_mask
                .ok_or(CompositionError::Invariant("revelation_mask is required"))?,
            anchor: self
                .anchor
                .ok_or(CompositionError::Invariant("anchor is required"))?,
            composition: self.composition,
            extensions: self.extensions,
            // transcript_version defaults to V1 for backward compat (§6 migration plan)
            #[cfg(feature = "transcript-v2")]
            transcript_version: crate::transcript_v2::TranscriptVersion::default(),
        };
        claim.validate()?;
        Ok(claim)
    }
}