From 9a5f06eaa2ffb9cead9615dd8cf4680d9c6bc33c Mon Sep 17 00:00:00 2001 From: Jer Miller Date: Wed, 22 Jul 2026 18:22:22 -0600 Subject: [PATCH] fix(rust): resolve transparency publisher review findings Document why snapshot_candidate intentionally performs a diagnostic-only deserialize before authoritative validation: the schema pins source_dirty to const:false, while the early check preserves the source-specific failure. Remove the dead first-publication setup from the mutable-object publication and resign test, and correct the archive-channel documentation to specify its sole staging-directory argument and verified ARCHIVED receipt on stdout. Co-Authored-By: OpenAI Codex --- RELEASING.md | 4 +++- .../rust-release-manifest/src/transparency.rs | 3 +++ .../src/transparency_tests.rs | 17 ++++++----------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/RELEASING.md b/RELEASING.md index de309de..3dfbd85 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -234,7 +234,9 @@ version. - `TRANSPARENCY_MINISIGN_PUB` — local path to the corresponding public trust anchor. - `TRANSPARENCY_ARCHIVE_CHANNEL` — archive command invoked with the staging - directory and its SHA-256 receipt; required for publication. + directory as its sole argument; required for publication. The command must + emit an `ARCHIVED ` receipt as the last line of stdout, which the + publisher verifies against the manifest SHA-256. - `TRANSPARENCY_GENESIS` — first-publication approval; only the literal value `1` enables genesis. diff --git a/crates/rust-release-manifest/src/transparency.rs b/crates/rust-release-manifest/src/transparency.rs index 079ea30..9e2fe60 100644 --- a/crates/rust-release-manifest/src/transparency.rs +++ b/crates/rust-release-manifest/src/transparency.rs @@ -1764,6 +1764,9 @@ pub(crate) fn snapshot_candidate(root: &RepoRoot, release_dir: &Path) -> Result< .find(|path| path.file_name().and_then(OsStr::to_str).is_some_and(|name| name.ends_with(".rust-release-manifest.json"))) .ok_or_else(|| Error::new("terminal: transparency manifest mismatch: expected one companion manifest, actual missing\nrepair: restore the retained five-file candidate"))?; let manifest_bytes = fs::read(&manifest_path).map_err(display_error)?; + // The schema pins source_dirty to const:false, so full validation would only + // report a generic schema mismatch. This diagnostic-only deserialize gives a + // source-specific error; every non-dirty path still runs authoritative validation. let unchecked_manifest: Manifest = serde_json::from_slice(&manifest_bytes).map_err(display_error)?; if unchecked_manifest.source_dirty { diff --git a/crates/rust-release-manifest/src/transparency_tests.rs b/crates/rust-release-manifest/src/transparency_tests.rs index 5211a11..6c7fe48 100644 --- a/crates/rust-release-manifest/src/transparency_tests.rs +++ b/crates/rust-release-manifest/src/transparency_tests.rs @@ -980,16 +980,11 @@ fn transparency_directory_fake_mutable_put_overwrites_existing_object() { #[test] fn transparency_second_publication_and_resign_replace_mutable_objects_end_to_end() { - let mut first_transport = FaultTransport::new(); - run_fixture_publication_with_remote_and_chain(&mut first_transport, None, None) - .0 - .unwrap(); - - let mut second_transport = FaultTransport::new(); - let (chain, old_pointer, old_signature) = seed_old_chain(&mut second_transport); + let mut transport = FaultTransport::new(); + let (chain, old_pointer, old_signature) = seed_old_chain(&mut transport); let old_ledger = chain.transparency_ledger.clone(); let (result, new_pointer, objects) = - run_fixture_publication_with_remote_and_chain(&mut second_transport, None, Some(chain)); + run_fixture_publication_with_remote_and_chain(&mut transport, None, Some(chain)); result.unwrap(); let prefix = objects.join("releases/solstone-linux"); let ledger_path = prefix.join("ledger.jsonl"); @@ -1011,16 +1006,16 @@ fn transparency_second_publication_and_resign_replace_mutable_objects_end_to_end let renewed_signature = fake_signature(&pointer_trusted_comment(&renewed)); let signature_destination = s3_destination("releases/solstone-linux/latest.json.minisig"); let pointer_destination = s3_destination("releases/solstone-linux/latest.json"); - second_transport + transport .put_mutable(&signature_destination, &renewed_signature, MUTABLE_CACHE) .unwrap(); - let etag = second_transport + let etag = transport .get(&pointer_destination, true) .unwrap() .etag .unwrap(); assert_eq!( - second_transport + transport .put_conditional(&pointer_destination, &renewed_bytes, &etag, MUTABLE_CACHE,) .unwrap() .http_status, -- 2.51.2