selfhost-verify: pieza 4 (bwrap swap) + materialización de build-deps en el lab

Cuarta pieza del toolchain hammer-from-source (variante b, SDD 11 §7.2b): bubblewrap, el
sandbox del propio lab. Binario estático ⇒ swap de archivo sobre /toolchain/usr/bin/bwrap.
Como herramienta del toolchain (no input del 4/4) no necesita casar byte-a-byte con Alpine,
sólo aislar igual.

Tres piezas:
- recipes/libcap.toml (2.78): dep obligatoria de bwrap; el toolchain Alpine no trae el -dev
  (libcap.a / sys/capability.h). Build estático musl con zig cc, sin patches (es tool, no input).
- materialización de build-deps (hammer-build): deps.build ahora se CONSTRUYE recursivamente
  (build() llama build() por cada dep) y cada artefacto sellado se apila como capa --overlay-src
  bajo el rootfs del sandbox, dejando usr/{include,lib,lib/pkgconfig} en /usr. pkgconf y zig cc
  las hallan sin plumbing de flags. Recetas sin deps: sandbox byte-igual (baseline intacto).
  Tests nuevos: no_deps_emits_single_overlay_src, deps_stack_as_overlay_layers_under_rootfs.
- recipes/bwrap.toml (0.11.0): el toolchain no trae meson/ninja/python, así que bypaseamos meson
  compilando los 4 .c de bubblewrap directo con zig cc (+config.h trivial). deps.build=["libcap"].

Validación host fuerte: hammer-bwrap es estático, corre --version y sandboxea, y musl rebuildeó
BYTE-IDÉNTICO usándolo de sandbox (bisección). Expuesto con SWAP_BWRAP=1. Tests verdes.
Pendiente: corrida in-VM acumulando swaps para el sello ✓ REPRODUCIBLE.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-13 20:05:55 -04:00
co-authored by Claude Opus 4.8
parent b05badee23
commit e9f535a1bb
6 changed files with 214 additions and 5 deletions
+17 -1
View File
@@ -117,9 +117,14 @@ done
# SWAP_BUSYBOX=1 → monta el busybox de hammer sobre /toolchain/bin/busybox (los symlinks de
# applets de Alpine — sh/sed/grep/awk/tar/find — pasan a usarlo; cp/mkdir/
# install siguen siendo GNU coreutils, intactos).
# SWAP_LINUX_HEADERS=1 → construye recipes/linux-headers.toml y swap-directorio de los 13 subdirs
# kernel-owned de /toolchain/usr/include (linux/asm/…); musl bits/sys intactos.
# SWAP_BWRAP=1 → construye recipes/bwrap.toml (+libcap, su dep, vía deps.build) y lo monta
# sobre /toolchain/usr/bin/bwrap (el sandbox del propio lab).
# SWAPS="name=hash[:rel] …" → swaps explícitos extra (formato del flag --swap).
# Por defecto, off ⇒ corrida pura-Alpine (variante a), idéntica a la baseline conocida-buena.
# Ambas piezas validadas en host: con make+busybox de hammer los 4/4 reproducen of_tree=9adefb82.
# Piezas validadas en host: make+busybox reproducen of_tree=9adefb82 in-VM; linux-headers da un
# header-tree byte-idéntico a Alpine (diff -r vacío); bwrap rebuildea musl byte-idéntico de sandbox.
SWAP_ARGS=()
if [[ "${SWAP_MAKE:-0}" == 1 ]]; then
say "variante b — construir make desde fuente (recipes/make.toml) y swapearlo en /toolchain"
@@ -152,6 +157,17 @@ if [[ "${SWAP_LINUX_HEADERS:-0}" == 1 ]]; then
SWAP_ARGS+=(--swap "linux-headers=${LH_HASH}:usr/include/$sub")
done
fi
if [[ "${SWAP_BWRAP:-0}" == 1 ]]; then
# Pieza 4: bwrap (bubblewrap), EL sandbox del lab. Binario estático ⇒ swap de archivo sobre
# /toolchain/usr/bin/bwrap. Su dep libcap la construye y materializa el lab solo (deps.build).
# bwrap es herramienta, no input del 4/4: no necesita casar byte-a-byte con Alpine, sólo aislar
# igual (validado en host — musl rebuildeó byte-idéntico bajo hammer-bwrap).
say "variante b — construir bwrap (+libcap) desde fuente y swapearlo en /toolchain/usr/bin/bwrap"
BW_HASH="$("$HAMMER" --store "$STORE" build recipes/bwrap.toml | grep -oE 'b3:[0-9a-f]{64}' | tail -1)"
[[ "$BW_HASH" == b3:* ]] || die "no obtuve el hash sellado de bwrap"
say "bwrap hammer: $BW_HASH"
SWAP_ARGS+=(--swap "bwrap=${BW_HASH}:usr/bin/bwrap")
fi
for s in ${SWAPS:-}; do SWAP_ARGS+=(--swap "$s"); done
# 4) Ensamblar el builder con la referencia embebida.