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 1411Shell 141Markdown 85Rust 842928 Sutichaykuna

⎇ 3d6d25661cc690e2779a7e873089691493f2c539 docs/03-hydration.md Markdown · 104 siq'ikuna · 4.6 KB Ñawpa willay ch'uya

Scaffold inicial: workspace Rust + SDDs completos 8bf162304 · sergio ·

1# SDD 03 — Hidratación y store
2
3La hidratación es el puente del sótano al piso de arriba: cómo un artefacto del store
4content-addressed termina siendo un `/bin/grep` normal, mutable, en un FHS clásico — sin
5arrastrar la ruta del store grabada a fuego, y sin el infierno de symlinks de Nix.
6
7## 1. El store
8
9```
10/store/<blake3>-<name>/        un artefacto sellado e inmutable
11    bin/grep
12    share/...
13```
14
15- **Inmutable y append-only.** Nada modifica un artefacto sellado. Reconstruir produce un
16  hash nuevo, una entrada nueva.
17- **Direccionado por contenido.** El prefijo es el `artifact_hash` (ver [SDD 02](02-build-lab.md)).
18- **Deduplicado.** Dos recetas que producen el mismo árbol comparten entrada.
19- **GC por alcanzabilidad.** Un artefacto es basura si ningún hardlink del FHS ni ningún pin
20  lo referencia. `hammer gc` libera lo inalcanzable.
21
22## 2. El problema que resolvemos
23
24Un binario compilado en un entorno funcional lleva grabado:
25
26- el **intérprete ELF** (el loader de la libc): p. ej. `/store/<hash>/lib/ld-musl-x86_64.so.1`,
27- el **RPATH** (dónde busca las `.so` dinámicas): rutas dentro del store.
28
29Si copias ese binario tal cual a `/bin`, falla: busca la libc en una ruta del store. Hay que
30**normalizar** las rutas al esquema clásico antes de que toque el FHS real.
31
32## 3. Estrategia primaria: enlazado estático (la vía limpia)
33
34Con musl, el camino de oro es **enlazar todo estáticamente** (`link = "static"`). El resultado
35es un único binario autosuficiente, sin `.so`, sin intérprete externo, sin RPATH que importe.
36
37- **Hidratar = hardlink directo** del binario del store a `/bin`/`/sbin`.
38- **Estructura familiar:** `/bin` real lleno de ejecutables normales; cero symlinks crípticos.
39- **Control total:** ¿reemplazar `ls` por una versión experimental compilada a mano? Copias el
40  binario encima y listo (ver §6, copy-on-write).
41
42Esta es la estrategia por defecto.
43
44## 4. Estrategia secundaria: purga de RPATH con `patchelf` (la vía dinámica)
45
46Cuando un paquete requiere enlazado dinámico (plugins, tooling específico), el lab compila
47contra el store, y la hidratación **reescribe el binario** antes de inyectarlo:
48
491. `patchelf --set-interpreter /lib/ld-musl-x86_64.so.1 <bin>` — loader estándar del sistema.
502. `patchelf --set-rpath /lib:/usr/lib <bin>` — rutas clásicas.
513. Hardlink/copia del binario normalizado y de sus `.so` a `/lib`.
52
53`patchelf` (irónicamente, creado por el equipo de Nix) es la herramienta exacta para esto.
54
55## 5. El core dinámico curado (matiz honesto sobre el ABI de musl)
56
57La idea de "actualizar el sustrato atómicamente y que los binarios no se enteren" **sólo es
58segura si se versiona explícitamente.** musl **no garantiza estabilidad de ABI entre
59versiones**; confiar ciegamente en ello rompería binarios.
60
61Política de `hammer`:
62
63- El grueso del sistema se enlaza **estático** → inmune al problema.
64- Un subconjunto hiper-reducido de librerías core de actualización frecuente por seguridad
65  (p. ej. `openssl`, `zlib`) puede vivir **dinámico** en una ruta controlada `/lib/core/`,
66  **versionada** (`/lib/core/libssl.so.3`).
67- Las actualizaciones de ese core respetan el `soname`/versión. Si una actualización cambia el
68  ABI, **es un artefacto nuevo con soname nuevo**, no un reemplazo silencioso.
69- Para plugins reales, preferir `dlopen` versionado sobre fe en el ABI.
70
71Resultado: el superpoder de "reemplazar el suelo" existe, pero acotado y honesto, sin la
72promesa mágica que rompería en producción.
73
74## 6. Mutabilidad: copy-on-write sobre hardlinks
75
76El FHS está hidratado por **hardlinks** al store (no symlinks → rutas reales; no copias →
77dedup). El store es inmutable; el FHS es mutable. ¿Cómo conviven?
78
79- **Leer/ejecutar:** el hardlink apunta al inode del store. Cero copia.
80- **Escribir/pisar en caliente:** al reemplazar `/bin/grep`, **se rompe el hardlink** (se
81  escribe un inode nuevo). El artefacto del store queda intacto → base de rollback.
82- **Rollback:** re-hidratar desde el store restaura el hardlink original.
83
84Esto da exactamente lo buscado: "un `rm -rf` rompe cosas de verdad", pero siempre hay una base
85limpia reconstruible debajo.
86
87## 7. Interfaz
88
89```rust
90// hammer-core
91pub struct Store { root: PathBuf }
92impl Store {
93    pub fn has(&self, h: &ArtifactHash) -> bool;
94    pub fn seal(&self, out_dir: &Path, h: ArtifactHash) -> Result<PathBuf>;
95    pub fn path_of(&self, h: &ArtifactHash) -> PathBuf;
96    pub fn gc(&self, roots: &[ArtifactHash]) -> Result<GcReport>;
97}
98
99// hammer-build
100pub fn hydrate(h: &ArtifactHash, store: &Store, target_fhs: &Path, mode: LinkMode)
101    -> Result<Vec<HydratedFile>>;
102```
103
104CLI: `hammer hydrate <hash> [--into /]` — proyecta el artefacto al FHS (real o de overlay).

03-hydration.md

SDD 03 — Hidratación y store

La hidratación es el puente del sótano al piso de arriba: cómo un artefacto del store content-addressed termina siendo un /bin/grep normal, mutable, en un FHS clásico — sin arrastrar la ruta del store grabada a fuego, y sin el infierno de symlinks de Nix.

1. El store

/store/<blake3>-<name>/        un artefacto sellado e inmutable
    bin/grep
    share/...

2. El problema que resolvemos

Un binario compilado en un entorno funcional lleva grabado:

Si copias ese binario tal cual a /bin, falla: busca la libc en una ruta del store. Hay que normalizar las rutas al esquema clásico antes de que toque el FHS real.

3. Estrategia primaria: enlazado estático (la vía limpia)

Con musl, el camino de oro es enlazar todo estáticamente (link = "static"). El resultado es un único binario autosuficiente, sin .so, sin intérprete externo, sin RPATH que importe.

Esta es la estrategia por defecto.

4. Estrategia secundaria: purga de RPATH con patchelf (la vía dinámica)

Cuando un paquete requiere enlazado dinámico (plugins, tooling específico), el lab compila contra el store, y la hidratación reescribe el binario antes de inyectarlo:

  1. patchelf --set-interpreter /lib/ld-musl-x86_64.so.1 <bin> — loader estándar del sistema.
  2. patchelf --set-rpath /lib:/usr/lib <bin> — rutas clásicas.
  3. Hardlink/copia del binario normalizado y de sus .so a /lib.

patchelf (irónicamente, creado por el equipo de Nix) es la herramienta exacta para esto.

5. El core dinámico curado (matiz honesto sobre el ABI de musl)

La idea de "actualizar el sustrato atómicamente y que los binarios no se enteren" sólo es segura si se versiona explícitamente. musl no garantiza estabilidad de ABI entre versiones; confiar ciegamente en ello rompería binarios.

Política de hammer:

Resultado: el superpoder de "reemplazar el suelo" existe, pero acotado y honesto, sin la promesa mágica que rompería en producción.

6. Mutabilidad: copy-on-write sobre hardlinks

El FHS está hidratado por hardlinks al store (no symlinks → rutas reales; no copias → dedup). El store es inmutable; el FHS es mutable. ¿Cómo conviven?

Esto da exactamente lo buscado: "un rm -rf rompe cosas de verdad", pero siempre hay una base limpia reconstruible debajo.

7. Interfaz

// hammer-core
pub struct Store { root: PathBuf }
impl Store {
    pub fn has(&self, h: &ArtifactHash) -> bool;
    pub fn seal(&self, out_dir: &Path, h: ArtifactHash) -> Result<PathBuf>;
    pub fn path_of(&self, h: &ArtifactHash) -> PathBuf;
    pub fn gc(&self, roots: &[ArtifactHash]) -> Result<GcReport>;
}

// hammer-build
pub fn hydrate(h: &ArtifactHash, store: &Store, target_fhs: &Path, mode: LinkMode)
    -> Result<Vec<HydratedFile>>;

CLI: hammer hydrate <hash> [--into /] — proyecta el artefacto al FHS (real o de overlay).