# ADR 0021 — El dueño del verbo de instalar: takana pone el motor, churay pone la cara - **Estado:** PROPUESTO, con **las dos partes IMPLEMENTADAS y medidas** (2026-09-23): el verbo `takana metal` acá, y la cara en tawasuyu (`churay-core::metal`, la pestaña «Sistema en disco» y `churay-cli metal`). - **Fecha:** 2026-09-23 - **Contesta:** [SDD 28 §8](../28-servidor-de-produccion.md) («`churay` como instalador centralizado — la dirección, no la decisión»), que dejó tres preguntas anotadas para que se **decidieran** en un ADR propio y no se descubrieran a mitad. - **Frontera:** `crates/takana-cli/src/metal.rs`, `scripts/takana-install-partition.sh`, `scripts/instalador-initramfs.sh`, y —del otro lado— `02_ruway/churay` en tawasuyu. - **Relacionado:** [ADR 0017](0017-ciclo-de-vida-del-kernel.md) (kexec), [ADR 0018](0018-soberania-del-arranque.md) (NVRAM), [ADR 0015](0015-imagenes-ajenas.md) (glibc), [SDD 27](../27-perfiles-instalables-y-el-instalador.md) (perfiles instalables). ## Contexto El instalador en metal quedó funcionando el 2026-09-23: censo del terreno, elección por PARTUUID, formateo de una sola partición, ESP poblada sin montarla, entrada NVRAM con respaldo previo, y el camino «sin USB» por `kexec`. Y aun así **no se podía usar**. La forma de invocarlo era ésta: ```sh sudo ./takana kernel kexec ./kernel --initrd ./takana-instalador.cpio.gz \ --cmdline 'console=ttyS0,115200 console=tty0' --jump ``` El usuario lo dijo en una línea: > *pero esos son comandos a lo poweruser.* Tiene razón, y el diagnóstico es preciso: eso no es un instalador, es **el motor con la tapa abierta**. Quien lo teclea tiene que saber que existe `kexec`, que el payload va por `--initrd`, que sin `--jump` sólo se carga y qué consola pedirle al kernel nuevo. **Ninguna de esas cuatro cosas es una decisión del que instala** — son detalles de implementación que se filtraron a la superficie. Y la segunda mitad de su observación es la que importa para este ADR: > *churay era, la herramienta de instalar? ya tiene varias cosas adelantadas.* Sí. `churay` (quechua: *poner*) existe desde el 2026-06-24 en tawasuyu y está lejos de ser un esqueleto: instalador **por grafo** con GUI (`churay-llimphi`) y CLI (`churay-cli`), modo sistema y modo local, bundles precompilados firmados con ed25519, repo remoto multi-origen con clave anclada y anillo rotable, actualizador con `rollback`, vigía de espejos en cron, y una puerta de entrada desde la web (`tawasuyu.net/instalar.sh`). Lo que **no** hace es instalar takana en metal. Entonces la pregunta no es «¿hay que escribir un instalador?» sino **quién es dueño de qué**. ## Decisión > **takana es dueño del MOTOR y expone un verbo estable. churay es dueño de la CARA y lo llama. > Ninguna cara vuelve a leer discos por su cuenta.** ### 1. El verbo vive en takana, y es `takana metal` ``` takana metal check ¿puede esta máquina instalarse sin USB? (no toca nada) takana metal survey ¿qué hay en los discos y qué se puede usar? (no toca nada) takana metal install el viaje entero: comprueba, avisa y salta ``` Tres verbos y el orden en que se usan es el orden en que se leen. `install` encuentra el paquete solo —junto al binario, no en el directorio actual, porque el paquete se copia a un pen drive y se corre desde cualquier lado—, corre el diagnóstico **antes** de prometer nada, dice en voz alta qué va a pasar y pide un «si» escrito. No acepta un *enter* pelado: el enter es lo que se aprieta sin leer, y lo que sigue mata la sesión. **Por qué en takana y no en churay.** El motor necesita root, `kexec_file_load`, dispositivos de bloque, las herramientas selladas del store y el rootfs ya construido. Nada de eso se puede mover a un instalador de usuario sin arrastrarlo entero. churay ya llegó a esa misma conclusión por su lado y lo dejó escrito en su LEEME: *«hammer-build/overlay (bwrap, zig, overlayfs, root) no encajan en un instalador de usuario, así que no se usan»*. ### 2. El censo es UNO, y las caras lo consumen `takana metal survey` **no reimplementa nada**: ejecuta el mismo `takana-install-partition.sh --survey` que corre dentro del instalador. Con `--json` emite el contrato: ```json { "version": 1, "raiz_viva": "8:2", "particiones": [ {"dev": "/dev/sda2", "partuuid": "6F0B…", "mib": 6144, "fs": "ext4", "etiqueta": "hammer-root", "montaje": "/", "veredicto": "RAIZ_VIVA", "usable": true, "explicacion": "la raíz del sistema que está corriendo AHORA"} ] } ``` `veredicto` ∈ `CANDIDATA · LIBRE · RAIZ_VIVA · SOLO_ESP · EN_USO · NO_TOCAR`. El campo `usable` es la lectura de una sola pregunta —¿se puede instalar acá?— para que una cara **no tenga que reimplementar el `case` de los veredictos y equivocarse en el default**: lo que no reconozca no es usable. **Por qué esto es la parte que no se negocia.** El SDD 28 §8 ya nombra el riesgo —«un motor, tres frentes»— y este repo lo pagó dos veces (los `hydrate-*.sh` contra `targets.toml`; la unidad systemd del worker contra el repo). Acá el coste de divergir es peor que quedar desactualizado: **el censo es lo que decide qué NO se toca**. Una cara que clasifique por su cuenta y no conozca, por ejemplo, que una partición marcada LUKS en la tabla no se ofrece aunque `blkid` no vea cabecera adentro, no muestra de menos: **formatea de más**. ### 3. Lo que churay hace, y lo que no | | churay | takana | |---|---|---| | pintar el terreno y preguntar | **sí** (consume `survey --json`) | modo texto, de respaldo | | decidir si una partición se puede tocar | **no** | sí, y es el único | | formatear, poblar la ESP, NVRAM | **no** | sí, dentro del instalador | | llegar a una máquina ajena (web, bundle, firma) | **sí, ya lo tiene** | no, y no lo va a tener | Lo último es el aporte real de churay y la razón por la que esto no es una capa de más: **el camino de la web al escritorio ya existe del lado de churay** —`instalar.sh`, `blobs/` verificados, manifiesto firmado, clave anclada, multi-origen, anillo rotable— y del lado de takana no existe ninguno. Hoy el paquete del instalador se copia a mano. ## Las tres preguntas del SDD 28 §8, contestadas **(1) ¿Hidrata binarios o reproduce desde fuente en una máquina ajena?** Para **este** verbo, ninguna de las dos: el instalador **lleva el rootfs ya construido adentro**, en RAM, y lo copia. No hay build en la máquina del usuario y no hace falta red. La pregunta seguía teniendo sentido para *paquetes sueltos en cualquier distro*, que es otro verbo (`takana install`, SDD 27 §4) y **queda abierta ahí**. Confundirlas fue lo que hacía parecer que había una sola decisión. **(2) ¿Quién es dueño del verbo?** Contestado arriba: takana el motor, churay la cara. El verbo canónico es inglés (regla 4 de `CLAUDE.md`); lo que se lee, castellano. **(3) ¿Qué pasa con un host glibc?** **No es un problema, y hay que decir por qué para que nadie lo trate como si lo fuera.** Lo que el ADR 0015 aparta del store son *imágenes ajenas* —rootfs que no reproducen desde fuente—. Acá no entra nada al store: lo que corre en el host ajeno es **un ELF estático** (medido: `statically linked`, sin intérprete), así que el libc del anfitrión no participa. El instalador de verdad corre sobre **su propio kernel** después del salto, donde ya no hay host. ## El salto, ejecutado de verdad (2026-09-23) Hasta este día el camino «sin USB» tenía **todo probado menos el salto**: el instalador en RAM se había arrancado a mano y hacía su trabajo, pero `kexec_file_load` **no se había ejecutado nunca** — ninguna de nuestras máquinas corre un kernel con `CONFIG_KEXEC_FILE`, así que el primer sitio donde el salto iba a pasar era la máquina del usuario. Eso convierte al usuario en el banco de pruebas. `scripts/metal-salto-test.sh` lo cierra: arranca una VM con `linux-metal-kexec` —la variante que sí trae el flag—, le da un disco con vecinos de verdad (una ESP con un `bootmgfw.efi` de Microsoft dentro, un destino vacío y un hueco sin asignar) y corre ahí **los tres verbos de usuario**. Las once comprobaciones en verde, y el veredicto sale del **disco**, no de lo que la pantalla dijo: ``` ✓ el sistema origen arrancó ✓ EL SALTO OCURRIÓ: el origen no volvió del kexec ✓ metal check: dice que SÍ ✓ el instalador arrancó DESPUÉS del salto ✓ metal survey: el censo salió ✓ el instalador terminó bien ✓ metal install: anunció el salto ✓ la tabla de particiones NO cambió ✓ el destino quedó ext4 con LABEL=hammer-root ✓ la ESP tiene \EFI\takana\takanax64.efi ✓ el vecino de la ESP (bootmgfw.efi de Microsoft) quedó byte a byte igual ``` El log serial corta exactamente donde tiene que cortar —`⚡ saltando al instalador — esto no vuelve.`— y la línea siguiente ya es del otro kernel: `TAKANA-INSTALADOR: arrancado en RAM. El sistema viejo YA NO CORRE: su disco está libre.` ⚠ Y el arnés nació con dos comprobaciones que fallaban **sin que el instalador tuviera nada que ver**, que es la forma más cara de tener un test: comparaba el listado de `mdir` del vecino contra sí mismo —y el listado trae el «bytes free» del volumen, que cambia en cuanto se copia cualquier otra cosa— y usaba `cmp`, que **no existe en este anfitrión musl**: `command not found` sale 127, el `if` lo toma como falso y el test acusaba «la tabla cambió» sin haber comparado nada. Un test que no puede correr tiene que decirlo, no fallar con el mensaje de otra cosa. ## Lo medido (2026-09-23) | | | |---|---| | `metal check` como uid 1001 | dice «falta root», **y avisa que el diagnóstico no es concluyente** | | `metal check` como root del anfitrión | dice la causa real: el kernel no trae `CONFIG_KEXEC_FILE` | | `metal survey --json` en el hub | 6 entradas, JSON válido, una sola `usable` | | `metal install` sin paquete | nombra los tres directorios donde buscó | | `--unattended` sin destino | aborta: «nadie va a estar ahí para elegirlo» | | la cmdline sin respuestas | **idéntica al default**: no hay ninguna máquina horneada (test) | Dos defectos aparecieron al poner la cara, y los dos eran del motor: - **`--survey` exigía el kernel y mtools.** En una máquina ajena —sin store y sin kernel del corpus— el censo moría con «no encuentro el kernel EFI-stub» **antes de imprimir una sola línea del terreno**. Mirar no puede costar lo mismo que escribir. - **`--survey` salía con 1 habiendo funcionado.** Un `a && b && c` como último comando del bucle de impresión decide el estado de salida del script entero; con `set -e`, `mostrar_censo` moría ahí si la última fila no tenía PARTUUID (un disco sin tabla, un hueco libre). En este hub la última fila es `/dev/sdc`. Un `if` no propaga; el `&&` sí. Y uno de clasificación, que es el que más se parece a lo que este ADR quiere evitar: el censo ofrecía `/dev/sda1` —**2 MiB**, el hueco de arranque— como «✓ se puede usar», porque el veredicto miraba **qué** hay dentro y nunca **cuánto** cabe. Elegirla formatea algo real y muere a mitad de la copia. El piso es ahora el mismo número con el que se talla un hueco (`mib_necesarios`), así que las dos puertas no pueden divergir. ## Lo que este ADR NO decide - **Windows.** El instalador standalone desde Windows sigue donde lo dejó el runbook: WSL2 no tiene efivarfs y un `.exe` nativo es un port, no una envoltura. churay tiene su propio frente ahí (`PLAN-MULTIPLATAFORMA.md`, F4) y no se mezcla con éste. - **Firmar el kernel del instalador.** Con Secure Boot en modo `integrity` el salto no ocurre, y hoy no firmamos. Es la decisión abierta del ADR 0018. - **Redimensionar.** Encoger un filesystem pide desmontarlo, y la raíz viva no se desmonta. Eso es física, no una carencia: el redimensionado vive **después** del salto, dentro del instalador, y todavía no está escrito. ## La cara de churay — HECHA el 2026-09-23 Está implementada en tawasuyu: `churay-core::metal` (el envoltorio, con 9 tests), la pestaña **«Sistema en disco»** de `churay-llimphi`, y `churay-cli metal` para headless. Once claves en los tres idiomas. El binario `takana` que churay necesita es el estático del paquete del instalador; para el `survey` no hace falta ni store, ni rootfs, ni root. **Tres cosas salieron distintas de lo que este ADR había anotado, y las tres a mejor:** 1. **No es un nodo del grafo, es una pestaña.** Un nodo con `Scope::System` habría entrado en el conjunto que `install_unit` recorre, y el instalador de apps habría intentado instalarlo como a una app. La pestaña —al lado de «Actualizaciones»— no toca ningún flujo existente. 2. **churay NO pasa `--unattended`.** El botón autoriza el **salto**, no el formateo: la máquina salta al instalador en RAM y el instalador vuelve a mostrar el terreno y a preguntar en su propia pantalla, donde ya no hay un sistema montado estorbando. Dos consentimientos para dos cosas distintas, y el segundo se da en el sitio donde el disco ya está libre. 3. **La raíz viva se pinta `⚡` y no `✓`, y desaparece si la máquina no puede saltar.** Sin `kexec` no hay forma de soltarla; ofrecerla igual sería ofrecer algo que no se puede hacer. Un `✓` idéntico al de una partición libre sería la peor forma de ofrecer la partición del sistema que la persona está usando en ese momento. Y una que este ADR daba por resuelta y no lo estaba: **`takana metal survey` sólo encontraba el censo junto al binario**. Llamado desde churay —que encuentra `takana` en el `PATH`, que es como lo va a encontrar siempre— el binario está en `/usr/bin` y el censo no está al lado, así que el censo moría. Ahora se busca también en `/usr/libexec/takana`, `/usr/lib/takana` y `/usr/share/takana`. El defecto sólo se ve desde el otro lado de la frontera, que es para lo que sirve tener dos lados. ### Lo que churay decide, y que no es reclasificar Leer el veredicto para pintarlo distinto **no** es recalcularlo. Las tres decisiones de la cara se equivocan del lado seguro y están en sus tests: | decisión | por qué | |---|---| | un veredicto **desconocido** no se ofrece, aunque venga `usable: true` | si takana publica uno nuevo y ese churay es viejo: perder una opción se nota; ofrecer la equivocada, no | | un JSON que no parsea es un **error**, no un censo vacío | un censo vacío se pinta como «esta máquina no tiene discos», que es la mentira tranquila | | lo que **no** se puede elegir se muestra igual, con su motivo | una lista que sólo trae lo elegible se lee como «acá no hay nada más», y el que no encuentra su partición no sabe si el instalador no la vio o decidió no ofrecerla | ## Respuesta a la propuesta de churay (2026-09-25) Del otro lado se escribió `02_ruway/churay/SDD-COORDINACION-TAKANA.md`: una lista de **datos** que la cara necesita para dibujar el terreno en vez de listarlo, explícitamente sin mover ni una decisión a churay. Se contesta acá porque dos de sus puntos son decisiones y no código. ### Concedido e implementado: el censo pasa a la versión 2 Los cuatro puntos de §2.1–§2.4 del pedido, en `censo()` y `censo_json()`. Por fila: `clase` (`particion` · `hueco` · `disco`), `disco`, `inicio_bytes`, `tamano_bytes`, `tipo_guid`. Y un array `discos` con `modelo`, `removible`, `tamano_bytes`, `sector_bytes`, `tabla`. **Ni un campo de decisión.** `veredicto` y `usable` siguen siendo los únicos que deciden y siguen saliendo de acá; lo agregado es para pintar y explicar, que es exactamente lo que se pidió. Dos cosas salieron distintas de lo propuesto, y conviene saber por qué: 1. **El aparato va en un array propio, no como campos de cada fila.** Se pidió `disco_modelo` / `disco_removible` / `disco_tamano_bytes` por partición. Un dato del disco repetido en cada fila se puede **contradecir entre filas** —y entonces hay que decidir a cuál creerle—, así que cada fila trae `disco` y eso es la clave del array. Es un `HashMap` del lado de la cara y un error menos. 2. **El hueco ya venía con `dev`, y eso era peor que no tenerlo.** El pedido dice que un hueco «no tiene `dev` ni `partuuid`»; en realidad **ya traía `dev` = el disco**, así que dos huecos del mismo disco llegaban con el MISMO `dev` y una cara que los indexe por ahí se queda con uno y pierde el otro **sin que nada falle**. Por eso existe `clase`: la identidad de un hueco es `disco` + `inicio_bytes`, y está dicho en el contrato en vez de quedar implícito. ### Y apareció un defecto que el pedido no buscaba: el sector de 512 estaba horneado `mib_de_sectores()` dividía por 2048 a ciegas. `sfdisk -d` cuenta en sectores **lógicos**, que en un disco 4Kn son 4096 — y `/sys/class/block//size`, que usa la otra rama, cuenta **siempre** en unidades de 512. Las dos conversiones estaban mezcladas en una. Medido con un loop de sector 4096 (`losetup --sector-size 4096`), censo viejo contra censo nuevo sobre el MISMO disco: | | viejo | nuevo | real | |---|---|---|---| | partición de 1 GiB | **128 M** | 1024 M | 1024 M | | el hueco de al lado | **895 M → ✗ NO TOCAR, «hacen falta 2048 M»** | 7166 M → ✓ instalar al lado | 7166 M | O sea que en una máquina con discos 4Kn el censo **escondía el único sitio donde instalar no destruye nada** y decía que era chico. Se equivocaba del lado seguro —ocultaba, no ofrecía— pero el resultado práctico es un instalador que en esa máquina contesta «acá no hay dónde». Es el mismo patrón del `/dev/sda1` de 2 MiB que este ADR ya trae: **el veredicto mira lo que hay y se olvida de cuánto cabe**, y la unidad en la que se mide es parte de «cuánto». Comprobado además que el JSON sale **solo** por stdout (la línea de la herramienta resuelta del store va por stderr) y que parsea; los huecos, el 4Kn y el disco sin tabla, con discos de verdad. ### Lo que NO se concede todavía, y qué falta para poder - **§2.5 `usado_bytes`** — de acuerdo con el orden propuesto: es el más caro (montar en sólo lectura para medir) y el que menos cambia una decisión. Queda anotado con su condición, que es del pedido y es correcta: **si no hay dato, ausente y no cero.** Un 0 % dibujado sobre una partición llena miente justo en el número que hace decidir. - **§3 conservar `/home`** — `takana metal install --conservar PARTUUID=…:/home` es aceptable como forma, y las tres condiciones que el pedido pone (no formatear, comprobar que monta ANTES de tocar la raíz, declararlo en el plan) son de takana y se asumen. Pero **la trampa 1 no es de la cara y no está decidida**: si el usuario que crea takana no tiene el mismo `uid` que el del sistema viejo, los archivos quedan de otro dueño y el escritorio arranca sin poder escribir en su propia carpeta. Las dos salidas —crear el usuario con el uid que se encuentra, o cambiar dueños y decirlo— son decisiones de takana con consecuencias distintas, y hasta que se elija **el botón no se ofrece**. La instantánea de `pacha-dotfiles` que churay propone para la trampa 2 no le pide nada a takana y no hace falta esperarla. - **§7 la raíz del suelo** — hay dos llaves reales y un anillo firmado que hoy **no anclan nada**, y eso es de este repo decidirlo. No están apagadas por diseño: están sin conectar, que se ve igual y no protege lo mismo. Sigue abierto quién es dueño de esa raíz; una llave sin dueño es peor que no tenerla. ### Una corrección menor al pedido Su §1 lista los veredictos como `CANDIDATA · LIBRE · RAIZ_VIVA · SOLO_ESP · EN_USO · NO_TOCAR` y falta **`CRUDA`** (sin identificar, usable con confirmación), que el censo emite desde el principio. No es un problema real —`churay-core::metal` sí lo conoce y lo trata—, pero la tabla del documento quedó corta y es la que alguien va a leer. ## Las dos decisiones que faltaban, tomadas (2026-09-25) ### 1. Conservar el `/home` viejo: manda el uid de los DATOS > **takana crea los usuarios con el uid que encuentra en el `/home` conservado —todos los que > haya— y el login por defecto es el nombre del directorio.** No se hace `chown` de nada. El motivo de elegir esto y no lo contrario: recorrer un `/home` de cientos de miles de ficheros es lento, es destructivo sobre los metadatos, y **pierde el reparto si había más de un dueño**. El uid de los datos es el dato duro; el del sistema nuevo es lo barato de adaptar. Implementado como `takana metal install --keep PARTUUID=…:/home` → `takana.keep=` en la cmdline → `--keep` en `takana-install-partition.sh`. **El verbo es `--keep` y no `--conservar`**: la regla 4 del `CLAUDE.md` manda que la superficie de la CLI sea inglés; lo que se LEE sigue en castellano. Las tres condiciones del pedido se cumplen, y hay una cuarta que apareció al escribirlo: 1. **No se formatea.** La partición conservada no se toca en ningún momento. 2. **Se comprueba que monta ANTES de tocar la raíz** — en sólo lectura, y si ya estaba montada se lee de donde está y **no se desmonta**: un `umount` de un montaje ajeno puede propagarse al original, que es un accidente que este repo ya midió. 3. **Se declara en el plan**, junto a lo que sí se borra, y nombrando a cada usuario que va a crear con su uid — antes de pedir el «si». 4. **Un choque de uid aborta, y aborta ANTES del `mke2fs`.** Si el `/home` viejo trae un uid que en el sistema nuevo ya es de otro (`sshd` es el 74), no hay arreglo automático: la salida es del usuario —renombrar el directorio, o instalar sin `--keep`— y se dice cuál es el choque. Nada se formateó. Sólo se admite `/home`. Conservar `/usr` o `/etc` de otro sistema no es conservar datos: es arrancar un híbrido de dos distros, y se rechaza nombrando el motivo. #### Dos cosas que se descubrieron al implementarlo, y las dos habrían fallado en silencio **El `findfs` de busybox NO entiende `PARTUUID`.** Medido: `busybox 1.36.1` dice `Usage: findfs LABEL=label or UUID=uuid`, y nada más. El initramfs de pivote es el que monta el `/home` conservado, y ahí sólo hay busybox — así que un `findfs PARTUUID=…` **devuelve vacío sin error**, el `if` elige la otra rama y la máquina arranca con `/home` vacío diciendo que todo fue bien. Por eso el montaje va por `UUID` del filesystem (que tampoco cambia, porque esa partición no se formatea nunca) y el PARTUUID se anota igual en `/etc/takana/home.conf` para quien repare a mano. **El árbol del stage son HARDLINKS del rootfs sellado, así que un `>>` escribe DENTRO DEL STORE.** No es teórico: se reprodujo a propósito sobre el artefacto real (`5011955a…-product-rootfs/etc/passwd`, un inode con 2 enlaces tras el `cp -al`), y un simple `echo … >> arbol/etc/passwd` **cambió el fichero del store** — `662e02d6…` → `e22ddba3…`. Un instalador que agregue usuarios al árbol envenena el corpus para todos y nada falla. Por eso `keep_aplicar` **copia y hace `mv` encima** de `passwd`/`group`/`shadow` antes de escribir: eso rompe el enlace y deja el inode del store intacto. Comprobado en los dos sentidos —con el `mv`, el store queda byte a byte igual y el árbol pasa a otro inode; sin él, el store cambia. ⚠ Y una lección del propio experimento: **`sed -i` no repara ese daño.** Al quitar la línea del árbol con `sed -i` el store SIGUIÓ envenenado, porque `sed -i` escribe un fichero nuevo y lo renombra — rompe el enlace y deja el contenido malo en el inode del store. Hubo que reescribir el fichero *del store* para restaurarlo (verificado: vuelve a `662e02d6…`). La herramienta que rompe el hardlink es la que no sirve para deshacerlo. Las contraseñas de los usuarios creados quedan **bloqueadas** (`!` en `shadow`), no vacías: un campo vacío es login SIN CLAVE. Y un directorio cuyo nombre no es un login válido, o que es de root, se salta **nombrándolo en voz alta** — sus datos no se tocan, pero el que lo busque tiene que enterarse. La trampa 2 del pedido —los dotfiles de otra versión— no se resuelve acá y se AVISA en el plan. La instantánea de `pacha-dotfiles` que churay propone para desarmarla vive del lado de la suite y no le pide nada a takana. ### 2. La raíz del suelo es de takana — pero **no hay nada que importar** Decidido: la raíz del suelo es de este repo. Y al ir a importar las dos llaves que el pedido daba por existentes, **no existen**. Medido hoy en esta máquina: | lo que el pedido dice | lo que hay | |---|---| | semillas privadas en `~/.takana/seeds/{raiz,release}.seed` (600) | **no existe ni el directorio `~/.takana`** — ni en `/home/sergio` ni en `/root` | | anillo serie 1 en `dist/takana/claves.signed.json` | **no existe** ese fichero en ningún sitio de tawasuyu | | las dos pubkeys | existen **como texto, en dos ficheros markdown** y en el espejo git del repo | O sea que de la ceremonia del 2026-09-24 sobrevivieron **dos cadenas hexadecimales en un documento**. Una pubkey sin su mitad privada se puede anclar, pero nadie puede firmar con ella: sería una raíz que no puede emitir nada, y eso es peor que no tener raíz, porque *parece* que hay una. ⇒ **La decisión se sostiene y el «se importan esas dos» no se puede ejecutar.** Lo que hace falta es una ceremonia AQUÍ, y eso genera material criptográfico real: no se corre de paso. Queda como el siguiente paso explícito de este frente, y las dos pubkeys del documento de churay hay que tratarlas como lo que son —**restos sin dueño y sin uso**— y borrarlas de la lista de cosas que protegen algo. ⚠ Y la lección que vale más que el incidente: **un documento afirmaba la existencia de material criptográfico con rutas y permisos concretos (`600, fuera del repo`), y ninguna de las tres rutas existía.** El detalle no es evidencia. Es el mismo patrón que este repo ya nombró dos veces —la etiqueta no es el hecho, una protección que funciona por accidente se ve igual que una por diseño—: acá una protección que **no existe** se veía igual que una que sí, y con más detalle que la real.