Files
takana/docs/adr/0008-bootstrap-stages.md
Sergio 97ceb72411 takana etapa 5b: los 59 docs de diseño, runbooks y ADR
645 líneas. Los ADR entran porque en este repo SON documentos vivos, no
registros inmutables: el 0013 tiene 5 commits, el 0009 dos. Eso se comprobó
antes de decidir, no se asumió por convención general.

EXCLUIDOS por ser REGISTRO o generado: docs/evidencia/ (6), el HANDOFF de la
noche de KDE (1) y docs/state/ (24, se regenera solo). Reescribir un comando
dentro de una evidencia la falsifica.

Y el ADR 0016 se excluye de todo barrido, con un aviso adentro para el próximo
que barra: habla SOBRE el renombre, así que necesita seguir diciendo 'hammer'.
El barrido se lo llevó puesto y lo dejó titulado 'Renombre del sistema: takana
→ takana'; revertido.

Congelados, verificados uno por uno con controles: /opt/hammer, /var/lib/hammer,
/usr/bin/hammer, /mnt/vvv/hammer, la URL de gitea, hammer-farm.service,
hammer-live-install.sh, BRIEFING-hammer.md, hammerd, hammer-recover y
HAMMER_LIVE.
2026-09-09 19:25:51 +00:00

3.8 KiB

ADR 0008 — Bootstrap from-scratch en 3 stages, con zig como semilla

  • Estado: aceptada
  • Fecha: 2026-06-10

Contexto

El track posterior (SDD 11) baja de "takana sobre Alpine" a "takana sobre sí mismo": compilar el sistema completo sin heredar el toolchain ni el userland de Alpine. Hay que decidir cómo se rompe el cordón umbilical sin reintroducir la fragilidad del Stage 0 clásico (cross-toolchain a mano) que ADR 0003 ya esquivó.

Decisión

Bootstrap en tres etapas, todas modeladas como recetas selladas en el Store (sin mecanismo de build nuevo):

  1. Stage 0 — toolchain semilla: se ingiere un toolchain ya construido (no se compila) como una fuente fijada por sha256, y se sella en el store. El ArtifactHash se deriva de la identidad pinned (clase + versión + sha256), no de rutas del host. zig es la semilla primaria; musl-cross-make (gcc+musl) es escotilla detrás de la misma interfaz.
  2. Stage 1 — userland mínimo: cross-compilado con Stage 0 (musl, busybox, init, hammerd), ensamblado en un rootfs sellado. Decisiones de implementación fijadas al abrir el Lote 4:
    • coreutils+shell = busybox (no toybox): el Stage 1 es una balsa desechable —se sustituye por el userland multi-call nativo en Rust/Zig más adelante—, así que se optimiza la velocidad y la compatibilidad de flags POSIX en el pipeline (mismo comportamiento que el rootfs Alpine de desarrollo). Su GPLv2 queda atrapada en una etapa temprana del manifiesto; no contamina el sistema final mutable.
    • init arje diferido: Stage 1 arranca con musl+busybox+hammerd y un init mínimo provisional. arje (ADR 0007) —y con él el CRASHED real de la Fase 5— se integra como receta git pinned en un lote posterior, sin retrabajo.
    • layout de la semilla: Stage 0 sella el árbol del tarball tal cual (ingesta pura, no aplana); el directorio del toolchain se resuelve al usarlo localizando el ejecutable zig en la raíz o en su único hijo versionado (SeedSpec::toolchain_dir). Stage 0 no adivina layouts y el sandbox recibe un zig_dir correcto sea cual sea la forma del tarball.
  3. Stage 2 — rebuild nativo: dentro del rootfs Stage 1, recompilar con las herramientas de Stage 1 y comparar hashes (stage1 vs stage1'). Iguales ⇒ auto-alojado y reproducible.

El único insumo del host es la semilla pinned (más un kernel para correr procesos).

Razones

  • Reusa el lab entero: las etapas son subgrafos del grafo de dependencias de SDD 02; cero retrabajo.
  • zig semilla por las mismas razones que ADR 0003: un binario hermético = compilador + musl + headers, cross al target, determinista. Evita compilar gcc desde cero sólo para arrancar.
  • Ingerir, no compilar, el Stage 0 mantiene el bootstrap finito y reproducible: el sha256 fijado (ADR 0006) ancla la confianza; quien audita reproduce desde el mismo tarball.
  • Stage 2 como verificación convierte la reproducibilidad en una propiedad comprobable, no una promesa — alimenta el log de transparencia (SDD 09 §4).

Consecuencias / riesgos

  • La semilla no se compila desde fuente: confiamos en el tarball pinned de zig. Es un punto de confianza explícito y auditable (su sha256 está en el manifiesto), no oculto. Reducir esa confianza (diverse double-compilation, semilla desde fuente) es trabajo futuro.
  • El kernel se importa pinned en el primer hito; construirlo desde fuente es ortogonal al auto-alojamiento del userland y queda después.
  • Stage 2 expondrá no-determinismos reales (timestamps, paths embebidos, orden de enlace): es el costo esperado de exigir bit-reproducibilidad, no una sorpresa.