@sanning/proof 0.17.0 → 0.19.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 +2 -2
- package/dist/case-file.js +2 -1
- package/dist/case.js +11 -4
- package/dist/chain.d.ts +28 -0
- package/dist/chain.js +61 -4
- package/dist/cli.js +226 -33
- package/dist/crypto.d.ts +17 -0
- package/dist/crypto.js +116 -16
- package/dist/declaration.d.ts +43 -4
- package/dist/declaration.js +198 -14
- package/dist/environment.d.ts +42 -0
- package/dist/environment.js +136 -0
- package/dist/evidence.d.ts +6 -0
- package/dist/evidence.js +32 -1
- package/dist/exit-codes.d.ts +18 -0
- package/dist/exit-codes.js +25 -0
- package/dist/index.d.ts +9 -5
- package/dist/index.js +21 -5
- package/dist/run-adapters.d.ts +10 -0
- package/dist/run-adapters.js +35 -0
- package/dist/run.d.ts +209 -0
- package/dist/run.js +1405 -0
- package/dist/verifier.d.ts +43 -0
- package/dist/verifier.js +113 -6
- package/dist/witness-lookup.d.ts +13 -1
- package/dist/witness-lookup.js +12 -2
- package/package.json +2 -2
- package/src/case-file.ts +2 -1
- package/src/case.ts +11 -4
- package/src/chain.ts +81 -4
- package/src/cli.ts +259 -28
- package/src/crypto.ts +125 -16
- package/src/declaration.ts +242 -12
- package/src/environment.ts +145 -0
- package/src/evidence.ts +29 -1
- package/src/exit-codes.ts +28 -0
- package/src/index.ts +31 -1
- package/src/run-adapters.ts +44 -0
- package/src/run.ts +1598 -0
- package/src/verifier.ts +102 -5
- package/src/witness-lookup.ts +18 -1
- package/vectors/README.md +37 -0
- package/vectors/sandbox-evidence.json +3161 -0
package/dist/evidence.js
CHANGED
|
@@ -1019,6 +1019,10 @@ async function verifyAnchorTrace(b, specVersionOk, assertedStatus, errors, optio
|
|
|
1019
1019
|
let gatewayUnavailable = false;
|
|
1020
1020
|
let uncheckedKind = false;
|
|
1021
1021
|
let uncheckedId = false;
|
|
1022
|
+
// Simulated witnesses against witnesses of any other kind, counted over the
|
|
1023
|
+
// checkpoints that name one, as `refetchStamps` counts stamps.
|
|
1024
|
+
let simulated = 0;
|
|
1025
|
+
let onChainKinds = 0;
|
|
1022
1026
|
if (onChainChecked) {
|
|
1023
1027
|
if (typeof fetchImpl !== "function") {
|
|
1024
1028
|
gatewayUnavailable = true;
|
|
@@ -1060,6 +1064,10 @@ async function verifyAnchorTrace(b, specVersionOk, assertedStatus, errors, optio
|
|
|
1060
1064
|
cpr.errors.push("checkpoint has no anchor_ref -- not yet witnessed, nothing to re-fetch");
|
|
1061
1065
|
continue;
|
|
1062
1066
|
}
|
|
1067
|
+
if (cpr.anchorRef.kind === SIMULATED_WITNESS_KIND)
|
|
1068
|
+
simulated++;
|
|
1069
|
+
else
|
|
1070
|
+
onChainKinds++;
|
|
1063
1071
|
const outcome = await refetchCheckpoint(cp, cpr.anchorRef, gateways, fetchImpl);
|
|
1064
1072
|
cpr.onChain = outcome.onChain;
|
|
1065
1073
|
cpr.onChainOk = outcome.onChain?.onChainOk ?? null;
|
|
@@ -1127,7 +1135,10 @@ async function verifyAnchorTrace(b, specVersionOk, assertedStatus, errors, optio
|
|
|
1127
1135
|
bodyHashOk: true,
|
|
1128
1136
|
signatureOk: true,
|
|
1129
1137
|
bodyType,
|
|
1130
|
-
|
|
1138
|
+
// A run whose only witnessed checkpoints are simulated looked nothing up
|
|
1139
|
+
// on a chain, so it is not counted as checked on one (the stamp rule in
|
|
1140
|
+
// `refetchStamps`). The checkpoints stay not checked and the run partial.
|
|
1141
|
+
onChainChecked: onChainChecked && !(simulated > 0 && onChainKinds === 0),
|
|
1131
1142
|
checkpoints: checkpointResults,
|
|
1132
1143
|
events: eventResults,
|
|
1133
1144
|
assertedStatus,
|
|
@@ -1939,6 +1950,8 @@ async function refetchStamps(stamps, witnessed, options, errors) {
|
|
|
1939
1950
|
let gatewayUnavailable = false;
|
|
1940
1951
|
let uncheckedKind = false;
|
|
1941
1952
|
let uncheckedId = false;
|
|
1953
|
+
let simulated = 0;
|
|
1954
|
+
let onChainKinds = 0;
|
|
1942
1955
|
for (let i = 0; i < stamps.length; i++) {
|
|
1943
1956
|
const st = stamps[i];
|
|
1944
1957
|
const witnessedHex = witnessed[i];
|
|
@@ -1946,6 +1959,10 @@ async function refetchStamps(stamps, witnessed, options, errors) {
|
|
|
1946
1959
|
// nothing a gateway could confirm or deny. Left as `onChain: null`.
|
|
1947
1960
|
if (st.anchorRef === null || witnessedHex === undefined)
|
|
1948
1961
|
continue;
|
|
1962
|
+
if (st.anchorRef.kind === SIMULATED_WITNESS_KIND)
|
|
1963
|
+
simulated++;
|
|
1964
|
+
else
|
|
1965
|
+
onChainKinds++;
|
|
1949
1966
|
const outcome = await refetchStamp(witnessedHex, st.anchorRef, gateways, fetchImpl);
|
|
1950
1967
|
st.onChain = outcome.onChain;
|
|
1951
1968
|
st.onChainOk = outcome.onChain?.onChainOk ?? null;
|
|
@@ -1968,8 +1985,22 @@ async function refetchStamps(stamps, witnessed, options, errors) {
|
|
|
1968
1985
|
// unreachable note would fail a stamp for a gateway being down.
|
|
1969
1986
|
st.ok = st.ok && st.onChainOk !== false;
|
|
1970
1987
|
}
|
|
1988
|
+
// A simulated witness is a sandbox plane's stand-in for a chain: there is no
|
|
1989
|
+
// chain to look it up on, so it is never counted as checked on one.
|
|
1990
|
+
// It stays not checked like any kind this verifier has no adapter for, and
|
|
1991
|
+
// the run stays undetermined; what changes is that a run whose only
|
|
1992
|
+
// witnesses are simulated no longer says it checked anything on a chain.
|
|
1993
|
+
if (simulated > 0 && onChainKinds === 0) {
|
|
1994
|
+
return { onChainChecked: false, gatewayUnavailable, uncheckedKind, uncheckedId };
|
|
1995
|
+
}
|
|
1971
1996
|
return { onChainChecked, gatewayUnavailable, uncheckedKind, uncheckedId };
|
|
1972
1997
|
}
|
|
1998
|
+
/**
|
|
1999
|
+
* The `anchor_ref.kind` a sandbox plane writes for a witness it simulated
|
|
2000
|
+
* (chain id `sanning-sandbox`). Never looked up and never counted as checked
|
|
2001
|
+
* on a chain.
|
|
2002
|
+
*/
|
|
2003
|
+
export const SIMULATED_WITNESS_KIND = "simulated";
|
|
1973
2004
|
// How many `sanning.evidence.export/v2` wrappers deep the source bundle may be
|
|
1974
2005
|
// nested before this path gives up. verifyEvidenceBundle's canonicalization
|
|
1975
2006
|
// depth bound already rejects a pathological bundle, but the unwrap must be
|
package/dist/exit-codes.d.ts
CHANGED
|
@@ -3,6 +3,14 @@ export declare const EXIT_FAILED = 1;
|
|
|
3
3
|
export declare const EXIT_MALFORMED = 2;
|
|
4
4
|
export declare const EXIT_UNDETERMINED = 3;
|
|
5
5
|
export declare const EXIT_MIXED = 4;
|
|
6
|
+
/**
|
|
7
|
+
* Sandbox evidence (envelope-spec §2): a run that would exit 0 over a pack or
|
|
8
|
+
* case holding a record signed `environment: "dev"`, or a run over records
|
|
9
|
+
* that are ALL signed `dev` whose only unsettled witnesses are simulated.
|
|
10
|
+
* Not a verdict word: the verdict stays what the checks established
|
|
11
|
+
* (`sandboxExit`). No flag turns 5 into 0.
|
|
12
|
+
*/
|
|
13
|
+
export declare const EXIT_SANDBOX = 5;
|
|
6
14
|
/**
|
|
7
15
|
* The exit code of each of the eight verdict words (`evidence-bundle.md` §3).
|
|
8
16
|
* `undetermined` is the name of 3, and never a word here.
|
|
@@ -15,3 +23,13 @@ export declare const EXIT_CODES_HELP: string;
|
|
|
15
23
|
* nothing can render, so it exits 2, never 0.
|
|
16
24
|
*/
|
|
17
25
|
export declare function exitCodeFor(verdict: unknown): number;
|
|
26
|
+
/**
|
|
27
|
+
* The code a verb exits with once the environment marker is read. 5 where the
|
|
28
|
+
* run would otherwise exit 0 and the pack or case holds a record signed `dev`;
|
|
29
|
+
* 5 where the run is undetermined only because a simulated witness could not
|
|
30
|
+
* be looked up (`onlySimulatedUnsettled`, which the caller works out) and
|
|
31
|
+
* EVERY record is signed `dev`, so a production or mixed pack carrying a
|
|
32
|
+
* simulated witness keeps 3; the code unchanged everywhere else. A failure
|
|
33
|
+
* stays 1, malformed 2 and mixed 4.
|
|
34
|
+
*/
|
|
35
|
+
export declare function sandboxExit(code: number, environmentMarker: string | null, onlySimulatedUnsettled?: boolean): number;
|
package/dist/exit-codes.js
CHANGED
|
@@ -15,6 +15,14 @@ export const EXIT_FAILED = 1;
|
|
|
15
15
|
export const EXIT_MALFORMED = 2;
|
|
16
16
|
export const EXIT_UNDETERMINED = 3;
|
|
17
17
|
export const EXIT_MIXED = 4;
|
|
18
|
+
/**
|
|
19
|
+
* Sandbox evidence (envelope-spec §2): a run that would exit 0 over a pack or
|
|
20
|
+
* case holding a record signed `environment: "dev"`, or a run over records
|
|
21
|
+
* that are ALL signed `dev` whose only unsettled witnesses are simulated.
|
|
22
|
+
* Not a verdict word: the verdict stays what the checks established
|
|
23
|
+
* (`sandboxExit`). No flag turns 5 into 0.
|
|
24
|
+
*/
|
|
25
|
+
export const EXIT_SANDBOX = 5;
|
|
18
26
|
/**
|
|
19
27
|
* The exit code of each of the eight verdict words (`evidence-bundle.md` §3).
|
|
20
28
|
* `undetermined` is the name of 3, and never a word here.
|
|
@@ -37,6 +45,7 @@ export const EXIT_CODES_HELP = [
|
|
|
37
45
|
" 2 usage or malformed",
|
|
38
46
|
" 3 undetermined: partial, pending, incomplete or not_found",
|
|
39
47
|
" 4 mixed: more than one outcome, none failed; read the exceptions",
|
|
48
|
+
" 5 sandbox: a record is signed environment dev; would be 0, or only a simulated witness is unchecked",
|
|
40
49
|
].join("\n");
|
|
41
50
|
/**
|
|
42
51
|
* The exit code of a verdict word. A word outside the eight is a verdict
|
|
@@ -48,3 +57,19 @@ export function exitCodeFor(verdict) {
|
|
|
48
57
|
}
|
|
49
58
|
return EXIT_MALFORMED;
|
|
50
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* The code a verb exits with once the environment marker is read. 5 where the
|
|
62
|
+
* run would otherwise exit 0 and the pack or case holds a record signed `dev`;
|
|
63
|
+
* 5 where the run is undetermined only because a simulated witness could not
|
|
64
|
+
* be looked up (`onlySimulatedUnsettled`, which the caller works out) and
|
|
65
|
+
* EVERY record is signed `dev`, so a production or mixed pack carrying a
|
|
66
|
+
* simulated witness keeps 3; the code unchanged everywhere else. A failure
|
|
67
|
+
* stays 1, malformed 2 and mixed 4.
|
|
68
|
+
*/
|
|
69
|
+
export function sandboxExit(code, environmentMarker, onlySimulatedUnsettled = false) {
|
|
70
|
+
if (code === EXIT_VERIFIED && environmentMarker !== null)
|
|
71
|
+
return EXIT_SANDBOX;
|
|
72
|
+
if (code === EXIT_UNDETERMINED && environmentMarker === "dev" && onlySimulatedUnsettled)
|
|
73
|
+
return EXIT_SANDBOX;
|
|
74
|
+
return code;
|
|
75
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
export { ACCEPTED_SPEC_MAJORS, contentHashes, jcs, specVersionSupported, verifyEnvelope, } from "./verifier.js";
|
|
2
|
-
export {
|
|
2
|
+
export { jcsParse } from "./verifier.js";
|
|
3
|
+
export { exceedsTextDepth, hasNonFiniteNumber, jcsParseWithinLimits, MAX_READ_DEPTH } from "./verifier.js";
|
|
4
|
+
export { bytesToHex, deriveOperatorAddress, ed25519Refusal, ed25519Verify, hexToBytes, sha256Bytes, sha256Hex, utf8, verifyRsaPssSha256, } from "./crypto.js";
|
|
3
5
|
export { EMPTY_TREE_ROOT_HEX, auditPath, leafHash, merkleRoot, nodeHash, verifyInclusion, } from "./merkle.js";
|
|
4
6
|
export type { ContentRole, Envelope, Subject, VerificationResult, VerifyOptions } from "./types.js";
|
|
5
7
|
export { ACCEPTED_EVIDENCE_MAJORS, ANCHOR_TRACE_BODY_TYPE, CO_SIGNATURES_NOTE, EXPORT_BODY_TYPE, STAMP_BODY_VERSION, STAMP_TRACE_BODY_TYPE, STAMP_EVIDENCE_BODY_TYPE, coSignaturesPresent, disclosedContent, recomputeExportVerdict, verifyEvidenceBundle, } from "./evidence.js";
|
|
6
8
|
export type { AnchorTraceBody, AttestationPayload, AttestationRecord, AttestationResult, CheckpointResult, ComposeVerdictResult, DisclosedContentResult, DisclosedEventContent, DisclosureStatus, EvidenceBundle, EvidenceBundleResult, EvidenceIssuer, EvidenceStatus, EvidenceVerdict, EventResult, ExportBody, ExportResult, OnChainOutcome, OnChainResult, PerGatewayOutcome, AnchorRef, StampBody, StampEntry, StampResult, StampSubtree, StampSubtreeResult, StampTraceBody, StampEvidenceBody, StampEvidenceEvent, StampEvidenceInclusion, TraceCheckpoint, TraceEvent, TraceInclusion, VerdictAttestation, VerdictCheckpoint, VerdictEvent, VerdictObject, VerdictOnChain, VerdictOnChainGateway, VerifyEvidenceOptions, } from "./evidence.js";
|
|
7
9
|
export { PACK_GRADE_CAUSE_KINDS, PACK_VERDICTS, accountDisclosure, completenessNotes, gradeCauses, gradePack, renderCause, signedLeafCount, } from "./grading.js";
|
|
8
10
|
export type { CompletenessNote, DisclosureAccount, GradeInput, PackGrade, PackGradeCause, PackGradeCauseKind, PackVerdict, } from "./grading.js";
|
|
9
|
-
export { DECLARATION_CONTENT_KINDS, DECLARATION_DEVIATION_KINDS, DECLARATION_NOTE_KINDS, DECLARATION_ROLES, DECLARATION_VERDICTS, DECLARATION_VERSION, DECLARATION_VERSION_V2, DECLARATION_VERSIONS, checkDeclaration, declarationClaims, packRecords, renderContentFinding, renderDeclarationSummary, renderDeviation, renderNote, } from "./declaration.js";
|
|
11
|
+
export { DECLARATION_CONTENT_KINDS, DECLARATION_DEVIATION_KINDS, DECLARATION_NOTE_KINDS, DECLARATION_ROLES, DECLARATION_VERDICTS, DECLARATION_VERSION, DECLARATION_VERSION_V2, DECLARATION_VERSION_V3, DECLARATION_VERSIONS, checkDeclaration, declarationClaims, packRecords, renderContentFinding, renderDeclarationSummary, renderDeviation, renderNote, } from "./declaration.js";
|
|
10
12
|
export type { DeclarationCheck, DeclarationClaims, DeclarationContentFinding, DeclarationContentKind, DeclarationDeviation, DeclarationDeviationKind, DeclarationNote, DeclarationNoteKind, DeclarationRole, DeclarationVerdict, PackRecord, } from "./declaration.js";
|
|
11
13
|
export { CASE_BODY_TYPES, CASE_EXCEPTION_KINDS, CASE_QUARANTINED_PROFILES, CASE_RECORD_PROFILES, CASE_RECORD_STATUSES, CASE_NOTE_KINDS, CASE_RELIANCE, CASE_RELIANCE_HANDOFF_CLAUSE, CASE_VERDICTS, CONTENT_WITHHELD_BY_DECLARATION, CO_SIGNATURES_PRESENT, VERDICT_DISPLAY_TITLES, WITNESS_NOT_LOOKED_UP, WITNESS_STATES, WITNESS_TIME_CACHED, WITNESS_TIME_RECORDED, caseReliance, readCase, renderCaseNote, renderCaseSummary, renderException, renderWitnessLine, } from "./case.js";
|
|
12
14
|
export { MAX_BLOCK_TIME, MAX_WITNESS_CACHE_DEPTH, WITNESS_CACHE_NAME, WITNESS_CACHE_VERSION, checkWitnessCache, formatBlockTime, readWitnessCache, renderWitnessTime, witnessTimeQuery, } from "./witness-cache.js";
|
|
@@ -18,9 +20,11 @@ export { CASE_FILE_FINDING_KINDS, CASE_FILE_INDEX_NAME, CASE_FILE_VERSION, HOW_T
|
|
|
18
20
|
export type { CaseFileFinding, CaseFileFindingKind, CaseFileIndexReading, } from "./case-file.js";
|
|
19
21
|
export { FILE_MATCH_SCOPE, NOT_READ_REASONS, SKIPPED_REASONS, fileMatchToJson, matchCaseFiles, matchFiles, notAccountedFor, renderFileMatch, } from "./file-match.js";
|
|
20
22
|
export type { FileCommitment, FileMatchPack, FileMatchReading, MatchedFile, NotRead, NotReadReason, OfferedFile, SkippedFile, SkippedReason, UnmatchedFile, } from "./file-match.js";
|
|
21
|
-
export { ADAPTER_CHAIN_NAMESPACES, CHAIN_READING_SCOPE, readChains, renderChainFinding, } from "./chain.js";
|
|
22
|
-
export type { ChainFinding, ChainFindingKind, ChainReading, ChainSource, ChainSummary, } from "./chain.js";
|
|
23
|
-
export { EXIT_CODES, EXIT_CODES_HELP, EXIT_FAILED, EXIT_MALFORMED, EXIT_MIXED, EXIT_UNDETERMINED, EXIT_VERIFIED, exitCodeFor, } from "./exit-codes.js";
|
|
23
|
+
export { ADAPTER_CHAIN_NAMESPACES, CHAIN_READING_SCOPE, readChainLinks, readChains, renderChainFinding, } from "./chain.js";
|
|
24
|
+
export type { ChainFinding, ChainFindingKind, ChainLink, ChainReading, ChainSource, ChainSummary, } from "./chain.js";
|
|
25
|
+
export { EXIT_CODES, EXIT_CODES_HELP, EXIT_FAILED, EXIT_MALFORMED, EXIT_MIXED, EXIT_SANDBOX, EXIT_UNDETERMINED, EXIT_VERIFIED, exitCodeFor, sandboxExit, } from "./exit-codes.js";
|
|
26
|
+
export { SANDBOX_HEADLINE, SANDBOX_LINE, SANDBOX_TITLE, environmentMarker, onlySimulatedUnsettled, packEnvelopes, } from "./environment.js";
|
|
27
|
+
export type { EnvironmentMarker } from "./environment.js";
|
|
24
28
|
export { attestationSignatureToHex, composeExport } from "./compose.js";
|
|
25
29
|
export type { ComposeExportOptions, ComposeExportResult, ExporterKey } from "./compose.js";
|
|
26
30
|
export { AGENT_PROOF_SPEC_VERSION, isAgentProofSpec, verifyAgentProof } from "./agent-proof.js";
|
package/dist/index.js
CHANGED
|
@@ -18,7 +18,16 @@
|
|
|
18
18
|
// mutable accept-set would be a runtime-widenable kernel. Additive — no
|
|
19
19
|
// existing export changes.
|
|
20
20
|
export { ACCEPTED_SPEC_MAJORS, contentHashes, jcs, specVersionSupported, verifyEnvelope, } from "./verifier.js";
|
|
21
|
-
|
|
21
|
+
// The strict reader of bytes that claim to be JCS, the twin of Python's public
|
|
22
|
+
// `canonicalize.jcs_loads`. The enclave attestation adapters read a token's
|
|
23
|
+
// JSON through it, so they refuse what the kernel refuses. Additive.
|
|
24
|
+
export { jcsParse } from "./verifier.js";
|
|
25
|
+
// The same reader within the enclave readers' limits (enclave-attestation
|
|
26
|
+
// section 2.1): depth checked on the bytes first, every number finite. The
|
|
27
|
+
// adapters read a token's header and claims and the manifest through it.
|
|
28
|
+
// Additive.
|
|
29
|
+
export { exceedsTextDepth, hasNonFiniteNumber, jcsParseWithinLimits, MAX_READ_DEPTH } from "./verifier.js";
|
|
30
|
+
export { bytesToHex, deriveOperatorAddress, ed25519Refusal, ed25519Verify, hexToBytes, sha256Bytes, sha256Hex, utf8, verifyRsaPssSha256, } from "./crypto.js";
|
|
22
31
|
export { EMPTY_TREE_ROOT_HEX, auditPath, leafHash, merkleRoot, nodeHash, verifyInclusion, } from "./merkle.js";
|
|
23
32
|
// Evidence-bundle verification (specs/evidence-bundle.md): the signed
|
|
24
33
|
// sanning.evidence/v1 wrapper carrying the sanning.anchor.trace/v3 body. The CLI
|
|
@@ -67,7 +76,7 @@ export { PACK_GRADE_CAUSE_KINDS, PACK_VERDICTS, accountDisclosure, completenessN
|
|
|
67
76
|
// Pure: data in, data out, no I/O. `gradePack` takes the result as an
|
|
68
77
|
// optional fourth argument, so a surface gets one verdict; omitting it is the
|
|
69
78
|
// pre-§5.4 behavior, unchanged. Additive: no existing export changes.
|
|
70
|
-
export { DECLARATION_CONTENT_KINDS, DECLARATION_DEVIATION_KINDS, DECLARATION_NOTE_KINDS, DECLARATION_ROLES, DECLARATION_VERDICTS, DECLARATION_VERSION, DECLARATION_VERSION_V2, DECLARATION_VERSIONS, checkDeclaration, declarationClaims, packRecords, renderContentFinding, renderDeclarationSummary, renderDeviation, renderNote, } from "./declaration.js";
|
|
79
|
+
export { DECLARATION_CONTENT_KINDS, DECLARATION_DEVIATION_KINDS, DECLARATION_NOTE_KINDS, DECLARATION_ROLES, DECLARATION_VERDICTS, DECLARATION_VERSION, DECLARATION_VERSION_V2, DECLARATION_VERSION_V3, DECLARATION_VERSIONS, checkDeclaration, declarationClaims, packRecords, renderContentFinding, renderDeclarationSummary, renderDeviation, renderNote, } from "./declaration.js";
|
|
71
80
|
// The case (src/case.ts): one verdict over SEVERAL packs, across organizations
|
|
72
81
|
// (anchor#198). The layer above the declaration, and the closure for what a
|
|
73
82
|
// declaration cannot reach.
|
|
@@ -126,20 +135,27 @@ export { FILE_MATCH_SCOPE, NOT_READ_REASONS, SKIPPED_REASONS, fileMatchToJson, m
|
|
|
126
135
|
// `vectors/chain-reading.json` beside the pack-grading table for the same
|
|
127
136
|
// reason: a rule consumers must agree with needs a statement they can fetch.
|
|
128
137
|
//
|
|
129
|
-
// It returns FINDINGS, never a verdict, and it feeds no status
|
|
138
|
+
// It returns FINDINGS, never a verdict, and it feeds no status on its own: a
|
|
139
|
+
// pack's signed v3 declaration can claim a chain complete and in order, and
|
|
140
|
+
// `checkDeclaration` holds that claim to the links `readChainLinks` reads
|
|
141
|
+
// (evidence-bundle.md 5.4.2 rule 11). Chain links are
|
|
130
142
|
// deletion/reorder-evidence for the events present and NOT a completeness proof
|
|
131
143
|
// (`anchor/docs/profile-sanning.events-v2.md` §5), drop the last N events of a
|
|
132
144
|
// chain and nothing dangles. `CHAIN_READING_SCOPE` is that sentence, exported so
|
|
133
145
|
// every surface prints the same limit rather than paraphrasing it into a claim.
|
|
134
146
|
// Additive — no existing export changes.
|
|
135
|
-
export { ADAPTER_CHAIN_NAMESPACES, CHAIN_READING_SCOPE, readChains, renderChainFinding, } from "./chain.js";
|
|
147
|
+
export { ADAPTER_CHAIN_NAMESPACES, CHAIN_READING_SCOPE, readChainLinks, readChains, renderChainFinding, } from "./chain.js";
|
|
136
148
|
// The `proof export` composer (specs/evidence-export.md §5, phase 2): produce a
|
|
137
149
|
// signed, offline-verifiable sanning.evidence.export/v2 artifact from a source
|
|
138
150
|
// anchor-trace bundle + operator attestations + an exporter Ed25519 key. The
|
|
139
151
|
// inverse of verifyEvidenceBundle's verifyExportBody dispatch.
|
|
140
152
|
// One exit-code table for every verb (0.13.0): the verdict word to the exit
|
|
141
153
|
// code, and the help text every verb prints. Additive.
|
|
142
|
-
export { EXIT_CODES, EXIT_CODES_HELP, EXIT_FAILED, EXIT_MALFORMED, EXIT_MIXED, EXIT_UNDETERMINED, EXIT_VERIFIED, exitCodeFor, } from "./exit-codes.js";
|
|
154
|
+
export { EXIT_CODES, EXIT_CODES_HELP, EXIT_FAILED, EXIT_MALFORMED, EXIT_MIXED, EXIT_SANDBOX, EXIT_UNDETERMINED, EXIT_VERIFIED, exitCodeFor, sandboxExit, } from "./exit-codes.js";
|
|
155
|
+
// Sandbox evidence: the environment marker over the envelopes a pack or case
|
|
156
|
+
// holds (envelope-spec §2, the `environment_marker` MAY), and the headline and
|
|
157
|
+
// line both commands print for it. Additive.
|
|
158
|
+
export { SANDBOX_HEADLINE, SANDBOX_LINE, SANDBOX_TITLE, environmentMarker, onlySimulatedUnsettled, packEnvelopes, } from "./environment.js";
|
|
143
159
|
export { attestationSignatureToHex, composeExport } from "./compose.js";
|
|
144
160
|
// Agent inclusion-proof bundle verification: the
|
|
145
161
|
// sanning.agent.proof/v1 bundle. The CLI sniffs spec_version and routes here so
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type EnclaveAdapter } from "./run.js";
|
|
2
|
+
/** Import a module by name. A parameter so a test can watch what is asked for. */
|
|
3
|
+
export type Importer = (name: string) => Promise<unknown>;
|
|
4
|
+
/**
|
|
5
|
+
* The adapters this environment holds, loaded from `ADAPTER_MODULES` and
|
|
6
|
+
* nothing else. A module counts only when it exports the provider it was
|
|
7
|
+
* loaded for as `provider`, a `check` function, and the failure kinds it
|
|
8
|
+
* declares as `kinds` (`declaredKinds`).
|
|
9
|
+
*/
|
|
10
|
+
export declare function loadInstalledAdapters(importer?: Importer): Promise<Map<string, EnclaveAdapter>>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Loading the enclave attestation adapters a reader has installed. Kept out of
|
|
2
|
+
// `index.ts` on purpose: it imports packages by name, which a browser bundle
|
|
3
|
+
// cannot resolve, and only the command line needs it. `run.ts` imports nothing.
|
|
4
|
+
//
|
|
5
|
+
// The packages are named by `ADAPTER_MODULES` and by nothing else: a provider
|
|
6
|
+
// id read from a pack is never turned into a module name.
|
|
7
|
+
import { ADAPTER_MODULES, declaredKinds } from "./run.js";
|
|
8
|
+
const dynamicImport = (name) => import(/* @vite-ignore */ name);
|
|
9
|
+
/**
|
|
10
|
+
* The adapters this environment holds, loaded from `ADAPTER_MODULES` and
|
|
11
|
+
* nothing else. A module counts only when it exports the provider it was
|
|
12
|
+
* loaded for as `provider`, a `check` function, and the failure kinds it
|
|
13
|
+
* declares as `kinds` (`declaredKinds`).
|
|
14
|
+
*/
|
|
15
|
+
export async function loadInstalledAdapters(importer = dynamicImport) {
|
|
16
|
+
const found = new Map();
|
|
17
|
+
for (const [provider, name] of Object.entries(ADAPTER_MODULES)) {
|
|
18
|
+
let module;
|
|
19
|
+
try {
|
|
20
|
+
module = await importer(name);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const m = module;
|
|
26
|
+
if (m !== null &&
|
|
27
|
+
typeof m === "object" &&
|
|
28
|
+
m.provider === provider &&
|
|
29
|
+
typeof m.check === "function" &&
|
|
30
|
+
declaredKinds(m) !== null) {
|
|
31
|
+
found.set(provider, m);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return found;
|
|
35
|
+
}
|
package/dist/run.d.ts
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { type SideContentMap } from "./side-content.js";
|
|
2
|
+
export declare const ATTESTATION_VERSION = "sanning.enclave-attestation/v1";
|
|
3
|
+
export declare const BINDING_VERSION = "sanning.run-binding/v1";
|
|
4
|
+
export declare const POLICY_VERSION = "sanning.enclave-policy/v1";
|
|
5
|
+
export declare const MANIFEST_VERSION = "sanning.run-manifest/v1";
|
|
6
|
+
export declare const RUN_OPENED = "runner.run_opened";
|
|
7
|
+
export declare const RUN_CLOSED = "runner.run_closed";
|
|
8
|
+
export declare const PROVIDER_GCP = "gcp-confidential-space";
|
|
9
|
+
export declare const PROVIDER_FLARE = "flare-fcc";
|
|
10
|
+
/**
|
|
11
|
+
* The fixed table: provider id to the package that answers for it. A provider
|
|
12
|
+
* id read from a pack is looked up HERE and nowhere else, so a pack naming `os`
|
|
13
|
+
* or `../x` loads nothing.
|
|
14
|
+
*/
|
|
15
|
+
export declare const ADAPTER_MODULES: Readonly<Record<string, string>>;
|
|
16
|
+
/** Printed after an enclave line whose token was checked. Never a state. */
|
|
17
|
+
export declare const REVOCATION_SENTENCE: string;
|
|
18
|
+
export declare const ENCLAVE_STATES: readonly ["confirmed", "differs", "not_checked"];
|
|
19
|
+
export declare const RUN_ACCOUNT_STATES: readonly ["closed", "differs", "not_closed"];
|
|
20
|
+
/** Why an enclave line reads `not_checked`. */
|
|
21
|
+
export declare const ENCLAVE_NOT_CHECKED_KINDS: readonly ["no_adapter", "no_attestation", "unknown_version", "no_policy", "policy_unreadable", "adapter_failed", "no_opening_record"];
|
|
22
|
+
/** The provider-neutral checks that make a line `differs`, in line order. */
|
|
23
|
+
export declare const ENCLAVE_DIFFERS_KINDS: readonly ["attestation_malformed", "subject_key_not_signer", "manifest_not_content", "binding_other_run", "binding_other_manifest", "binding_other_keys", "signed_at_outside_tolerance", "manifest_content_mismatch", "manifest_unreadable", "case_hash_differs", "agent_record_under_runner_key"];
|
|
24
|
+
/** The kinds an adapter may answer with; any other reads `adapter_failed`. */
|
|
25
|
+
export declare const ENCLAVE_NOTE_KINDS: readonly ["no_issue_time", "manifest_withheld", "stamp_unwitnessed"];
|
|
26
|
+
/**
|
|
27
|
+
* Every kind and note the kernel itself names. An adapter declares its own
|
|
28
|
+
* failure kinds (its `kinds`, section 9); none of them may be one of these, so
|
|
29
|
+
* an adapter can never speak for a neutral check.
|
|
30
|
+
*/
|
|
31
|
+
export declare const NEUTRAL_KINDS: ReadonlySet<string>;
|
|
32
|
+
export declare const ACCOUNT_FINDING_KINDS: readonly ["record_not_listed", "listed_record_absent", "more_than_one_closing_record", "closing_malformed"];
|
|
33
|
+
/**
|
|
34
|
+
* Why the online line (`flare-fcc` only, section 8) reads `not_checked`:
|
|
35
|
+
* nothing was decided. `adapter_failed` is the kernel's.
|
|
36
|
+
*/
|
|
37
|
+
export declare const ONLINE_NOT_CHECKED_KINDS: readonly ["adapter_failed", "evidence_not_confirmed", "no_contracts", "manifest_withheld", "manifest_unreadable", "chain_unavailable", "not_final"];
|
|
38
|
+
/** Why the online line reads `differs`: the chain answered, and it does not match. */
|
|
39
|
+
export declare const ONLINE_DIFFERS_KINDS: readonly ["instruction_count", "instruction_other_extension", "instruction_other_machine", "instruction_other_operation", "instruction_other_message", "transaction_failed", "log_malformed", "run_opened_differs", "run_opened_count", "machine_not_production", "machine_other_extension", "code_not_supported", "call_reverted"];
|
|
40
|
+
export declare const ACCOUNT_NOTE_KINDS: readonly ["agent_key_unknown", "runner_record_under_agent_key", "runner_record_bytes_withheld", "payload_hashes_absent", "unacknowledged_record_absent"];
|
|
41
|
+
/**
|
|
42
|
+
* Whether `s`, the text between a host's brackets, is an IPv6 address as the
|
|
43
|
+
* WHATWG URL Standard's IPv6 parser accepts one (RFC 4291 text form), in
|
|
44
|
+
* lowercase. A step for step port of the parser, the twin of Python's
|
|
45
|
+
* `is_ipv6_text` and the runner's `run.IsPlaneOrigin`.
|
|
46
|
+
*/
|
|
47
|
+
export declare function isIpv6Text(s: string): boolean;
|
|
48
|
+
/** The object does not read under the one spelling. The message is the reason. */
|
|
49
|
+
export declare class AttestationRefused extends Error {
|
|
50
|
+
}
|
|
51
|
+
/** `attestation_version` is a string this reader does not know. */
|
|
52
|
+
export declare class UnknownAttestationVersion extends AttestationRefused {
|
|
53
|
+
}
|
|
54
|
+
/** `sanning.run-binding/v1`, read strictly from the evidence. */
|
|
55
|
+
export interface Binding {
|
|
56
|
+
runId: string;
|
|
57
|
+
manifestHash: string;
|
|
58
|
+
runnerPublicKey: string;
|
|
59
|
+
agentPublicKey: string;
|
|
60
|
+
credentialPublicKey: string;
|
|
61
|
+
caseHash: string;
|
|
62
|
+
/**
|
|
63
|
+
* The plane's origin the runner claimed the run from (section 4). Carried,
|
|
64
|
+
* not compared: the plane refuses a claim whose binding names another plane.
|
|
65
|
+
*/
|
|
66
|
+
plane: string;
|
|
67
|
+
request: Readonly<Record<string, unknown>>;
|
|
68
|
+
}
|
|
69
|
+
/** `sanning.enclave-attestation/v1`, read strictly. */
|
|
70
|
+
export interface Attestation {
|
|
71
|
+
runnerPublicKey: string;
|
|
72
|
+
agentPublicKey: string;
|
|
73
|
+
manifestHash: string;
|
|
74
|
+
runId: string;
|
|
75
|
+
provider: string;
|
|
76
|
+
evidence: Readonly<Record<string, unknown>>;
|
|
77
|
+
/** The binding the evidence carries, for a registered provider; else null. */
|
|
78
|
+
binding: Binding | null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Read the `enclave_attestation` member of an opening record strictly. Throws
|
|
82
|
+
* `UnknownAttestationVersion` for a version string this reader does not know,
|
|
83
|
+
* and `AttestationRefused` for anything else that is not the one spelling.
|
|
84
|
+
*/
|
|
85
|
+
export declare function readAttestation(value: unknown): Attestation;
|
|
86
|
+
/** `readAttestation` over bytes that must be `JCS(object)`. */
|
|
87
|
+
export declare function readAttestationJson(raw: Uint8Array): Attestation;
|
|
88
|
+
/**
|
|
89
|
+
* What an adapter answers (checks 2 to 6 and 8). `binding` is the binding the
|
|
90
|
+
* adapter verified its evidence commits to: `confirmed` without one is outside
|
|
91
|
+
* the contract and reads `adapter_failed`, because the kernel runs checks 7
|
|
92
|
+
* and 11 on that binding. Each kind is one the adapter declares in `kinds`.
|
|
93
|
+
*/
|
|
94
|
+
export interface AdapterResult {
|
|
95
|
+
state: (typeof ENCLAVE_STATES)[number];
|
|
96
|
+
kinds?: readonly string[];
|
|
97
|
+
/** The verified token's issue time, seconds since the epoch, or null. */
|
|
98
|
+
issuedAt?: number | null;
|
|
99
|
+
imageId?: string | null;
|
|
100
|
+
hwModel?: string | null;
|
|
101
|
+
tokenChecked?: boolean;
|
|
102
|
+
binding?: Binding | null;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* An adapter: the provider it answers for, the failure kinds it declares, its
|
|
106
|
+
* check, and optionally the online line.
|
|
107
|
+
*/
|
|
108
|
+
export interface EnclaveAdapter {
|
|
109
|
+
provider: string;
|
|
110
|
+
kinds: readonly string[];
|
|
111
|
+
check(attestation: Attestation, options: {
|
|
112
|
+
policy: Readonly<Record<string, unknown>>;
|
|
113
|
+
at: string | null;
|
|
114
|
+
}): AdapterResult | Promise<AdapterResult>;
|
|
115
|
+
online?(attestation: Attestation, options: {
|
|
116
|
+
policy: Readonly<Record<string, unknown>>;
|
|
117
|
+
at: string | null;
|
|
118
|
+
manifest: Uint8Array | null;
|
|
119
|
+
rpc: string;
|
|
120
|
+
}): OnlineLine | Promise<OnlineLine>;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The online line (section 8): what the chain says of a `flare-fcc` opening,
|
|
124
|
+
* read by the adapter at the offline line's evaluation time. `confirmed`
|
|
125
|
+
* carries no kind; `not_checked` and `differs` carry one. It moves nothing.
|
|
126
|
+
*/
|
|
127
|
+
export interface OnlineLine {
|
|
128
|
+
state: (typeof ENCLAVE_STATES)[number];
|
|
129
|
+
kinds: string[];
|
|
130
|
+
}
|
|
131
|
+
export interface EnclaveLine {
|
|
132
|
+
state: (typeof ENCLAVE_STATES)[number];
|
|
133
|
+
kinds: string[];
|
|
134
|
+
notes: string[];
|
|
135
|
+
reason: string | null;
|
|
136
|
+
provider: string | null;
|
|
137
|
+
evaluatedAt: string | null;
|
|
138
|
+
evaluation: "stamp" | "token_issue_time" | null;
|
|
139
|
+
tokenChecked: boolean;
|
|
140
|
+
}
|
|
141
|
+
export interface AccountEntry {
|
|
142
|
+
kind: string;
|
|
143
|
+
eventId: string | null;
|
|
144
|
+
}
|
|
145
|
+
export interface RunAccountLine {
|
|
146
|
+
state: (typeof RUN_ACCOUNT_STATES)[number];
|
|
147
|
+
findings: AccountEntry[];
|
|
148
|
+
notes: AccountEntry[];
|
|
149
|
+
closingEventId: string | null;
|
|
150
|
+
reason: string | null;
|
|
151
|
+
}
|
|
152
|
+
export interface RunReading {
|
|
153
|
+
/** The pack by the reader's name for it; two packs can share one (A43). */
|
|
154
|
+
packRef: string;
|
|
155
|
+
/** The pack's position among the packs read, as the case reading's `pack_index`. */
|
|
156
|
+
packIndex: number;
|
|
157
|
+
eventId: string;
|
|
158
|
+
runnerPublicKey: string;
|
|
159
|
+
agentPublicKey: string | null;
|
|
160
|
+
enclave: EnclaveLine;
|
|
161
|
+
account: RunAccountLine;
|
|
162
|
+
/** The online line, where the reader asked for one and the adapter reads the chain; else null. */
|
|
163
|
+
online: OnlineLine | null;
|
|
164
|
+
}
|
|
165
|
+
export interface RunsReading {
|
|
166
|
+
runs: RunReading[];
|
|
167
|
+
}
|
|
168
|
+
/** One pack, as `readCase` takes it. */
|
|
169
|
+
export interface RunPack {
|
|
170
|
+
ref: string;
|
|
171
|
+
bundle: unknown;
|
|
172
|
+
content?: SideContentMap | null;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* The time the token is evaluated at (7): the interval end of a stamp that
|
|
176
|
+
* holds the opening record and whose witness the reader's lookup confirmed;
|
|
177
|
+
* otherwise null, the token's own issue time.
|
|
178
|
+
*/
|
|
179
|
+
/**
|
|
180
|
+
* @internal For the kernel's own tests: the enclave line of one opening record,
|
|
181
|
+
* verified as the caller says, under a provider table the caller names. It is
|
|
182
|
+
* how a test reaches a provider outside `ADAPTER_MODULES`; `readRuns` always
|
|
183
|
+
* reads under `ADAPTER_MODULES`.
|
|
184
|
+
*/
|
|
185
|
+
export declare function enclaveLineForTest(record: Record<string, unknown>, publicKey: string, content: Uint8Array | null, policy: unknown, adapters: ReadonlyMap<string, EnclaveAdapter>, table: Readonly<Record<string, string>>): Promise<EnclaveLine>;
|
|
186
|
+
/**
|
|
187
|
+
* The failure kinds an adapter declares as its `kinds`: an array of snake_case
|
|
188
|
+
* strings, at least one, none of them a kind or note the kernel names
|
|
189
|
+
* (`NEUTRAL_KINDS`). `null` where the declaration is not of that form, an
|
|
190
|
+
* empty one included, and then the adapter is not loaded.
|
|
191
|
+
*/
|
|
192
|
+
export declare function declaredKinds(adapter: unknown): ReadonlySet<string> | null;
|
|
193
|
+
export declare function readRuns(packs: readonly RunPack[], options?: {
|
|
194
|
+
policy?: unknown;
|
|
195
|
+
adapters?: ReadonlyMap<string, EnclaveAdapter> | null;
|
|
196
|
+
/** A chain endpoint for the online line, handed to an adapter that reads one. */
|
|
197
|
+
rpc?: string | null;
|
|
198
|
+
/**
|
|
199
|
+
* For each pack by position, the `stamp_ref` of every stamp whose witness
|
|
200
|
+
* the caller looked up and the public record confirmed (the on-chain
|
|
201
|
+
* half's `confirm`). A token is evaluated at a stamp's interval end only
|
|
202
|
+
* there, and at its own issue time otherwise. Absent: no lookup.
|
|
203
|
+
*/
|
|
204
|
+
witnessed?: readonly (readonly string[] | null | undefined)[] | null;
|
|
205
|
+
}): Promise<RunsReading>;
|
|
206
|
+
/** The enclave line, the revocation sentence where a token was checked, and the online line. */
|
|
207
|
+
export declare function renderEnclaveLines(r: RunReading): string[];
|
|
208
|
+
/** The run-account line (specs/run-records.md). */
|
|
209
|
+
export declare function renderAccountLine(r: RunReading): string;
|