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…

TOML 1184Shell 70Rust 62Markdown 501503 Definiciones

SDD 26: la unidad 5 está hecha — el host, y por qué la extensión no puede hablarle al testigo

Cierra la fila 5 del plan con lo que hay: `puriy-costura` + `shared/foreign-webext` en tawasuyu
(`ebe41e96`, 14 tests) y `recipes/puriy-costura.toml` acá (`b3:3b633431`, verificado como artefacto:
contesta un marco de 4 bytes y hace la promesa del §6.1 completa).

El §7.quater deja tres cosas que no estaban escritas:

· POR QUÉ HACÍA FALTA el host y no se podía atajar: el §6.1 decía que la extensión «consulta al
  testigo», y el cable del testigo es un POST con postcard, no JSON — un JS no puede ser su cliente.
  Reimplementar el TOFU en la extensión sería el sustituto paralelo que la regla 10 de tawasuyu
  prohíbe, además de duplicar la única pieza ya certificada.

· CÓMO SE ELIGIÓ EL NOMBRE, con el grep de la regla 10 hecho ANTES: ningún término del dominio
  significaba esto, y los que suenan a mensajero están ocupados por dominios ajenos y grandes
  (chasqui = type broker, chaka = puente a COBOL, paloma = correo, tampu = común de objetos). El
  nombre salió del título de este propio §7: la costura.

· LOS DOS LÍMITES, que van en el código y en los LEEME y no en una nota de sesión: se hashea el texto
  ya decodificado (vale para detectar, no es comparable con el hash de un tercero ni con el de la v2),
  y la semilla del log sale del directorio de estado ⇒ a prueba de reescritura, no de suplantación.

Y lo medido para la unidad 6 preguntándole al artefacto: `filterResponseData` y el permiso
`webRequestFilterResponse` SÍ están en nuestro omni.ja ⇒ la extensión podrá leer el cuerpo de un
script. Los inline NO se ven por esa vía, y para v1 está bien: el ataque que sct nombra es la
sustitución en el CDN, o sea el caso `<script src>`.

9f476ddd70372b61b4ccdd0ff7e99f7ab97faeac · por Sergio · (hace 1 mes) · padre 60703e397 · ver el árbol en este commit

Delta semántico

Ninguna definición cambió: el cambio es de texto, documentación o datos.

1 archivos · +50 −1

diff --git a/docs/26-atuq-envoltorio-gecko.md b/docs/26-atuq-envoltorio-gecko.md
index 36248ec5..ea77638a 100644
--- a/docs/26-atuq-envoltorio-gecko.md
+++ b/docs/26-atuq-envoltorio-gecko.md
@@ -1060,6 +1060,55 @@ hidratado el rootfs de `scripts/atuq-nested.sh`, así que **es una decisión con
 `echo` más en el cron** — queda escrita acá y sin dar por hecho lo contrario. El día que se meta, el
 sitio es el bloque de guardianes de `cosecha-cron.sh` (L341-352).
 
+### 7.quater El host, escrito — y por qué la extensión NO puede hablarle al testigo (2026-09-10)
+
+El §6.1 decía que `sct` v1 es «extensión con `webRequest` bloqueante que hashea cada respuesta de
+script y **consulta al testigo** antes de dejarla pasar». La primera mitad es correcta; la segunda es
+imposible tal como está escrita, y conviene decirlo porque parecía un atajo para saltarse esta
+unidad: **el cable de `puriy-sct-testigo` es un POST con `postcard` en el body**, no JSON. Un JS no
+puede ser su cliente. Y reimplementar el registro TOFU en la extensión sería fabricar un sustituto
+paralelo del original —lo que la regla 10 de tawasuyu prohíbe— además de duplicar la única pieza que
+ya estaba certificada. Entonces v1 pasa por el host, y el host es esta unidad.
+
+Se decidió con el operador, con el `grep` de la regla 10 hecho primero: **ningún término del dominio
+significaba «host de native messaging»**, y los que suenan a mensajero están todos ocupados por
+dominios ajenos y grandes (`chasqui` es un type broker, `chaka` el puente a COBOL, `paloma` el cliente
+de correo, `tampu` el común de objetos). El nombre salió del título de este propio §7: **la costura**.
+
+| Pieza | Dónde | Por qué ahí |
+|---|---|---|
+| `puriy-costura` | `00_unanchay/puriy/` | regla 1: subcrate del dominio, no proliferación lateral. Precedentes: `puriy-sct-testigo`, `rimay/verbo-daemon`, `watuy-daemon` |
+| `foreign-webext` | `shared/` | regla 4: el protocolo es AJENO. Lib pura sin binario, como los otros 37 puentes (medido: ninguno lleva `[[bin]]`) |
+| `recipes/puriy-costura.toml` | takana | el artefacto: estático musl, pineado por commit, `--locked` |
+
+Verbos v1: `ping`, `sct.observe`, `sct.state`. Claves del cable en inglés (regla 7 de allá y regla 4
+de acá: se tipean). `phase` es `learning`/`stable`/`not-evaluable`, y un `events[]` vacío es lo normal
+— sólo hay evento cuando un origen **ya estable** ejecuta un hash que nadie vio nunca.
+
+**Los tres tests que hacen que el veredicto signifique algo** (de catorce): el mismo cambio de script
+mientras el origen todavía aprende **no** alerta; rotar `?v=` con el mismo código **tampoco** (la
+identidad del recurso es su contenido, y sin eso cada despliegue con cache-buster sería un aviso de
+supply-chain: un detector que grita todos los días no se mira más); y el aprendizaje **sobrevive al
+cierre del navegador**, sin lo cual cada arranque volvería a «aprendiendo» y ningún cambio sería nunca
+un evento.
+
+**Los dos límites, escritos en el código y en los dos LEEME, no en una nota de sesión:**
+
+1. **Qué bytes se hashean.** La extensión manda el TEXTO ya decodificado; se hashea su UTF-8. La
+   detección vale —el TOFU compara lo mismo contra lo mismo—, pero nuestro hash **no es comparable**
+   con el de los bytes servidos que publique un tercero, ni con el de la v2 (el gancho en el script
+   loader). Un hash que uno cree comparable y no lo es sería peor que no tenerlo.
+2. **La semilla del log es provisional**: se deriva del directorio de estado, así que es
+   determinística (el log se reanuda) pero **no es un secreto** ⇒ la bitácora es a prueba de
+   REESCRITURA, no de SUPLANTACIÓN. La de verdad sale del perfil cuando el almacén del perfil exista.
+
+**Y lo que queda medido para la unidad 6, preguntándole al artefacto y no a la documentación de
+Mozilla** (§2.sexies): `filterResponseData` y el permiso `webRequestFilterResponse` **están** en
+nuestro build (`omni.ja`, `chrome/toolkit/content/extensions/schemas/web_request.json`), así que la
+extensión va a poder leer el cuerpo de un script. Lo que NO va a poder es ver los scripts **inline**
+por esa vía —`filterResponseData` entrega el documento, no cada `<script>`—, y eso está bien para v1:
+el ataque que `sct` nombra es la sustitución en el CDN, que es exactamente el caso `<script src>`.
+
 ## 8. Plan, por unidades de trabajo
 
 Cada una cierra sola, se commitea y se pushea. El orden no es preferencia: cada una destraba a la
@@ -1080,7 +1129,7 @@ siguiente.
 | 4.c | `MOZ_BUILD_DATE` determinista ✅ — `BuildID=19700101000001`, con guardián en install y **`why-differs` 56/56 sobre dos builds reales** | el invariante de reproducibilidad | — |
 | 4.g | **El chrome se programa desde `atuq.cfg`, sin abrir `omni.ja`** ✅ 2026-09-09 — y de paso: la **vista dividida ya la trae el motor y viene prendida** (fx 154), ejercitada de verdad con `gBrowser.addTabSplitView` ⇒ `activeSplitView` + 2 navegadores. Guardián `scripts/test-atuq-chrome.py` con control negativo del propio motor | retira dos pendientes que eran de upstream, y deja el camino del chrome que NO pelea con el `jarlog` | — |
 | 4.h | **Quién instala las extensiones, medido** ✅ 2026-09-09 — tres escenarios en `scripts/test-atuq-instalacion.py`: instala el ESCANEO de `distribution/extensions/`, `install_url` con `file://` no instala nada. El README de la receta afirmaba lo contrario y quedó corregido | el mecanismo del que cuelga la extensión de `sct` deja de ser una nota al pie y pasa a estar vigilado | — |
-| 5 | Host de native messaging (tawasuyu) — **camino COMPROBADO 2026-09-07** (§7.bis): sonda extensión↔proceso nativo con control negativo, y las tres trampas medidas (dónde va el manifiesto, qué instala de verdad, y que el host tiene que ser un proceso largo) | los verbos del §6 | 4 |
+| 5 | **Host de native messaging — HECHO 2026-09-10.** `puriy-costura` en tawasuyu (`ebe41e96`) + el cable `shared/foreign-webext`, 14 tests sin navegador; y del lado de acá `recipes/puriy-costura.toml` ⇒ `b3:3b633431`, ELF estático de 952 K **verificado como artefacto**: contesta un marco de 4 bytes y hace la promesa del §6.1 completa (4 visitas aprendiendo → `stable` → un script cambiado = un evento). El camino ya estaba comprobado en el §7.bis con sonda y control negativo | los verbos del §6 | 4 ✅ |
 | 6 | `sct` v1 (extensión + testigo) | el diferenciador que nadie tiene | 5 |
 | 7 | Descargas al CAS | 6.2, y alimenta 6.9 | 5 |
 | 8 | Archivo + RAG | 6.3 | 5, 7 |