Con el arreglo de llimghi sellado, el guardián de metal pasó de la A a la D:
A ✓ sin la app dueña, el host contesta locked:true (y con ok:true, que es la trampa)
B ✓ con la app, vault.status dice ABIERTA — el socket sube en 1 s
C ✓ el diálogo ABRE en el compositor y se lo CONTESTA: «1» ⇒ yes, «2» ⇒ no (los dos sentidos)
D ✓ vault.save con consentimiento real guarda, y vault.match la encuentra SIN contraseña
E ✗ el navegador pide la contraseña y no llega nunca
La E destapó un fallo que no es de atuq ni de llimphi: el dueño de la bóveda atendía de a UN cliente
—`atender_cliente` no vuelve hasta que el cliente se va, y se lo llamaba en el hilo del accept—, así
que la primera conexión se quedaba con él mientras viviera. Y el caso normal es ése: Gecko lanza un
`puriy-costura` por PUERTO, ocho en atuq, y todos conectan al arrancar. La extensión de la bóveda
mandaba `vault.match` y no volvía nunca: sin insignia, sin log y sin error, indistinguible de «este
sitio no tiene contraseñas».
Control sin navegador, en los dos sentidos: un solo cliente contesta en milisegundos; con otro host
conectado y quieto, la misma pregunta queda colgada y la mata el timeout a los 30 s.
Arreglado en tawasuyu (`cf3540460`, un hilo por conexión; los diálogos los serializa ahora el Mutex
de la bóveda) con su test de regresión, que además cazó que el arreglo obvio —clonar el Dueno— borra
el socket en el Drop del primer hilo que termina. Los siete tests que ya había no podían ver el fallo:
abrían un cliente por vez, que es justo lo que producción nunca hace.
⚠ Y subir el pin volvió a chocar con el `Cargo.lock` abierto de tawasuyu. Lo que importa para la
próxima es CUÁL operación lo cierra: `cargo metadata` sin `--locked` da **1 línea** de diff y cero
checksums movidos; `cargo generate-lockfile` da 6.305 líneas y 750 checksums, e invalidaría el
vendoreo de todos. Publicado en `b80f7567c` con índice temporal (estaba MM).
Del lado del guardián, tres cosas que salieron de fallar:
· el contestador INSISTE hasta que la ventana se va — con el mismo `wtype rc=0`, una corrida
contestaba y otra volvía `denied`: la ventana entra al árbol del compositor antes de que llimphi
tenga el teclado enganchado, y un sleep más largo sólo mueve el borde;
· el contestador busca la ventana POR PATRÓN: con el navegador abierto, teclear «la enfocada» le
contestaría a la página, y eso es un sí que nadie dio;
· la sonda del chrome mira `isShownForTab` y la insignia ANTES de apretar — `triggerClickOrPopup`
sale por la puerta de atrás si la acción no está mostrada, y un click que no llega se ve igual que
una bóveda que no contesta. (Y `WebExtensionPolicy` no es global en el scope de una ventana: sale
del módulo. Eso costó una corrida.)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
102 lines
6.7 KiB
TOML
102 lines
6.7 KiB
TOML
# boveda — la app de la bóveda de la suite, y **el dueño único** de su base (SDD-BOVEDA §8.5).
|
|
#
|
|
# ── POR QUÉ ESTA RECETA, Y POR QUÉ RECIÉN AHORA (2026-09-18) ────────────────────────────────────
|
|
# `atuq` trae desde el 2026-09-15 la extensión `boveda@atuq.tawasuyu` —la décima— y desde el
|
|
# 2026-09-16 el host `puriy-costura` pineado a un commit que SÍ atiende `vault.*`. Con eso el SDD 26
|
|
# (§7.quinquies.bis) dio la unidad 12 por destrabada y anunció que «ahora sí se puede escribir el
|
|
# guardián de metal porque hay con qué correrlo».
|
|
#
|
|
# ⚠ **Y no había.** Medido contra el artefacto sellado, en esta máquina, con el binario que va en la
|
|
# imagen:
|
|
#
|
|
# ← {"id":2,"ok":true,"verb":"vault.status","locked":true,"count":0}
|
|
# ← {"id":3,"ok":true,"verb":"vault.match","locked":true,"items":[]}
|
|
# stderr: puriy-costura: sin bóveda (No such file or directory (os error 2)):
|
|
# los verbos vault.* dirán «cerrada»
|
|
#
|
|
# El host **nunca abre la bóveda por su cuenta, a propósito**: `sled` toma un lock exclusivo, y el
|
|
# proceso que lanza el navegador muere y revive con cada pestaña, así que no es un buen dueño de la
|
|
# base. El host le habla al DUEÑO por un socket… y el dueño no estaba en el corpus. O sea que la
|
|
# función que el navegador anuncia —insignia, `vault.match`, `vault.fill`— hoy contesta «cerrada»
|
|
# en las cuatro imágenes de escritorio, sin un solo error a la vista. Es exactamente la forma de
|
|
# fallo que el §7.quinquies describe: ficheros en orden, navegador sin la función.
|
|
#
|
|
# El dueño es ESTA app: abre la bóveda para su propia ventana y levanta el socket en un hilo para
|
|
# el navegador (`atender_al_navegador`), con políticas distintas de cada lado — sin preguntar a
|
|
# quien está mirando la ventana, preguntando SIEMPRE a lo que llega de afuera (`PorDialogo`, que
|
|
# lanza `shuma-pregunta`; ver `recipes/shuma-pregunta.toml`, sin la cual todo `vault.fill` se
|
|
# deniega).
|
|
#
|
|
# ── LA FORMA DE LA RECETA ──────────────────────────────────────────────────────────────────────
|
|
# Es una llimphi GUI del monorepo: el patrón es `mirada-greeter` (winit + wgpu/vello ⇒ `link =
|
|
# "dynamic"`, porque EGL/Vulkan/wayland se cargan por `dlopen` en runtime y `crt-static` lo
|
|
# impediría) sobre el pin `23a292863`, que es el que ya comparten `puriy-costura`, `shuma-*`,
|
|
# `pacha-*` y `tejido`: **un pin distinto es otro vendoreo de 2,4 G**, no un detalle de gusto.
|
|
name = "boveda"
|
|
version = "0.1.0"
|
|
license = "MPL-2.0"
|
|
|
|
[source]
|
|
# ⚠ El pin subió otra vez el 2026-09-18, a `b80f7567c` (el arreglo es `cf3540460`; el commit de
|
|
# arriba es el que además publica el `Cargo.lock` cerrado, sin el cual `cargo vendor --locked`
|
|
# no corre): el dueño de la bóveda atendía de a UN
|
|
# cliente y con el navegador abierto eso la deja MUDA (Gecko lanza un host por extensión, ocho, y
|
|
# todos se conectan al arrancar). SDD 26 §7.octies. Las dos recetas se mueven juntas para no pagar
|
|
# un tercer vendoreo de 2,4 G: comparten árbol por `<repo>-<sha>`.
|
|
# ⚠ EL PIN NO ES EL DE SUS HERMANAS, Y ES A PROPÓSITO (2026-09-18). Las demás recetas del monorepo
|
|
# están en `23a292863`; ésta apunta a `eed3120b6`, que es el commit donde llimphi aprende a pasarle
|
|
# el **display handle** a wgpu en el camino de escritorio. Con el pin viejo este binario sella,
|
|
# arranca y **no abre ventana**: wgpu cae a la plataforma EGL surfaceless, la surface no tiene un
|
|
# solo formato y la app panica con un «index out of bounds» que no nombra nada de esto (SDD 26
|
|
# §7.septies). El precio es un árbol de fuentes propio — otro vendoreo de 2,4 G, porque el árbol se
|
|
# comparte por `<repo>-<sha>`—; se paga hasta que las demás suban al mismo commit.
|
|
repo = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git"
|
|
commit = "b80f7567c189f0bcba988efb7b0c5c2049f9aca6"
|
|
# tawasuyu COMMITEA su propio `vendor/` (smithay parcheado por `[patch.crates-io]` POR RUTA); el
|
|
# `cargo vendor` de takana lo pisaría y el error hablaría de un crate cualquiera, no de esto.
|
|
# No entra en `hash_inputs`.
|
|
cargo_vendor_dir = ".hammer-cargo-vendor"
|
|
|
|
[build]
|
|
compiler = "zig-cc"
|
|
target = "x86_64-linux-musl"
|
|
link = "dynamic"
|
|
flags = ["-p", "pacha-boveda-llimphi", "--bin", "boveda"]
|
|
|
|
# Fase `compile` EXPLÍCITA —réplica de la que takana genera para Cargo— porque hay que inyectar
|
|
# `LOCKSTEP_XML_PATH` ANTES del build. La causa está escrita entera en `mirada-greeter.toml` y es
|
|
# la misma acá, con el mismo `accesskit_winit` 0.33 y el mismo `zbus-lockstep-macros` 0.5.2 en el
|
|
# lock: su `#[validate]` escanea el dir `xml/` de `atspi-common` llamando `.extension().expect()`
|
|
# en CADA entrada ⇒ PANICA en el subdirectorio `xml/schemas/`. Apuntando la variable a un dir con
|
|
# sólo los `.xml` se evita.
|
|
#
|
|
# ⚠ La ruta NO es `vendor/` como en `mirada-greeter`: con `cargo_vendor_dir` los crates vendoreados
|
|
# caen en `.hammer-cargo-vendor/`. Y la comprobación es a GRITOS: si mañana `atspi-common` deja de
|
|
# vendorearse ahí, un `cp` que falla en silencio dejaría la variable apuntando a un dir vacío y el
|
|
# panic volvería con el error lejos de la causa.
|
|
[build.phases]
|
|
compile = '''
|
|
set -e
|
|
XMLDIR="$PWD/.atspi-lockstep-xml"
|
|
mkdir -p "$XMLDIR"
|
|
ls .hammer-cargo-vendor/atspi-common/xml/*.xml >/dev/null 2>&1 || { echo "no hay .hammer-cargo-vendor/atspi-common/xml/*.xml — ¿cambió el vendoreo o la versión de atspi? sin esto zbus-lockstep-macros panica en xml/schemas/" >&2; exit 1; }
|
|
cp .hammer-cargo-vendor/atspi-common/xml/*.xml "$XMLDIR"/
|
|
export LOCKSTEP_XML_PATH="$XMLDIR"
|
|
printf '%s\n' '#!/bin/sh' 'for a do' 'case "$a" in --target=*) a=--target=x86_64-linux-musl ;; esac' 'set -- "$@" "$a"' 'shift' 'done' 'exec zig cc -mcpu=baseline "$@"' > "$PWD/.hammer-zig-cc"
|
|
chmod +x "$PWD/.hammer-zig-cc"
|
|
RF="-C linker=$PWD/.hammer-zig-cc"
|
|
rustc -vV | grep -q 'host: .*-alpine-' || RF="$RF -C link-self-contained=no"
|
|
CC="$PWD/.hammer-zig-cc" RUSTFLAGS="$RF" cargo rustc --release --locked --offline -p pacha-boveda-llimphi --bin boveda -- -C target-feature=-crt-static
|
|
'''
|
|
install = '''
|
|
set -e
|
|
test -x target/release/boveda || { echo "no hay target/release/boveda — ¿cambió el nombre del bin en pacha-boveda-llimphi?" >&2; exit 1; }
|
|
install -Dm755 target/release/boveda /out/usr/bin/boveda
|
|
'''
|
|
|
|
[deps]
|
|
# Las mismas que `mirada-greeter` menos `linux-pam` (eso era de `auth-core`, que esta app no usa:
|
|
# su segundo factor es `nakui-auth`, Rust puro). El stack gráfico se consulta en build-time por
|
|
# pkg-config y se carga por `dlopen` en runtime.
|
|
build = ["mesa", "wayland", "wayland-protocols", "libdrm", "expat", "zlib", "zstd", "libffi", "pkgconf"]
|