El SDD 30 sacó las Cards de una constante de Rust y las puso en la receta. Los USUARIOS se quedaron
donde estaban las Cards: `/etc/passwd` de la imagen es `takana_bootstrap::PRODUCT_PASSWD`, un literal
con `root` y `sshd`, y añadir un tercero era editar Rust y recompilar takana.
No es simetría por elegancia, es un servicio que no arranca: `gitea` se niega a correr como root, su
Card hace `setuidgid gitea`, y sin la cuenta arranca, muere y reintenta para siempre con un log que
dice `unknown user` — no «a la imagen le falta una cuenta».
[[user]]
name = "gitea"
uid = 916
home = "/var/lib/gitea"
**El uid se declara, no se asigna**, por la misma razón que el ULID de la Card: un «primero libre a
partir de 1000» hace que dos imágenes del mismo perfil salgan con dueños distintos y el rootfs deje
de reproducir SIN QUE NADA FALLE — los ficheros se ven iguales y `ls -l` dice otro número. Fuera de
`hash_inputs`, medido: el hash de gitea no se movió (`b3:391a613e…` antes y después).
`takana users <recetas…> [--merge <rootfs>]` es el gemelo de `service-cards`, y fusiona **por clave,
no por línea entera** — componer dos veces no duplica, y `grep -q` de la línea completa no serviría
porque la misma cuenta con otro GECOS se leería como nueva. Tres decisiones con su control:
· Una cuenta ya presente con OTRA línea es CONFLICTO y no se pisa: sale ≠0. Pisarla es cambiarle el
uid a ficheros que ya son de alguien, y eso se descubre dentro de la VM.
· Se planea todo y sólo entonces se escribe. Fichero a fichero, un conflicto en `passwd` dejaba el
`group` ya escrito: media cuenta es peor que ninguna, porque parece que está. Comprobado con el
caso exacto — `group` sin la cuenta, `passwd` con otro uid — y los DOS ficheros quedan intactos.
· Un `passwd` ausente es un error, no un fichero a crear: crearlo dejaría una imagen SIN `root`.
La validación rechaza lo que rompe tarde: `root`/`sshd`/`nobody` y sus uids, uid fuera de
100..=65533, `home` relativo y un `:` en cualquier campo — que partiría la línea y fallaría lejos.
Y `--user-paths` NO es `--service-paths` con otro nombre: aquél lista los servicios HABILITADOS,
éste los paquetes INSTALADOS que declaran cuentas. `postgres` instalado y sin levantar necesita su
usuario igual, porque los ficheros de la imagen ya son suyos.
`scripts/servidor-image.sh` lo aplica entre hidratar el perfil y sellar la imagen, y aborta si hay
conflicto: un rootfs con el uid equivocado produce ficheros de un dueño que no existe.
Verde: 6 tests del módulo, core 234, cli 88, bootstrap 42, `targets.py --selftest` 7/7.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Tf9T4vGzsMoT7eS8YzMFn
Documentación de diseño de takana
Estos documentos son la fuente de verdad del diseño. El código los implementa; cuando haya discrepancia, o se corrige el código o se actualiza el SDD con un commit que explique por qué.
Software Design Documents (SDD)
| # | Documento | Qué cubre |
|---|---|---|
| 00 | Visión y filosofía | Por qué existe, qué problema resuelve, la actitud de ingeniería |
| 01 | Arquitectura general | El modelo de dos mundos, componentes, flujo de datos |
| 02 | El laboratorio de build | Sandbox, zig cc, recetas, CAS, grafo de dependencias |
| 03 | Hidratación y store | Store content-addressed, hardlinks a FHS, patchelf, rollback |
| 04 | Overlay de experimentación | overlayfs en caliente, try/commit/discard |
| 05 | Diario de mutaciones | fanotify, log append-only, config-sin-ser-declarativa |
| 06 | Formato .swm |
Manifiesto de mutación compartible, esquema, firma |
| 07 | Bus de init y de agente | /run/init.control, /run/agent.sock, protocolo |
| 08 | Integración de la IA | El bucle agéntico, seguridad, intención → .swm |
| 09 | Modelo de confianza | Reproducibilidad, verificar-no-confiar, log de transparencia |
| 10 | Roadmap | Fases, MVP, primer entregable |
| 11 | Bootstrap from-scratch | Track posterior: Stage 0/1/2, auto-alojamiento, semilla pinned |
| 12 | arje como init real del Stage 1 |
Contrato de runtime: seed card, hammerd supervisado, CRASHED real |
| 16 | harkaq: la jaula de takana | Landlock+seccomp sobre el bwrap actual; política = clausura; evidencia negativa de hermeticidad |
| 26 | atuq: el envoltorio Gecko |
Navegador propio como artefacto DERIVADO de firefox (no fork de fuente); la toolchain clang como puerta de PGO/LTO; qué se promete y qué no |
| 30 | Los servicios que trae un paquete | [[service]] en la receta → Card de arje; por qué arje-absorb no cubre una distro construida desde fuente; los tres árboles de servicios y cuál es el canónico |
Runbooks (operativos)
| Runbook | Para qué |
|---|---|
| Validar Stage 1 booteando en QEMU | stage0→stage1→initramfs→QEMU; criterios de éxito y troubleshooting |
Architecture Decision Records (ADR)
Decisiones tomadas, con su contexto y consecuencias. Ver adr/.