gioser

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 188Rust 55Shell 30Markdown 281211 Sutichaykuna

sitio: el dominio ya tiene SSL, y takana.gioser.net pasa a redirigir acá

El DNS de `takana-os.net` y `www` quedó apuntado, así que Caddy sacó el
certificado de Let's Encrypt (vence el 2026-12-20) y el sitio responde 200. Un
detalle que costó dos minutos y no estaba escrito: **el vhost se había puesto
ANTES del DNS**, y Caddy no reintenta al instante — se queda en su backoff y el
nombre sigue mudo aunque el registro ya esté. `arjectl restart caddy` fuerza el
reintento; anotado en el README del sitio.

Dos nombres más, y los dos SÓLO redirigen:

  takana.gioser.net  → 301 a takana-os.net   (la página vieja, la de hermanas.py)
  git.takana-os.net  → 301 a git.gioser.net  (⏳ le falta el registro A)

`git.takana-os.net` no sirve gitea y no es por pereza: gitea tiene UN `ROOT_URL`
con el que arma cada enlace absoluto y cada URL de clon que muestra la UI.
Colgarlo de un segundo nombre daría un sitio que se contradice —entrás por uno y
te ofrece clonar del otro— y moverlo de verdad rompe los clones y el CI que ya
apuntan al viejo. `git clone` sigue el 301 sin chistar.

⚠ `publicar-webs.sh` comparaba `takana.gioser.net` contra el fichero en disco, y
eso ya no aplica: ahora es un 301. Se separó el control en dos —`comprobar` por
sha contra el disco, `redirige` por destino— y `takana-os.net` entra en el
primero. Lo que NO entra es el `pull`: su raíz es el árbol de trabajo que los
agentes editan, y tirar de ahí mueve HEAD bajo los pies de otro (CLAUDE.md §2 ter).

⚠ Y la primera versión de `redirige()` preguntaba por `getent hosts` quién
resuelve: **en esta caja `getent` NO EXISTE** —musl/busybox no lo traen— así que
daba 127 para todo y declaraba «no resuelve todavía» hasta de los nombres que
estaban andando. Un control que nunca mira nada se ve igual que uno en verde; es
la lección del reaper otra vez. Ahora se lo pregunta a curl, por su código 6.
Corrido entero: 4 verdes por contenido, 1 por destino, 1 avisando del A que falta.

La página suma los dos verbos que ya se pueden correr contra el repo remoto sin
construir nada (`repo list` y `repo verify`), que es el commit de al lado.

008692f7b9fd861917f4ef9cf461713e0e8434c2 · ruwaq Sergio · (1 killa ñawpaq) · tayta edc486477 · kay commitpi sach'ata qhaway

Semántico sayk'uy

Mana ima sutichaypas t'ikrakurqanchu: qillqalla, yachachiylla utaq willaylla t'ikrakurqan.

3 qillqakuna · +92 −20

diff --git a/scripts/servidor/publicar-webs.sh b/scripts/servidor/publicar-webs.sh
index 5ddc7ada..e5bca0d5 100755
--- a/scripts/servidor/publicar-webs.sh
+++ b/scripts/servidor/publicar-webs.sh
@@ -11,8 +11,9 @@
 #
 #     tawasuyu.net, www          → /work/sergio/tawasuyu            (monorepo, con rewrites a web/tawasuyu-web)
 #     gioser.net                 → /work/sergio/gioser-web/
-#     takana.gioser.net          → /work/sergio/gioser-web/takana   } las genera scripts/hermanas.py
-#     hifas.gioser.net           → /work/sergio/gioser-web/hifas    }
+#     takana-os.net, www         → /work/sergio/takana/web/takana-os.net   (⚠ el ÁRBOL DE TRABAJO)
+#     takana.gioser.net          → 301 a takana-os.net              (desde el 2026-09-21)
+#     hifas.gioser.net           → /work/sergio/gioser-web/hifas    (la genera scripts/hermanas.py)
 #     gioser.net/{humanoid,muestras,vivo,ende,reencuentro} → /work/www/gioser-web/…  (MEDIOS, no están en git)
 #
 # El `.git` de los clones no se filtra: el vhost tiene `@oculto path /.* */.*` → 404, y se comprueba
@@ -22,7 +23,13 @@
 # Idempotente. Se corre EN LA CAJA.
 set -eu
 
+# ⚠ `takana-os.net` NO ENTRA EN EL `pull` DE ARRIBA, Y ES A PROPÓSITO (2026-09-21). Su raíz no es
+# un clon de publicación: es `/work/sergio/takana`, el árbol que los agentes editan. Un `pull` ahí
+# mueve HEAD bajo los pies de quien esté trabajando (CLAUDE.md §2 ter, donde eso ya costó un commit
+# entero). Para ese sitio, publicar es guardar el fichero — no hay nada que tirar, sólo que
+# comprobar. Por eso figura abajo, en los controles, y no acá.
 MONO=${MONO:-/work/sergio/tawasuyu}
+TAKANA=${TAKANA:-/work/sergio/takana}
 WEB=${WEB:-/work/sergio/gioser-web}
 
 tirar() {  # $1 = clon
@@ -58,10 +65,14 @@ sed "s|^DESTINO = Path(\"/home/sergio/gioser-web\")|DESTINO = Path(\"$WEB\")|" \
     "$WEB/scripts/hermanas.py" > /tmp/hermanas-caja.py
 python3 /tmp/hermanas-caja.py >/dev/null
 rm -f /tmp/hermanas-caja.py
+# `hermanas.py` sigue escribiendo las DOS, pero desde el 2026-09-21 la de takana ya no se sirve:
+# `takana.gioser.net` redirige al dominio propio y la página buena vive en el repo takana. Se deja
+# generar porque el guion es de ese otro repo y partirlo acá es tocarlo de paso; lo que sí cambió
+# es el control, que abajo espera un 301 y no un fichero.
 for p in takana hifas; do
   [ -s "$WEB/$p/index.html" ] || { echo "  ✗ $p quedó sin index.html" >&2; exit 1; }
 done
-echo "  ✓ takana $(wc -c < "$WEB/takana/index.html") B · hifas $(wc -c < "$WEB/hifas/index.html") B"
+echo "  ✓ hifas $(wc -c < "$WEB/hifas/index.html") B · takana $(wc -c < "$WEB/takana/index.html") B (ya no servida)"
 
 echo "==> control: lo que se SIRVE tiene que ser lo que está en disco"
 falla=0
@@ -71,10 +82,32 @@ comprobar() {  # $1 = url  $2 = fichero en disco
   if [ "$viv" = "$dis" ]; then printf "  ✓ %-30s %s\n" "$1" "$viv"
   else printf "  ✗ %-30s vivo=%s disco=%s\n" "$1" "$viv" "$dis"; falla=$((falla+1)); fi
 }
+# Un nombre que REDIRIGE no se comprueba por contenido: se comprueba por destino. Y un nombre que
+# todavía no resuelve no es un fallo del sitio —es un registro DNS que falta—, así que avisa en vez
+# de ponerse rojo: mezclar las dos cosas es cómo un control deja de leerse.
+#
+# ⚠ Quién resuelve se lo pregunto a CURL, por su código de salida 6 («couldn't resolve host»), y no
+# a `getent`: **en esta caja `getent` NO EXISTE** —musl/busybox no lo traen— así que la primera
+# versión de esta función daba `not found` (127) para TODO y declaraba «no resuelve todavía» hasta
+# de los nombres que estaban andando. Un control que nunca mira nada se ve igual que uno en verde.
+redirige() {  # $1 = url  $2 = destino esperado
+  rc=0
+  d=$(curl -s -o /dev/null -w "%{redirect_url}" --max-time 15 "$1") || rc=$?
+  if [ "$rc" -eq 6 ]; then
+    printf "  ~ %-30s el nombre no resuelve todavía (¿falta el registro A?)\n" "$1"; return 0
+  fi
+  if [ "$rc" -ne 0 ]; then
+    printf "  ✗ %-30s curl salió %s (¿certificado, o no escucha?)\n" "$1" "$rc"; falla=$((falla+1)); return 0
+  fi
+  if [ "$d" = "$2" ]; then printf "  ✓ %-30s → %s\n" "$1" "$d"
+  else printf "  ✗ %-30s → %s (esperaba %s)\n" "$1" "${d:-nada}" "$2"; falla=$((falla+1)); fi
+}
 comprobar https://tawasuyu.net/        "$MONO/web/tawasuyu-web/index.html"
-comprobar https://takana.gioser.net/   "$WEB/takana/index.html"
+comprobar https://takana-os.net/       "$TAKANA/web/takana-os.net/index.html"
 comprobar https://hifas.gioser.net/    "$WEB/hifas/index.html"
 comprobar https://gioser.net/          "$WEB/index.html"
+redirige  https://takana.gioser.net/   https://takana-os.net/
+redirige  https://git.takana-os.net/   https://git.gioser.net/
 
 # Los medios no salen de git, pero tienen que seguir en pie.
 for u in https://gioser.net/humanoid/ https://gioser.net/muestras/; do
@@ -82,10 +115,14 @@ for u in https://gioser.net/humanoid/ https://gioser.net/muestras/; do
   [ "$c" = "200" ] && printf "  ✓ %-30s %s\n" "$u" "$c" || { printf "  ✗ %-30s %s\n" "$u" "$c"; falla=$((falla+1)); }
 done
 
-# Y que servir DESDE UN CLON no exponga el repo.
-g=$(curl -s -o /dev/null -w "%{http_code}" --max-time 15 https://tawasuyu.net/.git/config)
-[ "$g" = "404" ] && echo "  ✓ /.git/config → 404 (la regla @oculto cubre el clon)" \
-                 || { echo "  ✗ /.git/config → $g — EL REPO ESTÁ EXPUESTO"; falla=$((falla+1)); }
+# Y que servir DESDE UN ÁRBOL DE GIT no exponga el repo. Son dos ahora, y el de takana además
+# sirve un subdirectorio del árbol vivo, así que el día que alguien suba el root un nivel quedaría
+# el repo entero publicado — y eso no falla de forma visible.
+for u in https://tawasuyu.net/.git/config https://takana-os.net/.git/config; do
+  g=$(curl -s -o /dev/null -w "%{http_code}" --max-time 15 "$u")
+  [ "$g" = "404" ] && printf "  ✓ %-30s 404 (la regla @oculto tapa el árbol)\n" "$u" \
+                   || { printf "  ✗ %-30s %s — EL REPO ESTÁ EXPUESTO\n" "$u" "$g"; falla=$((falla+1)); }
+done
 
 [ "$falla" -eq 0 ] || { echo "==> $falla control(es) en rojo" >&2; exit 1; }
 echo "==> sitios publicados y verificados"
diff --git a/web/takana-os.net/README.md b/web/takana-os.net/README.md
index 073134e6..145ea0fd 100644
--- a/web/takana-os.net/README.md
+++ b/web/takana-os.net/README.md
@@ -23,8 +23,15 @@ medidas: ninguna baja de 4,5:1.
   `repo.gioser.net`. Comprobado: `takana install age --repo https://repo.gioser.net --trust ./trust`
   responde `release: trusted (by release)`.
 
-⚠ `takana repo list --repo <url>` **no habla HTTP** — sólo directorios locales — y ante una URL dice
-«repo vacío» con salida 0 en vez de decir que no sabe. El que sí baja por red es `install --repo`.
+Y **desde el 2026-09-21 se puede mirar el repo sin construir nada**, que antes no se podía:
+`repo list` y `repo verify` aceptan la misma lista de orígenes que `install`. Hasta ese día sólo
+miraban directorios locales y ante una URL respondían «repo vacío» **con salida 0** — 173 paquetes
+leídos como ninguno.
+
+```sh
+takana repo list   --repo https://takana-os.net/repo                  # 173 paquete(s)
+takana repo verify --repo https://takana-os.net/repo --trust ./trust  # release: trusted
+```
 
 ## Cómo se sirve
 
@@ -35,7 +42,7 @@ HEAD bajo los pies de otro agente (CLAUDE.md §2 ter).
 
 Este README **no se sirve**: son notas de operación, y el matcher del vhost las 404ea.
 
-El bloque, por si hay que rehacer la caja (`caddy validate` → `arjectl restart caddy`, **nunca**
+Los bloques, por si hay que rehacer la caja (`caddy validate` → `arjectl restart caddy`, **nunca**
 `caddy reload`: el Caddyfile lleva `admin off`, SDD 28 §6.14):
 
 ```caddyfile
@@ -56,18 +63,44 @@ takana-os.net, www.takana-os.net {
 		file_server
 	}
 }
+
+git.takana-os.net {
+	import acceso
+	redir https://git.gioser.net{uri} permanent
+}
+
+takana.gioser.net {
+	import acceso
+	redir https://takana-os.net{uri} permanent
+}
 ```
 
-## DNS
+`scripts/servidor/publicar-webs.sh` comprueba los cuatro: los dos que sirven ficheros por sha
+contra el disco, y los dos que redirigen por destino.
+
+## Los nombres
+
+| nombre | qué hace | estado |
+|---|---|---|
+| `takana-os.net`, `www` | el sitio | ✅ con certificado de Let's Encrypt (2026-09-21) |
+| `takana-os.net/repo/` | el repo de paquetes, el mismo `/srv/repo` | ✅ |
+| `takana.gioser.net` | **301 → `takana-os.net`** | ✅ |
+| `git.takana-os.net` | **301 → `git.gioser.net`** | ⏳ vhost puesto, **falta el registro A** |
+
+`git.takana-os.net` sólo redirige, y es deliberado: gitea tiene UN `ROOT_URL` con el que arma cada
+enlace y cada URL de clon que muestra, así que colgarlo de un segundo nombre daría un sitio que se
+contradice —entrás por uno y te ofrece clonar del otro— y moverlo de verdad rompe los clones y el
+CI que ya apuntan al viejo.
 
-El dominio se registró el 2026-09-21 y **el vhost está puesto antes que los registros**: hasta que
-`takana-os.net` resuelva a la caja, Caddy no puede pedir el certificado y el nombre no responde.
-Hacen falta dos `A` a `2.29.29.217` (la IP de la caja), igual que la de `repo`:
+Los registros van a `2.29.29.217`, la IP de la caja:
 
 ```
-takana-os.net.       A  2.29.29.217
-www.takana-os.net.   A  2.29.29.217
+takana-os.net.       A  2.29.29.217   ✅ puesto
+www.takana-os.net.   A  2.29.29.217   ✅ puesto
+git.takana-os.net.   A  2.29.29.217   ⏳ falta
 ```
 
-Con eso puesto, el certificado sale solo en la primera petición — y **tarda unos segundos más que
-el primer `curl`**: si da error, reintentar antes de ir a mirar logs (SDD 28 §6.14).
+El certificado sale solo en la primera petición tras el DNS — y **tarda unos segundos más que el
+primer `curl`**: si da error, reintentar antes de ir a mirar logs (SDD 28 §6.14). Si el nombre ya
+resolvía cuando Caddy arrancó pero el certificado no llegó, **reiniciar caddy fuerza el reintento**
+sin esperar el backoff: fue lo que hizo falta acá.
diff --git a/web/takana-os.net/index.html b/web/takana-os.net/index.html
index 0d1a189d..49b46b15 100644
--- a/web/takana-os.net/index.html
+++ b/web/takana-os.net/index.html
@@ -312,7 +312,9 @@ footer.pie{border-top:1px solid var(--linea);background:var(--papel);padding:2.6
   <a class="url" href="/repo/">https://takana-os.net/repo/</a>
  </div>
 
-<pre><span class="p">$</span> takana install age --repo https://takana-os.net/repo --trust ./trust</pre>
+<pre><span class="p">$</span> takana repo list   --repo https://takana-os.net/repo
+<span class="p">$</span> takana repo verify --repo https://takana-os.net/repo --trust ./trust
+<span class="p">$</span> takana install age --repo https://takana-os.net/repo --trust ./trust</pre>
 
  <p class="nota">
   <span data-l="es">Hoy publica la clausura del perfil <code>servidor</code>. El mismo repo se sirve también en <a href="https://repo.gioser.net/">repo.gioser.net</a>; <code>--repo</code> acepta varios orígenes separados por coma y los prueba en orden.</span>