@sanning/proof 0.19.1 → 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 +339 -822
- package/dist/case.js +667 -1160
- 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 +814 -1328
- 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 +131 -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 +573 -581
- 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,1022 +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";
|
|
246
66
|
import type { EnvironmentMarker } from "./environment.js";
|
|
247
67
|
import type { SideContentMap } from "./side-content.js";
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
* no new verdict word is introduced anywhere.
|
|
252
|
-
*/
|
|
253
|
-
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"];
|
|
254
71
|
export type CaseVerdict = (typeof CASE_VERDICTS)[number];
|
|
255
72
|
/**
|
|
256
|
-
* The
|
|
257
|
-
* (
|
|
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.
|
|
258
76
|
*
|
|
259
|
-
* `
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
* the case read clean over it: the exact defect class this module is written
|
|
263
|
-
* against. An unknown value is `PACK_BODY_TYPE_UNKNOWN`.
|
|
264
|
-
*
|
|
265
|
-
* **`sanning.evidence.export/v2` is NOT in this set and is NOT unwrapped.** It
|
|
266
|
-
* verifies as a bundle and carries a whole `sanning.anchor.trace/v3` pack under
|
|
267
|
-
* `body.source_bundle`, so its records do not reach the pile and the export is
|
|
268
|
-
* named `PACK_BODY_TYPE_UNKNOWN`, `incomplete`. Reading inside it changes which
|
|
269
|
-
* packs this reader grades, so it is a decision of its own. A reader who needs
|
|
270
|
-
* the records hands in the source bundle as a pack. The export's wrapper key is
|
|
271
|
-
* still read, so wrapping a pack in one does not change which counterpart kind
|
|
272
|
-
* 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.
|
|
273
80
|
*/
|
|
274
81
|
export declare const CASE_BODY_TYPES: readonly ["sanning.anchor.trace/v3", "sanning.stamp.evidence/v2"];
|
|
275
82
|
/**
|
|
276
|
-
* The
|
|
277
|
-
* accept-set
|
|
278
|
-
*
|
|
279
|
-
* from that file, and a test here pins this one equal to this kernel's own
|
|
280
|
-
* `ACCEPTED_SPEC_MAJORS`, which is what `verifyEvidenceBundle` reads under:
|
|
281
|
-
* the Python kernel narrows its verifier to this set for the case reader, and
|
|
282
|
-
* this kernel's verifier already reads exactly it. If this kernel ever admits
|
|
283
|
-
* a quarantined profile, that test fails, and the case reader has to narrow
|
|
284
|
-
* 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.
|
|
285
86
|
*/
|
|
286
|
-
export declare const CASE_RECORD_PROFILES: readonly ["sanning.
|
|
287
|
-
/**
|
|
87
|
+
export declare const CASE_RECORD_PROFILES: readonly ["sanning.events/v2"];
|
|
88
|
+
/** Accepted profiles under quarantine. */
|
|
288
89
|
export declare const CASE_QUARANTINED_PROFILES: readonly ["sanning.mlflow/v1"];
|
|
289
90
|
/**
|
|
290
|
-
* A conformant hand-off record with no counterpart
|
|
291
|
-
*
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
* That is ALL it says. It does not say the counterparty's account is absent,
|
|
298
|
-
* and it does not say nothing was tampered with: a counterparty that signs its
|
|
299
|
-
* own pack under a second key, or hands over an export an issuer signed,
|
|
300
|
-
* reaches this reading too, and nothing offline binds a pack's key to the keys
|
|
301
|
-
* of the records inside it (proof#143). The rendered text states the fact and
|
|
302
|
-
* stops.
|
|
303
|
-
*
|
|
304
|
-
* It says nothing about RECORDS signed by that key either. A party may hold records
|
|
305
|
-
* its counterparty signed, and those are still graded as candidates, but they
|
|
306
|
-
* are not the counterparty's account of itself, so they do not move this
|
|
307
|
-
* 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.
|
|
308
97
|
*/
|
|
309
98
|
export declare const COUNTERPART_ABSENT = "counterpart_absent";
|
|
310
99
|
/**
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
*
|
|
314
|
-
* and is SIGNED by the key this record names is in the case, and not one
|
|
315
|
-
* record this reader could read is this record's counterpart. It states that a
|
|
316
|
-
* pack signed by the named key is present and holds no counterpart this reader
|
|
317
|
-
* could read, and nothing more. 4.1 (v1.10, A15) and 5.4.2 rule 7 (v1.10) both point here, and
|
|
318
|
-
* `declaration/declaration-unclaimed-record-01` is the pack that reaches this
|
|
319
|
-
* line.
|
|
320
|
-
*
|
|
321
|
-
* **"Its own account" is read from the key that signed the PACK, and never
|
|
322
|
-
* from the keys that signed records.** A pack's wrapper key signs `body_hash`
|
|
323
|
-
* and `body` carries the declaration (`evidence-bundle.md` 5.4, "Who signs
|
|
324
|
-
* it"), so a wrapper signed by B is provenance the accusing party cannot forge
|
|
325
|
-
* without B's private key. Records signed by B that A merely HOLDS are not B's
|
|
326
|
-
* account of itself: keyed on record keys, one pack from A plus one unrelated
|
|
327
|
-
* record B signed at some other time reached this line when B had handed over
|
|
328
|
-
* 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`).
|
|
329
103
|
*
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
* otherwise (the declaration's `case_id` and `period`) are written by B and
|
|
334
|
-
* would let B leave this line by writing them differently. The cost the other
|
|
335
|
-
* way: a pack B assembles under any key other than the one its records name, a
|
|
336
|
-
* per-organization hand-over key (anchor#196) included, reads
|
|
337
|
-
* `COUNTERPART_ABSENT`, because nothing in the case binds that key to B. That
|
|
338
|
-
* reading is still true: no pack signed by the named key is here. So a
|
|
339
|
-
* counterparty can AVOID this line by choosing the key it signs under; what it
|
|
340
|
-
* 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.
|
|
341
107
|
*
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
*
|
|
345
|
-
*
|
|
346
|
-
*
|
|
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.
|
|
347
113
|
*
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
*
|
|
351
|
-
* contain this hand-off" are the honest reading and the damning one, and one
|
|
352
|
-
* name for both lets the second read as the first.
|
|
353
|
-
*
|
|
354
|
-
* It is still an EXCEPTION and not a failure, which criterion 3 requires and
|
|
355
|
-
* which is also the honest call: the counterparty's pack is a selection over
|
|
356
|
-
* its own interval, and a hand-off outside that interval is legitimately not
|
|
357
|
-
* in it. What this names is that the question can now be ASKED of the other
|
|
358
|
-
* 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.
|
|
359
117
|
*/
|
|
360
118
|
export declare const COUNTERPART_ABSENT_FROM_COUNTERPARTY_RECORDS = "counterpart_absent_from_counterparty_records";
|
|
361
119
|
/**
|
|
362
|
-
* A conformant hand-off record with no counterpart, no
|
|
363
|
-
*
|
|
364
|
-
*
|
|
365
|
-
*
|
|
366
|
-
* Whether a pack signed by the named key is in the case is UNKNOWN, so neither
|
|
367
|
-
* of the other two kinds is true.
|
|
368
|
-
*
|
|
369
|
-
* The gate on the previous version of this reader showed why it exists. A
|
|
370
|
-
* counterparty that signed its own pack under `" " + key` got
|
|
371
|
-
* `PACK_KEY_UNREADABLE` for the pack and the innocent `COUNTERPART_ABSENT` for
|
|
372
|
-
* the record, and the output contradicted itself: whose pack it was is
|
|
373
|
-
* UNKNOWN, and then no pack is signed by the named key. The second sentence
|
|
374
|
-
* was not established.
|
|
375
|
-
*
|
|
376
|
-
* `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`.
|
|
377
124
|
*/
|
|
378
125
|
export declare const COUNTERPART_ABSENT_SIGNER_UNKNOWN = "counterpart_absent_signer_unknown";
|
|
379
126
|
/**
|
|
380
|
-
* More than one candidate counterpart
|
|
381
|
-
*
|
|
382
|
-
*
|
|
383
|
-
* record. `count` is how many of the candidates are live, which is the number
|
|
384
|
-
* 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.
|
|
385
130
|
*/
|
|
386
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";
|
|
387
136
|
/**
|
|
388
|
-
* A
|
|
389
|
-
*
|
|
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`.
|
|
390
142
|
*/
|
|
391
|
-
export declare const
|
|
143
|
+
export declare const COUNTERPART_MALFORMED = "counterpart_malformed";
|
|
392
144
|
/**
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
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.
|
|
396
148
|
*/
|
|
397
|
-
export declare const
|
|
149
|
+
export declare const RECORD_NONCONFORMING = "record_nonconforming";
|
|
398
150
|
/**
|
|
399
|
-
* A
|
|
400
|
-
*
|
|
401
|
-
*
|
|
402
|
-
* outranks `failed`, so one junk record signed by the counterparty's key makes
|
|
403
|
-
* the reading of a perfectly well formed record `malformed` too. Filed under
|
|
404
|
-
* `RECORD_MALFORMED`, that read as "this record is not a well formed hand-off
|
|
405
|
-
* record" about the HONEST record, and the branch it took skipped the
|
|
406
|
-
* counterpart, ambiguity and `failedChecks` reporting entirely: one junk record
|
|
407
|
-
* both blamed the wrong party and stripped a named `message_hash` failure out
|
|
408
|
-
* of the case. That is proof#133 ruling 6, which 4.1 closed by keeping the
|
|
409
|
-
* UNION of `failedChecks`, reappearing one layer out because this layer
|
|
410
|
-
* discarded that union.
|
|
411
|
-
*
|
|
412
|
-
* A record's own conformance and its candidate's are different facts and do
|
|
413
|
-
* not share a kind. This one is `incomplete` and not `malformed`: the proven
|
|
414
|
-
* defect belongs to the candidate, which carries its own `RECORD_MALFORMED`
|
|
415
|
-
* line, and what is true of THIS record is that its pairing could not be
|
|
416
|
-
* determined. Contributing `malformed` here would attribute the candidate's
|
|
417
|
-
* 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`.
|
|
418
154
|
*/
|
|
419
|
-
export declare const
|
|
155
|
+
export declare const COUNTERPART_NONCONFORMING = "counterpart_nonconforming";
|
|
420
156
|
/**
|
|
421
|
-
* A record
|
|
422
|
-
*
|
|
423
|
-
*
|
|
424
|
-
*
|
|
425
|
-
*
|
|
426
|
-
* **It turns on what the PACK said about the record, and never on whether 4.1
|
|
427
|
-
* governs it.** Gating it on "is this a conformant hand-off record" put it
|
|
428
|
-
* behind a value the audited party writes: the same second receipt, respelled
|
|
429
|
-
* with an `ff` ligature in `event_type` and a Cyrillic `е` in
|
|
430
|
-
* `counterparty_public_key`, left 4.1's scope, took the `not_a_handoff_record`
|
|
431
|
-
* branch, and bought a case reading of `verified` with zero exceptions where
|
|
432
|
-
* the conformant spelling read `mixed` with four. proof#136 ratified that a
|
|
433
|
-
* respelling buys a DIFFERENT LINE rather than no line; at this layer it
|
|
434
|
-
* 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.
|
|
435
161
|
*
|
|
436
|
-
*
|
|
437
|
-
*
|
|
438
|
-
*
|
|
439
|
-
* meant to give or one it is keeping out of its own account, and that is "I
|
|
440
|
-
* could not tell", which is why it carries `incomplete` and not `verified`.
|
|
441
|
-
*
|
|
442
|
-
* THE COST, stated rather than left to be found: a pack that declares records
|
|
443
|
-
* which are not hand-off sides at all, an ordinary log line among them, is
|
|
444
|
-
* named once per such record, so a case holding one cannot read `verified`.
|
|
445
|
-
* That is the price of a rule with no branch the holder selects, and the only
|
|
446
|
-
* narrower rule available keys on a value the holder writes. A surface that
|
|
447
|
-
* wants the two apart reads `CaseRecordReading.findings`, where
|
|
448
|
-
* `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.
|
|
449
165
|
*/
|
|
450
166
|
export declare const RECORD_UNCLAIMED = "record_unclaimed_by_its_pack";
|
|
451
167
|
/**
|
|
452
|
-
* The pack
|
|
453
|
-
*
|
|
454
|
-
*
|
|
455
|
-
* `event_bytes` is OPTIONAL (5.1, 5.3) and withholding it is minimum
|
|
456
|
-
* disclosure, which the corpus calls a customer's right and not a defect
|
|
457
|
-
* (proof#137, defect 3), so this is not a deviation and does not fail. It is
|
|
458
|
-
* still SAID, because a withheld record is exactly where a missing counterpart
|
|
459
|
-
* would hide, and a reader that dropped it silently would read a trimmed pack
|
|
460
|
-
* 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.
|
|
461
171
|
*/
|
|
462
172
|
export declare const RECORD_BYTES_WITHHELD = "record_bytes_withheld";
|
|
463
173
|
/**
|
|
464
|
-
* The pack
|
|
465
|
-
*
|
|
466
|
-
* `packRecords`). Bytes the holder handed over that do not decode are a defect
|
|
467
|
-
* 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`.
|
|
468
176
|
*/
|
|
469
177
|
export declare const RECORD_BYTES_UNREADABLE = "record_bytes_unreadable";
|
|
470
|
-
/**
|
|
471
|
-
* The pack deviates from its own declaration (5.4.2). A proven mismatch, so it
|
|
472
|
-
* fails: a case cannot be clean over a pack that is proven to be trimmed.
|
|
473
|
-
*/
|
|
178
|
+
/** The pack deviates from its own declaration (§5.4.2). A proven mismatch: `failed`. */
|
|
474
179
|
export declare const PACK_DECLARATION_DEVIATES = "pack_declaration_deviates";
|
|
475
180
|
/**
|
|
476
|
-
* The pack and the
|
|
477
|
-
*
|
|
478
|
-
*
|
|
479
|
-
* declares `content_withheld` for which bytes reached this reader from the
|
|
480
|
-
* side-content map alone.
|
|
481
|
-
*
|
|
482
|
-
* `incomplete` and never `failed`, which is the whole point of the kind. 5.4
|
|
483
|
-
* grades a pack's declaration partly against content the READER was handed,
|
|
484
|
-
* and whoever assembles a case fills that map in. Under
|
|
485
|
-
* `PACK_DECLARATION_DEVIATES` an accuser could put an intact pack into a
|
|
486
|
-
* `failed` case WITH NO KEY AT ALL: supply bytes for a record its holder
|
|
487
|
-
* declared withheld, or drop the bytes of one it declared disclosed. The pack
|
|
488
|
-
* was intact, its wrapper verified, and its holder had done nothing. This is
|
|
489
|
-
* the mirror of proof#143, where a counterparty makes ITSELF look better by
|
|
490
|
-
* 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.
|
|
491
184
|
*
|
|
492
|
-
*
|
|
493
|
-
*
|
|
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.
|
|
494
188
|
*/
|
|
495
189
|
export declare const PACK_DECLARATION_CONTENT_DEPENDENT = "pack_declaration_content_dependent";
|
|
496
190
|
/**
|
|
497
|
-
* The pack
|
|
498
|
-
*
|
|
499
|
-
* does not satisfy 5.4.1. `declaration_version` is chosen by the same party
|
|
500
|
-
* that assembles the pack and has no accept-set of its own, so this is UNKNOWN
|
|
501
|
-
* 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.
|
|
502
193
|
*/
|
|
503
194
|
export declare const PACK_DECLARATION_UNREADABLE = "pack_declaration_unreadable";
|
|
504
195
|
/**
|
|
505
|
-
* The pack carries no `declaration`
|
|
506
|
-
*
|
|
507
|
-
* `verified`, because there is nothing to check the pack against, and never
|
|
508
|
-
* `failed`, because nothing is wrong.
|
|
196
|
+
* The pack carries no `declaration`. `partial` (§5.4.3): nothing to check
|
|
197
|
+
* against, and nothing wrong.
|
|
509
198
|
*/
|
|
510
199
|
export declare const PACK_UNDECLARED = "pack_undeclared";
|
|
511
|
-
/**
|
|
512
|
-
* The pack's `body_type` is not one this reader knows to carry `events[]`
|
|
513
|
-
* (`CASE_BODY_TYPES`).
|
|
514
|
-
*/
|
|
200
|
+
/** The pack's `body_type` is not in `CASE_BODY_TYPES`. */
|
|
515
201
|
export declare const PACK_BODY_TYPE_UNKNOWN = "pack_body_type_unknown";
|
|
516
|
-
/**
|
|
517
|
-
* The pack carries a body this reader knows and no records in it. A pack that
|
|
518
|
-
* contributes nothing is named rather than passed over.
|
|
519
|
-
*/
|
|
202
|
+
/** The pack carries a known body with no records. */
|
|
520
203
|
export declare const PACK_HOLDS_NO_RECORDS = "pack_holds_no_records";
|
|
521
204
|
/**
|
|
522
|
-
* The
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
*
|
|
526
|
-
* `
|
|
527
|
-
*
|
|
528
|
-
* Found by constructing it, while enumerating this module's exits: the wrapper
|
|
529
|
-
* key is the ONE input that separates the two counterpart kinds, and a key this
|
|
530
|
-
* reader could not read used to drop out of that set in silence. The Python
|
|
531
|
-
* `verify_evidence_bundle` accepts a wrapper `public_key` with ASCII
|
|
532
|
-
* whitespace inside it or around it (`bytes.fromhex` skips it; this kernel's
|
|
533
|
-
* verifier rejects it), so a counterparty that signed its own pack under
|
|
534
|
-
* `" " + key` handed a Python reader a pack that verified, contributed no key,
|
|
535
|
-
* and moved the subject from `COUNTERPART_ABSENT_FROM_COUNTERPARTY_RECORDS` to
|
|
536
|
-
* the innocent `COUNTERPART_ABSENT`. The same repair 4.1 made for a RECORD
|
|
537
|
-
* whose envelope key it cannot read (proof#133, fourth hunt): a key a reader
|
|
538
|
-
* holds and cannot read is named, never treated as absent. It is `incomplete`
|
|
539
|
-
* rather than `malformed` because whether the spelling verifies is the envelope
|
|
540
|
-
* 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.
|
|
541
211
|
*/
|
|
542
212
|
export declare const PACK_KEY_UNREADABLE = "pack_key_unreadable";
|
|
543
213
|
/**
|
|
544
|
-
* The pack
|
|
545
|
-
*
|
|
546
|
-
*
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
*
|
|
551
|
-
*
|
|
552
|
-
*
|
|
553
|
-
*
|
|
554
|
-
* an unknown body or withheld bytes produce, and those are named on their own.
|
|
555
|
-
*
|
|
556
|
-
* `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`.
|
|
557
224
|
*/
|
|
558
225
|
export declare const PACK_DOES_NOT_VERIFY = "pack_does_not_verify";
|
|
559
226
|
/**
|
|
560
|
-
* The pack's wrapper
|
|
561
|
-
* (evidence-bundle 5.5.1
|
|
562
|
-
*
|
|
563
|
-
*
|
|
564
|
-
*
|
|
565
|
-
*
|
|
566
|
-
*
|
|
567
|
-
* otherwise the full grade. A body the verifier could not read is `malformed`,
|
|
568
|
-
* a body that is not one of the two event-carrying bodies takes the signed
|
|
569
|
-
* run's status, and a verifier that graded a different number of records than
|
|
570
|
-
* 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
|
|
571
234
|
* `verified`.
|
|
572
235
|
*
|
|
573
|
-
*
|
|
574
|
-
*
|
|
575
|
-
* `
|
|
576
|
-
* CONTRIBUTES the grade, and `incomplete` for `pending`, `not_found` or
|
|
577
|
-
* `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.
|
|
578
239
|
*/
|
|
579
240
|
export declare const PACK_GRADE_NOT_VERIFIED = "pack_grade_not_verified";
|
|
580
241
|
/**
|
|
581
|
-
* A record
|
|
582
|
-
*
|
|
583
|
-
*
|
|
584
|
-
* is proven not to verify. As a reason to drop the whole pack it let the
|
|
585
|
-
* counterparty add one junk event to its own pack, re-seal it, and strip a
|
|
586
|
-
* 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.
|
|
587
245
|
*/
|
|
588
246
|
export declare const RECORD_ENVELOPE_DOES_NOT_VERIFY = "record_envelope_does_not_verify";
|
|
589
247
|
/**
|
|
590
|
-
* A record whose envelope verifies
|
|
591
|
-
*
|
|
592
|
-
*
|
|
593
|
-
*
|
|
594
|
-
* remove its own tampered receipt from pairing by breaking that receipt's
|
|
595
|
-
* 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.
|
|
596
252
|
*/
|
|
597
253
|
export declare const RECORD_DOES_NOT_VERIFY_IN_ITS_PACK = "record_does_not_verify_in_its_pack";
|
|
598
254
|
/**
|
|
599
|
-
* A record whose
|
|
600
|
-
*
|
|
601
|
-
*
|
|
602
|
-
* side map EMPTY: the content is inside the signed body. The same mismatch from
|
|
603
|
-
* content handed in beside the pack is `RECORD_CONTENT_DEPENDENT` (proof#159).
|
|
604
|
-
* `failed`, and the record STAYS in the pile: content beside a pack is unsigned and often
|
|
605
|
-
* supplied by whoever assembled the case, and gate 3 on proof#140 showed that
|
|
606
|
-
* 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.
|
|
607
258
|
*/
|
|
608
259
|
export declare const RECORD_CONTENT_MISMATCH = "record_content_mismatch";
|
|
609
260
|
/**
|
|
610
|
-
*
|
|
611
|
-
*
|
|
612
|
-
* bundle
|
|
613
|
-
*
|
|
614
|
-
*
|
|
615
|
-
* that map alone is `RECORD_CONTENT_DEPENDENT`. Both are `incomplete`: the
|
|
616
|
-
* reader established that the bytes it was handed are not the bytes the record
|
|
617
|
-
* commits to, and nothing about the party that signed the record, because
|
|
618
|
-
* whoever assembled the case chose those bytes with no key. Up to v1.15 both
|
|
619
|
-
* readings carried `failed`, and one flipped nibble of accuser-supplied content
|
|
620
|
-
* put a `failed` against an intact pack; under A17's headline rule that would
|
|
621
|
-
* have become the case's headline.
|
|
622
|
-
*
|
|
623
|
-
* The test that separates the two is the one proof#159 states for the inverse:
|
|
624
|
-
* every deviation a signature covers still reads `failed` with the side map
|
|
625
|
-
* EMPTY. So the pack is verified twice, with the map and without it, and what
|
|
626
|
-
* fails without it is `PACK_GRADE_NOT_VERIFIED`, `RECORD_CONTENT_MISMATCH`
|
|
627
|
-
* (content inside the signed body) or `RECORD_DOES_NOT_VERIFY_IN_ITS_PACK`,
|
|
628
|
-
* each still `failed`. Emptying the map is the most a party that signed
|
|
629
|
-
* 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.
|
|
630
266
|
*/
|
|
631
267
|
export declare const PACK_BUNDLE_CONTENT_DEPENDENT = "pack_bundle_content_dependent";
|
|
632
268
|
export declare const RECORD_CONTENT_DEPENDENT = "record_content_dependent";
|
|
633
269
|
/**
|
|
634
|
-
* A record
|
|
635
|
-
*
|
|
636
|
-
* `incomplete`: whether it verifies is what the kernels disagree about.
|
|
270
|
+
* A record under a quarantined profile (`CASE_QUARANTINED_PROFILES`). Not read.
|
|
271
|
+
* `incomplete`.
|
|
637
272
|
*/
|
|
638
273
|
export declare const RECORD_PROFILE_QUARANTINED = "record_profile_quarantined";
|
|
639
274
|
/** The reader was handed no packs at all. */
|
|
640
275
|
export declare const CASE_HOLDS_NO_PACKS = "case_holds_no_packs";
|
|
641
276
|
/**
|
|
642
|
-
*
|
|
643
|
-
*
|
|
644
|
-
*
|
|
645
|
-
*
|
|
646
|
-
* 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.
|
|
647
281
|
*/
|
|
648
282
|
export declare const CONTENT_WITHHELD_BY_DECLARATION = "content_withheld_by_declaration";
|
|
649
283
|
/**
|
|
650
|
-
* A pack's wrapper carries
|
|
651
|
-
*
|
|
652
|
-
*
|
|
653
|
-
* 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.
|
|
654
287
|
*/
|
|
655
288
|
export declare const CO_SIGNATURES_PRESENT = "co_signatures_present";
|
|
656
289
|
export declare const CASE_NOTE_KINDS: readonly ["pack_undeclared", "content_withheld_by_declaration", "co_signatures_present"];
|
|
657
290
|
export type CaseNoteKind = (typeof CASE_NOTE_KINDS)[number];
|
|
658
|
-
/**
|
|
659
|
-
|
|
660
|
-
* them and a test may assert over them; nothing outside this array is emitted.
|
|
661
|
-
*/
|
|
662
|
-
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"];
|
|
663
293
|
export type CaseExceptionKind = (typeof CASE_EXCEPTION_KINDS)[number];
|
|
664
294
|
/**
|
|
665
|
-
* The status
|
|
666
|
-
*
|
|
667
|
-
* of its pack's `body.events` as `packRecords` reads them, or, for a
|
|
668
|
-
* `sanning.evidence.export/v2` pack, of the events of the inline source
|
|
669
|
-
* bundle it wraps (`resolveTraceEvents`), and gets exactly one:
|
|
670
|
-
*
|
|
671
|
-
* - `read_clean`: the record went into the pile, no exception carries its
|
|
672
|
-
* `packIndex` and `recordIndex`, and its pack's declaration check
|
|
673
|
-
* names it by nothing (`declarationFindings` is empty). It says nothing
|
|
674
|
-
* about its PACK: the pack's own grade and exceptions are on the pack, and a
|
|
675
|
-
* surface MUST show that grade beside the status.
|
|
676
|
-
* - `read_flagged`: the record went into the pile, and at least one
|
|
677
|
-
* exception carries its `packIndex` and `recordIndex`, or its pack's
|
|
678
|
-
* declaration check names its `eventId` by a deviation or a content
|
|
679
|
-
* finding (`declarationFindings` is not empty; under an `eventId` the
|
|
680
|
-
* pack carries twice, every record with that id). An exception about the
|
|
681
|
-
* pack alone flags no record.
|
|
682
|
-
* - `not_read`: the record never went into the pile. `reason` is the kind
|
|
683
|
-
* of the exception that says why, on the record
|
|
684
|
-
* (`record_profile_quarantined`, `record_envelope_does_not_verify`,
|
|
685
|
-
* `record_bytes_withheld`, `record_bytes_unreadable`) or on its pack
|
|
686
|
-
* (`pack_key_unreadable`, `pack_does_not_verify`,
|
|
687
|
-
* `pack_body_type_unknown`, `pack_grade_not_verified` where the body
|
|
688
|
-
* could not be read or the verifier graded a different number of records).
|
|
689
|
-
* An export's wrapped records carry the reason of the exception their pack
|
|
690
|
-
* actually got: `pack_body_type_unknown` where its wrapper holds, and
|
|
691
|
-
* otherwise `pack_key_unreadable`, `pack_does_not_verify` or
|
|
692
|
-
* `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):
|
|
693
297
|
*
|
|
694
|
-
*
|
|
695
|
-
*
|
|
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.
|
|
696
306
|
*/
|
|
697
307
|
export declare const CASE_RECORD_STATUSES: readonly ["read_clean", "read_flagged", "not_read"];
|
|
698
308
|
export type CaseRecordStatus = (typeof CASE_RECORD_STATUSES)[number];
|
|
699
309
|
/**
|
|
700
|
-
* One pack in a case, as
|
|
701
|
-
*
|
|
702
|
-
* `
|
|
703
|
-
*
|
|
704
|
-
* the party that assembled it, and two packs are free to claim one name.
|
|
705
|
-
*
|
|
706
|
-
* A caller passes packs as it received them. `readCase` runs
|
|
707
|
-
* `verifyEvidenceBundle` over each one itself, so `HeldRecord`'s precondition
|
|
708
|
-
* (every envelope it compares has verified) is met by this module and cannot
|
|
709
|
-
* be skipped by a caller. A pack that does not verify is
|
|
710
|
-
* `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.
|
|
711
314
|
*/
|
|
712
315
|
export interface CasePack {
|
|
713
316
|
ref: string;
|
|
714
317
|
bundle: unknown;
|
|
715
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;
|
|
716
321
|
}
|
|
717
|
-
/** One named exception, as data. A surface renders
|
|
718
|
-
* `renderException`. */
|
|
322
|
+
/** One named exception, as data. A surface renders it or calls `renderException`. */
|
|
719
323
|
export interface CaseException {
|
|
720
324
|
kind: CaseExceptionKind;
|
|
721
|
-
/**
|
|
722
|
-
* Which pack this is about, by the reader's own name for it. Two packs can
|
|
723
|
-
* carry one `ref`, so it is a label and never the join: `packIndex` is.
|
|
724
|
-
*/
|
|
325
|
+
/** The reader's name for the pack: a label, never the join (`packIndex` is). */
|
|
725
326
|
packRef?: string;
|
|
726
|
-
/**
|
|
727
|
-
* Which pack this is about, by its position in `CaseReading.packs` (0
|
|
728
|
-
* first), present wherever `packRef` is (A43). Unique in the reading.
|
|
729
|
-
*/
|
|
327
|
+
/** The pack's position in `CaseReading.packs`, wherever `packRef` is set. */
|
|
730
328
|
packIndex?: number;
|
|
731
329
|
/** Which record, by its envelope `event_id`. */
|
|
732
330
|
eventId?: string;
|
|
733
331
|
/**
|
|
734
|
-
*
|
|
735
|
-
*
|
|
736
|
-
*
|
|
737
|
-
* `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.
|
|
738
335
|
*/
|
|
739
336
|
recordIndex?: number;
|
|
740
|
-
/**
|
|
741
|
-
* The counterparty key the record named, for the two counterpart kinds.
|
|
742
|
-
* Normalized (`normalizedSigningKey`), so a reader compares what this module
|
|
743
|
-
* compared.
|
|
744
|
-
*/
|
|
337
|
+
/** The counterparty key the record named, normalized as this module compared it. */
|
|
745
338
|
counterpartyKey?: string | null;
|
|
746
|
-
/** 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. */
|
|
747
340
|
failedChecks?: string[];
|
|
748
341
|
/**
|
|
749
|
-
*
|
|
750
|
-
*
|
|
751
|
-
* (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.
|
|
752
344
|
*/
|
|
753
345
|
count?: number;
|
|
754
346
|
/** The pack's case grade, for `PACK_GRADE_NOT_VERIFIED`. */
|
|
755
347
|
status?: CaseVerdict;
|
|
756
348
|
/**
|
|
757
|
-
*
|
|
758
|
-
*
|
|
759
|
-
* not computed (an unreadable body, a body that is not one of the two
|
|
760
|
-
* 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.
|
|
761
351
|
*/
|
|
762
352
|
causes?: PackGradeCauseKind[];
|
|
763
353
|
/**
|
|
764
|
-
*
|
|
765
|
-
*
|
|
766
|
-
* 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.
|
|
767
356
|
*/
|
|
768
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[];
|
|
769
365
|
}
|
|
770
366
|
/**
|
|
771
|
-
* One record of one pack, with its status and, where
|
|
772
|
-
*
|
|
773
|
-
*
|
|
774
|
-
*
|
|
775
|
-
* in bundle order: the ones this reader read, including the ones that are not
|
|
776
|
-
* hand-off records at all (`findings` carries `not_a_handoff_record`), and the
|
|
777
|
-
* ones it did not, with `status` `not_read` and the `reason`. 4.1 (v1.9, A14)
|
|
778
|
-
* names why: the one thing an attacker wants is for a record to be absent from
|
|
779
|
-
* the output. An export's wrapped records are listed, `not_read`. A pack whose
|
|
780
|
-
* body carries no `events` array, and wraps none, lists none, and its own
|
|
781
|
-
* 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.
|
|
782
371
|
*/
|
|
783
372
|
export interface CaseRecordReading {
|
|
784
373
|
packRef: string;
|
|
785
|
-
/** The pack
|
|
374
|
+
/** The pack's position in `CaseReading.packs`. */
|
|
786
375
|
packIndex: number;
|
|
787
376
|
eventId: string;
|
|
788
377
|
/**
|
|
789
|
-
* The record
|
|
790
|
-
*
|
|
791
|
-
* source bundle it wraps.
|
|
378
|
+
* The record's position in its pack's events (for an export, its source
|
|
379
|
+
* bundle's events).
|
|
792
380
|
*/
|
|
793
381
|
recordIndex: number;
|
|
794
|
-
/** One of `CASE_RECORD_STATUSES` (A43). */
|
|
795
382
|
status: CaseRecordStatus;
|
|
796
|
-
/**
|
|
797
|
-
* For `not_read`, the kind of the exception that says why; `null` for a
|
|
798
|
-
* record that was read.
|
|
799
|
-
*/
|
|
383
|
+
/** For `not_read`, the exception kind that says why; else `null`. */
|
|
800
384
|
reason: CaseExceptionKind | null;
|
|
801
385
|
/**
|
|
802
|
-
* The
|
|
803
|
-
*
|
|
804
|
-
*
|
|
805
|
-
* `eventId`, so under an `event_id` the pack carries twice every record with
|
|
806
|
-
* that id carries it. A record that went into the pile with any is
|
|
807
|
-
* `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`.
|
|
808
389
|
*/
|
|
809
390
|
declarationFindings: string[];
|
|
810
|
-
/** 4.1's verdict, or `null` where
|
|
391
|
+
/** §4.1's verdict, or `null` where it gave none or the record was not read. */
|
|
811
392
|
verdict: string | null;
|
|
812
393
|
findings: string[];
|
|
813
394
|
failedChecks: string[];
|
|
814
395
|
/**
|
|
815
|
-
* 4.1's candidate counterparts
|
|
816
|
-
*
|
|
817
|
-
* 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.
|
|
818
398
|
*/
|
|
819
399
|
counterparts: string[];
|
|
820
400
|
/**
|
|
821
|
-
* The role the pack's v2 declaration signs for this record, `
|
|
822
|
-
*
|
|
823
|
-
* 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).
|
|
824
403
|
*/
|
|
825
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;
|
|
826
412
|
}
|
|
827
|
-
/**
|
|
828
|
-
* One NOTE on the reading (5.5.3 v1.20): something true a reader needs and
|
|
829
|
-
* nothing a reader could not tell, so it carries no contribution.
|
|
830
|
-
*/
|
|
413
|
+
/** A note on the reading (§5.5.3): true and needed, with no contribution. */
|
|
831
414
|
export interface CaseNote {
|
|
832
415
|
kind: CaseNoteKind;
|
|
833
|
-
/** Which pack, by the reader's own name for it. */
|
|
834
416
|
packRef: string;
|
|
835
|
-
/** Which pack, by its position in `CaseReading.packs` (A43). */
|
|
836
417
|
packIndex: number;
|
|
837
|
-
/**
|
|
838
|
-
* For `CONTENT_WITHHELD_BY_DECLARATION`, how many of the pack's records its
|
|
839
|
-
* declaration withholds.
|
|
840
|
-
*/
|
|
418
|
+
/** For `CONTENT_WITHHELD_BY_DECLARATION`, how many records are withheld. */
|
|
841
419
|
count?: number;
|
|
842
420
|
}
|
|
843
421
|
/**
|
|
844
|
-
* One pack as
|
|
845
|
-
*
|
|
846
|
-
* 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.
|
|
847
424
|
*/
|
|
848
425
|
export interface CasePackReading {
|
|
849
|
-
/**
|
|
850
|
-
* The pack's position in the order the reader was given the packs, 0 first
|
|
851
|
-
* (A43): the one name for a pack that is unique in the reading. Every
|
|
852
|
-
* exception, note and record names its pack by it as `packIndex`.
|
|
853
|
-
*/
|
|
426
|
+
/** The pack's position in the order given: its one unique name in the reading. */
|
|
854
427
|
index: number;
|
|
855
|
-
/** The reader's own name for the pack.
|
|
428
|
+
/** The reader's own name for the pack. Not unique. */
|
|
856
429
|
ref: string;
|
|
857
430
|
/** The wrapper key, normalized, or `null` where this reader could not read it. */
|
|
858
431
|
signingKey: string | null;
|
|
859
|
-
/**
|
|
860
|
-
* The case grade (5.5.1 step 1), or `null` where the wrapper did not hold or
|
|
861
|
-
* the key could not be read.
|
|
862
|
-
*/
|
|
432
|
+
/** The case grade (§5.5.1), or `null` where the wrapper did not hold or the key is unreadable. */
|
|
863
433
|
grade: PackVerdict | null;
|
|
864
|
-
/**
|
|
865
|
-
* Records withheld by the pack's declaration (5.4.5): in scope for their
|
|
866
|
-
* signature and commitment only. Never counted as verified records.
|
|
867
|
-
*/
|
|
434
|
+
/** Records withheld by the declaration (§5.4.5). Never counted as verified. */
|
|
868
435
|
recordsWithheld: number;
|
|
869
|
-
/**
|
|
870
|
-
* `sanning.declaration/v1`, `sanning.declaration/v2`, or `null` where the
|
|
871
|
-
* pack carries no declaration, one this reader does not know, or a body this
|
|
872
|
-
* reader does not read.
|
|
873
|
-
*/
|
|
436
|
+
/** The declaration version, or `null` where absent, unknown or in an unread body. */
|
|
874
437
|
declarationVersion: string | null;
|
|
875
438
|
}
|
|
876
439
|
export interface CaseReading {
|
|
877
440
|
verdict: CaseVerdict;
|
|
441
|
+
/** `changed` or `nonconforming` where `verdict` is `failed`. */
|
|
442
|
+
reasonKind?: ReasonKind;
|
|
878
443
|
/**
|
|
879
|
-
* Every
|
|
880
|
-
* order
|
|
881
|
-
* order and bundle order.
|
|
882
|
-
*
|
|
883
|
-
* **An empty array is the only shape a reader may read as clean**, and it is
|
|
884
|
-
* 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`.
|
|
885
446
|
*/
|
|
886
|
-
|
|
447
|
+
problems: Problem[];
|
|
887
448
|
/**
|
|
888
|
-
*
|
|
889
|
-
* 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"`.
|
|
890
452
|
*/
|
|
453
|
+
exceptions: CaseException[];
|
|
454
|
+
/** One entry per record of every pack, read or not. */
|
|
891
455
|
records: CaseRecordReading[];
|
|
892
456
|
/**
|
|
893
|
-
* Every `[contributor, verdict]` the
|
|
894
|
-
*
|
|
895
|
-
* 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.
|
|
896
459
|
*/
|
|
897
460
|
contributions: [string, CaseVerdict][];
|
|
898
|
-
/**
|
|
461
|
+
/** Hand-off records in the case. Zero is its own exception. */
|
|
899
462
|
handoffRecords: number;
|
|
900
463
|
/**
|
|
901
|
-
* Whether any witness
|
|
902
|
-
*
|
|
903
|
-
*
|
|
904
|
-
*
|
|
905
|
-
*
|
|
906
|
-
* is ABSENT, so the honest omission is named and the unverifiable assertion
|
|
907
|
-
* is not: a holder that writes any `anchor_ref` at all reads `verified`,
|
|
908
|
-
* because this reader makes no network call. That is the standing lens
|
|
909
|
-
* inverted, and the answer is not to refuse the assertion, which no offline
|
|
910
|
-
* reader can grade. It is to say what was not checked, so nobody reads a
|
|
911
|
-
* clean case as "a witness held". Re-fetching on chain stays the caller's
|
|
912
|
-
* job, exactly as `evidence-bundle.md` 5.5's does-not-claim list says.
|
|
913
|
-
*
|
|
914
|
-
* Derived from each pack's own `EvidenceBundleResult.onChainChecked` rather
|
|
915
|
-
* than written as a constant, so it stays true of what was actually run:
|
|
916
|
-
* this reader passes no gateways, and it is the ALL of an empty list of
|
|
917
|
-
* 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.
|
|
918
469
|
*/
|
|
919
470
|
onChainChecked: boolean;
|
|
920
|
-
/**
|
|
471
|
+
/** Notes, in pack order (§5.5.3). No contribution. */
|
|
921
472
|
notes: CaseNote[];
|
|
922
|
-
/** One reading per pack, in the order
|
|
473
|
+
/** One reading per pack, in the order given. */
|
|
923
474
|
packs: CasePackReading[];
|
|
924
475
|
}
|
|
925
476
|
/**
|
|
926
|
-
*
|
|
927
|
-
*
|
|
928
|
-
|
|
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.
|
|
929
483
|
*
|
|
930
|
-
* 1.
|
|
931
|
-
*
|
|
932
|
-
*
|
|
933
|
-
*
|
|
934
|
-
*
|
|
935
|
-
*
|
|
936
|
-
*
|
|
937
|
-
* 3. **Every record every pack supplied goes into ONE pile**, with no partition
|
|
938
|
-
* by pack, by issuer or by organization, and the pile is read by
|
|
939
|
-
* `readHandoffs`, which is the one implementation of 4.1. This is where
|
|
940
|
-
* matching happens, and it is on keys and hashes alone.
|
|
941
|
-
* 4. **Each reading becomes an exception or a clean contribution**, and the two
|
|
942
|
-
* counterpart kinds are separated by asking whether a pack SIGNED by the
|
|
943
|
-
* counterparty's key is in the case, a key read from every pack's wrapper
|
|
944
|
-
* 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.
|
|
945
491
|
*
|
|
946
|
-
*
|
|
947
|
-
*
|
|
948
|
-
*
|
|
949
|
-
* `incomplete`: the reader genuinely cannot tell whether the record it cannot
|
|
950
|
-
* 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).
|
|
951
495
|
*/
|
|
952
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
|
+
*/
|
|
953
501
|
export declare function renderException(exception: CaseException): string;
|
|
954
|
-
/** The house wording for one
|
|
502
|
+
/** The house wording for one note. */
|
|
955
503
|
export declare function renderCaseNote(note: CaseNote): string;
|
|
956
504
|
/**
|
|
957
|
-
* The scope sentence
|
|
958
|
-
*
|
|
959
|
-
*
|
|
960
|
-
*
|
|
961
|
-
*
|
|
962
|
-
* exceptions; and that the reading was made offline. Where any pack holds
|
|
963
|
-
* records withheld by its declaration, their total; where any pack is noted
|
|
964
|
-
* `pack_undeclared`, how many. Those two lines are part of what the headline
|
|
965
|
-
* MEANS, and a surface MUST print them with it.
|
|
966
|
-
*
|
|
967
|
-
* What was not checked on the public record is no longer a clause here. It is
|
|
968
|
-
* 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.
|
|
969
510
|
*/
|
|
970
511
|
export declare function renderCaseSummary(reading: CaseReading): string;
|
|
971
512
|
/**
|
|
972
|
-
* The one display title of each of the
|
|
973
|
-
* title, never the word, and never a title of its own
|
|
974
|
-
* is Will's to change through the glossary (DL-71); what each MEANS is pinned
|
|
975
|
-
* 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.
|
|
976
515
|
*/
|
|
977
516
|
export declare const VERDICT_DISPLAY_TITLES: Readonly<Record<string, string>>;
|
|
978
517
|
/**
|
|
979
|
-
* What a reader may rely on, for each
|
|
980
|
-
*
|
|
981
|
-
*
|
|
982
|
-
* witness states. `verified` is the base sentence, printed alone where the
|
|
983
|
-
* drop holds no hand-off record; a caller reads `caseReliance` for
|
|
984
|
-
* `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.
|
|
985
521
|
*/
|
|
986
|
-
export declare const CASE_RELIANCE: Readonly<Record<CaseVerdict, string>>;
|
|
522
|
+
export declare const CASE_RELIANCE: Readonly<Record<CaseVerdict | "failed_nonconforming", string>>;
|
|
987
523
|
/**
|
|
988
|
-
*
|
|
989
|
-
*
|
|
990
|
-
* and never where `handoffRecords` is zero: most drops hold one agent's
|
|
991
|
-
* 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.
|
|
992
526
|
*/
|
|
993
527
|
export declare const CASE_RELIANCE_HANDOFF_CLAUSE = "Every hand-off with both sides in this drop is intact.";
|
|
994
528
|
/**
|
|
995
|
-
*
|
|
996
|
-
*
|
|
997
|
-
* marker (`environmentMarker`): `dev` where every envelope is signed dev,
|
|
998
|
-
* `mixed` where only some are. Inserted after the line's first sentence, for
|
|
999
|
-
* every verdict word. A drop with no `dev` envelope has no marker and gains
|
|
1000
|
-
* nothing.
|
|
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.
|
|
1001
531
|
*/
|
|
1002
532
|
export declare const CASE_RELIANCE_SANDBOX: Readonly<Record<EnvironmentMarker, string>>;
|
|
1003
533
|
/**
|
|
1004
|
-
* What a reader may rely on for one case reading (5.5.6
|
|
1005
|
-
*
|
|
1006
|
-
*
|
|
1007
|
-
*
|
|
1008
|
-
* `verified`, the hand-off clause is inserted after the first sentence
|
|
1009
|
-
* where `handoffRecords` is not zero, and left out where it is zero: the
|
|
1010
|
-
* base sentence never claims a hand-off the drop does not hold.
|
|
1011
|
-
*
|
|
1012
|
-
* Where `environmentMarker` is `dev` or `mixed`, the `CASE_RELIANCE_SANDBOX`
|
|
1013
|
-
* sentence for it is inserted after the first sentence, for every word, so
|
|
1014
|
-
* it directly follows the claim it qualifies (and precedes the hand-off
|
|
1015
|
-
* clause). Where it is null or absent, the text is exactly what it was
|
|
1016
|
-
* before A48.
|
|
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.
|
|
1017
538
|
*/
|
|
1018
|
-
export declare function caseReliance(verdict: CaseVerdict, handoffRecords: number, environmentMarker?: EnvironmentMarker | null): string;
|
|
1019
|
-
/** 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. */
|
|
1020
541
|
export declare const WITNESS_STATES: {
|
|
1021
542
|
readonly confirmed: "Confirmed on the public record";
|
|
1022
543
|
readonly not_checked: "Not checked";
|
|
@@ -1024,34 +545,30 @@ export declare const WITNESS_STATES: {
|
|
|
1024
545
|
};
|
|
1025
546
|
export type WitnessState = keyof typeof WITNESS_STATES;
|
|
1026
547
|
/**
|
|
1027
|
-
* The
|
|
1028
|
-
*
|
|
1029
|
-
*
|
|
1030
|
-
* settle, in a fixed order; `services` names each service that answered, as
|
|
1031
|
-
* 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.
|
|
1032
551
|
*/
|
|
1033
552
|
export interface WitnessLine {
|
|
1034
553
|
state: WitnessState;
|
|
1035
554
|
reasons: string[];
|
|
1036
555
|
services: string[];
|
|
1037
556
|
/**
|
|
1038
|
-
*
|
|
1039
|
-
*
|
|
1040
|
-
*
|
|
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.
|
|
1041
560
|
*/
|
|
1042
561
|
cached?: [number, number][];
|
|
1043
562
|
/**
|
|
1044
|
-
* Witness times the public record returned
|
|
1045
|
-
*
|
|
1046
|
-
* 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.
|
|
1047
565
|
*/
|
|
1048
566
|
recorded?: [number, number][];
|
|
1049
567
|
}
|
|
1050
|
-
/** The line
|
|
568
|
+
/** The line where no lookup ran: every reading this module produces on its own. */
|
|
1051
569
|
export declare const WITNESS_NOT_LOOKED_UP: Readonly<WitnessLine>;
|
|
1052
|
-
/**
|
|
1053
|
-
/** 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). */
|
|
1054
571
|
export declare const WITNESS_TIME_CACHED = "the pack dates the witness, not checked";
|
|
1055
|
-
/**
|
|
572
|
+
/** A witness time the public record returned that matched the cache. */
|
|
1056
573
|
export declare const WITNESS_TIME_RECORDED = "the public record dates the witness";
|
|
1057
574
|
export declare function renderWitnessLine(line: WitnessLine): string;
|