atuq §7.terdecies: «no hay identidad» era también «no pude preguntar» — y en pacha-cli eso guardaba los dotfiles EN CLARO

Contesta el segundo pendiente del §7.duodecies: `pacha`/`pacha-secretos` en
`perfil.servidor`. La respuesta a la pregunta de origen es **NO**, y es la
CONTRARIA a la del escritorio.

Premisa medida, no supuesta: la Card de `pacha-secretos` es `scope=system` y
entra al `genesis`, o sea que arje arranca el daemon EN EL ARRANQUE. De ahí se
sigue que un sembrador en la imagen no llega a tiempo por construcción — en el
arranque no hay nadie logueado; `abrir_almacen()` decide una vez en `main()` y
no vuelve a mirar; y `agora-cli unlock` de una sesión ssh siembra en el llavero
de ESA sesión. Declararlo dejaría la función PARECIENDO cerrada, que es peor
que el hueco. Queda escrito al lado de las dos raíces, en `targets.toml`, para
que nadie copie la decisión del escritorio.

Y al ir a medirlo, el control POSITIVO salió rojo — con la seed en `/proc/keys`
el daemon decía que no había identidad — y eso destapó el defecto de verdad:
los CINCO lectores de la seed hacían `.ok().flatten()` (o un `_ =>`), que
convierte «el llavero no se pudo consultar» en «no hay identidad desbloqueada».
La causa del rojo la mide la sonda de syscalls: en el LXC `add_key` funciona y
`keyctl(KEYCTL_SEARCH)` da `ENOSYS` ⇒ se puede sembrar y no cosechar.

El peor de los cinco no era un mensaje feo: `pacha-cli` guardaba los dotfiles
SIN CIFRAR, en silencio, con la identidad del usuario desbloqueada.

Arreglado en tawasuyu (`4f2b5eac7`) con `pacha_llavero::SeedDeSesion` —tres
estados, tres textos— y `Reason` en `net.tawasuyu.Secretos1`. Pin de las dos
recetas `23a292863` → `cd9acd0d9` ⇒ `b3:e8038352` (4,6 M) y `b3:a9fb8c17`
(8,5 M), mirados por dentro y probados como artefacto: el daemon sellado ahora
dice «motivo=el llavero de sesión NO se pudo consultar (… os error 38) — esto
no es «no hay identidad»».

Tres cosas más que quedaron medidas por el camino:
- la guarda pegada al build **se disparó sola por primera vez**: el latido
  revirtió `pacha.toml` entre las dos construcciones de la misma tanda;
- el muro del `Cargo.lock`, quinta vez, y la arista que faltaba era la mía de
  esa mañana: se la llevó un «merge de git en «main» (import)». Bisecado con
  `git log -S`;
- el índice Y el árbol compartidos de tawasuyu tenían una versión de
  `pacha-boveda-llimphi` ANTERIOR al arreglo de `7917fbb96`. Lo delató el test
  de regresión, no el diff.
This commit is contained in:
Sergio
2026-09-21 21:41:43 +00:00
parent c020c2af19
commit 5fd8746445
2 changed files with 219 additions and 1 deletions
File diff suppressed because one or more lines are too long
+28
View File
@@ -1639,6 +1639,34 @@ paquetes = [
# ARRANCAN solos es otra pregunta y está más abajo, en `servicios`.
"matilda", "tupu", "sandokan-watch", "pacha", "pacha-secretos",
"willay-daemon", "willay-crosscheck", "tejido", "thasnuna",
# ── ⚠ NO, `agora-cli` NO VA ACÁ — y la tentación es fuerte (SDD 26 §7.terdecies, 2026-09-21) ──
# Los cuatro perfiles de ESCRITORIO declaran `agora-cli` desde el §7.duodecies, porque es el único
# binario del corpus que siembra `pacha_llavero::SEED_IDENTIDAD`. Y `pacha` y `pacha-secretos`, que
# están acá arriba, leen esa misma seed: sin ella el Secret Service corre en modo memoria —los
# secretos NO sobreviven al reinicio— y `pacha dotfiles` no cifra. Parece el mismo hueco y parece
# que se cierra igual. **No se cierra**, y copiar la decisión del escritorio dejaría la función
# PARECIENDO arreglada, que es peor que el hueco.
#
# Lo medido, que es la premisa y no la conclusión:
# scripts/targets.py --service-paths servidor ⇒ incluye recipes/pacha-secretos.toml
# takana service-cards recipes/pacha-secretos.toml ⇒ Card scope=system, "lifecycle":"daemon"
# o sea que la Card entra al `genesis` y **arje arranca el daemon EN EL ARRANQUE**, con
# `setuidgid pacha`. De ahí se sigue, sin medir ningún llavero:
# 1. en el arranque no hay nadie logueado ⇒ no hay seed que sembrar todavía: un sembrador en la
# imagen no llega a tiempo, por construcción;
# 2. `abrir_almacen()` corre UNA sola vez en `main()` y el resultado queda en `Estado`: aunque el
# operador desbloquee después, el daemon ya decidió y no vuelve a mirar;
# 3. y `agora-cli unlock` en una sesión ssh siembra en el llavero de ESA sesión, no en el del
# daemon (`KEY_SPEC_SESSION_KEYRING` es de sesión por diseño).
# En el escritorio el sembrador sirve porque la persona está delante; acá no hay persona en el
# momento que importa. **Misma raíz, dos respuestas.**
#
# Lo que sí lo cerraría, nombrado y NO decidido —`pacha-llavero` ya lo tiene previsto: «kernel hoy;
# mañana PAM/TPM/passphrase+Argon2/greeter»—: un backend de llavero que un daemon pueda usar al
# arrancar (fichero con permisos recortados, TPM sellado), o que el daemon vuelva a mirar en vez de
# decidir una vez. Hasta entonces el almacén es efímero —lo que su propia receta ya decía— y desde
# el pin `cd9acd0d9` al menos lo DICE con el motivo correcto y lo publica por D-Bus (`Reason`, al
# lado de `Persistent`).
# `curl`/`wget`: bajar del mirror y del repo. `takana install --repo https://…` los necesita del
# lado del cliente, y son también la única forma de diagnosticar un origen caído desde la caja.
"curl", "wget",