Tres cosas, y las tres quitan vueltas.
1. NO HACE FALTA NINGUNA CREDENCIAL EN EL WORKER, Y TAMPOCO UN USUARIO NUEVO
`tawasuyu/tawasuyu` y `sergio/takana` son repos PÚBLICOS en el gitea. Las 23 recetas que apuntaban a
`gitea@git.tawasuyu.net` (SSH, que exige la clave que es el SSH de todo) pasan a
`https://git.tawasuyu.net/…`. La URL es locator y NO entra en `hash_inputs` (ADR 0013): hecho con
control antes/después, **ningún ArtifactHash se movió**. Medido en el worker: `git clone --mirror
--filter=blob:none` + `git archive` extrae el árbol (155 M) **sin una sola credencial**.
Un usuario propio en gitea sólo haría falta para un repo PRIVADO; hoy ninguna receta usa uno. Si
mañana hace falta, es una cuenta de máquina con acceso al repo que toque — nunca la clave personal.
De paso, tres recetas decían «HUB-ONLY: el worker secretless recibe Connection refused». Ya no es
cierto y el comentario decía lo contrario de lo que pasa: corregido en las tres.
2. LA COPIA FUERA LA DA LA MUDANZA, NO GITHUB (decisión del usuario)
El «paso 1: espejar los 26 repos» deja de ser el paso 1. En cuanto el gitea vive en la caja nueva,
esos repos dejan de existir sólo en la máquina que se borra — que es lo que el paso pedía. El
objetivo es dejar de pagar dos máquinas, no sumar una dependencia. `espejar-repos.sh` queda como
herramienta disponible.
3. EL §9 REESCRITO: qué está hecho, qué falta y en qué orden
Hecho y cerrado: la caja arranca takana puro · store/grafos/granja/respaldo · repo firmado · la
imagen del perfil servidor con gitea sirviendo 200 supervisado por arje · `arjectl` · y el ensayo con
los datos REALES de gioser corriendo sobre takana.
Falta, en orden: actualizar la caja a la imagen nueva (`upgrade`, no `dd`) → mudar los datos del
gitea (`.backup` + rsync, con el origen parado en el corte) → caddy con los 6 dominios vivos → DNS →
verificar desde fuera con un clone real → el resto de servicios del censo → borrar gioser con las 8
puertas en verde.
Bloqueantes con su tamaño: `git` sellado sin `remote-http` (afecta a clonar DESDE una caja takana,
no al gitea que sirve; re-sella una raíz de `base`) y la puerta 5, que no bloquea la mudanza.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Tf9T4vGzsMoT7eS8YzMFn
Barrido de TEXTO puro: 1427 líneas de comentario TOML. Cero ArtifactHash
movidos, y eso está MEDIDO, no deducido: hasheé las 741 antes y después y los
ficheros de hashes son idénticos byte a byte (723 con hash real + 18 que ya no
hasheaban de antes).
El guardián valió la pena: el primer barrido, filtrando por 'la línea empieza
con #', movió el hash de helix, lsof y steam-runtime-sniper. La causa es que una
fase se escribe como compile = <triple> ... <triple> y sus comentarios de SHELL
también empiezan con #, pero viven dentro del VALOR — y las fases sí entran en
hash_inputs. El barrido ahora calcula los rangos de las cadenas multilínea de
TOML y no entra ahí.
Quedan intactos a propósito: .hammer-zig-cc y .hammer-cargo-vendor (literales
dentro de fases), hammerd, hammer-recover y toda ruta que empiece por /
Decisión del usuario: «tawasuyu está en MIT». Es la misma licencia que hammer (LICENSE en
la raíz + Cargo.toml), así que todo lo nuestro queda coherente bajo un solo término. Las 20
recetas con fuente en git.tawasuyu.net: arje-* (el init y sus compat), mirada-* (el
compositor, el greeter y mirada-ctl), netup, agora-cli, cosmos-cli, dominium-cli,
tinkuy-sim, llimphi-counter y libelogind.
⚠ ANOTADO EN LA TABLA porque es una trampa que casi pisé: `libelogind` NO es el elogind de
upstream (que sería LGPL-2.1+). Por el nombre lo parece; su cabecera dice que es una
reimplementación PROPIA de la C-ABI sd-login dentro de arje-compat. Declararla LGPL «porque
se llama así» habría sido exactamente el error que este fichero prohíbe — el tercero del
mismo tipo hoy, después de `knighttime` (parecía Go y es KDE) y de la familia `kube*`
(parecen KDE y son Go). El nombre nunca es evidencia; la fuente sí.
Hashes verificados sobre las 20: idénticos.
Quedan 124 sin declarar, ya todas de terceros.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bump del commit pinneado de c78a0ada → 06184e43 (rama tawasuyu selfhost/arje-zero-attest-
lockfile = c78a0ada + Cargo.lock del workspace force-committeado). Sin lock, tawasuyu lo
gitignora y `cargo vendor` corre SIN --locked ⇒ las deps derivan ⇒ el gated arje-zero (y el
of_tree del producto atestado) no es reproducible. Con el lock, el build es
`cargo rustc --release --locked --offline` ⇒ bit-reproducible. Espeja el patrón del núcleo
(arje-zero.toml @ selfhost/arje-zero-lockfile 9967b02c).
Lock regenerado sobre c78a0ada reusando los pins de main (1 línea de diff ⇒ versiones
MSRV ≤ 1.91.1 del sandbox preservadas). Rebuild --locked validado en host: compila limpio
(418 crates, sin error MSRV), sella arje-zero-attest d1a6f5c7 + arje-packager 2267b9b0;
producto atestado d35a9c09 BOOTEA en QEMU (gate anclado a rootkey soberana, 3 ✓, SSH OK).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cierra la integración canónica firmada de I4 (decisión del usuario): la mitad de
arje (gate) + la mitad de hammer (firma) acopladas con la cripto real de
arje-attest/agora — NO el manifiesto plano de /ente/attest.json.
tawasuyu (pusheado, commit c78a0ada en main): `arje-packager --seed-out` emite el
seed FIRMADO standalone (el gate attest_gate.rs ya estaba en main).
hammer:
- recipes/arje-packager.toml: el firmador (build-time tool, static musl, corre en
el host). GOTCHA: lib+bin + monorepo virtual ⇒ flags `-p ... --bin ...`.
- recipes/arje-zero-attest.toml: arje-zero CON gate, variante SÓLO de producto
(commit c78a0ada). El arje-zero del núcleo (9967b02c) NO se toca ⇒ of_tree
baseline (9adefb82/7fa6cb4e) BLINDADO. Separación Mecanismo/Política.
- scripts/attest-boot-test.sh: valida E2E sobre una copia del product-rootfs
(override del PID1 por el gated + seed firmado por arje-packager + boot QEMU).
Validado in-VM (rootkey fija ⇒ firmas Ed25519 deterministas):
- ÍNTEGRO: gate atesta arje-zero+hammerd+busybox ✓ (politica=Halt) → servicios
arriba → SSH OK.
- TAMPER (1 byte en hammerd tras firmar): "atestación ✗ binario no atestado" →
"ARRANQUE FALLIDO ... Halt — abortando antes de incarnar" → shell de rescate,
SIN SSH. La integridad comprometida NO levanta el entorno.
Pendiente (estructurar bien): cablear esto en hammer-bootstrap product() (firmar
+ hidratar el gated automáticamente) y reproducibilidad (Cargo.lock committeado
en tawasuyu para el gated). El mecanismo ya está probado.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>