tawasuyu

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 604Rust 56Shell 36Markdown 281227 Definitions

verificar-arranque: el test de arranque, en un comando y desde el repo

A pedido del usuario: «lo que necesitas de kvm guardalo en el repo, por si en
la laptop donde no tengo granja pero actualizo el repo, lo pruebo».

`scripts/verificar-arranque.sh` es el punto de entrada: FIJA el artefacto que
hay que verificar (b3:9d4d28c7, el product-rootfs con simi en lugar de
busybox), comprueba las cinco piezas que hacen falta y, por cada una que falte,
dice CÓMO conseguirla — rsync desde el hub/worker, o los dos comandos de
bootstrap para reconstruirla. Si todo está, corre el test.

Fijar el hash importa: `product-boot-test.sh` sin `PRODUCT` coge «el más
reciente del store», que en una máquina ajena puede ser cualquier cosa.

Y avisa de la aceleración: con /dev/kvm tarda segundos, sin él va por TCG y
tarda MINUTOS — por eso sube el DEADLINE a 600 s. Un test que parece colgado se
cancela, y entonces no verifica nada.

── Dos arreglos a product-boot-test.sh que lo hacían no-portable ──

1. EL STORE SE RESUELVE, NO SE SUPONE. Usaba `store/` RELATIVO en cuatro
   sitios, así que en el hub decía «no encuentro product-rootfs» con 1400
   artefactos al lado: ahí el store es /store y el ./store del clon está vacío.
   Misma enfermedad que tenía poda-fuentes.sh. Ahora honra
   HAMMER_STORE/TAKANA_STORE/STORE, cae a /store si tiene contenido, y a
   ./store como último recurso — que es el caso del portátil recién clonado.

2. TESTKEY, porque ssh-keygen NO SIEMPRE PUEDE generar la clave. Medido en la
   jaula: corre como uid 1001 y su /etc/passwd no tiene ese uid, así que muere
   con «No user exists for uid 1001». Probados -C, LOGNAME, USER y HOME: los
   cuatro fallan igual. Con TESTKEY=<ruta> se usa una clave ya hecha.

── Por qué no se verificó donde se hizo el cambio ──

Dos razones medidas, ninguna del cambio: no hay qemu-system-x86_64 en la jaula,
y tampoco /dev/kvm (una VM de Hetzner no expone virtualización anidada). El
guion las nombra las dos en vez de fallar de forma opaca.

3e9432fe67fa10d85cf1739aa7087ae9d546b063 · by Sergio · (12 h ago) · parent 0c1179f44 · browse the tree at this commit

Semantic delta

No definition changed: this change is text, documentation or data.

2 files · +175 −4

diff --git a/scripts/product-boot-test.sh b/scripts/product-boot-test.sh
index 8e6e01e1..f22a764d 100755
--- a/scripts/product-boot-test.sh
+++ b/scripts/product-boot-test.sh
@@ -13,15 +13,29 @@
 # Vars:  KERNEL MEM (def 2048) KVM (def 1) PORT (def 2223) DEADLINE (def 150)
 set -euo pipefail
 ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT"
-KERNEL="${KERNEL:-$(ls store/*-linux/boot/bzImage 2>/dev/null | head -1)}"
+# ── ⚠ EL STORE SE RESUELVE, NO SE SUPONE (2026-10-22) ──────────────────────────────────────────
+# Esto usaba `store/` RELATIVO en cuatro sitios, y por eso no corría en el hub: ahí el store vive
+# en `/store` y el `./store` del clon está VACÍO, así que el script decía «no encuentro
+# product-rootfs» con 1400 artefactos al lado. Misma enfermedad que tenía `poda-fuentes.sh`.
+#
+# Ahora: `$HAMMER_STORE` / `$TAKANA_STORE` / `$STORE` si están, `/store` si existe, y `./store` como
+# último recurso — que es el caso del portátil con el repo recién clonado.
+STORE_DIR="${HAMMER_STORE:-${TAKANA_STORE:-${STORE:-}}}"
+if [ -z "$STORE_DIR" ]; then
+  if [ -d /store ] && [ -n "$(ls -d /store/*-* 2>/dev/null | head -1)" ]; then STORE_DIR=/store
+  else STORE_DIR="$ROOT/store"; fi
+fi
+[ -d "$STORE_DIR" ] || { echo "no existe el store '$STORE_DIR' (poné \$STORE)"; exit 1; }
+echo "==> store:          $STORE_DIR"
+KERNEL="${KERNEL:-$(ls "$STORE_DIR"/*-linux/boot/bzImage "$STORE_DIR"/*-linux-metal/boot/bzImage "$STORE_DIR"/*-linux-generic/boot/bzImage 2>/dev/null | head -1)}"
 MEM="${MEM:-2048}"; KVM="${KVM:-1}"; PORT="${PORT:-2223}"; DEADLINE="${DEADLINE:-150}"
 WORK="$ROOT/work/product-boot"; RFS="$WORK/rootfs"; LOG="$WORK/console.log"
 
 # localizar el product-rootfs sellado (por prefijo, o el más reciente)
 if [ -n "${PRODUCT:-}" ]; then
-  PDIR=$(ls -d store/"${PRODUCT#b3:}"*-product-rootfs 2>/dev/null | head -1)
+  PDIR=$(ls -d "$STORE_DIR"/"${PRODUCT#b3:}"*-product-rootfs 2>/dev/null | head -1)
 else
-  PDIR=$(ls -dt store/*-product-rootfs 2>/dev/null | head -1)
+  PDIR=$(ls -dt "$STORE_DIR"/*-product-rootfs 2>/dev/null | head -1)
 fi
 [ -n "$PDIR" ] && [ -d "$PDIR" ] || { echo "no encuentro product-rootfs (corré 'hammer bootstrap product')"; exit 1; }
 [ -n "$KERNEL" ] && [ -e "$KERNEL" ] || { echo "no encuentro kernel"; exit 1; }
@@ -35,7 +49,25 @@ chmod -R u+w "$RFS"
 rm -rf "$RFS/.hammer"
 
 # provisión de admin: una authorized_keys de prueba (única cosa que el producto NO trae horneada)
-"$(ls store/*-openssh/usr/bin/ssh-keygen | head -1)" -t ed25519 -N '' -f "$WORK/clientkey" -q
+# ⚠ **`TESTKEY` existe porque `ssh-keygen` NO SIEMPRE PUEDE generar la clave** (2026-10-22).
+# Medido en la jaula de desarrollo: corre como uid 1001 y su `/etc/passwd` no tiene ese uid, así que
+# ssh-keygen muere con «No user exists for uid 1001» — llama a `getpwuid` para el comentario y no
+# hay forma de sortearlo (probados `-C`, `LOGNAME`, `USER`, `HOME`: los cuatro fallan igual).
+# Con `TESTKEY=<ruta>` se usa una clave ya existente (su `.pub` al lado) y el test corre igual.
+if [ -n "${TESTKEY:-}" ]; then
+  [ -f "$TESTKEY" ] && [ -f "$TESTKEY.pub" ] || { echo "TESTKEY='$TESTKEY': falta la clave o su .pub"; exit 1; }
+  cp "$TESTKEY" "$WORK/clientkey"; cp "$TESTKEY.pub" "$WORK/clientkey.pub"
+  chmod 600 "$WORK/clientkey"
+  echo "==> clave:          provista por TESTKEY"
+else
+  KEYGEN="$(ls "$STORE_DIR"/*-openssh/usr/bin/ssh-keygen | head -1)"
+  "$KEYGEN" -t ed25519 -N '' -f "$WORK/clientkey" -q || {
+    echo "!! ssh-keygen no pudo generar la clave de prueba."
+    echo "   Si dice «No user exists for uid N», tu entorno no tiene ese uid en /etc/passwd."
+    echo "   Salida: pasá una clave ya hecha ⇒ TESTKEY=~/.ssh/id_ed25519 $0"
+    exit 1
+  }
+fi
 install -d -m 0700 "$RFS/root/.ssh"
 cat "$WORK/clientkey.pub" > "$RFS/root/.ssh/authorized_keys"
 chmod 0600 "$RFS/root/.ssh/authorized_keys"
diff --git a/scripts/verificar-arranque.sh b/scripts/verificar-arranque.sh
new file mode 100755
index 00000000..12aa989b
--- /dev/null
+++ b/scripts/verificar-arranque.sh
@@ -0,0 +1,139 @@
+#!/usr/bin/env bash
+# =============================================================================
+#  verificar-arranque.sh — «¿ARRANCA la imagen?», en un comando.
+#
+#  Uso:  ./scripts/verificar-arranque.sh
+#        STORE=/ruta/al/store ./scripts/verificar-arranque.sh
+#        TESTKEY=~/.ssh/id_ed25519 ./scripts/verificar-arranque.sh
+#
+#  ── POR QUÉ EXISTE (2026-10-22) ─────────────────────────────────────────────
+#
+#  El 2026-10-22 salió busybox de la raíz de confianza del arranque: el núcleo
+#  pasó de `musl+busybox+util-linux+hammerd+arje-zero` a llevar **`simi`** en
+#  lugar de busybox, `/bin/sh` pasó a ser un enlace a `/usr/bin/simi`, y
+#  `ATTEST_PATHS` cambió `bin/busybox` por `usr/bin/simi`.
+#
+#  Eso está verificado hasta donde se puede sin encender una máquina: 42 tests
+#  del crate pasan, el stage1 se reconstruye, el árbol sellado tiene lo que debe
+#  y busybox ya no está. **Lo que NO está verificado es que ARRANQUE.**
+#
+#  Y no se pudo verificar donde se hizo, por dos razones medidas en la jaula de
+#  desarrollo —ninguna de ellas es un defecto del cambio—:
+#
+#    1. **no hay `qemu-system-x86_64`** (y tampoco `/dev/kvm`: una VM de Hetzner
+#       no expone virtualización anidada);
+#    2. **`ssh-keygen` no puede generar la clave de prueba**: la jaula corre como
+#       uid 1001 y su `/etc/passwd` no tiene ese uid, así que muere con
+#       «No user exists for uid 1001». Probados `-C`, `LOGNAME`, `USER` y `HOME`:
+#       los cuatro fallan igual. Mitigado con `TESTKEY`.
+#
+#  ⇒ Este guion existe para que **cualquiera con una máquina normal** —un
+#  portátil con qemu— pueda cerrar esa verificación sin reconstruir el contexto
+#  de la sesión en que se hizo el cambio. Dice qué le falta y cómo conseguirlo.
+#
+#  ── QUÉ VERIFICA, EXACTAMENTE ───────────────────────────────────────────────
+#
+#  Que el `product-rootfs` sellado bootea bajo QEMU con `arje-zero` de PID 1 y
+#  sirve SSH. Es el axioma de la consolidación: el MISMO árbol que produce el
+#  pipeline arranca el daemon sin tocar el núcleo verificado.
+#
+#  Si eso pasa con `simi` como `/bin/sh`, el cambio está cerrado: significa que
+#  el init arrancó, que la seed card se leyó, que el `exec` de la card de sshd
+#  —que es un `sh -c`— lo ejecutó simi, y que la red subió.
+# =============================================================================
+set -uo pipefail
+ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT"
+
+# El artefacto que hay que verificar, FIJADO. Sin esto el test coge «el más
+# reciente del store», que en una máquina ajena puede ser cualquier cosa.
+ESPERADO="9d4d28c7fd3f310c15fc6ab4cc52c3da86ccc58b064c5b2dff4612c9ad041dd6"
+STAGE1="f9b550e016881d8541da84a67379ed121c964bd6e6e86f800464df28996de1a0"
+
+echo "══ verificación de arranque · product-rootfs b3:${ESPERADO:0:12}… ══"
+echo
+
+# ── el store ────────────────────────────────────────────────────────────────
+STORE_DIR="${HAMMER_STORE:-${TAKANA_STORE:-${STORE:-}}}"
+if [ -z "$STORE_DIR" ]; then
+  if [ -d /store ] && [ -n "$(ls -d /store/*-* 2>/dev/null | head -1)" ]; then STORE_DIR=/store
+  else STORE_DIR="$ROOT/store"; fi
+fi
+falta=0
+
+if [ ! -d "$STORE_DIR" ] || [ -z "$(ls -d "$STORE_DIR"/*-* 2>/dev/null | head -1)" ]; then
+  echo "✗ no hay store en '$STORE_DIR'"
+  echo "    poné \$STORE, o traelo:  rsync -aHz --info=progress2 \\"
+  echo "      root@<hub-o-worker>:/store/${ESPERADO}-product-rootfs \\"
+  echo "      root@<hub-o-worker>:/store/*-linux-metal \$STORE/"
+  falta=1
+else
+  echo "✓ store: $STORE_DIR"
+fi
+
+# ── el artefacto exacto ─────────────────────────────────────────────────────
+PDIR="$STORE_DIR/${ESPERADO}-product-rootfs"
+if [ -d "$PDIR" ]; then
+  echo "✓ product-rootfs sellado y presente"
+else
+  echo "✗ falta el product-rootfs b3:${ESPERADO:0:12}…"
+  echo "    o se trae con rsync (ver arriba), o se reconstruye:"
+  echo "      takana --store \$STORE bootstrap stage1  --seed-hash <el de seed-zig>"
+  echo "      takana --store \$STORE bootstrap product --rootfs  $STAGE1"
+  falta=1
+fi
+
+# ── el kernel ───────────────────────────────────────────────────────────────
+KERNEL="${KERNEL:-$(ls "$STORE_DIR"/*-linux/boot/bzImage "$STORE_DIR"/*-linux-metal/boot/bzImage "$STORE_DIR"/*-linux-generic/boot/bzImage 2>/dev/null | head -1)}"
+if [ -n "$KERNEL" ] && [ -e "$KERNEL" ]; then
+  echo "✓ kernel: ${KERNEL#$STORE_DIR/}"
+else
+  echo "✗ no hay bzImage en el store (hace falta un artefacto linux*/boot/bzImage)"
+  falta=1
+fi
+
+# ── qemu ────────────────────────────────────────────────────────────────────
+if command -v qemu-system-x86_64 >/dev/null 2>&1; then
+  echo "✓ qemu-system-x86_64"
+else
+  echo "✗ falta qemu-system-x86_64 — instalalo con el gestor de tu distro"
+  falta=1
+fi
+
+# ── la clave de prueba ──────────────────────────────────────────────────────
+# El test necesita UNA authorized_keys para entrar por ssh y comprobar que el
+# daemon contesta. Es lo único que el producto NO trae horneado, a propósito.
+if [ -n "${TESTKEY:-}" ]; then
+  if [ -f "$TESTKEY" ] && [ -f "$TESTKEY.pub" ]; then
+    echo "✓ clave: TESTKEY=$TESTKEY"
+  else
+    echo "✗ TESTKEY='$TESTKEY': falta la clave o su .pub"; falta=1
+  fi
+elif command -v ssh-keygen >/dev/null 2>&1 && ssh-keygen -t ed25519 -N '' -f /tmp/.vatest-$$ -q 2>/dev/null; then
+  rm -f /tmp/.vatest-$$ /tmp/.vatest-$$.pub
+  echo "✓ ssh-keygen puede generar la clave de prueba"
+else
+  rm -f /tmp/.vatest-$$ /tmp/.vatest-$$.pub 2>/dev/null
+  echo "✗ ssh-keygen no puede generar la clave acá (¿uid sin entrada en /etc/passwd?)"
+  echo "    salida:  TESTKEY=~/.ssh/id_ed25519 $0"
+  falta=1
+fi
+
+# ── aceleración ─────────────────────────────────────────────────────────────
+echo
+if [ -w /dev/kvm ]; then
+  echo "▶ KVM disponible: el arranque tarda ~segundos."
+else
+  echo "▶ SIN /dev/kvm: va por emulación TCG. Funciona, pero tarda MINUTOS —"
+  echo "  por eso el DEADLINE sube a 600 s. No es un cuelgue."
+  export DEADLINE="${DEADLINE:-600}"
+fi
+
+if [ "$falta" != 0 ]; then
+  echo
+  echo "══ FALTAN PIEZAS (arriba) — no corro el test ══"
+  exit 2
+fi
+
+echo
+echo "══ arrancando ══"
+PRODUCT="$ESPERADO" KERNEL="$KERNEL" exec bash "$ROOT/scripts/product-boot-test.sh"