@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/vectors/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# `vectors
|
|
1
|
+
# `vectors/`: conformance tables that ship to consumers
|
|
2
2
|
|
|
3
|
-
Unlike [`../../test-vectors/`](../../test-vectors/)
|
|
4
|
-
for the kernel primitives
|
|
3
|
+
Unlike [`../../test-vectors/`](../../test-vectors/), the tagged, vendored corpus
|
|
4
|
+
for the kernel primitives, everything here is **inside the published package**
|
|
5
5
|
(`files: ["vectors", …]`) and reaches downstream surfaces through npm.
|
|
6
6
|
|
|
7
7
|
That distinction is the whole point. A rule that consumers must agree with needs
|
|
@@ -11,26 +11,26 @@ correctly.
|
|
|
11
11
|
## `stamp-on-chain.json`
|
|
12
12
|
|
|
13
13
|
The rule that decides what re-fetching a **stamp's witness** from a gateway does
|
|
14
|
-
and does not settle
|
|
14
|
+
and does not settle: the optional, online half of `sanning.stamp.trace/v1` and
|
|
15
15
|
`sanning.stamp.evidence/v2` (`evidence-bundle.md` §5.2.4 / §5.3.4). Implemented
|
|
16
16
|
by [`../src/evidence.ts`](../src/evidence.ts) and asserted against this table by
|
|
17
|
-
[`../test/stamp-on-chain-vectors.test.ts`](../test/stamp-on-chain-vectors.test.ts)
|
|
18
|
-
|
|
17
|
+
[`../test/stamp-on-chain-vectors.test.ts`](../test/stamp-on-chain-vectors.test.ts),
|
|
18
|
+
**and by the Python kernel against the same bytes**, in
|
|
19
19
|
`tests/test_stamp_on_chain_vectors.py`, so neither kernel can pass by agreeing
|
|
20
20
|
with the other.
|
|
21
21
|
|
|
22
22
|
**The one thing a consumer must not do with it: collapse the four states into a
|
|
23
23
|
boolean.** `not checked` · `confirm` · `mismatch` · `unreachable`. A reader that
|
|
24
24
|
cannot tell the first from the last will report that no gateway could be reached
|
|
25
|
-
on a run that contacted none
|
|
26
|
-
state
|
|
25
|
+
on a run that contacted none: a false accusation manufactured by a missing
|
|
26
|
+
state. Vendoring rules are the same
|
|
27
27
|
three steps as below, against `vectors/stamp-on-chain.json`.
|
|
28
28
|
|
|
29
29
|
## `witness-cache.json`
|
|
30
30
|
|
|
31
31
|
The rule that decides what a reader does with the witnessed-time cache, the
|
|
32
32
|
unsigned `witness-cache.json` beside a pack's `bundle.json` (`evidence-bundle.md`
|
|
33
|
-
§5.5.6 and §5.6.6
|
|
33
|
+
§5.5.6 and §5.6.6). Implemented by [`../src/witness-cache.ts`](../src/witness-cache.ts)
|
|
34
34
|
and the `case` command in [`../src/cli.ts`](../src/cli.ts), and asserted against
|
|
35
35
|
this table by
|
|
36
36
|
[`../test/witness-cache-vectors.test.ts`](../test/witness-cache-vectors.test.ts)
|
|
@@ -49,13 +49,12 @@ lookup settled stays labelled not checked.
|
|
|
49
49
|
The rule that decides how a kernel reads bytes that claim to be `JCS(value)`
|
|
50
50
|
(RFC 8785). Five checks, none of them left to a built-in decoder's defaults:
|
|
51
51
|
**strict UTF-8**, **no leading byte-order mark**, **no non-finite literal**,
|
|
52
|
-
**no object that names one member twice** (I-JSON, RFC 7493
|
|
53
|
-
proof#144), and **no unpaired surrogate in the parsed value**. A duplicate is
|
|
52
|
+
**no object that names one member twice** (I-JSON, RFC 7493), and **no unpaired surrogate in the parsed value**. A duplicate is
|
|
54
53
|
refused with the same message in both kernels, `duplicate key "<name>"`, and a
|
|
55
54
|
case that carries `error` pins that exact string. The fourth is not the first one
|
|
56
55
|
twice: a surrogate written as the ASCII escape `\ud800` survives every
|
|
57
56
|
byte-level check, because the bytes are ASCII, and the parser produces the
|
|
58
|
-
malformed code unit afterwards
|
|
57
|
+
malformed code unit afterwards.
|
|
59
58
|
Implemented by [`../src/verifier.ts`](../src/verifier.ts) as `jcsParse` and by
|
|
60
59
|
`src/sanning_proof/canonicalize.py` as `jcs_loads`, and asserted against this
|
|
61
60
|
table by [`../test/host-wording.test.ts`](../test/host-wording.test.ts) **and by
|
|
@@ -68,7 +67,7 @@ BOM. Python's `json.loads(<bytes>)` is not `bytes.decode("utf-8")` then
|
|
|
68
67
|
`json.loads`: CPython sniffs the encoding and decodes with
|
|
69
68
|
`errors="surrogatepass"`, so it strips a BOM too, accepts a UTF-16 or UTF-32
|
|
70
69
|
body, and passes a lone surrogate and a CESU-8 pair through. Both defaults have
|
|
71
|
-
shipped a split verdict on one pack that verifies
|
|
70
|
+
shipped a split verdict on one pack that verifies.
|
|
72
71
|
|
|
73
72
|
**The accepted cases matter as much as the rejected ones.** An honest body
|
|
74
73
|
carrying astral characters, a noncharacter, a U+FEFF *inside a string value* or
|
|
@@ -84,8 +83,8 @@ been tested.
|
|
|
84
83
|
|
|
85
84
|
## `pack-grading.json`
|
|
86
85
|
|
|
87
|
-
The rule that decides whether a **pack
|
|
88
|
-
disclosed bytes travelled beside it
|
|
86
|
+
The rule that decides whether a **pack**, a signed bundle plus whatever
|
|
87
|
+
disclosed bytes travelled beside it, is `verified`, `failed` or `incomplete`.
|
|
89
88
|
Implemented by [`../src/grading.ts`](../src/grading.ts) and asserted against this
|
|
90
89
|
table by [`../test/grading.test.ts`](../test/grading.test.ts).
|
|
91
90
|
|
|
@@ -110,30 +109,30 @@ One implementation, no table to keep in step, no drift to guard against.
|
|
|
110
109
|
An older pinned kernel, another language, a surface that adapts a result from
|
|
111
110
|
somewhere else. Then, and only then:
|
|
112
111
|
|
|
113
|
-
1. **Vendor this file byte-for-byte.** Not "equivalent"
|
|
112
|
+
1. **Vendor this file byte-for-byte.** Not "equivalent": identical. A vendored
|
|
114
113
|
copy that is not byte-identical to this one is a defect, not a variant.
|
|
115
114
|
2. **Assert your derivation against it** in your own suite, so an implementation
|
|
116
115
|
that drifts from the rule goes red in your repo.
|
|
117
116
|
3. **Run a drift check in CI** that compares your copy against the copy in
|
|
118
117
|
`node_modules/@sanning/proof/vectors/pack-grading.json` and fails on any
|
|
119
|
-
difference
|
|
118
|
+
difference, *and fails when it cannot find a copy to compare against.* A
|
|
120
119
|
drift check that skips when its source is missing is not a check.
|
|
121
120
|
|
|
122
121
|
Step 3 is the one people skip, and it is the one that matters. Steps 1 and 2
|
|
123
122
|
catch an implementation drifting from its own table. Only step 3 catches the
|
|
124
|
-
table itself being edited on one side
|
|
125
|
-
|
|
123
|
+
table itself being edited on one side, and that is why this file ships in the
|
|
124
|
+
package.
|
|
126
125
|
|
|
127
126
|
### Shape
|
|
128
127
|
|
|
129
128
|
| Key | Meaning |
|
|
130
129
|
|---|---|
|
|
131
130
|
| `ruleVersion` | Bumped when a case's expectation changes **or a case is added**. An implementation asserts the version it was written against, so a table it does not understand fails loudly rather than passing vacuously. Currently **6**: `evidence-bundle.md` §5.4.5, where a record withheld by a readable declaration is counted apart and holds the pack at nothing. |
|
|
132
|
-
| `kernelEventClasses` | The six per-event outcome classes a verification result can carry, named so a case can be written as counts rather than as a hand-built bundle.
|
|
131
|
+
| `kernelEventClasses` | The six per-event outcome classes a verification result can carry, named so a case can be written as counts rather than as a hand-built bundle. Two of them, `withheldBound` and `withheldUnbound`, carry an `eventId` and a `payloadBindingOk`; `howToUse` says how an adapter builds them. |
|
|
133
132
|
| `cases[].kernel` | The verification result to grade, as class counts. |
|
|
134
133
|
| `cases[].logs` | The disclosure account: how many records the bundle presents, and how many disclosed usable bytes. |
|
|
135
|
-
| `cases[].omissions` | Completeness notes
|
|
136
|
-
| `cases[].expect` | The verdict, the three counts, how many causes the grade must carry, and
|
|
134
|
+
| `cases[].omissions` | Completeness notes: a checkpoint's signed `leaf_count` against the records the pack presents for it. |
|
|
135
|
+
| `cases[].expect` | The verdict, the three counts, how many causes the grade must carry, and `recordsWithheld` where a case pins it. |
|
|
137
136
|
|
|
138
137
|
Nothing in a case names a transport. A directory read and a browser drop produce
|
|
139
138
|
the same account and must produce the same verdict; a table that encoded one
|
|
@@ -142,7 +141,7 @@ surface's mechanism would let the other one drift while staying green.
|
|
|
142
141
|
## `case-file-index.json`
|
|
143
142
|
|
|
144
143
|
How a reader compares a case file's index, `contents.json`, with the folder it
|
|
145
|
-
sits at the root of (`evidence-bundle.md` §5.6.3
|
|
144
|
+
sits at the root of (`evidence-bundle.md` §5.6.3). One pure function
|
|
146
145
|
in both kernels, `readCaseFileIndex` in [`../src/case-file.ts`](../src/case-file.ts)
|
|
147
146
|
and `read_case_file_index` in `src/sanning_proof/case_file.py`, asserted against
|
|
148
147
|
this table by [`../test/case-file-index.test.ts`](../test/case-file-index.test.ts)
|
|
@@ -159,7 +158,7 @@ literals.
|
|
|
159
158
|
## `file-match.json`
|
|
160
159
|
|
|
161
160
|
How a reader matches files handed in beside a pack against the commitments its
|
|
162
|
-
signed records make (`evidence-bundle.md` §5.7
|
|
161
|
+
signed records make (`evidence-bundle.md` §5.7). One pure
|
|
163
162
|
reading in both kernels, `matchFiles` and `matchCaseFiles` in
|
|
164
163
|
[`../src/file-match.ts`](../src/file-match.ts) and `match_files` and
|
|
165
164
|
`match_case_files` in `src/sanning_proof/file_match.py`, asserted against this
|
|
@@ -173,8 +172,8 @@ matched by its SHA-256 and by nothing else**, and **no match moves a verdict**:
|
|
|
173
172
|
a surface that matched by name, or took a hash from a field no record's key
|
|
174
173
|
signed, would vouch for a file the pack never committed to. Written by
|
|
175
174
|
`tools/gen-vectors/gen_file_match_vectors.py`, whose expectations are written
|
|
176
|
-
by hand from what it built.
|
|
177
|
-
|
|
175
|
+
by hand from what it built. Every commitment and every `not_read` entry
|
|
176
|
+
carries `pack_index` and `record_index`: the pack's
|
|
178
177
|
position among the row's packs in `mode: case` (`null` in `mode: pack`) and
|
|
179
178
|
the record's position among the events the pack presents, both read off the
|
|
180
179
|
packs the row names.
|
|
@@ -182,8 +181,7 @@ packs the row names.
|
|
|
182
181
|
## `case-split.json`
|
|
183
182
|
|
|
184
183
|
How `case` turns the folders it was handed into packs: the verify page's
|
|
185
|
-
splitting rule (`
|
|
186
|
-
`src/lib/pack.ts` `assemble`) over a walk whose rules are the command's own,
|
|
184
|
+
splitting rule (`splitCase`) over a walk whose rules are the command's own,
|
|
187
185
|
restated in [`../src/cli.ts`](../src/cli.ts) and `src/sanning_proof/cli.py`
|
|
188
186
|
because the page's code lives in the page. Two tables and the limits:
|
|
189
187
|
|
|
@@ -192,7 +190,7 @@ because the page's code lives in the page. Two tables and the limits:
|
|
|
192
190
|
the packs, the outside paths and the paths that are not regular files, or
|
|
193
191
|
the refusal. The rows include the decision file unpacked, a symbolic link
|
|
194
192
|
under `logs/`, each side of the depth and entry limits, names that are not
|
|
195
|
-
UTF-8, and
|
|
193
|
+
UTF-8, and a case file unpacked and as a `.zip` argument, with
|
|
196
194
|
the entries a reader lists and never reads and the archives it refuses.
|
|
197
195
|
- `parses`: how `bundle.json` bytes become JSON through the reader `verify`
|
|
198
196
|
and `case` share, including each side of the nesting limit.
|
|
@@ -205,8 +203,7 @@ run through both commands by `cross-kernel/run_case_cli.sh`.
|
|
|
205
203
|
|
|
206
204
|
Every expectation is a literal written in
|
|
207
205
|
`tools/gen-vectors/gen_case_split_vectors.py`, not the output of either
|
|
208
|
-
kernel. The splitting rows
|
|
209
|
-
table was first written. The walk rows (links, depth, entry count, names, a
|
|
206
|
+
kernel. The splitting rows match the page's own splitting. The walk rows (links, depth, entry count, names, a
|
|
210
207
|
`.zip` argument) and the reader rows are the command's own rules, and the page
|
|
211
208
|
does not share them: it opens a dropped `.zip`, drops a leading byte-order
|
|
212
209
|
mark, and reads whatever the browser hands it for a link, a bad name or a deep
|
|
@@ -248,6 +245,27 @@ TypeScript verdict line and the Python `Gateways` line exactly.
|
|
|
248
245
|
Two more members: `stoppedEarly` holds packs whose verification stops before
|
|
249
246
|
any witness is read, each of which must print and write the same with
|
|
250
247
|
`--gateways`, reachable or not, as offline (the Python `Gateways` line names
|
|
251
|
-
the gateways passed); `
|
|
252
|
-
|
|
253
|
-
|
|
248
|
+
the gateways passed); `retiredAgentProof` holds a `sanning.agent.proof/v1` proof signed `dev`, which
|
|
249
|
+
both `verify` commands read malformed, exit 2, and never as sandbox evidence: no
|
|
250
|
+
kernel reads that retired format.
|
|
251
|
+
|
|
252
|
+
## `agent-record.json`
|
|
253
|
+
|
|
254
|
+
How a kernel reads one `agent.*` record on its own: steps 1 to 6 of
|
|
255
|
+
`agent-events.md` §10, in the `sanning-io/specs` release pinned in
|
|
256
|
+
[`../../vendor/specs/`](../../vendor/specs/). Implemented by `readAgentRecord`
|
|
257
|
+
in [`../src/agent-record.ts`](../src/agent-record.ts), against the schemas
|
|
258
|
+
bundled in [`../src/agent-schemas.generated.ts`](../src/agent-schemas.generated.ts),
|
|
259
|
+
and asserted against this table by
|
|
260
|
+
[`../test/agent-record.test.ts`](../test/agent-record.test.ts). The pinned
|
|
261
|
+
release's own cases are asserted by
|
|
262
|
+
[`../test/agent-conformance.test.ts`](../test/agent-conformance.test.ts). Every
|
|
263
|
+
expectation is written by hand in
|
|
264
|
+
`tools/gen-vectors/gen_agent_record_table.py`, which writes this file. The
|
|
265
|
+
Python kernel does not read `agent.*` records yet, so only the TypeScript
|
|
266
|
+
kernel asserts this table today.
|
|
267
|
+
|
|
268
|
+
**The one thing a consumer must not do with it: read `partial` as a pass.** A
|
|
269
|
+
record whose `extras.event_schema` names a version the kernel does not know,
|
|
270
|
+
`sanning.agent/1.1` or `sanning.agent/2`, reads `partial`: the kernel holds no
|
|
271
|
+
schema to check it against. It is never `verified` and never `malformed`.
|