1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//! RFC3161 checks consume the selected original member through one common pass.
use crate::{
content::Content,
error::Error as ArchiveError,
zip::{MemberId, ReadFailure},
};
use structured_asn1::{Reader, memory::Execution, range::RangeSource};
use structured_cms::{
provider::SignatureProvider,
timestamp::{CheckContext, CheckedTimestamp, Token, TokenExtension},
};
/// Explicit check purpose; absence of live request fields never selects a
/// historical operation implicitly or relabels historical proof as freshness.
pub enum Context<'c, 'a, 'r> {
/// Complete ordinary request/current-reference processing.
Live(&'c CheckContext<'a, 'r>),
/// Archived evidence; no live request, comparison instant or window allowed.
Historical(&'c CheckContext<'a, 'r>),
}
/// Explicit covered input role. This does not assert that a source-produced
/// manifest is conforming, that its declared hashes match or that a TSA is trusted.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InputKind {
/// Original data or ordinary assertion-manifest bytes.
Data,
/// Selected original archive-manifest bytes; coverage needs the graph proof.
Archive,
}
/// Archive framing, actual payload and timestamp execution remain independent.
#[derive(Debug)]
pub enum Error<SE, PE, RE, D, G> {
/// Source generation/current-source execution refused before checking.
Archive(ArchiveError<SE>),
/// The actual original member cannot be acquired completely.
Payload(ReadFailure<SE, D, G>),
/// Unchanged common check cause, including its independently retained map.
Check(structured_cms::timestamp::CheckError<ReadFailure<SE, D, G>, PE, RE>),
}
/// One original token's actual input association and common execution answer.
/// This does not establish a trusted historical path or archive continuity.
pub struct Checked<'a, D, G> {
token: MemberId<D, G>,
input: MemberId<D, G>,
inner: CheckedTimestamp<'a>,
}
impl<'a, D: Copy, G: Copy> Checked<'a, D, G> {
/// Exact original time assertion, not a filename selected by success.
#[must_use]
pub fn token(&self) -> MemberId<D, G> {
self.token
}
/// Exact complete original file/manifest consumed by the imprint check.
#[must_use]
pub fn input(&self) -> MemberId<D, G> {
self.input
}
/// Every independent common timestamp answer, including negative outcomes.
#[must_use]
pub fn common(&self) -> &CheckedTimestamp<'a> {
&self.inner
}
/// Transfers the original common answer without copying evidence/source maps.
#[must_use]
pub fn into_common(self) -> CheckedTimestamp<'a> {
self.inner
}
}
impl<'v, 's, S: RangeSource> Content<'v, 's, S> {
/// Requires the actual carried token/source first, then invokes the shared
/// full asynchronous timestamp validator on the sealed original payload.
/// Candidate/key/time/extension recognition stay caller-provided contracts.
#[expect(
clippy::result_large_err,
reason = "retain original timestamp diagnostic maps on refusal without a secondary allocation"
)]
pub async fn check_timestamp<'a, P, PE, RE>(
&'a self,
token: &'a Token<'a>,
parent: &Reader<'a>,
provider: &'a P,
context: Context<'_, 'a, '_>,
input: &impl crate::payload::Payload<'v, 's, S>,
recognizes: impl FnMut(&TokenExtension<'_>, &Execution<'_>) -> Result<bool, RE>,
) -> Result<
Checked<'a, S::Document, S::Generation>,
Error<S::Error, PE, RE, S::Document, S::Generation>,
>
where
P: for<'scope> SignatureProvider<'scope, Error = PE>,
{
let execution = parent.execution();
self.require(token.message(), parent, &execution)
.map_err(Error::Archive)?;
if !core::ptr::eq(self.member().archive(), input.member().archive()) {
return Err(Error::Archive(ArchiveError::Foreign {
range: self.enclosure(),
}));
}
let mut source = input.source(&execution).map_err(Error::Payload)?;
let checked = match context {
Context::Live(context) => {
token
.check_async(provider, parent, context, &mut source, recognizes)
.await
}
Context::Historical(context) => {
token
.check_historical_async(provider, parent, context, &mut source, recognizes)
.await
}
}
.map_err(Error::Check)?;
self.member()
.archive()
.admit(&execution, self.enclosure())
.map_err(Error::Archive)?;
Ok(Checked {
token: self.member().id(),
input: input.member().id(),
inner: checked,
})
}
}