1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
//! Build script — derive `EMBEDDED_TRUSTED_ROOT_SNAPSHOT_DATE` from the
//! embedded `sigstore_trusted_root_YYYY-MM-DD.json` filename.
//!
//! ## Why a build script
//!
//! Finding F2 (`docs/reviews/BUG_HUNT_2026-05-12_post_8f43450.md`) — the
//! constant `EMBEDDED_TRUSTED_ROOT_SNAPSHOT_DATE` in
//! `src/external_sink/trusted_root.rs` previously sat next to the
//! `include_bytes!("embedded/sigstore_trusted_root_2026-05-12.json")` literal
//! as a hand-written sibling. A future snapshot refresh that bumped the
//! filename (e.g. `…_2026-08-12.json`) but forgot to bump the constant
//! would silently anchor the 30-day freshness gate to the stale capture
//! date.
//!
//! This script enforces the invariant at build time:
//!
//! 1. Read `src/external_sink/embedded/` and find every entry matching
//! `sigstore_trusted_root_YYYY-MM-DD.json`.
//! 2. Refuse any entry that is a symlink (Red Team v2 F2-S1: a
//! name-friendly symlink planted at checkout time could redirect
//! `include_bytes!` to attacker-controlled JSON).
//! 3. Validate the date prefix is a real calendar date via
//! `chrono::NaiveDate::parse_from_str` (Code Review v2 F3: stops
//! `…_2026-02-30.json` from compiling and failing at runtime).
//! 4. Fail loudly with a hard build error if zero or multiple matches
//! are found — both cases mean operator intent is ambiguous.
//! 5. Emit `cargo:rustc-env=EMBEDDED_TRUSTED_ROOT_SNAPSHOT_DATE=YYYY-MM-DD`
//! so the source can `env!()` it instead of hand-writing a parallel
//! literal.
//! 6. Emit `cargo:rerun-if-changed=...` on the embedded directory and
//! every matching file so a snapshot refresh re-runs this script.
//!
//! ## Trade-off vs. test-only pin (option 2 in the finding)
//!
//! Option 2 (a `#[cfg(test)]` enumerator + assert_eq!) was rejected as
//! the primary mechanism because a CI run that only invoked
//! `cargo check` / `cargo clippy` could skip the test and let the
//! drift land in main. The build-script approach is structurally safer:
//! every consumer of the crate, including doc-builds and downstream
//! `cargo check`, evaluates this script.
//!
//! The trade-off is that a build-script bug can mask a Rust error. The
//! script delegates to `build_validation::discover_embedded_snapshot`
//! (in `build_validation.rs`), which is unit-tested against synthetic
//! directories from `tests/build_validation.rs`.
use Path;
use discover_embedded_snapshot;
const EMBEDDED_DIR: &str = "src/external_sink/embedded";