@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/environment.d.ts
CHANGED
|
@@ -1,42 +1,21 @@
|
|
|
1
1
|
import { type EvidenceBundleResult } from "./evidence.js";
|
|
2
2
|
/** `"dev"` when every envelope is signed `dev`, `"mixed"` when only some are. */
|
|
3
3
|
export type EnvironmentMarker = "dev" | "mixed";
|
|
4
|
-
/** The headline `verify` prints for sandbox evidence in place of `VERIFIED`. */
|
|
5
|
-
export declare const SANDBOX_HEADLINE = "SANDBOX";
|
|
6
|
-
/** The title `case` prints for sandbox evidence in place of `Verified` (case titles are title case). */
|
|
7
|
-
export declare const SANDBOX_TITLE = "Sandbox";
|
|
8
|
-
/** The one line printed with it, and with any other headline, wherever the marker is present. */
|
|
9
|
-
export declare const SANDBOX_LINE = "Sandbox evidence (environment dev): not production evidence";
|
|
10
4
|
/**
|
|
11
|
-
* The signed envelopes a pack holds:
|
|
12
|
-
* anchor-trace body,
|
|
13
|
-
*
|
|
14
|
-
* envelope. A stamp-trace body holds none. A value that is not an object is
|
|
15
|
-
* not an envelope and is not counted.
|
|
5
|
+
* The signed envelopes a pack holds: checkpoint and event envelopes of an
|
|
6
|
+
* anchor-trace body, event envelopes of a stamp-evidence body (also inside an
|
|
7
|
+
* export's inline source bundle). Non-objects are not counted.
|
|
16
8
|
*/
|
|
17
9
|
export declare function packEnvelopes(bundle: unknown): Record<string, unknown>[];
|
|
18
10
|
/**
|
|
19
|
-
* The
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* is, which is every production pack and every pack that holds no envelope.
|
|
11
|
+
* The marker over one or more packs: `"dev"` where every envelope is signed
|
|
12
|
+
* `environment: "dev"`, `"mixed"` where only some are, `null` where none is
|
|
13
|
+
* (including a pack that holds no envelope).
|
|
23
14
|
*/
|
|
24
15
|
export declare function environmentMarker(bundles: readonly unknown[]): EnvironmentMarker | null;
|
|
25
16
|
/**
|
|
26
|
-
* Whether a
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* one thing that keeps the bundle from `verified` is a simulated witness
|
|
30
|
-
* nobody can look up: no mismatch, no unreachable gateway, no witness of
|
|
31
|
-
* another kind, no checkpoint or stamp witnessed by nobody.
|
|
32
|
-
*/
|
|
33
|
-
export declare function onlySimulatedUnsettled(result: EvidenceBundleResult): boolean;
|
|
34
|
-
/**
|
|
35
|
-
* Whether a run with gateways counted only simulated witnesses, so nothing
|
|
36
|
-
* was looked up on a chain: gateways were passed, the run is not counted as
|
|
37
|
-
* checked on a chain, and it holds a simulated witness. A run that stopped
|
|
38
|
-
* before its witnesses were read (a bad wrapper signature or `body_hash`, an
|
|
39
|
-
* unknown `body_type`, an export whose source is not inline) holds none, so it
|
|
40
|
-
* is not one, and prints what it printed before simulated witnesses existed.
|
|
17
|
+
* Whether a run with gateways counted only simulated witnesses, so nothing was
|
|
18
|
+
* looked up on a chain. A run that stopped before reading its witnesses holds
|
|
19
|
+
* none and is not one.
|
|
41
20
|
*/
|
|
42
21
|
export declare function simulatedOnlyRun(result: EvidenceBundleResult, gateways: readonly string[]): boolean;
|
package/dist/environment.js
CHANGED
|
@@ -1,27 +1,13 @@
|
|
|
1
|
-
// The environment marker:
|
|
1
|
+
// The environment marker: whether a pack holds sandbox evidence.
|
|
2
2
|
//
|
|
3
|
-
// `environment` is an
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// The marker is read from the signed envelopes the pack holds, never from a
|
|
11
|
-
// wrapper field, a pack name or anything else the holder could write without a
|
|
12
|
-
// key. It never moves the verdict word: a sandbox pack that verifies is still
|
|
13
|
-
// `verified`, and the commands map that to the headline `SANDBOX` and exit 5
|
|
14
|
-
// (`sandboxExit` in `./exit-codes.ts`). The Python twin is
|
|
15
|
-
// `src/sanning_proof/environment.py`.
|
|
16
|
-
import { isAgentProofSpec } from "./agent-proof.js";
|
|
3
|
+
// `environment` is an optional field inside every envelope's signed scope,
|
|
4
|
+
// `"dev"` or `"production"` (envelope-spec section 2). It is read from the signed
|
|
5
|
+
// envelopes a pack holds, never from a wrapper field, a pack name or anything
|
|
6
|
+
// else the holder could write without a key. It is a label, never a claim or a
|
|
7
|
+
// verdict: a sandbox pack that verifies is still `verified`, prints the sandbox
|
|
8
|
+
// line, and exits 3 (`exitCodeFor`).
|
|
17
9
|
import { ANCHOR_TRACE_BODY_TYPE, EXPORT_BODY_TYPE, SIMULATED_WITNESS_KIND, STAMP_EVIDENCE_BODY_TYPE, } from "./evidence.js";
|
|
18
|
-
|
|
19
|
-
export const SANDBOX_HEADLINE = "SANDBOX";
|
|
20
|
-
/** The title `case` prints for sandbox evidence in place of `Verified` (case titles are title case). */
|
|
21
|
-
export const SANDBOX_TITLE = "Sandbox";
|
|
22
|
-
/** The one line printed with it, and with any other headline, wherever the marker is present. */
|
|
23
|
-
export const SANDBOX_LINE = "Sandbox evidence (environment dev): not production evidence";
|
|
24
|
-
// The same bound `resolveTraceEvents` puts on unwrapping export wrappers.
|
|
10
|
+
// Same bound as `resolveTraceEvents` puts on unwrapping export wrappers.
|
|
25
11
|
const MAX_EXPORT_UNWRAP = 4;
|
|
26
12
|
function isObject(v) {
|
|
27
13
|
return v !== null && typeof v === "object" && !Array.isArray(v);
|
|
@@ -41,20 +27,12 @@ function entryEnvelopes(list, out) {
|
|
|
41
27
|
}
|
|
42
28
|
}
|
|
43
29
|
/**
|
|
44
|
-
* The signed envelopes a pack holds:
|
|
45
|
-
* anchor-trace body,
|
|
46
|
-
*
|
|
47
|
-
* envelope. A stamp-trace body holds none. A value that is not an object is
|
|
48
|
-
* not an envelope and is not counted.
|
|
30
|
+
* The signed envelopes a pack holds: checkpoint and event envelopes of an
|
|
31
|
+
* anchor-trace body, event envelopes of a stamp-evidence body (also inside an
|
|
32
|
+
* export's inline source bundle). Non-objects are not counted.
|
|
49
33
|
*/
|
|
50
34
|
export function packEnvelopes(bundle) {
|
|
51
35
|
const out = [];
|
|
52
|
-
if (isObject(bundle) && isAgentProofSpec(own(bundle, "spec_version"))) {
|
|
53
|
-
const env = own(bundle, "checkpoint_envelope");
|
|
54
|
-
if (isObject(env))
|
|
55
|
-
out.push(env);
|
|
56
|
-
return out;
|
|
57
|
-
}
|
|
58
36
|
let cur = bundle;
|
|
59
37
|
for (let depth = 0; depth < MAX_EXPORT_UNWRAP; depth++) {
|
|
60
38
|
if (!isObject(cur))
|
|
@@ -79,10 +57,9 @@ export function packEnvelopes(bundle) {
|
|
|
79
57
|
return out;
|
|
80
58
|
}
|
|
81
59
|
/**
|
|
82
|
-
* The
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
* is, which is every production pack and every pack that holds no envelope.
|
|
60
|
+
* The marker over one or more packs: `"dev"` where every envelope is signed
|
|
61
|
+
* `environment: "dev"`, `"mixed"` where only some are, `null` where none is
|
|
62
|
+
* (including a pack that holds no envelope).
|
|
86
63
|
*/
|
|
87
64
|
export function environmentMarker(bundles) {
|
|
88
65
|
let total = 0;
|
|
@@ -99,35 +76,9 @@ export function environmentMarker(bundles) {
|
|
|
99
76
|
return dev === total ? "dev" : "mixed";
|
|
100
77
|
}
|
|
101
78
|
/**
|
|
102
|
-
* Whether a
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* one thing that keeps the bundle from `verified` is a simulated witness
|
|
106
|
-
* nobody can look up: no mismatch, no unreachable gateway, no witness of
|
|
107
|
-
* another kind, no checkpoint or stamp witnessed by nobody.
|
|
108
|
-
*/
|
|
109
|
-
export function onlySimulatedUnsettled(result) {
|
|
110
|
-
const witnesses = [...result.checkpoints, ...(result.stamps ?? [])];
|
|
111
|
-
if (witnesses.length === 0 || result.events.length === 0)
|
|
112
|
-
return false;
|
|
113
|
-
let simulated = 0;
|
|
114
|
-
for (const w of witnesses) {
|
|
115
|
-
if (w.anchorRef === null)
|
|
116
|
-
return false;
|
|
117
|
-
if (w.anchorRef.kind === SIMULATED_WITNESS_KIND)
|
|
118
|
-
simulated++;
|
|
119
|
-
else if (w.onChain?.rollup !== "confirm")
|
|
120
|
-
return false;
|
|
121
|
-
}
|
|
122
|
-
return simulated > 0;
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Whether a run with gateways counted only simulated witnesses, so nothing
|
|
126
|
-
* was looked up on a chain: gateways were passed, the run is not counted as
|
|
127
|
-
* checked on a chain, and it holds a simulated witness. A run that stopped
|
|
128
|
-
* before its witnesses were read (a bad wrapper signature or `body_hash`, an
|
|
129
|
-
* unknown `body_type`, an export whose source is not inline) holds none, so it
|
|
130
|
-
* is not one, and prints what it printed before simulated witnesses existed.
|
|
79
|
+
* Whether a run with gateways counted only simulated witnesses, so nothing was
|
|
80
|
+
* looked up on a chain. A run that stopped before reading its witnesses holds
|
|
81
|
+
* none and is not one.
|
|
131
82
|
*/
|
|
132
83
|
export function simulatedOnlyRun(result, gateways) {
|
|
133
84
|
if (gateways.length === 0 || result.onChainChecked)
|
package/dist/evidence.d.ts
CHANGED
|
@@ -1,40 +1,26 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
1
|
+
import { type AgentRecordReading } from "./agent-record.js";
|
|
2
|
+
import type { Envelope, EnvelopeFault } from "./types.js";
|
|
3
|
+
/** The accepted evidence-bundle wrapper majors. */
|
|
3
4
|
export declare const ACCEPTED_EVIDENCE_MAJORS: readonly string[];
|
|
4
5
|
export declare const ANCHOR_TRACE_BODY_TYPE = "sanning.anchor.trace/v3";
|
|
5
6
|
/**
|
|
6
|
-
* The name `event_bytes` replaced.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* checked, the fail-open the new majors exist to prevent (governance.md §8,
|
|
10
|
-
* W-3).
|
|
7
|
+
* The field name `event_bytes` replaced. A body entry still carrying it is a
|
|
8
|
+
* hard reject: ignored, it would read as a withheld record and verify with
|
|
9
|
+
* nothing checked.
|
|
11
10
|
*/
|
|
12
11
|
export declare const LEGACY_EVENT_BYTES_FIELD = "record_bytes";
|
|
13
12
|
export declare const EXPORT_BODY_TYPE = "sanning.evidence.export/v2";
|
|
14
13
|
/**
|
|
15
|
-
* The Sanning-signed interval stamp body (evidence-bundle.md §5.2
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* is the whole decision: an anchor-trace checkpoint carries a PRODUCER-signed
|
|
19
|
-
* `sanning.events/v2` envelope, and a stamp has no producer signature at all:
|
|
20
|
-
* Sanning places it, under DL-52, for a customer who holds no chain identity.
|
|
21
|
-
* The two rejected options were making `envelope` optional and synthesising an
|
|
22
|
-
* envelope that Sanning signs; the second would have made a Sanning
|
|
23
|
-
* attestation indistinguishable ON THE WIRE from a producer's, which is
|
|
24
|
-
* unrecoverable once witnessed.
|
|
14
|
+
* The Sanning-signed interval stamp body (evidence-bundle.md §5.2). Its own
|
|
15
|
+
* body type, because a stamp has no producer signature: a Sanning attestation
|
|
16
|
+
* must never be indistinguishable on the wire from a producer's.
|
|
25
17
|
*/
|
|
26
18
|
export declare const STAMP_TRACE_BODY_TYPE = "sanning.stamp.trace/v1";
|
|
27
19
|
export declare const STAMP_EVIDENCE_BODY_TYPE = "sanning.stamp.evidence/v2";
|
|
28
20
|
/**
|
|
29
|
-
* The version string
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* `sanning.stamp.trace/v1` discriminates the BUNDLE BODY: it is the reader's
|
|
33
|
-
* dispatch key. `sanning.stamp/v1` is the control plane's own version of the
|
|
34
|
-
* bytes it hands a witness (`control-plane/src/stamp-tree.ts`,
|
|
35
|
-
* `STAMP_BODY_VERSION`). A `sanning.stamp.trace/v1` body pins the inner
|
|
36
|
-
* version to exactly this value: two answers to one question inside one
|
|
37
|
-
* signature is the §5.1.2 mixed-vocabulary reject, one layer down.
|
|
21
|
+
* The version string inside a witnessed stamp body, distinct from the
|
|
22
|
+
* `body_type` above (the dispatch key). A stamp trace body pins it to exactly
|
|
23
|
+
* this value (§5.1.2).
|
|
38
24
|
*/
|
|
39
25
|
export declare const STAMP_BODY_VERSION = "sanning.stamp/v1";
|
|
40
26
|
export interface EvidenceIssuer {
|
|
@@ -43,23 +29,9 @@ export interface EvidenceIssuer {
|
|
|
43
29
|
agent_id?: string;
|
|
44
30
|
[k: string]: unknown;
|
|
45
31
|
}
|
|
46
|
-
export interface EvidenceVerdict {
|
|
47
|
-
status: string;
|
|
48
|
-
summary?: string;
|
|
49
|
-
counts?: Record<string, number>;
|
|
50
|
-
as_of?: string;
|
|
51
|
-
[k: string]: unknown;
|
|
52
|
-
}
|
|
53
32
|
/**
|
|
54
|
-
* Where a commitment was witnessed (evidence-bundle.md §5.1.1).
|
|
55
|
-
*
|
|
56
|
-
* The same three-part shape the control plane indexes (`kind` / one promoted
|
|
57
|
-
* `id` / a typed remainder), so the signed body, the index row and the SDK
|
|
58
|
-
* artifact stop being three vocabularies for one fact.
|
|
59
|
-
*
|
|
60
|
-
* NOT ONE FIELD HERE NAMES A CHAIN. Arweave's chunk proof, data_path, offsets
|
|
61
|
-
* and packing live in `ref`, opaque to every reader above this seam. A field
|
|
62
|
-
* that would need renaming for a second witness belongs in `ref` by definition.
|
|
33
|
+
* Where a commitment was witnessed (evidence-bundle.md §5.1.1). No field here
|
|
34
|
+
* names a chain: chain-specific detail lives in the opaque `ref`.
|
|
63
35
|
*/
|
|
64
36
|
export interface AnchorRef {
|
|
65
37
|
kind: string;
|
|
@@ -68,15 +40,13 @@ export interface AnchorRef {
|
|
|
68
40
|
}
|
|
69
41
|
export interface TraceCheckpoint {
|
|
70
42
|
/**
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* label.
|
|
43
|
+
* Hex SHA-256 of the decoded `event_bytes`: the checkpoint's identity and join
|
|
44
|
+
* key. Recomputed by the verifier, never trusted.
|
|
74
45
|
*/
|
|
75
46
|
checkpoint_ref: string;
|
|
76
47
|
/**
|
|
77
|
-
* Where it was witnessed,
|
|
78
|
-
*
|
|
79
|
-
* required field that must be filled dishonestly is a defect in the format.
|
|
48
|
+
* Where it was witnessed, if it has been. Absent is honest: checkpoints are
|
|
49
|
+
* placed before they are witnessed.
|
|
80
50
|
*/
|
|
81
51
|
anchor_ref?: AnchorRef;
|
|
82
52
|
envelope: Envelope;
|
|
@@ -102,13 +72,9 @@ export interface AnchorTraceBody {
|
|
|
102
72
|
events: TraceEvent[];
|
|
103
73
|
}
|
|
104
74
|
/**
|
|
105
|
-
* One sub-tree of a stamp, as the
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
* never publish), so a reader learns that the org runs N agents and their
|
|
109
|
-
* relative volumes and learns no name. The RANGE is deliberately in the clear:
|
|
110
|
-
* it is what makes a later per-agent slice claim checkable by a third party
|
|
111
|
-
* without Sanning, and hiding it would put us back in the trust path.
|
|
75
|
+
* One sub-tree of a stamp, as the witnessed bytes carry it. Keyed by a blinded
|
|
76
|
+
* reference, so a reader learns no agent name. The range is in the clear so a
|
|
77
|
+
* per-agent slice claim is checkable without Sanning.
|
|
112
78
|
*/
|
|
113
79
|
export interface StampSubtree {
|
|
114
80
|
first_leaf: number;
|
|
@@ -117,15 +83,12 @@ export interface StampSubtree {
|
|
|
117
83
|
root: string;
|
|
118
84
|
}
|
|
119
85
|
/**
|
|
120
|
-
* The stamp body as the control plane witnesses it
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* Never read from the bundle directly — it is parsed out of `stamp_bytes`,
|
|
124
|
-
* which is the only authority. Present as a type so the parse has a shape.
|
|
86
|
+
* The stamp body as the control plane witnesses it. Only ever parsed out of
|
|
87
|
+
* `stamp_bytes`, the sole authority.
|
|
125
88
|
*/
|
|
126
89
|
export interface StampBody {
|
|
127
90
|
stamp_version: string;
|
|
128
|
-
/** The org,
|
|
91
|
+
/** The org, blinded. Not reversible without the secret. */
|
|
129
92
|
org_ref: string;
|
|
130
93
|
interval_start: string;
|
|
131
94
|
interval_end: string;
|
|
@@ -135,18 +98,13 @@ export interface StampBody {
|
|
|
135
98
|
}
|
|
136
99
|
/** One entry of a `sanning.stamp.trace/v1` body's `stamps[]` (§5.2). */
|
|
137
100
|
export interface StampEntry {
|
|
138
|
-
/**
|
|
139
|
-
* The stamp's identity within this bundle, DERIVED: hex SHA-256 of the
|
|
140
|
-
* DECODED `stamp_bytes`, not of the hex text. A verifier MUST recompute it.
|
|
141
|
-
*/
|
|
101
|
+
/** Hex SHA-256 of the decoded `stamp_bytes`, not the hex text. Recomputed by the verifier. */
|
|
142
102
|
stamp_ref: string;
|
|
143
103
|
/** Lowercase hex of the exact JCS bytes that were handed to the witness. */
|
|
144
104
|
stamp_bytes: string;
|
|
145
105
|
/**
|
|
146
|
-
* Where the stamp was witnessed,
|
|
147
|
-
*
|
|
148
|
-
* filled this in from a submission receipt would be claiming a chain
|
|
149
|
-
* position that does not exist yet.
|
|
106
|
+
* Where the stamp was witnessed, if it has been (§5.1.1). Absent is honest: a
|
|
107
|
+
* submission receipt is not a chain position.
|
|
150
108
|
*/
|
|
151
109
|
anchor_ref?: AnchorRef;
|
|
152
110
|
}
|
|
@@ -159,7 +117,7 @@ export interface StampEvidenceInclusion {
|
|
|
159
117
|
leaf_index: number;
|
|
160
118
|
leaf_count: number;
|
|
161
119
|
audit_path: string[];
|
|
162
|
-
/** Resolves against `stamps[].stamp_ref` in the
|
|
120
|
+
/** Resolves against `stamps[].stamp_ref` in the same body. */
|
|
163
121
|
stamp_ref: string;
|
|
164
122
|
}
|
|
165
123
|
export interface StampEvidenceEvent {
|
|
@@ -169,7 +127,7 @@ export interface StampEvidenceEvent {
|
|
|
169
127
|
inclusion: StampEvidenceInclusion;
|
|
170
128
|
}
|
|
171
129
|
export interface StampEvidenceBody {
|
|
172
|
-
/** Byte-identical to §5.2.2
|
|
130
|
+
/** Byte-identical to §5.2.2. */
|
|
173
131
|
stamps: StampEntry[];
|
|
174
132
|
events: StampEvidenceEvent[];
|
|
175
133
|
}
|
|
@@ -179,7 +137,6 @@ export interface EvidenceBundle {
|
|
|
179
137
|
issuer: EvidenceIssuer;
|
|
180
138
|
generated_at: string;
|
|
181
139
|
gateway?: string | null;
|
|
182
|
-
verdict: EvidenceVerdict;
|
|
183
140
|
body?: unknown;
|
|
184
141
|
body_ref?: string;
|
|
185
142
|
body_hash: string;
|
|
@@ -189,7 +146,7 @@ export interface EvidenceBundle {
|
|
|
189
146
|
signature: string;
|
|
190
147
|
[k: string]: unknown;
|
|
191
148
|
}
|
|
192
|
-
export type EvidenceStatus = "verified" | "
|
|
149
|
+
export type EvidenceStatus = "verified" | "failed" | "incomplete";
|
|
193
150
|
export type OnChainOutcome = "confirm" | "mismatch" | "unreachable";
|
|
194
151
|
export interface PerGatewayOutcome {
|
|
195
152
|
gateway: string;
|
|
@@ -203,11 +160,7 @@ export interface OnChainResult {
|
|
|
203
160
|
export interface CheckpointResult {
|
|
204
161
|
/** The derived `checkpoint_ref`, empty when it could not be derived. */
|
|
205
162
|
checkpointRef: string;
|
|
206
|
-
/**
|
|
207
|
-
* Where this checkpoint was witnessed. `null` when the checkpoint carries no
|
|
208
|
-
* `anchor_ref`: placed but not yet witnessed, which is a normal state and NOT
|
|
209
|
-
* a deficiency.
|
|
210
|
-
*/
|
|
163
|
+
/** Where it was witnessed; `null` when placed but not yet witnessed, which is normal. */
|
|
211
164
|
anchorRef: AnchorRef | null;
|
|
212
165
|
envelopeOk: boolean;
|
|
213
166
|
merkleRootOk: boolean;
|
|
@@ -215,6 +168,7 @@ export interface CheckpointResult {
|
|
|
215
168
|
onChain: OnChainResult | null;
|
|
216
169
|
ok: boolean;
|
|
217
170
|
errors: string[];
|
|
171
|
+
anchorRefMalformed?: boolean;
|
|
218
172
|
}
|
|
219
173
|
export interface EventResult {
|
|
220
174
|
eventId: string;
|
|
@@ -225,10 +179,45 @@ export interface EventResult {
|
|
|
225
179
|
contentOk: boolean | null;
|
|
226
180
|
ok: boolean;
|
|
227
181
|
errors: string[];
|
|
182
|
+
/**
|
|
183
|
+
* The `sanning.agent` reading of this record (agent-events.md section 10), read with
|
|
184
|
+
* every other record of the pile it was verified in: the bundle, or every pack
|
|
185
|
+
* of a case. `null` where the record is not an agent record, or its envelope
|
|
186
|
+
* did not verify, or its record bytes did not travel or did not bind. It never
|
|
187
|
+
* moves `ok` or the bundle status; the pack grade reads it (section 5.4.5).
|
|
188
|
+
*/
|
|
189
|
+
agent: AgentRecordReading | null;
|
|
190
|
+
/**
|
|
191
|
+
* True where the record's `stamp_ref` or `checkpoint_ref` names a stamp or checkpoint the
|
|
192
|
+
* pack does not hold: `witnessed` is not proven (`missing`), never disproven, whatever else
|
|
193
|
+
* about the record fails.
|
|
194
|
+
*/
|
|
195
|
+
stampAbsent?: boolean;
|
|
196
|
+
/**
|
|
197
|
+
* True where the record carries a retired field name, or bytes that are present and cannot
|
|
198
|
+
* be read: a defect in the artifact that fails the record under a key that can be read.
|
|
199
|
+
*/
|
|
200
|
+
ownFormFailed?: boolean;
|
|
201
|
+
/**
|
|
202
|
+
* True where the record's signed bytes bind to its `payload_hash` under a signature that
|
|
203
|
+
* holds and are not JSON: the producer broke the format it signed, so `follows_rules` is
|
|
204
|
+
* disproven and nothing was proven altered.
|
|
205
|
+
*/
|
|
206
|
+
recordNotJson?: boolean;
|
|
207
|
+
/**
|
|
208
|
+
* True where the bytes this record's content was checked against came from the side
|
|
209
|
+
* input, which nobody signed: a mismatch then leaves `unchanged` not proven
|
|
210
|
+
* (`not_checked`), never disproven.
|
|
211
|
+
*/
|
|
212
|
+
contentUnsigned?: boolean;
|
|
213
|
+
/** Why the record's envelope does not verify: the worst of `envelopeFaults`, or `null`. */
|
|
214
|
+
envelopeFault?: EnvelopeFault | null;
|
|
215
|
+
/** Every envelope fault found (`ENVELOPE_FAULTS`), worst first. */
|
|
216
|
+
envelopeFaults?: EnvelopeFault[];
|
|
228
217
|
}
|
|
229
218
|
/** One sub-tree's recomputed result (§5.2). */
|
|
230
219
|
export interface StampSubtreeResult {
|
|
231
|
-
/** The blinded key the body
|
|
220
|
+
/** The blinded key the body uses. */
|
|
232
221
|
ref: string;
|
|
233
222
|
firstLeaf: number;
|
|
234
223
|
leafCount: number;
|
|
@@ -236,17 +225,13 @@ export interface StampSubtreeResult {
|
|
|
236
225
|
}
|
|
237
226
|
/** One `stamps[]` entry's result (§5.2). */
|
|
238
227
|
export interface StampResult {
|
|
239
|
-
/** The stamp's derived identity
|
|
228
|
+
/** The stamp's derived identity. "" when unusable. */
|
|
240
229
|
stampRef: string;
|
|
241
230
|
/** The asserted `stamp_ref` equals SHA-256 of the decoded `stamp_bytes`. */
|
|
242
231
|
stampRefOk: boolean;
|
|
243
232
|
/**
|
|
244
|
-
* The witnessed bytes
|
|
245
|
-
*
|
|
246
|
-
* The last clause is not pedantry. The plane stores these bytes as TEXT and
|
|
247
|
-
* replays them verbatim precisely because a round-trip through a normalizing
|
|
248
|
-
* serializer is not guaranteed to reproduce what was signed; a body that is
|
|
249
|
-
* not JCS-canonical is one that every re-deriving reader hashes differently.
|
|
233
|
+
* The witnessed bytes decode, parse and re-canonicalize to themselves. A body
|
|
234
|
+
* that is not JCS-canonical hashes differently for every re-deriving reader.
|
|
250
235
|
*/
|
|
251
236
|
bodyOk: boolean;
|
|
252
237
|
stampVersion: string | null;
|
|
@@ -255,55 +240,34 @@ export interface StampResult {
|
|
|
255
240
|
merkleRoot: string | null;
|
|
256
241
|
leafCount: number | null;
|
|
257
242
|
/**
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
* overlap, and their counts sum to `leaf_count`.
|
|
243
|
+
* The sub-tree ranges, sorted by `first_leaf`, tile `[0, leaf_count)` with no
|
|
244
|
+
* gap or overlap.
|
|
261
245
|
*/
|
|
262
246
|
subtreesOk: boolean;
|
|
263
247
|
subtrees: StampSubtreeResult[];
|
|
264
248
|
/**
|
|
265
|
-
* Where it was witnessed, or `null`
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
* of every stamp for the first minutes of its life and the permanent state
|
|
269
|
-
* of every stamp when no witness is configured. It does hold the bundle at
|
|
270
|
-
* `partial`: a stamp is Sanning's own assertion until something independent
|
|
271
|
-
* carries it.
|
|
249
|
+
* Where it was witnessed, or `null` if nothing has witnessed it yet. Never an
|
|
250
|
+
* accusation, but it holds the bundle at `partial`: until witnessed, a stamp
|
|
251
|
+
* is Sanning's own assertion.
|
|
272
252
|
*/
|
|
273
253
|
anchorRef: AnchorRef | null;
|
|
274
254
|
/**
|
|
275
|
-
* Per-gateway
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
* `null` means not checked — no gateways were supplied, or this stamp names
|
|
281
|
-
* no witness to check, or its `anchor_ref.kind` has no witness adapter, or
|
|
282
|
-
* its id is not one the adapter accepts; the witness was not checked. It is
|
|
283
|
-
* a statement about the RUN, never about the stamp. The other three are
|
|
284
|
-
* statements about the stamp and live in `onChain.rollup`: `confirm` (a
|
|
285
|
-
* gateway returned the witnessed bytes), `mismatch` (a gateway returned
|
|
286
|
-
* DIFFERENT bytes: a finding, and the only one of the four that fails
|
|
287
|
-
* anything), `unreachable` (we asked and nobody answered: an availability
|
|
288
|
-
* gap, never an accusation).
|
|
289
|
-
*
|
|
290
|
-
* Keeping "not checked" distinct from "unreachable" is the whole point. A
|
|
291
|
-
* surface handed a collapsed boolean cannot tell "no gateway could be
|
|
292
|
-
* reached" from "no gateway was tried", and reported the first when the
|
|
293
|
-
* second was true — a false accusation manufactured by a missing state.
|
|
255
|
+
* Per-gateway outcomes for this stamp's `anchor_ref`, or `null` when nothing
|
|
256
|
+
* was checked (a statement about the run, not the stamp). Of `confirm`,
|
|
257
|
+
* `mismatch` and `unreachable`, only `mismatch` fails anything. "Not checked"
|
|
258
|
+
* and "unreachable" stay distinct so a surface never reports an availability
|
|
259
|
+
* gap that was never tested.
|
|
294
260
|
*/
|
|
295
261
|
onChain: OnChainResult | null;
|
|
296
262
|
/**
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
* on confirm, `null` on unreachable AND on not-checked.
|
|
300
|
-
*
|
|
301
|
-
* It is deliberately the LOSSY view — `null` is three-quarters of the state
|
|
302
|
-
* space here. Anything that needs to tell those apart reads `onChain`.
|
|
263
|
+
* Lossy collapse of `onChain`, as on `CheckpointResult`: `false` mismatch,
|
|
264
|
+
* `true` confirm, `null` unreachable or not checked.
|
|
303
265
|
*/
|
|
304
266
|
onChainOk: boolean | null;
|
|
305
267
|
ok: boolean;
|
|
306
268
|
errors: string[];
|
|
269
|
+
/** True where the only thing wrong is a malformed `anchor_ref` (as on a checkpoint). */
|
|
270
|
+
anchorRefMalformed?: boolean;
|
|
307
271
|
}
|
|
308
272
|
export interface EvidenceBundleResult {
|
|
309
273
|
status: EvidenceStatus;
|
|
@@ -314,10 +278,13 @@ export interface EvidenceBundleResult {
|
|
|
314
278
|
onChainChecked: boolean;
|
|
315
279
|
checkpoints: CheckpointResult[];
|
|
316
280
|
events: EventResult[];
|
|
317
|
-
assertedStatus: string | null;
|
|
318
281
|
export?: ExportResult;
|
|
319
282
|
stamps?: StampResult[];
|
|
320
283
|
errors: string[];
|
|
284
|
+
unreadable?: boolean;
|
|
285
|
+
generatedAtMalformed?: boolean;
|
|
286
|
+
keyUnreadable?: boolean;
|
|
287
|
+
versionUnknown?: boolean;
|
|
321
288
|
notes?: string[];
|
|
322
289
|
}
|
|
323
290
|
export interface AttestationRecord {
|
|
@@ -414,6 +381,7 @@ export interface AttestationResult {
|
|
|
414
381
|
subjectRefOk: boolean | null;
|
|
415
382
|
ok: boolean;
|
|
416
383
|
errors: string[];
|
|
384
|
+
fieldError?: string | null;
|
|
417
385
|
}
|
|
418
386
|
export interface ExportResult {
|
|
419
387
|
sourceLinkageOk: boolean;
|
|
@@ -422,6 +390,7 @@ export interface ExportResult {
|
|
|
422
390
|
attestations: AttestationResult[];
|
|
423
391
|
verdict: VerdictObject;
|
|
424
392
|
status: EvidenceStatus;
|
|
393
|
+
sourceUnreadable?: boolean;
|
|
425
394
|
}
|
|
426
395
|
export interface VerifyEvidenceOptions {
|
|
427
396
|
gateways?: string[];
|
|
@@ -429,40 +398,35 @@ export interface VerifyEvidenceOptions {
|
|
|
429
398
|
fetchImpl?: typeof fetch;
|
|
430
399
|
}
|
|
431
400
|
/**
|
|
432
|
-
* A
|
|
433
|
-
*
|
|
434
|
-
*
|
|
435
|
-
* signed scope (`bundleForSig` below), so anyone holding a pack's bytes can
|
|
436
|
-
* append it with no key at all. This is the one sentence both kernels attach
|
|
437
|
-
* as a note, never a verdict, never an exit code.
|
|
401
|
+
* A wrapper's `co_signatures` is not evidence (evidence-bundle.md §2): nothing
|
|
402
|
+
* verifies it, and it sits outside the signed scope, so anyone can append it.
|
|
403
|
+
* Attached as a note, never a verdict or exit code.
|
|
438
404
|
*/
|
|
439
405
|
export declare const CO_SIGNATURES_NOTE = "unverified co-signatures are present in this pack's wrapper and are not part of the evidence";
|
|
440
406
|
/**
|
|
441
|
-
*
|
|
442
|
-
*
|
|
443
|
-
*
|
|
444
|
-
* Absence and an empty array read the same way here: the field asserts
|
|
445
|
-
* nothing about a second signer until it holds one, and evidence-bundle.md's
|
|
446
|
-
* own carve-out language for the analogous envelope field treats "absent"
|
|
447
|
-
* and "an empty array" as one thing (envelope-spec.md §7.1). A non-array
|
|
448
|
-
* value (malformed shape, but the field is reserved, not yet specified)
|
|
449
|
-
* still counts as present: it is not the well-formed absence either rule
|
|
450
|
-
* describes.
|
|
407
|
+
* Whether the wrapper's reserved `co_signatures` carries at least one entry.
|
|
408
|
+
* Absent and empty read the same (envelope-spec.md §7.1); a non-array value
|
|
409
|
+
* counts as present.
|
|
451
410
|
*/
|
|
452
411
|
export declare function coSignaturesPresent(b: unknown): boolean;
|
|
412
|
+
/** evidence-bundle.md §2. Byte-identical to the Python kernel's. */
|
|
413
|
+
export declare const GENERATED_AT_MALFORMED = "malformed generated_at: not an RFC 3339 UTC date-time with Z naming a real date and time (evidence-bundle section 2)";
|
|
453
414
|
/**
|
|
454
|
-
*
|
|
455
|
-
*
|
|
456
|
-
*
|
|
457
|
-
*
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
*
|
|
461
|
-
*
|
|
462
|
-
|
|
415
|
+
* Name an envelope `public_key` or `signature` spelled outside the hex charset
|
|
416
|
+
* or at the wrong length, in the same words as Python, so both kernels give one
|
|
417
|
+
* reading. Only a string is checked; a missing one is the envelope layer's to
|
|
418
|
+
* fail.
|
|
419
|
+
*/
|
|
420
|
+
/**
|
|
421
|
+
* The envelope faults that leave a claim not proven rather than disproven: the record's
|
|
422
|
+
* envelope or key cannot be read, or its version is one this verifier does not know.
|
|
423
|
+
*/
|
|
424
|
+
export declare const UNPROVEN_ENVELOPE_FAULTS: readonly EnvelopeFault[];
|
|
425
|
+
/**
|
|
426
|
+
* Verify a `sanning.evidence/v1` bundle, dispatching on its `body_type`. The
|
|
427
|
+
* returned `status` is recomputed from the body; a wrapper `verdict` member,
|
|
428
|
+
* where a producer still writes one, is never read (evidence-bundle.md section 4).
|
|
463
429
|
*/
|
|
464
|
-
/** evidence-bundle §2 (A31). Byte-identical to the Python kernel's. */
|
|
465
|
-
export declare const GENERATED_AT_MALFORMED = "malformed generated_at: not an RFC 3339 UTC date-time with Z naming a real date and time (evidence-bundle \u00A72)";
|
|
466
430
|
export declare function verifyEvidenceBundle(bundle: unknown, options?: VerifyEvidenceOptions): Promise<EvidenceBundleResult>;
|
|
467
431
|
/**
|
|
468
432
|
* The `anchor_ref.kind` a sandbox plane writes for a witness it simulated
|
|
@@ -485,18 +449,13 @@ export interface DisclosedContentResult {
|
|
|
485
449
|
errors: string[];
|
|
486
450
|
}
|
|
487
451
|
/**
|
|
488
|
-
* Materialize the disclosed raw bytes of a received bundle (evidence-bundle
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
*
|
|
492
|
-
* bytes are returned ONLY when that verification bound them to the committed
|
|
493
|
-
* `content_hash`. There is no path through this function that yields bytes
|
|
494
|
-
* whose SHA-256 is not the commitment.
|
|
452
|
+
* Materialize the disclosed raw bytes of a received bundle (evidence-bundle.md
|
|
453
|
+
* §5.1). The bundle is verified with {@link verifyEvidenceBundle}, and an
|
|
454
|
+
* event's bytes are returned only when that verification bound them to the
|
|
455
|
+
* committed `content_hash`.
|
|
495
456
|
*
|
|
496
|
-
* Returns `Uint8Array`, never a string:
|
|
497
|
-
*
|
|
498
|
-
* such a string would produce different bytes and a different hash. Callers who
|
|
499
|
-
* know their payload is text decode it themselves and own that assumption.
|
|
457
|
+
* Returns `Uint8Array`, never a string: a UTF-8 decode is lossy and would
|
|
458
|
+
* change the hash.
|
|
500
459
|
*/
|
|
501
460
|
export declare function disclosedContent(bundle: unknown, options?: VerifyEvidenceOptions): Promise<DisclosedContentResult>;
|
|
502
461
|
export declare function resolveTraceEvents(bundle: unknown): TraceEvent[] | undefined;
|