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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
//! **One verifier. Every surface calls it.**
//!
//! [`verify_unit`] is the only place in this line where the question *"is this
//! unit what it says it is?"* is decided. The harness calls it. `newt frame
//! verify` calls it. A second implementation of a verification decision is two
//! answers waiting to disagree, and the one that disagrees quietly is the one
//! that ships.
//!
//! # What re-derivation actually means
//!
//! `checkOf .elide = .rederive` is a claim with content only if something can
//! be recomputed and compared. Here it is three comparisons, in the order a
//! sceptic would make them:
//!
//! 1. **Is this the source it names?** Hash the supplied bytes; compare to
//! [`Derivation::source`]. A verifier that trusts the caller's word about
//! which bytes are the source has verified nothing.
//! 2. **Does the address resolve?** The span must lie within those bytes.
//! 3. **Is the elided material what it claims?** Hash the addressed range;
//! compare to [`Derivation::elided`]. *This* is the re-derivation — the step
//! the previous revision had no recorded claim to perform.
//!
//! All three must hold. Any failure names both sides, because "verification
//! failed" that does not say what did not match sends the reader back to a
//! debugger.
//!
//! # One link is the whole obligation
//!
//! [`verify_unit`] checks **one** derivation and stops. It does not resolve the
//! source's own provenance, and it does not fail because the source is itself a
//! derived thing — that is the source's business, not this unit's.
//!
//! That is complete verification, not a pragmatic cut, and the reason is
//! `Unit.wf`. `depth <= 1` says nothing is more than one derivation away from
//! source material; a frame with no parents is genesis, the defined bottom. So
//! there is no deeper chain to regress into **by construction**. The forensic
//! obligation and the depth bound are the same constraint seen from two
//! directions — which is also why refusing `concise` and `generate` in v0 is
//! not merely caution: it is what keeps regress impossible.
//!
//! **And it does not resolve the root.** `verify_unit` recomputes the three
//! claims that the source bytes can settle — source, span, elided — and no
//! others. A unit naming a root id nothing ever minted verifies exactly like
//! one naming a real event, because the bytes in hand cannot tell them apart.
//! [`Verified`] therefore carries no root field: reporting one would imply this
//! function had established something about it. Root resolution belongs to
//! whoever holds the store, and `newt frame` reports it as a separate,
//! separately-failable fact.
//!
//! There is deliberately no walker here. [`Verified`] reports the source id
//! that was checked, so a caller who wants the next link calls again with it.
//! The recursion lives in the caller; nothing in this design forbids depth, it
//! simply does not implement an unbounded walk over data we do not control on
//! anybody's behalf.
//!
//! # Why not `NodeStore`
//!
//! `content-addressable`'s [`NodeStore`] is the right seam for units and
//! packets, and its `get` / `get_unverified` split is the distinction this
//! module honours. It cannot serve *source* bytes: it is keyed by [`ContentId`]
//! (the dag-cbor profile) and a source is an opaque byte string keyed by
//! [`RawContentId`] (the raw profile). The two are deliberately different types
//! with no conversion between them. [`SourceResolver`] is that second profile's
//! lookup, not a second copy of the first.
//!
//! [`NodeStore`]: https://docs.rs/content-addressable
//! [`Derivation::source`]: crate::Derivation::source
//! [`Derivation::elided`]: crate::Derivation::elided
use RawContentId;
use crateSpan;
use crateUnit;
/// Where source bytes come from.
///
/// Split verified/unverified in the same shape as `NodeStore`: an implementor
/// supplies the raw fetch, and verification is the caller's — here,
/// [`verify_unit`]'s — job. An implementation that "helpfully" verified inside
/// `resolve` would make the mismatch case untestable.
/// Both sides of a hash comparison.
///
/// Boxed inside [`VerifyError`] rather than inlined: a [`RawContentId`] is ~96
/// bytes, so two of them in a variant made every `Result` from [`verify_unit`]
/// 200 bytes wide — on the success path too. `clippy::result_large_err` is
/// right about that.
/// Why a unit did not verify.
/// What a successful verification establishes — the facts a report renders.
///
/// Returned rather than a bare `bool` so a caller (and `newt frame explain`)
/// reports what was checked, not merely that something was.
/// **The verification decision.** Recompute the unit's claims from the source
/// bytes and compare.
///
/// # Errors
///
/// See [`VerifyError`]; each variant names both the declared and the actual
/// value.
/// [`verify_unit`], fetching the source through a resolver.
///
/// A thin wrapper on purpose: the decision stays in one function, and this adds
/// only the fetch. The CLI uses this; the harness may use either.
///
/// # Errors
///
/// [`VerifyError::SourceUnavailable`] if the fetch fails, else whatever
/// [`verify_unit`] returns.