SDD 28 §5: la caja sirve su propio repo firmado — y consumirlo choca con la decisión del SDD 27 §4

Cerrado: clave de release estable, 88/88 del perfil publicados con hash anclado, servidos por la
caja, y el control de firma en los dos sentidos (confianza buena ⇒ instala; confianza vacía ⇒
aborta).

El lazo destapó dos cosas que sólo se ven cerrándolo:

- **`strip_debug` no viajaba en el `.swm`** y ES entrada de hash ⇒ 40 recetas del corpus (18 de las
  88 de este perfil) no se podían instalar. Nadie lo sabía porque nunca se había hecho el viaje
  completo receta → paquete → `install --require-signed`.
- **El loopback nunca se levantaba.** `lo` DOWN, y el síntoma era un timeout de 30 s con caddy
  escuchando: un cuelgue que parece del servidor, no un "connection refused".

Y deja el límite escrito, que es lo que más vale: **la caja sirve, verifica y descarga, pero NO
puede reproducir**. `install` construye desde fuente y eso exige el LAB ENTERO en el cliente — no es
que falte un compilador: el lab entra en el ArtifactHash, así que sin él no se puede ni calcular el
hash a comparar. Es el SDD 27 §4 visto desde el otro lado: para cualquiera que no sea un hub de
build, reproducir no es una opción, y el default tiene que ser hidratar artefactos firmados.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RomoxEGZUhaT4pob1QSX5x
This commit is contained in:
Sergio
2026-09-10 21:44:46 +00:00
co-authored by Claude Opus 5
parent 6eb7960bef
commit f4efd8b3e3
+67 -1
View File
@@ -410,6 +410,71 @@ Lo que falta **no es servir**, son dos cosas:
2. **La receta de `takana`** (§3.4). El host necesita `takana` instalado para consumir los paquetes,
y hoy no puede instalarlo desde el repo porque takana no está en el repo.
### 5.1 Hecho *(2026-09-10)*: clave estable, repo firmado, y la caja sirviéndolo
- **`trust/`** — la clave PÚBLICA de release en el repo; la privada en `~/.config/takana/keys/`
(0600, fuera de git). `scripts/repo-perfil.sh` **aborta si no la encuentra** en vez de inventar una
efímera, y tras firmar **verifica** el índice contra `trust/`.
- **88/88** paquetes del perfil `servidor` publicados con `expected_hash` anclado.
- **La caja los sirve** con `caddy file-server` sobre `/srv/repo`.
**El control de la firma, en los dos sentidos**, contra el repo servido por la caja:
| `--trust` | resultado |
|---|---|
| `./trust` | `release: trusted (by release)` ⇒ instala |
| un directorio vacío | `release: unknown-key … clave no confiada`**ABORTA** |
### 5.2 ⚠ Lo que el lazo destapó: `strip_debug` no viajaba en el paquete
La primera instalación real de `takana` desde su propio repo falló:
```
Error: expected_hash no coincide:
declarado = b3:941d1857… obtenido = b3:2727050e…
```
`why-differs` lo nombró: los dos binarios pesaban **exactamente lo mismo** y sólo divergían en
`.shstrtab` — la firma de un `strip` que corrió una vez y la otra no. `swm_bridge` re-inyecta con
cuidado `flags`, `phases`, `zig_version`, `strip_components`, `patches`, `deps`… y **se olvidaba de
`strip_debug`**, que ni siquiera existía en `SwmBuild`. Como **entra en `hash_inputs`**, el receptor
reconstruía en otra dirección.
**Alcance: 40 recetas del corpus, 18 de las 88 de este perfil.** Una quinta parte del repo no se
podía instalar, y nadie lo sabía porque **nunca se había cerrado el lazo**. Arreglado, con test de
regresión y su control. Tras el arreglo, `install takana` da cache-hit en el hash anclado.
### 5.3 ⚠ Y el loopback nunca se levantaba
Al intentar que la caja instalara de sí misma por `http://127.0.0.1`: **timeout de 30 s**, con caddy
escuchando en `0.0.0.0:80`. `lo` estaba **`DOWN` y sin dirección** — con systemd o OpenRC lo levanta
el init; con arje-zero no lo hacía **nadie**. El síntoma no era «connection refused», que se
diagnostica en un minuto: era un cuelgue que parecía del servidor. Arreglado en `netup` (es quien
configura la red) y verificado desde la imagen, sin tocar la caja a mano.
### 5.4 🚧 Lo que NO se puede todavía, y por qué importa
Con todo lo anterior en verde, la caja **sigue sin poder instalar de su propio repo**:
```
release: trusted (by release) ← la firma verifica
repo: bajados 2 .swm de http://127.0.0.1 ← descarga de sí misma
Error: no pude leer el apk db del lab en /.dev-fs/alpine/lib/apk/db/installed.
El toolchain entra en el ArtifactHash, así que sin rootfs no se puede
calcular un hash comparable
```
O sea: **la mitad de servir está cerrada y probada; la de consumir, no** — y no por un detalle de
instalación, sino porque `install` **reproduce desde fuente** y eso exige el LAB ENTERO en el
cliente. No es «falta un compilador»: el lab entra en el `ArtifactHash`, así que sin él no se puede
ni calcular el hash a comparar.
Es exactamente el punto que [SDD 27 §4](27-perfiles-instalables-y-el-instalador.md) dejó planteado
y sin decidir —*reproducir o hidratar*— visto desde el otro lado: para un servidor, o para
cualquiera que no sea un hub de build, **reproducir no es una opción**. El camino normal tiene que
ser hidratar artefactos firmados, con `--reproduce` como camino auditable. Mientras esa decisión no
se tome, el repo firmado sirve para distribuir **a hubs**, no a usuarios.
**Y una caja que se sirve a sí misma es un solo origen** — justo lo que el ADR 0014 existe para no
tener. El camino normal puede ser el local, pero la lista de orígenes del host debe incluir también
el Storage Box o gioser. Si no, el primer origen roto es el último.
@@ -519,7 +584,8 @@ del store a propósito. Queda anotado para que se **decida**, no para que se des
| **0.** `perfil.servidor` + este documento + el renombre `hammer-*` de los instaladores | ✅ **2026-09-09** |
| **1a.** caja de sacrificio creada — `cx33` (no había `cx53`), hel1, §3.5 | ✅ **2026-09-10** |
| **1b.** imagen del `perfil.servidor` + rescue → `dd` → arranca takana puro (§3) | ✅ **2026-09-10** — puerta 1 pasada, §3.8 |
| **2.** el servidor se sirve sus paquetes y se actualiza a sí mismo (§5) | pendiente — requiere clave estable + receta de `takana` |
| **2a.** clave estable + receta de `takana` + repo firmado servido por la caja (§5.1) | ✅ **2026-09-10** |
| **2b.** que el host se actualice DESDE su propio repo (§5.4) | 🚧 bloqueado por la decisión de [SDD 27 §4](27-perfiles-instalables-y-el-instalador.md): `install` reproduce, y eso exige el lab entero |
| **3.** mudanza con las 8 puertas del §6, y recetas nuevas del §6.2 | pendiente |
| **4.** la utilidad de absorción (§4), estrenándose con esta migración | pendiente |
| **5.** `churay` como instalador centralizado (§8) | ADR propio, sin decidir |