feat(ente-zero): enchufa el handshake server al Init real
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>
This commit is contained in:
@@ -21,3 +21,8 @@ tracing = { workspace = true }
|
||||
[dev-dependencies]
|
||||
tempfile = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
|
||||
[[example]]
|
||||
name = "probe"
|
||||
path = "examples/probe.rs"
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
//! probe — herramienta de diagnóstico del handshake.
|
||||
//!
|
||||
//! Conecta a un Init brahman vivo, hace handshake, un ping, y se va.
|
||||
//! Ruta del socket: `$BRAHMAN_INIT_SOCKET` o el default
|
||||
//! ([`brahman_handshake::transport::default_socket_path`]).
|
||||
//!
|
||||
//! Uso:
|
||||
//! ```sh
|
||||
//! cargo run -p brahman-handshake --example probe
|
||||
//! ```
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use brahman_card::{Card, Payload, Supervision, CARD_SCHEMA_VERSION};
|
||||
use brahman_handshake::{client::Client, transport};
|
||||
use ulid::Ulid;
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let card = Card {
|
||||
schema_version: CARD_SCHEMA_VERSION,
|
||||
id: Ulid::new(),
|
||||
label: "brahman-probe".into(),
|
||||
payload: Payload::Virtual,
|
||||
supervision: Supervision::OneShot,
|
||||
provides: BTreeSet::new(),
|
||||
requires: BTreeSet::new(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let path = transport::default_socket_path();
|
||||
println!("connecting to {}", path.display());
|
||||
|
||||
let mut client = Client::connect(&path, card).await?;
|
||||
let info = client.server_info();
|
||||
println!(
|
||||
" HelloAck: session={} server={} protocol={} init_attached={}",
|
||||
client.session(),
|
||||
info.server_version,
|
||||
info.protocol_version,
|
||||
info.init_attached
|
||||
);
|
||||
|
||||
let ts = client.ping().await?;
|
||||
println!(" Pong: ts={}ms", ts);
|
||||
|
||||
client.farewell().await?;
|
||||
println!(" Farewell OK");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -21,6 +21,7 @@ pub mod codec;
|
||||
pub mod messages;
|
||||
pub mod server;
|
||||
pub mod client;
|
||||
pub mod transport;
|
||||
|
||||
pub use brahman_card::PROTOCOL_VERSION;
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
//! Convenciones de transporte: dónde vive el socket del Init.
|
||||
//!
|
||||
//! Resolución del path canónico:
|
||||
//! 1. Variable de entorno [`SOCKET_ENV`] si está definida (override
|
||||
//! explícito, prioridad máxima).
|
||||
//! 2. `$XDG_RUNTIME_DIR/brahman-init.sock` (sesión usuario).
|
||||
//! 3. `$TMPDIR/brahman-init.sock` (fallback portable).
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Variable de entorno que sobreescribe la ruta del socket del Init.
|
||||
pub const SOCKET_ENV: &str = "BRAHMAN_INIT_SOCKET";
|
||||
|
||||
/// Nombre del socket dentro del runtime dir.
|
||||
pub const SOCKET_NAME: &str = "brahman-init.sock";
|
||||
|
||||
/// Ruta canónica al socket del Init brahman.
|
||||
pub fn default_socket_path() -> PathBuf {
|
||||
if let Ok(p) = std::env::var(SOCKET_ENV) {
|
||||
return PathBuf::from(p);
|
||||
}
|
||||
let base = std::env::var_os("XDG_RUNTIME_DIR")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(std::env::temp_dir);
|
||||
base.join(SOCKET_NAME)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn env_override_wins() {
|
||||
// Nota: estos tests modifican entorno del proceso. `cargo test`
|
||||
// los corre paralelos por defecto pero usamos un nombre de var
|
||||
// único y restablecemos al final.
|
||||
let key = "BRAHMAN_INIT_SOCKET_TEST_OVERRIDE";
|
||||
// SAFETY: sólo escribimos una variable local al test; sin
|
||||
// contaminar SOCKET_ENV.
|
||||
std::env::set_var(key, "/tmp/explicit.sock");
|
||||
let saved = std::env::var(SOCKET_ENV).ok();
|
||||
std::env::set_var(SOCKET_ENV, "/tmp/explicit.sock");
|
||||
let p = default_socket_path();
|
||||
assert_eq!(p, PathBuf::from("/tmp/explicit.sock"));
|
||||
// Restaurar
|
||||
match saved {
|
||||
Some(v) => std::env::set_var(SOCKET_ENV, v),
|
||||
None => std::env::remove_var(SOCKET_ENV),
|
||||
}
|
||||
std::env::remove_var(key);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user