gioser

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 188Rust 55Shell 30Markdown 281211 Definiciones

⎇ 534014c3ec69daea789a1d0523e1d00a69c6ed65 docs/adr/0008-bootstrap-stages.md Markdown · 62 líneas · 3.8 KB Historia crudo

takana etapa 5b: los 59 docs de diseño, runbooks y ADR 97ceb7241 · Sergio ·

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 "takana sobre Alpine" a "takana 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**, init, `hammerd`),
23   ensamblado en un rootfs sellado. Decisiones de implementación fijadas al abrir el Lote 4:
24   - **coreutils+shell = `busybox`** (no toybox): el Stage 1 es una *balsa desechable* —se sustituye
25     por el userland multi-call nativo en Rust/Zig más adelante—, así que se optimiza la velocidad
26     y la compatibilidad de flags POSIX en el pipeline (mismo comportamiento que el rootfs Alpine de
27     desarrollo). Su GPLv2 queda *atrapada* en una etapa temprana del manifiesto; no contamina el
28     sistema final mutable.
29   - **init `arje` diferido:** Stage 1 arranca con musl+busybox+`hammerd` y un init mínimo
30     provisional. `arje` ([ADR 0007](0007-arje-como-init-propio.md)) —y con él el `CRASHED` real
31     de la Fase 5— se integra como receta git pinned en un lote posterior, sin retrabajo.
32   - **layout de la semilla:** Stage 0 sella el árbol del tarball **tal cual** (ingesta pura, no
33     aplana); el directorio del toolchain se resuelve **al usarlo** localizando el ejecutable `zig`
34     en la raíz o en su único hijo versionado (`SeedSpec::toolchain_dir`). Stage 0 no adivina
35     layouts y el sandbox recibe un `zig_dir` correcto sea cual sea la forma del tarball.
362. **Stage 2 — rebuild nativo:** dentro del rootfs Stage 1, recompilar con las herramientas de
37   Stage 1 y comparar hashes (`stage1` vs `stage1'`). Iguales ⇒ auto-alojado y reproducible.
38
39El único insumo del host es la semilla pinned (más un kernel para correr procesos).
40
41## Razones
42
43- **Reusa el lab entero:** las etapas son subgrafos del grafo de dependencias de
44  [SDD 02](../02-build-lab.md); cero retrabajo.
45- **`zig` semilla** por las mismas razones que ADR 0003: un binario hermético = compilador +
46  musl + headers, cross al target, determinista. Evita compilar gcc desde cero sólo para
47  arrancar.
48- **Ingerir, no compilar, el Stage 0** mantiene el bootstrap finito y reproducible: el sha256
49  fijado ([ADR 0006](0006-pinned-commits.md)) ancla la confianza; quien audita reproduce desde
50  el mismo tarball.
51- **Stage 2 como verificación** convierte la reproducibilidad en una propiedad *comprobable*,
52  no una promesa — alimenta el log de transparencia ([SDD 09](../09-trust-model.md) §4).
53
54## Consecuencias / riesgos
55
56- La semilla **no** se compila desde fuente: confiamos en el tarball pinned de `zig`. Es un
57  punto de confianza explícito y auditable (su sha256 está en el manifiesto), no oculto. Reducir
58  esa confianza (diverse double-compilation, semilla desde fuente) es trabajo futuro.
59- El **kernel** se importa pinned en el primer hito; construirlo desde fuente es ortogonal al
60  auto-alojamiento del userland y queda después.
61- Stage 2 expondrá no-determinismos reales (timestamps, paths embebidos, orden de enlace): es
62  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

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

Consecuencias / riesgos