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 `