SDD 26: atuq, el envoltorio Gecko — derivado, no fork; y la puerta es clang
La pregunta era «nuestro propio envoltorio en vez de zen». La respuesta tiene tres hallazgos que cambian el precio, y el documento los pone antes que la lista de features. 1. NO HAY ENVOLTORIO FUERA DEL CHROME. Gecko no tiene API de embebido en escritorio desde que murió XULRunner (GeckoView es Android) ⇒ una carcasa Llimphi con el motor adentro no es posible. El envoltorio es chrome-level o no es. Que es exactamente lo que Zen es. 2. ARTEFACTO DERIVADO, NO FORK DE FUENTE. Si atuq parchea el árbol, cada iteración de UI cuesta cuatro horas de Gecko y el diseño de chrome es iterativo por naturaleza. Como no distribuimos un binario sino que sellamos artefactos, atuq puede depender de `firefox` e inyectar marca, prefs, policies.json y omni.ja encima: itera en segundos, no mueve el ArtifactHash del corpus, y hereda las CVE gratis — que es lo que hundió a los forks de Firefox. Con sus dos gotchas escritos: el omni.ja es un zip y hay que re-empacarlo determinista, y sin invalidar el startup cache el overlay PARECE no agarrar. 3. LAS OPTIMIZACIONES NO SON UN FLAG, SON UNA TOOLCHAIN. PGO/LTO/BOLT son cadena de clang en Gecko, y el corpus no tiene clang usable como compilador: clang18.toml compila SÓLO libclang.so (para bindgen) y llvm18 se selló con PROJECTS="". La unidad real es una receta llvm-toolchain con clang+lld+libc++ musl — la misma pieza que resuelve el muro 3 de firefox.toml. Es la mayor palanca del frente, y por eso encabeza el plan. Lo que NO se promete va escrito ANTES de la lista de features, con el criterio del modelo de adversario de qullqa: atuq no es Tor Browser y no va a tener «modo Tor» — es un binario único en el mundo (musl, wayland-only, branding propio), así que salir por Tor desde acá identifica MÁS, no menos. Se ofrece proxy por contenedor, que es separación de tráfico y no anonimato. Los diferenciadores van con una columna «quién más lo tiene» para no contarnos un cuento: sct (transparencia de scripts, BLAKE3 + testigo) no lo tiene nadie y ya está escrito en tawasuyu; torrent SÍ lo tiene Vivaldi, y lo nuestro sólo vale por dónde cae lo bajado (el CAS). Todo lo que no es CSS pasa por UNA costura: un host de native messaging en Rust. Y atuq no abandona a puriy: el host, el testigo y el archivo con RAG son agnósticos del motor, así que cuando puriy madure se enchufan del mismo lado. atuq es su andamio, no su desvío.
This commit is contained in:
@@ -0,0 +1,237 @@
|
||||
# SDD 26 — `atuq`: el envoltorio Gecko de la distro
|
||||
|
||||
Escrito 2026-09-05, a partir de la pregunta del usuario: *«ya habiendo compilado firefox y waterfox,
|
||||
qué tan complicado vs provechoso suena crear nuestro propio envoltorio, en vez de zen?»*, y de su
|
||||
aclaración de por qué la pregunta existe: **`puriy` quedó muy verde y es difícil sacarlo de ahí**.
|
||||
|
||||
`atuq` es *zorro* en quechua. El nombre estaba libre —verificado con `grep -ri atuq` sobre
|
||||
`/mnt/vvv/hammer` y `/mnt/vvv/tawasuyu`, cero coincidencias— y dice exactamente lo que la cosa es:
|
||||
otro fox, con marca propia y sin usar la de Mozilla (ver el §branding de `recipes/firefox.toml`).
|
||||
|
||||
**Este documento no reemplaza a `puriy` ni lo cancela.** `puriy` sigue siendo el motor soberano; el
|
||||
§9 explica por qué `atuq` es su andamio y no su desvío.
|
||||
|
||||
---
|
||||
|
||||
## 1. La corrección que ordena todo: no hay envoltorio fuera del chrome
|
||||
|
||||
La intuición natural —una carcasa Llimphi con nuestros widgets, y Gecko adentro pintando la página—
|
||||
**no es posible**. Gecko no tiene API de embebido en escritorio desde que murió XULRunner; GeckoView
|
||||
existe y es de Android. No hay forma soportada de meter el motor en una ventana de `mirada`.
|
||||
|
||||
⇒ un envoltorio de Gecko es, necesariamente, **chrome-level**: JS/CSS/XHTML *dentro* del propio
|
||||
Firefox, más extensiones, más procesos externos que hablen con él.
|
||||
|
||||
Y eso es exactamente lo que Zen es. Zen no toca el motor: su diferencia entera —workspaces, split
|
||||
view, glance, compact mode— vive en el chrome, más una herramienta (`surfer`) que reaplica sus
|
||||
parches sobre el árbol de Firefox y recompila. **Su costo no es el motor: es la cinta de correr del
|
||||
rebase cada cuatro semanas.** Copiar su método sería heredar su costo sin heredar su equipo.
|
||||
|
||||
## 2. La decisión de arquitectura: artefacto DERIVADO, no fork de fuente
|
||||
|
||||
Si `atuq` parchea el árbol, **cada iteración de UI cuesta un build de Gecko de cuatro horas**. Eso
|
||||
mata el proyecto en la primera semana de diseño, porque el diseño de chrome es iterativo por
|
||||
naturaleza.
|
||||
|
||||
Pero nosotros no distribuimos un binario: sellamos artefactos. Entonces `atuq` es una receta cuyo
|
||||
`[deps]` incluye `firefox`, y cuyas fases copian el árbol instalado e inyectan encima:
|
||||
|
||||
| Qué se inyecta | Mecanismo de Firefox | Sin recompilar |
|
||||
|---|---|---|
|
||||
| Marca, iconos, nombre | `distribution/`, `application.ini` | ✅ |
|
||||
| Prefs de fábrica | `defaults/pref/*.js` + autoconfig (`.cfg`) | ✅ |
|
||||
| Política de empresa | `distribution/policies.json` | ✅ |
|
||||
| Chrome propio (dientes, layout) | `userChrome.css` + re-empaque de `omni.ja` | ✅ |
|
||||
| Extensiones nuestras | `distribution/extensions/` | ✅ |
|
||||
|
||||
**Ventajas que esto tiene sobre el método de Zen, y que son estructurales:**
|
||||
|
||||
1. **Iteración en segundos, no en horas.** El chrome se toca sin volver a compilar C++.
|
||||
2. **No mueve el `ArtifactHash` de `firefox`.** El corpus no se invalida; `waterfox` y cualquier otro
|
||||
fork siguen compartiendo el mismo artefacto base.
|
||||
3. **Las CVE se heredan gratis.** Un fork de fuente te vuelve dueño del reloj de seguridad del
|
||||
binario más atacado de la máquina — es lo que hundió a casi todos los forks de Firefox, y el
|
||||
reproche histórico a Waterfox. Un derivado se reconstruye solo cuando sube `firefox`.
|
||||
|
||||
**Los dos gotchas reales del camino, que son trabajo pero chico:**
|
||||
|
||||
- **`omni.ja` es un zip ⇒ hay que re-empacarlo determinista** (mtimes fijos, orden estable) o el
|
||||
artefacto deja de reproducir bit a bit. Es la misma disciplina que ya exige la imagen del lab.
|
||||
- **Hay que invalidar el startup cache** tras tocarlo (fichero `.purgecaches` junto al binario, o
|
||||
bump del BuildID). Si no, los cambios no se ven y **parece que el overlay no agarró**: un falso
|
||||
negativo de los caros, de la misma familia que el cache-hit que congela regresiones.
|
||||
|
||||
### 2.bis Cuándo SÍ hay que parchear el árbol
|
||||
|
||||
Cuando algo necesite tocar C++ del motor. Hoy conocemos un caso: `sct` en su forma fuerte (§6.1).
|
||||
La regla es: **nada baja al árbol antes de que exista la toolchain del §3**, porque hasta entonces
|
||||
cada intento cuesta cuatro horas. Y cuando baje, el vigía de parches (`scripts/vigia-parches.py`,
|
||||
commit `aa200a4`) es lo que convierte esas cuatro horas en un minuto para saber si el parche agarra.
|
||||
|
||||
## 3. La puerta de las optimizaciones: no es un flag, es una toolchain
|
||||
|
||||
El usuario decidió habilitar las optimizaciones. Lo que hay que saber antes de intentarlo:
|
||||
|
||||
`recipes/firefox.toml` va con `compiler = "gcc"` por el **muro 3** (zig enlaza `libc++` estática para
|
||||
musl y el `configure` de Mozilla exige encontrar un `NEEDED …libc++`; es negativa de upstream, no una
|
||||
perilla). El problema es que **PGO, LTO y BOLT son cadena de clang en Gecko**:
|
||||
|
||||
- `--enable-lto=cross` quiere clang + lld. El LTO de GCC sobre Gecko no está soportado upstream.
|
||||
- `--enable-profile-use` espera `-fprofile-instr-use` (clang), no `-fprofile-use` (gcc).
|
||||
- BOLT necesita `llvm-bolt`.
|
||||
|
||||
Y **el corpus no tiene clang usable como compilador**. Verificado en las recetas, no supuesto:
|
||||
|
||||
- `recipes/clang18.toml` compila `ninja -C build libclang.so clang-resource-headers` y su fase
|
||||
`install` copia **sólo** `build/lib/libclang.so*` y las cabeceras `clang-c`. Está ahí porque
|
||||
`bindgen` carga `libclang.so` en runtime. **No hay driver `clang`, ni `lld`, ni `libc++`.**
|
||||
- `llvm18` se selló con `-DLLVM_ENABLE_PROJECTS=""` — LLVM a secas.
|
||||
|
||||
⇒ **la unidad de trabajo real es una receta `llvm-toolchain` con clang + lld + `libc++` compartida
|
||||
para musl.** Es la misma pieza que resuelve el muro 3, así que destraba de una sola vez: LTO, PGO,
|
||||
BOLT, y el regreso de Firefox a una toolchain más cercana a la del resto del corpus. **Es la mayor
|
||||
palanca por unidad de trabajo que hay en este frente**, y por eso encabeza el plan del §8.
|
||||
|
||||
**Riesgos de PGO, escritos antes de empezar:**
|
||||
|
||||
- El PGO de Mozilla **corre el navegador** para juntar el perfil (`profileserver.py`, headless +
|
||||
marionette). Dentro de un sandbox hermético, sin red y sin X11, eso hay que hacerlo andar.
|
||||
Headless no necesita display, pero sí necesita que el árbol de perfil se genere adentro.
|
||||
- **El perfil resultante es un input del artefacto.** O entra en `hash_inputs`, o `atuq` deja de ser
|
||||
determinista y no lo vamos a notar: sería otra forma del lab que no está en `hash_inputs`.
|
||||
- Ganancia esperable, para calibrar expectativas: PGO+LTO en Gecko son del orden de 10-25% en carga
|
||||
de página y JS. **Hoy estamos ATRÁS de Zen en este eje, no adelante** — Zen hereda la
|
||||
configuración de Mozilla tal cual. Esto no es una ventaja nuestra: es una deuda que se salda.
|
||||
|
||||
## 4. Lo que `atuq` NO promete
|
||||
|
||||
Esta sección existe antes que la lista de features a propósito, con el mismo criterio que el modelo
|
||||
de adversario de `qullqa`: **lo que no se promete se escribe primero, porque una promesa falsa de
|
||||
privacidad es peor que no ofrecer nada.**
|
||||
|
||||
**`atuq` no es Tor Browser y no va a tener «modo Tor».** Tor Browser no es «Firefox + SOCKS»: su
|
||||
valor son las contramedidas de huella (RFP, letterboxing, normalización de fuentes/canvas/timers) y
|
||||
sobre todo **un conjunto de anonimato donde todos se ven idénticos**. `atuq` es, por construcción, un
|
||||
binario único en el mundo: musl, Wayland-only, branding propio, extensiones propias. Alguien saliendo
|
||||
por Tor desde `atuq` es **más** identificable, no menos, y su conjunto de anonimato son diez
|
||||
personas. Para anonimato: Tor Browser, y lo decimos nosotros primero.
|
||||
|
||||
Lo que sí se ofrece, y es honesto porque es otra cosa: **proxy por contenedor** (§6.8) — separación
|
||||
de tráfico, no anonimato.
|
||||
|
||||
**`atuq` tampoco promete** anti-fingerprinting propio (es un programa de investigación con equipo
|
||||
full-time) ni bloqueo de anuncios propio (se shipea uBO y listo).
|
||||
|
||||
## 5. Contexto verificado al escribir (2026-09-05)
|
||||
|
||||
De `docs/state/build-state.json`, no de memoria:
|
||||
|
||||
| Dato | Valor |
|
||||
|---|---|
|
||||
| Recetas / nodos | 838 / 840 |
|
||||
| Selladas | 837 |
|
||||
| `firefox` 154.0 | **sealed**, cola `corpus` |
|
||||
| `waterfox` 6.7.1.1 | **never** — primer build en curso |
|
||||
| Plataforma compartida | `gtk3`, `atk`, `nodejs`, `clang18`, `cbindgen`: todas sealed |
|
||||
|
||||
**`atuq` no arranca hasta que `waterfox` selle.** Waterfox es la prueba de la tesis del reúso —«las
|
||||
diferencias reales con `firefox.toml` son TRES: la fuente, el branding y la versión»—. Si esa tesis
|
||||
falla, el precio de todo este documento cambia y hay que releerlo.
|
||||
|
||||
## 6. Los diferenciadores, priorizados
|
||||
|
||||
La columna «quién más lo tiene» es lo que evita que nos contemos un cuento.
|
||||
|
||||
| # | Qué | Quién más lo tiene | Pieza que ya existe | Costo |
|
||||
|---|---|---|---|---|
|
||||
| 6.1 | **`sct` — transparencia de scripts** | **nadie** | `puriy-sct`, `puriy-sct-testigo` | medio |
|
||||
| 6.2 | **Descargas direccionadas por contenido** | nadie | store CAS de hammer, `tejido` | bajo |
|
||||
| 6.3 | **Archivo personal + RAG local** | Rewind/Recall (nube, Windows); SingleFile (guarda, no busca) | `khipu`, `rag-motor`, `willay-rag` | medio |
|
||||
| 6.4 | **Historial y perfil sobre `qullqa`** | nadie | `qullqa-core`, `qullqa-pozo` | medio |
|
||||
| 6.5 | **Foco por `cortafuegos`, no por extensión** | nadie (nadie es dueño del navegador *y* del sistema) | `cortafuegos`, `pacha` | bajo |
|
||||
| 6.6 | **Medios por fuera del navegador** | extensiones sueltas; de fábrica no | `foreign-ytdlp`, `-platform`, `-dlna` | bajo |
|
||||
| 6.7 | **IA local en la barra lateral** | Chrome/Edge son nube; Zen no tiene | `rimay`, `iniy` | bajo |
|
||||
| 6.8 | **Proxy por contenedor** | nadie de fábrica | — (API de Firefox) | bajo |
|
||||
| 6.9 | **Torrent adentro** | **Vivaldi lo trae; Brave tuvo WebTorrent** | `shared/foreign-torrent` (SDD propio, sobre librqbit) | bajo |
|
||||
|
||||
### 6.1 `sct` es la joya
|
||||
|
||||
BLAKE3 a todo lo que se ejecuta, y **negarse a correr código que ningún testigo vio nunca**. Es lo
|
||||
más cerca que hay de «Certificate Transparency, pero para el JavaScript que te corre en la cara», y
|
||||
no lo tiene nadie: ni Zen, ni Brave, ni Tor Browser.
|
||||
|
||||
En tawasuyu ya está escrito y —dice su README— la lógica es **agnóstica del transporte** y está
|
||||
certificada sin red; `puriy-sct-testigo` es sólo el cable HTTP.
|
||||
|
||||
- **v1, sin tocar C++:** extensión con `webRequest` bloqueante que hashea cada respuesta de script y
|
||||
consulta al testigo antes de dejarla pasar.
|
||||
- **v2, forma fuerte:** gancho en el script loader de Gecko. Eso sí es parche de árbol ⇒ §2.bis ⇒
|
||||
después de la toolchain del §3.
|
||||
|
||||
### 6.2 Una descarga con identidad
|
||||
|
||||
Lo bajado no es un archivo en `~/Downloads`: es un objeto BLAKE3 en el store — deduplicado,
|
||||
verificable, y re-compartible por `tejido`. El torrent (6.9) alimenta lo mismo. **Ningún navegador
|
||||
trata una descarga como algo con identidad**; para todos es un blob con nombre, y por eso lo bajás
|
||||
dos veces y no lo sabés.
|
||||
|
||||
Ésa, y no «tener torrent», es la razón por la que 6.9 vale: Vivaldi ya tiene torrent, pero termina en
|
||||
una carpeta.
|
||||
|
||||
### 6.3 El archivo personal es la razón por la que alguien usaría `atuq`
|
||||
|
||||
Cada página visitada se congela en el CAS y entra al DAG de `khipu`; después le preguntás a tu
|
||||
propio historial en lenguaje natural, **todo local**. Es la feature que más justifica el proyecto
|
||||
entero, y sale de piezas que ya están escritas.
|
||||
|
||||
### 6.4 `qullqa` con su advertencia puesta
|
||||
|
||||
Almacenamiento con negación plausible y modelo de adversario **escrito** — ningún navegador tiene
|
||||
eso; el modo incógnito es teatro. ⚠ Con la advertencia que el propio SDD de `qullqa` ya anotó y que
|
||||
**hay que repetir acá, no esconder**: en una máquina con swap sin cifrar, el documento no aplica.
|
||||
Se promete lo que se puede probar.
|
||||
|
||||
## 7. La costura: un host de native messaging en Rust
|
||||
|
||||
Todo lo del §6 que no es CSS pasa por **un solo mecanismo**: un proceso Rust que habla native
|
||||
messaging con la extensión de `atuq` y, del otro lado, con la suite (`agora` para identidad Ed25519,
|
||||
`khipu`, el store, `foreign-*`, `cortafuegos`).
|
||||
|
||||
Que sea **uno** y no siete es la decisión: cada feature del §6 pasa a ser un verbo de ese host, no un
|
||||
proyecto nuevo. El binario vive en tawasuyu (es suite, no build system); `atuq` sólo lo declara como
|
||||
dep y le deja el manifiesto de native messaging en su sitio. **El nombre del crate se decide en
|
||||
tawasuyu y con su regla 10 puesta** — acá no se bautiza nada de allá.
|
||||
|
||||
## 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
|
||||
siguiente.
|
||||
|
||||
| # | Unidad | Puerta que abre | Bloqueada por |
|
||||
|---|---|---|---|
|
||||
| 1 | `waterfox` sella | valida la tesis del reúso | build en curso |
|
||||
| 2 | **`llvm-toolchain`** (clang+lld+libc++ musl) | LTO, PGO, BOLT **y** el muro 3 | — |
|
||||
| 3 | `firefox` con LTO+PGO (perfil en `hash_inputs`) | el eje de velocidad | 2 |
|
||||
| 4 | **`atuq`: receta derivada + overlay de chrome** | el andamio de todo lo demás | 1 |
|
||||
| 5 | Host de native messaging (tawasuyu) | 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 |
|
||||
| 9 | Proxy por contenedor, torrent, medios, foco | 6.5–6.9 | 5 |
|
||||
|
||||
Las unidades 2 y 4 son **paralelizables**: la toolchain no toca el chrome y el chrome no toca la
|
||||
toolchain. Si hay dos frentes, van juntas.
|
||||
|
||||
## 9. Por qué esto no abandona a `puriy`
|
||||
|
||||
`puriy` es el motor DOM/CSS propio con JS real (QuickJS-NG sobre `wasmi`) cuyo límite declarado no es
|
||||
el lenguaje sino **el wiring nativo**: DOM bindings completos, red, render. Eso no se acelera
|
||||
escribiendo otro navegador; se acelera con tiempo.
|
||||
|
||||
`atuq` no le compite porque no comparte una sola línea con él, y **le sirve** porque todo lo del §6
|
||||
vive del lado Rust: el host del §7, el testigo de `sct`, las descargas al CAS, el archivo con RAG.
|
||||
Son **agnósticos del motor**. Cuando `puriy` madure, se enchufan del mismo lado sin reescribirse.
|
||||
|
||||
Dicho al revés, que es como conviene recordarlo: **`atuq` es el navegador que se puede usar mientras
|
||||
`puriy` crece, y el andamio de las features que `puriy` va a heredar.** Si dentro de dos años `atuq`
|
||||
se apaga, lo que se tira es una receta derivada y una hoja de CSS; todo lo demás sobrevive.
|
||||
@@ -21,6 +21,7 @@ discrepancia, o se corrige el código o se actualiza el SDD con un commit que ex
|
||||
| 11 | [Bootstrap from-scratch](11-bootstrap.md) | Track posterior: Stage 0/1/2, auto-alojamiento, semilla pinned |
|
||||
| 12 | [`arje` como init real del Stage 1](12-init-real.md) | Contrato de runtime: seed card, hammerd supervisado, `CRASHED` real |
|
||||
| 16 | [harkaq: la jaula de hammer](16-harkaq-jaula.md) | Landlock+seccomp sobre el bwrap actual; política = clausura; evidencia negativa de hermeticidad |
|
||||
| 26 | [`atuq`: el envoltorio Gecko](26-atuq-envoltorio-gecko.md) | Navegador propio como artefacto DERIVADO de `firefox` (no fork de fuente); la toolchain clang como puerta de PGO/LTO; qué se promete y qué no |
|
||||
|
||||
### Runbooks (operativos)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user