The adversarial corpus, public. These are the Wycheproof-style conformance vectors every Attest verifier — browser JavaScript, stdlib Python, and AWS Lambda — must judge identically. Each row ships the real exported pack; verify → opens the browser verifier on it. A verifier that disagrees with the expected verdict is wrong, whatever surface it runs on. Five more vectors exercise issuer-document pinning and need a companion trust document — they live in the repo's tests/vectors/.

Verifier conformance vectors

The interesting rows aren't the obvious tampers — they're the grammar traps: leaf_index: true (a bool is an int subclass in Python, not an integer in JSON), "5" as a string, 5.5 fractional indices, -1 indices and tree sizes (real JSON integers — the type check accepts them; the range guard is the load-bearing branch), space-padded hex, a tree_size of 240 that kills JS bitwise ops. These are the cases where two verifiers silently diverge — the corpus exists so ours can't.

Expected: PASS (16)

vectororacle what it exercisesverify
ok-chain-case-rootsmust PASStwo members carry the SAME head at one size, spelled upper- and lower-case — one head, not a collision; every surface dedupes on the decoded rootverify →
ok-chain-quoted-bridgemust PASSa member's signed extends.first spelled as a digit string — signed material is evaluated with JS-mirrored coercion, so the quoted hop is legal on every surfaceverify →
ok-checkpoint-chainmust PASSthe pack embeds prior signed checkpoint heads — each verified under the issuer lineage so two exports can reconcile non-adjacent heads offline, hop-by-hopverify →
ok-clean-bundlemust PASSone visit, one key, media digests all present — the baselineverify →
ok-decoy-successor-ordermust PASSa consented decoy successor listed FIRST in key_rotations.json — only the highest-sequence consented pivot (K_A->K_B) may inherit trust; a first-match-in-pool verifier would pick the attacker and fail this packverify →
ok-embedded-monitor-trailmust PASSmonitor_observation receipts embedded in the checkpoint doc — each verified under the issuer lineage and proven inside the signed head, so the watch trail travels with the packverify →
ok-float-leaf-indexmust PASSleaf_index spelled 5.0 — JSON keeps no int/float distinction, so Number.isInteger parity means every verifier accepts integral floats identicallyverify →
ok-float-tree-sizemust PASSa properly SIGNED head claiming tree_size 5.0 — the signature verifies on the literal bytes, and Number.isInteger parity means integral floats verify identically everywhereverify →
ok-forged-cosig-ignoredmust PASSa cosig attesting a DIFFERENT head (or one whose signature fails after the edit) counts as absent — the pack still verifies on its own proofs; auxiliary attestations report honestly, never gateverify →
ok-grafted-revocationmust PASSa self-signed key_revocation grafted into key_rotations.json is inert twice over — it can't join the signed trust walk, and foreign-signed receipts owe no log proof so the graft can't kill the pack eitherverify →
ok-legacy-no-manifestmust PASSa pre-pin pack still verifies — the manifest is optional when absent, mandatory when presentverify →
ok-redacted-mediamust PASSmedia bytes withheld by redaction; signed digests still verifyverify →
ok-revoked-casemust PASSrevocation annotates: records + the pivot receipt itself sit in the suspect windowverify →
ok-rotated-casemust PASScase pack spanning a signed rotation — predecessor pin verifies both erasverify →
ok-witness-anchoredmust PASSthe witness's attestation is itself committed to the witness's own transparency log — the pack proves the cosignature was published, not just signed and handed oververify →
ok-witness-cosignedmust PASSan independent witness's counter-signature rides the checkpoint doc — verified under its own key, reported as an auxiliary attestation, never a gateverify →

Expected: FAIL (28)

vectororacle what it exercisesverify
fail-anchor-proof-graftmust FAILa packed anchor whose cosig cannot reach the anchor's signed head — a claimed anchor is either verifiable or a lie; every verifier fails closedverify →
fail-bool-leaf-indexmust FAILleaf_index true — bool is an int subclass in Python but not an integer in JSON; Number.isInteger parity rejects itverify →
fail-chain-dup-sizemust FAILtwo issuer-signed heads at one tree size inside a single document is a fork claim the reconcile cannot read honestly — the pack refuses it at verification timeverify →
fail-chain-foreign-membermust FAILa chain member signed by a foreign key — the walk could never trust a bridge it names, so the pack fails closedverify →
fail-chain-nonhex-rootmust FAILa 64-char non-hex member root — the strictest spelling wins on every surface, so the pack fails closed at intake instead of diverging mid-walkverify →
fail-doctored-verifiermust FAILa post-export edit to verify_case.py — membership checks names, only the signed pin checks the bytesverify →
fail-embedded-foreign-receiptmust FAILan embedded receipt signed outside the issuer lineage — embedded evidence must bind the pack's issuer or it is grafted testimonyverify →
fail-embedded-tampered-receiptmust FAILan embedded receipt's payload flipped — payload hash and signature both fail; a doctored observation can never ride the signed headverify →
fail-foreign-pinmust FAILa valid pin receipt under an untrusted key — signature integrity is not issuer authorityverify →
fail-forged-verifier-toolmust FAILa modified verify_bundle.py fails its own signed pin — membership whitelists names, only the manifest pins bytesverify →
fail-fractional-leaf-indexmust FAILleaf_index 5.5 — non-integral indices are not integers on any surface; Python must not silently truncate where JS rejectsverify →
fail-grafted-log-proofmust FAILanother receipt's audit path grafted on — the Merkle math catches what a presence check never wouldverify →
fail-grafted-pinmust FAILa verifier_manifest signed for another pack cannot pin this one — the scope binding stops the replayverify →
fail-media-mismatchmust FAILmedia bytes that don't hash to the signed digest are caughtverify →
fail-missing-listedmust FAILa bundle the signed manifest lists but the zip lacks failsverify →
fail-missing-log-proofmust FAILa pack receipt silently dropped from log_checkpoint.json — the pack cannot claim log membership it does not proveverify →
fail-missing-pinned-toolmust FAILa tool the signed pin names but the pack lacks fails — the pin binds both directionsverify →
fail-negative-leaf-indexmust FAILleaf_index -1 — Number.isInteger(-1) is TRUE, so this isolates the explicit index<0 range guard every surface must carry beyond the type checkverify →
fail-negative-tree-sizemust FAILa properly SIGNED head claiming tree_size -1 — Number.isInteger(-1) is TRUE, so this isolates the size<1 range guard: a log with negative size is a malformed head everywhereverify →
fail-orphan-rotationmust FAILa rotation the successor never countersigned cannot pivot trustverify →
fail-oversize-tree-sizemust FAILa properly SIGNED head claiming tree_size 2^40 — valid signature, impossible size: JS bitwise ops die past 2^31, so every surface rejects it rather than divergingverify →
fail-payload-tampermust FAILa flipped payload field breaks the signed hashverify →
fail-signature-tampermust FAILa corrupted signature must never verifyverify →
fail-smuggled-membermust FAILa member the pack format doesn't name fails closedverify →
fail-spaced-hex-proofmust FAILa proof node spelled with spaces between byte pairs — Python bytes.fromhex tolerates whitespace where strict hex rejects; every surface now fails closed identicallyverify →
fail-string-leaf-indexmust FAILleaf_index as a quoted string — JSON-typed fields must not pass through Python's permissive int() where JS === rejectsverify →
fail-unreferenced-junk-proofmust FAILa proof entry referencing nothing and reaching nothing — every proofs entry must verify; unexplained material is a lie, not decorationverify →
fail-wrong-pinmust FAIL
under --key pin
pinning an unrelated key must not bless the pack — the browser has no pin flag, so watch it VERIFY self-declared: that green stamp is exactly the attack a pin defeats (attest verify pack.zip --key reproduces the FAIL)verify →

Back to the landing page · the oracle as JSON · regenerate: tools/make_vectors.py (never hand-edit the zips).