qorpa: nombre adoptado y el preflight que mide si una máquina puede alojar
ADR 0015 pasa de "propuesta de nombre" a `qorpa` adoptado: la frontera es
`hammer qorpa {…}` y el espacio de nombres se unifica en
/var/lib/hammer/qorpa/{imagenes,instancias}/ — un solo árbol, para que la poda
de §NO-resuelve 5 tenga un único sitio que barrer. La clase de nodo del grafo
sigue siendo `ajeno`: describe la procedencia, no el subsistema.
Y arranca el §Orden de trabajo 1 (subuid) como GUARDIÁN en vez de a mano:
scripts/qorpa/qorpa-preflight.sh mide las cinco capacidades de entorno que un
huésped necesita y que no están en ningún grafo — userns sin privilegios (+
anidado), mapeo multi-id, overlayfs sin root, los nodos del borde y disco.
Tres niveles (BLOQUEA/LIMITA/NOTA) y salida 0/1/2, porque "arranca pero sin
dnf" es una respuesta legítima, no un error.
Medido en `momento` (exit 2, 2 limitaciones):
- userns ANIDADO funciona ⇒ el "verificar, no asumir" de D6 (pressure-vessel
creando su userns dentro del nuestro) queda verificado a nivel de primitiva.
- subuid es papel mojado acá: el rango está declarado en /etc/subuid y las
herramientas están, pero newuidmap/newgidmap vienen sin setuid y sin
capability ⇒ no pueden escribir el uid_map. Es exactamente la "primera cosa
que va a fallar" del ADR, y resulta ser de PROVISIÓN, no de kernel.
El guardián ya se corrigió a sí mismo una vez: marcaba LIMITA por
CONFIG_OVERLAY_FS=m mientras tres secciones más abajo el overlay montaba de
verdad. Manda la prueba funcional, no la declarada.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U5cQtQrYNjWJVXVE6aEpQ2
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
# ADR 0015 — Imágenes ajenas: el mundo glibc entra enjaulado, y no entra al store
|
||||
# ADR 0015 — qorpa: el mundo glibc entra enjaulado, y no entra al store
|
||||
|
||||
- **Estado:** PROPUESTO — sin implementar. Este documento decide la frontera; el código viene después.
|
||||
- **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 ajenas {traer,crear,correr,exportar,listar,podar}`,
|
||||
`/var/lib/hammer/ajenas/<sha256>/`, `/var/lib/hammer/instancias/<id>/`,
|
||||
- **Frontera (a crear):** `hammer qorpa {traer,crear,correr,exportar,listar,podar}`,
|
||||
`/var/lib/hammer/qorpa/imagenes/<sha256>/`, `/var/lib/hammer/qorpa/instancias/<id>/`,
|
||||
`instancia.toml` (manifiesto), clase de nodo `ajeno` en `build-state.py`.
|
||||
- **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)
|
||||
@@ -88,8 +89,8 @@ todo fue bien»).
|
||||
Espacio de nombres paralelo, direccionado por digest, **fuera de `hash_inputs` de todo**:
|
||||
|
||||
```
|
||||
/var/lib/hammer/ajenas/<sha256>/ imagen — INMUTABLE, verificada por digest
|
||||
/var/lib/hammer/instancias/<id>/
|
||||
/var/lib/hammer/qorpa/imagenes/<sha256>/ imagen — INMUTABLE, verificada por digest
|
||||
/var/lib/hammer/qorpa/instancias/<id>/
|
||||
├── instancia.toml manifiesto — LA VERDAD
|
||||
├── upper/ capa mutable — CACHÉ
|
||||
└── work/ overlayfs
|
||||
@@ -127,7 +128,7 @@ Si el `upper` con 200 paquetes instalados a mano fuese el activo, tendríamos un
|
||||
justo lo que hammer existe para no tener. La relación correcta es la misma que receta↔artefacto:
|
||||
|
||||
```toml
|
||||
# /var/lib/hammer/instancias/juegos/instancia.toml
|
||||
# /var/lib/hammer/qorpa/instancias/juegos/instancia.toml
|
||||
base = "sha256:…" # digest de la imagen, inmutable
|
||||
distro = "fedora-43" # informativo
|
||||
paquetes = ["steam", "mesa-dri-drivers", "mesa-vulkan-drivers"]
|
||||
@@ -144,11 +145,11 @@ apps = ["steam.desktop"]
|
||||
```
|
||||
|
||||
Consecuencias que se caen solas:
|
||||
- **`hammer ajenas recrear <id>`** reconstruye la instancia desde el manifiesto. El `upper` es
|
||||
- **`hammer qorpa recrear <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
|
||||
`/var/lib/hammer/instancias/*/upper` y eso es correcto, no un olvido.
|
||||
`/var/lib/hammer/qorpa/instancias/*/upper` y eso es correcto, no un olvido.
|
||||
- La poda tiene una regla trivial: **un `upper` siempre se puede borrar.**
|
||||
|
||||
### D4 — Granularidad: cuatro tipos, no uno
|
||||
@@ -306,17 +307,21 @@ 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 ajenas traer <url> --sha256` + verificación de digest. Reusa el patrón de `lab-image.sh`.
|
||||
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`.
|
||||
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`.
|
||||
6. **Steam de punta a punta**, con verificación explícita del bwrap anidado.
|
||||
7. Poda (`hammer ajenas podar`) y renglón en SDD 20 sobre licencias.
|
||||
7. Poda (`hammer qorpa podar`) y renglón en SDD 20 sobre licencias.
|
||||
8. Proxy filtrante de Wayland — ticket propio, el más valioso de la lista.
|
||||
|
||||
## Nombre
|
||||
## Nombre — ADOPTADO 2026-09-03
|
||||
|
||||
El subsistema pide un nombre de la familia del repo (harkaq, yupana, arje, wawafs, kikin, churay,
|
||||
mirada, minga, khipu). Propuesta: **`qorpa`** — *huésped alojado*: alguien que entra a la casa, se
|
||||
le dan habitaciones concretas y no las demás. Encaja con lo que hace y con cómo se comporta. Queda a
|
||||
criterio del autor del repo; el resto del ADR no depende del nombre.
|
||||
El subsistema se llama **`qorpa`** — *huésped alojado*: alguien que entra a la casa, se le dan
|
||||
habitaciones concretas y no las demás. Elegido por el autor del repo; entra en la familia (harkaq,
|
||||
yupana, arje, wawafs, kikin, churay, mirada, minga).
|
||||
|
||||
Consecuencias de nombre, ya aplicadas arriba: la frontera es `hammer qorpa {…}`, el espacio de
|
||||
nombres es `/var/lib/hammer/qorpa/{imagenes,instancias}/` —uno solo, para que la poda de
|
||||
§NO-resuelve 5 tenga un único árbol que barrer— y el adjetivo del grafo sigue siendo `ajeno`
|
||||
(clase de nodo), porque describe la **procedencia** del nodo, no el subsistema que lo aloja.
|
||||
|
||||
Reference in New Issue
Block a user