@colophon-claims/verify 0.2.0 → 0.2.1
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 +18 -8
- package/dist/admission/contracts.d.ts +241 -0
- package/dist/admission/contracts.js +116 -0
- package/dist/admission/index.d.ts +2 -0
- package/dist/admission/index.js +2 -0
- package/dist/admission/prompted-commitment.d.ts +19 -0
- package/dist/admission/prompted-commitment.js +52 -0
- package/dist/admission/prompted-selection.d.ts +24 -0
- package/dist/admission/prompted-selection.js +85 -0
- package/dist/admission/verification.d.ts +1 -0
- package/dist/admission/verification.js +88 -42
- package/dist/assets.d.ts +21 -1
- package/dist/assets.js +60 -3
- package/dist/binding/beacon-binding.d.ts +230 -0
- package/dist/binding/beacon-binding.js +325 -0
- package/dist/binding/report-face.d.ts +45 -0
- package/dist/binding/report-face.js +153 -0
- package/dist/cli.js +74 -12
- package/dist/index.d.ts +14 -3
- package/dist/index.js +16 -3
- package/dist/manifest.d.ts +30 -4
- package/dist/manifest.js +30 -0
- package/dist/materialize.d.ts +7 -0
- package/dist/materialize.js +7 -0
- package/dist/outcome.d.ts +31 -0
- package/dist/outcome.js +45 -0
- package/dist/profile/claim-consistency.d.ts +8 -1
- package/dist/profile/claim-consistency.js +4 -4
- package/dist/profile/claim.d.ts +201 -2
- package/dist/profile/claim.js +178 -47
- package/dist/profile/disclosure.d.ts +273 -0
- package/dist/profile/disclosure.js +240 -0
- package/dist/profile/run-results.d.ts +8 -2
- package/dist/profile/run-results.js +9 -3
- package/dist/profile/task-selection.d.ts +69 -0
- package/dist/profile/task-selection.js +140 -0
- package/dist/reader-instructions.d.ts +38 -1
- package/dist/reader-instructions.js +42 -2
- package/dist/schema.d.ts +4 -3
- package/dist/schema.js +17 -0
- package/dist/signers.d.ts +48 -0
- package/dist/signers.js +77 -0
- package/dist/verify.d.ts +20 -6
- package/dist/verify.js +156 -31
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +14 -14
package/dist/schema.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export declare const BUNDLE_ASSEMBLY_FORMAT: "benchmark-product-assembly/2";
|
|
|
6
6
|
export declare const BUNDLE_V4_TRUST_FORMAT: "benchmark-product-public-trust/4";
|
|
7
7
|
export declare const BUNDLE_V4_EVIDENCE_FORMAT: "benchmark-product-evidence-catalog/4";
|
|
8
8
|
export declare const BUNDLE_QUALIFICATION_FORMAT: "benchmark-product-binary-qualification/1";
|
|
9
|
-
export declare const BUNDLE_V4_EVIDENCE_ROLES: readonly ["task", "runtime-selection", "evaluation-spec", "admission-receipt", "solve-submission", "run-pinning-evidence", "evaluation-submission", "solve-delivery", "solve-output", "evaluation-task", "evaluation-delivery", "verdict", "item-bank", "source-manifest", "admission-index", "admission-manifest", "replacement-ledger", "source-item", "judge-instrument", "analysis-context", "label-resolution", "human-review-evaluation-spec", "human-review-form", "human-review-packet", "human-review-response", "human-review-verdict", "reviewer-roster", "review-visibility-receipt", "review-reveal-receipt", "operator-assertion", "snapshot-probe", "screening-table", "screening-reveal-receipt", "screening-instrument", "screening-sampling-script", "screening-raw-outputs", "screening-prompt", "screening-procedure", "screening-pool", "screening-sample-commitment", "screening-transcript"];
|
|
9
|
+
export declare const BUNDLE_V4_EVIDENCE_ROLES: readonly ["task", "runtime-selection", "evaluation-spec", "admission-receipt", "solve-submission", "run-pinning-evidence", "evaluation-submission", "solve-delivery", "solve-output", "evaluation-task", "evaluation-delivery", "verdict", "item-bank", "source-manifest", "admission-index", "admission-manifest", "replacement-ledger", "source-item", "judge-instrument", "analysis-context", "label-resolution", "human-review-evaluation-spec", "human-review-form", "human-review-packet", "human-review-response", "human-review-verdict", "reviewer-roster", "review-visibility-receipt", "review-reveal-receipt", "operator-assertion", "snapshot-probe", "screening-table", "screening-reveal-receipt", "screening-instrument", "screening-sampling-script", "screening-raw-outputs", "screening-prompt", "screening-procedure", "screening-pool", "screening-sample-commitment", "screening-transcript", "disclosure-specification"];
|
|
10
10
|
export type BundleV4EvidenceRole = (typeof BUNDLE_V4_EVIDENCE_ROLES)[number];
|
|
11
11
|
export declare const BUNDLE_V4_ADMISSION_EVIDENCE_ROLES: readonly ["admission-manifest", "replacement-ledger", "source-item", "label-resolution", "analysis-context", "human-review-evaluation-spec", "human-review-form", "human-review-packet", "human-review-response", "human-review-verdict", "reviewer-roster", "review-visibility-receipt", "review-reveal-receipt", "operator-assertion", "screening-table", "screening-reveal-receipt", "screening-instrument", "screening-sampling-script", "screening-raw-outputs", "screening-prompt", "screening-procedure", "screening-pool", "screening-sample-commitment", "screening-transcript"];
|
|
12
12
|
export declare const BundleTrustSchema: z.ZodObject<{
|
|
@@ -76,7 +76,6 @@ export declare const BundleEvidenceCatalogSchema: z.ZodObject<{
|
|
|
76
76
|
records: z.ZodArray<z.ZodObject<{
|
|
77
77
|
sha256: z.ZodString;
|
|
78
78
|
roles: z.ZodArray<z.ZodEnum<{
|
|
79
|
-
verdict: "verdict";
|
|
80
79
|
task: "task";
|
|
81
80
|
"runtime-selection": "runtime-selection";
|
|
82
81
|
"evaluation-spec": "evaluation-spec";
|
|
@@ -88,6 +87,7 @@ export declare const BundleEvidenceCatalogSchema: z.ZodObject<{
|
|
|
88
87
|
"solve-output": "solve-output";
|
|
89
88
|
"evaluation-task": "evaluation-task";
|
|
90
89
|
"evaluation-delivery": "evaluation-delivery";
|
|
90
|
+
verdict: "verdict";
|
|
91
91
|
"judge-instrument": "judge-instrument";
|
|
92
92
|
"analysis-context": "analysis-context";
|
|
93
93
|
"label-resolution": "label-resolution";
|
|
@@ -100,7 +100,7 @@ export declare const BundleV4EvidenceCatalogSchema: z.ZodObject<{
|
|
|
100
100
|
records: z.ZodArray<z.ZodObject<{
|
|
101
101
|
sha256: z.ZodString;
|
|
102
102
|
roles: z.ZodArray<z.ZodEnum<{
|
|
103
|
-
|
|
103
|
+
"disclosure-specification": "disclosure-specification";
|
|
104
104
|
task: "task";
|
|
105
105
|
"runtime-selection": "runtime-selection";
|
|
106
106
|
"evaluation-spec": "evaluation-spec";
|
|
@@ -112,6 +112,7 @@ export declare const BundleV4EvidenceCatalogSchema: z.ZodObject<{
|
|
|
112
112
|
"solve-output": "solve-output";
|
|
113
113
|
"evaluation-task": "evaluation-task";
|
|
114
114
|
"evaluation-delivery": "evaluation-delivery";
|
|
115
|
+
verdict: "verdict";
|
|
115
116
|
"item-bank": "item-bank";
|
|
116
117
|
"source-manifest": "source-manifest";
|
|
117
118
|
"admission-index": "admission-index";
|
package/dist/schema.js
CHANGED
|
@@ -57,6 +57,17 @@ export const BUNDLE_V4_EVIDENCE_ROLES = [
|
|
|
57
57
|
"screening-pool",
|
|
58
58
|
"screening-sample-commitment",
|
|
59
59
|
"screening-transcript",
|
|
60
|
+
// Appended at the very end (disclosure-specification-record design §6.2, issue #2839). Appending
|
|
61
|
+
// is the ONLY additive move available here: this array's index order is the frozen role-ordering
|
|
62
|
+
// map used by both the catalog schema's ordering refinement and the bundle writer, so inserting
|
|
63
|
+
// anywhere earlier would re-order existing bundles' role arrays and move their bytes. The /2
|
|
64
|
+
// catalog is a SEPARATE constant (`BUNDLE_EVIDENCE_ROLES` below) and is untouched by this append.
|
|
65
|
+
//
|
|
66
|
+
// The token is admitted on every v4-graph closure, because the enum is one shared constant and
|
|
67
|
+
// there is no per-closure role vocabulary. What keeps a disclosure record off an earlier closure
|
|
68
|
+
// is that nothing DERIVES the role there: off `/8` the Report extension is never read, so the
|
|
69
|
+
// evidence closure's own size and per-digest guards refuse the record as unreachable (§6.5.2).
|
|
70
|
+
"disclosure-specification",
|
|
60
71
|
];
|
|
61
72
|
export const BUNDLE_V4_ADMISSION_EVIDENCE_ROLES = [
|
|
62
73
|
"admission-manifest", "replacement-ledger", "source-item", "label-resolution",
|
|
@@ -215,6 +226,12 @@ const PrefixedSha256Schema = z.string().regex(/^sha256:[a-f0-9]{64}$/u);
|
|
|
215
226
|
const IDENTIFIER_NAME = /^[A-Za-z][A-Za-z0-9._-]{0,63}$/u;
|
|
216
227
|
export const BundleQualificationSchema = z.strictObject({
|
|
217
228
|
format: z.literal(BUNDLE_QUALIFICATION_FORMAT),
|
|
229
|
+
// Deliberately NOT widened when a later closure allocates a new claim id (issue #3205's
|
|
230
|
+
// claim-package/5; the same resolution the disclosure-record design reached in its §6.5.1).
|
|
231
|
+
// This field names WHICH CLAIM PROJECTION SHAPE the qualification graph was built for, and the
|
|
232
|
+
// anchors section changes nothing about that graph: the qualification projection under /5 is
|
|
233
|
+
// byte-identical to the one under /2. Widening the literal would make this schema co-vary with
|
|
234
|
+
// an unrelated section, and would need widening again for every future closure.
|
|
218
235
|
claimSchema: z.literal("benchmark-product.claim-package/2"),
|
|
219
236
|
sourceManifestSha256: PrefixedSha256Schema,
|
|
220
237
|
admissionManifestSha256: PrefixedSha256Schema,
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { BundleTrust, BundleV4Trust } from "./schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* Who signed, in reader terms. The bundle's own identifiers select signatures and join records,
|
|
4
|
+
* so they stay exact on the machine surface; the human surface is given the role instead
|
|
5
|
+
* (issue #3024).
|
|
6
|
+
*/
|
|
7
|
+
export type PublicBundleSignerRole = "publisher" | "automated-grader" | "human-reviewer" | "label-admission";
|
|
8
|
+
export interface PublicBundleSigner {
|
|
9
|
+
readonly role: PublicBundleSignerRole;
|
|
10
|
+
/** The load-bearing signer identity, verbatim. Machine surface only. */
|
|
11
|
+
readonly identity: string;
|
|
12
|
+
/** The exact key the signature selection resolved to. Machine surface only. */
|
|
13
|
+
readonly keyId: string;
|
|
14
|
+
/**
|
|
15
|
+
* `same-operator` where the bundle itself declares that the key is workspace-minted under the
|
|
16
|
+
* publisher's own custody; `undeclared` where it makes no custody statement. Never a claim that
|
|
17
|
+
* a signer is an independent party -- no bundle format can establish that.
|
|
18
|
+
*/
|
|
19
|
+
readonly custody: "same-operator" | "undeclared";
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Signers of a v2/v4/v6/v7 bundle, read from its already-authenticated `trust/public-keys.json`
|
|
23
|
+
* and the Matrix verdict closure the `trust` check validated it against.
|
|
24
|
+
*
|
|
25
|
+
* Every group this returns is ground-truthed rather than merely declared: `trust.evaluators` is
|
|
26
|
+
* pinned to exactly the union of the Matrix-referenced evaluators and the admission reviewers, and
|
|
27
|
+
* each reviewer binding to the authenticated signed review closure. That union is why the two roles
|
|
28
|
+
* are read from the two sets separately -- an identity that both graded cells and signed reviews is
|
|
29
|
+
* in both, and classifying reviewer-first would print one fewer grader than actually graded. Both
|
|
30
|
+
* trust grammars pin `selfRun.custody: "workspace-minted"` and `partyIndependence:
|
|
31
|
+
* "not-established"`, so same-operator custody is a fact of the parsed record, not an inference.
|
|
32
|
+
*
|
|
33
|
+
* Admission authorities are deliberately absent: the v4 grammar pins every authority keyId to the
|
|
34
|
+
* report key, so listing them would count the publisher's one key twice under two headings.
|
|
35
|
+
*/
|
|
36
|
+
export declare function legacyBundleSigners(trust: BundleTrust | BundleV4Trust, verdictEvaluators: ReadonlySet<string>): readonly PublicBundleSigner[];
|
|
37
|
+
/**
|
|
38
|
+
* Signers of a v5 evidence-native bundle, read from the same authenticated `claim-package.json`
|
|
39
|
+
* bytes the closure verified.
|
|
40
|
+
*
|
|
41
|
+
* `claim.trust.signers` is a publisher-written declaration used by the closure only as a lookup
|
|
42
|
+
* table: a surplus entry there is never contradicted, because no signature ever selects it. So this
|
|
43
|
+
* keeps only the keys that actually carried a signature the closure accepted
|
|
44
|
+
* (`verifiedSignerKeyIds`). Without that filter a bundle could declare a human reviewer, or a dozen
|
|
45
|
+
* graders, that signed nothing and have the checker print them as fact. The claim package declares
|
|
46
|
+
* no custody, so nothing here upgrades a signer to same-operator either.
|
|
47
|
+
*/
|
|
48
|
+
export declare function evidenceNativeBundleSigners(claimPackageBytes: Uint8Array, verifiedSignerKeyIds: readonly string[]): readonly PublicBundleSigner[];
|
package/dist/signers.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { parseEvidenceNativeClaimPackageV3 } from "@jinn-network/benchmarking-protocol";
|
|
2
|
+
function deduplicate(signers) {
|
|
3
|
+
const seen = new Set();
|
|
4
|
+
return signers.filter((signer) => {
|
|
5
|
+
const key = `${signer.role} ${signer.keyId}`;
|
|
6
|
+
if (seen.has(key))
|
|
7
|
+
return false;
|
|
8
|
+
seen.add(key);
|
|
9
|
+
return true;
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Signers of a v2/v4/v6/v7 bundle, read from its already-authenticated `trust/public-keys.json`
|
|
14
|
+
* and the Matrix verdict closure the `trust` check validated it against.
|
|
15
|
+
*
|
|
16
|
+
* Every group this returns is ground-truthed rather than merely declared: `trust.evaluators` is
|
|
17
|
+
* pinned to exactly the union of the Matrix-referenced evaluators and the admission reviewers, and
|
|
18
|
+
* each reviewer binding to the authenticated signed review closure. That union is why the two roles
|
|
19
|
+
* are read from the two sets separately -- an identity that both graded cells and signed reviews is
|
|
20
|
+
* in both, and classifying reviewer-first would print one fewer grader than actually graded. Both
|
|
21
|
+
* trust grammars pin `selfRun.custody: "workspace-minted"` and `partyIndependence:
|
|
22
|
+
* "not-established"`, so same-operator custody is a fact of the parsed record, not an inference.
|
|
23
|
+
*
|
|
24
|
+
* Admission authorities are deliberately absent: the v4 grammar pins every authority keyId to the
|
|
25
|
+
* report key, so listing them would count the publisher's one key twice under two headings.
|
|
26
|
+
*/
|
|
27
|
+
export function legacyBundleSigners(trust, verdictEvaluators) {
|
|
28
|
+
const reviewers = new Set("admission" in trust ? trust.admission.reviewers.map((entry) => entry.evaluator) : []);
|
|
29
|
+
return deduplicate([
|
|
30
|
+
{ role: "publisher", identity: trust.report.author, keyId: trust.report.keyId, custody: "same-operator" },
|
|
31
|
+
...trust.evaluators.flatMap((entry) => {
|
|
32
|
+
const roles = [];
|
|
33
|
+
// The trust set equals verdicts + reviewers, so "in neither" is unreachable; if a future
|
|
34
|
+
// widening makes it reachable, a signer must still be shown rather than silently dropped.
|
|
35
|
+
if (verdictEvaluators.has(entry.evaluator) || !reviewers.has(entry.evaluator))
|
|
36
|
+
roles.push("automated-grader");
|
|
37
|
+
if (reviewers.has(entry.evaluator))
|
|
38
|
+
roles.push("human-reviewer");
|
|
39
|
+
return roles.map((role) => ({
|
|
40
|
+
role,
|
|
41
|
+
identity: entry.evaluator,
|
|
42
|
+
keyId: entry.keyId,
|
|
43
|
+
custody: "same-operator",
|
|
44
|
+
}));
|
|
45
|
+
}),
|
|
46
|
+
]);
|
|
47
|
+
}
|
|
48
|
+
// Keyed to the purpose union rather than to `string`, so a protocol widening is a build failure
|
|
49
|
+
// here instead of an `undefined` role reaching the reader's screen.
|
|
50
|
+
const EVIDENCE_NATIVE_PURPOSE_ROLES = {
|
|
51
|
+
report: "publisher",
|
|
52
|
+
"automated-evaluator": "automated-grader",
|
|
53
|
+
"human-reviewer": "human-reviewer",
|
|
54
|
+
"label-admission": "label-admission",
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Signers of a v5 evidence-native bundle, read from the same authenticated `claim-package.json`
|
|
58
|
+
* bytes the closure verified.
|
|
59
|
+
*
|
|
60
|
+
* `claim.trust.signers` is a publisher-written declaration used by the closure only as a lookup
|
|
61
|
+
* table: a surplus entry there is never contradicted, because no signature ever selects it. So this
|
|
62
|
+
* keeps only the keys that actually carried a signature the closure accepted
|
|
63
|
+
* (`verifiedSignerKeyIds`). Without that filter a bundle could declare a human reviewer, or a dozen
|
|
64
|
+
* graders, that signed nothing and have the checker print them as fact. The claim package declares
|
|
65
|
+
* no custody, so nothing here upgrades a signer to same-operator either.
|
|
66
|
+
*/
|
|
67
|
+
export function evidenceNativeBundleSigners(claimPackageBytes, verifiedSignerKeyIds) {
|
|
68
|
+
const verified = new Set(verifiedSignerKeyIds);
|
|
69
|
+
return deduplicate(parseEvidenceNativeClaimPackageV3(claimPackageBytes).trust.signers
|
|
70
|
+
.filter((signer) => verified.has(signer.keyId))
|
|
71
|
+
.map((signer) => ({
|
|
72
|
+
role: EVIDENCE_NATIVE_PURPOSE_ROLES[signer.purpose],
|
|
73
|
+
identity: signer.identity,
|
|
74
|
+
keyId: signer.keyId,
|
|
75
|
+
custody: "undeclared",
|
|
76
|
+
})));
|
|
77
|
+
}
|
package/dist/verify.d.ts
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import { type EvidenceNativePortableBundleVerification } from "@jinn-network/benchmarking-evidence";
|
|
2
|
+
import { type PublicBundleSigner } from "./signers.js";
|
|
2
3
|
import { type InspectRuntimeMethodDisclosure } from "./profile/inspect-disclosure.js";
|
|
3
4
|
import { type PublicComparisonView } from "./comparison.js";
|
|
4
5
|
import { type VerifiedBundleSnapshot, type VerifyBundleSnapshotDeps } from "./manifest.js";
|
|
6
|
+
import { type DisclosureSpecificationReport } from "./profile/disclosure.js";
|
|
5
7
|
import { type IntegrityAnchorsReport, type PublicBundleAnchorTrustMaterial } from "./anchor/check.js";
|
|
6
8
|
import { type BinaryItemBankEntry, type BinarySourceManifestEntry } from "./admission/intake.js";
|
|
7
9
|
export type PublicBundleVerificationCheck = "manifest" | "evidence-closure" | "trust" | "matrix-rederivation" | "report-verification" | "claim-consistency"
|
|
8
|
-
/** Always present for `benchmark-product-public-bundle/6`,
|
|
9
|
-
* (anchor-evidence design §8, §12). */
|
|
10
|
-
| "integrity-anchors"
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
/** Always present for the anchored closures, `benchmark-product-public-bundle/6`, `/7`, and `/8`,
|
|
11
|
+
* never for any earlier one (anchor-evidence design §8, §12). */
|
|
12
|
+
| "integrity-anchors"
|
|
13
|
+
/** Always present for `benchmark-product-public-bundle/8`, never for any earlier closure
|
|
14
|
+
* (disclosure-specification-record design §7, issue #2839). Runs last: the claim's `disclosure`
|
|
15
|
+
* section is among the things it depends on having already been byte-compared. */
|
|
16
|
+
| "disclosure-specification";
|
|
17
|
+
export interface LegacyPublicBundleVerificationResult extends PublicBundleSignerDisclosure {
|
|
18
|
+
readonly format: "benchmark-product-public-bundle/2" | "benchmark-product-public-bundle/4" | "benchmark-product-public-bundle/6" | "benchmark-product-public-bundle/7" | "benchmark-product-public-bundle/8";
|
|
13
19
|
readonly identity: string;
|
|
14
20
|
readonly checks: readonly PublicBundleVerificationCheck[];
|
|
15
21
|
readonly benchmarkSha256: string;
|
|
@@ -22,6 +28,10 @@ export interface LegacyPublicBundleVerificationResult {
|
|
|
22
28
|
* subject's context outcome (anchor-evidence design §8). Statuses are disclosed facts, not a
|
|
23
29
|
* summary — nothing here is folded into a single verified badge. */
|
|
24
30
|
readonly anchors?: IntegrityAnchorsReport;
|
|
31
|
+
/** Present exactly for the disclosed closure (issue #2839, design §7 step 11): the sealed record's
|
|
32
|
+
* identity and all six variables' statuses. Statuses are DISCLOSED FACTS, never folded into a
|
|
33
|
+
* single badge and never counted — the same posture `anchors` takes, and for the same reason. */
|
|
34
|
+
readonly disclosure?: DisclosureSpecificationReport;
|
|
25
35
|
readonly qualification?: {
|
|
26
36
|
readonly publicationGrade: boolean;
|
|
27
37
|
readonly truthAdmission: "two-human-unanimous" | "operator-only" | "screened-operator-sampled";
|
|
@@ -32,7 +42,11 @@ export interface LegacyPublicBundleVerificationResult {
|
|
|
32
42
|
readonly exclusionCount: number;
|
|
33
43
|
};
|
|
34
44
|
}
|
|
35
|
-
|
|
45
|
+
/** Who signed the bundle, with the identifiers the human surface deliberately does not print. */
|
|
46
|
+
export interface PublicBundleSignerDisclosure {
|
|
47
|
+
readonly signers?: readonly PublicBundleSigner[];
|
|
48
|
+
}
|
|
49
|
+
export type PublicBundleVerificationResult = LegacyPublicBundleVerificationResult | (EvidenceNativePortableBundleVerification & PublicBundleSignerDisclosure);
|
|
36
50
|
export interface VerifyPublicBundleDeps extends VerifyBundleSnapshotDeps {
|
|
37
51
|
/**
|
|
38
52
|
* Trust material for the `integrity-anchors` check (anchor-evidence design §8 step 3): timestamp
|
package/dist/verify.js
CHANGED
|
@@ -2,16 +2,17 @@ import { createHash, createPublicKey, verify as verifySignature } from "node:cry
|
|
|
2
2
|
import { verifyReport } from "@jinn-network/benchmarking-aggregate";
|
|
3
3
|
import { verifyEvidenceNativePortableBundle, } from "@jinn-network/benchmarking-evidence";
|
|
4
4
|
import { exportStaticBundle } from "@jinn-network/benchmarking-interop";
|
|
5
|
-
import { cellIdempotencyKey, expectedCellSet, parseBenchmark, parseMatrix, parseReport, parseRun, readRunAnchorIntentExtension, readRunPublicationExtension, } from "@jinn-network/benchmarking-records";
|
|
5
|
+
import { DISCLOSURE_SPECIFICATION_EXTENSION, cellIdempotencyKey, expectedCellSet, parseBenchmark, parseMatrix, parseReport, parseRun, readReportDisclosureExtension, readRunAnchorIntentExtension, readRunPublicationExtension, } from "@jinn-network/benchmarking-records";
|
|
6
6
|
import { verifyMatrix } from "@jinn-network/benchmarking-run";
|
|
7
7
|
import { BINARY_JUDGMENT_INSTRUMENT_REQUIREMENT_KEY, BINARY_JUDGMENT_PROFILE_URI, BinaryJudgmentSnapshotProbeSchema, deriveEvaluationTask, parseBinaryJudgmentAnalysisContext, parseBinaryJudgmentInstrument, parseEvaluationSpec, } from "@jinn-network/task-execution-profiles";
|
|
8
8
|
import { DeliveryRecordSchema, SubmissionRecordSchema, TaskSpecificationSchema } from "@jinn-network/task-execution-protocol";
|
|
9
9
|
import { canonicalJsonBytes, dssePreAuthEncoding, parseExactDsseEnvelope } from "@jinn-network/trust-core";
|
|
10
10
|
import { refuse } from "./profile/errors.js";
|
|
11
|
-
import { ClaimPackageSchema } from "./profile/claim.js";
|
|
11
|
+
import { BINARY_QUALIFICATION_CLAIM_PACKAGE_SCHEMA_ID, ClaimPackageSchema, DISCLOSED_CLAIM_PACKAGE_SCHEMA_ID, } from "./profile/claim.js";
|
|
12
12
|
import { buildMethodPortsFromResolver } from "./profile/ports.js";
|
|
13
13
|
import { didKeyFromEd25519PublicKey } from "./profile/signing.js";
|
|
14
14
|
import { buildPublicReportTrustDeps } from "./profile/trust.js";
|
|
15
|
+
import { evidenceNativeBundleSigners, legacyBundleSigners } from "./signers.js";
|
|
15
16
|
import { buildAssemblyPortsFromFacts } from "./profile/assembly-ports.js";
|
|
16
17
|
import { parseRunPinningEvidenceArtifact, pinningEvidenceFacts, } from "./profile/pinning-evidence.js";
|
|
17
18
|
import { parsePredictionSnapshotAdmissionReceipt, } from "./profile/admission-receipts.js";
|
|
@@ -23,11 +24,13 @@ import { InspectSelectionManifestSchema, isInspectMultiScorerSelection, } from "
|
|
|
23
24
|
import { describeInspectRuntimeMethod, } from "./profile/inspect-disclosure.js";
|
|
24
25
|
import { deriveInspectEvaluationStrategy, INSPECT_SEPARATE_ASSURANCE_LIMITATIONS, inspectLogVerifierMethod, } from "./profile/inspect-assurance.js";
|
|
25
26
|
import { assertClaimConsistency } from "./profile/claim-consistency.js";
|
|
27
|
+
import { assertTaskSelectionConsistency } from "./profile/task-selection.js";
|
|
26
28
|
import { buildPublicAssets } from "./assets.js";
|
|
27
29
|
import { derivePublicComparison } from "./comparison.js";
|
|
28
30
|
import { verifyBundleSnapshot, } from "./manifest.js";
|
|
29
31
|
import { PUBLIC_BUNDLE_FILES, PUBLIC_BUNDLE_V4_FILES } from "./materialize.js";
|
|
30
|
-
import { BUNDLE_V4_FORMAT, BUNDLE_V5_FORMAT, BUNDLE_V6_FORMAT } from "./manifest.js";
|
|
32
|
+
import { BUNDLE_V4_FORMAT, BUNDLE_V5_FORMAT, BUNDLE_V6_FORMAT, BUNDLE_V7_FORMAT, BUNDLE_V8_FORMAT } from "./manifest.js";
|
|
33
|
+
import { DISCLOSURE_SPECIFICATION_BUNDLE_ROLE, DisclosureProjectionError, assertDisclosureSpecification, deriveDisclosureSpecification, } from "./profile/disclosure.js";
|
|
31
34
|
import { evaluateIntegrityAnchors, } from "./anchor/check.js";
|
|
32
35
|
import { ClaimAnchorProjectionError, deriveClaimAnchors } from "./profile/anchor-claims.js";
|
|
33
36
|
import { verifyBinaryJudgmentAdmissionClosure, } from "./admission/verification.js";
|
|
@@ -214,13 +217,54 @@ export function checkItemBankSourceClosure(itemRows, sourceRows) {
|
|
|
214
217
|
* public keys. No pathname is reopened after manifest authentication. */
|
|
215
218
|
export async function verifyPublicBundleSnapshot(bundleDir, deps = {}) {
|
|
216
219
|
const checked = verifyBundleSnapshot(bundleDir, deps);
|
|
220
|
+
// ── G0, the closure-INDEPENDENT extension guard (disclosure design §7 preamble, issue #2839) ──
|
|
221
|
+
//
|
|
222
|
+
// A Report carrying `DISCLOSURE_SPECIFICATION_EXTENSION` on any format other than `/8` refuses,
|
|
223
|
+
// here, before the format branch — so this holds for `/2`, `/4`, `/5`, `/6`, and `/7` alike, the
|
|
224
|
+
// evidence-native path included.
|
|
225
|
+
//
|
|
226
|
+
// Without it there is a real hole: a `/7` bundle could carry both the extension and the record,
|
|
227
|
+
// have the record's role derived by the extension edge, satisfy the evidence-closure reachability
|
|
228
|
+
// guard, and never be looked at by any check — because the named check runs only on `/8`. G0
|
|
229
|
+
// closes that direction; the evidence closure's own size and per-digest guards close the
|
|
230
|
+
// complementary one (role present, extension absent). The two together are what make the
|
|
231
|
+
// extension and the closure inseparable.
|
|
232
|
+
//
|
|
233
|
+
// Read deliberately at the JSON level rather than through `parseReport`: this must fire on a
|
|
234
|
+
// format whose `report.json` this function never otherwise parses, and it must fire on the
|
|
235
|
+
// extension's PRESENCE, not on its well-formedness.
|
|
236
|
+
if (checked.manifest.format !== BUNDLE_V8_FORMAT) {
|
|
237
|
+
const carriedReport = checked.fileBytes.get("report.json");
|
|
238
|
+
if (carriedReport !== undefined) {
|
|
239
|
+
let parsedReportJson;
|
|
240
|
+
try {
|
|
241
|
+
parsedReportJson = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(carriedReport));
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
parsedReportJson = undefined;
|
|
245
|
+
}
|
|
246
|
+
if (typeof parsedReportJson === "object" && parsedReportJson !== null && !Array.isArray(parsedReportJson)
|
|
247
|
+
&& parsedReportJson[DISCLOSURE_SPECIFICATION_EXTENSION] !== undefined) {
|
|
248
|
+
refuse("record-integrity", "report.json", `a Report carrying ${DISCLOSURE_SPECIFICATION_EXTENSION} is publishable only on`
|
|
249
|
+
+ ` ${BUNDLE_V8_FORMAT}, whose disclosure-specification check reads it; this bundle`
|
|
250
|
+
+ ` declares ${checked.manifest.format}`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
217
254
|
if (checked.manifest.format === BUNDLE_V5_FORMAT) {
|
|
218
255
|
try {
|
|
256
|
+
const claimPackageBytes = checked.fileBytes.get("claim-package.json");
|
|
257
|
+
if (claimPackageBytes === undefined)
|
|
258
|
+
throw new TypeError("portable bundle is missing claim-package.json");
|
|
259
|
+
const verification = await verifyEvidenceNativePortableBundle({
|
|
260
|
+
files: checked.fileBytes,
|
|
261
|
+
verifySignature: verifyEvidenceNativeSignature,
|
|
262
|
+
});
|
|
219
263
|
return {
|
|
220
|
-
verification:
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
}
|
|
264
|
+
verification: {
|
|
265
|
+
...verification,
|
|
266
|
+
signers: evidenceNativeBundleSigners(claimPackageBytes, verification.verifiedSignerKeyIds),
|
|
267
|
+
},
|
|
224
268
|
snapshot: checked,
|
|
225
269
|
};
|
|
226
270
|
}
|
|
@@ -236,17 +280,25 @@ export async function verifyPublicBundleSnapshot(bundleDir, deps = {}) {
|
|
|
236
280
|
};
|
|
237
281
|
const checks = ["manifest"];
|
|
238
282
|
const manifestPaths = new Set(checked.manifest.files.map((file) => file.path));
|
|
239
|
-
|
|
240
|
-
//
|
|
241
|
-
//
|
|
242
|
-
|
|
243
|
-
|
|
283
|
+
// Three independent axes, five formats. The qualification axis decides the mandatory member list,
|
|
284
|
+
// the evidence-catalog grammar, and the trust grammar; the anchor axis decides the `anchors/`
|
|
285
|
+
// allowlist and the `integrity-anchors` check; the disclosure axis decides the Report-extension
|
|
286
|
+
// edge and the `disclosure-specification` check. v6 is v2 plus anchors, v7 is v4 plus anchors
|
|
287
|
+
// (issue #3205), v8 is v7 plus disclosure (issue #2839) — no axis reinterprets another.
|
|
288
|
+
const carriesQualification = checked.manifest.format === BUNDLE_V4_FORMAT
|
|
289
|
+
|| checked.manifest.format === BUNDLE_V7_FORMAT
|
|
290
|
+
|| checked.manifest.format === BUNDLE_V8_FORMAT;
|
|
291
|
+
const carriesAnchors = checked.manifest.format === BUNDLE_V6_FORMAT
|
|
292
|
+
|| checked.manifest.format === BUNDLE_V7_FORMAT
|
|
293
|
+
|| checked.manifest.format === BUNDLE_V8_FORMAT;
|
|
294
|
+
const carriesDisclosure = checked.manifest.format === BUNDLE_V8_FORMAT;
|
|
295
|
+
const mandatoryFiles = carriesQualification ? PUBLIC_BUNDLE_V4_FILES : PUBLIC_BUNDLE_FILES;
|
|
244
296
|
for (const path of mandatoryFiles) {
|
|
245
297
|
if (!manifestPaths.has(path))
|
|
246
298
|
refuse("record-integrity", path, `mandatory public bundle file "${path}" is missing`);
|
|
247
299
|
}
|
|
248
300
|
const evidenceBytes = read("evidence.json");
|
|
249
|
-
const evidence =
|
|
301
|
+
const evidence = carriesQualification
|
|
250
302
|
? parseJson(evidenceBytes, BundleV4EvidenceCatalogSchema, "evidence.json")
|
|
251
303
|
: parseJson(evidenceBytes, BundleEvidenceCatalogSchema, "evidence.json");
|
|
252
304
|
requireCanonical(evidenceBytes, evidence, "evidence.json");
|
|
@@ -263,10 +315,10 @@ export async function verifyPublicBundleSnapshot(bundleDir, deps = {}) {
|
|
|
263
315
|
if (/^native\/inspect\/[a-f0-9]{64}\.eval$/u.test(path))
|
|
264
316
|
expectedPaths.add(path);
|
|
265
317
|
}
|
|
266
|
-
// `anchors/<sha256>.bin` is allowlisted only by the closure
|
|
267
|
-
// member in a v2 or v4 bundle is a non-allowlisted file, exactly as it was before
|
|
318
|
+
// `anchors/<sha256>.bin` is allowlisted only by the closure versions that define it: an anchor
|
|
319
|
+
// member in a v2 or v4 bundle is a non-allowlisted file, exactly as it was before these formats.
|
|
268
320
|
const anchorPaths = [];
|
|
269
|
-
if (
|
|
321
|
+
if (carriesAnchors) {
|
|
270
322
|
for (const path of manifestPaths) {
|
|
271
323
|
if (/^anchors\/[a-f0-9]{64}\.bin$/u.test(path)) {
|
|
272
324
|
expectedPaths.add(path);
|
|
@@ -290,7 +342,7 @@ export async function verifyPublicBundleSnapshot(bundleDir, deps = {}) {
|
|
|
290
342
|
declaredRoles.set(record.sha256, new Set(record.roles));
|
|
291
343
|
}
|
|
292
344
|
const trustBytes = read("trust/public-keys.json");
|
|
293
|
-
const trust =
|
|
345
|
+
const trust = carriesQualification
|
|
294
346
|
? parseJson(trustBytes, BundleV4TrustSchema, "trust/public-keys.json")
|
|
295
347
|
: parseJson(trustBytes, BundleTrustSchema, "trust/public-keys.json");
|
|
296
348
|
requireCanonical(trustBytes, trust, "trust/public-keys.json");
|
|
@@ -300,7 +352,7 @@ export async function verifyPublicBundleSnapshot(bundleDir, deps = {}) {
|
|
|
300
352
|
{ keyId: entry.keyId, publicKey: publicKey(entry.spkiDerBase64, `trust.evaluators.${entry.evaluator}`) },
|
|
301
353
|
]));
|
|
302
354
|
let qualification;
|
|
303
|
-
if (
|
|
355
|
+
if (carriesQualification) {
|
|
304
356
|
const qualificationBytes = read("qualification.json");
|
|
305
357
|
qualification = parseJson(qualificationBytes, BundleQualificationSchema, "qualification.json");
|
|
306
358
|
requireCanonical(qualificationBytes, qualification, "qualification.json");
|
|
@@ -348,7 +400,7 @@ export async function verifyPublicBundleSnapshot(bundleDir, deps = {}) {
|
|
|
348
400
|
// empty section and an omitted one are different claims, and §7.3's declared-but-absent bundle
|
|
349
401
|
// carries the first.
|
|
350
402
|
let claimAnchors;
|
|
351
|
-
if (
|
|
403
|
+
if (carriesAnchors) {
|
|
352
404
|
const anchorRecords = anchorPaths
|
|
353
405
|
.map((path) => {
|
|
354
406
|
const bytes = read(path);
|
|
@@ -384,6 +436,33 @@ export async function verifyPublicBundleSnapshot(bundleDir, deps = {}) {
|
|
|
384
436
|
throw cause;
|
|
385
437
|
}
|
|
386
438
|
}
|
|
439
|
+
// ── The disclosed closure's Report-extension edge and claim projection (issue #2839) ────────
|
|
440
|
+
//
|
|
441
|
+
// Read here, beside the anchors, and for the same two reasons: the evidence-closure walk below
|
|
442
|
+
// needs the edge to derive the record's role, and `assertClaimConsistency` needs the projection to
|
|
443
|
+
// rebuild the claim from the RECORD'S OWN BYTES rather than from the claim under test.
|
|
444
|
+
let disclosureExtensionDigest;
|
|
445
|
+
let claimDisclosure;
|
|
446
|
+
if (carriesDisclosure) {
|
|
447
|
+
const descriptor = readReportDisclosureExtension(report);
|
|
448
|
+
if (descriptor === undefined) {
|
|
449
|
+
refuse("record-integrity", "disclosure-specification", `a ${BUNDLE_V8_FORMAT} bundle must carry ${DISCLOSURE_SPECIFICATION_EXTENSION} on its Report`);
|
|
450
|
+
}
|
|
451
|
+
disclosureExtensionDigest = descriptor.digest.sha256;
|
|
452
|
+
const disclosureBytes = records.get(disclosureExtensionDigest);
|
|
453
|
+
if (disclosureBytes === undefined) {
|
|
454
|
+
refuse("record-integrity", `records/${disclosureExtensionDigest}.bin`, "the bundle does not carry the disclosure-specification record its Report names");
|
|
455
|
+
}
|
|
456
|
+
try {
|
|
457
|
+
claimDisclosure = deriveDisclosureSpecification(disclosureBytes);
|
|
458
|
+
}
|
|
459
|
+
catch (cause) {
|
|
460
|
+
if (cause instanceof DisclosureProjectionError) {
|
|
461
|
+
refuse("record-integrity", `records/${disclosureExtensionDigest}.bin`, cause.message);
|
|
462
|
+
}
|
|
463
|
+
throw cause;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
387
466
|
const assembly = parseAssembly(read("verification/assembly.jsonl"));
|
|
388
467
|
const expectedNativePaths = new Set(assembly.header.graph.solveDeliveries.flatMap((delivery) => delivery.outputs
|
|
389
468
|
.filter((output) => output.name === "inspect-log")
|
|
@@ -415,6 +494,18 @@ export async function verifyPublicBundleSnapshot(bundleDir, deps = {}) {
|
|
|
415
494
|
const cellsByKey = new Map(assembly.cells.map((cell) => [cell.cellKey, cell]));
|
|
416
495
|
const coordinatesByKey = new Map(expectedCoordinates.map((coord) => [coord.cellKey, coord]));
|
|
417
496
|
const expectedRoles = new Map();
|
|
497
|
+
// ── The disclosed closure's one graph edge (issue #2839, design §6.2 / §10.2) ───────────────
|
|
498
|
+
//
|
|
499
|
+
// The Report extension IS the edge: it is the only thing that derives the
|
|
500
|
+
// `disclosure-specification` role for any record. Adding it here — and only on `/8` — is what
|
|
501
|
+
// makes the two refusals in §6.5.2 fire on every other format without a bespoke guard. A
|
|
502
|
+
// standalone disclosure record on a `/7` bundle makes `declaredRoles` exceed `expectedRoles` and
|
|
503
|
+
// trips the size compare; the role appended to an existing graph record's array leaves the sizes
|
|
504
|
+
// equal and trips the per-digest compare instead. Both refusals already existed and cannot be
|
|
505
|
+
// forgotten.
|
|
506
|
+
if (disclosureExtensionDigest !== undefined) {
|
|
507
|
+
addRole(expectedRoles, disclosureExtensionDigest, DISCLOSURE_SPECIFICATION_BUNDLE_ROLE);
|
|
508
|
+
}
|
|
418
509
|
const evaluationSpecs = new Map();
|
|
419
510
|
const taskSpecs = new Map();
|
|
420
511
|
const inspectSelections = new Map();
|
|
@@ -1476,6 +1567,11 @@ export async function verifyPublicBundleSnapshot(bundleDir, deps = {}) {
|
|
|
1476
1567
|
if (!equalBytes(canonicalJsonBytes(verifiedReport.record), reportBytes))
|
|
1477
1568
|
refuse("record-integrity", "report-verification", "verified Report payload does not match report.json");
|
|
1478
1569
|
checks.push("report-verification");
|
|
1570
|
+
// Task-selection provenance (#2980). Runs under the `claim-consistency` check because that is
|
|
1571
|
+
// exactly the question it answers -- does the claim's declared selection survive contact with
|
|
1572
|
+
// the records? -- and because the claim pins the check list byte-for-byte, so a new named check
|
|
1573
|
+
// would be a bundle-format bump rather than an addition.
|
|
1574
|
+
assertTaskSelectionConsistency({ benchmarkRecord: benchmark, runRecord: run });
|
|
1479
1575
|
assertClaimConsistency({
|
|
1480
1576
|
claim,
|
|
1481
1577
|
identities,
|
|
@@ -1490,12 +1586,41 @@ export async function verifyPublicBundleSnapshot(bundleDir, deps = {}) {
|
|
|
1490
1586
|
: {}),
|
|
1491
1587
|
...(assembly.header.rehearsal === undefined ? {} : { rehearsal: assembly.header.rehearsal }),
|
|
1492
1588
|
...(claimAnchors === undefined ? {} : { anchors: claimAnchors }),
|
|
1589
|
+
...(claimDisclosure === undefined ? {} : { disclosure: claimDisclosure }),
|
|
1493
1590
|
});
|
|
1494
1591
|
checks.push("claim-consistency");
|
|
1495
|
-
// Always present for
|
|
1496
|
-
// whose anchors were stripped is a closure failure above, not a shorter check list here.
|
|
1497
|
-
if (
|
|
1592
|
+
// Always present for the anchored closure versions, and never for any earlier one: an anchored
|
|
1593
|
+
// bundle whose anchors were stripped is a closure failure above, not a shorter check list here.
|
|
1594
|
+
if (carriesAnchors)
|
|
1498
1595
|
checks.push("integrity-anchors");
|
|
1596
|
+
// ── disclosure-specification (issue #2839, design §7 steps 1-9) ────────────────────────────
|
|
1597
|
+
//
|
|
1598
|
+
// Runs after `claim-consistency` because step 10 — projection equality — is delivered BY that
|
|
1599
|
+
// check's existing whole-claim byte-compare rather than by a second comparison here. What is left
|
|
1600
|
+
// for this block is authenticating the record itself and pairing the two claim identifiers.
|
|
1601
|
+
let disclosureReport;
|
|
1602
|
+
if (carriesDisclosure) {
|
|
1603
|
+
// Step 9: claim-id pairing. `qualification.json`'s `claimSchema` names WHICH PROJECTION SHAPE
|
|
1604
|
+
// the qualification graph was built for, and that shape is claim-package/2's on every binary
|
|
1605
|
+
// allocation — so the frozen literal does not move, while `claim-package.json` declares the
|
|
1606
|
+
// closure. Either field carrying the other's value refuses, so the two cannot drift together.
|
|
1607
|
+
if (claim.claimSchema !== DISCLOSED_CLAIM_PACKAGE_SCHEMA_ID) {
|
|
1608
|
+
refuse("record-integrity", "claim-package.json", `a ${BUNDLE_V8_FORMAT} bundle's claim must declare ${DISCLOSED_CLAIM_PACKAGE_SCHEMA_ID}`);
|
|
1609
|
+
}
|
|
1610
|
+
if (qualification?.claimSchema !== BINARY_QUALIFICATION_CLAIM_PACKAGE_SCHEMA_ID) {
|
|
1611
|
+
refuse("record-integrity", "qualification.json", `a ${BUNDLE_V8_FORMAT} bundle's qualification document must keep its frozen`
|
|
1612
|
+
+ ` ${BINARY_QUALIFICATION_CLAIM_PACKAGE_SCHEMA_ID} projection literal`);
|
|
1613
|
+
}
|
|
1614
|
+
disclosureReport = assertDisclosureSpecification({
|
|
1615
|
+
extensionDigestSha256: disclosureExtensionDigest,
|
|
1616
|
+
catalogRoles: declaredRoles,
|
|
1617
|
+
recordBytes: records,
|
|
1618
|
+
matrixSha256: identities.matrixSha256,
|
|
1619
|
+
reportAuthor: verifiedReport.record.author,
|
|
1620
|
+
refuse: (path, message) => refuse("record-integrity", path, message),
|
|
1621
|
+
});
|
|
1622
|
+
checks.push("disclosure-specification");
|
|
1623
|
+
}
|
|
1499
1624
|
const dissentCellKeys = assembly.cells
|
|
1500
1625
|
.filter((cell) => new Set(cell.verdicts.map((verdict) => verdict.verdict)).size > 1)
|
|
1501
1626
|
.map((cell) => cell.cellKey)
|
|
@@ -1520,17 +1645,15 @@ export async function verifyPublicBundleSnapshot(bundleDir, deps = {}) {
|
|
|
1520
1645
|
}),
|
|
1521
1646
|
dissentCellKeys,
|
|
1522
1647
|
};
|
|
1523
|
-
//
|
|
1524
|
-
//
|
|
1525
|
-
//
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1648
|
+
// The closure selects the presentation profile and the bundle must byte-match that one
|
|
1649
|
+
// profile completely — assets cannot be mixed, and there is no second profile to fall back
|
|
1650
|
+
// to (issue #2984). A qualification-projecting bundle (`/4`, `/7`) renders the
|
|
1651
|
+
// instrument-qualification graph; every other one renders the human comparison, which
|
|
1652
|
+
// `derivePublicComparison` above always produces. The comparison-absent rendering a
|
|
1653
|
+
// pre-comparison producer would have written is therefore no bundle's profile.
|
|
1529
1654
|
const expectedAssets = qualification !== undefined
|
|
1530
1655
|
? buildPublicAssets({ ...assetFacts, binaryQualification: binaryAssetQualification })
|
|
1531
|
-
:
|
|
1532
|
-
? legacyAssets
|
|
1533
|
-
: buildPublicAssets({ ...assetFacts, comparison });
|
|
1656
|
+
: buildPublicAssets({ ...assetFacts, comparison });
|
|
1534
1657
|
for (const [path, bytes] of Object.entries(expectedAssets)) {
|
|
1535
1658
|
if (!equalBytes(read(path), bytes))
|
|
1536
1659
|
refuse("record-integrity", path, `${path} is not the exact projection of verified public facts`);
|
|
@@ -1547,9 +1670,11 @@ export async function verifyPublicBundleSnapshot(bundleDir, deps = {}) {
|
|
|
1547
1670
|
format: checked.manifest.format,
|
|
1548
1671
|
identity: checked.identity,
|
|
1549
1672
|
checks,
|
|
1673
|
+
signers: legacyBundleSigners(trust, new Set(verdictCatalog.verdicts.map((verdict) => verdict.evaluator))),
|
|
1550
1674
|
...identities,
|
|
1551
1675
|
...(runtimeMethod === undefined ? {} : { runtimeMethod }),
|
|
1552
1676
|
...(anchorReport === undefined ? {} : { anchors: anchorReport }),
|
|
1677
|
+
...(disclosureReport === undefined ? {} : { disclosure: disclosureReport }),
|
|
1553
1678
|
...(qualification === undefined ? {} : {
|
|
1554
1679
|
qualification: {
|
|
1555
1680
|
publicationGrade: qualification.publicationGrade,
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Public verifier release line. Kept in one module for output and bundle instructions. */
|
|
2
|
-
export declare const VERIFIER_VERSION: "0.2.
|
|
2
|
+
export declare const VERIFIER_VERSION: "0.2.1";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Public verifier release line. Kept in one module for output and bundle instructions. */
|
|
2
|
-
export const VERIFIER_VERSION = "0.2.
|
|
2
|
+
export const VERIFIER_VERSION = "0.2.1";
|