57c56ee4e2
The load seam's aura-core stamp becomes AURA_CORE_FINGERPRINT: an FNV-1a
64 hash over aura-core's sorted src/**/*.rs (prefix-free records: path,
NUL, u64-LE content length, contents), emitted by build.rs beside the
rustc stamp and baked into the descriptor by aura_project!. validate_c_tier
compares fingerprints ('aura-core build'); a stale dylib — same rustc,
different aura-core sources — is refused instead of trusted at the
Rust-ABI tier. RED-first: the headline test pins that the frozen crate
version is never again the host stamp (plus a version-bump-proof twin and
an aura-core shape pin: 16 hex, never CARGO_PKG_VERSION).
Descriptor field renamed aura_core_version -> aura_core_fingerprint
(engine-internal; field names are not ABI, order is). Documented accepted
C30 limit: source-level identity only — the consuming build's lockfile/
features stay outside the stamp. C13/C30 prose aligned.
closes #348
77 lines
3.1 KiB
Rust
77 lines
3.1 KiB
Rust
//! Bakes the compiling toolchain's version into `AURA_RUSTC_VERSION`, and a
|
|
//! deterministic fingerprint of aura-core's own sources into
|
|
//! `AURA_CORE_FINGERPRINT`, so the project descriptor (src/project.rs) can
|
|
//! stamp both. Runs per consuming build: the host binary and a project
|
|
//! cdylib each recompile aura-core under their own toolchain / from their own
|
|
//! checkout, which is exactly what makes the two stamps comparable (C30: the
|
|
//! load seam commits to a build-identity fingerprint, never the frozen crate
|
|
//! version).
|
|
|
|
use std::path::{Path, PathBuf};
|
|
|
|
const FNV_OFFSET_BASIS: u64 = 0xcbf2_9ce4_8422_2325;
|
|
const FNV_PRIME: u64 = 0x0100_0000_01b3;
|
|
|
|
fn fnv1a(bytes: &[u8], mut hash: u64) -> u64 {
|
|
for &b in bytes {
|
|
hash ^= b as u64;
|
|
hash = hash.wrapping_mul(FNV_PRIME);
|
|
}
|
|
hash
|
|
}
|
|
|
|
/// Recursively collect every `*.rs` file under `dir`.
|
|
fn collect_rs_files(dir: &Path, out: &mut Vec<PathBuf>) {
|
|
let Ok(entries) = std::fs::read_dir(dir) else { return };
|
|
for entry in entries.flatten() {
|
|
let path = entry.path();
|
|
if path.is_dir() {
|
|
collect_rs_files(&path, out);
|
|
} else if path.extension().is_some_and(|e| e == "rs") {
|
|
out.push(path);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
let rustc = std::env::var("RUSTC").unwrap_or_else(|_| "rustc".into());
|
|
let out = std::process::Command::new(&rustc)
|
|
.arg("--version")
|
|
.output()
|
|
.expect("rustc --version");
|
|
println!(
|
|
"cargo:rustc-env=AURA_RUSTC_VERSION={}",
|
|
String::from_utf8_lossy(&out.stdout).trim()
|
|
);
|
|
|
|
// Deterministic staleness fingerprint: hash (relative path + contents) of
|
|
// every source file under src/, in sorted order. Not a security hash —
|
|
// FNV-1a is dependency-free and plenty for detecting a stale build. This
|
|
// is *source-level* identity only, an accepted C30 limit: the consuming
|
|
// build resolves its own lockfile and features, so shared-dependency
|
|
// types riding the Rust tier (e.g. chrono-tz's) are NOT guarded by this
|
|
// stamp — the seam refuses staleness of aura-core itself, not the full
|
|
// link graph.
|
|
let src_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("src");
|
|
let mut files = Vec::new();
|
|
collect_rs_files(&src_dir, &mut files);
|
|
files.sort();
|
|
|
|
let mut hash = FNV_OFFSET_BASIS;
|
|
for path in &files {
|
|
// The walk starts at src_dir, so every path strips; a silent fallback
|
|
// here would make the fingerprint checkout-dependent.
|
|
let rel = path.strip_prefix(&src_dir).expect("walked file lies outside src/");
|
|
let contents = std::fs::read(path).expect("read aura-core source file");
|
|
// Prefix-free record: path NUL length-prefixed contents (paths never
|
|
// contain NUL, the length pins the content boundary).
|
|
hash = fnv1a(rel.to_string_lossy().as_bytes(), hash);
|
|
hash = fnv1a(&[0], hash);
|
|
hash = fnv1a(&(contents.len() as u64).to_le_bytes(), hash);
|
|
hash = fnv1a(&contents, hash);
|
|
}
|
|
|
|
println!("cargo:rustc-env=AURA_CORE_FINGERPRINT={hash:016x}");
|
|
println!("cargo:rerun-if-changed=src");
|
|
}
|