crates/nornir-build-thing/tests/attestation_end_to_end.rs
//! **A lying receipt is caught on a STRIPPED artifact, by the real pipeline.**
//!
//! The problem this file is the proof of. `[profile.release] strip = true` leaves
//! the delivered binary with no symbol table, so
//! [`receipt_proof::audit_artifact`] can only answer `NotMeasured` for it. The
//! artifact we hand out carries a `gpu = false` nobody can check. Measured on
//! gunnar-server, oden 2026-08-06: 16 001 760 B stripped and unprovable against
//! 19 190 152 B unstripped and provable, +19,9 %.
//!
//! The answer here is SLSA's: audit at build time on a binary that still has
//! symbols, and let the verdict travel as text, anchored to the bytes by the
//! allocated-section digest.
//!
//! # Why the fixture's GPU stack is modules named `wgpu` and `naga`
//!
//! Because the production rule *is* a substring match over demangled symbol
//! names — [`GPU_FAMILIES`] is `["wgpu", "naga", "ash::vk", "nvml"]` and
//! [`count_families`](nornir_build_thing::linkage::count_families) counts symbols
//! containing them. A fixture that declares `mod wgpu` and calls into it produces
//! genuine symbols with those paths, out of a real rustc and a real linker, and
//! every step after that is the shipping code: the `object` parse, the
//! demangling, the glue exclusion, the count, the verdict. Depending on the real
//! `wgpu` crate would add a network, minutes of build time, and would exercise
//! not one extra line of the thing under test.
//!
//! The claim is checked rather than assumed: assertion (0) below reads the
//! symbols back out and fails if the families are not really there, so this file
//! cannot go green by measuring a binary that has nothing in it.
//!
//! [`receipt_proof::audit_artifact`]: nornir_build_thing::receipt_proof::audit_artifact
//! [`GPU_FAMILIES`]: nornir_build_thing::receipt_proof::GPU_FAMILIES
mod common;
use common::build_fixture_with_main;
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use nornir_build_thing::code_digest::code_digest;
use nornir_build_thing::contract::{Coordinate, Receipt, RECEIPT_VERSION};
use nornir_build_thing::history::{
attest_proven, deliver_stripped, AttestationVerdict, HistoryPackage, Outsider, Unprovable,
};
use nornir_build_thing::linkage::demangled_symbols;
use nornir_build_thing::receipt::emit_source;
use nornir_build_thing::receipt_proof::{audit_artifact, ClaimVerdict, ReceiptVerdict};
/// A receipt claiming `gpu = <gpu>`. `hash` is set, because an unpinned recipe is
/// refused before any of this is reached and that refusal has its own test.
fn receipt(atom: &str, gpu: &str) -> Receipt {
let mut settings = BTreeMap::new();
settings.insert("feature.gpu".to_string(), gpu.to_string());
settings.insert("profile".to_string(), "release".to_string());
let mut inputs = BTreeMap::new();
inputs.insert("source-commit".to_string(), "9f2c1ab".to_string());
inputs.insert("target".to_string(), "x86_64-unknown-linux-gnu".to_string());
Receipt {
receipt_version: RECEIPT_VERSION,
build_thing: Coordinate::parse("korp-build-thing:0.3.1:a91f4c2e").unwrap(),
atom: atom.to_string(),
target: "exe".to_string(),
settings,
inputs,
}
}
/// Module paths that land in the symbol table as `…::wgpu::…`, `…::naga::…` and
/// `…::ash::vk::…`.
///
/// `#[inline(never)]` plus a `black_box` round trip plus a call from `main` is
/// what survives `opt-level = 3` + `lto = true`; without all three the linker is
/// entitled to delete the lot, and then this file would be measuring an empty
/// binary and calling it a pass.
const GPU_STACK: &str = r#"
pub mod wgpu {
#[inline(never)]
pub fn submit(x: u64) -> u64 { std::hint::black_box(x).wrapping_mul(0x9e37_79b9) }
}
pub mod naga {
#[inline(never)]
pub fn validate(x: u64) -> u64 { std::hint::black_box(x).rotate_left(17) }
}
pub mod ash {
pub mod vk {
#[inline(never)]
pub fn create_instance(x: u64) -> u64 { std::hint::black_box(x) ^ 0x5851_f42d }
}
}
"#;
/// The `main` body that keeps [`GPU_STACK`] reachable.
const GPU_MAIN: &str = "let n = ash::vk::create_instance(naga::validate(wgpu::submit(7))); \
std::hint::black_box(n);";
/// A comparably-sized program with no GPU family in it at all — the control.
const PLAIN_STACK: &str = r#"
pub mod storage {
#[inline(never)]
pub fn put(x: u64) -> u64 { std::hint::black_box(x).wrapping_mul(0x9e37_79b9) }
}
pub mod codec {
#[inline(never)]
pub fn encode(x: u64) -> u64 { std::hint::black_box(x).rotate_left(17) }
}
"#;
/// The `main` body that keeps [`PLAIN_STACK`] reachable.
const PLAIN_MAIN: &str = "let n = codec::encode(storage::put(7)); std::hint::black_box(n);";
/// Build the same program twice — once with its symbol table, once without —
/// which is the two-file situation `attest_proven` exists for.
///
/// Returns `(shipped, audited)`: stripped first, because that is the one that
/// goes out.
///
/// # Same crate, same directory, twice — and both halves were learned the hard way
///
/// `attest_proven` refused the first two attempts as
/// [`Unprovable::DifferentProgram`], and it was right both times. What leaks into
/// an allocated section is more than the code:
///
/// ```text
/// the crate name `gpus` vs `gpuu`, in .rodata and in every symbol path
/// the source PATH rustc puts it in panic metadata, so .../shipped/gpu and
/// .../audited/gpu are two different programs
/// ```
///
/// Both were invisible in the coarse numbers — 37 allocated sections and 303 014
/// bytes of content, identical — and the digest caught them anyway. So the
/// fixture builds the *same crate in the same directory* twice, flipping only
/// `strip`, which is exactly what a real delivery does. **That constraint is
/// real, not a test artefact:** a build pipeline that produces its audited copy
/// in a different directory produces a different program, and the attestation
/// will say so rather than paper over it.
fn shipped_and_audited(
root: &Path,
name: &str,
r: &Receipt,
stack: &str,
main_body: &str,
) -> (PathBuf, PathBuf) {
let prelude = format!(
"{}{stack}",
emit_source(r).expect("generate the receipt source")
);
build_two_ways(root, name, &prelude, main_body)
}
/// Compile once with the symbol table, then strip a copy — the real delivery
/// path, through the function the pipeline calls.
///
/// Returns `(shipped, audited)`. `deliver_stripped` does the stripping and the
/// attesting in one call; this helper throws the attestation away and hands back
/// the two files, because most assertions below want to drive `attest_proven`
/// themselves.
fn build_two_ways(root: &Path, name: &str, prelude: &str, main_body: &str) -> (PathBuf, PathBuf) {
let built = build_fixture_with_main(root, name, prelude, main_body, false);
let audited = root.join(format!("{name}-audited"));
std::fs::copy(&built, &audited).expect("keep the unstripped binary");
let shipped = root.join(format!("{name}-shipped"));
deliver_stripped(&audited, &shipped).expect("strip the delivery out of the audited binary");
(shipped, audited)
}
/// **The whole lane over real binaries.** Eleven assertions, each able to go red
/// on its own subject.
///
/// ```text
/// 0 the fixture really links the families the guard on the guard
/// 1 the stripped artifact alone is NOT MEASURED the problem, restated
/// 2 gpu=false over a GPU binary is DISPROVEN THE headline red
/// 3 the evidence names the families and counts
/// 4 the same shape over a GPU-free binary is PROVEN so (2) is not always-red
/// 5 gpu=true over that binary is DISPROVEN too the vacuity direction
/// 6 a stripped binary as the AUDITED one is refused NotMeasured is never a pass
/// 7 audited and shipped must be the same program the bridge, watched red
/// 8 the trade is in the data, both settings
/// 9 verify() catches a tampered proof, two ways
/// 10 regeneration from bytes recovers all but proof stated, not hidden
/// ```
#[test]
fn a_lying_receipt_on_a_stripped_artifact_is_caught_by_the_attestation() {
let root = tempfile::tempdir().expect("scratch dir");
let root = root.path();
let lying = receipt("korp-ui", "false");
let (gpu_shipped, gpu_audited) = shipped_and_audited(root, "gpu", &lying, GPU_STACK, GPU_MAIN);
// (0) The fixture is not empty. Without this the whole file could pass by
// measuring a binary the linker had gutted — the exact silent green it is
// written to catch elsewhere.
let symbols = demangled_symbols(&gpu_audited).expect("the unstripped fixture has symbols");
for family in ["wgpu", "naga", "ash::vk"] {
assert!(
symbols.iter().any(|s| s.contains(family)),
"the fixture must really carry `{family}` symbols, or every assertion below is \
measuring nothing. {} symbols read.",
symbols.len()
);
}
assert!(
demangled_symbols(&gpu_shipped).is_none(),
"the shipped fixture is supposed to be stripped — if it has symbols, `strip = true` \
stopped working and this file is not testing the case it names"
);
// (1) The problem, measured rather than described: on its own, the artifact
// we would deliver cannot be judged at all.
assert_eq!(
audit_artifact(&gpu_shipped).verdict(),
ReceiptVerdict::NotMeasured,
"a stripped artifact must be NOT MEASURED — if this ever says Proven, a binary with \
no symbol table has started proving claims by having nothing to show"
);
// (2) THE headline. Audited at build time, the lie is caught, and the verdict
// is attached to the stripped artifact that ships.
let attested = attest_proven(&gpu_shipped, &gpu_audited).expect("both binaries are real");
let proof = attested.proof.as_ref().expect("a proof was written");
assert_eq!(
proof.verdict,
ReceiptVerdict::Disproven,
"gpu = false over a binary that links wgpu/naga/ash::vk must be DISPROVEN: {:?}",
proof.lines()
);
assert!(!attested.proof_holds());
// (3) …and it says what it counted, or nobody can act on it a year later.
let claim = proof
.claims
.iter()
.find(|c| c.key == "feature.gpu")
.expect("the gpu claim was measured");
assert_eq!(claim.verdict, ClaimVerdict::Disproven);
assert_eq!(claim.claimed, "false");
for family in ["wgpu×", "naga×", "ash::vk×"] {
assert!(
claim.evidence.contains(family),
"the evidence must name {family} and its count: {:?}",
claim.evidence
);
}
assert!(
claim.line.contains("the receipt is a lie"),
"{}",
claim.line
);
assert!(proof.symbols > 0, "{proof:?}");
// (4) The control. The same claim over a program with no GPU family in it is
// PROVEN — so (2) is a measurement and not a check that is always red.
let honest = receipt("korp-server", "false");
let (plain_shipped, plain_audited) =
shipped_and_audited(root, "plain", &honest, PLAIN_STACK, PLAIN_MAIN);
let ok = attest_proven(&plain_shipped, &plain_audited).expect("both binaries are real");
let ok_proof = ok.proof.as_ref().expect("a proof was written");
assert_eq!(
ok_proof.verdict,
ReceiptVerdict::Proven,
"gpu = false over a GPU-free binary must be PROVEN: {:?}",
ok_proof.lines()
);
assert!(ok.proof_holds());
// (5) The other direction of the same lie, on the same bytes: claiming a GPU
// stack that is not there. Without this arm, (4) could be satisfied forever
// by never building anything that links a GPU.
let boastful = receipt("korp-server", "true");
let (boast_shipped, boast_audited) =
shipped_and_audited(root, "boast", &boastful, PLAIN_STACK, PLAIN_MAIN);
let boast = attest_proven(&boast_shipped, &boast_audited).expect("real binaries");
let boast_proof = boast.proof.as_ref().expect("a proof was written");
assert_eq!(boast_proof.verdict, ReceiptVerdict::Disproven);
assert!(
boast_proof
.claims
.iter()
.any(|c| c.line.contains("vacuous")),
"{:?}",
boast_proof.lines()
);
// (6) **NotMeasured never becomes a pass.** Hand in the stripped artifact as
// the audited one — the mistake a build script makes once — and the answer is
// a refusal that names the file, never a proof recording "audited".
match attest_proven(&gpu_shipped, &gpu_shipped) {
Err(Unprovable::NotMeasured { audited }) => {
assert_eq!(audited, gpu_shipped);
let msg = format!("{}", Unprovable::NotMeasured { audited });
assert!(msg.contains("no symbol table"), "{msg}");
}
other => panic!(
"auditing a stripped binary must be refused, not written down as a proof: {other:?}"
),
}
// (7) The bridge, watched going red. Two perfectly readable binaries, both
// with symbol tables, both carrying receipts — and an audit of one says
// nothing about the other.
match attest_proven(&plain_shipped, &gpu_audited) {
Err(Unprovable::DifferentProgram {
audited,
shipped,
sections,
}) => {
assert_ne!(audited, shipped);
assert!(
!sections.is_empty(),
"a refusal that will not say WHICH sections differ leaves the reader with \
two binaries and no next step"
);
}
other => panic!("auditing a different program must be refused: {other:?}"),
}
// …and the bridge holds for the pair that IS the same program, which is the
// green half. Asserted against both files rather than against the stored
// value, so a digest that had quietly become a constant would show.
let ship_code = code_digest(&gpu_shipped).expect("stripped artifact digests");
let audit_code = code_digest(&gpu_audited).expect("unstripped binary digests");
assert_eq!(
ship_code, audit_code,
"strip removed something allocated — the whole bridge rests on it not doing that"
);
assert_eq!(proof.code, ship_code);
assert_ne!(
ship_code,
code_digest(&plain_shipped).expect("digests"),
"two different programs must not share a code digest"
);
// (8) The trade, in the data. The shipped artifact cannot be re-audited, and
// the attestation says so in the field an outsider reads.
assert!(!proof.recomputable);
assert!(
proof
.outsider
.cannot
.iter()
.any(|l| l.contains("re-run the symbol audit")),
"{:?}",
proof.outsider
);
assert!(
proof
.outsider
.can
.iter()
.any(|l| l.contains("recompute `proof.code`")),
"what they CAN still do has to be there too: {:?}",
proof.outsider
);
// The other setting of the same switch: ship the unstripped binary and the
// audit becomes reproducible rather than testimony.
let unstripped_delivery =
attest_proven(&gpu_audited, &gpu_audited).expect("an unstripped delivery");
let live = unstripped_delivery.proof.as_ref().expect("proof");
assert!(live.recomputable);
assert!(
live.outsider
.can
.iter()
.any(|l| l.contains("re-run the symbol audit")),
"{:?}",
live.outsider
);
assert!(
!live
.outsider
.cannot
.iter()
.any(|l| l.contains("re-run the symbol audit")),
"the notice must not say both: {:?}",
live.outsider
);
// (9) Verification over the real artifact, and both ways of faking it.
assert_eq!(attested.verify(&gpu_shipped), AttestationVerdict::Attested);
let mut edited = attested.clone();
edited.proof.as_mut().unwrap().code.sha256 = "0".repeat(64);
assert!(
matches!(
edited.verify(&gpu_shipped),
AttestationVerdict::CodeMismatch { .. }
),
"a proof anchored to another program must not verify: {}",
edited.verify(&gpu_shipped)
);
let mut relabelled = attested.clone();
{
let p = relabelled.proof.as_mut().unwrap();
// The lie that would matter: keep the Disproven verdict, but tell the
// reader they could go and check it themselves.
p.outsider = Outsider::of(true, p.verdict);
}
assert_eq!(
relabelled.verify(&gpu_shipped),
AttestationVerdict::ProofTampered,
"the notice and the fields it describes must not be allowed to disagree"
);
// (10) Regeneration. A package built from attestations keeps its proofs
// across a serialise/parse round trip; a package regenerated from the shipped
// bytes alone does NOT, because the symbols are gone. That is the trade, and
// it is asserted rather than written down somewhere.
let package = HistoryPackage::from_attestations(vec![attested.clone(), ok.clone()]);
let files = package.files().expect("serialise");
let reread = HistoryPackage::from_files(&files).expect("parse");
assert_eq!(reread, package, "the proof did not survive the round trip");
assert_eq!(
reread
.by_artifact(&attested.artifact.sha256)
.and_then(|a| a.proof.as_ref())
.map(|p| p.verdict),
Some(ReceiptVerdict::Disproven)
);
let (regenerated, refused) = HistoryPackage::from_artifacts(&[&gpu_shipped, &plain_shipped]);
assert!(refused.is_empty(), "{refused:?}");
assert_eq!(regenerated.len(), 2);
for a in regenerated.attestations() {
assert!(
a.proof.is_none(),
"a package regenerated from stripped artifacts cannot carry a symbol proof — if \
this ever holds one, either the artifacts stopped being stripped or the proof \
stopped being a measurement"
);
assert!(!a.proof_holds(), "and an absent proof never counts as held");
}
// The receipt half, by contrast, does come back — which is what makes the
// line above a statement about the SYMBOLS and not about regeneration.
assert_eq!(
regenerated
.by_artifact(&attested.artifact.sha256)
.map(|a| &a.receipt),
Some(&attested.receipt)
);
}
/// A receipt with nothing a symbol table can check must not come out Proven.
///
/// Its own test because it is the cheapest way for this whole lane to become
/// decorative: attach an attestation to every artifact, claim nothing provable in
/// any of them, and every build is green forever.
#[test]
fn an_attestation_over_a_receipt_that_claims_nothing_provable_does_not_hold() {
let root = tempfile::tempdir().expect("scratch dir");
let root = root.path();
let mut r = receipt("korp-cli", "false");
r.settings.remove("feature.gpu");
assert!(
!r.settings.is_empty(),
"the receipt still has settings — they are just not checkable ones"
);
let prelude = emit_source(&r).expect("generate");
let (shipped, audited) = build_two_ways(root, "nothing", &prelude, "");
let a = attest_proven(&shipped, &audited).expect("real binaries");
let p = a.proof.as_ref().expect("proof");
assert_eq!(
p.verdict,
ReceiptVerdict::NothingProvable,
"an audit with no subject must not report green: {:?}",
p.lines()
);
assert!(!a.proof_holds());
assert!(p.claims.is_empty(), "{:?}", p.claims);
}
/// **A `strip = true` REBUILD is not the program you audited, and the pipeline
/// says so instead of pretending.**
///
/// This is the measurement that decided the delivery path. Same source, same
/// directory, same target directory, one compilation flag apart:
///
/// ```text
/// strip=false then strip=true .text and .data.rel.ro DIFFER, same sizes
/// strip=false then objcopy every allocated section IDENTICAL
/// ```
///
/// so `strip` in this toolchain is not purely a link-time deletion — flipping it
/// changes the code that comes out. An "audit the unstripped rebuild" pipeline
/// would therefore be auditing a different binary from the one it ships, and the
/// only reason that is not a silent wrong answer is that
/// [`code_digest`](nornir_build_thing::code_digest) catches it.
///
/// The assertion is deliberately weak in one direction: it requires the delivery
/// path to work and the rebuild to be *either* refused or identical. Whether a
/// given crate's `.text` moves is up to the optimiser, and a test that demanded
/// it move would go red the day it stopped — which would be good news, not a
/// regression. What must never happen is a proof written across a mismatch, and
/// that is asserted unconditionally.
#[test]
fn an_unstripped_rebuild_is_never_silently_accepted_as_the_shipped_program() {
let root = tempfile::tempdir().expect("scratch dir");
let root = root.path();
let r = receipt("korp-ui", "false");
let prelude = format!(
"{}{GPU_STACK}",
emit_source(&r).expect("generate the receipt source")
);
// The audited binary, and the delivery cut from it.
let built = build_fixture_with_main(root, "rebuild", &prelude, GPU_MAIN, false);
let audited = root.join("rebuild-audited");
std::fs::copy(&built, &audited).expect("keep");
let shipped = root.join("rebuild-shipped");
let good = deliver_stripped(&audited, &shipped).expect("the delivery path works");
assert!(
good.proof.is_some(),
"stripping the audited binary must always leave the bridge intact"
);
assert!(
demangled_symbols(&shipped).is_none(),
"the delivery is stripped: {} bytes",
std::fs::metadata(&shipped).map(|m| m.len()).unwrap_or(0)
);
// Now the other pipeline: a second compilation with `strip = true`.
let rebuilt = build_fixture_with_main(root, "rebuild", &prelude, GPU_MAIN, true);
match attest_proven(&rebuilt, &audited) {
Ok(a) => {
// Identical after all — then it had better be identical for the
// right reason, i.e. the sections really match.
assert_eq!(
code_digest(&rebuilt).expect("digest"),
code_digest(&audited).expect("digest"),
"a proof was written across binaries whose code digests differ"
);
assert!(a.proof.is_some());
}
Err(Unprovable::DifferentProgram { sections, .. }) => {
assert!(
!sections.is_empty(),
"the refusal must name what differs, or nobody can act on it"
);
}
other => panic!("unexpected outcome for a strip=true rebuild: {other:?}"),
}
}
/// **The verb, not the library.** `cargo xtask build --attest` over a real repo:
/// compile, audit, strip, write the attestation — and go RED on a receipt that
/// lies.
///
/// This is the assertion that says the audit *runs*. Everything above proves the
/// pieces work when something calls them, and the failure mode this whole area
/// has already paid for once is exactly that: the receipt WRITER sat finished in
/// edda for weeks while every build-thing panel said "no receipt written in the
/// artifact", because nothing called it.
///
/// Both directions, on one fixture repo:
///
/// ```text
/// gpu = false, links wgpu -> the verb FAILS, and the attestation is on disk
/// gpu = true, links wgpu -> the verb succeeds, verdict proven
/// ```
///
/// The failing direction writes its attestation *before* returning the error, on
/// purpose: the evidence of a disproven delivery is the most useful artifact of
/// the whole run and throwing it away with the exit code would be the one thing
/// worse than not checking.
#[test]
fn the_build_verb_attests_a_real_repo_and_goes_red_on_a_receipt_that_lies() {
use nornir_build_thing::suite_cli::{run, BuildArgs};
for (gpu_claim, must_hold) in [("false", false), ("true", true)] {
let root = tempfile::tempdir().expect("scratch dir");
let root = root.path();
let r = receipt("att-server", gpu_claim);
std::fs::create_dir_all(root.join("src")).expect("dirs");
std::fs::create_dir_all(root.join(".nornir")).expect("dirs");
std::fs::write(
root.join("Cargo.toml"),
"[package]\nname = \"attrepo\"\nversion = \"0.0.0\"\nedition = \"2021\"\n\
[workspace]\n\
[[bin]]\nname = \"att-server\"\npath = \"src/main.rs\"\n\
[profile.release]\nopt-level = 3\nlto = true\nstrip = true\n",
)
.expect("manifest");
std::fs::write(
root.join("src/main.rs"),
format!(
"{}{GPU_STACK}\nfn main() {{ {GPU_MAIN} println!(\"att\"); }}\n",
emit_source(&r).expect("generate")
),
)
.expect("source");
std::fs::write(
root.join(".nornir/build-variants.toml"),
"[build]\nbase_suite = \"ORIGINAL\"\n\
[[build.variant]]\nname = \"att-server\"\npackage = \"attrepo\"\n\
bin = \"att-server\"\nrole = \"server\"\ndefault = true\n\
profile = \"release\"\nsuites = [\"ORIGINAL\"]\n",
)
.expect("build space");
let out_dir = std::env::var_os("CARGO_TARGET_DIR")
.map(|d| root.join(d))
.unwrap_or_else(|| root.join("target"))
.join("release");
let json = out_dir.join("att-server.attestation.json");
// Cleared BEFORE the run: under a shared `CARGO_TARGET_DIR` the previous
// iteration's file is still sitting there, and reading that one back
// would make this test green on a run that wrote nothing at all.
let _ = std::fs::remove_file(&json);
let args = BuildArgs {
attest: true,
..Default::default()
};
let outcome = run(root, &args);
// The attestation is on disk either way — that is the point of writing it
// before deciding the exit code.
assert!(
json.is_file(),
"gpu={gpu_claim}: no attestation at {} (verb said {outcome:?})",
json.display()
);
let text = std::fs::read_to_string(&json).expect("read the attestation");
let parsed: serde_json::Value = serde_json::from_str(&text).expect("valid JSON");
let verdict = parsed["proof"]["verdict"].as_str().unwrap_or("<missing>");
if must_hold {
assert!(
outcome.is_ok(),
"gpu=true over a binary that links wgpu must pass: {outcome:?}"
);
assert_eq!(verdict, "proven", "{text}");
} else {
let err = format!("{:#}", outcome.expect_err("a lying receipt must be RED"));
assert!(err.contains("does NOT survive"), "{err}");
assert_eq!(verdict, "disproven", "{text}");
assert!(
text.contains("wgpu×"),
"the evidence travels in the file: {text}"
);
}
// The delivery really is stripped, and really is anchored.
let artifact = out_dir.join("att-server");
assert!(
demangled_symbols(&artifact).is_none(),
"the delivered artifact must have no symbol table"
);
assert_eq!(
parsed["proof"]["code"]["sha256"].as_str().unwrap_or(""),
code_digest(&artifact).expect("digest").sha256,
"the attestation must be anchored to the bytes on disk"
);
assert_eq!(parsed["proof"]["recomputable"], serde_json::json!(false));
}
}