atuq: el torrent lo toma un daemon propio, perezoso, que sobrevive al navegador

El 6.9 del SDD 26, con la arquitectura que pidió el operador: daemon PROPIO,
CONFIGURABLE y PEREZOSO. Vivaldi ya trae torrent y termina en una carpeta; acá lo que
baja entra al CAS —un objeto BLAKE3 con la misma identidad que una descarga del
navegador (§6.2) o un `.swm`—, y ésa es la razón por la que esto vale.

    página de la extensión → fondo → connectNative → puriy-costura
      → /usr/bin/puriy-costura-torrent add   (que LEVANTA el daemon si no está)
      → daemon: librqbit, y al completarse, el CAS

POR QUÉ NO ES UN VERBO MÁS DEL HOST — dos razones, y la primera decide:
1. una descarga tiene que sobrevivir al navegador, y Gecko mata al host cuando se
   cierra el puerto (medido hoy);
2. librqbit + tokio + rustls son 226 crates: dentro del host, ese binario —952 K,
   compartido por CINCO extensiones— pasaría a ~20 MB y cada iteración de cualquier
   función del navegador a un cuarto de hora.

⚠ Que esa pila COMPILA para musl con zig-cc se midió ANTES de decidir, con una receta
desechable: 226 crates y sella. Era una incógnita real —ninguna receta del corpus
había construido tokio+rustls desde tawasuyu— así que la decisión no fue «no se
puede», fue «no ahí». El artefacto del daemon pesa 7,7 M.

PEREZOSO EN LOS DOS SENTIDOS: no hay servicio en la imagen (el binario está y no corre
hasta que hay un torrent; lo levanta su cliente con `setsid`, sin lo cual moriría con
el navegador) y se va solo tras `inactividad_seg` sin nada activo — sembrar cuenta como
actividad.

CONFIGURABLE: TOML opcional; sin fichero anda, y uno ROTO es error. El CAS por defecto
es el del host, con un test que falla si esas raíces se separan.

LO QUE EL GUARDIÁN NO HACE, Y POR QUÉ (está en su cabecera y en el §6.9):
· no usa un `magnet:` sino un `.torrent` servido por HTTP —dar de alta un magnet
  BLOQUEA esperando metadata que sin peers no llega: se mediría un timeout y no la
  cadena—. El `.torrent` se arma en el propio guardián, en bencode a mano, porque un
  binario de prueba en el repo es una dependencia que nadie revisa;
· no pasa por el despacho de protocolos de Gecko: un clic en `magnet:` abre el diálogo
  de «¿con qué lo abro?», que en headless no contesta nadie, y eso es una elección del
  usuario y no código nuestro. Se abre la página de la extensión —la misma que el
  handler abriría— descubriendo su URL base del `dump` de una primera corrida, porque
  el UUID lo asigna Gecko por perfil y adivinarlo sería inventar.

El control negativo saca el cliente del daemon de la imagen y exige que el host lo diga
NOMBRANDO lo que falta, en vez de fingir que lo tomó.

⚠ Y sigue sin haber test automático de un transfer REAL entre peers: haría falta un
sembrador y una espera que volverían la suite una que nadie corre. Dicho en el test del
daemon y en el §6.9, para que nadie lo lea como «probado de punta a punta».

La página de la extensión NO valida la forma del origen: la valida el host, que es
quien decide qué le pasa al daemon. Tener esa regla escrita dos veces es tenerla
mintiendo el día que una cambie.

Del §6 quedan el foco (6.5) y la IA local (6.7), ésta bloqueada por algo medido: el
corpus no tiene ninguna receta de LLM ni de embeddings.

MEDIDO sobre `atuq b3:d1a444ad`, `puriy-costura b3:cad5c855` y
`puriy-costura-torrent b3:76afb7a8` (7,8 M):

    MAGNET http://…/prueba.torrent
    TOMADO prueba-atuq.bin · nuevo · en /salida/hogar/Downloads · id=0
    socket del daemon: run/puriy-costura-torrent.sock      ← nadie lo arrancó

⚠ Y DOS COSAS QUE EL GUARDIÁN DESTAPÓ, las dos por comprobar el NOMBRE y no sólo que
la respuesta llegara:

1. **la extensión leía claves que el daemon no manda** (`name`/`files`/`bytes` contra
   `nombre`/`carpeta`), y el síntoma era «TOMADO — 0 fichero(s), 0 bytes»: parecía un
   torrent vacío y era un vocabulario inventado del lado del lector — la misma trampa
   que había evitado en el host y no acá;
2. mirándolo apareció que **el socket y la config del daemon estaban en castellano**, y
   la regla 7 de tawasuyu nombra explícitamente las claves de configuración entre lo
   que se tipea. Corregido allá antes de que llegara a ninguna imagen: un protocolo y
   un fichero de config son contrato, y renombrarlos después rompe lo que alguien ya
   escribió.

tawasuyu: 4f36f057 (el crate) · 3f69aab2 (lock) · 3b56db26 (el verbo del host) ·
066b3761 (el log del daemon, que faltaba y hacía invisible su único fallo de arranque)
· ca9947b9 (las claves en inglés).
This commit is contained in:
Sergio
2026-09-10 20:45:53 +00:00
parent ca7d228512
commit c214438f00
12 changed files with 592 additions and 6 deletions
+45
View File
@@ -0,0 +1,45 @@
# puriy-costura-torrent — el brazo LARGO de la costura (SDD 26 §6.9): el daemon de torrent.
#
# ══ POR QUÉ ES UN BINARIO APARTE Y NO UN VERBO DENTRO DEL HOST ════════════════════════════════
# Dos razones, y la primera decide: **una descarga tiene que sobrevivir al navegador**, y Gecko
# lanza un host de native messaging POR PUERTO y lo mata cuando el puerto se cierra (medido el
# 2026-09-10). Un cliente BitTorrent dentro de `puriy-costura` dejaría de bajar al cerrar la
# pestaña. La segunda es el precio: librqbit + tokio + rustls son 226 crates, y ese host —952 K,
# compartido por las extensiones del navegador— pasaría a ~20 MB y cada iteración a un cuarto de
# hora.
#
# ⚠ Que esa pila COMPILA para musl con zig-cc se midió antes de decidir nada, con una receta
# desechable: 226 crates y sella. Era una incógnita real —ninguna receta de tawasuyu del corpus
# había construido tokio+rustls; las que hay dicen «deps livianas (sin tokio/libp2p/axum)»— así que
# la decisión no fue «no se puede», fue «no ahí».
#
# ══ PEREZOSO: ESTO NO ES UN SERVICIO ══════════════════════════════════════════════════════════
# El artefacto es un binario y nada más: NO se declara ningún `.service`, ni nada que corra al
# iniciar sesión. Lo levanta su propio cliente la primera vez que hay un `magnet:` que tomar, y se
# va solo cuando no queda nada bajando. Un daemon que arranca con la sesión es un daemon que nadie
# pidió, y en una distro se nota.
#
# ══ EL COMMIT PINEADO ═════════════════════════════════════════════════════════════════════════
# `3f69aab2` = el crate + el `Cargo.lock` cerrado (generado en un árbol LIMPIO del commit, que es
# la única forma de que describa `main` y no el árbol compartido de las sesiones).
name = "puriy-costura-torrent"
version = "0.1.0"
license = "MIT OR Apache-2.0"
[source]
repo = "gitea@git.tawasuyu.net:tawasuyu/tawasuyu.git"
commit = "ca9947b92f89d00ca549d7bbaa3293ec909db7d8"
# Obligatorio para cualquier receta desde este monorepo: tawasuyu commitea su propio `vendor/` con
# un `smithay` parcheado por RUTA, y el `cargo vendor` de takana convertiría ese directorio en uno
# de reemplazo de fuente, donde cada crate tiene que traer `.cargo-checksum.json` — que ese patch
# nunca tuvo. El síntoma no menciona nada de esto (ver `puriy-costura.toml`).
cargo_vendor_dir = ".hammer-cargo-vendor"
[build]
compiler = "zig-cc"
target = "x86_64-linux-musl"
# Estático: lo lanza el navegador (a través del host) y no puede depender de encontrar un loader.
link = "static"
# `--bin` además de `-p` porque el crate tiene lib + bin y `cargo rustc` exige un target único.
flags = ["-p", "puriy-costura-torrent", "--bin", "puriy-costura-torrent"]