Skip to main content

structured_xades/prepare/
fields.rs

1//! Original root field preflight before certificate/provider side effects.
2
3use super::{Prepared, UriError, check_uris};
4use crate::attributes::{self, AttributeXml};
5use crate::binary::BinaryXml;
6use crate::properties::{self, ClaimedTime, ClaimedTimeBinding, DateTimeXml};
7use crate::scalar::{ScalarXml, UriXml};
8use crate::xml::{Access, Xml};
9use structured_asn1::memory::Work;
10
11/// Completed root declared-attribute, URI/OID, optional validation-reference
12/// syntax and claimed-time checks against exactly this prepared source.
13/// The borrow prevents substituting another
14/// preparation when composing subsequent certificate/provider checks.
15///
16/// This is deliberately not whole-schema validity or a baseline level. Open
17/// property semantics, binary values, counters, certificate/path/status binding,
18/// policy acceptance and timestamp/material completeness remain obligations.
19pub struct Fields<'prepared, N, D, G> {
20    prepared: &'prepared super::Preparation<N, D, G>,
21    claimed_time: ClaimedTime<N, D, G>,
22}
23
24impl<N, D, G> Fields<'_, N, D, G> {
25    /// Same preparation whose original fields were checked, without reparsing.
26    #[must_use]
27    pub fn prepared(&self) -> &super::Preparation<N, D, G> {
28        self.prepared
29    }
30
31    /// Actual schema-qualified zoned claim, not a verified generation instant.
32    #[must_use]
33    pub fn claimed_time(&self) -> &ClaimedTime<N, D, G> {
34        &self.claimed_time
35    }
36}
37
38/// A failed/incomplete field never creates a successful preflight receipt.
39#[derive(Debug)]
40pub enum FieldError<E, N, D, G> {
41    /// Original root attribute declaration/scalar/source refusal.
42    Attributes(attributes::Error<E, N>),
43    /// Original URI/OID/policy-qualifier refusal.
44    Uri(UriError<E, N>),
45    /// Original optional validation-reference scalar/base64/method refusal.
46    ValidationReference(crate::validation::ReferenceFieldError<E, N, D, G>),
47    /// Original claimed-time source/current-operation refusal.
48    Time(properties::ClaimedTimeError<E, N>),
49    /// Completed claimed-time interpretation did not establish a zoned claim.
50    UnprovenTime {
51        /// Original protected `SigningTime`.
52        node: N,
53        /// Unsupported, malformed and genuinely absent timezone stay distinct.
54        cause: properties::ClaimedTimeFailure,
55    },
56}
57
58/// Root preflight in the XML owner's original identity/error domain.
59pub type FieldResult<'prepared, X> = Result<
60    Fields<'prepared, <X as Xml>::Id, <X as Xml>::Document, <X as Xml>::Generation>,
61    FieldError<<X as Xml>::Error, <X as Xml>::Id, <X as Xml>::Document, <X as Xml>::Generation>,
62>;
63
64/// Execute root field preflight in one ordered path, BEFORE certificate hashes,
65/// key association, path building or timestamp/provider work. Optional original
66/// reference fields use their retained structural model and XML-owned scalar/
67/// base64 kernels; this does not compare references against actual artifacts.
68/// It invokes the
69/// existing field kernels once; no successful caller-supplied flags or copied
70/// normalized values can stand in for the original protected source.
71///
72/// All operations use this current Access/Work, even when preparation survives
73/// its earlier parsing operation. Refusal drops temporary OID/attribute scratch;
74/// the prepared source and its retained storage account remain unchanged.
75pub fn check_fields<'prepared, X, W>(
76    prepared: &'prepared Prepared<X>,
77    access: &Access<'_, X, W>,
78) -> FieldResult<'prepared, X>
79where
80    X: AttributeXml + ScalarXml + UriXml + DateTimeXml + BinaryXml,
81    W: Work,
82{
83    attributes::check_prepared(prepared, access).map_err(FieldError::Attributes)?;
84    check_uris(prepared, access).map_err(FieldError::Uri)?;
85    for index in 0..prepared.validation_references().len() {
86        access.execution().charge_work(1).map_err(|cause| {
87            FieldError::ValidationReference(crate::validation::ReferenceFieldError::Resource {
88                node: prepared.bound().containers().signature(),
89                cause,
90            })
91        })?;
92        crate::validation::check_reference_fields(&prepared.validation_references()[index], access)
93            .map_err(FieldError::ValidationReference)?;
94    }
95    let claimed_time =
96        match properties::check_time(prepared.signed(), access).map_err(FieldError::Time)? {
97            ClaimedTimeBinding::Bound(claimed_time) => claimed_time,
98            ClaimedTimeBinding::Unproven { node, cause } => {
99                return Err(FieldError::UnprovenTime { node, cause });
100            }
101        };
102    Ok(Fields {
103        prepared,
104        claimed_time,
105    })
106}