tawasuyu

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…

feat(servidor): el latido ya espeja a GitHub — con el token pedido en el momento, no guardado

El latido corre como ROOT (`HOME=/root`) y `gh` está logueado como **sergio**
(`/home/sergio/.config/gh/hosts.yml`), así que root no veía credencial ninguna y el espejo se
quedaba atrás 48 commits de estado al día. El camino SSH se descartó midiéndolo: ninguna de las
claves de `/root/.ssh` abre el repo del espejo.

`credencial-espejo-github.sh` es un ayudante de credencial de git que pide el token con
`su - sergio -c 'gh auth token'` **en el momento de empujar** y no lo escribe en ningún sitio. Las
alternativas se descartaron por lo que dejan en reposo: el token en `.git/config` o en
`~/.git-credentials` es un secreto en claro en una caja con root compartido, y la URL con el token
adentro sale además en cada mensaje de error de git. Si `gh` pierde la sesión, el push falla
ruidosamente en vez de empujar con un token muerto.

Y se arregla un aviso que MENTÍA, que es lo que más cuesta: `espejo-setup.sh` daba `gh auth status`
por única credencial válida, así que en el latido decía «el push a GitHub va a fallar» mientras el
push funcionaba. Ahora mira primero el ayudante —que es lo que git usa de hecho— y sólo cae a `gh`
si no hay. Un guardián que grita en falso se deja de leer, y el día que grite de verdad tampoco.

Comprobado: `git ls-remote https://github.com/…` como root del anfitrión devuelve el sha.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

d28e1a74511c103a909780487c2ae28fadfc792c · ruwaq Sergio · (14 p'unchaw ñawpaq) · tayta 176308cfe · kay commitpi sach'ata qhaway

Semántico sayk'uy

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

2 qillqakuna · +59 −3

diff --git a/scripts/espejo-setup.sh b/scripts/espejo-setup.sh
index d4ffaa96..bd7596c4 100755
--- a/scripts/espejo-setup.sh
+++ b/scripts/espejo-setup.sh
@@ -82,14 +82,26 @@ else
 fi
 
 # --- credencial de GitHub: avisar temprano, no fallar al primer push ---
-if command -v gh >/dev/null 2>&1; then
+# ⚠ `gh auth status` NO es la única forma válida de tener credencial, y darlo por supuesto hacía
+# que este aviso MINTIERA (2026-10-07). El latido corre como ROOT con `HOME=/root`, y `gh` está
+# logueado como **sergio**: `gh auth status` de root dice «NO autenticado» aunque el push funcione
+# perfectamente, porque el clon declara un AYUDANTE DE CREDENCIAL
+# (`credential.https://github.com.helper`) que pide el token en el momento. Un guardián que grita en
+# falso se deja de leer, y entonces el día que grite de verdad tampoco se lee.
+# ⇒ se mira primero el ayudante, que es lo que git va a usar de hecho.
+HELPER="$(git config --get credential.https://github.com.helper 2>/dev/null || true)"
+if [ -n "$HELPER" ]; then
+  ok "credencial por ayudante: $HELPER (no hace falta sesión de gh en ESTE usuario)"
+elif command -v gh >/dev/null 2>&1; then
   if gh auth status >/dev/null 2>&1; then
     ok "gh autenticado (el push a GitHub va por HTTPS con su token)"
   else
-    warn "gh NO autenticado ⇒ el push a GitHub va a fallar. Corré: gh auth login && gh auth setup-git"
+    warn "sin ayudante de credencial y gh NO autenticado ⇒ el push a GitHub va a fallar."
+    warn "  misma sesión:  gh auth login && gh auth setup-git"
+    warn "  otro usuario:  ver scripts/servidor/credencial-espejo-github.sh"
   fi
 else
-  warn "no hay gh instalado ⇒ el push a GitHub va a fallar. Instalalo y corré: gh auth login && gh auth setup-git"
+  warn "no hay gh ni ayudante de credencial ⇒ el push a GitHub va a fallar."
 fi
 
 echo "listo. Verificar:  git push origin main   (debe reportar DOS veces, una por remoto)"
diff --git a/scripts/servidor/credencial-espejo-github.sh b/scripts/servidor/credencial-espejo-github.sh
new file mode 100755
index 00000000..9f988aa6
--- /dev/null
+++ b/scripts/servidor/credencial-espejo-github.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+# credencial-espejo-github.sh — da a git el token de GitHub del espejo, sin guardarlo en ningún sitio.
+#
+# ══ POR QUÉ EXISTE ════════════════════════════════════════════════════════════════════════════
+# El latido (`cosecha-cron.sh`, crontab de ROOT con `HOME=/root`) publica el estado y debe espejarlo
+# a GitHub. El espejo va por HTTPS con el token de `gh` —las claves SSH disponibles no llegan: se
+# comprobó el 2026-10-07 que ninguna de `/root/.ssh` abre el repo del espejo— y `gh` está logueado
+# como **sergio**, en `/home/sergio/.config/gh/hosts.yml`. Root no lo ve.
+#
+# Las alternativas se descartaron por lo que dejan a la intemperie:
+#   - meter el token en `.git/config` o en un `~/.git-credentials` ⇒ secreto EN REPOSO, en claro,
+#     en una caja que ya tiene root compartido.
+#   - poner la URL con el token adentro (`https://x:TOKEN@github.com/…`) ⇒ lo mismo, y además sale
+#     en cada mensaje de error de git.
+#   - loguear `gh` como root ⇒ dos sesiones que caducan por separado, y la de root nadie la mira.
+#
+# Esto lo pide EN EL MOMENTO y no lo escribe: si `gh` pierde la sesión, el push falla ruidosamente
+# en vez de empujar con un token muerto.
+#
+# ⚠ El token NO se imprime en ninguna traza: `gh auth token` escribe sólo a stdout, que git consume.
+# No añadir `set -x` acá ni redirigir esta salida a un log.
+#
+# Uso: no se invoca a mano. Se declara como ayudante de credencial del clon del latido:
+#   git -C /opt/takana config credential.https://github.com.helper /usr/local/bin/credencial-espejo-github
+#
+# git llama al ayudante con la operación en $1 (`get`/`store`/`erase`). Sólo `get` tiene respuesta:
+# no se guarda ni se borra nada, porque no hay nada guardado.
+[ "${1:-}" = "get" ] || exit 0
+
+DUENO="${DUENO_GH:-sergio}"
+USUARIO="${USUARIO_GH:-sergiovelasquezzeballos}"
+
+# `su - <dueño>` y no `sudo`: en esta caja `sudo` reenvía al anfitrión por ssh (ver CLAUDE.md) y acá
+# ya estamos en el anfitrión. El login shell es necesario para que `gh` encuentre su HOME.
+token="$(su - "$DUENO" -c 'gh auth token' 2>/dev/null)"
+if [ -z "$token" ]; then
+  # A stderr, que git muestra: un ayudante que calla deja a git pidiendo usuario y contraseña por
+  # teclado, y en un cron eso es un cuelgue sin mensaje.
+  echo "credencial-espejo-github: $DUENO no tiene sesión de gh (corré: gh auth login)" >&2
+  exit 1
+fi
+
+echo "username=$USUARIO"
+echo "password=$token"