use std::fs;
use std::path::Path;
struct ZeroizeRow {
label: &'static str,
source_file: &'static str,
evidence: &'static [&'static str],
}
const ZEROIZE_ROWS: &[ZeroizeRow] = &[
ZeroizeRow {
label: "envelope::discriminate() wraps OWNED payload Vec",
source_file: "src/envelope.rs",
evidence: &["payload_with_prefix: Zeroizing<Vec<u8>>"],
},
ZeroizeRow {
label: "envelope::package() wraps OWNED data Vec",
source_file: "src/envelope.rs",
evidence: &["let data: Zeroizing<Vec<u8>>"],
},
ZeroizeRow {
label: "payload.rs documents caller-wrap contract",
source_file: "src/payload.rs",
evidence: &["Caller-wrap contract", "must wrap"],
},
ZeroizeRow {
label: "shares::{encode_shares,combine_shares} wrap OWNED secret Vecs",
source_file: "src/shares.rs",
evidence: &[
"let mut filler: Zeroizing<Vec<u8>>",
"let data: Zeroizing<Vec<u8>> = Zeroizing::new(secret.parts().data())",
],
},
ZeroizeRow {
label: "codex32::Codex32String scrubs its inner String on drop (vendored, Cycle-B)",
source_file: "src/codex32/mod.rs",
evidence: &[
"zeroize::ZeroizeOnDrop",
"impl fmt::Debug for Codex32String",
],
},
];
fn crate_root() -> &'static Path {
Path::new(".")
}
#[test]
fn canonical_list_has_expected_row_count() {
let n = ZEROIZE_ROWS.len();
assert_eq!(
n, 5,
"ZEROIZE_ROWS row count = {n}; expected 5 (3 v0.1 survey §1 rows + 1 v0.2 K-of-N shares.rs row + 1 vendored-codex32 Codex32String drop-scrub row, Cycle-B; the theater decode row was dropped in cycle-15 Lane M slug #2)."
);
}
#[test]
fn decode_has_no_clone_into_bare_vec() {
let src = fs::read_to_string(crate_root().join("src/decode.rs")).expect("read src/decode.rs");
assert!(
!src.contains("(*scrubbed).clone()"),
"decode.rs still contains the theater `(*scrubbed).clone()` — the slug-#2 \
move-into-Payload fix is missing or regressed."
);
assert!(
!src.contains("let scrubbed: Zeroizing<Vec<u8>>"),
"decode.rs still binds the throwaway `scrubbed` Zeroizing envelope — the \
slug-#2 fix removed it; the bytes move straight into `Payload`."
);
}
#[test]
fn every_canonical_zeroize_row_has_evidence_anchor() {
let mut missing: Vec<String> = Vec::new();
for row in ZEROIZE_ROWS {
let path = crate_root().join(row.source_file);
let source = fs::read_to_string(&path).unwrap_or_else(|e| {
panic!(
"failed to read evidence source {} for row {:?}: {e}",
path.display(),
row.label
)
});
let hit = row.evidence.iter().any(|needle| source.contains(needle));
if !hit {
missing.push(format!(
" - {} ({}): no evidence anchor; expected one of {:?}",
row.label, row.source_file, row.evidence,
));
}
}
assert!(
missing.is_empty(),
"ms-codec zeroize-discipline lint: {} row(s) missing Zeroizing evidence:\n{}",
missing.len(),
missing.join("\n"),
);
}