diff --git a/recipes/arje-logind-compat.toml b/recipes/arje-logind-compat.toml
index 95a1f148..fa13dd80 100644
--- a/recipes/arje-logind-compat.toml
+++ b/recipes/arje-logind-compat.toml
@@ -42,3 +42,38 @@ compiler = "zig-cc"
target = "x86_64-linux-musl"
link = "static"
flags = ["-p", "arje-compat", "--bin", "arje-logind-compat"]
+
+# ── La POLÍTICA D-Bus viaja con el artefacto, no con la imagen ──────────────────────────────────
+# El `system.conf` de dbus trae `` por defecto: cada servicio de sistema aporta su
+# propio fichero de política, y el de login1 normalmente lo instala systemd. Acá no hay systemd, así
+# que hasta hoy lo escribía `scripts/gnome/qemu-desktop-image.sh` — con un TODO al lado diciendo que
+# ése no era su lugar. Y no lo era: **un servicio que no puede adueñarse de su nombre no es un
+# servicio**, así que la política es parte de lo que este paquete PROMETE, igual que el binario.
+# Dejarla en el script de una imagen significaba que cualquier otra imagen —metal, KDE, mirada— tenía
+# el daemon y no podía usarlo.
+#
+# `allow own` sólo a root (es quien lo lanza) y `send_destination` a cualquiera, porque mutter y el
+# resto consultan login1 sin ser root.
+#
+# La fase `install` REPLICA el default del lab para Cargo (copiar los ejecutables de target/release a
+# /usr/bin) y le agrega el fichero. Sobrescribir la fase es la única forma: el default no tiene un
+# gancho para material extra.
+[build.phases]
+install = '''
+set -e
+mkdir -p /out/usr/bin /out/usr/share/dbus-1/system.d
+find target/release -maxdepth 1 -type f -perm -100 -exec cp {} /out/usr/bin/ \;
+cat > /out/usr/share/dbus-1/system.d/org.freedesktop.login1.conf <<'XML'
+
+
+
+
+
+
+
+
+
+
+XML
+'''
diff --git a/recipes/arje-polkit-compat.toml b/recipes/arje-polkit-compat.toml
index 4a72768d..d86291d3 100644
--- a/recipes/arje-polkit-compat.toml
+++ b/recipes/arje-polkit-compat.toml
@@ -49,3 +49,36 @@ compiler = "zig-cc"
target = "x86_64-linux-musl"
link = "static"
flags = ["-p", "arje-compat", "--bin", "arje-polkit-compat"]
+
+# ── La POLÍTICA D-Bus viaja con el artefacto ───────────────────────────────────────────────────
+# Misma razón que en arje-logind-compat: un servicio que no puede adueñarse de su nombre no es un
+# servicio, así que su política es parte de lo que el paquete promete. Hasta hoy la escribía el script
+# de la imagen de GNOME, con lo cual el shim existía para las otras imágenes y no servía en ellas.
+#
+# ⚠ EL NOMBRE `zz-` NO ES DECORATIVO. A diferencia de login1, acá el nombre YA TIENE política: la trae
+# el artefacto de `polkit`, y permite `own` sólo al usuario **polkitd** — este shim corre como root, así
+# que con ella sola se lo niegan. dbus lee `system.d` en ORDEN ALFABÉTICO y las reglas posteriores
+# ganan, de modo que un fichero que ordene después AÑADE el permiso sin descartar el resto de la
+# política de upstream (que además trae las reglas de `AuthenticationAgent`). Reescribir la de polkit
+# habría sido pisar un artefacto sellado.
+[build.phases]
+install = '''
+set -e
+mkdir -p /out/usr/bin /out/usr/share/dbus-1/system.d
+find target/release -maxdepth 1 -type f -perm -100 -exec cp {} /out/usr/bin/ \;
+cat > /out/usr/share/dbus-1/system.d/zz-arje-polkit-compat.conf <<'XML'
+
+
+
+
+
+
+
+
+
+
+
+XML
+'''
diff --git a/scripts/gnome/qemu-desktop-image.sh b/scripts/gnome/qemu-desktop-image.sh
index 0f169d37..be6e68e0 100755
--- a/scripts/gnome/qemu-desktop-image.sh
+++ b/scripts/gnome/qemu-desktop-image.sh
@@ -99,36 +99,22 @@ if [ -n "${ALC_BIN:-}" ] && [ -x "$ALC_BIN" ]; then
echo " ⚠ binario LOCAL (no sellado): $ALC_BIN"
elif ALC="${ALC:-store/$(./target/release/hammer --store store hash recipes/arje-logind-compat.toml 2>/dev/null | tail -1 | sed 's/^b3://')-arje-logind-compat}"; [ -d "$ALC" ]; then
install -Dm755 "$ALC"/usr/bin/arje-logind-compat "$MERGED"/usr/bin/arje-logind-compat
+ # …y su POLÍTICA D-Bus, que desde 2026-07-30 viaja en el artefacto. Se copia, no se escribe: el
+ # dueño del fichero es el paquete. Ojo — inyectar «sólo el binario» era el bug que destapó la
+ # comprobación de abajo: el artefacto traía el .conf y la imagen lo dejaba afuera.
+ install -d "$MERGED/usr/share/dbus-1/system.d"
+ cp -a --remove-destination "$ALC"/usr/share/dbus-1/system.d/. "$MERGED"/usr/share/dbus-1/system.d/ 2>/dev/null || true
echo " ✓ $(basename "$ALC" | cut -c1-12)"
else
echo " ✗ falta arje-logind-compat en store/ — mutter no hallará sesión" >&2; exit 1
fi
-echo "==> política D-Bus para org.freedesktop.login1"
-# Segundo muro del mismo eslabón: con el bus ya visible, dbus RECHAZA que el daemon se adueñe del
-# nombre — "not allowed to own the service org.freedesktop.login1 due to security policies". El
-# system.conf de dbus trae `` por defecto: cada servicio de sistema aporta su propio
-# fichero de política, y systemd normalmente instala el de login1. Acá no hay systemd, y el artefacto
-# de arje-logind-compat es sólo el binario ⇒ nadie pone la política. La escribimos: root puede
-# adueñarse del nombre, y cualquiera puede hablarle (mutter consulta login1 sin ser root).
-# TODO: esto pertenece al artefacto de arje-logind-compat, no a la imagen; acá está de forma
-# explícita para que se vea qué falta empaquetar del lado de arje.
+# La POLÍTICA D-Bus de login1 YA NO SE ESCRIBE ACÁ (2026-07-30): la trae el artefacto de
+# `arje-logind-compat`, que es su dueño. Este bloque tenía un TODO diciendo exactamente eso, y estaba
+# bien puesto: un servicio que no puede adueñarse de su nombre no es un servicio, así que su política
+# es parte de lo que el paquete promete. Teniéndola acá, cualquier OTRA imagen —metal, KDE, mirada—
+# se llevaba el daemon y no podía usarlo. Se comprueba abajo, junto con la de polkit.
install -d "$MERGED/usr/share/dbus-1/system.d"
-cat > "$MERGED/usr/share/dbus-1/system.d/org.freedesktop.login1.conf" <<'XML'
-
-
-
-
-
-
-
-
-
-
-XML
-chmod 644 "$MERGED/usr/share/dbus-1/system.d/org.freedesktop.login1.conf"
-echo " ✓ org.freedesktop.login1.conf"
echo "==> inyectando arje-polkit-compat (el PolicyKit1 del fractal) + su política"
# EL TERCER ESLABÓN DEL MISMO TIPO, y lo destapó la lista de nombres del bus: accounts-daemon y
@@ -139,40 +125,28 @@ echo "==> inyectando arje-polkit-compat (el PolicyKit1 del fractal) + su políti
# ⚠ El shim autoriza TODO (postura de sistema confiado ya tomada por arje) — ver su receta.
if APC="${APC:-store/$(./target/release/hammer --store store hash recipes/arje-polkit-compat.toml 2>/dev/null | tail -1 | sed 's/^b3://')-arje-polkit-compat}"; [ -d "$APC" ]; then
install -Dm755 "$APC"/usr/bin/arje-polkit-compat "$MERGED"/usr/bin/arje-polkit-compat
+ install -d "$MERGED/usr/share/dbus-1/system.d"
+ cp -a --remove-destination "$APC"/usr/share/dbus-1/system.d/. "$MERGED"/usr/share/dbus-1/system.d/ 2>/dev/null || true
echo " ✓ $(basename "$APC" | cut -c1-12)"
else
echo " ✗ falta arje-polkit-compat en store/ — accounts-daemon y upowerd no adquirirán su nombre" >&2
exit 1
fi
-# A DIFERENCIA de login1, acá el nombre YA tiene política: la trae el artefacto de `polkit`. Pero
-# permite `own` sólo al usuario **polkitd**, y nuestro shim corre como root ⇒ dbus se lo niega.
+# Su política tampoco se escribe acá: viaja en el artefacto (ver recipes/arje-polkit-compat.toml, que
+# explica por qué el fichero se llama `zz-` y no reemplaza al de polkit).
#
-# Se agrega un fichero APARTE en vez de reescribir el de polkit, por dos razones:
-# 1. dbus lee todo `system.d` en orden alfabético y las reglas posteriores ganan, así que un
-# `zz-…` añade el permiso sin descartar el resto de la política de upstream (que además trae las
-# reglas de `AuthenticationAgent`).
-# 2. **el fichero de polkit es un HARDLINK DE SÓLO LECTURA del store** — el rootfs fundido se arma
-# con hardlinks a los artefactos sellados, que están a 0444. Un `cat >` encima falla con
-# `Permission denied`, y eso ya rompió un build de esta imagen. Regla para este script: nunca
-# sobrescribir un fichero que venga de un artefacto; agregar al lado, o `rm -f` primero para
-# romper el enlace (y entonces se está pisando algo sellado, que es una decisión, no un descuido).
-cat > "$MERGED/usr/share/dbus-1/system.d/zz-arje-polkit-compat.conf" <<'XML'
-
-
-
-
-
-
-
-
-
-
-
-XML
-chmod 644 "$MERGED/usr/share/dbus-1/system.d/zz-arje-polkit-compat.conf"
-echo " ✓ zz-arje-polkit-compat.conf (añade own= para root sobre la política de polkit)"
+# ── COMPROBACIÓN, que es lo que reemplaza a escribirlas ────────────────────────────────────────
+# Mover algo a un artefacto sólo es una mejora si se NOTA cuando falta. Sin esto, un artefacto viejo
+# sin su .conf daría el mismo fallo tardío y confuso de antes: el daemon arranca, no adquiere el
+# nombre, y el escritorio espera 25 s por servicio sin decir por qué.
+for pol in org.freedesktop.login1.conf zz-arje-polkit-compat.conf; do
+ if [ -f "$MERGED/usr/share/dbus-1/system.d/$pol" ]; then
+ echo " ✓ $pol (del artefacto)"
+ else
+ echo " ✗ falta $pol — el artefacto que lo trae es viejo; re-sellá su receta" >&2
+ exit 1
+ fi
+done
echo "==> usuario messagebus (el system bus hace setuid a él)"
for f in passwd:messagebus:x:81:81:messagebus:/dev/null:/sbin/nologin group:messagebus:x:81:; do