1# ADR 0008 — Bootstrap from-scratch en 3 stages, con `zig` como semilla
2
3- **Estado:** aceptada
4- **Fecha:** 2026-06-10
5
6## Contexto
7
8El track posterior ([SDD 11](../11-bootstrap.md)) baja de "hammer sobre Alpine" a "hammer sobre
9sí mismo": compilar el sistema completo sin heredar el toolchain ni el userland de Alpine. Hay
10que decidir **cómo se rompe el cordón umbilical** sin reintroducir la fragilidad del Stage 0
11clásico (cross-toolchain a mano) que [ADR 0003](0003-zig-cc-builder.md) ya esquivó.
12
13## Decisión
14
15Bootstrap en **tres etapas**, todas modeladas como recetas selladas en el `Store` (sin
16mecanismo de build nuevo):
17
180. **Stage 0 — toolchain semilla:** se **ingiere** un toolchain ya construido (no se compila)
19 como una *fuente fijada por sha256*, y se sella en el store. El `ArtifactHash` se deriva de
20 la **identidad pinned** (clase + versión + sha256), no de rutas del host. **`zig` es la
21 semilla primaria**; `musl-cross-make` (gcc+musl) es escotilla detrás de la misma interfaz.
221. **Stage 1 — userland mínimo:** cross-compilado con Stage 0 (musl, busybox/toybox, el init
23 `arje` [ADR 0007](0007-arje-como-init-propio.md), `hammerd`), ensamblado en un rootfs sellado.
242. **Stage 2 — rebuild nativo:** dentro del rootfs Stage 1, recompilar con las herramientas de
25 Stage 1 y comparar hashes (`stage1` vs `stage1'`). Iguales ⇒ auto-alojado y reproducible.
26
27El único insumo del host es la semilla pinned (más un kernel para correr procesos).
28
29## Razones
30
31- **Reusa el lab entero:** las etapas son subgrafos del grafo de dependencias de
32 [SDD 02](../02-build-lab.md); cero retrabajo.
33- **`zig` semilla** por las mismas razones que ADR 0003: un binario hermético = compilador +
34 musl + headers, cross al target, determinista. Evita compilar gcc desde cero sólo para
35 arrancar.
36- **Ingerir, no compilar, el Stage 0** mantiene el bootstrap finito y reproducible: el sha256
37 fijado ([ADR 0006](0006-pinned-commits.md)) ancla la confianza; quien audita reproduce desde
38 el mismo tarball.
39- **Stage 2 como verificación** convierte la reproducibilidad en una propiedad *comprobable*,
40 no una promesa — alimenta el log de transparencia ([SDD 09](../09-trust-model.md) §4).
41
42## Consecuencias / riesgos
43
44- La semilla **no** se compila desde fuente: confiamos en el tarball pinned de `zig`. Es un
45 punto de confianza explícito y auditable (su sha256 está en el manifiesto), no oculto. Reducir
46 esa confianza (diverse double-compilation, semilla desde fuente) es trabajo futuro.
47- El **kernel** se importa pinned en el primer hito; construirlo desde fuente es ortogonal al
48 auto-alojamiento del userland y queda después.
49- Stage 2 expondrá no-determinismos reales (timestamps, paths embebidos, orden de enlace): es
50 el costo esperado de exigir bit-reproducibilidad, no una sorpresa.
0008-bootstrap-stages.md
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 "hammer sobre Alpine" a "hammer 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):
- 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.
- Stage 1 — userland mínimo: cross-compilado con Stage 0 (musl, busybox/toybox, el init
arje ADR 0007, hammerd), ensamblado en un rootfs sellado.
- 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.