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.
90 lines
5.7 KiB
TOML
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"]
|