@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/profile/claim.js
CHANGED
|
@@ -27,13 +27,19 @@
|
|
|
27
27
|
* disclosure. The one deliberate exception to "never cross-check here": `buildClaimPackage`
|
|
28
28
|
* THROWS when the stated primitives disagree with what the sealed Run record's own policy
|
|
29
29
|
* carries — a claim stating primitives the sealed Run does not carry would be dishonest.
|
|
30
|
+
*
|
|
31
|
+
* Issue #3205: the claim id is chosen on TWO independent axes — anchored or not, and
|
|
32
|
+
* qualification-projecting or not — which is four allocations, not three. `claim-package/5` is
|
|
33
|
+
* the fourth cell; before it existed an anchored binary-instrument run could not produce a
|
|
34
|
+
* claim at all, which made anchoring and binary-instrument benchmarking mutually exclusive.
|
|
30
35
|
*/
|
|
31
36
|
import { z } from "zod";
|
|
32
37
|
import { Buffer } from "node:buffer";
|
|
33
38
|
import { validateBinaryInstrumentQualificationProjection } from "@jinn-network/benchmarking-aggregate";
|
|
34
39
|
import { BENCHMARKING_METHOD_IDS, BENCHMARKING_METHOD_VERSION } from "@jinn-network/benchmarking-records";
|
|
35
40
|
import { canonicalJsonBytes } from "@jinn-network/trust-core";
|
|
36
|
-
import { PUBLIC_BUNDLE_COMPATIBLE_VERIFICATION_COMMAND, PUBLIC_BUNDLE_VERIFICATION_CHECKS as READER_VERIFICATION_CHECKS, PUBLIC_BUNDLE_VERIFICATION_COMMAND as READER_VERIFICATION_COMMAND, PUBLIC_BUNDLE_V6_CHECKS as READER_ANCHORED_VERIFICATION_CHECKS, PUBLIC_BUNDLE_V6_COMPATIBLE_VERIFICATION_COMMAND, PUBLIC_BUNDLE_V6_VERIFICATION_COMMAND, } from "../reader-instructions.js";
|
|
41
|
+
import { PUBLIC_BUNDLE_COMPATIBLE_VERIFICATION_COMMAND, PUBLIC_BUNDLE_VERIFICATION_CHECKS as READER_VERIFICATION_CHECKS, PUBLIC_BUNDLE_VERIFICATION_COMMAND as READER_VERIFICATION_COMMAND, PUBLIC_BUNDLE_V6_CHECKS as READER_ANCHORED_VERIFICATION_CHECKS, PUBLIC_BUNDLE_V6_COMPATIBLE_VERIFICATION_COMMAND, PUBLIC_BUNDLE_V6_VERIFICATION_COMMAND, PUBLIC_BUNDLE_V7_CHECKS as READER_ANCHORED_QUALIFICATION_VERIFICATION_CHECKS, PUBLIC_BUNDLE_V7_COMPATIBLE_VERIFICATION_COMMAND, PUBLIC_BUNDLE_V7_VERIFICATION_COMMAND, PUBLIC_BUNDLE_V8_CHECKS as READER_DISCLOSED_VERIFICATION_CHECKS, } from "../reader-instructions.js";
|
|
42
|
+
import { ClaimDisclosureSectionSchema } from "./disclosure.js";
|
|
37
43
|
import { PROMPTED_SCREENING_PROFILE } from "../admission/contracts.js";
|
|
38
44
|
import { ClaimAnchorSchema, SELF_RUN_TRUST_ROOT, anchoredTrustRoot } from "./anchor-claims.js";
|
|
39
45
|
export const CLAIM_PACKAGE_SCHEMA_ID = "benchmark-product.claim-package/1";
|
|
@@ -45,10 +51,34 @@ export const BINARY_QUALIFICATION_CLAIM_PACKAGE_SCHEMA_ID = "benchmark-product.c
|
|
|
45
51
|
* own later allocation.
|
|
46
52
|
*/
|
|
47
53
|
export const ANCHORED_CLAIM_PACKAGE_SCHEMA_ID = "benchmark-product.claim-package/4";
|
|
54
|
+
/**
|
|
55
|
+
* The anchored binary-qualification claim package (issue #3205): claim-package/2's exact
|
|
56
|
+
* qualification projection plus claim-package/4's `anchors` section, carried by
|
|
57
|
+
* `benchmark-product-public-bundle/7`. This is the "later allocation" both earlier guards named:
|
|
58
|
+
* /2 has no anchors slot and /4 has no qualification slot, so before this number existed an
|
|
59
|
+
* anchored run of a binary-instrument benchmark could not produce a claim at all. The allocation is
|
|
60
|
+
* an ADDITION — /1, /2, /3, and /4 keep their meanings and their bytes.
|
|
61
|
+
*/
|
|
62
|
+
export const ANCHORED_BINARY_QUALIFICATION_CLAIM_PACKAGE_SCHEMA_ID = "benchmark-product.claim-package/5";
|
|
63
|
+
/**
|
|
64
|
+
* The disclosed anchored binary-qualification claim package (issue #2839,
|
|
65
|
+
* disclosure-specification-record design §6.5/§6.6): claim-package/5 exactly, plus the
|
|
66
|
+
* `disclosure` section, carried by `benchmark-product-public-bundle/8`.
|
|
67
|
+
*
|
|
68
|
+
* The design reserved `/5` for its own disclosure allocation on the UNANCHORED qualified branch, on
|
|
69
|
+
* the premise (its §12.2) that anchoring and qualification could never combine. Issue #3205 both
|
|
70
|
+
* took `/5` and dissolved that premise, so per the design's own §6.5 rule — the implementation
|
|
71
|
+
* packet takes the then-next free numbers if a line has advanced — this is `/6`, and it stacks on
|
|
72
|
+
* the ANCHORED branch so the real flagship bundle can carry its disclosure record without giving up
|
|
73
|
+
* its anchor. The allocation is an ADDITION: /1, /2, /3, /4, and /5 keep their meanings and bytes.
|
|
74
|
+
*/
|
|
75
|
+
export const DISCLOSED_CLAIM_PACKAGE_SCHEMA_ID = "benchmark-product.claim-package/6";
|
|
48
76
|
export const BINARY_QUALIFICATION_VERIFICATION_COMMAND = "npx @colophon-claims/verify@0.1.0 <bundle-dir>";
|
|
49
77
|
export const BINARY_QUALIFICATION_COMPATIBLE_VERIFICATION_COMMAND = "npx @colophon-claims/verify@0.1 <bundle-dir>";
|
|
50
78
|
/** Prompted-screening v2 claims require the verifier release that carries that admission surface. */
|
|
51
|
-
export const PROMPTED_BINARY_QUALIFICATION_VERIFICATION_COMMAND = "npx @colophon-claims/verify@0.2.
|
|
79
|
+
export const PROMPTED_BINARY_QUALIFICATION_VERIFICATION_COMMAND = "npx @colophon-claims/verify@0.2.1 <bundle-dir>";
|
|
80
|
+
/** Previously materialized prompted bundles remain valid under their immutable 0.2.0 claim. */
|
|
81
|
+
export const LEGACY_PROMPTED_BINARY_QUALIFICATION_VERIFICATION_COMMAND = "npx @colophon-claims/verify@0.2.0 <bundle-dir>";
|
|
52
82
|
export const PROMPTED_BINARY_QUALIFICATION_COMPATIBLE_VERIFICATION_COMMAND = "npx @colophon-claims/verify@0.2 <bundle-dir>";
|
|
53
83
|
const Sha256HexSchema = z.string().regex(/^[a-f0-9]{64}$/, "must be a lowercase sha256 hex digest");
|
|
54
84
|
/** Mirrors `../run/preview-log.ts`'s own (unexported) `Rfc3339Schema` — restated here rather than
|
|
@@ -189,6 +219,8 @@ const ClaimPackageWireSchema = z.object({
|
|
|
189
219
|
z.literal(CLAIM_PACKAGE_SCHEMA_ID),
|
|
190
220
|
z.literal(BINARY_QUALIFICATION_CLAIM_PACKAGE_SCHEMA_ID),
|
|
191
221
|
z.literal(ANCHORED_CLAIM_PACKAGE_SCHEMA_ID),
|
|
222
|
+
z.literal(ANCHORED_BINARY_QUALIFICATION_CLAIM_PACKAGE_SCHEMA_ID),
|
|
223
|
+
z.literal(DISCLOSED_CLAIM_PACKAGE_SCHEMA_ID),
|
|
192
224
|
]),
|
|
193
225
|
scope: z.object({
|
|
194
226
|
draftId: z.string().min(1),
|
|
@@ -248,35 +280,70 @@ const ClaimPackageWireSchema = z.object({
|
|
|
248
280
|
* headline, comparison, threshold, selection, or ranking projection. */
|
|
249
281
|
qualification: z.unknown().optional(),
|
|
250
282
|
/** anchor-evidence §7.4: one entry per AnchorEvidence record the bundle carries, in record-digest
|
|
251
|
-
* order, each carrying only the facts embedded in the proof's own bytes. Present exactly on
|
|
252
|
-
* claim-package/4 — the schema-level refine below
|
|
253
|
-
*
|
|
283
|
+
* order, each carrying only the facts embedded in the proof's own bytes. Present exactly on the
|
|
284
|
+
* two anchored allocations, claim-package/4 and claim-package/5 — the schema-level refine below
|
|
285
|
+
* refuses it on /1 and /2, so an unanchored claim cannot grow an anchors section and an anchored
|
|
286
|
+
* one cannot be published without it. */
|
|
254
287
|
anchors: z.array(ClaimAnchorSchema).optional(),
|
|
288
|
+
/** disclosure-specification-record design §6.6: the sealed record's digest plus the facts embedded
|
|
289
|
+
* in its own bytes, each variable entry VERBATIM. Nothing here is summarized, counted, ranked, or
|
|
290
|
+
* reworded, and nothing here is derived from anything but the record. Present exactly on
|
|
291
|
+
* claim-package/6 — the refine below refuses it on every earlier allocation, so a claim cannot
|
|
292
|
+
* grow a disclosure section without moving to the closure whose check reads it. */
|
|
293
|
+
disclosure: ClaimDisclosureSectionSchema.optional(),
|
|
255
294
|
}).superRefine((claim, ctx) => {
|
|
256
|
-
|
|
295
|
+
// The two anchored allocations differ only in which method projection they carry: /4 takes the
|
|
296
|
+
// headline/comparison family, /5 (issue #3205) the binary qualification. Both carry the section.
|
|
297
|
+
// The disclosed allocation is the anchored binary one plus a section, so it inherits BOTH parents'
|
|
298
|
+
// rules by falling through every branch below that /5 falls through (issue #2839).
|
|
299
|
+
const disclosedClosure = claim.claimSchema === DISCLOSED_CLAIM_PACKAGE_SCHEMA_ID;
|
|
300
|
+
if (!disclosedClosure && claim.disclosure !== undefined) {
|
|
301
|
+
ctx.addIssue({
|
|
302
|
+
code: "custom",
|
|
303
|
+
message: `only ${DISCLOSED_CLAIM_PACKAGE_SCHEMA_ID} carries a disclosure section`,
|
|
304
|
+
path: ["disclosure"],
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
if (disclosedClosure && claim.disclosure === undefined) {
|
|
308
|
+
// Unlike `anchors`, this section has no legal EMPTY form: all six variables are structurally
|
|
309
|
+
// required, so a disclosed bundle with nothing to disclose is not a thing that exists. Omitting
|
|
310
|
+
// the section while claiming the closure would leave the check reading a record that no reader
|
|
311
|
+
// of the claim alone can see.
|
|
312
|
+
ctx.addIssue({
|
|
313
|
+
code: "custom",
|
|
314
|
+
message: `${DISCLOSED_CLAIM_PACKAGE_SCHEMA_ID} must carry its disclosure section`,
|
|
315
|
+
path: ["disclosure"],
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
const anchoredClosure = claim.claimSchema === ANCHORED_CLAIM_PACKAGE_SCHEMA_ID
|
|
319
|
+
|| claim.claimSchema === ANCHORED_BINARY_QUALIFICATION_CLAIM_PACKAGE_SCHEMA_ID
|
|
320
|
+
// /6 is /5 plus a disclosure section, so it is anchored by inheritance: it carries the anchors
|
|
321
|
+
// section under the same presence rule, and an omitted one refuses identically.
|
|
322
|
+
|| disclosedClosure;
|
|
323
|
+
if (!anchoredClosure && claim.anchors !== undefined) {
|
|
324
|
+
ctx.addIssue({
|
|
325
|
+
code: "custom",
|
|
326
|
+
message: `only ${ANCHORED_CLAIM_PACKAGE_SCHEMA_ID} and ${ANCHORED_BINARY_QUALIFICATION_CLAIM_PACKAGE_SCHEMA_ID} carry an anchors section`,
|
|
327
|
+
path: ["anchors"],
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
if (anchoredClosure && claim.anchors === undefined) {
|
|
331
|
+
// Present, not necessarily non-empty. An empty section is legal on exactly one bundle: one
|
|
332
|
+
// whose sealed Run declared anchoring intent that no carried anchor satisfies (§7.3). That
|
|
333
|
+
// bundle must still be on the anchored closure so the check that reports the absence runs,
|
|
334
|
+
// and its claim must therefore still state the closure's seven checks. What no claim may do
|
|
335
|
+
// is omit the section while claiming the closure, or carry one while claiming an earlier one.
|
|
257
336
|
ctx.addIssue({
|
|
258
337
|
code: "custom",
|
|
259
|
-
message:
|
|
338
|
+
message: `${claim.claimSchema} must carry its anchors section, even when the section is empty`,
|
|
260
339
|
path: ["anchors"],
|
|
261
340
|
});
|
|
262
341
|
}
|
|
263
342
|
if (claim.claimSchema === ANCHORED_CLAIM_PACKAGE_SCHEMA_ID) {
|
|
264
|
-
if (claim.anchors === undefined) {
|
|
265
|
-
// Present, not necessarily non-empty. An empty section is legal on exactly one bundle: one
|
|
266
|
-
// whose sealed Run declared anchoring intent that no carried anchor satisfies (§7.3). That
|
|
267
|
-
// bundle must still be on the anchored closure so the check that reports the absence runs,
|
|
268
|
-
// and its claim must therefore still state the closure's seven checks. What no claim may do
|
|
269
|
-
// is omit the section while claiming the closure, or carry one while claiming an earlier one.
|
|
270
|
-
ctx.addIssue({
|
|
271
|
-
code: "custom",
|
|
272
|
-
message: `${ANCHORED_CLAIM_PACKAGE_SCHEMA_ID} must carry its anchors section, even when the section is empty`,
|
|
273
|
-
path: ["anchors"],
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
343
|
if (claim.qualification !== undefined) {
|
|
277
344
|
ctx.addIssue({
|
|
278
345
|
code: "custom",
|
|
279
|
-
message:
|
|
346
|
+
message: `the anchored binary-qualification closure is ${ANCHORED_BINARY_QUALIFICATION_CLAIM_PACKAGE_SCHEMA_ID}, not claim-package/4`,
|
|
280
347
|
path: ["qualification"],
|
|
281
348
|
});
|
|
282
349
|
}
|
|
@@ -365,6 +432,30 @@ const ClaimPackageWireSchema = z.object({
|
|
|
365
432
|
if (!exactResult) {
|
|
366
433
|
ctx.addIssue({ code: "custom", message: "qualification must exactly equal the Report's one F6 per-subject result", path: ["qualification"] });
|
|
367
434
|
}
|
|
435
|
+
if (claim.claimSchema === ANCHORED_BINARY_QUALIFICATION_CLAIM_PACKAGE_SCHEMA_ID
|
|
436
|
+
|| disclosedClosure) {
|
|
437
|
+
// No released reader before 0.2.1 understands `benchmark-product-public-bundle/7` or `/8`, so
|
|
438
|
+
// both allocations pin that line unconditionally rather than inheriting /2's prompted/unprompted
|
|
439
|
+
// split — a claim naming an older reader would be an instruction to fail.
|
|
440
|
+
const expectedChecks = disclosedClosure
|
|
441
|
+
? READER_DISCLOSED_VERIFICATION_CHECKS
|
|
442
|
+
: READER_ANCHORED_QUALIFICATION_VERIFICATION_CHECKS;
|
|
443
|
+
if (claim.verification.command !== PUBLIC_BUNDLE_V7_VERIFICATION_COMMAND
|
|
444
|
+
|| claim.verification.compatibleCommand !== PUBLIC_BUNDLE_V7_COMPATIBLE_VERIFICATION_COMMAND) {
|
|
445
|
+
ctx.addIssue({ code: "custom", message: "anchored binary claim package must pin verifier 0.2.1/@0.2", path: ["verification"] });
|
|
446
|
+
}
|
|
447
|
+
if (claim.verification.checks.length !== expectedChecks.length
|
|
448
|
+
|| claim.verification.checks.some((check, index) => check !== expectedChecks[index])) {
|
|
449
|
+
ctx.addIssue({
|
|
450
|
+
code: "custom",
|
|
451
|
+
message: disclosedClosure
|
|
452
|
+
? "disclosed claim package must retain the seven anchored verification checks plus disclosure-specification, in order"
|
|
453
|
+
: "anchored binary claim package must retain the six frozen verification checks plus integrity-anchors, in order",
|
|
454
|
+
path: ["verification", "checks"],
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
368
459
|
const prompted = claim.method.parameters["promptedScreeningProfile"] === PROMPTED_SCREENING_PROFILE;
|
|
369
460
|
const command = prompted
|
|
370
461
|
? PROMPTED_BINARY_QUALIFICATION_VERIFICATION_COMMAND
|
|
@@ -372,8 +463,12 @@ const ClaimPackageWireSchema = z.object({
|
|
|
372
463
|
const compatibleCommand = prompted
|
|
373
464
|
? PROMPTED_BINARY_QUALIFICATION_COMPATIBLE_VERIFICATION_COMMAND
|
|
374
465
|
: BINARY_QUALIFICATION_COMPATIBLE_VERIFICATION_COMMAND;
|
|
375
|
-
|
|
376
|
-
|
|
466
|
+
const promptedCommandAccepted = prompted
|
|
467
|
+
&& (claim.verification.command === PROMPTED_BINARY_QUALIFICATION_VERIFICATION_COMMAND
|
|
468
|
+
|| claim.verification.command === LEGACY_PROMPTED_BINARY_QUALIFICATION_VERIFICATION_COMMAND);
|
|
469
|
+
if ((prompted ? !promptedCommandAccepted : claim.verification.command !== command)
|
|
470
|
+
|| claim.verification.compatibleCommand !== compatibleCommand) {
|
|
471
|
+
ctx.addIssue({ code: "custom", message: `binary claim package must pin verifier ${prompted ? "0.2.1 (or historical 0.2.0)/@0.2" : "0.1.0/@0.1"}`, path: ["verification"] });
|
|
377
472
|
}
|
|
378
473
|
if (claim.verification.checks.length !== READER_VERIFICATION_CHECKS.length
|
|
379
474
|
|| claim.verification.checks.some((check, index) => check !== READER_VERIFICATION_CHECKS[index])) {
|
|
@@ -400,7 +495,7 @@ function exactBinaryClaimControls(input) {
|
|
|
400
495
|
// control-shape failure. Neither judge field is ever set on an actual binary-instrument claim
|
|
401
496
|
// (`methodProjection`'s dispatch is exclusive), so admitting them here is defense in depth, not
|
|
402
497
|
// a widening any real claim exercises.
|
|
403
|
-
return exactKeys(input, ["claimSchema", "scope", "records", "method", "results", "completeness", "attrition", "conflicted", "assurance", "disclosures", "limitations", "venueHonesty", "verification", "rehearsal", "qualification", "anchors", "pairwiseDisagreement", "pairedMajorityDelta"])
|
|
498
|
+
return exactKeys(input, ["claimSchema", "scope", "records", "method", "results", "completeness", "attrition", "conflicted", "assurance", "disclosures", "limitations", "venueHonesty", "verification", "rehearsal", "qualification", "anchors", "disclosure", "pairwiseDisagreement", "pairedMajorityDelta"])
|
|
404
499
|
&& exactKeys(scope, ["draftId", "benchmarkSha256", "taskCount", "arms", "replicates", "venue"])
|
|
405
500
|
&& Array.isArray(scope.arms)
|
|
406
501
|
&& (scope.arms).every((arm) => exactKeys(arm, ["armId", "pinning"]))
|
|
@@ -415,9 +510,17 @@ function exactBinaryClaimControls(input) {
|
|
|
415
510
|
&& exactKeys(verification, ["command", "compatibleCommand", "checks", "trustRoot"])
|
|
416
511
|
&& (input.rehearsal === undefined || exactKeys(input.rehearsal, ["previewCount", "timestamps"]));
|
|
417
512
|
}
|
|
513
|
+
/** Both binary allocations pass through the same anti-conclusion control-shape gate: /5 is /2's
|
|
514
|
+
* projection plus an anchors section, so smuggling a ranking into it must fail identically. */
|
|
515
|
+
const BINARY_CLAIM_PACKAGE_SCHEMA_IDS = [
|
|
516
|
+
BINARY_QUALIFICATION_CLAIM_PACKAGE_SCHEMA_ID,
|
|
517
|
+
ANCHORED_BINARY_QUALIFICATION_CLAIM_PACKAGE_SCHEMA_ID,
|
|
518
|
+
// /6 is /5 plus a section, so a ranking smuggled into it must fail identically (issue #2839).
|
|
519
|
+
DISCLOSED_CLAIM_PACKAGE_SCHEMA_ID,
|
|
520
|
+
];
|
|
418
521
|
export const ClaimPackageSchema = z.preprocess((input) => {
|
|
419
522
|
if (typeof input === "object" && input !== null && !Array.isArray(input)
|
|
420
|
-
&& input.claimSchema
|
|
523
|
+
&& BINARY_CLAIM_PACKAGE_SCHEMA_IDS.includes(input.claimSchema)
|
|
421
524
|
&& !exactBinaryClaimControls(input)) {
|
|
422
525
|
return { claimSchema: "invalid-binary-claim-control-shape" };
|
|
423
526
|
}
|
|
@@ -619,6 +722,8 @@ function summedPinningUnverifiableCounts(perSubject) {
|
|
|
619
722
|
export const CLAIM_VERIFICATION_CHECKS = READER_VERIFICATION_CHECKS;
|
|
620
723
|
/** The anchored closure's list: the six frozen checks plus `integrity-anchors` (§8). */
|
|
621
724
|
export const ANCHORED_CLAIM_VERIFICATION_CHECKS = READER_ANCHORED_VERIFICATION_CHECKS;
|
|
725
|
+
/** The disclosed closure's list: the anchored seven plus `disclosure-specification` (design §7). */
|
|
726
|
+
export const DISCLOSED_CLAIM_VERIFICATION_CHECKS = READER_DISCLOSED_VERIFICATION_CHECKS;
|
|
622
727
|
export const PUBLIC_BUNDLE_VERIFICATION_COMMAND = READER_VERIFICATION_COMMAND;
|
|
623
728
|
/** The unconditional trust-root sentence, re-exported unchanged. It is DEFINED once beside its
|
|
624
729
|
* anchored replacement in `anchor-claims.ts`: one sentence written out twice, in two mirrored
|
|
@@ -657,16 +762,32 @@ export function buildClaimPackage(input) {
|
|
|
657
762
|
// this builder produced before the feature existed.
|
|
658
763
|
const anchors = input.anchors ?? [];
|
|
659
764
|
const anchored = input.anchors !== undefined;
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
765
|
+
// Strictly opt-in, exactly like `anchors`: a run with no sealed disclosure declaration produces
|
|
766
|
+
// the claim this builder produced before the feature existed, byte for byte (issue #2839).
|
|
767
|
+
const disclosure = input.disclosure;
|
|
768
|
+
// Four allocations across two independent axes (anchored yes/no × qualification yes/no). The
|
|
769
|
+
// fourth cell, anchored+qualification, is claim-package/5 (issue #3205); before it existed this
|
|
770
|
+
// pairing threw, which made anchoring and binary-instrument benchmarking mutually exclusive.
|
|
771
|
+
const anchoredQualification = anchored && projection.qualification !== undefined;
|
|
772
|
+
// The disclosed allocation is the anchored QUALIFICATION cell plus a section, and there is no
|
|
773
|
+
// other disclosed cell (issue #2839). A run publishes one bundle per analysis, and its sibling
|
|
774
|
+
// headline/comparison analyses project no qualification, so they have nowhere to put the section.
|
|
775
|
+
// Refusing here rather than dropping it silently is what makes the caller state which entry the
|
|
776
|
+
// record belongs to instead of discovering later that one bundle quietly lost it.
|
|
777
|
+
if (disclosure !== undefined && !anchoredQualification) {
|
|
778
|
+
throw new Error("claim package: only the anchored binary-qualification closure carries a disclosure section"
|
|
779
|
+
+ " — this projection has no qualification, and no other closure version expresses one");
|
|
663
780
|
}
|
|
664
781
|
return {
|
|
665
|
-
claimSchema:
|
|
666
|
-
?
|
|
667
|
-
:
|
|
668
|
-
?
|
|
669
|
-
:
|
|
782
|
+
claimSchema: anchoredQualification && disclosure !== undefined
|
|
783
|
+
? DISCLOSED_CLAIM_PACKAGE_SCHEMA_ID
|
|
784
|
+
: anchoredQualification
|
|
785
|
+
? ANCHORED_BINARY_QUALIFICATION_CLAIM_PACKAGE_SCHEMA_ID
|
|
786
|
+
: anchored
|
|
787
|
+
? ANCHORED_CLAIM_PACKAGE_SCHEMA_ID
|
|
788
|
+
: projection.qualification === undefined
|
|
789
|
+
? CLAIM_PACKAGE_SCHEMA_ID
|
|
790
|
+
: BINARY_QUALIFICATION_CLAIM_PACKAGE_SCHEMA_ID,
|
|
670
791
|
scope: {
|
|
671
792
|
draftId: input.draftId,
|
|
672
793
|
benchmarkSha256: input.benchmarkSha256,
|
|
@@ -707,26 +828,36 @@ export function buildClaimPackage(input) {
|
|
|
707
828
|
limitations: [...(reportRecord.limitations ?? [])],
|
|
708
829
|
venueHonesty: input.venueHonesty,
|
|
709
830
|
verification: {
|
|
710
|
-
command:
|
|
711
|
-
?
|
|
712
|
-
:
|
|
713
|
-
?
|
|
714
|
-
:
|
|
715
|
-
?
|
|
716
|
-
:
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
831
|
+
command: anchoredQualification
|
|
832
|
+
? PUBLIC_BUNDLE_V7_VERIFICATION_COMMAND
|
|
833
|
+
: anchored
|
|
834
|
+
? PUBLIC_BUNDLE_V6_VERIFICATION_COMMAND
|
|
835
|
+
: promptedScreening
|
|
836
|
+
? PROMPTED_BINARY_QUALIFICATION_VERIFICATION_COMMAND
|
|
837
|
+
: projection.qualification === undefined
|
|
838
|
+
? PUBLIC_BUNDLE_VERIFICATION_COMMAND
|
|
839
|
+
: BINARY_QUALIFICATION_VERIFICATION_COMMAND,
|
|
840
|
+
compatibleCommand: anchoredQualification
|
|
841
|
+
? PUBLIC_BUNDLE_V7_COMPATIBLE_VERIFICATION_COMMAND
|
|
842
|
+
: anchored
|
|
843
|
+
? PUBLIC_BUNDLE_V6_COMPATIBLE_VERIFICATION_COMMAND
|
|
844
|
+
: promptedScreening
|
|
845
|
+
? PROMPTED_BINARY_QUALIFICATION_COMPATIBLE_VERIFICATION_COMMAND
|
|
846
|
+
: projection.qualification === undefined
|
|
847
|
+
? PUBLIC_BUNDLE_COMPATIBLE_VERIFICATION_COMMAND
|
|
848
|
+
: BINARY_QUALIFICATION_COMPATIBLE_VERIFICATION_COMMAND,
|
|
849
|
+
checks: anchoredQualification && disclosure !== undefined
|
|
850
|
+
? [...DISCLOSED_CLAIM_VERIFICATION_CHECKS]
|
|
851
|
+
: anchored ? [...ANCHORED_CLAIM_VERIFICATION_CHECKS] : [...CLAIM_VERIFICATION_CHECKS],
|
|
725
852
|
// §9.2: the trust-root sentence is replaced only by a governing lock anchor. A bundle whose
|
|
726
853
|
// only anchors are pending, or cover the Matrix alone, keeps the unconditional sentence.
|
|
727
854
|
trustRoot: anchoredTrustRoot(anchors),
|
|
728
855
|
},
|
|
729
856
|
...(anchored ? { anchors: anchors.map((anchor) => ({ ...anchor })) } : {}),
|
|
857
|
+
// Copied through, never rebuilt here: the section is `deriveDisclosureSpecification`'s output
|
|
858
|
+
// over the sealed record's exact bytes, and this builder is not entitled to a second opinion
|
|
859
|
+
// about what that record says (issue #2839, design §6.6).
|
|
860
|
+
...(disclosure === undefined ? {} : { disclosure }),
|
|
730
861
|
...(input.previewDisclosure !== undefined
|
|
731
862
|
? {
|
|
732
863
|
rehearsal: {
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The disclosed closure's projection and check (disclosure-specification-record design §6.4, §6.6,
|
|
3
|
+
* §7; issue #2839).
|
|
4
|
+
*
|
|
5
|
+
* This module is **single-sourced, not mirrored**, exactly as `anchor-claims.ts` is: `@colophon-
|
|
6
|
+
* claims/core` already depends on this package, so the producer and the standalone verifier call
|
|
7
|
+
* ONE `deriveDisclosureSpecification`. The claim-consistency byte-compare then compares one
|
|
8
|
+
* function's output over two byte sets rather than two implementations' guesses.
|
|
9
|
+
*
|
|
10
|
+
* The one posture that matters more than any mechanism here (design R4):
|
|
11
|
+
*
|
|
12
|
+
* **The verifier AUTHENTICATES measurements and CARRIES assertions.**
|
|
13
|
+
*
|
|
14
|
+
* A `measured-here` variable must cite records the bundle actually carries, under a role admissible
|
|
15
|
+
* for the citation. A `disclosed-by-publisher` variable is checked for internal well-formedness and
|
|
16
|
+
* for nothing else — no lookup, no fetch, no cross-check against the Matrix or the Report, no status
|
|
17
|
+
* upgrade or downgrade. An assertion that turns out to be false is a false assertion in a valid
|
|
18
|
+
* record; that is the correct outcome and the honest one, and a verifier that refused it would be
|
|
19
|
+
* claiming a power it does not have.
|
|
20
|
+
*
|
|
21
|
+
* What this check deliberately does NOT do (design §8, each one a thing a well-meaning implementer
|
|
22
|
+
* would add):
|
|
23
|
+
*
|
|
24
|
+
* - It does not reconcile against `Report.disclosures.perSubject[].pinning`. Those counts answer
|
|
25
|
+
* "how well did each executed axis pin"; this record answers "which variables were executed at
|
|
26
|
+
* all". Two surfaces restating one fact are two surfaces that can disagree.
|
|
27
|
+
* - It does not infer a status from the bundle. A bundle that plainly executed a judge model does
|
|
28
|
+
* not license marking `judge-model` as `measured-here` if the record says otherwise.
|
|
29
|
+
* - It does not fetch anything, ever. A verifier that reached the network would make its own result
|
|
30
|
+
* depend on when it ran.
|
|
31
|
+
* - It does not rank, score, compare, or aggregate. There is no disclosure-completeness score:
|
|
32
|
+
* counting statuses would create a number publishers optimize against, and a six-of-six record
|
|
33
|
+
* with six vague assertions would outscore a two-of-six record with two proofs.
|
|
34
|
+
*/
|
|
35
|
+
import { z } from "zod";
|
|
36
|
+
import { SIX_VARIABLE_DISCLOSURE_SPECIFICATION, type DisclosureEvidenceRole, type DisclosureVariableEntry, type DisclosureVariableKey, type DisclosureVariableStatus } from "@jinn-network/benchmarking-records";
|
|
37
|
+
import type { BundleV4EvidenceRole } from "../schema.js";
|
|
38
|
+
/** The evidence-catalog role a disclosure-specification record carries, and the ONLY one it may
|
|
39
|
+
* carry: a record bearing this token together with any second role refuses (§7 step 1). */
|
|
40
|
+
export declare const DISCLOSURE_SPECIFICATION_BUNDLE_ROLE: "disclosure-specification";
|
|
41
|
+
/**
|
|
42
|
+
* §6.4's binding profile: which of this carrier's evidence roles satisfy which of the standard's two
|
|
43
|
+
* portable disclosure roles. Jinn-side mapping, deliberately NOT part of the portable record — the
|
|
44
|
+
* mapping from the standard's roles onto a specific carrier's record roles is the carrier's business.
|
|
45
|
+
*
|
|
46
|
+
* v1 deliberately does not narrow the admissible set per variable. Which record species fixes
|
|
47
|
+
* `judge-model` depends on the judge profile packet P0 is freezing, and encoding a guess here would
|
|
48
|
+
* put this module in P0's lane. Reserved as a v2 tightening once P0's record vocabulary merges.
|
|
49
|
+
*/
|
|
50
|
+
export declare const DISCLOSURE_ROLE_BINDING: Readonly<Record<DisclosureEvidenceRole, readonly BundleV4EvidenceRole[]>>;
|
|
51
|
+
/** The claim package's `disclosure` section (§6.6). Every variable entry is its record entry
|
|
52
|
+
* VERBATIM: nothing is summarized, counted, ranked, or reworded (R5). */
|
|
53
|
+
export interface ClaimDisclosureSection {
|
|
54
|
+
readonly recordSha256: string;
|
|
55
|
+
/** The literal standard identifier, not any string: this section names the standard the record
|
|
56
|
+
* claims compliance with, and a section naming a different one is not this record's projection. */
|
|
57
|
+
readonly specification: typeof SIX_VARIABLE_DISCLOSURE_SPECIFICATION;
|
|
58
|
+
readonly subjectSha256: string;
|
|
59
|
+
readonly variables: Readonly<Record<DisclosureVariableKey, DisclosureVariableEntry>>;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The claim section's own grammar, single-sourced from the record's schema so the section cannot
|
|
63
|
+
* describe a variable entry the record could not have carried. It is a second line of defense
|
|
64
|
+
* rather than the primary one: `assertClaimConsistency`'s whole-claim byte-compare against the
|
|
65
|
+
* rebuilt claim is what actually proves the section is this record's projection.
|
|
66
|
+
*/
|
|
67
|
+
export declare const ClaimDisclosureSectionSchema: z.ZodObject<{
|
|
68
|
+
recordSha256: z.ZodString;
|
|
69
|
+
specification: z.ZodLiteral<"https://spec.jinn.network/disclosure/six-variable/v1">;
|
|
70
|
+
subjectSha256: z.ZodString;
|
|
71
|
+
variables: z.ZodObject<{
|
|
72
|
+
"ingestion-model": z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
73
|
+
status: z.ZodLiteral<"measured-here">;
|
|
74
|
+
statement: z.ZodString;
|
|
75
|
+
evidence: z.ZodArray<z.ZodObject<{
|
|
76
|
+
role: z.ZodEnum<{
|
|
77
|
+
"pinned-configuration": "pinned-configuration";
|
|
78
|
+
"execution-observation": "execution-observation";
|
|
79
|
+
}>;
|
|
80
|
+
digest: z.ZodObject<{
|
|
81
|
+
sha256: z.ZodString;
|
|
82
|
+
}, z.core.$strict>;
|
|
83
|
+
}, z.core.$strict>>;
|
|
84
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
85
|
+
status: z.ZodLiteral<"disclosed-by-publisher">;
|
|
86
|
+
statement: z.ZodString;
|
|
87
|
+
sources: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
88
|
+
uri: z.ZodString;
|
|
89
|
+
}, z.core.$strict>>>;
|
|
90
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
91
|
+
status: z.ZodLiteral<"undisclosed">;
|
|
92
|
+
reason: z.ZodEnum<{
|
|
93
|
+
"not-stated": "not-stated";
|
|
94
|
+
"stated-without-identifiers": "stated-without-identifiers";
|
|
95
|
+
"outside-this-experiment": "outside-this-experiment";
|
|
96
|
+
}>;
|
|
97
|
+
}, z.core.$strict>], "status">;
|
|
98
|
+
"retrieval-config": z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
99
|
+
status: z.ZodLiteral<"measured-here">;
|
|
100
|
+
statement: z.ZodString;
|
|
101
|
+
evidence: z.ZodArray<z.ZodObject<{
|
|
102
|
+
role: z.ZodEnum<{
|
|
103
|
+
"pinned-configuration": "pinned-configuration";
|
|
104
|
+
"execution-observation": "execution-observation";
|
|
105
|
+
}>;
|
|
106
|
+
digest: z.ZodObject<{
|
|
107
|
+
sha256: z.ZodString;
|
|
108
|
+
}, z.core.$strict>;
|
|
109
|
+
}, z.core.$strict>>;
|
|
110
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
111
|
+
status: z.ZodLiteral<"disclosed-by-publisher">;
|
|
112
|
+
statement: z.ZodString;
|
|
113
|
+
sources: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
114
|
+
uri: z.ZodString;
|
|
115
|
+
}, z.core.$strict>>>;
|
|
116
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
117
|
+
status: z.ZodLiteral<"undisclosed">;
|
|
118
|
+
reason: z.ZodEnum<{
|
|
119
|
+
"not-stated": "not-stated";
|
|
120
|
+
"stated-without-identifiers": "stated-without-identifiers";
|
|
121
|
+
"outside-this-experiment": "outside-this-experiment";
|
|
122
|
+
}>;
|
|
123
|
+
}, z.core.$strict>], "status">;
|
|
124
|
+
"answer-model": z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
125
|
+
status: z.ZodLiteral<"measured-here">;
|
|
126
|
+
statement: z.ZodString;
|
|
127
|
+
evidence: z.ZodArray<z.ZodObject<{
|
|
128
|
+
role: z.ZodEnum<{
|
|
129
|
+
"pinned-configuration": "pinned-configuration";
|
|
130
|
+
"execution-observation": "execution-observation";
|
|
131
|
+
}>;
|
|
132
|
+
digest: z.ZodObject<{
|
|
133
|
+
sha256: z.ZodString;
|
|
134
|
+
}, z.core.$strict>;
|
|
135
|
+
}, z.core.$strict>>;
|
|
136
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
137
|
+
status: z.ZodLiteral<"disclosed-by-publisher">;
|
|
138
|
+
statement: z.ZodString;
|
|
139
|
+
sources: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
140
|
+
uri: z.ZodString;
|
|
141
|
+
}, z.core.$strict>>>;
|
|
142
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
143
|
+
status: z.ZodLiteral<"undisclosed">;
|
|
144
|
+
reason: z.ZodEnum<{
|
|
145
|
+
"not-stated": "not-stated";
|
|
146
|
+
"stated-without-identifiers": "stated-without-identifiers";
|
|
147
|
+
"outside-this-experiment": "outside-this-experiment";
|
|
148
|
+
}>;
|
|
149
|
+
}, z.core.$strict>], "status">;
|
|
150
|
+
"answer-prompt": z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
151
|
+
status: z.ZodLiteral<"measured-here">;
|
|
152
|
+
statement: z.ZodString;
|
|
153
|
+
evidence: z.ZodArray<z.ZodObject<{
|
|
154
|
+
role: z.ZodEnum<{
|
|
155
|
+
"pinned-configuration": "pinned-configuration";
|
|
156
|
+
"execution-observation": "execution-observation";
|
|
157
|
+
}>;
|
|
158
|
+
digest: z.ZodObject<{
|
|
159
|
+
sha256: z.ZodString;
|
|
160
|
+
}, z.core.$strict>;
|
|
161
|
+
}, z.core.$strict>>;
|
|
162
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
163
|
+
status: z.ZodLiteral<"disclosed-by-publisher">;
|
|
164
|
+
statement: z.ZodString;
|
|
165
|
+
sources: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
166
|
+
uri: z.ZodString;
|
|
167
|
+
}, z.core.$strict>>>;
|
|
168
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
169
|
+
status: z.ZodLiteral<"undisclosed">;
|
|
170
|
+
reason: z.ZodEnum<{
|
|
171
|
+
"not-stated": "not-stated";
|
|
172
|
+
"stated-without-identifiers": "stated-without-identifiers";
|
|
173
|
+
"outside-this-experiment": "outside-this-experiment";
|
|
174
|
+
}>;
|
|
175
|
+
}, z.core.$strict>], "status">;
|
|
176
|
+
"judge-model": z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
177
|
+
status: z.ZodLiteral<"measured-here">;
|
|
178
|
+
statement: z.ZodString;
|
|
179
|
+
evidence: z.ZodArray<z.ZodObject<{
|
|
180
|
+
role: z.ZodEnum<{
|
|
181
|
+
"pinned-configuration": "pinned-configuration";
|
|
182
|
+
"execution-observation": "execution-observation";
|
|
183
|
+
}>;
|
|
184
|
+
digest: z.ZodObject<{
|
|
185
|
+
sha256: z.ZodString;
|
|
186
|
+
}, z.core.$strict>;
|
|
187
|
+
}, z.core.$strict>>;
|
|
188
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
189
|
+
status: z.ZodLiteral<"disclosed-by-publisher">;
|
|
190
|
+
statement: z.ZodString;
|
|
191
|
+
sources: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
192
|
+
uri: z.ZodString;
|
|
193
|
+
}, z.core.$strict>>>;
|
|
194
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
195
|
+
status: z.ZodLiteral<"undisclosed">;
|
|
196
|
+
reason: z.ZodEnum<{
|
|
197
|
+
"not-stated": "not-stated";
|
|
198
|
+
"stated-without-identifiers": "stated-without-identifiers";
|
|
199
|
+
"outside-this-experiment": "outside-this-experiment";
|
|
200
|
+
}>;
|
|
201
|
+
}, z.core.$strict>], "status">;
|
|
202
|
+
"judge-prompt": z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
203
|
+
status: z.ZodLiteral<"measured-here">;
|
|
204
|
+
statement: z.ZodString;
|
|
205
|
+
evidence: z.ZodArray<z.ZodObject<{
|
|
206
|
+
role: z.ZodEnum<{
|
|
207
|
+
"pinned-configuration": "pinned-configuration";
|
|
208
|
+
"execution-observation": "execution-observation";
|
|
209
|
+
}>;
|
|
210
|
+
digest: z.ZodObject<{
|
|
211
|
+
sha256: z.ZodString;
|
|
212
|
+
}, z.core.$strict>;
|
|
213
|
+
}, z.core.$strict>>;
|
|
214
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
215
|
+
status: z.ZodLiteral<"disclosed-by-publisher">;
|
|
216
|
+
statement: z.ZodString;
|
|
217
|
+
sources: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
218
|
+
uri: z.ZodString;
|
|
219
|
+
}, z.core.$strict>>>;
|
|
220
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
221
|
+
status: z.ZodLiteral<"undisclosed">;
|
|
222
|
+
reason: z.ZodEnum<{
|
|
223
|
+
"not-stated": "not-stated";
|
|
224
|
+
"stated-without-identifiers": "stated-without-identifiers";
|
|
225
|
+
"outside-this-experiment": "outside-this-experiment";
|
|
226
|
+
}>;
|
|
227
|
+
}, z.core.$strict>], "status">;
|
|
228
|
+
}, z.core.$strict>;
|
|
229
|
+
}, z.core.$strict>;
|
|
230
|
+
export declare class DisclosureProjectionError extends Error {
|
|
231
|
+
constructor(message: string);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* The one shared projection, called by BOTH the workspace producer and the standalone verifier.
|
|
235
|
+
*
|
|
236
|
+
* It carries only facts embedded in the record's own bytes, plus the record's digest — which is the
|
|
237
|
+
* digest of the very bytes handed in, never a separately supplied one. It exists at all so a reader
|
|
238
|
+
* of `claim-package.json` alone sees all six statuses without opening an evidence record, and so
|
|
239
|
+
* `assertClaimConsistency`'s existing whole-claim byte-compare covers the disclosure without a
|
|
240
|
+
* second bespoke comparison.
|
|
241
|
+
*/
|
|
242
|
+
export declare function deriveDisclosureSpecification(recordBytes: Uint8Array): ClaimDisclosureSection;
|
|
243
|
+
/** The disclosed statuses, surfaced on the verification result (§7 step 11). Disclosed facts, never
|
|
244
|
+
* folded into a single badge — the same posture `anchors` takes. */
|
|
245
|
+
export interface DisclosureSpecificationReport {
|
|
246
|
+
readonly recordSha256: string;
|
|
247
|
+
readonly specification: string;
|
|
248
|
+
readonly subjectSha256: string;
|
|
249
|
+
readonly statuses: Readonly<Record<DisclosureVariableKey, DisclosureVariableStatus>>;
|
|
250
|
+
}
|
|
251
|
+
export interface AssertDisclosureSpecificationInput {
|
|
252
|
+
/** The Report extension's descriptor digest — what the carrier says the record is. */
|
|
253
|
+
readonly extensionDigestSha256: string;
|
|
254
|
+
/** Every evidence-catalog record's declared roles, keyed by record digest. */
|
|
255
|
+
readonly catalogRoles: ReadonlyMap<string, ReadonlySet<string>>;
|
|
256
|
+
/** The exact carried bytes for every evidence record, keyed by digest. */
|
|
257
|
+
readonly recordBytes: ReadonlyMap<string, Uint8Array>;
|
|
258
|
+
/** The bundle's own Matrix digest — the record's one legal subject (R1). */
|
|
259
|
+
readonly matrixSha256: string;
|
|
260
|
+
/** The verified Report's author IRI. */
|
|
261
|
+
readonly reportAuthor: string;
|
|
262
|
+
/** Refuses with the verifier's own typed refusal, so this module raises no error class of its own
|
|
263
|
+
* at the call boundary and every path lands in the caller's issue shape. */
|
|
264
|
+
readonly refuse: (path: string, message: string) => never;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* §7 steps 1–8: authenticate what the Report extension names.
|
|
268
|
+
*
|
|
269
|
+
* Step 9 (claim-id pairing) and step 10 (projection equality) live in `verify.ts` and
|
|
270
|
+
* `assertClaimConsistency` respectively, because both compare against documents this function is
|
|
271
|
+
* deliberately not handed — keeping this function a statement about the RECORD and its evidence.
|
|
272
|
+
*/
|
|
273
|
+
export declare function assertDisclosureSpecification(input: AssertDisclosureSpecificationInput): DisclosureSpecificationReport;
|