@colophon-claims/verify 0.0.0 → 0.2.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 +39 -0
- package/dist/admission/application.d.ts +18 -0
- package/dist/admission/application.js +53 -0
- package/dist/admission/contracts.d.ts +506 -0
- package/dist/admission/contracts.js +459 -0
- package/dist/admission/index.d.ts +5 -0
- package/dist/admission/index.js +5 -0
- package/dist/admission/intake.d.ts +75 -0
- package/dist/admission/intake.js +70 -0
- package/dist/admission/result-evaluation.d.ts +18 -0
- package/dist/admission/result-evaluation.js +71 -0
- package/dist/admission/screening-sample.d.ts +56 -0
- package/dist/admission/screening-sample.js +126 -0
- package/dist/admission/verification.d.ts +102 -0
- package/dist/admission/verification.js +844 -0
- package/dist/anchor/check.d.ts +95 -0
- package/dist/anchor/check.js +146 -0
- package/dist/anchor/ports.d.ts +6 -0
- package/dist/anchor/ports.js +354 -0
- package/dist/assets.d.ts +33 -0
- package/dist/assets.js +885 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +20 -0
- package/dist/cli.d.ts +14 -0
- package/dist/cli.js +205 -0
- package/dist/comparison.d.ts +64 -0
- package/dist/comparison.js +235 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +23 -0
- package/dist/manifest.d.ts +54 -0
- package/dist/manifest.js +240 -0
- package/dist/materialize.d.ts +4 -0
- package/dist/materialize.js +13 -0
- package/dist/profile/admission-receipts.d.ts +11 -0
- package/dist/profile/admission-receipts.js +24 -0
- package/dist/profile/anchor-claims.d.ts +157 -0
- package/dist/profile/anchor-claims.js +330 -0
- package/dist/profile/artifacts.d.ts +261 -0
- package/dist/profile/artifacts.js +139 -0
- package/dist/profile/assembly-ports.d.ts +19 -0
- package/dist/profile/assembly-ports.js +42 -0
- package/dist/profile/binary-judge-manifest.d.ts +121 -0
- package/dist/profile/binary-judge-manifest.js +106 -0
- package/dist/profile/binary-qualification.d.ts +9 -0
- package/dist/profile/binary-qualification.js +58 -0
- package/dist/profile/branding-assets.d.ts +5 -0
- package/dist/profile/branding-assets.js +5 -0
- package/dist/profile/branding.d.ts +24 -0
- package/dist/profile/branding.js +14 -0
- package/dist/profile/claim-consistency.d.ts +26 -0
- package/dist/profile/claim-consistency.js +91 -0
- package/dist/profile/claim.d.ts +327 -0
- package/dist/profile/claim.js +742 -0
- package/dist/profile/errors.d.ts +49 -0
- package/dist/profile/errors.js +78 -0
- package/dist/profile/inspect-assurance.d.ts +16 -0
- package/dist/profile/inspect-assurance.js +30 -0
- package/dist/profile/inspect-disclosure.d.ts +28 -0
- package/dist/profile/inspect-disclosure.js +54 -0
- package/dist/profile/inspect-manifest.d.ts +706 -0
- package/dist/profile/inspect-manifest.js +397 -0
- package/dist/profile/isolation.d.ts +21 -0
- package/dist/profile/isolation.js +31 -0
- package/dist/profile/pinning-evidence.d.ts +41 -0
- package/dist/profile/pinning-evidence.js +43 -0
- package/dist/profile/ports.d.ts +3 -0
- package/dist/profile/ports.js +11 -0
- package/dist/profile/preview-log.d.ts +4 -0
- package/dist/profile/preview-log.js +3 -0
- package/dist/profile/run-results.d.ts +17 -0
- package/dist/profile/run-results.js +23 -0
- package/dist/profile/signing.d.ts +10 -0
- package/dist/profile/signing.js +46 -0
- package/dist/profile/trust.d.ts +13 -0
- package/dist/profile/trust.js +35 -0
- package/dist/profile/venue.d.ts +2 -0
- package/dist/profile/venue.js +2 -0
- package/dist/profile/verdict.d.ts +28 -0
- package/dist/profile/verdict.js +51 -0
- package/dist/reader-instructions.d.ts +41 -0
- package/dist/reader-instructions.js +52 -0
- package/dist/schema.d.ts +380 -0
- package/dist/schema.js +498 -0
- package/dist/verify.d.ts +72 -0
- package/dist/verify.js +1573 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +2 -0
- package/package.json +63 -3
- package/schemas/assembly-row.schema.json +194 -0
- package/schemas/bundle-manifest.schema.json +23 -0
- package/schemas/claim-package.schema.json +279 -0
- package/schemas/dsse-envelope.schema.json +25 -0
- package/schemas/evidence-catalog.schema.json +43 -0
- package/schemas/public-trust.schema.json +44 -0
- package/schemas/verdict-catalog.schema.json +27 -0
- package/scripts/external-verify.py +238 -0
package/dist/schema.js
ADDED
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { compareCodeUnitStrings } from "@jinn-network/benchmarking-records";
|
|
3
|
+
import { TASK_EXECUTION_ERROR_CATEGORIES } from "@jinn-network/task-execution-protocol";
|
|
4
|
+
const Sha256HexSchema = z.string().regex(/^[a-f0-9]{64}$/);
|
|
5
|
+
const Rfc3339Schema = z.string().datetime({ offset: true });
|
|
6
|
+
export const BUNDLE_TRUST_FORMAT = "benchmark-product-public-trust/2";
|
|
7
|
+
export const BUNDLE_EVIDENCE_FORMAT = "benchmark-product-evidence-catalog/2";
|
|
8
|
+
export const BUNDLE_VERDICTS_FORMAT = "benchmark-product-verdict-catalog/2";
|
|
9
|
+
export const BUNDLE_ASSEMBLY_FORMAT = "benchmark-product-assembly/2";
|
|
10
|
+
export const BUNDLE_V4_TRUST_FORMAT = "benchmark-product-public-trust/4";
|
|
11
|
+
export const BUNDLE_V4_EVIDENCE_FORMAT = "benchmark-product-evidence-catalog/4";
|
|
12
|
+
export const BUNDLE_QUALIFICATION_FORMAT = "benchmark-product-binary-qualification/1";
|
|
13
|
+
export const BUNDLE_V4_EVIDENCE_ROLES = [
|
|
14
|
+
"task",
|
|
15
|
+
"runtime-selection",
|
|
16
|
+
"evaluation-spec",
|
|
17
|
+
"admission-receipt",
|
|
18
|
+
"solve-submission",
|
|
19
|
+
"run-pinning-evidence",
|
|
20
|
+
"evaluation-submission",
|
|
21
|
+
"solve-delivery",
|
|
22
|
+
"solve-output",
|
|
23
|
+
"evaluation-task",
|
|
24
|
+
"evaluation-delivery",
|
|
25
|
+
"verdict",
|
|
26
|
+
"item-bank",
|
|
27
|
+
"source-manifest",
|
|
28
|
+
"admission-index",
|
|
29
|
+
"admission-manifest",
|
|
30
|
+
"replacement-ledger",
|
|
31
|
+
"source-item",
|
|
32
|
+
"judge-instrument",
|
|
33
|
+
"analysis-context",
|
|
34
|
+
"label-resolution",
|
|
35
|
+
"human-review-evaluation-spec",
|
|
36
|
+
"human-review-form",
|
|
37
|
+
"human-review-packet",
|
|
38
|
+
"human-review-response",
|
|
39
|
+
"human-review-verdict",
|
|
40
|
+
"reviewer-roster",
|
|
41
|
+
"review-visibility-receipt",
|
|
42
|
+
"review-reveal-receipt",
|
|
43
|
+
"operator-assertion",
|
|
44
|
+
// Appended at the very end (spec §1.6 site 9 / §1.5 rule 5): this array's index order is the
|
|
45
|
+
// frozen role-ordering map used by both the catalog schema's ordering refinement and the bundle
|
|
46
|
+
// writer, so inserting anywhere else would move existing bundles' bytes.
|
|
47
|
+
"snapshot-probe",
|
|
48
|
+
// Appended after snapshot-probe (spec §6.8a Group C, first bullet; packet P6): the
|
|
49
|
+
// screened-operator-sampled admission branch's two new sealed records.
|
|
50
|
+
"screening-table",
|
|
51
|
+
"screening-reveal-receipt",
|
|
52
|
+
"screening-instrument",
|
|
53
|
+
"screening-sampling-script",
|
|
54
|
+
"screening-raw-outputs",
|
|
55
|
+
"screening-prompt",
|
|
56
|
+
"screening-procedure",
|
|
57
|
+
"screening-pool",
|
|
58
|
+
"screening-sample-commitment",
|
|
59
|
+
"screening-transcript",
|
|
60
|
+
];
|
|
61
|
+
export const BUNDLE_V4_ADMISSION_EVIDENCE_ROLES = [
|
|
62
|
+
"admission-manifest", "replacement-ledger", "source-item", "label-resolution",
|
|
63
|
+
"analysis-context", "human-review-evaluation-spec", "human-review-form",
|
|
64
|
+
"human-review-packet", "human-review-response", "human-review-verdict",
|
|
65
|
+
"reviewer-roster", "review-visibility-receipt", "review-reveal-receipt",
|
|
66
|
+
"operator-assertion",
|
|
67
|
+
// Appended after operator-assertion (spec §6.8a Group C, first bullet; packet P6), matching the
|
|
68
|
+
// full list above. This subset's relative order intentionally differs from the full list
|
|
69
|
+
// elsewhere (no judge-instrument, analysis-context/label-resolution swapped) — that is frozen
|
|
70
|
+
// and is not to be normalized.
|
|
71
|
+
"screening-table",
|
|
72
|
+
"screening-reveal-receipt",
|
|
73
|
+
"screening-instrument",
|
|
74
|
+
"screening-sampling-script",
|
|
75
|
+
"screening-raw-outputs",
|
|
76
|
+
"screening-prompt",
|
|
77
|
+
"screening-procedure",
|
|
78
|
+
"screening-pool",
|
|
79
|
+
"screening-sample-commitment",
|
|
80
|
+
"screening-transcript",
|
|
81
|
+
];
|
|
82
|
+
const PublicKeySchema = z.object({
|
|
83
|
+
keyId: z.string().min(1),
|
|
84
|
+
algorithm: z.literal("ed25519"),
|
|
85
|
+
spkiDerBase64: z.string().min(1),
|
|
86
|
+
});
|
|
87
|
+
export const BundleTrustSchema = z.object({
|
|
88
|
+
format: z.literal(BUNDLE_TRUST_FORMAT),
|
|
89
|
+
selfRun: z.object({
|
|
90
|
+
custody: z.literal("workspace-minted"),
|
|
91
|
+
evaluatorDistinctness: z.literal("agent-distinctness-only"),
|
|
92
|
+
partyIndependence: z.literal("not-established"),
|
|
93
|
+
}),
|
|
94
|
+
report: PublicKeySchema.extend({
|
|
95
|
+
author: z.string().min(1),
|
|
96
|
+
didKey: z.string().min(1),
|
|
97
|
+
validFrom: Rfc3339Schema,
|
|
98
|
+
}),
|
|
99
|
+
evaluators: z.array(PublicKeySchema.extend({ evaluator: z.string().min(1) })),
|
|
100
|
+
});
|
|
101
|
+
const BundleV4PublicKeySchema = z.strictObject({
|
|
102
|
+
keyId: z.string().min(1),
|
|
103
|
+
algorithm: z.literal("ed25519"),
|
|
104
|
+
spkiDerBase64: z.string().min(1),
|
|
105
|
+
});
|
|
106
|
+
export const BundleV4TrustSchema = z.strictObject({
|
|
107
|
+
format: z.literal(BUNDLE_V4_TRUST_FORMAT),
|
|
108
|
+
selfRun: z.strictObject({
|
|
109
|
+
custody: z.literal("workspace-minted"),
|
|
110
|
+
evaluatorDistinctness: z.literal("agent-distinctness-only"),
|
|
111
|
+
partyIndependence: z.literal("not-established"),
|
|
112
|
+
}),
|
|
113
|
+
report: BundleV4PublicKeySchema.extend({
|
|
114
|
+
author: z.string().min(1),
|
|
115
|
+
didKey: z.string().min(1),
|
|
116
|
+
validFrom: Rfc3339Schema,
|
|
117
|
+
}),
|
|
118
|
+
evaluators: z.array(BundleV4PublicKeySchema.extend({ evaluator: z.string().min(1) })),
|
|
119
|
+
admission: z.strictObject({
|
|
120
|
+
reviewers: z.array(z.strictObject({
|
|
121
|
+
evaluator: z.string().min(1),
|
|
122
|
+
keyId: z.string().min(1),
|
|
123
|
+
})),
|
|
124
|
+
authorities: z.array(z.strictObject({
|
|
125
|
+
role: z.enum(["roster-attestor", "truth-reveal-attestor", "operator-truth-attestor"]),
|
|
126
|
+
keyId: z.string().min(1),
|
|
127
|
+
})),
|
|
128
|
+
}),
|
|
129
|
+
}).superRefine((trust, ctx) => {
|
|
130
|
+
for (let index = 1; index < trust.evaluators.length; index += 1) {
|
|
131
|
+
if (compareCodeUnitStrings(trust.evaluators[index - 1].evaluator, trust.evaluators[index].evaluator) >= 0) {
|
|
132
|
+
ctx.addIssue({ code: "custom", path: ["evaluators", index], message: "v4 evaluators must be code-unit sorted and unique" });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (new Set(trust.evaluators.map((entry) => entry.keyId)).size !== trust.evaluators.length) {
|
|
136
|
+
ctx.addIssue({ code: "custom", path: ["evaluators"], message: "v4 evaluator key IDs must be unique" });
|
|
137
|
+
}
|
|
138
|
+
const evaluatorKeys = new Map(trust.evaluators.map((entry) => [entry.evaluator, entry.keyId]));
|
|
139
|
+
const reviewers = trust.admission.reviewers;
|
|
140
|
+
if (reviewers.length === 1)
|
|
141
|
+
ctx.addIssue({ code: "custom", path: ["admission", "reviewers"], message: "admission reviewers must be empty or a registry of at least two reviewers" });
|
|
142
|
+
for (const [index, reviewer] of reviewers.entries()) {
|
|
143
|
+
if (index > 0 && compareCodeUnitStrings(reviewers[index - 1].evaluator, reviewer.evaluator) >= 0)
|
|
144
|
+
ctx.addIssue({ code: "custom", path: ["admission", "reviewers"], message: "reviewer bindings must be sorted and unique" });
|
|
145
|
+
if (evaluatorKeys.get(reviewer.evaluator) !== reviewer.keyId)
|
|
146
|
+
ctx.addIssue({ code: "custom", path: ["admission", "reviewers", index], message: "reviewer binding does not resolve to one exact carried public key" });
|
|
147
|
+
}
|
|
148
|
+
if (new Set(reviewers.map((entry) => entry.keyId)).size !== reviewers.length)
|
|
149
|
+
ctx.addIssue({ code: "custom", path: ["admission", "reviewers"], message: "reviewer keys must be distinct" });
|
|
150
|
+
const authorityRoles = trust.admission.authorities.map((entry) => entry.role);
|
|
151
|
+
const humanRoles = ["roster-attestor", "truth-reveal-attestor"];
|
|
152
|
+
const operatorRoles = ["operator-truth-attestor"];
|
|
153
|
+
// Third legal authority set (spec §6.8a Group C, third bullet; packet P6): the screened
|
|
154
|
+
// branch's ordering receipt (§6.6) presents `truth-reveal-attestor` alone -- neither of the two
|
|
155
|
+
// existing sets. `AdmissionAuthorityRole` itself stays unchanged (§6.6 deliberately reuses the
|
|
156
|
+
// role rather than minting one).
|
|
157
|
+
const screenedRoles = ["truth-reveal-attestor"];
|
|
158
|
+
if (JSON.stringify(authorityRoles) !== JSON.stringify(humanRoles)
|
|
159
|
+
&& JSON.stringify(authorityRoles) !== JSON.stringify(operatorRoles)
|
|
160
|
+
&& JSON.stringify(authorityRoles) !== JSON.stringify(screenedRoles))
|
|
161
|
+
ctx.addIssue({ code: "custom", path: ["admission", "authorities"], message: "authority bindings must be exactly the human pair, the operator-only role, or the screened role alone" });
|
|
162
|
+
if (trust.admission.authorities.some((entry) => entry.keyId !== trust.report.keyId))
|
|
163
|
+
ctx.addIssue({ code: "custom", path: ["admission", "authorities"], message: "admission authority must resolve to the carried report-authority public key" });
|
|
164
|
+
});
|
|
165
|
+
// The /2 catalog's original twelve roles, plus the three binary-family records
|
|
166
|
+
// pairwise-disagreement@1 / paired-majority-delta@1 recompute from (packet P5).
|
|
167
|
+
// Existing /2 bundles do not declare the three; adding them is a compatible
|
|
168
|
+
// widening. Snapshot-probe and the admission-only V4 roles stay V4-only.
|
|
169
|
+
export const BUNDLE_EVIDENCE_ROLES = [
|
|
170
|
+
"task",
|
|
171
|
+
"runtime-selection",
|
|
172
|
+
"evaluation-spec",
|
|
173
|
+
"admission-receipt",
|
|
174
|
+
"solve-submission",
|
|
175
|
+
"run-pinning-evidence",
|
|
176
|
+
"evaluation-submission",
|
|
177
|
+
"solve-delivery",
|
|
178
|
+
"solve-output",
|
|
179
|
+
"evaluation-task",
|
|
180
|
+
"evaluation-delivery",
|
|
181
|
+
"verdict",
|
|
182
|
+
"judge-instrument",
|
|
183
|
+
"analysis-context",
|
|
184
|
+
"label-resolution",
|
|
185
|
+
];
|
|
186
|
+
export const BundleEvidenceCatalogSchema = z.object({
|
|
187
|
+
format: z.literal(BUNDLE_EVIDENCE_FORMAT),
|
|
188
|
+
records: z.array(z.object({
|
|
189
|
+
sha256: Sha256HexSchema,
|
|
190
|
+
roles: z.array(z.enum(BUNDLE_EVIDENCE_ROLES)).min(1),
|
|
191
|
+
})),
|
|
192
|
+
});
|
|
193
|
+
export const BundleV4EvidenceCatalogSchema = z.strictObject({
|
|
194
|
+
format: z.literal(BUNDLE_V4_EVIDENCE_FORMAT),
|
|
195
|
+
records: z.array(z.strictObject({
|
|
196
|
+
sha256: Sha256HexSchema,
|
|
197
|
+
roles: z.array(z.enum(BUNDLE_V4_EVIDENCE_ROLES)).min(1),
|
|
198
|
+
})),
|
|
199
|
+
}).superRefine((catalog, ctx) => {
|
|
200
|
+
for (let index = 0; index < catalog.records.length; index += 1) {
|
|
201
|
+
const record = catalog.records[index];
|
|
202
|
+
if (index > 0 && compareCodeUnitStrings(catalog.records[index - 1].sha256, record.sha256) >= 0)
|
|
203
|
+
ctx.addIssue({ code: "custom", path: ["records", index], message: "records must be sorted and unique" });
|
|
204
|
+
const order = new Map(BUNDLE_V4_EVIDENCE_ROLES.map((role, roleIndex) => [role, roleIndex]));
|
|
205
|
+
for (let roleIndex = 1; roleIndex < record.roles.length; roleIndex += 1) {
|
|
206
|
+
if (order.get(record.roles[roleIndex - 1]) >= order.get(record.roles[roleIndex]))
|
|
207
|
+
ctx.addIssue({ code: "custom", path: ["records", index, "roles"], message: "roles must be in frozen order and unique" });
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
const PrefixedSha256Schema = z.string().regex(/^sha256:[a-f0-9]{64}$/u);
|
|
212
|
+
// §3.1 rule 1: the same identifier dialect used for stratum names elsewhere (e.g.
|
|
213
|
+
// `admission/contracts.ts`'s `BinaryJudgmentStratumSchema`). `candidateClasses` below deliberately
|
|
214
|
+
// stays ungrammared: tightening it is outside P4's contract and could refuse bundles written today.
|
|
215
|
+
const IDENTIFIER_NAME = /^[A-Za-z][A-Za-z0-9._-]{0,63}$/u;
|
|
216
|
+
export const BundleQualificationSchema = z.strictObject({
|
|
217
|
+
format: z.literal(BUNDLE_QUALIFICATION_FORMAT),
|
|
218
|
+
claimSchema: z.literal("benchmark-product.claim-package/2"),
|
|
219
|
+
sourceManifestSha256: PrefixedSha256Schema,
|
|
220
|
+
admissionManifestSha256: PrefixedSha256Schema,
|
|
221
|
+
publicationGrade: z.boolean(),
|
|
222
|
+
// Widened spec §6.8 (packet P6): a third admission mode, screened by a pinned model and
|
|
223
|
+
// sampled/hand-checked by the operator. BUNDLE_QUALIFICATION_FORMAT does not move (§0.4): every
|
|
224
|
+
// existing document still validates and seals byte-identically. The publicationGrade coupling
|
|
225
|
+
// for this third branch, and the admission-record/authority-set closure that makes a screened
|
|
226
|
+
// document constructible at all, are out of this packet's scope (spec §6.8a Group A/C).
|
|
227
|
+
truthAdmission: z.enum(["two-human-unanimous", "operator-only", "screened-operator-sampled"]),
|
|
228
|
+
candidateClasses: z.array(z.string().min(1)),
|
|
229
|
+
// Sorted-unique, grammar-conforming, non-empty (spec §3.1 rule 6). BUNDLE_QUALIFICATION_FORMAT
|
|
230
|
+
// stays at its current version under §0.4: every ["core","stress"] bundle ever written still
|
|
231
|
+
// validates, byte-identically.
|
|
232
|
+
strata: z.array(z.string().regex(IDENTIFIER_NAME)).min(1),
|
|
233
|
+
// .min(2), not a literal count (spec §1.6 rule 3). BUNDLE_QUALIFICATION_FORMAT stays at its
|
|
234
|
+
// current version under §0.4: every four-arm bundle ever written still validates,
|
|
235
|
+
// byte-identically.
|
|
236
|
+
arms: z.array(z.strictObject({
|
|
237
|
+
armId: z.string().min(1),
|
|
238
|
+
instrumentSha256: PrefixedSha256Schema,
|
|
239
|
+
})).min(2),
|
|
240
|
+
items: z.array(z.strictObject({
|
|
241
|
+
taskSha256: PrefixedSha256Schema,
|
|
242
|
+
itemSha256: PrefixedSha256Schema,
|
|
243
|
+
labelResolutionSha256: PrefixedSha256Schema,
|
|
244
|
+
analysisContextSha256: PrefixedSha256Schema,
|
|
245
|
+
})),
|
|
246
|
+
exclusions: z.array(z.strictObject({
|
|
247
|
+
itemSha256: PrefixedSha256Schema,
|
|
248
|
+
replacementItemSha256: PrefixedSha256Schema,
|
|
249
|
+
// Widened spec §6.4 (packet P6), second copy of the replacement-ledger reason vocabulary
|
|
250
|
+
// (the first is `admission/contracts.ts`'s `HumanReviewReplacementLedgerEntrySchema.reason`).
|
|
251
|
+
// The existing three values are byte-unchanged; the three new values are derived from §6.4's
|
|
252
|
+
// admission rule (screen disagreed, screen indeterminate, or the hand check excluded it).
|
|
253
|
+
reason: z.enum([
|
|
254
|
+
"review-disagreement", "review-indeterminate", "review-incomplete",
|
|
255
|
+
"screening-disagreement", "screening-indeterminate", "screening-hand-excluded",
|
|
256
|
+
]),
|
|
257
|
+
})),
|
|
258
|
+
admissionRecords: z.array(z.strictObject({
|
|
259
|
+
sha256: PrefixedSha256Schema,
|
|
260
|
+
roles: z.array(z.enum(BUNDLE_V4_ADMISSION_EVIDENCE_ROLES)).min(1),
|
|
261
|
+
})),
|
|
262
|
+
reachableSha256s: z.array(PrefixedSha256Schema),
|
|
263
|
+
}).superRefine((qualification, ctx) => {
|
|
264
|
+
const sortedUnique = (values, path) => {
|
|
265
|
+
for (let index = 1; index < values.length; index += 1) {
|
|
266
|
+
if (compareCodeUnitStrings(values[index - 1], values[index]) >= 0)
|
|
267
|
+
ctx.addIssue({ code: "custom", path, message: "values must be code-unit sorted and unique" });
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
sortedUnique(qualification.candidateClasses, ["candidateClasses"]);
|
|
271
|
+
sortedUnique(qualification.strata, ["strata"]);
|
|
272
|
+
sortedUnique(qualification.arms.map((entry) => entry.armId), ["arms"]);
|
|
273
|
+
sortedUnique(qualification.items.map((entry) => entry.taskSha256), ["items"]);
|
|
274
|
+
for (const field of ["itemSha256", "labelResolutionSha256", "analysisContextSha256"]) {
|
|
275
|
+
if (new Set(qualification.items.map((entry) => entry[field])).size !== qualification.items.length)
|
|
276
|
+
ctx.addIssue({ code: "custom", path: ["items"], message: `${field} edges must be unique` });
|
|
277
|
+
}
|
|
278
|
+
sortedUnique(qualification.exclusions.map((entry) => entry.itemSha256), ["exclusions"]);
|
|
279
|
+
sortedUnique(qualification.admissionRecords.map((entry) => entry.sha256), ["admissionRecords"]);
|
|
280
|
+
const admissionRoleOrder = new Map(BUNDLE_V4_ADMISSION_EVIDENCE_ROLES.map((role, index) => [role, index]));
|
|
281
|
+
for (const [recordIndex, record] of qualification.admissionRecords.entries()) {
|
|
282
|
+
for (let roleIndex = 1; roleIndex < record.roles.length; roleIndex += 1) {
|
|
283
|
+
if (admissionRoleOrder.get(record.roles[roleIndex - 1]) >= admissionRoleOrder.get(record.roles[roleIndex]))
|
|
284
|
+
ctx.addIssue({ code: "custom", path: ["admissionRecords", recordIndex, "roles"], message: "admission roles must be in frozen order and unique" });
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
sortedUnique(qualification.reachableSha256s, ["reachableSha256s"]);
|
|
288
|
+
// Counts against arms.length, not the literal 4 (spec §1.6 rule 3, site 9).
|
|
289
|
+
if (new Set(qualification.arms.map((entry) => entry.instrumentSha256)).size !== qualification.arms.length)
|
|
290
|
+
ctx.addIssue({ code: "custom", path: ["arms"], message: "arms must bind one distinct instrument each" });
|
|
291
|
+
for (const [index, item] of qualification.items.entries()) {
|
|
292
|
+
for (const digest of [item.itemSha256, item.labelResolutionSha256, item.analysisContextSha256]) {
|
|
293
|
+
if (!qualification.reachableSha256s.includes(digest))
|
|
294
|
+
ctx.addIssue({ code: "custom", path: ["items", index], message: "item graph edge is absent from the authenticated admission closure" });
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
for (const [index, exclusion] of qualification.exclusions.entries()) {
|
|
298
|
+
if (!qualification.reachableSha256s.includes(exclusion.itemSha256) || !qualification.reachableSha256s.includes(exclusion.replacementItemSha256))
|
|
299
|
+
ctx.addIssue({ code: "custom", path: ["exclusions", index], message: "exclusion graph edge is absent from the authenticated admission closure" });
|
|
300
|
+
}
|
|
301
|
+
if (!qualification.reachableSha256s.includes(qualification.admissionManifestSha256))
|
|
302
|
+
ctx.addIssue({ code: "custom", path: ["admissionManifestSha256"], message: "admission manifest is absent from reachable closure" });
|
|
303
|
+
const rolesByDigest = new Map(qualification.admissionRecords.map((entry) => [entry.sha256, new Set(entry.roles)]));
|
|
304
|
+
const requireRole = (digest, role, path) => {
|
|
305
|
+
if (!rolesByDigest.get(digest)?.has(role))
|
|
306
|
+
ctx.addIssue({ code: "custom", path, message: `${digest} is not bound to semantic role ${role}` });
|
|
307
|
+
};
|
|
308
|
+
requireRole(qualification.admissionManifestSha256, "admission-manifest", ["admissionManifestSha256"]);
|
|
309
|
+
for (const [index, item] of qualification.items.entries()) {
|
|
310
|
+
requireRole(item.itemSha256, "source-item", ["items", index, "itemSha256"]);
|
|
311
|
+
requireRole(item.labelResolutionSha256, "label-resolution", ["items", index, "labelResolutionSha256"]);
|
|
312
|
+
requireRole(item.analysisContextSha256, "analysis-context", ["items", index, "analysisContextSha256"]);
|
|
313
|
+
}
|
|
314
|
+
for (const [index, exclusion] of qualification.exclusions.entries()) {
|
|
315
|
+
requireRole(exclusion.itemSha256, "source-item", ["exclusions", index, "itemSha256"]);
|
|
316
|
+
requireRole(exclusion.replacementItemSha256, "source-item", ["exclusions", index, "replacementItemSha256"]);
|
|
317
|
+
}
|
|
318
|
+
const roleCounts = new Map(BUNDLE_V4_ADMISSION_EVIDENCE_ROLES.map((role) => [
|
|
319
|
+
role,
|
|
320
|
+
qualification.admissionRecords.filter((entry) => entry.roles.includes(role)).length,
|
|
321
|
+
]));
|
|
322
|
+
if (roleCounts.get("admission-manifest") !== 1 || roleCounts.get("replacement-ledger") !== 1
|
|
323
|
+
|| roleCounts.get("human-review-evaluation-spec") !== 1 || roleCounts.get("human-review-form") !== 1) {
|
|
324
|
+
ctx.addIssue({ code: "custom", path: ["admissionRecords"], message: "admission closure must bind one manifest, ledger, frozen review spec, and frozen review form" });
|
|
325
|
+
}
|
|
326
|
+
const humanEvidenceRoles = [
|
|
327
|
+
"human-review-packet", "human-review-response", "human-review-verdict", "reviewer-roster",
|
|
328
|
+
"review-visibility-receipt", "review-reveal-receipt",
|
|
329
|
+
];
|
|
330
|
+
const commonScreeningEvidenceRoles = ["screening-table", "screening-reveal-receipt", "screening-sampling-script"];
|
|
331
|
+
const legacyScreeningEvidenceRoles = ["screening-instrument", "screening-raw-outputs"];
|
|
332
|
+
const promptedScreeningEvidenceRoles = [
|
|
333
|
+
"screening-prompt", "screening-procedure", "screening-pool",
|
|
334
|
+
"screening-sample-commitment", "screening-transcript",
|
|
335
|
+
];
|
|
336
|
+
if (qualification.truthAdmission === "two-human-unanimous") {
|
|
337
|
+
if (humanEvidenceRoles.some((role) => (roleCounts.get(role) ?? 0) === 0)
|
|
338
|
+
|| roleCounts.get("operator-assertion") !== 0) {
|
|
339
|
+
ctx.addIssue({ code: "custom", path: ["admissionRecords"], message: "two-human admission must carry the frozen human-review closure and no operator assertion" });
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
else if (qualification.truthAdmission === "operator-only") {
|
|
343
|
+
if (humanEvidenceRoles.some((role) => (roleCounts.get(role) ?? 0) !== 0) || (roleCounts.get("operator-assertion") ?? 0) === 0) {
|
|
344
|
+
ctx.addIssue({ code: "custom", path: ["admissionRecords"], message: "operator-only admission must carry operator assertions and no human-review evidence" });
|
|
345
|
+
}
|
|
346
|
+
// Spec §6.8a Group C, second bullet. Named explicitly rather than left as a bare `else`: this
|
|
347
|
+
// was the family's last catch-all router, and Group B's doctrine is that a mode-dispatching
|
|
348
|
+
// branch names the mode it handles, so a fourth admission mode lands in no arm instead of
|
|
349
|
+
// silently inheriting the screened one's evidence rules.
|
|
350
|
+
}
|
|
351
|
+
else if (qualification.truthAdmission === "screened-operator-sampled") {
|
|
352
|
+
const legacyRoleSet = legacyScreeningEvidenceRoles.every((role) => roleCounts.get(role) === 1)
|
|
353
|
+
&& promptedScreeningEvidenceRoles.every((role) => roleCounts.get(role) === 0);
|
|
354
|
+
const promptedRoleSet = promptedScreeningEvidenceRoles.every((role) => roleCounts.get(role) === 1)
|
|
355
|
+
&& legacyScreeningEvidenceRoles.every((role) => roleCounts.get(role) === 0);
|
|
356
|
+
if (commonScreeningEvidenceRoles.some((role) => (roleCounts.get(role) ?? 0) !== 1)
|
|
357
|
+
|| (!legacyRoleSet && !promptedRoleSet)
|
|
358
|
+
|| humanEvidenceRoles.some((role) => (roleCounts.get(role) ?? 0) !== 0)
|
|
359
|
+
|| (roleCounts.get("operator-assertion") ?? 0) !== 0) {
|
|
360
|
+
ctx.addIssue({ code: "custom", path: ["admissionRecords"], message: "screened admission must carry exactly one complete legacy-v1 or prompted-v2 screening record set and no human-review evidence or operator assertion" });
|
|
361
|
+
}
|
|
362
|
+
const screeningInstrument = qualification.admissionRecords.find((entry) => (entry.roles.includes("screening-instrument")));
|
|
363
|
+
if (screeningInstrument !== undefined
|
|
364
|
+
&& qualification.arms.some((arm) => arm.instrumentSha256 === screeningInstrument.sha256)) {
|
|
365
|
+
ctx.addIssue({ code: "custom", path: ["arms"], message: "the screening instrument cannot also be a run judge arm" });
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
if (qualification.admissionRecords.length !== qualification.reachableSha256s.length
|
|
369
|
+
|| qualification.admissionRecords.some((entry, index) => entry.sha256 !== qualification.reachableSha256s[index]))
|
|
370
|
+
ctx.addIssue({ code: "custom", path: ["admissionRecords"], message: "semantic admission roles must exactly cover reachableSha256s" });
|
|
371
|
+
if (qualification.truthAdmission === "two-human-unanimous" && !qualification.publicationGrade)
|
|
372
|
+
ctx.addIssue({ code: "custom", path: ["publicationGrade"], message: "two-human unanimous truth is publication grade" });
|
|
373
|
+
if (qualification.truthAdmission === "operator-only" && qualification.publicationGrade)
|
|
374
|
+
ctx.addIssue({ code: "custom", path: ["publicationGrade"], message: "operator-only truth is not publication grade" });
|
|
375
|
+
// §6.8: the screened branch is publication-grade -- without this branch, §6.8a Group A's fix to
|
|
376
|
+
// the two publicationGrade derivations (verification.ts, human-review.ts) would have nothing to
|
|
377
|
+
// enforce against.
|
|
378
|
+
if (qualification.truthAdmission === "screened-operator-sampled" && !qualification.publicationGrade)
|
|
379
|
+
ctx.addIssue({ code: "custom", path: ["publicationGrade"], message: "screened-operator-sampled truth is publication grade" });
|
|
380
|
+
});
|
|
381
|
+
export const BundleVerdictCatalogSchema = z.object({
|
|
382
|
+
format: z.literal(BUNDLE_VERDICTS_FORMAT),
|
|
383
|
+
verdicts: z.array(z.object({
|
|
384
|
+
sha256: Sha256HexSchema,
|
|
385
|
+
evaluator: z.string().min(1),
|
|
386
|
+
keyId: z.string().min(1),
|
|
387
|
+
cellKeys: z.array(z.string().min(1)).min(1),
|
|
388
|
+
})),
|
|
389
|
+
});
|
|
390
|
+
const AssemblyVerdictSchema = z.object({
|
|
391
|
+
sha256: Sha256HexSchema,
|
|
392
|
+
relationship: z.enum(["same-execution-scorer", "separate-log-verifier"]).optional(),
|
|
393
|
+
evalTaskSha256: Sha256HexSchema.optional(),
|
|
394
|
+
evalSubmissionSha256: Sha256HexSchema.optional(),
|
|
395
|
+
evalDeliverySha256: Sha256HexSchema.optional(),
|
|
396
|
+
evalAttempt: z.string().min(1).optional(),
|
|
397
|
+
evalIndex: z.number().int().positive(),
|
|
398
|
+
evaluator: z.string().min(1),
|
|
399
|
+
verdict: z.enum(["pass", "fail", "inconclusive"]),
|
|
400
|
+
evaluationSpecSha256: Sha256HexSchema,
|
|
401
|
+
measurements: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])),
|
|
402
|
+
});
|
|
403
|
+
export const BundleAssemblyHeaderSchema = z.object({
|
|
404
|
+
format: z.literal(BUNDLE_ASSEMBLY_FORMAT),
|
|
405
|
+
kind: z.literal("run"),
|
|
406
|
+
runCancelled: z.boolean(),
|
|
407
|
+
draftId: z.string().min(1),
|
|
408
|
+
assurancePreset: z.string().min(1),
|
|
409
|
+
rehearsal: z.object({
|
|
410
|
+
previewCount: z.number().int().positive(),
|
|
411
|
+
timestamps: z.array(Rfc3339Schema).min(1),
|
|
412
|
+
}).optional(),
|
|
413
|
+
graph: z.object({
|
|
414
|
+
admissions: z.array(z.object({ taskSha256: Sha256HexSchema, receiptSha256: Sha256HexSchema })),
|
|
415
|
+
solveSubmissions: z.array(z.object({
|
|
416
|
+
cellKey: z.string().min(1),
|
|
417
|
+
dispatch: z.number().int().positive(),
|
|
418
|
+
sha256: Sha256HexSchema,
|
|
419
|
+
pinningEvidenceSha256: Sha256HexSchema.optional(),
|
|
420
|
+
})),
|
|
421
|
+
evaluationSubmissions: z.array(z.object({
|
|
422
|
+
cellKey: z.string().min(1),
|
|
423
|
+
dispatch: z.number().int().positive(),
|
|
424
|
+
evalIndex: z.number().int().positive(),
|
|
425
|
+
evaluationAttempt: z.number().int().positive().optional(),
|
|
426
|
+
evaluator: z.string().min(1),
|
|
427
|
+
evalTaskSha256: Sha256HexSchema,
|
|
428
|
+
sha256: Sha256HexSchema,
|
|
429
|
+
})),
|
|
430
|
+
solveDeliveries: z.array(z.object({
|
|
431
|
+
cellKey: z.string().min(1),
|
|
432
|
+
dispatch: z.number().int().positive(),
|
|
433
|
+
attempt: z.string().min(1),
|
|
434
|
+
sha256: Sha256HexSchema,
|
|
435
|
+
outputs: z.array(z.object({ name: z.string(), sha256: Sha256HexSchema })),
|
|
436
|
+
})),
|
|
437
|
+
evaluations: z.array(z.object({
|
|
438
|
+
cellKey: z.string().min(1),
|
|
439
|
+
evalIndex: z.number().int().positive(),
|
|
440
|
+
evaluationAttempt: z.number().int().positive().optional(),
|
|
441
|
+
relationship: z.enum(["same-execution-scorer", "separate-log-verifier"]).optional(),
|
|
442
|
+
evaluator: z.string().optional(),
|
|
443
|
+
evalTaskSha256: Sha256HexSchema.optional(),
|
|
444
|
+
evalSubmissionSha256: Sha256HexSchema.optional(),
|
|
445
|
+
evalAttempt: z.string().optional(),
|
|
446
|
+
evalDeliverySha256: Sha256HexSchema.optional(),
|
|
447
|
+
verdictSha256: Sha256HexSchema.optional(),
|
|
448
|
+
evaluationTerminal: z.literal("could-not-grade").optional(),
|
|
449
|
+
/** The operational category that terminalized this leg as could-not-grade. Present only
|
|
450
|
+
* on a could-not-grade terminal whose journal entry recorded one, which today is the
|
|
451
|
+
* infrastructure failure that exhausted the sealed retry budget. Without it the accounted
|
|
452
|
+
* ungradeable cell reaches the bundle as an uncategorized absence: `evaluationRetries`
|
|
453
|
+
* carries the category of every failure that WAS retried, and the terminal one is the
|
|
454
|
+
* only failure in the leg that has no retry row to carry it. Additive and optional, so
|
|
455
|
+
* every bundle that carried no such terminal seals to identical bytes. */
|
|
456
|
+
failureCategory: z.enum(TASK_EXECUTION_ERROR_CATEGORIES).optional(),
|
|
457
|
+
})),
|
|
458
|
+
evaluationRetries: z.array(z.object({
|
|
459
|
+
cellKey: z.string().min(1),
|
|
460
|
+
dispatch: z.number().int().positive(),
|
|
461
|
+
evalIndex: z.number().int().positive(),
|
|
462
|
+
evaluationAttempt: z.number().int().positive(),
|
|
463
|
+
evaluator: z.string().min(1),
|
|
464
|
+
evalTaskSha256: Sha256HexSchema.optional(),
|
|
465
|
+
evalSubmissionSha256: Sha256HexSchema.optional(),
|
|
466
|
+
evalAttempt: z.string().min(1).optional(),
|
|
467
|
+
failureCategory: z.enum(TASK_EXECUTION_ERROR_CATEGORIES),
|
|
468
|
+
recoveryAdvice: z.literal("new-attempt-required"),
|
|
469
|
+
detail: z.string().min(1),
|
|
470
|
+
})).optional(),
|
|
471
|
+
}),
|
|
472
|
+
});
|
|
473
|
+
export const BundleAssemblyCellSchema = z.object({
|
|
474
|
+
kind: z.literal("cell"),
|
|
475
|
+
cellKey: z.string().min(1),
|
|
476
|
+
armId: z.string().min(1),
|
|
477
|
+
replicate: z.number().int().positive(),
|
|
478
|
+
taskDigest: Sha256HexSchema,
|
|
479
|
+
dispatches: z.number().int().nonnegative(),
|
|
480
|
+
accounted: z.number().int().positive().optional(),
|
|
481
|
+
submissionSha256: Sha256HexSchema.optional(),
|
|
482
|
+
pinningEvidenceSha256: Sha256HexSchema.optional(),
|
|
483
|
+
attempt: z.string().min(1).optional(),
|
|
484
|
+
deliverySha256: Sha256HexSchema.optional(),
|
|
485
|
+
solveOutputs: z.array(z.object({ name: z.string(), sha256: Sha256HexSchema })).optional(),
|
|
486
|
+
evaluationSpecSha256: Sha256HexSchema.optional(),
|
|
487
|
+
evaluationTerminal: z.literal("could-not-grade").optional(),
|
|
488
|
+
admission: z.object({
|
|
489
|
+
zeroReplayVariance: z.boolean(),
|
|
490
|
+
externalCapabilities: z.boolean(),
|
|
491
|
+
}).optional(),
|
|
492
|
+
admissionReceiptSha256: Sha256HexSchema.optional(),
|
|
493
|
+
verdicts: z.array(AssemblyVerdictSchema),
|
|
494
|
+
});
|
|
495
|
+
export const BundleCancelMarkerSchema = z.object({
|
|
496
|
+
requestedAt: Rfc3339Schema,
|
|
497
|
+
principal: z.string().min(1),
|
|
498
|
+
});
|
package/dist/verify.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { type EvidenceNativePortableBundleVerification } from "@jinn-network/benchmarking-evidence";
|
|
2
|
+
import { type InspectRuntimeMethodDisclosure } from "./profile/inspect-disclosure.js";
|
|
3
|
+
import { type PublicComparisonView } from "./comparison.js";
|
|
4
|
+
import { type VerifiedBundleSnapshot, type VerifyBundleSnapshotDeps } from "./manifest.js";
|
|
5
|
+
import { type IntegrityAnchorsReport, type PublicBundleAnchorTrustMaterial } from "./anchor/check.js";
|
|
6
|
+
import { type BinaryItemBankEntry, type BinarySourceManifestEntry } from "./admission/intake.js";
|
|
7
|
+
export type PublicBundleVerificationCheck = "manifest" | "evidence-closure" | "trust" | "matrix-rederivation" | "report-verification" | "claim-consistency"
|
|
8
|
+
/** Always present for `benchmark-product-public-bundle/6`, never for any earlier closure
|
|
9
|
+
* (anchor-evidence design §8, §12). */
|
|
10
|
+
| "integrity-anchors";
|
|
11
|
+
export interface LegacyPublicBundleVerificationResult {
|
|
12
|
+
readonly format: "benchmark-product-public-bundle/2" | "benchmark-product-public-bundle/4" | "benchmark-product-public-bundle/6";
|
|
13
|
+
readonly identity: string;
|
|
14
|
+
readonly checks: readonly PublicBundleVerificationCheck[];
|
|
15
|
+
readonly benchmarkSha256: string;
|
|
16
|
+
readonly runSha256: string;
|
|
17
|
+
readonly matrixSha256: string;
|
|
18
|
+
readonly reportSha256: string;
|
|
19
|
+
readonly reportEnvelopeSha256: string;
|
|
20
|
+
readonly runtimeMethod?: InspectRuntimeMethodDisclosure;
|
|
21
|
+
/** Present exactly for the anchored closure: every carried anchor's own outcome plus each
|
|
22
|
+
* subject's context outcome (anchor-evidence design §8). Statuses are disclosed facts, not a
|
|
23
|
+
* summary — nothing here is folded into a single verified badge. */
|
|
24
|
+
readonly anchors?: IntegrityAnchorsReport;
|
|
25
|
+
readonly qualification?: {
|
|
26
|
+
readonly publicationGrade: boolean;
|
|
27
|
+
readonly truthAdmission: "two-human-unanimous" | "operator-only" | "screened-operator-sampled";
|
|
28
|
+
readonly candidateClasses: readonly string[];
|
|
29
|
+
readonly strata: readonly string[];
|
|
30
|
+
readonly armCount: number;
|
|
31
|
+
readonly itemCount: number;
|
|
32
|
+
readonly exclusionCount: number;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export type PublicBundleVerificationResult = LegacyPublicBundleVerificationResult | EvidenceNativePortableBundleVerification;
|
|
36
|
+
export interface VerifyPublicBundleDeps extends VerifyBundleSnapshotDeps {
|
|
37
|
+
/**
|
|
38
|
+
* Trust material for the `integrity-anchors` check (anchor-evidence design §8 step 3): timestamp
|
|
39
|
+
* authority roots, Bitcoin block headers. **Strictly the verifier operator's own configuration.**
|
|
40
|
+
* This package ships none, so the default outcome for a well-formed proof is `present`, not
|
|
41
|
+
* `verified`; a chain validated solely against roots a bundle carried would re-import the
|
|
42
|
+
* self-run problem with extra ceremony.
|
|
43
|
+
*/
|
|
44
|
+
readonly anchorTrust?: PublicBundleAnchorTrustMaterial;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* One semantically verified result bound to the exact authenticated bytes used
|
|
48
|
+
* to derive it. Consumers such as the local reader must serve these bytes
|
|
49
|
+
* rather than reopening bundle paths after verification.
|
|
50
|
+
*/
|
|
51
|
+
export interface VerifiedPublicBundleSnapshot {
|
|
52
|
+
readonly verification: PublicBundleVerificationResult;
|
|
53
|
+
readonly comparison?: PublicComparisonView;
|
|
54
|
+
readonly snapshot: VerifiedBundleSnapshot;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The cold verifier's item-bank/source-manifest closure, over already-parsed canonical rows.
|
|
58
|
+
*
|
|
59
|
+
* Exported so the closure can be exercised directly. It has to be: a bundle whose cluster key is
|
|
60
|
+
* decoupled from its declared sources cannot be produced by this repository's own import path,
|
|
61
|
+
* because the importer's code-unit-least rule is strictly stronger than the membership rule below.
|
|
62
|
+
* This check exists for bundles produced by other implementations, so its test has to construct
|
|
63
|
+
* the rows rather than round-trip them through the importer.
|
|
64
|
+
*/
|
|
65
|
+
export declare function checkItemBankSourceClosure(itemRows: readonly BinaryItemBankEntry[], sourceRows: readonly BinarySourceManifestEntry[]): {
|
|
66
|
+
readonly itemDigests: ReadonlySet<string>;
|
|
67
|
+
};
|
|
68
|
+
/** Verifies a copied public bundle using one authenticated byte snapshot and only bundle-carried
|
|
69
|
+
* public keys. No pathname is reopened after manifest authentication. */
|
|
70
|
+
export declare function verifyPublicBundleSnapshot(bundleDir: string, deps?: VerifyPublicBundleDeps): Promise<VerifiedPublicBundleSnapshot>;
|
|
71
|
+
/** Verifies a bundle without exposing its authenticated byte snapshot. */
|
|
72
|
+
export declare function verifyPublicBundle(bundleDir: string, deps?: VerifyPublicBundleDeps): Promise<PublicBundleVerificationResult>;
|