qorpa pull/list: la imagen ajena entra verificada, o no entra
Paso 2 del §Orden de trabajo del ADR 0015. Verbos en inglés (regla 4); el ADR decía traer/crear/correr y queda corregido, con una línea que dice por qué para que no se vuelva a proponer. `hammer qorpa pull <url> --sha256 <sha>` baja, VERIFICA y recién entonces desempaca — nunca al revés: un tar ajeno sin verificar es código ajeno que ya escribió en tu disco. Veredicto de ADR 0014: contenido distinto ⇒ ABORTAR, y no queda nada a medias. La identidad es el sha256 del ARCHIVO, no del árbol, así que la URL es informativa y espejar sale gratis (ADR 0013). `list` marca a gritos las imágenes vacías y sale ≠0 (regla 3). Los pasos 3-7 están declarados en la superficie y fallan diciendo a qué paso del ADR pertenecen. Nada de esto toca el store: es el espacio paralelo /var/lib/hammer/qorpa (D1). PROBADO de punta a punta contra las dos imágenes curadas — Ubuntu base 24.04.3 (2760 ficheros, 78 M) y Arch bootstrap 2026.09.01 (31748, 534 M), las dos con su glibc adentro, que es el montón B entero. Y probarlo de verdad destapó tres cosas que en verde no se ven: 1. `-p` sin `--delay-directory-restore` NO extrae un rootfs real sin ser root: /etc/ca-certificates/extracted/cadir es 0555 y tar lo crea con su modo final ANTES de llenarlo. 2. Mi limpieza mentía: `remove_dir_all().ok()` no puede con un árbol que trae directorios de sólo-lectura, así que el staging de un pull roto SOBREVIVÍA y el siguiente pull extraía encima. El síntoma («Permission denied» en un directorio recién creado) no se parece en nada a la causa. 3. Renombrar un DIRECTORIO exige escritura sobre el directorio mismo, y el root.x86_64 de Arch viene dr-xr-xr-x. Se abre, se mueve y se le devuelve su modo exacto. Y una regla que sonaba razonable y era falsa: «si hay un solo directorio arriba, ése es el rootfs». El bootstrap de Arch trae TRES entradas arriba (root.x86_64, version, pkglist) ⇒ no disparaba y el rootfs quedaba un nivel abajo, con todo verde y sin un error. Ahora se ancla por ESTRUCTURA (tiene etc/ y usr|bin), con --subdir como escape, y si no acierta FALLA en vez de adivinar: un rootfs mal anclado no rompe acá, rompe cuando la instancia no encuentra su loader. Los hermanos descartados quedan escritos en el manifiesto, no tirados en silencio. 5 tests nuevos, incluida la cicatriz de Arch. 35/35 en hammer-cli. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U5cQtQrYNjWJVXVE6aEpQ2
This commit is contained in:
@@ -3,9 +3,11 @@
|
||||
- **Estado:** PROPUESTO — nombre ADOPTADO (`qorpa`, 2026-09-03); implementación EN CURSO por el
|
||||
§Orden de trabajo. Este documento decide la frontera; el código viene después.
|
||||
- **Fecha:** 2026-09-03
|
||||
- **Frontera (a crear):** `hammer qorpa {traer,crear,correr,exportar,listar,podar}`,
|
||||
- **Frontera (a crear):** `hammer qorpa {pull,create,run,export,list,prune}`,
|
||||
`/var/lib/hammer/qorpa/imagenes/<sha256>/`, `/var/lib/hammer/qorpa/instancias/<id>/`,
|
||||
`instancia.toml` (manifiesto), clase de nodo `ajeno` en `build-state.py`.
|
||||
- **Superficie:** verbos en inglés, mensajes en castellano — `CLAUDE.md` regla 4. Este ADR nació
|
||||
proponiendo `traer/crear/correr` y se corrigió el 2026-09-03; el nombre `qorpa` sí es quechua.
|
||||
- **Continúa:** [SDD 04](../04-overlay.md) (overlay), [SDD 16](../16-harkaq-jaula.md) (harkaq),
|
||||
[ADR 0004](0004-no-custom-nix.md) (hammer no usa nix), [SDD 20](../20-catalogo-publicable-y-completa.md)
|
||||
(catálogo publicable).
|
||||
@@ -145,7 +147,7 @@ apps = ["steam.desktop"]
|
||||
```
|
||||
|
||||
Consecuencias que se caen solas:
|
||||
- **`hammer qorpa recrear <id>`** reconstruye la instancia desde el manifiesto. El `upper` es
|
||||
- **`hammer qorpa recreate <id>`** reconstruye la instancia desde el manifiesto. El `upper` es
|
||||
descartable.
|
||||
- **Actualizar la base** (Fedora 43 → 44) no es un rebase riesgoso: se cambia el digest y se recrea.
|
||||
- **El respaldo** es el manifiesto (KB), no el `upper` (GB). `respaldo-storagebox.sh` no toca
|
||||
@@ -244,7 +246,7 @@ Dos preguntas que se confunden y tienen respuestas distintas.
|
||||
|
||||
| qué | ¿pineado? | cómo se actualiza |
|
||||
|---|---|---|
|
||||
| el rootfs base | **sí**, por sha256 | cambiar el digest en `instancia.toml` + `hammer qorpa recrear` |
|
||||
| el rootfs base | **sí**, por sha256 | cambiar el digest en `instancia.toml` + `hammer qorpa recreate` |
|
||||
| lo que instalás adentro (`dnf install steam`, `pacman -Syu`) | **no, y no puede estarlo** | con el gestor de la imagen, cuando quieras |
|
||||
|
||||
Subir la base de versión es barato **precisamente por D3**: como el manifiesto es la verdad y el
|
||||
@@ -255,7 +257,7 @@ El riesgo real del pin —que upstream borre el tarball— **ya está resuelto p
|
||||
[ADR 0013](0013-mirror-de-fuentes.md)**: la URL no entra en la identidad, sólo el sha256, así que
|
||||
espejar una imagen es gratis y una imagen pineada no se puede perder.
|
||||
|
||||
**b) Pinear ≠ lista cerrada.** `hammer qorpa traer <url> --sha256` acepta cualquier rootfs. Lo corto
|
||||
**b) Pinear ≠ lista cerrada.** `hammer qorpa pull <url> --sha256` acepta cualquier rootfs. Lo corto
|
||||
no es lo que *se puede* traer, sino lo que **nosotros probamos, espejamos y publicamos**, porque cada
|
||||
imagen curada es una segunda cadena de suministro que hay que sostener (§NO-resuelve 3). Se curan
|
||||
**tres**, y cada una entra por un trabajo distinto — no por sabor:
|
||||
@@ -353,12 +355,12 @@ Se escriben acá para que no se descubran en producción.
|
||||
|
||||
1. **Provisionar subuid** y probar `dnf install` en una instancia mínima. Es lo primero que falla
|
||||
(§NO-resuelve 2) y define si el resto es fácil o difícil.
|
||||
2. `hammer qorpa traer <url> --sha256` + verificación de digest. Reusa el patrón de `lab-image.sh`.
|
||||
3. Instancia = overlay sobre la imagen + `instancia.toml`; `crear` / `recrear` / `correr`.
|
||||
2. `hammer qorpa pull <url> --sha256` + verificación de digest. Reusa el patrón de `lab-image.sh`.
|
||||
3. Instancia = overlay sobre la imagen + `instancia.toml`; `create` / `recreate` / `run`.
|
||||
4. Concesiones → `PolicySpec` de harkaq. Empezar por **nada** y abrir sólo lo declarado.
|
||||
5. Shims + `.desktop` generados (`exportar`), y clase `ajeno` en `build-state.py`.
|
||||
5. Shims + `.desktop` generados (`export`), y clase `ajeno` en `build-state.py`.
|
||||
6. **Steam de punta a punta**, con verificación explícita del bwrap anidado.
|
||||
7. Poda (`hammer qorpa podar`) y renglón en SDD 20 sobre licencias.
|
||||
7. Poda (`hammer qorpa prune`) y renglón en SDD 20 sobre licencias.
|
||||
8. Proxy filtrante de Wayland — ticket propio, el más valioso de la lista.
|
||||
|
||||
## Nombre — ADOPTADO 2026-09-03
|
||||
|
||||
Reference in New Issue
Block a user