ente-zero (PID 1 del fractal arje) ahora levanta el server de
brahman-handshake junto al ente-bus existente, escuchando en
\$BRAHMAN_INIT_SOCKET (default \$XDG_RUNTIME_DIR/brahman-init.sock).
Es un canal paralelo dedicado a módulos brahman-conscientes que se
presentan con una Card y declaran flujos tipados.
Cambios:
- crates/core/brahman-handshake/src/transport.rs: helper nuevo con
resolución XDG_RUNTIME_DIR → TMPDIR, override por var de entorno
BRAHMAN_INIT_SOCKET. Test unitario para el override.
- crates/core/brahman-handshake/Cargo.toml: example "probe" + dev-dep
anyhow. Probe sirve como herramienta de diagnóstico para conectar
contra cualquier server vivo.
- crates/core/brahman-handshake/examples/probe.rs: cliente mínimo que
hace Hello → Ping → Farewell e imprime el HelloAck recibido.
- crates/core/ente-zero/Cargo.toml: dependencias brahman-handshake
+ brahman-broker.
- crates/core/ente-zero/src/main.rs: en primordial_loop, tras spawn
del ente-bus, crea Arc<Mutex<Broker>> compartido y llama
Server::bind. Si el bind falla (FS no escribible, socket en uso),
loggea y degrada a "modo bus-only" — la doctrina PID 1 no rompe por
subsistemas opcionales (mismo patrón que uevents).
Validación end-to-end manual:
$ BRAHMAN_INIT_SOCKET=/tmp/e2e.sock ./target/debug/ente-zero &
$ BRAHMAN_INIT_SOCKET=/tmp/e2e.sock cargo run --example probe
HelloAck: session=01KR41Q8... server=0.1.0 protocol=0.1.0 init_attached=true
Pong: ts=1778252489714ms
Farewell OK
Tests: 27/27 (broker 11 + card 8 + handshake codec+transport 2 + integ 6).
cargo check --workspace: 0 errores.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Crate nuevo en crates/core/brahman-handshake que implementa el handshake
real del shared_wit/protocol.wit como wire format Rust↔Rust sobre Unix
socket con frames length-prefixed + cuerpo postcard.
Componentes:
- src/messages.rs: Hello, HelloAck, Ping, Pong, Farewell, HandshakeError
y Frame (enum-suma). HandshakeError ya implementa thiserror::Error y
cruza el wire.
- src/codec.rs: write_frame / read_frame asíncronos con MAX_FRAME_BYTES
de 4 MiB. Test interno de roundtrip.
- src/server.rs: Server::bind crea el listener en Unix socket; emite
ResolvedCard tras validar la Card y devuelve ULID como SessionId.
ServerConfig.init_attached se reporta en HelloAck.
- src/client.rs: Client::connect hace pre-validación local de la Card
(fail fast), envía Hello, parsea HelloAck. ping() y farewell() expuestos.
- tests/handshake.rs: 4 tests de integración:
* full_handshake_roundtrip — happy path con 3 pings + farewell
* rejects_invalid_card_client_side — label vacío rechazado pre-envío
* server_rejects_protocol_mismatch — protocol_version 999.0.0 → Error
* ping_before_hello_rejected — Ping sin Hello previo → Rejected
Limitación conocida: postcard no serializa serde_json::Value (variantes
Array/Object con length dinámico). Se removieron por eso los campos
`extensions` (Card) y `extra` (Permissions). Forward-compat queda
cubierta por schema_version + protocol_version negotiation; si más
adelante necesitamos preservar campos JSON desconocidos, irá en un
WireCard separado o un envelope.
13/13 tests verdes (brahman-card 8 + brahman-handshake codec 1 + integ 4).
cargo check --workspace: 0 errores.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>