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…

docs: SDD 11 — bootstrap from-scratch (abre el track posterior)

Diseña el corte del cordón umbilical con Alpine en tres etapas, reusando el lab
de Fase 0 sin mecanismo nuevo:

- Stage 0: toolchain semilla (zig primario, musl-cross-make como escotilla)
  ingerido al store como fuente pinned por sha256 — el único insumo del host.
- Stage 1: userland mínimo cross-compilado (musl, busybox/toybox, init propio,
  hammerd) ensamblado en un rootfs sellado. El init propio habilita el CRASHED
  real diferido de Fase 5.
- Stage 2: rebuild nativo dentro del rootfs y diff de hashes stage1 vs stage1'
  ⇒ auto-alojamiento bit-reproducible.

Cada etapa anota (stage, recipe_hash, artifact_hash) en bootstrap.json, embrión
del log de transparencia (SDD 09 §4). Propone el crate hammer-bootstrap y la CLI
`hammer bootstrap stage0|stage1|stage2|--all`. Decisiones abiertas marcadas para
un futuro ADR 0007. Enlazado desde el índice de docs y el roadmap.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

bbab5a204d57d43d9e01f6fb4252dddd04c4d5a1 · by Sergio · (4 months ago) · parent 9f7c1aa04 · browse the tree at this commit

Semantic delta

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

3 files · +155 −3

diff --git a/docs/10-roadmap.md b/docs/10-roadmap.md
index 58cee248..f5e7bfb0 100644
--- a/docs/10-roadmap.md
+++ b/docs/10-roadmap.md
@@ -176,11 +176,19 @@ pre-requisito de validación.
 ---
 
 ## Track posterior — distro propia
-- Reemplazar el init de Alpine por **tu init** (bus por pipes nativo).
-- **Bootstrap from-scratch** con `zig`/`musl-cross-make` (Stage 0/1/2 → imagen destino).
+
+Diseño completo en [SDD 11 — Bootstrap from-scratch](11-bootstrap.md). Resumen:
+
+- **Bootstrap from-scratch** en tres etapas ([SDD 11 §3](11-bootstrap.md)): Stage 0 (toolchain
+  semilla `zig`/`musl-cross-make` sellado por hash), Stage 1 (userland mínimo cross-compilado:
+  musl + busybox/toybox + init + `hammerd`), Stage 2 (rebuild nativo dentro del rootfs y diff
+  de hashes ⇒ auto-alojamiento bit-reproducible). ⏭️ **Primer paso del track.**
+- Reemplazar el init de Alpine por **tu init** (bus por pipes nativo) — habilita el `CRASHED`
+  real que la Fase 5 dejó diferido.
 - Userland propio (busybox/toybox a elección), `/etc/service/*` propios.
 - Decidir particionado/montaje de `/store` y `/var/lib/hammer`.
-- Log de transparencia para compartir en comunidad ([SDD 09](09-trust-model.md) §4).
+- Log de transparencia para compartir en comunidad ([SDD 09](09-trust-model.md) §4): el
+  `bootstrap.json` de [SDD 11 §4](11-bootstrap.md) es su embrión.
 - Mini-lenguaje de consulta del sistema para la IA ([SDD 08](08-ai-integration.md) §6).
 
 ---
diff --git a/docs/11-bootstrap.md b/docs/11-bootstrap.md
new file mode 100644
index 00000000..ad7c2a99
--- /dev/null
+++ b/docs/11-bootstrap.md
@@ -0,0 +1,143 @@
+# SDD 11 — Bootstrap from-scratch (track posterior)
+
+> **Estado:** diseño. Abre el *track posterior* del [SDD 10](10-roadmap.md): bajar de "hammer
+> sobre Alpine" a "hammer sobre sí mismo". No bloquea ninguna Fase 0–6 (ya cerradas); reusa
+> el laboratorio de build ([SDD 02](02-build-lab.md)) sin retrabajo.
+
+## 1. El problema: el cordón umbilical
+
+Hoy el userland que `hammer` muta es el de Alpine (musl + busybox ya cocidos). Eso fue
+deliberado ([ADR 0002](adr/0002-alpine-first.md)): validar la capa AI-nativa antes de gastar
+meses en un bootstrap. Validada esa capa, el track posterior responde una sola pregunta:
+
+> **¿Puede `hammer` compilar el sistema completo que ejecuta, sin pedirle nada al host más
+> que un toolchain semilla fijado por hash?**
+
+Si la respuesta es sí *y* el resultado es bit-reproducible, hammer deja de heredar la
+confianza de Alpine y la deriva de su propio [log de transparencia](09-trust-model.md).
+
+## 2. Principios (heredados, no nuevos)
+
+- **Todo es una receta sellada.** Cada pieza del bootstrap es un `Recipe` ([SDD 02 §1](02-build-lab.md))
+  cuyo artefacto se direcciona por hash en el `Store`. El bootstrap es un *subgrafo* del grafo
+  de dependencias que ya construye el lab, no un mecanismo aparte.
+- **Nada del host entra al hash.** El único insumo externo es el **toolchain semilla**, y entra
+  como un artefacto importado con su sha256 **fijado** ([ADR 0006](adr/0006-pinned-commits.md)),
+  igual que un tarball upstream. El host aporta un kernel para correr procesos y nada más.
+- **`zig cc` es la semilla primaria** ([ADR 0003](adr/0003-zig-cc-builder.md)): un binario
+  hermético = compilador C/C++ + musl + headers, cross al target. Escotilla `musl-cross-make`
+  (gcc+musl) detrás de la misma interfaz de receta (`compiler = "gcc"`) para los paquetes con
+  gcc-ismos.
+
+## 3. Las tres etapas
+
+```
+        host (sólo kernel + seed pinned)
+                 │
+   ┌─────────────▼─────────────┐
+   │ Stage 0 — toolchain semilla│  zig (o musl-cross-make) ingerido al store,
+   │   sellado por hash         │  fijado por sha256. Cross → x86_64-linux-musl.
+   └─────────────┬─────────────┘
+                 │ artifact_hash(seed)  ← dependencia de build de todo lo demás
+   ┌─────────────▼─────────────┐
+   │ Stage 1 — userland mínimo  │  musl, busybox/toybox, init propio, hammerd,
+   │   cross-compilado          │  cross-compilados CON Stage 0. Sale un rootfs sellado.
+   └─────────────┬─────────────┘
+                 │ rootfs_hash(stage1)
+   ┌─────────────▼─────────────┐
+   │ Stage 2 — rebuild nativo   │  DENTRO del rootfs Stage 1 (bwrap/chroot/VM),
+   │   y verificación           │  recompila toolchain+userland con las herramientas
+   └────────────────────────────┘  de Stage 1, NO las del host. Compara hashes.
+```
+
+### Stage 0 — Toolchain semilla
+
+Modelamos el toolchain semilla como una **fuente fijada**, no como un build: un `Source` de
+tipo tarball con `sha256` pinned (`zig-<ver>-linux-x86_64.tar.xz`, o el tarball de
+`musl-cross-make`). `hammer-bootstrap` lo descarga (fuera del sandbox, como `hammer_build::download`
+ya hace para `patch_url`/`content_url`), verifica el sha256 **antes** de sellarlo, y lo deposita
+en el store con un `artifact_hash` derivado de ese sha256. A partir de ahí el resto del
+bootstrap depende del *hash del store*, no de la ruta del host.
+
+Salida: `seed_hash` (artefacto del toolchain en el store).
+
+### Stage 1 — Userland mínimo
+
+Un conjunto de recetas cuyo `[deps].build` incluye `seed_hash`. El conjunto mínimo que arranca
+y se administra solo:
+
+| Pieza | Por qué | Compilador |
+|---|---|---|
+| `musl` | libc del target | zig cc (estático) |
+| `busybox` o `toybox` | coreutils + shell | zig cc (estático) |
+| `init` propio | PID 1 + bus por pipes nativo ([SDD 07](07-agent-bus.md)) | zig cc |
+| `hammerd` | diario + bus de agente + watcher | el toolchain Rust del lab |
+
+Todo se enlaza estático o con rpath controlado (sin depender del loader del host). El resultado
+se ensambla en un **rootfs** (árbol FHS) que a su vez se sella como un artefacto del store
+(`stage1_hash`). El init propio es la pieza que habilita `CRASHED` real (el único ítem diferido
+de la Fase 5): PID 1 supervisa servicios y publica `Crashed` al bus.
+
+> El **kernel** no es el foco de este hito: se importa pinned (como la semilla) para poder
+> correr el rootfs. Construirlo desde fuente es un sub-ítem posterior, ortogonal al
+> auto-alojamiento del userland.
+
+### Stage 2 — Rebuild nativo y verificación
+
+El corte del cordón. Dentro del rootfs Stage 1 (primero vía `bwrap`/`chroot`, luego en la VM
+destino), se reconstruyen Stage 0' y Stage 1' usando **sólo** las herramientas de Stage 1.
+Se compara:
+
+```
+hash(stage1)   vs   hash(stage1')
+```
+
+- **Iguales** ⇒ el sistema se compila a sí mismo bit a bit: reproducible y auto-alojado. Hito
+  cumplido.
+- **Distintos** ⇒ hay no-determinismo (timestamps, paths embebidos, orden de enlace). Se
+  caza y se elimina; es exactamente el trabajo que [SDD 09](09-trust-model.md) §2 exige.
+
+## 4. Manifiesto de bootstrap (embrión del log de transparencia)
+
+Cada etapa anota una línea `(stage, recipe_hash, artifact_hash, seed_hash, ts)` en un
+`bootstrap.json` versionado. Ese manifiesto **es** la semilla del log de transparencia
+([SDD 09 §4](09-trust-model.md)): un tercero reproduce el bootstrap y verifica que sus hashes
+coinciden con los publicados, sin confiar en el binario del autor.
+
+## 5. Interfaz
+
+Nuevo crate `hammer-bootstrap` (orquestador) sobre `hammer-build` + `hammer-core::Store`.
+No introduce mecanismo nuevo de build: encadena recetas y persiste el manifiesto.
+
+```rust
+// hammer-bootstrap
+pub fn stage0(seed: SeedSpec, store: &Store) -> Result<ArtifactHash>;        // toolchain semilla
+pub fn stage1(seed: &ArtifactHash, store: &Store) -> Result<RootfsHash>;     // userland mínimo
+pub fn stage2(stage1: &RootfsHash, store: &Store) -> Result<VerifyReport>;   // rebuild + diff
+pub fn all(seed: SeedSpec, store: &Store) -> Result<BootstrapManifest>;
+```
+
+CLI:
+
+```
+hammer bootstrap stage0 [--seed zig|musl-cross-make]
+hammer bootstrap stage1 [--target x86_64-linux-musl]
+hammer bootstrap stage2 --verify
+hammer bootstrap --all                # las tres + reporte de reproducibilidad
+```
+
+## 6. Decisiones abiertas (a fijar en ADR 0007)
+
+- **Semilla primaria:** `zig` vs `musl-cross-make`. Inclinación: `zig` por hermeticidad
+  (ADR 0003), con `musl-cross-make` como escotilla por receta.
+- **busybox vs toybox** para el userland mínimo (licencia vs cobertura de comandos).
+- **Particionado/montaje** de `/store` y `/var/lib/hammer` en la imagen destino (track posterior
+  del roadmap).
+- **Kernel:** importado pinned ahora; from-source después.
+
+## 7. Hecho cuando
+
+`hammer bootstrap --all` produce un rootfs que, ejecutado en la VM destino, **reconstruye su
+propio toolchain y userland con hashes idénticos a los publicados**, sin que ninguna
+herramienta del host entre al resultado. Ese día Alpine deja de ser una dependencia y pasa a
+ser, a lo sumo, una conveniencia de desarrollo.
diff --git a/docs/README.md b/docs/README.md
index 61771976..2acf4af8 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -18,6 +18,7 @@ discrepancia, o se corrige el código o se actualiza el SDD con un commit que ex
 | 08 | [Integración de la IA](08-ai-integration.md) | El bucle agéntico, seguridad, intención → `.swm` |
 | 09 | [Modelo de confianza](09-trust-model.md) | Reproducibilidad, verificar-no-confiar, log de transparencia |
 | 10 | [Roadmap](10-roadmap.md) | Fases, MVP, primer entregable |
+| 11 | [Bootstrap from-scratch](11-bootstrap.md) | Track posterior: Stage 0/1/2, auto-alojamiento, semilla pinned |
 
 ## Architecture Decision Records (ADR)