1# Boot test: GNOME bajo Ente #0 (sin systemd)
2
3Procedimiento para verificar que GNOME 45+ arranca con `ente-zero` como
4PID 1 y los 8 D-Bus shims (logind, hostnamed, timedated, localed,
5journald, resolved, polkit, machined) cubren las llamadas que el
6escritorio realiza durante la sesión.
7
8## Qué se prueba
9
101. **PID 1 boot**: el kernel arranca, mounta initramfs, transfiere control
11 a `/init` que es `ente-zero` con la Card Semilla.
122. **Genesis spawning**: ente-zero encarna el bus D-Bus (dbus-daemon),
13 los 8 compat-shims, NetworkManager, y gdm/sddm (display manager).
143. **D-Bus interception**: los compat-shims toman los nombres
15 `org.freedesktop.{logind,hostname1,timedate1,locale1,resolve1,
16 PolicyKit1,machine1}` antes que cualquier sondeo de systemd.
174. **GNOME session**: gdm autenticación → GNOME shell → settings panels
18 funcionan (Region & Language, Date & Time, About, Network).
19
20## Prerequisitos
21
22- QEMU (`qemu-system-x86_64`) con KVM.
23- Imagen base con kernel + GNOME instalados — sugerencia: una Arch Linux
24 o Fedora minimal modificada (más abajo). NixOS también es razonable.
25- ~10 GiB libre.
26
27## Esqueleto del rootfs
28
29`scripts/build-rootfs.sh` genera un overlay sobre una imagen base que:
30
311. Compila el workspace en modo release (`cargo build --workspace --release`)
322. Copia los binarios a `<rootfs>/usr/local/bin/`:
33 - `ente-zero`
34 - `ente-{logind,hostnamed,timedated,localed,journald,resolved,polkit,machined}-compat`
35 - `ente-echo`, `brainctl`, `busctl`, `ente-journalctl`
363. Renombra el `/init` original a `/sbin/init.systemd` (backup)
374. Symlink `/init` → `/usr/local/bin/ente-zero`
385. Coloca la Card Semilla en `/ente/seed.card.k`
396. Desinstala los services systemd que ahora son shims (logind, etc) o
40 los enmascara con `systemctl mask` (en la imagen base, antes de
41 reescribir `/init`)
42
43## Card Semilla para el boot test
44
45`/ente/seed.card.k` debe declarar como genesis los Entes esenciales:
46- D-Bus daemon (`/usr/bin/dbus-daemon --system`)
47- Los 8 compat-shims
48- NetworkManager
49- udev daemon (kernel events ya manejados por nuestro Netlink stream;
50 udev añade reglas de userspace — opcional)
51- gdm o sddm
52
53Ejemplo mínimo:
54
55```kcl
56import .card
57
58seed = EntityCard {
59 schema_version = 1
60 id = "01KQ_BOOT_SEED_GNOME_TEST_0"
61 label = "boot-gnome-test"
62 provides = [
63 Capability {kind = "Spawn"}
64 Capability {kind = "Journal"}
65 ]
66 soma = SomaSpec {}
67 payload = Payload {kind = "Virtual"}
68 supervision = Supervision {kind = "OneShot"}
69 genesis = [
70 # dbus-daemon — todo lo demás depende de él.
71 EntityCard {
72 schema_version = 1
73 id = "01KQ_BOOT_DBUS_DAEMON__________"
74 label = "dbus-daemon"
75 soma = SomaSpec {}
76 payload = Payload {
77 kind = "Native"
78 exec = "/usr/bin/dbus-daemon"
79 argv = ["--system", "--nofork"]
80 }
81 supervision = Supervision {
82 kind = "Restart"
83 initial_ms = 100
84 max_ms = 30000
85 }
86 }
87 # Aquí los 8 compat-shims (mismo patrón) ...
88 # Aquí gdm o sddm ...
89 ]
90}
91```
92
93## Boot
94
95```bash
96scripts/run-vm.sh /path/to/base.qcow2 /path/to/built-rootfs.iso
97```
98
99QEMU arranca con:
100- `-kernel` el kernel de la imagen base
101- `-initrd` (opcional) si la imagen no es bootable directa
102- `-append "init=/usr/local/bin/ente-zero rd.break=initqueue"` para
103 redirigir PID 1 desde el initramfs.
104- `-display gtk,gl=on` para ver la sesión gráfica.
105
106## Verificaciones
107
108### Console
109- ente-zero arranca como PID 1 (`/proc/1/comm` == `ente-zero`).
110- Genesis instancia los 8 shims: logs `Ente encarnado label=compat-X`.
111- D-Bus daemon responde: `busctl list` muestra los nombres tomados por
112 los shims (deberían aparecer como `org.freedesktop.X1`).
113
114### gdm
115- Llega al greeter — significa que polkit, logind, hostnamed responden.
116- Login funciona — verifica que `Inhibit`, `CreateSession`, `ListSessions`
117 no bloquean la pila de PAM.
118
119### GNOME shell
120- Settings → About: hostname y OS info pobladas (hostnamed properties).
121- Settings → Date & Time: timezone correcta (timedated).
122- Settings → Region & Language: locale actual visible (localed).
123- Settings → Network: NetworkManager opera, los DNS lookups funcionan
124 (resolved).
125- "Restart" en menú: invoca `org.freedesktop.login1.Reboot` → llega a
126 nuestro stub → log en journal.
127
128### Journal
129- `ente-journalctl --tail 100` muestra mensajes capturados durante el boot.
130- Filtros `--unit gdm.service` y `--source syslog` funcionan.
131
132## Limitaciones conocidas
133
134- **systemd-units**: GNOME no usa systemd unit files directamente, pero
135 algunas apps los crean dinámicamente (e.g., gnome-terminal con
136 `systemd-run --user`). Esas calls fallarán con NotSupported y la app
137 caerá a un fallback no-systemd.
138- **sd_notify**: services que usan `Type=notify` para anunciar readiness
139 fallan silenciosamente (NOTIFY_SOCKET no se setea). Reemplazables con
140 `Type=simple` y nuestro Supervision::Restart.
141- **systemd-tmpfiles**: tmpfiles.d no se procesa. Aplicar manualmente
142 o portar el comportamiento a un Ente.
143- **systemd journal binary export**: nuestro journal usa CAS por hash,
144 no el formato `.journal` binario. Apps que llamen
145 `journalctl --output=export` no son compatibles. `ente-journalctl`
146 cubre los casos típicos.
147
148## Plan de regresión
149
150Hacer boot test en CI tras cada cambio en los compat-shims:
151
1521. `cargo build --workspace --release`
1532. `scripts/build-rootfs.sh` (overlay sobre imagen base inmutable)
1543. `scripts/run-vm.sh --headless --timeout 120` con script de comprobación
155 automatizado (xdotool o similar, o screen-shotting).
1564. Capturar `dmesg` + `ente-journalctl` outputs como artefactos.
157
158Output esperado en stdout del test:
159```
160PASS: ente-zero como PID 1
161PASS: 8 compat-shims encarnados
162PASS: gdm greeter mostrado
163PASS: settings panels operativos
164```
gnome-boot-test.md
Boot test: GNOME bajo Ente #0 (sin systemd)
Procedimiento para verificar que GNOME 45+ arranca con ente-zero como
PID 1 y los 8 D-Bus shims (logind, hostnamed, timedated, localed,
journald, resolved, polkit, machined) cubren las llamadas que el
escritorio realiza durante la sesión.
Qué se prueba
- PID 1 boot: el kernel arranca, mounta initramfs, transfiere control
a
/init que es ente-zero con la Card Semilla.
- Genesis spawning: ente-zero encarna el bus D-Bus (dbus-daemon),
los 8 compat-shims, NetworkManager, y gdm/sddm (display manager).
- D-Bus interception: los compat-shims toman los nombres
org.freedesktop.{logind,hostname1,timedate1,locale1,resolve1, PolicyKit1,machine1} antes que cualquier sondeo de systemd.
- GNOME session: gdm autenticación → GNOME shell → settings panels
funcionan (Region & Language, Date & Time, About, Network).
Prerequisitos
- QEMU (
qemu-system-x86_64) con KVM.
- Imagen base con kernel + GNOME instalados — sugerencia: una Arch Linux
o Fedora minimal modificada (más abajo). NixOS también es razonable.
- ~10 GiB libre.
Esqueleto del rootfs
scripts/build-rootfs.sh genera un overlay sobre una imagen base que:
- Compila el workspace en modo release (
cargo build --workspace --release)
- Copia los binarios a
<rootfs>/usr/local/bin/:
ente-zero
ente-{logind,hostnamed,timedated,localed,journald,resolved,polkit,machined}-compat
ente-echo, brainctl, busctl, ente-journalctl
- Renombra el
/init original a /sbin/init.systemd (backup)
- Symlink
/init → /usr/local/bin/ente-zero
- Coloca la Card Semilla en
/ente/seed.card.k
- Desinstala los services systemd que ahora son shims (logind, etc) o
los enmascara con
systemctl mask (en la imagen base, antes de
reescribir /init)
Card Semilla para el boot test
/ente/seed.card.k debe declarar como genesis los Entes esenciales:
- D-Bus daemon (
/usr/bin/dbus-daemon --system)
- Los 8 compat-shims
- NetworkManager
- udev daemon (kernel events ya manejados por nuestro Netlink stream;
udev añade reglas de userspace — opcional)
- gdm o sddm
Ejemplo mínimo:
import .card
seed = EntityCard {
schema_version = 1
id = "01KQ_BOOT_SEED_GNOME_TEST_0"
label = "boot-gnome-test"
provides = [
Capability {kind = "Spawn"}
Capability {kind = "Journal"}
]
soma = SomaSpec {}
payload = Payload {kind = "Virtual"}
supervision = Supervision {kind = "OneShot"}
genesis = [
# dbus-daemon — todo lo demás depende de él.
EntityCard {
schema_version = 1
id = "01KQ_BOOT_DBUS_DAEMON__________"
label = "dbus-daemon"
soma = SomaSpec {}
payload = Payload {
kind = "Native"
exec = "/usr/bin/dbus-daemon"
argv = ["--system", "--nofork"]
}
supervision = Supervision {
kind = "Restart"
initial_ms = 100
max_ms = 30000
}
}
# Aquí los 8 compat-shims (mismo patrón) ...
# Aquí gdm o sddm ...
]
}
Boot
scripts/run-vm.sh /path/to/base.qcow2 /path/to/built-rootfs.iso
QEMU arranca con:
-kernel el kernel de la imagen base
-initrd (opcional) si la imagen no es bootable directa
-append "init=/usr/local/bin/ente-zero rd.break=initqueue" para
redirigir PID 1 desde el initramfs.
-display gtk,gl=on para ver la sesión gráfica.
Verificaciones
Console
- ente-zero arranca como PID 1 (
/proc/1/comm == ente-zero).
- Genesis instancia los 8 shims: logs
Ente encarnado label=compat-X.
- D-Bus daemon responde:
busctl list muestra los nombres tomados por
los shims (deberían aparecer como org.freedesktop.X1).
gdm
- Llega al greeter — significa que polkit, logind, hostnamed responden.
- Login funciona — verifica que
Inhibit, CreateSession, ListSessions
no bloquean la pila de PAM.
GNOME shell
- Settings → About: hostname y OS info pobladas (hostnamed properties).
- Settings → Date & Time: timezone correcta (timedated).
- Settings → Region & Language: locale actual visible (localed).
- Settings → Network: NetworkManager opera, los DNS lookups funcionan
(resolved).
- "Restart" en menú: invoca
org.freedesktop.login1.Reboot → llega a
nuestro stub → log en journal.
Journal
ente-journalctl --tail 100 muestra mensajes capturados durante el boot.
- Filtros
--unit gdm.service y --source syslog funcionan.
Limitaciones conocidas
- systemd-units: GNOME no usa systemd unit files directamente, pero
algunas apps los crean dinámicamente (e.g., gnome-terminal con
systemd-run --user). Esas calls fallarán con NotSupported y la app
caerá a un fallback no-systemd.
- sd_notify: services que usan
Type=notify para anunciar readiness
fallan silenciosamente (NOTIFY_SOCKET no se setea). Reemplazables con
Type=simple y nuestro Supervision::Restart.
- systemd-tmpfiles: tmpfiles.d no se procesa. Aplicar manualmente
o portar el comportamiento a un Ente.
- systemd journal binary export: nuestro journal usa CAS por hash,
no el formato
.journal binario. Apps que llamen
journalctl --output=export no son compatibles. ente-journalctl
cubre los casos típicos.
Plan de regresión
Hacer boot test en CI tras cada cambio en los compat-shims:
cargo build --workspace --release
scripts/build-rootfs.sh (overlay sobre imagen base inmutable)
scripts/run-vm.sh --headless --timeout 120 con script de comprobación
automatizado (xdotool o similar, o screen-shotting).
- Capturar
dmesg + ente-journalctl outputs como artefactos.
Output esperado en stdout del test:
PASS: ente-zero como PID 1
PASS: 8 compat-shims encarnados
PASS: gdm greeter mostrado
PASS: settings panels operativos