@sanning/proof 0.19.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -29
- package/dist/agent-record.d.ts +62 -0
- package/dist/agent-record.js +527 -0
- package/dist/agent-schemas.generated.d.ts +15 -0
- package/dist/agent-schemas.generated.js +5759 -0
- package/dist/case-file.d.ts +32 -89
- package/dist/case-file.js +41 -93
- package/dist/case.d.ts +343 -810
- package/dist/case.js +693 -1151
- package/dist/chain.d.ts +19 -47
- package/dist/chain.js +78 -205
- package/dist/claims.d.ts +211 -0
- package/dist/claims.js +1081 -0
- package/dist/cli.d.ts +45 -68
- package/dist/cli.js +618 -1022
- package/dist/compose.js +23 -65
- package/dist/crypto.d.ts +7 -8
- package/dist/crypto.js +60 -147
- package/dist/declaration.d.ts +68 -194
- package/dist/declaration.js +175 -518
- package/dist/environment.d.ts +9 -30
- package/dist/environment.js +17 -66
- package/dist/evidence.d.ts +119 -160
- package/dist/evidence.js +744 -1103
- package/dist/exit-codes.d.ts +11 -27
- package/dist/exit-codes.js +24 -59
- package/dist/file-match.d.ts +33 -79
- package/dist/file-match.js +33 -69
- package/dist/grading.d.ts +98 -135
- package/dist/grading.js +224 -380
- package/dist/handoff.d.ts +62 -160
- package/dist/handoff.js +153 -393
- package/dist/index.d.ts +14 -10
- package/dist/index.js +60 -167
- package/dist/json-schema.d.ts +29 -0
- package/dist/json-schema.js +298 -0
- package/dist/merkle.js +16 -28
- package/dist/message-parts.d.ts +56 -212
- package/dist/message-parts.js +142 -502
- package/dist/side-content.d.ts +11 -22
- package/dist/side-content.js +22 -65
- package/dist/types.d.ts +17 -0
- package/dist/types.js +19 -5
- package/dist/verifier.d.ts +40 -114
- package/dist/verifier.js +196 -535
- package/dist/witness-cache.d.ts +24 -45
- package/dist/witness-cache.js +38 -81
- package/dist/witness-lookup.d.ts +36 -57
- package/dist/witness-lookup.js +89 -139
- package/dist/zip-reader.d.ts +18 -33
- package/dist/zip-reader.js +19 -34
- package/package.json +11 -3
- package/src/agent-record.ts +608 -0
- package/src/agent-schemas.generated.ts +5764 -0
- package/src/case-file.ts +45 -109
- package/src/case.ts +848 -1322
- package/src/chain.ts +85 -224
- package/src/claims.ts +1253 -0
- package/src/cli.ts +714 -1176
- package/src/compose.ts +33 -79
- package/src/crypto.ts +60 -147
- package/src/declaration.ts +219 -656
- package/src/environment.ts +17 -65
- package/src/evidence.ts +958 -1381
- package/src/exit-codes.ts +24 -63
- package/src/file-match.ts +40 -89
- package/src/grading.ts +287 -421
- package/src/handoff.ts +175 -427
- package/src/index.ts +132 -177
- package/src/json-schema.ts +295 -0
- package/src/merkle.ts +16 -28
- package/src/message-parts.ts +155 -533
- package/src/side-content.ts +25 -68
- package/src/types.ts +55 -36
- package/src/verifier.ts +202 -526
- package/src/witness-cache.ts +45 -94
- package/src/witness-lookup.ts +107 -177
- package/src/zip-reader.ts +20 -38
- package/vectors/README.md +52 -34
- package/vectors/agent-record.json +2175 -0
- package/vectors/case-file-index.json +1 -1
- package/vectors/case-split.json +2 -2
- package/vectors/chain-reading.json +3 -3
- package/vectors/file-match.json +285 -148
- package/vectors/jcs-reader.json +6 -6
- package/vectors/pack-grading.json +102 -25
- package/vectors/sandbox-evidence.json +597 -580
- package/vectors/stamp-on-chain.json +18 -18
- package/vectors/witness-cache.json +49 -49
- package/dist/agent-proof.d.ts +0 -28
- package/dist/agent-proof.js +0 -226
- package/dist/run-adapters.d.ts +0 -10
- package/dist/run-adapters.js +0 -35
- package/dist/run.d.ts +0 -209
- package/dist/run.js +0 -1405
- package/src/agent-proof.ts +0 -264
- package/src/run-adapters.ts +0 -44
- package/src/run.ts +0 -1598
package/dist/case.d.ts
CHANGED
|
@@ -1,1006 +1,543 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* One verdict for a
|
|
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
|
-
* (anchor#198, and DL-60: producer identity gates what the plane accepts and
|
|
63
|
-
* never whether evidence verifies). The union pile is not partitioned by pack,
|
|
64
|
-
* by issuer, by `tenant_id` or by organization anywhere in this module, so a
|
|
65
|
-
* pair assembled by two organizations reads exactly as a pair assembled by
|
|
66
|
-
* one. There is no code path here that reads a tenant.
|
|
67
|
-
*
|
|
68
|
-
* THE DEFECT CLASS THIS MODULE IS WRITTEN AGAINST
|
|
69
|
-
* ===============================================
|
|
70
|
-
*
|
|
71
|
-
* Seventeen findings on this program share one generator: **a deviation
|
|
72
|
-
* designed as a comparison between two present things, where the deviation
|
|
73
|
-
* itself removes one of them, so the code takes the "nothing to compare"
|
|
74
|
-
* branch written for the honest case.** A rule shaped that way reads the
|
|
75
|
-
* absence of a signal as "fine" rather than as "I could not tell", and a real
|
|
76
|
-
* deviation grades clean.
|
|
77
|
-
*
|
|
78
|
-
* Acceptance criterion 3 of anchor#198 is made of exactly that shape: *a
|
|
79
|
-
* one-sided hand-off is an exception, not a failure*. So the four rules below
|
|
80
|
-
* are structural and are the thing to preserve in any change here.
|
|
81
|
-
*
|
|
82
|
-
* 1. **Every exception is NAMED and appears in the output, and every exception
|
|
83
|
-
* contributes a verdict.** There is no path through this module that
|
|
84
|
-
* removes a record, a pack or a claim from the reading. An empty
|
|
85
|
-
* `exceptions` is the ONLY shape a reader may read as clean, and `readCase`
|
|
86
|
-
* is invariant: `verified` is reachable only when that array is empty.
|
|
87
|
-
* 2. **Nothing a party writes decides whether grading happens.** No graded
|
|
88
|
-
* value is part of any key that selects a code path. The pile is everything
|
|
89
|
-
* every pack supplied; there is no filter.
|
|
90
|
-
* 3. **Every field that selects a code path and is chosen by the party being
|
|
91
|
-
* audited has an accept-set, and an unknown value goes to a named exception
|
|
92
|
-
* rather than to silence.** `body_type` is `CASE_BODY_TYPES`;
|
|
93
|
-
* `declaration_version` is `checkDeclaration`'s; `event_type` and
|
|
94
|
-
* `event.counterparty_public_key` are 4.1's, through `readHandoffs`. A pack
|
|
95
|
-
* that supplies zero records is `PACK_HOLDS_NO_RECORDS` and a case with no
|
|
96
|
-
* hand-off record in it at all is `CASE_HOLDS_NO_HANDOFF_RECORDS`, because
|
|
97
|
-
* "nothing to grade" is never "nothing is wrong".
|
|
98
|
-
* 4. **The 4.1 predicates are CALLED, never restated.** `readHandoffs`,
|
|
99
|
-
* `normalizedSigningKey` and `packRecords` are the one implementation of
|
|
100
|
-
* each rule. A validation copied beside the one that enforces it drifts,
|
|
101
|
-
* and a copy that is looser blesses a value the real one then rejects.
|
|
102
|
-
*
|
|
103
|
-
* EVERY EARLY EXIT IN THIS MODULE, AND WHAT IT SKIPS
|
|
104
|
-
* ==================================================
|
|
105
|
-
*
|
|
106
|
-
* Three defects on this layer were one shape: an exit between a record
|
|
107
|
-
* entering the pile and a check running over it, with the audited party
|
|
108
|
-
* choosing whether the exit was taken. So the exits are enumerated here rather
|
|
109
|
-
* than left to be rediscovered a fourth time. `src/sanning_proof/case.py` has
|
|
110
|
-
* the same exits in the same order, and the pull request that added this list
|
|
111
|
-
* carries the same table.
|
|
112
|
-
*
|
|
113
|
-
* 1. **No packs** (`return`). Skips everything. Reached by the reader, who
|
|
114
|
-
* chose what to hand in. Named: `CASE_HOLDS_NO_PACKS`.
|
|
115
|
-
* 2. **A wrapper key this reader cannot read** (`continue`). Skips the bundle
|
|
116
|
-
* verification, the declaration check and every record in the pack. The
|
|
117
|
-
* holder writes the key, so it steers here freely, and the pack is NAMED
|
|
118
|
-
* (`PACK_KEY_UNREADABLE`). Both bundle verifiers now refuse every such
|
|
119
|
-
* spelling in the same words (proof#142), so this exit and exit 3 agree on
|
|
120
|
-
* which packs they take; it stays first because it names WHY. While any
|
|
121
|
-
* pack takes this exit, a one-sided record whose named key signed no pack
|
|
122
|
-
* reads `COUNTERPART_ABSENT_SIGNER_UNKNOWN` and never the innocent
|
|
123
|
-
* `COUNTERPART_ABSENT`.
|
|
124
|
-
* 3. **The wrapper does not hold** (`continue`): `signatureOk` and
|
|
125
|
-
* `bodyHashOk` are not both true. Skips the declaration check and every
|
|
126
|
-
* record in the pack, and the key it claims is never counted as a pack
|
|
127
|
-
* signer. **This is the forger's case and the only exit that turns on
|
|
128
|
-
* provenance**: those two fields are the whole of what ties a pack to a
|
|
129
|
-
* key. Reached by whoever built the pack, and by anyone who alters its
|
|
130
|
-
* unsigned `signature` field, which is indistinguishable from a forgery.
|
|
131
|
-
* Named: `PACK_DOES_NOT_VERIFY`, and it moves one-sided records to
|
|
132
|
-
* `COUNTERPART_ABSENT_SIGNER_UNKNOWN` exactly as exit 2 does.
|
|
133
|
-
*
|
|
134
|
-
* A pack whose wrapper HOLDS is never sent here, whatever is wrong inside
|
|
135
|
-
* it (gate 3 on proof#140): its key is counted, its own bundle verdict is
|
|
136
|
-
* `PACK_BUNDLE_NOT_VERIFIED` when that verdict is not `verified`, and each
|
|
137
|
-
* record is graded on its own envelope below.
|
|
138
|
-
* 3b. **The bundle verdict is `malformed`** (`continue`, after exit 3 and after
|
|
139
|
-
* `PACK_BUNDLE_NOT_VERIFIED`). The body is one the verifier could not read,
|
|
140
|
-
* so it graded no record. The key is already counted.
|
|
141
|
-
* 4. **`body_type` outside `CASE_BODY_TYPES`** (`continue`). Skips the
|
|
142
|
-
* declaration check and every record in the pack. The holder writes
|
|
143
|
-
* `body_type`, so the holder steers here freely, which is why it is named
|
|
144
|
-
* every time (`PACK_BODY_TYPE_UNKNOWN`) and why the pack's wrapper key is
|
|
145
|
-
* counted ABOVE it: a counterparty cannot leave the damning counterpart
|
|
146
|
-
* line by choosing a body (F3). `sanning.evidence.export/v2` lands here and
|
|
147
|
-
* is not unwrapped.
|
|
148
|
-
* 5. **No records** (`continue`). Skips the declaration check, over nothing.
|
|
149
|
-
* The holder steers here by handing over an empty `events[]`. Named:
|
|
150
|
-
* `PACK_HOLDS_NO_RECORDS`; the wrapper key is already counted.
|
|
151
|
-
* 5b. **A record under a quarantined profile** and 5c. **a record whose own
|
|
152
|
-
* envelope does not verify** (`continue`). Each skips 4.1 for that record,
|
|
153
|
-
* its candidacy for any other record, and the claim check, because 4.1
|
|
154
|
-
* compares only envelopes that verified (`HeldRecord`). Named:
|
|
155
|
-
* `RECORD_PROFILE_QUARANTINED` (`incomplete`, pending DL-63) and
|
|
156
|
-
* `RECORD_ENVELOPE_DOES_NOT_VERIFY` (`failed`). Neither removes a named
|
|
157
|
-
* failure from another record: the other records of the pack are still
|
|
158
|
-
* graded, and pairs still form over every record that verified.
|
|
159
|
-
* 6. **`event_bytes` withheld** and 7. **`event_bytes` unreadable**
|
|
160
|
-
* (`continue`). Each skips 4.1 for that record, its candidacy for any other
|
|
161
|
-
* record, and the claim check. The holder steers into both by what it
|
|
162
|
-
* discloses. Each is named in the claim check's place
|
|
163
|
-
* (`RECORD_BYTES_WITHHELD` `incomplete`, `RECORD_BYTES_UNREADABLE`
|
|
164
|
-
* `malformed`), so neither buys a cleaner reading than an unclaimed record
|
|
165
|
-
* would get, and neither decides which counterpart kind another record
|
|
166
|
-
* gets, since that reads wrapper keys.
|
|
167
|
-
*
|
|
168
|
-
* Not exits: a record whose envelope verifies and whose content does not
|
|
169
|
-
* match its commitment is `RECORD_CONTENT_MISMATCH` where that content is
|
|
170
|
-
* inside the signed body and `RECORD_CONTENT_DEPENDENT` where it was handed
|
|
171
|
-
* in beside the pack (proof#159), and one that fails
|
|
172
|
-
* another check inside its pack is `RECORD_DOES_NOT_VERIFY_IN_ITS_PACK`.
|
|
173
|
-
* Both are named and both STAY in the pile, so neither unsigned content
|
|
174
|
-
* handed in beside a pack nor a broken inclusion proof removes a record
|
|
175
|
-
* from pairing.
|
|
176
|
-
* 8. **`not_a_handoff_record`** (`continue`). Skips the hand-off count and the
|
|
177
|
-
* counterpart, ambiguity and pair reporting, which 4.1 does not give a
|
|
178
|
-
* record outside its scope. The holder steers here by respelling a field.
|
|
179
|
-
* It no longer skips the claim check, which runs ABOVE it because it asks
|
|
180
|
-
* what the pack SAID and not what the record is (F1).
|
|
181
|
-
* 9. **THIS record is malformed** (`continue`). Skips the counterpart,
|
|
182
|
-
* ambiguity and pair reporting, and 4.1 computed none of them for a
|
|
183
|
-
* malformed subject, so nothing is lost. A party steers here only by
|
|
184
|
-
* breaking a record it signed, and the record is named `RECORD_MALFORMED`.
|
|
185
|
-
* A well formed record whose CANDIDATE is malformed does not take this
|
|
186
|
-
* exit: it is `COUNTERPART_MALFORMED` and the reporting below still runs
|
|
187
|
-
* (F2).
|
|
188
|
-
* 10. **`counterpart_absent`** (`continue`). Skips the ambiguity and pair
|
|
189
|
-
* reporting, and there is nothing to skip: 4.1 emits that finding only
|
|
190
|
-
* where no candidate is left to read, an EMPTY candidate list or one whose
|
|
191
|
-
* every candidate another record accounts for (4.1 v1.17, A20). Which of the three counterpart kinds it
|
|
192
|
-
* gets reads the keys of the packs that verified, counted before exit 4,
|
|
193
|
-
* and whether any pack took exit 2 or 3.
|
|
194
|
-
*
|
|
195
|
-
* Not an exit, and listed because it is one more place this shape could
|
|
196
|
-
* hide: the claim check runs only where the pack's declaration is READABLE. An
|
|
197
|
-
* absent or unreadable one is named once for the pack (`PACK_UNDECLARED`,
|
|
198
|
-
* `PACK_DECLARATION_UNREADABLE`) rather than once per record.
|
|
199
|
-
*
|
|
200
|
-
* THE VERDICT VOCABULARY IS CLOSED
|
|
201
|
-
* ================================
|
|
202
|
-
*
|
|
203
|
-
* `verified`, `failed`, `partial`, `mixed`, `incomplete` and `malformed`,
|
|
204
|
-
* every one of them already in use (`evidence-bundle.md` 3 and
|
|
205
|
-
* `PACK_VERDICTS`). **No new word is coined anywhere in this module**, and
|
|
206
|
-
* `CASE_VERDICTS` is asserted against `PACK_VERDICTS` by the test suite so a
|
|
207
|
-
* future addition here cannot invent one quietly. Everything this module has
|
|
208
|
-
* to say that is not one of those six is an EXCEPTION KIND reported beside the
|
|
209
|
-
* verdict, exactly as `counterpart_absent` and `not_a_handoff_record` are
|
|
210
|
-
* findings beside a verdict in 4.1.
|
|
211
|
-
*
|
|
212
|
-
* A case with any `failed` contribution is `failed`: a proven failure keeps
|
|
213
|
-
* the headline (5.5.4 v1.16, A17, proof#158). Otherwise a case with more than
|
|
214
|
-
* one outcome is `mixed` (anchor#198, criterion 4).
|
|
215
|
-
*
|
|
216
|
-
* WHAT THIS READER DOES NOT CLAIM
|
|
217
|
-
* ===============================
|
|
218
|
-
*
|
|
219
|
-
* * **Not that the case is complete.** Joining is voluntary. A counterparty
|
|
220
|
-
* that never handed over a pack leaves `COUNTERPART_ABSENT`, which is an
|
|
221
|
-
* exception and never a failure. It says that no pack in the case is signed
|
|
222
|
-
* by the named key, and nothing about what that party recorded.
|
|
223
|
-
* * **Not that a party which presented no pack under the named key recorded
|
|
224
|
-
* nothing.** See the top of this comment, and proof#143.
|
|
225
|
-
* * **Not that two organizations are independent.** One team holding both keys
|
|
226
|
-
* proves which agent said what, not that two parties agreed (4.1, 5.4.4).
|
|
227
|
-
* * **Not that a `verified` case has no other problem.** It reads hand-offs.
|
|
228
|
-
* It runs `verifyEvidenceBundle` over every pack itself, offline and with no
|
|
229
|
-
* gateways, and a pack whose own bundle verdict is not `verified` is named
|
|
230
|
-
* with that verdict and its reasons, so the case never reads above its
|
|
231
|
-
* weakest pack. On-chain re-fetch and `gradePack` are a caller's to run.
|
|
232
|
-
*
|
|
233
|
-
* THE COST OF 4.1's "GRADE EVERY CANDIDATE", AND WHAT IS LEFT OF IT (4.1
|
|
234
|
-
* v1.17, amendment A20, which reopens proof#134). Up to v1.16 a pile holding
|
|
235
|
-
* two or more records of the complementary type signed by one counterparty key
|
|
236
|
-
* could not reach `verified`. 4.1 now sets such a candidate aside where a
|
|
237
|
-
* record the subject's own key signed pairs with it verified at another
|
|
238
|
-
* sequence, so two messages in one direction, and the demo's A to B, B to A,
|
|
239
|
-
* A to B, read clean. What is left surfaces as `COUNTERPART_AMBIGUOUS` beside
|
|
240
|
-
* the failure: fan-in, fan-out, and the same pair in two cases at the same
|
|
241
|
-
* sequence. Narrowing any of it here with `handoffs[]` is precisely the move
|
|
242
|
-
* that would reopen proof#137's door.
|
|
2
|
+
* One verdict for a case: several packs, possibly from several organizations.
|
|
3
|
+
* Conformance: `test-vectors/case/`.
|
|
4
|
+
*
|
|
5
|
+
* A pack a party assembles about itself is not self-proving about what that
|
|
6
|
+
* party left out: a holder can declare a record and claim it nowhere, and the
|
|
7
|
+
* pack still reads `verified` (`declaration-unclaimed-record-01`). Reading
|
|
8
|
+
* several parties' packs at once closes that. An `agent.handoff.sent` with no
|
|
9
|
+
* counterpart among the case's records is always named, and when a pack signed
|
|
10
|
+
* by the key that record names is in the case, the reading says that pack
|
|
11
|
+
* holds no counterpart. It does not establish that a party which presented no
|
|
12
|
+
* such pack recorded nothing: nothing binds a pack's wrapper key to its
|
|
13
|
+
* records' keys.
|
|
14
|
+
*
|
|
15
|
+
* How the join works:
|
|
16
|
+
* - Records pair with records, through `readHandoffs`, over the union of every
|
|
17
|
+
* record every pack supplied. `handoffs[]` is written by the audited party,
|
|
18
|
+
* so it never selects a pair; it is read only to name a declared record that
|
|
19
|
+
* is claimed nowhere (`RECORD_UNCLAIMED`).
|
|
20
|
+
* - Matching is on hashes and identifiers only, never tenancy. Nothing here
|
|
21
|
+
* partitions the pile by pack, issuer, `tenant_id` or organization.
|
|
22
|
+
*
|
|
23
|
+
* Structural rules, to preserve in any change:
|
|
24
|
+
* 1. Every exception is named in the output and contributes a verdict.
|
|
25
|
+
* Nothing removes a record, pack or claim from the reading. `verified` is
|
|
26
|
+
* reachable only when `exceptions` is empty.
|
|
27
|
+
* 2. Nothing a party writes decides whether grading happens. The pile is
|
|
28
|
+
* everything every pack supplied.
|
|
29
|
+
* 3. Every party-chosen field that selects a code path has an accept-set, and
|
|
30
|
+
* an unknown value is a named exception. "Nothing to grade" is never
|
|
31
|
+
* "nothing is wrong".
|
|
32
|
+
* 4. The §4.1 predicates (`readHandoffs`, `normalizedSigningKey`,
|
|
33
|
+
* `packRecords`) are called, never restated.
|
|
34
|
+
*
|
|
35
|
+
* Every early exit in `readCase` names its exception, so no exit buys a
|
|
36
|
+
* cleaner reading than the record or pack would otherwise get. In particular:
|
|
37
|
+
* - A pack with an unreadable key or a wrapper that does not hold is skipped
|
|
38
|
+
* and its key never counted; while any pack takes that exit, a one-sided
|
|
39
|
+
* record reads `COUNTERPART_ABSENT_SIGNER_UNKNOWN`, never `COUNTERPART_ABSENT`.
|
|
40
|
+
* - A wrapper key is counted before the body-type and no-records exits, so
|
|
41
|
+
* choosing a body cannot dodge the counterpart line.
|
|
42
|
+
* - The claim check runs before the not-a-hand-off and malformed exits, so
|
|
43
|
+
* respelling or breaking a record cannot switch it off.
|
|
44
|
+
* - Content and in-pack failures are named and the record stays in the pile.
|
|
45
|
+
*
|
|
46
|
+
* The verdict vocabulary is closed: `verified`, `failed`, `incomplete`
|
|
47
|
+
* (evidence-bundle.md section 3). Every exception maps to one claim and one
|
|
48
|
+
* state (`claims.ts`), and the case reads its worst pack: any `failed`
|
|
49
|
+
* contribution makes the case `failed`, otherwise any `incomplete` makes it
|
|
50
|
+
* `incomplete`, and a reading with no contribution is `verified`.
|
|
51
|
+
*
|
|
52
|
+
* Not claimed: that the case is complete (joining is voluntary), that two
|
|
53
|
+
* organizations are independent (one team can hold both keys), or that a
|
|
54
|
+
* `verified` case has no other problem. Every pack is verified offline here
|
|
55
|
+
* and a pack whose bundle is not `verified` is named; on-chain re-fetch and
|
|
56
|
+
* `gradePack` are the caller's.
|
|
57
|
+
*
|
|
58
|
+
* Several records of the complementary type under one counterparty key can
|
|
59
|
+
* still be ambiguous (fan-in, fan-out, one pair in two cases at one sequence):
|
|
60
|
+
* that surfaces as `COUNTERPART_AMBIGUOUS`. Narrowing it with `handoffs[]`
|
|
61
|
+
* would reopen the hole above.
|
|
243
62
|
*/
|
|
244
63
|
import { type DeclarationRole } from "./declaration.js";
|
|
64
|
+
import { type AgentRecordReading } from "./agent-record.js";
|
|
245
65
|
import { type PackGradeCauseKind, type PackVerdict } from "./grading.js";
|
|
66
|
+
import type { EnvironmentMarker } from "./environment.js";
|
|
246
67
|
import type { SideContentMap } from "./side-content.js";
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
* no new verdict word is introduced anywhere.
|
|
251
|
-
*/
|
|
252
|
-
export declare const CASE_VERDICTS: readonly ["verified", "failed", "partial", "mixed", "incomplete", "malformed"];
|
|
68
|
+
import { type Problem, type ReasonKind } from "./claims.js";
|
|
69
|
+
/** The three verdicts (evidence-bundle.md section 3). A case reads its worst pack. */
|
|
70
|
+
export declare const CASE_VERDICTS: readonly ["verified", "failed", "incomplete"];
|
|
253
71
|
export type CaseVerdict = (typeof CASE_VERDICTS)[number];
|
|
254
72
|
/**
|
|
255
|
-
* The
|
|
256
|
-
* (
|
|
73
|
+
* The pack bodies that carry `events[]` and may carry a `declaration`
|
|
74
|
+
* (evidence-bundle.md §5.4.1). An accept-set: `body_type` is party-written, so
|
|
75
|
+
* an unknown value is `PACK_BODY_TYPE_UNKNOWN`, never zero records read clean.
|
|
257
76
|
*
|
|
258
|
-
* `
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
* the case read clean over it: the exact defect class this module is written
|
|
262
|
-
* against. An unknown value is `PACK_BODY_TYPE_UNKNOWN`.
|
|
263
|
-
*
|
|
264
|
-
* **`sanning.evidence.export/v2` is NOT in this set and is NOT unwrapped.** It
|
|
265
|
-
* verifies as a bundle and carries a whole `sanning.anchor.trace/v3` pack under
|
|
266
|
-
* `body.source_bundle`, so its records do not reach the pile and the export is
|
|
267
|
-
* named `PACK_BODY_TYPE_UNKNOWN`, `incomplete`. Reading inside it changes which
|
|
268
|
-
* packs this reader grades, so it is a decision of its own. A reader who needs
|
|
269
|
-
* the records hands in the source bundle as a pack. The export's wrapper key is
|
|
270
|
-
* still read, so wrapping a pack in one does not change which counterpart kind
|
|
271
|
-
* another record gets.
|
|
77
|
+
* `sanning.evidence.export/v2` is not unwrapped: it is named
|
|
78
|
+
* `PACK_BODY_TYPE_UNKNOWN`, and a reader who needs its records hands in the
|
|
79
|
+
* source bundle. Its wrapper key is still read.
|
|
272
80
|
*/
|
|
273
81
|
export declare const CASE_BODY_TYPES: readonly ["sanning.anchor.trace/v3", "sanning.stamp.evidence/v2"];
|
|
274
82
|
/**
|
|
275
|
-
* The
|
|
276
|
-
* accept-set
|
|
277
|
-
*
|
|
278
|
-
* from that file, and a test here pins this one equal to this kernel's own
|
|
279
|
-
* `ACCEPTED_SPEC_MAJORS`, which is what `verifyEvidenceBundle` reads under:
|
|
280
|
-
* the Python kernel narrows its verifier to this set for the case reader, and
|
|
281
|
-
* this kernel's verifier already reads exactly it. If this kernel ever admits
|
|
282
|
-
* a quarantined profile, that test fails, and the case reader has to narrow
|
|
283
|
-
* its verifier the way the Python one does before it can pass.
|
|
83
|
+
* The profiles records are read under: the accept-set (envelope-spec.md §5)
|
|
84
|
+
* minus quarantined profiles in `cross-kernel/accept-set.json`. A test pins
|
|
85
|
+
* this equal to `ACCEPTED_SPEC_MAJORS`, which `verifyEvidenceBundle` reads under.
|
|
284
86
|
*/
|
|
285
|
-
export declare const CASE_RECORD_PROFILES: readonly ["sanning.
|
|
286
|
-
/**
|
|
87
|
+
export declare const CASE_RECORD_PROFILES: readonly ["sanning.events/v2"];
|
|
88
|
+
/** Accepted profiles under quarantine. */
|
|
287
89
|
export declare const CASE_QUARANTINED_PROFILES: readonly ["sanning.mlflow/v1"];
|
|
288
90
|
/**
|
|
289
|
-
* A conformant hand-off record with no counterpart
|
|
290
|
-
*
|
|
291
|
-
*
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
* That is ALL it says. It does not say the counterparty's account is absent,
|
|
297
|
-
* and it does not say nothing was tampered with: a counterparty that signs its
|
|
298
|
-
* own pack under a second key, or hands over an export an issuer signed,
|
|
299
|
-
* reaches this reading too, and nothing offline binds a pack's key to the keys
|
|
300
|
-
* of the records inside it (proof#143). The rendered text states the fact and
|
|
301
|
-
* stops.
|
|
302
|
-
*
|
|
303
|
-
* It says nothing about RECORDS signed by that key either. A party may hold records
|
|
304
|
-
* its counterparty signed, and those are still graded as candidates, but they
|
|
305
|
-
* are not the counterparty's account of itself, so they do not move this
|
|
306
|
-
* record to `COUNTERPART_ABSENT_FROM_COUNTERPARTY_RECORDS`.
|
|
91
|
+
* A conformant hand-off record with no counterpart, where every pack verified
|
|
92
|
+
* under a readable key and none is signed by the key the record names, or every
|
|
93
|
+
* candidate was accounted for by another record (then `count` is set and no
|
|
94
|
+
* pack is named). An exception, never a failure. It says only that no pack is
|
|
95
|
+
* signed by the named key; records that key signed and others hold are not that
|
|
96
|
+
* party's own account and do not change it.
|
|
307
97
|
*/
|
|
308
98
|
export declare const COUNTERPART_ABSENT = "counterpart_absent";
|
|
309
99
|
/**
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
* and is SIGNED by the key this record names is in the case, and not one
|
|
314
|
-
* record this reader could read is this record's counterpart. It states that a
|
|
315
|
-
* pack signed by the named key is present and holds no counterpart this reader
|
|
316
|
-
* could read, and nothing more. 4.1 (v1.10, A15) and 5.4.2 rule 7 (v1.10) both point here, and
|
|
317
|
-
* `declaration/declaration-unclaimed-record-01` is the pack that reaches this
|
|
318
|
-
* line.
|
|
319
|
-
*
|
|
320
|
-
* **"Its own account" is read from the key that signed the PACK, and never
|
|
321
|
-
* from the keys that signed records.** A pack's wrapper key signs `body_hash`
|
|
322
|
-
* and `body` carries the declaration (`evidence-bundle.md` 5.4, "Who signs
|
|
323
|
-
* it"), so a wrapper signed by B is provenance the accusing party cannot forge
|
|
324
|
-
* without B's private key. Records signed by B that A merely HOLDS are not B's
|
|
325
|
-
* account of itself: keyed on record keys, one pack from A plus one unrelated
|
|
326
|
-
* record B signed at some other time reached this line when B had handed over
|
|
327
|
-
* nothing at all.
|
|
100
|
+
* A conformant hand-off record with no counterpart, where a verified pack
|
|
101
|
+
* signed by the key the record names is in the case and holds no counterpart.
|
|
102
|
+
* The closure this module exists for (`declaration-unclaimed-record-01`).
|
|
328
103
|
*
|
|
329
|
-
*
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
* otherwise (the declaration's `case_id` and `period`) are written by B and
|
|
333
|
-
* would let B leave this line by writing them differently. The cost the other
|
|
334
|
-
* way: a pack B assembles under any key other than the one its records name, a
|
|
335
|
-
* per-organization hand-over key (anchor#196) included, reads
|
|
336
|
-
* `COUNTERPART_ABSENT`, because nothing in the case binds that key to B. That
|
|
337
|
-
* reading is still true: no pack signed by the named key is here. So a
|
|
338
|
-
* counterparty can AVOID this line by choosing the key it signs under; what it
|
|
339
|
-
* cannot do is make the missing counterpart read clean.
|
|
104
|
+
* "Its own account" is read from the key that signed the pack, never from
|
|
105
|
+
* record keys: a wrapper signed by B is provenance an accuser cannot forge, but
|
|
106
|
+
* records signed by B that A holds are not B's account.
|
|
340
107
|
*
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
*
|
|
345
|
-
*
|
|
108
|
+
* Not proven: that B handed the pack over for this case. A pack B signs under
|
|
109
|
+
* any other key reads `COUNTERPART_ABSENT`, which is still true; B can avoid
|
|
110
|
+
* this line by choice of key, but cannot make the missing counterpart read
|
|
111
|
+
* clean. Not conditioned on B's records being readable, since each way B could
|
|
112
|
+
* make them unreadable is its own named choice.
|
|
346
113
|
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
* contain this hand-off" are the honest reading and the damning one, and one
|
|
351
|
-
* name for both lets the second read as the first.
|
|
352
|
-
*
|
|
353
|
-
* It is still an EXCEPTION and not a failure, which criterion 3 requires and
|
|
354
|
-
* which is also the honest call: the counterparty's pack is a selection over
|
|
355
|
-
* its own interval, and a hand-off outside that interval is legitimately not
|
|
356
|
-
* in it. What this names is that the question can now be ASKED of the other
|
|
357
|
-
* party's own evidence, which is what no single pack could ever support.
|
|
114
|
+
* A distinct kind from `COUNTERPART_ABSENT`: one name for both would let the
|
|
115
|
+
* damning reading pass as the honest one. Still `incomplete`, not a failure: a
|
|
116
|
+
* hand-off outside the interval B's pack covers is legitimately absent.
|
|
358
117
|
*/
|
|
359
118
|
export declare const COUNTERPART_ABSENT_FROM_COUNTERPARTY_RECORDS = "counterpart_absent_from_counterparty_records";
|
|
360
119
|
/**
|
|
361
|
-
* A conformant hand-off record with no counterpart, no
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
*
|
|
365
|
-
* Whether a pack signed by the named key is in the case is UNKNOWN, so neither
|
|
366
|
-
* of the other two kinds is true.
|
|
367
|
-
*
|
|
368
|
-
* The gate on the previous version of this reader showed why it exists. A
|
|
369
|
-
* counterparty that signed its own pack under `" " + key` got
|
|
370
|
-
* `PACK_KEY_UNREADABLE` for the pack and the innocent `COUNTERPART_ABSENT` for
|
|
371
|
-
* the record, and the output contradicted itself: whose pack it was is
|
|
372
|
-
* UNKNOWN, and then no pack is signed by the named key. The second sentence
|
|
373
|
-
* was not established.
|
|
374
|
-
*
|
|
375
|
-
* `incomplete`, like the other two one-sided kinds: "I could not tell".
|
|
120
|
+
* A conformant hand-off record with no counterpart, no verified pack signed by
|
|
121
|
+
* the key it names, and at least one pack whose signer is unknown
|
|
122
|
+
* (`PACK_KEY_UNREADABLE` or `PACK_DOES_NOT_VERIFY`). Whether the named key
|
|
123
|
+
* signed a pack is unknown, so neither other kind is true. `incomplete`.
|
|
376
124
|
*/
|
|
377
125
|
export declare const COUNTERPART_ABSENT_SIGNER_UNKNOWN = "counterpart_absent_signer_unknown";
|
|
378
126
|
/**
|
|
379
|
-
* More than one candidate counterpart
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
-
* record. `count` is how many of the candidates are live, which is the number
|
|
383
|
-
* the ambiguity is about.
|
|
127
|
+
* More than one live candidate counterpart (§4.1). The reading is the worst of
|
|
128
|
+
* them and the ambiguity is named, so an honest decoy cannot hide a tampered
|
|
129
|
+
* record. `count` is the number of live candidates.
|
|
384
130
|
*/
|
|
385
131
|
export declare const COUNTERPART_AMBIGUOUS = "counterpart_ambiguous";
|
|
132
|
+
/** A formed pair that failed checks, listed in §4.1's fixed order. */
|
|
133
|
+
export declare const PAIR_FAILED = "pair_failed";
|
|
134
|
+
/** This record itself is malformed under §4.1 (`recordIsMalformed`). */
|
|
135
|
+
export declare const RECORD_MALFORMED = "record_malformed";
|
|
386
136
|
/**
|
|
387
|
-
* A
|
|
388
|
-
*
|
|
137
|
+
* A candidate counterpart is malformed and this record is not. §4.1 reports
|
|
138
|
+
* the worst candidate, so without this kind one junk record signed by the
|
|
139
|
+
* counterparty's key would blame the honest record and drop its other failures.
|
|
140
|
+
* `incomplete`: the defect is the candidate's, which carries its own
|
|
141
|
+
* `RECORD_MALFORMED`.
|
|
389
142
|
*/
|
|
390
|
-
export declare const
|
|
143
|
+
export declare const COUNTERPART_MALFORMED = "counterpart_malformed";
|
|
391
144
|
/**
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
145
|
+
* This record is one of the two hand-off types, signed and intact, and does
|
|
146
|
+
* not follow its vocabulary (`recordIsNonconforming`). A producer's error,
|
|
147
|
+
* never a proven alteration.
|
|
395
148
|
*/
|
|
396
|
-
export declare const
|
|
149
|
+
export declare const RECORD_NONCONFORMING = "record_nonconforming";
|
|
397
150
|
/**
|
|
398
|
-
* A
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
* outranks `failed`, so one junk record signed by the counterparty's key makes
|
|
402
|
-
* the reading of a perfectly well formed record `malformed` too. Filed under
|
|
403
|
-
* `RECORD_MALFORMED`, that read as "this record is not a well formed hand-off
|
|
404
|
-
* record" about the HONEST record, and the branch it took skipped the
|
|
405
|
-
* counterpart, ambiguity and `failedChecks` reporting entirely: one junk record
|
|
406
|
-
* both blamed the wrong party and stripped a named `message_hash` failure out
|
|
407
|
-
* of the case. That is proof#133 ruling 6, which 4.1 closed by keeping the
|
|
408
|
-
* UNION of `failedChecks`, reappearing one layer out because this layer
|
|
409
|
-
* discarded that union.
|
|
410
|
-
*
|
|
411
|
-
* A record's own conformance and its candidate's are different facts and do
|
|
412
|
-
* not share a kind. This one is `incomplete` and not `malformed`: the proven
|
|
413
|
-
* defect belongs to the candidate, which carries its own `RECORD_MALFORMED`
|
|
414
|
-
* line, and what is true of THIS record is that its pairing could not be
|
|
415
|
-
* determined. Contributing `malformed` here would attribute the candidate's
|
|
416
|
-
* defect to the record a party being accused did not write.
|
|
151
|
+
* A candidate counterpart is nonconforming and this record is not.
|
|
152
|
+
* `incomplete` for the reason `COUNTERPART_MALFORMED` is: the defect is the
|
|
153
|
+
* candidate's, which carries its own `RECORD_NONCONFORMING`.
|
|
417
154
|
*/
|
|
418
|
-
export declare const
|
|
155
|
+
export declare const COUNTERPART_NONCONFORMING = "counterpart_nonconforming";
|
|
419
156
|
/**
|
|
420
|
-
* A record
|
|
421
|
-
*
|
|
422
|
-
*
|
|
423
|
-
*
|
|
424
|
-
*
|
|
425
|
-
* **It turns on what the PACK said about the record, and never on whether 4.1
|
|
426
|
-
* governs it.** Gating it on "is this a conformant hand-off record" put it
|
|
427
|
-
* behind a value the audited party writes: the same second receipt, respelled
|
|
428
|
-
* with an `ff` ligature in `event_type` and a Cyrillic `е` in
|
|
429
|
-
* `counterparty_public_key`, left 4.1's scope, took the `not_a_handoff_record`
|
|
430
|
-
* branch, and bought a case reading of `verified` with zero exceptions where
|
|
431
|
-
* the conformant spelling read `mixed` with four. proof#136 ratified that a
|
|
432
|
-
* respelling buys a DIFFERENT LINE rather than no line; at this layer it
|
|
433
|
-
* bought no line at all, and a strictly better outcome than honesty.
|
|
157
|
+
* A record its pack declares and its pack's readable declaration claims in no
|
|
158
|
+
* `handoffs[]` entry (§5.4.2 rules 2 and 7 cannot reach it). Turns on what the
|
|
159
|
+
* pack said, never on whether §4.1 governs the record, so respelling
|
|
160
|
+
* `event_type` cannot move a record out of this check.
|
|
434
161
|
*
|
|
435
|
-
*
|
|
436
|
-
*
|
|
437
|
-
*
|
|
438
|
-
* meant to give or one it is keeping out of its own account, and that is "I
|
|
439
|
-
* could not tell", which is why it carries `incomplete` and not `verified`.
|
|
440
|
-
*
|
|
441
|
-
* THE COST, stated rather than left to be found: a pack that declares records
|
|
442
|
-
* which are not hand-off sides at all, an ordinary log line among them, is
|
|
443
|
-
* named once per such record, so a case holding one cannot read `verified`.
|
|
444
|
-
* That is the price of a rule with no branch the holder selects, and the only
|
|
445
|
-
* narrower rule available keys on a value the holder writes. A surface that
|
|
446
|
-
* wants the two apart reads `CaseRecordReading.findings`, where
|
|
447
|
-
* `not_a_handoff_record` still says which is which.
|
|
162
|
+
* Not an accusation: `handoffs[]` may be empty and the record innocent, so it
|
|
163
|
+
* is `incomplete`. The cost is that a declared non-hand-off record (a log line)
|
|
164
|
+
* is named too; `CaseRecordReading.findings` tells the two apart.
|
|
448
165
|
*/
|
|
449
166
|
export declare const RECORD_UNCLAIMED = "record_unclaimed_by_its_pack";
|
|
450
167
|
/**
|
|
451
|
-
* The pack
|
|
452
|
-
*
|
|
453
|
-
*
|
|
454
|
-
* `event_bytes` is OPTIONAL (5.1, 5.3) and withholding it is minimum
|
|
455
|
-
* disclosure, which the corpus calls a customer's right and not a defect
|
|
456
|
-
* (proof#137, defect 3), so this is not a deviation and does not fail. It is
|
|
457
|
-
* still SAID, because a withheld record is exactly where a missing counterpart
|
|
458
|
-
* would hide, and a reader that dropped it silently would read a trimmed pack
|
|
459
|
-
* as an honest one.
|
|
168
|
+
* The pack withheld `event_bytes` for a record. Withholding is minimal
|
|
169
|
+
* disclosure (§5.1, §5.3), not a deviation, but it is said: a withheld record is
|
|
170
|
+
* where a missing counterpart would hide.
|
|
460
171
|
*/
|
|
461
172
|
export declare const RECORD_BYTES_WITHHELD = "record_bytes_withheld";
|
|
462
173
|
/**
|
|
463
|
-
* The pack
|
|
464
|
-
*
|
|
465
|
-
* `packRecords`). Bytes the holder handed over that do not decode are a defect
|
|
466
|
-
* in what was handed over, not an absence, so this one is `malformed`.
|
|
174
|
+
* The pack supplied `event_bytes` that do not read as `JCS(event record)`.
|
|
175
|
+
* A defect in what was handed over, so `malformed`.
|
|
467
176
|
*/
|
|
468
177
|
export declare const RECORD_BYTES_UNREADABLE = "record_bytes_unreadable";
|
|
469
|
-
/**
|
|
470
|
-
* The pack deviates from its own declaration (5.4.2). A proven mismatch, so it
|
|
471
|
-
* fails: a case cannot be clean over a pack that is proven to be trimmed.
|
|
472
|
-
*/
|
|
178
|
+
/** The pack deviates from its own declaration (§5.4.2). A proven mismatch: `failed`. */
|
|
473
179
|
export declare const PACK_DECLARATION_DEVIATES = "pack_declaration_deviates";
|
|
474
180
|
/**
|
|
475
|
-
* The pack and the
|
|
476
|
-
*
|
|
477
|
-
*
|
|
478
|
-
* declares `content_withheld` for which bytes reached this reader from the
|
|
479
|
-
* side-content map alone.
|
|
480
|
-
*
|
|
481
|
-
* `incomplete` and never `failed`, which is the whole point of the kind. 5.4
|
|
482
|
-
* grades a pack's declaration partly against content the READER was handed,
|
|
483
|
-
* and whoever assembles a case fills that map in. Under
|
|
484
|
-
* `PACK_DECLARATION_DEVIATES` an accuser could put an intact pack into a
|
|
485
|
-
* `failed` case WITH NO KEY AT ALL: supply bytes for a record its holder
|
|
486
|
-
* declared withheld, or drop the bytes of one it declared disclosed. The pack
|
|
487
|
-
* was intact, its wrapper verified, and its holder had done nothing. This is
|
|
488
|
-
* the mirror of proof#143, where a counterparty makes ITSELF look better by
|
|
489
|
-
* choosing what it hands over.
|
|
181
|
+
* The pack and the unsigned content beside it do not line up (§5.4.2 rules 3
|
|
182
|
+
* and 4): a record declared `disclosed` with no bytes, or declared
|
|
183
|
+
* `content_withheld` with bytes from the side-content map alone.
|
|
490
184
|
*
|
|
491
|
-
*
|
|
492
|
-
*
|
|
185
|
+
* `incomplete`, never `failed`: whoever assembles a case fills in that map, so
|
|
186
|
+
* otherwise an accuser could fail an intact pack with no key. Emitted beside
|
|
187
|
+
* `PACK_DECLARATION_DEVIATES` when a pack does both.
|
|
493
188
|
*/
|
|
494
189
|
export declare const PACK_DECLARATION_CONTENT_DEPENDENT = "pack_declaration_content_dependent";
|
|
495
190
|
/**
|
|
496
|
-
* The pack
|
|
497
|
-
*
|
|
498
|
-
* does not satisfy 5.4.1. `declaration_version` is chosen by the same party
|
|
499
|
-
* that assembles the pack and has no accept-set of its own, so this is UNKNOWN
|
|
500
|
-
* and never clean.
|
|
191
|
+
* The pack's `declaration` cannot be read (§5.4.3). Its version is chosen by
|
|
192
|
+
* the pack's assembler with no accept-set, so this is unknown, never clean.
|
|
501
193
|
*/
|
|
502
194
|
export declare const PACK_DECLARATION_UNREADABLE = "pack_declaration_unreadable";
|
|
503
195
|
/**
|
|
504
|
-
* The pack carries no `declaration`
|
|
505
|
-
*
|
|
506
|
-
* `verified`, because there is nothing to check the pack against, and never
|
|
507
|
-
* `failed`, because nothing is wrong.
|
|
196
|
+
* The pack carries no `declaration`. `partial` (§5.4.3): nothing to check
|
|
197
|
+
* against, and nothing wrong.
|
|
508
198
|
*/
|
|
509
199
|
export declare const PACK_UNDECLARED = "pack_undeclared";
|
|
510
|
-
/**
|
|
511
|
-
* The pack's `body_type` is not one this reader knows to carry `events[]`
|
|
512
|
-
* (`CASE_BODY_TYPES`).
|
|
513
|
-
*/
|
|
200
|
+
/** The pack's `body_type` is not in `CASE_BODY_TYPES`. */
|
|
514
201
|
export declare const PACK_BODY_TYPE_UNKNOWN = "pack_body_type_unknown";
|
|
515
|
-
/**
|
|
516
|
-
* The pack carries a body this reader knows and no records in it. A pack that
|
|
517
|
-
* contributes nothing is named rather than passed over.
|
|
518
|
-
*/
|
|
202
|
+
/** The pack carries a known body with no records. */
|
|
519
203
|
export declare const PACK_HOLDS_NO_RECORDS = "pack_holds_no_records";
|
|
520
204
|
/**
|
|
521
|
-
* The
|
|
522
|
-
*
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
* `
|
|
526
|
-
*
|
|
527
|
-
* Found by constructing it, while enumerating this module's exits: the wrapper
|
|
528
|
-
* key is the ONE input that separates the two counterpart kinds, and a key this
|
|
529
|
-
* reader could not read used to drop out of that set in silence. The Python
|
|
530
|
-
* `verify_evidence_bundle` accepts a wrapper `public_key` with ASCII
|
|
531
|
-
* whitespace inside it or around it (`bytes.fromhex` skips it; this kernel's
|
|
532
|
-
* verifier rejects it), so a counterparty that signed its own pack under
|
|
533
|
-
* `" " + key` handed a Python reader a pack that verified, contributed no key,
|
|
534
|
-
* and moved the subject from `COUNTERPART_ABSENT_FROM_COUNTERPARTY_RECORDS` to
|
|
535
|
-
* the innocent `COUNTERPART_ABSENT`. The same repair 4.1 made for a RECORD
|
|
536
|
-
* whose envelope key it cannot read (proof#133, fourth hunt): a key a reader
|
|
537
|
-
* holds and cannot read is named, never treated as absent. It is `incomplete`
|
|
538
|
-
* rather than `malformed` because whether the spelling verifies is the envelope
|
|
539
|
-
* layer's call (proof#135), and this reader only knows it cannot read it.
|
|
205
|
+
* The pack's wrapper key cannot be read (`normalizedSigningKey` returns
|
|
206
|
+
* nothing), so its signer is unknown. None of its records are read, and a
|
|
207
|
+
* one-sided record whose named key signed no verified pack reads
|
|
208
|
+
* `COUNTERPART_ABSENT_SIGNER_UNKNOWN`. A key a reader holds and cannot read is
|
|
209
|
+
* named, never treated as absent. `incomplete`: whether the spelling verifies
|
|
210
|
+
* is the envelope layer's call.
|
|
540
211
|
*/
|
|
541
212
|
export declare const PACK_KEY_UNREADABLE = "pack_key_unreadable";
|
|
542
213
|
/**
|
|
543
|
-
* The pack
|
|
544
|
-
*
|
|
545
|
-
*
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
*
|
|
550
|
-
*
|
|
551
|
-
*
|
|
552
|
-
*
|
|
553
|
-
* an unknown body or withheld bytes produce, and those are named on their own.
|
|
554
|
-
*
|
|
555
|
-
* `failed`: a pack in the case is proven broken.
|
|
214
|
+
* The pack's `bundle.json` cannot be read as JSON: it does not parse, nests too deep, or
|
|
215
|
+
* names one member twice. The pack is not verified and none of its records are read, and
|
|
216
|
+
* every other pack in the case still is. `incomplete`: the signature could not be checked.
|
|
217
|
+
*/
|
|
218
|
+
export declare const PACK_UNREADABLE = "pack_unreadable";
|
|
219
|
+
/**
|
|
220
|
+
* `verifyEvidenceBundle`, run offline here, returned `failed` or `malformed`.
|
|
221
|
+
* None of its records are read (§4.1 requires verified envelopes), and its
|
|
222
|
+
* wrapper key is never counted as a pack signer: an unverified wrapper claiming
|
|
223
|
+
* the counterparty's key is what an accuser would forge. `failed`.
|
|
556
224
|
*/
|
|
557
225
|
export declare const PACK_DOES_NOT_VERIFY = "pack_does_not_verify";
|
|
558
226
|
/**
|
|
559
|
-
* The pack's wrapper
|
|
560
|
-
* (evidence-bundle 5.5.1
|
|
561
|
-
*
|
|
562
|
-
*
|
|
563
|
-
*
|
|
564
|
-
*
|
|
565
|
-
*
|
|
566
|
-
* otherwise the full grade. A body the verifier could not read is `malformed`,
|
|
567
|
-
* a body that is not one of the two event-carrying bodies takes the signed
|
|
568
|
-
* run's status, and a verifier that graded a different number of records than
|
|
569
|
-
* the pack holds takes the signed status, or `malformed` where that status is
|
|
227
|
+
* The pack's wrapper holds and its case grade is not `verified`
|
|
228
|
+
* (evidence-bundle §5.5.1). The case grade is the §5.4.5 pack grade taken
|
|
229
|
+
* twice: signed (side map empty) and full (with it). The signed grade decides
|
|
230
|
+
* where it is `failed` or `malformed`; a failure only the full grade reaches is
|
|
231
|
+
* `incomplete`, since it rests on unsigned bytes; otherwise the full grade.
|
|
232
|
+
* An unreadable body is `malformed`; a non-event body takes the signed status;
|
|
233
|
+
* a record-count mismatch takes the signed status, or `malformed` where that is
|
|
570
234
|
* `verified`.
|
|
571
235
|
*
|
|
572
|
-
*
|
|
573
|
-
*
|
|
574
|
-
* `
|
|
575
|
-
* CONTRIBUTES the grade, and `incomplete` for `pending`, `not_found` or
|
|
576
|
-
* `mixed`, so the case verdict never reads above its weakest pack.
|
|
236
|
+
* Carries `status`, `causes` (the deciding grade's cause kinds) and `reasons`
|
|
237
|
+
* (from the signed run). Contributes the grade, or `incomplete` for `pending`,
|
|
238
|
+
* `not_found` or `mixed`, so the case never reads above its weakest pack.
|
|
577
239
|
*/
|
|
578
240
|
export declare const PACK_GRADE_NOT_VERIFIED = "pack_grade_not_verified";
|
|
579
241
|
/**
|
|
580
|
-
* A record
|
|
581
|
-
*
|
|
582
|
-
*
|
|
583
|
-
* is proven not to verify. As a reason to drop the whole pack it let the
|
|
584
|
-
* counterparty add one junk event to its own pack, re-seal it, and strip a
|
|
585
|
-
* proven `message_hash` failure out of the case (gate 3 on proof#140).
|
|
242
|
+
* A record whose own envelope does not verify, in a pack whose wrapper holds.
|
|
243
|
+
* Not read by §4.1. `failed`. Scoped to the record so one junk event cannot
|
|
244
|
+
* drop the whole pack and a proven failure with it.
|
|
586
245
|
*/
|
|
587
246
|
export declare const RECORD_ENVELOPE_DOES_NOT_VERIFY = "record_envelope_does_not_verify";
|
|
588
247
|
/**
|
|
589
|
-
* A record whose envelope verifies
|
|
590
|
-
*
|
|
591
|
-
*
|
|
592
|
-
*
|
|
593
|
-
* remove its own tampered receipt from pairing by breaking that receipt's
|
|
594
|
-
* inclusion proof would be choosing its own reading.
|
|
248
|
+
* A record whose envelope verifies but which fails another check in its pack
|
|
249
|
+
* (inclusion proof, checkpoint or stamp join, a retired field). `failed`, and
|
|
250
|
+
* the record stays in the pile, so breaking its own proof cannot remove a
|
|
251
|
+
* tampered receipt from pairing.
|
|
595
252
|
*/
|
|
596
253
|
export declare const RECORD_DOES_NOT_VERIFY_IN_ITS_PACK = "record_does_not_verify_in_its_pack";
|
|
597
254
|
/**
|
|
598
|
-
* A record whose
|
|
599
|
-
*
|
|
600
|
-
*
|
|
601
|
-
* side map EMPTY: the content is inside the signed body. The same mismatch from
|
|
602
|
-
* content handed in beside the pack is `RECORD_CONTENT_DEPENDENT` (proof#159).
|
|
603
|
-
* `failed`, and the record STAYS in the pile: content beside a pack is unsigned and often
|
|
604
|
-
* supplied by whoever assembled the case, and gate 3 on proof#140 showed that
|
|
605
|
-
* party erasing an honest verified pair by swapping it.
|
|
255
|
+
* A record whose disclosed content does not hash to its `content_hash` (or a
|
|
256
|
+
* hand-off record's `message_hash`) with the side map empty: the content is in
|
|
257
|
+
* the signed body. `failed`, and the record stays in the pile.
|
|
606
258
|
*/
|
|
607
259
|
export declare const RECORD_CONTENT_MISMATCH = "record_content_mismatch";
|
|
608
260
|
/**
|
|
609
|
-
*
|
|
610
|
-
*
|
|
611
|
-
* bundle
|
|
612
|
-
*
|
|
613
|
-
*
|
|
614
|
-
* that map alone is `RECORD_CONTENT_DEPENDENT`. Both are `incomplete`: the
|
|
615
|
-
* reader established that the bytes it was handed are not the bytes the record
|
|
616
|
-
* commits to, and nothing about the party that signed the record, because
|
|
617
|
-
* whoever assembled the case chose those bytes with no key. Up to v1.15 both
|
|
618
|
-
* readings carried `failed`, and one flipped nibble of accuser-supplied content
|
|
619
|
-
* put a `failed` against an intact pack; under A17's headline rule that would
|
|
620
|
-
* have become the case's headline.
|
|
621
|
-
*
|
|
622
|
-
* The test that separates the two is the one proof#159 states for the inverse:
|
|
623
|
-
* every deviation a signature covers still reads `failed` with the side map
|
|
624
|
-
* EMPTY. So the pack is verified twice, with the map and without it, and what
|
|
625
|
-
* fails without it is `PACK_GRADE_NOT_VERIFIED`, `RECORD_CONTENT_MISMATCH`
|
|
626
|
-
* (content inside the signed body) or `RECORD_DOES_NOT_VERIFY_IN_ITS_PACK`,
|
|
627
|
-
* each still `failed`. Emptying the map is the most a party that signed
|
|
628
|
-
* nothing can do to starve the check, and it cannot remove any of those.
|
|
261
|
+
* A pack whose bundle verdict is `failed` only with the unsigned side content,
|
|
262
|
+
* and a record whose content mismatch comes from that content alone
|
|
263
|
+
* (evidence-bundle §5.5.4). Both `incomplete`: whoever assembled the case chose
|
|
264
|
+
* those bytes with no key. Every deviation a signature covers still fails with
|
|
265
|
+
* the side map empty, so starving the check cannot hide one.
|
|
629
266
|
*/
|
|
630
267
|
export declare const PACK_BUNDLE_CONTENT_DEPENDENT = "pack_bundle_content_dependent";
|
|
631
268
|
export declare const RECORD_CONTENT_DEPENDENT = "record_content_dependent";
|
|
632
269
|
/**
|
|
633
|
-
* A record
|
|
634
|
-
*
|
|
635
|
-
* `incomplete`: whether it verifies is what the kernels disagree about.
|
|
270
|
+
* A record under a quarantined profile (`CASE_QUARANTINED_PROFILES`). Not read.
|
|
271
|
+
* `incomplete`.
|
|
636
272
|
*/
|
|
637
273
|
export declare const RECORD_PROFILE_QUARANTINED = "record_profile_quarantined";
|
|
638
274
|
/** The reader was handed no packs at all. */
|
|
639
275
|
export declare const CASE_HOLDS_NO_PACKS = "case_holds_no_packs";
|
|
640
276
|
/**
|
|
641
|
-
*
|
|
642
|
-
*
|
|
643
|
-
*
|
|
644
|
-
*
|
|
645
|
-
* of that name.
|
|
277
|
+
* Notes (§5.5.3): findings with no verdict contribution, printed in the scope
|
|
278
|
+
* sentence so a clean verdict never hides them. `pack_undeclared` is a note
|
|
279
|
+
* only where the reading holds no hand-off record; otherwise it is the
|
|
280
|
+
* exception.
|
|
646
281
|
*/
|
|
647
282
|
export declare const CONTENT_WITHHELD_BY_DECLARATION = "content_withheld_by_declaration";
|
|
648
283
|
/**
|
|
649
|
-
* A pack's wrapper carries
|
|
650
|
-
*
|
|
651
|
-
*
|
|
652
|
-
* rather than presenting it as evidence, and it contributes no verdict.
|
|
284
|
+
* A pack's wrapper carries `co_signatures` (evidence-bundle section 2). It verifies
|
|
285
|
+
* nothing and sits outside the signed scope, so it is named, not presented as
|
|
286
|
+
* evidence.
|
|
653
287
|
*/
|
|
654
288
|
export declare const CO_SIGNATURES_PRESENT = "co_signatures_present";
|
|
655
289
|
export declare const CASE_NOTE_KINDS: readonly ["pack_undeclared", "content_withheld_by_declaration", "co_signatures_present"];
|
|
656
290
|
export type CaseNoteKind = (typeof CASE_NOTE_KINDS)[number];
|
|
657
|
-
/**
|
|
658
|
-
|
|
659
|
-
* them and a test may assert over them; nothing outside this array is emitted.
|
|
660
|
-
*/
|
|
661
|
-
export declare const CASE_EXCEPTION_KINDS: readonly ["counterpart_absent", "counterpart_absent_from_counterparty_records", "counterpart_absent_signer_unknown", "counterpart_ambiguous", "counterpart_malformed", "pair_failed", "record_malformed", "record_unclaimed_by_its_pack", "record_bytes_withheld", "record_bytes_unreadable", "pack_declaration_deviates", "pack_declaration_content_dependent", "pack_declaration_unreadable", "pack_undeclared", "pack_body_type_unknown", "pack_holds_no_records", "pack_key_unreadable", "pack_does_not_verify", "pack_grade_not_verified", "pack_bundle_content_dependent", "record_envelope_does_not_verify", "record_does_not_verify_in_its_pack", "record_content_mismatch", "record_content_dependent", "record_profile_quarantined", "case_holds_no_packs"];
|
|
291
|
+
/** Every exception this reader can report. Nothing outside this set is emitted. */
|
|
292
|
+
export declare const CASE_EXCEPTION_KINDS: readonly ["counterpart_absent", "counterpart_absent_from_counterparty_records", "counterpart_absent_signer_unknown", "counterpart_ambiguous", "counterpart_malformed", "counterpart_nonconforming", "pair_failed", "record_malformed", "record_nonconforming", "record_unclaimed_by_its_pack", "record_bytes_withheld", "record_bytes_unreadable", "pack_declaration_deviates", "pack_declaration_content_dependent", "pack_declaration_unreadable", "pack_undeclared", "pack_body_type_unknown", "pack_holds_no_records", "pack_unreadable", "pack_key_unreadable", "pack_does_not_verify", "pack_grade_not_verified", "pack_bundle_content_dependent", "record_envelope_does_not_verify", "record_does_not_verify_in_its_pack", "record_content_mismatch", "record_content_dependent", "record_profile_quarantined", "case_holds_no_packs"];
|
|
662
293
|
export type CaseExceptionKind = (typeof CASE_EXCEPTION_KINDS)[number];
|
|
663
294
|
/**
|
|
664
|
-
* The status
|
|
665
|
-
*
|
|
666
|
-
* of its pack's `body.events` as `packRecords` reads them, or, for a
|
|
667
|
-
* `sanning.evidence.export/v2` pack, of the events of the inline source
|
|
668
|
-
* bundle it wraps (`resolveTraceEvents`), and gets exactly one:
|
|
669
|
-
*
|
|
670
|
-
* - `read_clean`: the record went into the pile, no exception carries its
|
|
671
|
-
* `packIndex` and `recordIndex`, and its pack's declaration check
|
|
672
|
-
* names it by nothing (`declarationFindings` is empty). It says nothing
|
|
673
|
-
* about its PACK: the pack's own grade and exceptions are on the pack, and a
|
|
674
|
-
* surface MUST show that grade beside the status.
|
|
675
|
-
* - `read_flagged`: the record went into the pile, and at least one
|
|
676
|
-
* exception carries its `packIndex` and `recordIndex`, or its pack's
|
|
677
|
-
* declaration check names its `eventId` by a deviation or a content
|
|
678
|
-
* finding (`declarationFindings` is not empty; under an `eventId` the
|
|
679
|
-
* pack carries twice, every record with that id). An exception about the
|
|
680
|
-
* pack alone flags no record.
|
|
681
|
-
* - `not_read`: the record never went into the pile. `reason` is the kind
|
|
682
|
-
* of the exception that says why, on the record
|
|
683
|
-
* (`record_profile_quarantined`, `record_envelope_does_not_verify`,
|
|
684
|
-
* `record_bytes_withheld`, `record_bytes_unreadable`) or on its pack
|
|
685
|
-
* (`pack_key_unreadable`, `pack_does_not_verify`,
|
|
686
|
-
* `pack_body_type_unknown`, `pack_grade_not_verified` where the body
|
|
687
|
-
* could not be read or the verifier graded a different number of records).
|
|
688
|
-
* An export's wrapped records carry the reason of the exception their pack
|
|
689
|
-
* actually got: `pack_body_type_unknown` where its wrapper holds, and
|
|
690
|
-
* otherwise `pack_key_unreadable`, `pack_does_not_verify` or
|
|
691
|
-
* `pack_grade_not_verified`.
|
|
295
|
+
* The status each record of each pack gets (evidence-bundle §5.5.4), one per
|
|
296
|
+
* element of `body.events` (or, for an export, its source bundle's events):
|
|
692
297
|
*
|
|
693
|
-
*
|
|
694
|
-
*
|
|
298
|
+
* - `read_clean`: in the pile, named by no exception and no declaration
|
|
299
|
+
* finding. Says nothing about its pack; a surface must show the pack grade
|
|
300
|
+
* beside it.
|
|
301
|
+
* - `read_flagged`: in the pile, and named by an exception or a declaration
|
|
302
|
+
* finding (every record sharing a duplicated `eventId`). A pack-only
|
|
303
|
+
* exception flags no record.
|
|
304
|
+
* - `not_read`: never in the pile. `reason` is the record or pack exception
|
|
305
|
+
* that says why; an export's wrapped records take their pack's exception.
|
|
695
306
|
*/
|
|
696
307
|
export declare const CASE_RECORD_STATUSES: readonly ["read_clean", "read_flagged", "not_read"];
|
|
697
308
|
export type CaseRecordStatus = (typeof CASE_RECORD_STATUSES)[number];
|
|
698
309
|
/**
|
|
699
|
-
* One pack in a case, as
|
|
700
|
-
*
|
|
701
|
-
* `
|
|
702
|
-
*
|
|
703
|
-
* the party that assembled it, and two packs are free to claim one name.
|
|
704
|
-
*
|
|
705
|
-
* A caller passes packs as it received them. `readCase` runs
|
|
706
|
-
* `verifyEvidenceBundle` over each one itself, so `HeldRecord`'s precondition
|
|
707
|
-
* (every envelope it compares has verified) is met by this module and cannot
|
|
708
|
-
* be skipped by a caller. A pack that does not verify is
|
|
709
|
-
* `PACK_DOES_NOT_VERIFY`.
|
|
310
|
+
* One pack in a case, as handed to the reader. `ref` is the reader's own name
|
|
311
|
+
* for it, never read from the pack, since two packs can claim one name.
|
|
312
|
+
* `readCase` verifies each pack itself, so the verified-envelope precondition
|
|
313
|
+
* of `HeldRecord` cannot be skipped by a caller.
|
|
710
314
|
*/
|
|
711
315
|
export interface CasePack {
|
|
712
316
|
ref: string;
|
|
713
317
|
bundle: unknown;
|
|
714
318
|
content?: SideContentMap | null;
|
|
319
|
+
/** Why the pack's `bundle.json` could not be read, where it could not; `bundle` is then ignored (`PACK_UNREADABLE`). */
|
|
320
|
+
unreadable?: string | null;
|
|
715
321
|
}
|
|
716
|
-
/** One named exception, as data. A surface renders
|
|
717
|
-
* `renderException`. */
|
|
322
|
+
/** One named exception, as data. A surface renders it or calls `renderException`. */
|
|
718
323
|
export interface CaseException {
|
|
719
324
|
kind: CaseExceptionKind;
|
|
720
|
-
/**
|
|
721
|
-
* Which pack this is about, by the reader's own name for it. Two packs can
|
|
722
|
-
* carry one `ref`, so it is a label and never the join: `packIndex` is.
|
|
723
|
-
*/
|
|
325
|
+
/** The reader's name for the pack: a label, never the join (`packIndex` is). */
|
|
724
326
|
packRef?: string;
|
|
725
|
-
/**
|
|
726
|
-
* Which pack this is about, by its position in `CaseReading.packs` (0
|
|
727
|
-
* first), present wherever `packRef` is (A43). Unique in the reading.
|
|
728
|
-
*/
|
|
327
|
+
/** The pack's position in `CaseReading.packs`, wherever `packRef` is set. */
|
|
729
328
|
packIndex?: number;
|
|
730
329
|
/** Which record, by its envelope `event_id`. */
|
|
731
330
|
eventId?: string;
|
|
732
331
|
/**
|
|
733
|
-
*
|
|
734
|
-
*
|
|
735
|
-
*
|
|
736
|
-
* `CaseReading.records`.
|
|
332
|
+
* The record's position in its pack's events, wherever `eventId` is set.
|
|
333
|
+
* With `packIndex`, the join to `CaseReading.records`, since one pack can
|
|
334
|
+
* carry an `event_id` twice.
|
|
737
335
|
*/
|
|
738
336
|
recordIndex?: number;
|
|
739
|
-
/**
|
|
740
|
-
* The counterparty key the record named, for the two counterpart kinds.
|
|
741
|
-
* Normalized (`normalizedSigningKey`), so a reader compares what this module
|
|
742
|
-
* compared.
|
|
743
|
-
*/
|
|
337
|
+
/** The counterparty key the record named, normalized as this module compared it. */
|
|
744
338
|
counterpartyKey?: string | null;
|
|
745
|
-
/** Which checks a formed pair failed, in 4.1's fixed order. */
|
|
339
|
+
/** Which checks a formed pair failed, in §4.1's fixed order. */
|
|
746
340
|
failedChecks?: string[];
|
|
747
341
|
/**
|
|
748
|
-
*
|
|
749
|
-
*
|
|
750
|
-
* (v1.17, A20), and it is how many were set aside.
|
|
342
|
+
* The count the exception is about. On `COUNTERPART_ABSENT`, set only where
|
|
343
|
+
* every candidate was set aside, and it is how many were.
|
|
751
344
|
*/
|
|
752
345
|
count?: number;
|
|
753
346
|
/** The pack's case grade, for `PACK_GRADE_NOT_VERIFIED`. */
|
|
754
347
|
status?: CaseVerdict;
|
|
755
348
|
/**
|
|
756
|
-
*
|
|
757
|
-
*
|
|
758
|
-
* not computed (an unreadable body, a body that is not one of the two
|
|
759
|
-
* event-carrying ones, a verifier that graded too few records).
|
|
349
|
+
* For `PACK_GRADE_NOT_VERIFIED`, the §5.4.5 cause kinds of the deciding grade.
|
|
350
|
+
* Empty where no grade was computed.
|
|
760
351
|
*/
|
|
761
352
|
causes?: PackGradeCauseKind[];
|
|
762
353
|
/**
|
|
763
|
-
*
|
|
764
|
-
*
|
|
765
|
-
* graded on the record's own envelope and content.
|
|
354
|
+
* The bundle verifier's own reasons, for `PACK_GRADE_NOT_VERIFIED` and the
|
|
355
|
+
* record kinds graded on the record's envelope and content.
|
|
766
356
|
*/
|
|
767
357
|
reasons?: string[];
|
|
358
|
+
/**
|
|
359
|
+
* For `PACK_GRADE_NOT_VERIFIED`, every problem behind the grade, each mapped to one
|
|
360
|
+
* claim and one state (`claims.ts`), at this pack's position. A grade that is not
|
|
361
|
+
* `failed` carries no disproof: one that only the unsigned side map reached reads
|
|
362
|
+
* `not_proven`.
|
|
363
|
+
*/
|
|
364
|
+
problems?: Problem[];
|
|
768
365
|
}
|
|
769
366
|
/**
|
|
770
|
-
* One record of one pack, with its status and, where
|
|
771
|
-
*
|
|
772
|
-
*
|
|
773
|
-
*
|
|
774
|
-
* in bundle order: the ones this reader read, including the ones that are not
|
|
775
|
-
* hand-off records at all (`findings` carries `not_a_handoff_record`), and the
|
|
776
|
-
* ones it did not, with `status` `not_read` and the `reason`. 4.1 (v1.9, A14)
|
|
777
|
-
* names why: the one thing an attacker wants is for a record to be absent from
|
|
778
|
-
* the output. An export's wrapped records are listed, `not_read`. A pack whose
|
|
779
|
-
* body carries no `events` array, and wraps none, lists none, and its own
|
|
780
|
-
* exception says why.
|
|
367
|
+
* One record of one pack, with its status and, where read, §4.1's reading.
|
|
368
|
+
* Every record of every pack is listed, in pack then bundle order, read or
|
|
369
|
+
* not, because the one thing an attacker wants is a record absent from the
|
|
370
|
+
* output. A pack with no `events` array lists none; its exception says why.
|
|
781
371
|
*/
|
|
782
372
|
export interface CaseRecordReading {
|
|
783
373
|
packRef: string;
|
|
784
|
-
/** The pack
|
|
374
|
+
/** The pack's position in `CaseReading.packs`. */
|
|
785
375
|
packIndex: number;
|
|
786
376
|
eventId: string;
|
|
787
377
|
/**
|
|
788
|
-
* The record
|
|
789
|
-
*
|
|
790
|
-
* source bundle it wraps.
|
|
378
|
+
* The record's position in its pack's events (for an export, its source
|
|
379
|
+
* bundle's events).
|
|
791
380
|
*/
|
|
792
381
|
recordIndex: number;
|
|
793
|
-
/** One of `CASE_RECORD_STATUSES` (A43). */
|
|
794
382
|
status: CaseRecordStatus;
|
|
795
|
-
/**
|
|
796
|
-
* For `not_read`, the kind of the exception that says why; `null` for a
|
|
797
|
-
* record that was read.
|
|
798
|
-
*/
|
|
383
|
+
/** For `not_read`, the exception kind that says why; else `null`. */
|
|
799
384
|
reason: CaseExceptionKind | null;
|
|
800
385
|
/**
|
|
801
|
-
* The
|
|
802
|
-
*
|
|
803
|
-
*
|
|
804
|
-
* `eventId`, so under an `event_id` the pack carries twice every record with
|
|
805
|
-
* that id carries it. A record that went into the pile with any is
|
|
806
|
-
* `read_flagged` (A43).
|
|
386
|
+
* The declaration check's deviations then content findings for this record's
|
|
387
|
+
* `eventId` (every record sharing a duplicated id). Any makes a read record
|
|
388
|
+
* `read_flagged`.
|
|
807
389
|
*/
|
|
808
390
|
declarationFindings: string[];
|
|
809
|
-
/** 4.1's verdict, or `null` where
|
|
391
|
+
/** §4.1's verdict, or `null` where it gave none or the record was not read. */
|
|
810
392
|
verdict: string | null;
|
|
811
393
|
findings: string[];
|
|
812
394
|
failedChecks: string[];
|
|
813
395
|
/**
|
|
814
|
-
* 4.1's candidate counterparts
|
|
815
|
-
*
|
|
816
|
-
* pack one `event_id` twice (A43).
|
|
396
|
+
* §4.1's candidate counterparts as `<pack ref>/<event_id>`: labels for a
|
|
397
|
+
* person, never the join.
|
|
817
398
|
*/
|
|
818
399
|
counterparts: string[];
|
|
819
400
|
/**
|
|
820
|
-
* The role the pack's v2 declaration signs for this record, `
|
|
821
|
-
*
|
|
822
|
-
* v1, or does not declare the record (5.5.1 v1.20).
|
|
401
|
+
* The role the pack's v2 declaration signs for this record, or `null` where
|
|
402
|
+
* the declaration is absent, unreadable, v1 or silent on it (§5.5.1).
|
|
823
403
|
*/
|
|
824
404
|
role: DeclarationRole | null;
|
|
405
|
+
/**
|
|
406
|
+
* The `sanning.agent` reading of this record (agent-events.md section 10), read with
|
|
407
|
+
* every record of every pack in the case, or `null` where step 1 gives it no
|
|
408
|
+
* verdict or it was not read. Its findings move no verdict; a `nonconforming`
|
|
409
|
+
* or `partial` reading moves its pack's grade (section 5.4.5).
|
|
410
|
+
*/
|
|
411
|
+
agent: AgentRecordReading | null;
|
|
825
412
|
}
|
|
826
|
-
/**
|
|
827
|
-
* One NOTE on the reading (5.5.3 v1.20): something true a reader needs and
|
|
828
|
-
* nothing a reader could not tell, so it carries no contribution.
|
|
829
|
-
*/
|
|
413
|
+
/** A note on the reading (§5.5.3): true and needed, with no contribution. */
|
|
830
414
|
export interface CaseNote {
|
|
831
415
|
kind: CaseNoteKind;
|
|
832
|
-
/** Which pack, by the reader's own name for it. */
|
|
833
416
|
packRef: string;
|
|
834
|
-
/** Which pack, by its position in `CaseReading.packs` (A43). */
|
|
835
417
|
packIndex: number;
|
|
836
|
-
/**
|
|
837
|
-
* For `CONTENT_WITHHELD_BY_DECLARATION`, how many of the pack's records its
|
|
838
|
-
* declaration withholds.
|
|
839
|
-
*/
|
|
418
|
+
/** For `CONTENT_WITHHELD_BY_DECLARATION`, how many records are withheld. */
|
|
840
419
|
count?: number;
|
|
841
420
|
}
|
|
842
421
|
/**
|
|
843
|
-
* One pack as
|
|
844
|
-
*
|
|
845
|
-
* its wrapper, and never by an organization (D10).
|
|
422
|
+
* One pack as read, in the order given (§5.5.4). A surface names a pack by
|
|
423
|
+
* `signingKey`, never by an organization.
|
|
846
424
|
*/
|
|
847
425
|
export interface CasePackReading {
|
|
848
|
-
/**
|
|
849
|
-
* The pack's position in the order the reader was given the packs, 0 first
|
|
850
|
-
* (A43): the one name for a pack that is unique in the reading. Every
|
|
851
|
-
* exception, note and record names its pack by it as `packIndex`.
|
|
852
|
-
*/
|
|
426
|
+
/** The pack's position in the order given: its one unique name in the reading. */
|
|
853
427
|
index: number;
|
|
854
|
-
/** The reader's own name for the pack.
|
|
428
|
+
/** The reader's own name for the pack. Not unique. */
|
|
855
429
|
ref: string;
|
|
856
430
|
/** The wrapper key, normalized, or `null` where this reader could not read it. */
|
|
857
431
|
signingKey: string | null;
|
|
858
|
-
/**
|
|
859
|
-
* The case grade (5.5.1 step 1), or `null` where the wrapper did not hold or
|
|
860
|
-
* the key could not be read.
|
|
861
|
-
*/
|
|
432
|
+
/** The case grade (§5.5.1), or `null` where the wrapper did not hold or the key is unreadable. */
|
|
862
433
|
grade: PackVerdict | null;
|
|
863
|
-
/**
|
|
864
|
-
* Records withheld by the pack's declaration (5.4.5): in scope for their
|
|
865
|
-
* signature and commitment only. Never counted as verified records.
|
|
866
|
-
*/
|
|
434
|
+
/** Records withheld by the declaration (§5.4.5). Never counted as verified. */
|
|
867
435
|
recordsWithheld: number;
|
|
868
|
-
/**
|
|
869
|
-
* `sanning.declaration/v1`, `sanning.declaration/v2`, or `null` where the
|
|
870
|
-
* pack carries no declaration, one this reader does not know, or a body this
|
|
871
|
-
* reader does not read.
|
|
872
|
-
*/
|
|
436
|
+
/** The declaration version, or `null` where absent, unknown or in an unread body. */
|
|
873
437
|
declarationVersion: string | null;
|
|
874
438
|
}
|
|
875
439
|
export interface CaseReading {
|
|
876
440
|
verdict: CaseVerdict;
|
|
441
|
+
/** `changed` or `nonconforming` where `verdict` is `failed`. */
|
|
442
|
+
reasonKind?: ReasonKind;
|
|
877
443
|
/**
|
|
878
|
-
* Every
|
|
879
|
-
* order
|
|
880
|
-
* order and bundle order.
|
|
881
|
-
*
|
|
882
|
-
* **An empty array is the only shape a reader may read as clean**, and it is
|
|
883
|
-
* reachable only together with `verdict === "verified"`.
|
|
444
|
+
* Every problem behind the verdict, each mapped to one claim and one state, in
|
|
445
|
+
* exception order. Empty exactly where `verdict` is `verified`.
|
|
884
446
|
*/
|
|
885
|
-
|
|
447
|
+
problems: Problem[];
|
|
886
448
|
/**
|
|
887
|
-
*
|
|
888
|
-
* bundle order
|
|
449
|
+
* Every exception: pack-level ones in pack order, then record-level ones in
|
|
450
|
+
* pack and bundle order. Empty is the only clean shape, and only with
|
|
451
|
+
* `verdict === "verified"`.
|
|
889
452
|
*/
|
|
453
|
+
exceptions: CaseException[];
|
|
454
|
+
/** One entry per record of every pack, read or not. */
|
|
890
455
|
records: CaseRecordReading[];
|
|
891
456
|
/**
|
|
892
|
-
* Every `[contributor, verdict]` the
|
|
893
|
-
*
|
|
894
|
-
* kernels compare the derivation and not only its answer.
|
|
457
|
+
* Every `[contributor, verdict]` the verdict was computed from, so the
|
|
458
|
+
* verdict is auditable rather than asserted.
|
|
895
459
|
*/
|
|
896
460
|
contributions: [string, CaseVerdict][];
|
|
897
|
-
/**
|
|
461
|
+
/** Hand-off records in the case. Zero is its own exception. */
|
|
898
462
|
handoffRecords: number;
|
|
899
463
|
/**
|
|
900
|
-
* Whether any witness
|
|
901
|
-
*
|
|
902
|
-
*
|
|
903
|
-
*
|
|
904
|
-
*
|
|
905
|
-
* is ABSENT, so the honest omission is named and the unverifiable assertion
|
|
906
|
-
* is not: a holder that writes any `anchor_ref` at all reads `verified`,
|
|
907
|
-
* because this reader makes no network call. That is the standing lens
|
|
908
|
-
* inverted, and the answer is not to refuse the assertion, which no offline
|
|
909
|
-
* reader can grade. It is to say what was not checked, so nobody reads a
|
|
910
|
-
* clean case as "a witness held". Re-fetching on chain stays the caller's
|
|
911
|
-
* job, exactly as `evidence-bundle.md` 5.5's does-not-claim list says.
|
|
912
|
-
*
|
|
913
|
-
* Derived from each pack's own `EvidenceBundleResult.onChainChecked` rather
|
|
914
|
-
* than written as a constant, so it stays true of what was actually run:
|
|
915
|
-
* this reader passes no gateways, and it is the ALL of an empty list of
|
|
916
|
-
* checked packs, which is false.
|
|
464
|
+
* Whether any witness was re-fetched on chain. Always false here: this reader
|
|
465
|
+
* makes no network call, so a pack with any `anchor_ref` reads `verified`
|
|
466
|
+
* without the witness being checked. Stated so nobody reads a clean case as
|
|
467
|
+
* "a witness held"; re-fetching is the caller's (evidence-bundle §5.5).
|
|
468
|
+
* Derived from each pack's `onChainChecked`, not written as a constant.
|
|
917
469
|
*/
|
|
918
470
|
onChainChecked: boolean;
|
|
919
|
-
/**
|
|
471
|
+
/** Notes, in pack order (§5.5.3). No contribution. */
|
|
920
472
|
notes: CaseNote[];
|
|
921
|
-
/** One reading per pack, in the order
|
|
473
|
+
/** One reading per pack, in the order given. */
|
|
922
474
|
packs: CasePackReading[];
|
|
923
475
|
}
|
|
924
476
|
/**
|
|
925
|
-
*
|
|
926
|
-
*
|
|
927
|
-
|
|
477
|
+
* Every exception, mapped to its claim and state, in exception order. A pack grade
|
|
478
|
+
* carries its own problems; a pack grade with none (a defence) reads as its status.
|
|
479
|
+
*/
|
|
480
|
+
export declare function caseProblems(exceptions: readonly CaseException[]): Problem[];
|
|
481
|
+
/**
|
|
482
|
+
* Reads a case: packs in, one verdict and its exceptions out.
|
|
928
483
|
*
|
|
929
|
-
* 1.
|
|
930
|
-
*
|
|
931
|
-
*
|
|
932
|
-
*
|
|
933
|
-
*
|
|
934
|
-
*
|
|
935
|
-
*
|
|
936
|
-
* 3. **Every record every pack supplied goes into ONE pile**, with no partition
|
|
937
|
-
* by pack, by issuer or by organization, and the pile is read by
|
|
938
|
-
* `readHandoffs`, which is the one implementation of 4.1. This is where
|
|
939
|
-
* matching happens, and it is on keys and hashes alone.
|
|
940
|
-
* 4. **Each reading becomes an exception or a clean contribution**, and the two
|
|
941
|
-
* counterpart kinds are separated by asking whether a pack SIGNED by the
|
|
942
|
-
* counterparty's key is in the case, a key read from every pack's wrapper
|
|
943
|
-
* before any exit can skip it.
|
|
484
|
+
* 1. Each pack is read into records (`packRecords`); an unknown body or no
|
|
485
|
+
* records is named.
|
|
486
|
+
* 2. Each pack is graded against its own declaration (`checkDeclaration`).
|
|
487
|
+
* 3. Every record goes into one pile, unpartitioned, read by `readHandoffs`.
|
|
488
|
+
* 4. Each reading becomes an exception or a clean contribution. The
|
|
489
|
+
* counterpart kinds are told apart by whether a pack signed by the
|
|
490
|
+
* counterparty's key is in the case, read from every wrapper before any exit.
|
|
944
491
|
*
|
|
945
|
-
*
|
|
946
|
-
*
|
|
947
|
-
*
|
|
948
|
-
* `incomplete`: the reader genuinely cannot tell whether the record it cannot
|
|
949
|
-
* see is the counterpart that is missing.
|
|
492
|
+
* Before step 1 the agent records of every pack are read as one pile
|
|
493
|
+
* (agent-events.md section 10), and each pack is graded with those readings
|
|
494
|
+
* (evidence-bundle.md section 5.4.5, section 5.5.1).
|
|
950
495
|
*/
|
|
951
496
|
export declare function readCase(packs: readonly CasePack[]): Promise<CaseReading>;
|
|
497
|
+
/**
|
|
498
|
+
* The house wording for one exception. Optional: the verdict and the set of
|
|
499
|
+
* exceptions are what must not vary between surfaces.
|
|
500
|
+
*/
|
|
952
501
|
export declare function renderException(exception: CaseException): string;
|
|
953
|
-
/** The house wording for one
|
|
502
|
+
/** The house wording for one note. */
|
|
954
503
|
export declare function renderCaseNote(note: CaseNote): string;
|
|
955
504
|
/**
|
|
956
|
-
* The scope sentence
|
|
957
|
-
*
|
|
958
|
-
*
|
|
959
|
-
*
|
|
960
|
-
*
|
|
961
|
-
* exceptions; and that the reading was made offline. Where any pack holds
|
|
962
|
-
* records withheld by its declaration, their total; where any pack is noted
|
|
963
|
-
* `pack_undeclared`, how many. Those two lines are part of what the headline
|
|
964
|
-
* MEANS, and a surface MUST print them with it.
|
|
965
|
-
*
|
|
966
|
-
* What was not checked on the public record is no longer a clause here. It is
|
|
967
|
-
* the witness line (`renderWitnessLine`), printed with every headline.
|
|
505
|
+
* The scope sentence printed under the headline (evidence-bundle §5.5.6): packs,
|
|
506
|
+
* distinct signing keys of packs whose wrapper held, hand-off records,
|
|
507
|
+
* exceptions, and that it was read offline, plus withheld and undeclared
|
|
508
|
+
* counts where non-zero. Those counts are part of what the headline means, and
|
|
509
|
+
* a surface must print them with it.
|
|
968
510
|
*/
|
|
969
511
|
export declare function renderCaseSummary(reading: CaseReading): string;
|
|
970
512
|
/**
|
|
971
|
-
* The one display title of each of the
|
|
972
|
-
* title, never the word, and never a title of its own
|
|
973
|
-
* is Will's to change through the glossary (DL-71); what each MEANS is pinned
|
|
974
|
-
* in the spec.
|
|
513
|
+
* The one display title of each of the three section 3 verdicts. A surface prints the
|
|
514
|
+
* title, never the word, and never a title of its own.
|
|
975
515
|
*/
|
|
976
516
|
export declare const VERDICT_DISPLAY_TITLES: Readonly<Record<string, string>>;
|
|
977
517
|
/**
|
|
978
|
-
* What a reader may rely on, for each
|
|
979
|
-
*
|
|
980
|
-
*
|
|
981
|
-
* witness states. `verified` is the base sentence, printed alone where the
|
|
982
|
-
* drop holds no hand-off record; a caller reads `caseReliance` for
|
|
983
|
-
* `verified`, never this mapping directly.
|
|
518
|
+
* What a reader may rely on, for each verdict a case reading reaches (section 5.5.6), the
|
|
519
|
+
* same for every drop, keyed by the verdict and, for `failed`, its reason kind. Call
|
|
520
|
+
* `caseReliance` rather than reading `verified` here directly.
|
|
984
521
|
*/
|
|
985
|
-
export declare const CASE_RELIANCE: Readonly<Record<CaseVerdict, string>>;
|
|
522
|
+
export declare const CASE_RELIANCE: Readonly<Record<CaseVerdict | "failed_nonconforming", string>>;
|
|
986
523
|
/**
|
|
987
|
-
*
|
|
988
|
-
*
|
|
989
|
-
* and never where `handoffRecords` is zero: most drops hold one agent's
|
|
990
|
-
* pack and no hand-off to say anything about.
|
|
524
|
+
* Added to a `verified` reliance line after its first sentence, only where the
|
|
525
|
+
* drop holds a hand-off record.
|
|
991
526
|
*/
|
|
992
527
|
export declare const CASE_RELIANCE_HANDOFF_CLAUSE = "Every hand-off with both sides in this drop is intact.";
|
|
993
528
|
/**
|
|
994
|
-
*
|
|
995
|
-
*
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
*
|
|
1000
|
-
*
|
|
529
|
+
* Added after the reliance line's first sentence, for every verdict, where the
|
|
530
|
+
* drop holds `environment: "dev"` envelopes: `dev` if all are, `mixed` if some.
|
|
531
|
+
*/
|
|
532
|
+
export declare const CASE_RELIANCE_SANDBOX: Readonly<Record<EnvironmentMarker, string>>;
|
|
533
|
+
/**
|
|
534
|
+
* What a reader may rely on for one case reading (§5.5.6). The sandbox
|
|
535
|
+
* sentence, if any, follows the first sentence and precedes the hand-off
|
|
536
|
+
* clause, which a `verified` reading gains only with `handoffRecords > 0`, so
|
|
537
|
+
* the line never claims a hand-off the drop does not hold.
|
|
1001
538
|
*/
|
|
1002
|
-
export declare function caseReliance(verdict: CaseVerdict, handoffRecords: number): string;
|
|
1003
|
-
/** The three witness states
|
|
539
|
+
export declare function caseReliance(verdict: CaseVerdict, handoffRecords: number, environmentMarker?: EnvironmentMarker | null, reasonKind?: ReasonKind | null): string;
|
|
540
|
+
/** The three witness states and how each is printed (§5.5.6). No others. */
|
|
1004
541
|
export declare const WITNESS_STATES: {
|
|
1005
542
|
readonly confirmed: "Confirmed on the public record";
|
|
1006
543
|
readonly not_checked: "Not checked";
|
|
@@ -1008,34 +545,30 @@ export declare const WITNESS_STATES: {
|
|
|
1008
545
|
};
|
|
1009
546
|
export type WitnessState = keyof typeof WITNESS_STATES;
|
|
1010
547
|
/**
|
|
1011
|
-
* The
|
|
1012
|
-
*
|
|
1013
|
-
*
|
|
1014
|
-
* settle, in a fixed order; `services` names each service that answered, as
|
|
1015
|
-
* the URL the lookup used: named, never trusted (6).
|
|
548
|
+
* The result of a public-record lookup, reported beside the headline, never
|
|
549
|
+
* in it, and never moving it. `reasons` says why `not_checked` did not settle;
|
|
550
|
+
* `services` names each gateway that answered: named, never trusted.
|
|
1016
551
|
*/
|
|
1017
552
|
export interface WitnessLine {
|
|
1018
553
|
state: WitnessState;
|
|
1019
554
|
reasons: string[];
|
|
1020
555
|
services: string[];
|
|
1021
556
|
/**
|
|
1022
|
-
*
|
|
1023
|
-
*
|
|
1024
|
-
*
|
|
557
|
+
* Cached witness times no lookup settled, as `[blockHeight, blockTime]`,
|
|
558
|
+
* distinct and in time order (§5.6.6). Printed as not checked, never as a
|
|
559
|
+
* time a reader may rely on.
|
|
1025
560
|
*/
|
|
1026
561
|
cached?: [number, number][];
|
|
1027
562
|
/**
|
|
1028
|
-
* Witness times the public record returned
|
|
1029
|
-
*
|
|
1030
|
-
* service, never the cache's value. Absent reads as none.
|
|
563
|
+
* Witness times the public record returned that matched the cache, distinct
|
|
564
|
+
* and in time order. Always the gateway's answer, never the cache's value.
|
|
1031
565
|
*/
|
|
1032
566
|
recorded?: [number, number][];
|
|
1033
567
|
}
|
|
1034
|
-
/** The line
|
|
568
|
+
/** The line where no lookup ran: every reading this module produces on its own. */
|
|
1035
569
|
export declare const WITNESS_NOT_LOOKED_UP: Readonly<WitnessLine>;
|
|
1036
|
-
/**
|
|
1037
|
-
/** How a witness time a pack caches is printed where nothing checked it (5.5.6, 5.6.6, v1.25, A30). */
|
|
570
|
+
/** A cached witness time no lookup checked (§5.6.6). */
|
|
1038
571
|
export declare const WITNESS_TIME_CACHED = "the pack dates the witness, not checked";
|
|
1039
|
-
/**
|
|
572
|
+
/** A witness time the public record returned that matched the cache. */
|
|
1040
573
|
export declare const WITNESS_TIME_RECORDED = "the public record dates the witness";
|
|
1041
574
|
export declare function renderWitnessLine(line: WitnessLine): string;
|