hammer hash: dry-run que faltaba — cierra el sobre-reporte del static-audit de raíz
El agujero que dejé señalado 3 veces esta sesión: nada podía saber el sellado VIGENTE de una receta sin construirla, así que static-audit.sh auditaba el más reciente por mtime (ls -dt) y acusaba a recetas ya sanas (dbus/libnl) por un sellado anterior a sus flags. FIX = subcomando `hammer hash <receta> [--check]`. Calcula el ArtifactHash puro sobre las recetas (source_id + compiler/target/link + patches + flags + fases + hashes de deps recursivos) SIN bajar fuentes ni compilar. artifact_hash() ya era pub; el CLI sólo lo expone. Cero cambios en la lógica de hashing ⇒ NINGÚN sellado se mueve. Verificado: `hash` da EXACTAMENTE el mismo hash que `build` (samurai, byte a byte); `--check` sobre receta editada → NO-SELLADO en 2ms, exit 1, sin construir nada. static-audit.sh ahora selecciona el artefacto VIGENTE por hash, no el más reciente por mtime. Con fallback a ls -dt si hammer no está compilado. Efecto en el store completo: las ~65 recetas cuyo sellado no es el vigente pasan de 'auditadas' (falsa cobertura) a 'sin artefacto' (deuda de rebuild REAL, ahora visible): estáticas de verdad 615 | MIENTEN 0 | sin artefacto 123. Corre en 15s, sin build. El '58 sin medir' de antes estaba enmascarando ~65 recetas más. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,18 @@ enum Cmd {
|
||||
/// Ruta a la receta TOML.
|
||||
recipe: String,
|
||||
},
|
||||
/// [Fase 0] Calcula el `ArtifactHash` de una receta SIN construir — puro sobre las recetas
|
||||
/// (source_id + compiler/target/link + patches + flags + fases + hashes de deps). No baja
|
||||
/// fuentes ni compila. Responde "¿cuál es el hash VIGENTE de esta receta?", que el store no
|
||||
/// puede dar sin sellar. Con `--check`: exit 0 si el artefacto vigente ya está en el store,
|
||||
/// 1 si no — el dry-run que le faltaba a scripts/static-audit.sh para no auditar sellados rancios.
|
||||
Hash {
|
||||
/// Ruta a la receta TOML.
|
||||
recipe: String,
|
||||
/// No imprime el hash; verifica si el artefacto vigente está sellado en el store (exit 0/1).
|
||||
#[arg(long)]
|
||||
check: bool,
|
||||
},
|
||||
/// [Atestación] Verifica un árbol FHS (p.ej. un product-rootfs hidratado) contra su
|
||||
/// `/ente/attest.json`: recomputa el BLAKE3 de cada binario crítico y lo compara. Es el gate de
|
||||
/// integridad que arje aplicará al boot, hecho hoy por hammer ("reproducir, no confiar"). Exit≠0
|
||||
@@ -755,6 +767,24 @@ fn main() -> anyhow::Result<()> {
|
||||
let hash = hammer_build::build(&recipe, &cfg, &store)?;
|
||||
println!("{hash}");
|
||||
}
|
||||
Cmd::Hash { recipe, check } => {
|
||||
let store = hammer_core::Store::open(&cli.store)?;
|
||||
let recipe = hammer_core::Recipe::load_from_path(&recipe)?;
|
||||
let hash = hammer_build::artifact_hash(&recipe, &store)?;
|
||||
if check {
|
||||
// ¿el artefacto VIGENTE (el que corresponde a la receta de HOY) ya está sellado?
|
||||
// Es lo que static-audit.sh no podía saber: `ls -dt store/*-<n>` da el más RECIENTE,
|
||||
// no el vigente. Exit 0 = sellado al día; 1 = haría falta construir.
|
||||
if store.has(&hash, &recipe.name) {
|
||||
println!("{hash}\tSELLADO");
|
||||
} else {
|
||||
println!("{hash}\tNO-SELLADO");
|
||||
std::process::exit(1);
|
||||
}
|
||||
} else {
|
||||
println!("{hash}");
|
||||
}
|
||||
}
|
||||
Cmd::Attest { rootfs } => {
|
||||
let report = hammer_bootstrap::verify_attestation(std::path::Path::new(&rootfs))?;
|
||||
for p in &report.ok {
|
||||
|
||||
Reference in New Issue
Block a user