@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/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
- onChainChecked,
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
@@ -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;
@@ -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 { bytesToHex, deriveOperatorAddress, ed25519Verify, hexToBytes, sha256Bytes, sha256Hex, utf8, verifyRsaPssSha256, } from "./crypto.js";
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
- export { bytesToHex, deriveOperatorAddress, ed25519Verify, hexToBytes, sha256Bytes, sha256Hex, utf8, verifyRsaPssSha256, } from "./crypto.js";
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. Chain links are
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;