crtx-ledger 0.1.1

Append-only event log, hash chain, trace assembly, and audit records.
Documentation
//! 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 std::path::Path;

#[path = "build_validation.rs"]
mod build_validation;

use build_validation::discover_embedded_snapshot;

const EMBEDDED_DIR: &str = "src/external_sink/embedded";

fn main() {
    // Re-run when anyone touches the embedded directory (e.g. operator
    // drops in a refreshed snapshot).
    println!("cargo:rerun-if-changed={EMBEDDED_DIR}");
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=build_validation.rs");

    let discovery = match discover_embedded_snapshot(Path::new(EMBEDDED_DIR)) {
        Ok(discovery) => discovery,
        Err(err) => panic!("cortex-ledger build.rs: {err}"),
    };

    // Emit a rerun trigger on each matched file so a snapshot refresh
    // that bumps the filename (rename) triggers a rebuild even on
    // systems whose directory-mtime semantics are weak.
    for filename in &discovery.matched_filenames {
        println!(
            "cargo:rerun-if-changed={}",
            Path::new(EMBEDDED_DIR).join(filename).display()
        );
    }

    // Emit for `env!("EMBEDDED_TRUSTED_ROOT_SNAPSHOT_DATE")` in
    // `trusted_root.rs`. Cargo restricts these to the crate the
    // build script is for; downstream crates do NOT see this env var,
    // which is the correct scope.
    println!(
        "cargo:rustc-env=EMBEDDED_TRUSTED_ROOT_SNAPSHOT_DATE={}",
        discovery.snapshot.date
    );
}