atuq ABRE: el app_id estaba compilado en el binario, y el árbol copiado llegaba de sólo lectura

Con la cadena GTK3 arreglada, atuq arrancó de verdad: parent vivo, CERO procesos de contenido
muertos, y pintando una página local. Quedaban dos cosas.

1. SE ANUNCIABA COMO `firefox-default`. El application.ini decía RemotingName=atuq y aun así el
   proceso se presentaba así — porque esa cadena es un MOZ_APP_REMOTINGNAME horneado en el ELF, y es
   la que Gecko pasa a g_set_prgname(), o sea el **app_id de Wayland**. Consecuencia visible: el
   escritorio no casaba la ventana con nuestro .desktop (StartupWMClass=atuq) ⇒ icono genérico y sin
   agrupar.

   Se parchea EN SITIO, no recompilando: cambiarlo en recipes/firefox.toml brandearía la BASE como
   atuq, y firefox tiene que seguir siendo firefox para los otros forks. Es seguro porque es una
   cadena C terminada en NUL en el pool de .rodata —`firefox-default\0` son 16 bytes exactos y se
   escriben 16—, y se EXIGE una única ocurrencia: si upstream la duplica o la renombra, falla en vez
   de parchear el sitio equivocado. Verificado después: 0 ocurrencias de la vieja, y el log dice
   `(atuq:26423)`.

2. UN BUG QUE SÓLO SE VE FUERA DE ROOT. `cp -a` preserva los modos y los ficheros del store están
   sellados sin permiso de escritura; todo lo que viene después los modifica. En el worker pasaba
   inadvertido porque corre como root, que ignora los bits. El primer build local murió con
   `PermissionError: /out/usr/lib/atuq/application.ini`. Se arregla con `chmod -R u+w` en la receta y
   no en el entorno: un artefacto no debe depender de con qué uid lo construiste.

Y el runner pasa a hidratar las variantes `-shared`: en runtime una `.a` no sirve de nada, y son las
que gtk3 declara NEEDED desde el arreglo del cuadro de las dos Pango.

Este atuq se construyó EN LOCAL en segundos, que era la promesa entera del diseño derivado del
SDD 26: iterar el envoltorio sin volver a pagar un build de Gecko.
This commit is contained in:
Sergio
2026-09-05 14:31:35 +00:00
parent 5db1c7ec89
commit 5d06a3b83d
3 changed files with 52 additions and 2 deletions
+8
View File
@@ -65,6 +65,14 @@ DST=/out/usr/lib/atuq
mkdir -p "$DST"
cp -a "$SRC"/. "$DST"/
# ── EL ÁRBOL COPIADO LLEGA DE SÓLO LECTURA ────────────────────────────────────────────────────
# `cp -a` preserva los modos, y los ficheros del store están sellados sin permiso de escritura. Todo
# lo que viene después —el `.ini`, el `omni.ja`, los iconos, el parche del app_id— los MODIFICA.
# En el worker esto pasaba inadvertido porque corre como root, que ignora los bits de permiso; el
# primer build fuera de root murió con `PermissionError: /out/usr/lib/atuq/application.ini`.
# Es la clase de bug que sólo aparece en la máquina de otro, así que se arregla acá y no en el
# entorno: un artefacto no debe depender de con qué uid lo construiste.
chmod -R u+w "$DST"
# ── LA CAPA DE CONFIGURACIÓN ──────────────────────────────────────────────────────────────────
# `defaults/pref/` es el único sitio desde el que se puede pedir el autoconfig ANTES de que exista
+40
View File
@@ -249,6 +249,42 @@ def renombrar_binarios():
return hechos
# ── 6. La marca COMPILADA dentro del binario ───────────────────────────────────────────────────
# `application.ini` dice `RemotingName=atuq` y aun así el proceso se anunciaba como
# `firefox-default`: esa cadena es un `MOZ_APP_REMOTINGNAME` horneado en el ELF en tiempo de
# compilación, y es la que Gecko pasa a `g_set_prgname()` ⇒ es el **app_id de Wayland**. O sea que
# el escritorio no casaba la ventana con nuestro `.desktop` (`StartupWMClass=atuq`): icono genérico
# y sin agrupar con el lanzador. Se ve en el log de cualquier arranque: `(firefox-default:7048)`.
#
# Se parchea EN SITIO y no se recompila: cambiarlo en `recipes/firefox.toml` brandearía la BASE de
# atuq como atuq, que es justo lo que un derivado no debe hacer —firefox tiene que seguir siendo
# firefox para los otros forks—.
#
# Es seguro porque es una cadena C terminada en NUL dentro del pool de `.rodata`: acortarla deja
# NULs muertos detrás y la siguiente cadena empieza donde empezaba. `firefox-default\0` son 16
# bytes exactos y se escriben 16. Y se EXIGE una única ocurrencia: si upstream la duplica o la
# renombra, esto falla en vez de parchear el sitio equivocado.
VIEJA = b"firefox-default\0"
NUEVA = MARCA.encode() + b"\0" * (len(VIEJA) - len(MARCA))
def rebrandear_binario(rel):
ruta = os.path.join(APPDIR, rel)
with open(ruta, "rb") as fh:
datos = fh.read()
n = datos.count(VIEJA)
if n != 1:
fatal(f"{rel}: esperaba 1 ocurrencia de {VIEJA!r} y hay {n} — ¿cambió upstream?")
modo = os.stat(ruta).st_mode
with open(ruta, "wb") as fh:
fh.write(datos.replace(VIEJA, NUEVA))
os.chmod(ruta, modo)
with open(ruta, "rb") as fh:
if fh.read().count(VIEJA) != 0:
fatal(f"{rel}: el parche no agarró")
return f"{rel}: app_id firefox-default → {MARCA}"
def main():
huella = huella_overlay()
bid = build_id(huella)
@@ -261,12 +297,16 @@ def main():
)
iconos = escribir_iconos()
binarios = renombrar_binarios()
# Después del renombrado: los ficheros ya se llaman atuq/atuq-bin.
parches = [rebrandear_binario(MARCA), rebrandear_binario(f"{MARCA}-bin")]
print(f"rebrand: overlay {huella[:16]}… ⇒ BuildID {bid}")
print(f"rebrand: application.ini {sorted(claves)}")
print(f"rebrand: browser/omni.ja re-empacado, {n} entradas, orden y STORED preservados")
print(f"rebrand: {len(iconos)} iconos escritos ({', '.join(str(s) for s in TAMANOS)} px)")
print(f"rebrand: binarios {', '.join(binarios)} (+ symlink firefox → {MARCA})")
for l in parches:
print(f"rebrand: {l}")
main()
+4 -2
View File
@@ -33,8 +33,10 @@ URL="${URL:-about:support}"
# Las raíces: atuq y lo que su motor abre en RUNTIME. `wayland-protocols` y compañía no están —son
# de build— y meterlas engordaría el rootfs sin cambiar nada de lo que se ve.
RAICES="atuq gtk3 atk gdk-pixbuf pango cairo libepoxy glib-shared pcre2-shared libffi-shared
zlib-shared harfbuzz fribidi freetype-shared fontconfig-shared pixman libpng-shared
# Las variantes `-shared` y NO las estáticas: en runtime una `.a` no sirve para nada, y son las que
# gtk3 declara NEEDED desde que se arregló el cuadro de las dos Pango.
RAICES="atuq gtk3 atk gdk-pixbuf-shared pango-shared cairo-shared libepoxy glib-shared pcre2-shared
libffi-shared zlib-shared harfbuzz-shared fribidi freetype-shared fontconfig-shared pixman libpng-shared
libjpeg-turbo-shared wayland libxkbcommon mesa libdrm dbus pipewire pulseaudio alsa-lib
libxml2-shared dejavu-fonts
xkeyboard-config"