diff --git a/scripts/static-audit.sh b/scripts/static-audit.sh index 9f6f2012..be8ed8f7 100755 --- a/scripts/static-audit.sh +++ b/scripts/static-audit.sh @@ -43,10 +43,39 @@ if [ $# -gt 0 ]; then recetas="" for n in "$@"; do recetas="$recetas recipes/$n.toml"; done else - recetas="$(grep -lE '^[[:space:]]*link[[:space:]]*=[[:space:]]*"static"' recipes/*.toml)" + # ⚠ **LAS COLAS TAMBIÉN.** Esto globeaba SÓLO `recipes/*.toml` y remataba con «✅ toda receta que + # declara link=static lo cumple» — una frase verdadera de una PARTE del corpus presentada como si + # fuera de todo él. Las cinco colas (`incoming{,-kde,-gnome,-cosmic,-wlr}`) son ~305 recetas que + # NUNCA se auditaron. Se destapó promoviendo `libseccomp` de `incoming-gnome/` al corpus el + # 2026-09-11: el artefacto no cambió ni un byte y el audit pasó de MIENTEN:0 a MIENTEN:1. O sea + # que la mentira estaba ahí desde siempre y lo único que la tapaba era el glob de esta línea. + # Un guardián que mide menos de lo que su resumen afirma es peor que no tenerlo: da por + # cubierto lo que no mira. Ver [[guardian-que-nunca-fallo]]. + recetas="$(grep -lE '^[[:space:]]*link[[:space:]]*=[[:space:]]*"static"' \ + recipes/*.toml recipes/incoming*/*.toml 2>/dev/null)" fi -mienten=0; honestos=0; sin=0 +# ── DEUDA MEDIDA Y DECIDIDA ──────────────────────────────────────────────────────────────────── +# Mentiras REALES cuyo arreglo está decidido EN CONTRA por ahora. Se imprimen como `•` con el número +# delante y NO hacen fallar. El motivo de separarlas no es cosmético: si el audit falla siempre por +# tres viejas, un ofensor NUEVO se pierde entre el ruido y el guardián deja de servir — que es +# exactamente cómo se muere uno. +# +# Las tres salieron a la luz el 2026-09-11 al ampliar el barrido a las colas (antes sólo miraba +# `recipes/*.toml`). En las tres, lo dinámico es un BINARIO AUXILIAR de diagnóstico, no la librería: +# los consumidores enlazan el `.a`, así que el impacto funcional hoy es NULO. Lo que está mal es la +# DECLARACIÓN, y arreglarla se paga en rebuilds (radio medido con `yupana radio`, que cruza colas): +# +# libseccomp scmp_sys_resolver 6 rebuilds (corpus 1 + incoming-gnome 5) +# libgcrypt dumpsexp y 2 más 41 rebuilds (corpus 1 + incoming-kde 40) +# libgpg-error gpg-error 45 rebuilds (corpus 4 + incoming-kde 41) +# +# ~92 rebuilds, casi todos KDE, para que tres binarios que nadie invoca dejen de ser dinámicos. Va +# con el próximo bump de cada una, cuando el re-hash ya esté pagado y la línea cueste cero — el mismo +# criterio que la deuda de `perl`. Esto no es un olvido: es una decisión con el número delante. +DEUDA_DECIDIDA=" libseccomp libgcrypt libgpg-error " + +mienten=0; honestos=0; sin=0; deuda=0 for f in $recetas; do n=$(basename "$f" .toml) grep -qE '^[[:space:]]*link[[:space:]]*=[[:space:]]*"static"' "$f" || continue @@ -94,6 +123,12 @@ for f in $recetas; do [ "$vistos" -eq 0 ] && { sin=$((sin + 1)); continue; } if [ -n "$needed" ]; then + case "$DEUDA_DECIDIDA" in + *" $n "*) + printf ' • %-18s DEUDA DECIDIDA: %d/%d ejecutable(s) dinámico(s) (%s) — auxiliar, no la librería\n' \ + "$n" "$malos" "$vistos" "$primer_malo" + deuda=$((deuda + 1)); continue ;; + esac if [ "$malos" -gt 1 ]; then printf ' ✗ %-18s dice static, %d de %d ejecutables DINÁMICOS (p.ej. %s) → %s\n' \ "$n" "$malos" "$vistos" "$primer_malo" "$needed" @@ -109,10 +144,10 @@ for f in $recetas; do done echo -echo "══ estáticos de verdad: $honestos | MIENTEN: $mienten | sin artefacto o sin ELF: $sin" +echo "══ estáticos de verdad: $honestos | MIENTEN (nuevos): $mienten | deuda decidida: $deuda | sin artefacto o sin ELF: $sin" [ "$mienten" -gt 0 ] && { echo " fix: LDFLAGS=\"-all-static -no-pie\" en compile Y en install (libtool relinkea al instalar)" exit 1 } -echo " ✅ toda receta que declara link=static lo cumple" +echo " ✅ ninguna receta NUEVA miente (corpus + las 5 colas). Las $deuda de deuda decidida están arriba, con su radio." exit 0