Files
takana/recipes/atuq.toml
T
Sergio aeebb194dc atuq 0.1.0: la receta del envoltorio, derivada de firefox
Primera receta del navegador de la distro (SDD 26). No compila nada: depende de `firefox`, copia su
árbol y le pone encima cuatro ficheros. Hash b3:2d6e4dcf.

LA CAPA SON CUATRO FICHEROS Y CADA UNO ESTÁ DONDE ESTÁ POR UNA RAZÓN:
- `defaults/pref/autoconfig.js` — el único gancho que corre ANTES de que exista un perfil.
- `atuq.cfg` — prefs de fábrica + carga del chrome. Con `defaultPref` y no `lockPref`: son valores
  de arranque, no una cárcel; lo que de verdad se bloquea va en policies.json.
- `chrome/atuq.css` — el aspecto.
- `distribution/policies.json` — telemetría, updates, primer arranque.

POR QUÉ EL CSS NO ES `userChrome.css`: ese fichero vive en el PERFIL y exige que el usuario prenda
`toolkit.legacyUserProfileCustomizations.stylesheets`. atuq tiene que verse como atuq en el primer
arranque, con un perfil recién creado, sin que nadie prenda nada. El único gancho a nivel de
APLICACIÓN es nsIStyleSheetService desde autoconfig — y llegar a él es la razón de
`sandbox_enabled = false`. Se registra como USER_SHEET, el mismo nivel de cascada que userChrome,
para que el usuario pueda seguir pisándolo.

DOS TRAMPAS DEL FORMATO, ESCRITAS EN EL PROPIO FICHERO:
- la PRIMERA LÍNEA de un autoconfig se ignora siempre, por diseño (herencia de Netscape). Código en
  la línea 1 no corre y no da error: el fallo más caro de ese fichero es el que no dice nada.
- el CSS va acotado con @-moz-document a browser.xhtml. Una hoja USER sin acotar alcanza CUALQUIER
  documento chrome —visor de PDF, inspector, diálogos— y un selector como `toolbar` termina pintando
  ventanas que nadie miró.

`extensions.autoDisableScopes = 0` es la otra mitad del `--with-unsigned-addon-scopes` que ya viaja
en el build de firefox: sin los dos, las extensiones de la distro se instalan DESACTIVADAS.

LAS ASERCIONES VAN PRIMERO Y FALLAN RUIDOSAS. Un derivado que no encuentra su base produciría un
directorio con cuatro ficheros de config, `Store::has` lo daría por presente y el fallo aparecería
el día que alguien abra el navegador (regla 3 del CLAUDE.md). Y al final imprime el inventario de la
capa con sus tamaños, que es la primera pregunta del diagnóstico cuando «atuq se ve como Firefox».

LO QUE LA v0.1 NO HACE, A PROPÓSITO: no renombra el binario ni toca application.ini, y no
re-empaqueta omni.ja. Las dos cosas necesitan mirar la forma real del árbol que selle `firefox`, y
adivinarla desde acá daría un artefacto que arranca en una máquina y en ninguna otra.

No se puede construir todavía: su dep `firefox` está en vuelo.
2026-09-05 04:12:55 +00:00

90 lines
5.7 KiB
TOML

# atuq 0.1.0 — el navegador de la distro, como ARTEFACTO DERIVADO de firefox.
#
# ══ POR QUÉ DERIVADO Y NO UN FORK DE FUENTE ════════════════════════════════════════════════════
# Zen —el fork de Firefox al que esto reemplaza en nuestro catálogo— parchea el árbol de Gecko y
# recompila. Nosotros no distribuimos un binario: sellamos artefactos. Entonces atuq puede DEPENDER
# de `firefox` y poner su capa encima, y eso cambia el precio de todo:
# · una iteración de chrome cuesta SEGUNDOS, no las cuatro horas de un build de Gecko;
# · no mueve el `ArtifactHash` de `firefox` ⇒ el corpus no se invalida;
# · las CVE se heredan gratis: cuando sube `firefox`, atuq se reconstruye solo.
# El razonamiento completo, con lo que se promete y lo que NO (spoiler: no habrá «modo Tor»), está
# en `docs/26-atuq-envoltorio-gecko.md`.
#
# ══ SU FUENTE ES ESTE REPO ═════════════════════════════════════════════════════════════════════
# `source.dir` es el modo de fuente que se agregó para esto (hammer-core/src/recipe.rs): el árbol
# vive en `recipes/atuq/` y se hashea por CONTENIDO con `ArtifactHash::of_tree`, igual que ya se
# hacía con los `patches`. No hay commit que pinear y no hay fetch: editar un CSS mueve el hash.
#
# ══ LO QUE ESTA v0.1 NO HACE, A PROPÓSITO ══════════════════════════════════════════════════════
# No renombra el binario ni toca `application.ini`. El branding necesita mirar la forma real del
# árbol que sella `firefox` —qué es `firefox-bin`, cómo se resuelve el appdir— y adivinarlo desde
# acá produciría un artefacto que arranca en la máquina de quien lo escribió y en ninguna otra.
# Tampoco re-empaqueta `omni.ja`, que es donde vive el chrome de verdad; eso es la v0.2 y trae dos
# condiciones ya sabidas (re-empacar determinista y preservar el orden del `jarlog` del PGO).
name = "atuq"
version = "0.1.0"
# El artefacto CONTIENE Firefox, así que hereda su licencia. El overlay de `recipes/atuq/` es
# nuestro, pero eso no cambia lo que se distribuye.
license = "MPL-2.0"
[source]
dir = "atuq"
[build]
# No se compila nada: esta receta copia y edita ficheros. `compiler` y `link` entran igual en el
# hash, así que se dejan en el default del corpus para no inventar una identidad que no significa
# nada.
target = "x86_64-linux-musl"
[build.phases]
configure = "echo 'atuq: nada que configurar — es un artefacto derivado'"
compile = "echo 'atuq: nada que compilar — el motor lo pone la dep firefox'"
install = '''
set -e
SRC=/usr/lib/firefox
DST=/out/usr/lib/atuq
# ── LAS ASERCIONES VAN PRIMERO, Y FALLAN RUIDOSAS ─────────────────────────────────────────────
# Un derivado que no encuentra su base no debe producir un artefacto flaco: produciría un
# directorio con cuatro ficheros de configuración, `Store::has` lo daría por presente y el fallo
# aparecería el día que alguien intente abrir el navegador. Un ausente falla fuerte; un vacío llega
# hasta el final diciendo que todo fue bien (regla 3 del CLAUDE.md).
[ -d "$SRC" ] || { echo "atuq: no está el árbol de firefox en $SRC — ¿la dep se materializó?" >&2; exit 1; }
[ -x "$SRC/firefox" ] || { echo "atuq: $SRC/firefox no existe o no es ejecutable" >&2; exit 1; }
[ -d "$SRC/browser" ] || { echo "atuq: falta $SRC/browser — el árbol no tiene la forma esperada" >&2; exit 1; }
mkdir -p "$DST"
cp -a "$SRC"/. "$DST"/
# ── LA CAPA DE atuq ───────────────────────────────────────────────────────────────────────────
# `defaults/pref/` es el único sitio desde el que se puede pedir el autoconfig ANTES de que exista
# un perfil; el resto cuelga de ahí.
mkdir -p "$DST/defaults/pref" "$DST/chrome" "$DST/distribution"
cp /src/prefs/autoconfig.js "$DST/defaults/pref/autoconfig.js"
cp /src/atuq.cfg "$DST/atuq.cfg"
cp /src/chrome/atuq.css "$DST/chrome/atuq.css"
cp /src/distribution/policies.json "$DST/distribution/policies.json"
# El comando que teclea la gente. Apunta al binario SIN renombrar (ver la nota de la cabecera):
# renombrarlo es branding y branding es la v0.2.
mkdir -p /out/usr/bin
ln -sf ../lib/atuq/firefox /out/usr/bin/atuq
# ── INVENTARIO: LO QUE SE MIRA CUANDO «ATUQ SE VE COMO FIREFOX» ───────────────────────────────
# Los cuatro ficheros de la capa son el 100% de lo que distingue este artefacto de su base, y son
# los que un `cp` silencioso podría no haber puesto. Se listan para que el log del build responda
# solo la primera pregunta del diagnóstico.
echo "atuq: capa aplicada —"
for f in defaults/pref/autoconfig.js atuq.cfg chrome/atuq.css distribution/policies.json; do
[ -s "$DST/$f" ] || { echo "atuq: $f quedó VACÍO o ausente" >&2; exit 1; }
echo " $f ($(wc -c < "$DST/$f") bytes)"
done
'''
[deps]
# `firefox` como dep de BUILD y no de runtime: su árbol se materializa en el sandbox, se copia
# dentro del artefacto de atuq y a partir de ahí atuq no lo necesita más. El precio es que el
# artefacto pesa lo que pesa Firefox otra vez; la salida barata (una granja de symlinks) rompe la
# resolución del appdir por /proc/self/exe, así que la v0.1 paga el disco y lo dice.
build = ["firefox"]