init.md
Changelog — init/
Init (PID 1) + encarnación Linux. Antes: core/ente-{zero,kernel,soma,snapshot} + shared/ente-incarnate.
feat(ente-zero): wire de Arje con brahman-net (red P2P opcional + identidad persistente)
Cierra el último pendiente del plan de red: Arje ahora puede arrancar
opcionalmente con BrahmanNet configurado, persistir su identidad
libp2p entre reboots, y participar en la malla brahman como nodo
público. Sin breaking changes: usuarios actuales (sin env vars) siguen
viendo el comportamiento Unix-only de antes.
Activación por env vars:
BRAHMAN_LISTEN_MULTIADDR— si set, activa la red P2P. Ej:/ip4/0.0.0.0/tcp/4101(público),/ip4/127.0.0.1/tcp/0(loopback, port aleatorio). Sin la var,brahman_net = Noney todo sigue como antes.BRAHMAN_KEYPAIR_PATH— override del path donde se persiste la keypair Ed25519 de identidad libp2p del nodo. Defaults sensatos:- PID 1 (root):
/var/lib/brahman/init-keypair.bin. - Dev mode:
$XDG_DATA_HOME/brahman/init-keypair.bin→$HOME/.local/share/brahman/init-keypair.bin→/tmp/brahman-init-keypair.bin(último recurso).
- PID 1 (root):
BRAHMAN_BOOTSTRAP_PEERS— lista coma-separada de multiaddrs para dial-ear al arranque y entrar al DHT. Sin esto, el nodo arranca aislado hasta que alguien se conecte a él.
Comportamiento al activarse:
keypair_store::load_or_generate(path)carga la keypair de disco o genera+persiste una nueva (32 bytes raw, permisos 0o600, atomic rename). Reboots conservan elpeer_id.BrahmanNet::with_keypair(kp)arma el swarm con esa identidad.net.listen(multiaddr)espera dirección resuelta y la loggea.BRAHMAN_BOOTSTRAP_PEERS(si set) → dial a cada multiaddr.- El handshake server se levanta con
ServerConfig.net = Some(net), que activaannounce_outputsautomático en el DHT por cada Card con outputs. - Además del Unix accept loop (existing), se monta un libp2p accept
loop sobre el mismo
Servercompartido. Sesiones locales y remotas conviven en las mismas tablas (sessions, push_table, broker, last_matches).
Refactor del Unix accept loop: antes consumía el server vía
server.run().await; ahora usa Arc<Server>::accept_one().await en
loop para coexistir con el libp2p accept loop sin moverse el server.
Degradación grácil en cada paso: si la keypair no carga, si el multiaddr es inválido, si el listen falla, si el bootstrap dial revienta — loggeamos y seguimos en modo Unix-only. La doctrina de PID 1 ("ningún subsistema opcional rompe el bucle primordial") se mantiene.
Tests: 4 unit en keypair_store:
generate_persist_and_reload_yields_same_peer_id— peer_id estable across reloads (la propiedad fundamental).rejects_corrupted_file— archivo de tamaño incorrecto rechazado.persisted_file_is_owner_only— permisos 0o600 verificados.default_path_honors_env—BRAHMAN_KEYPAIR_PATHoverride respeta tanto dev como root mode.
Ente-zero compila clean. Ningún test del workspace regresa.
Lo que esto desbloquea hoy:
- Para activar Arje como nodo público, basta:
BRAHMAN_LISTEN_MULTIADDR=/ip4/0.0.0.0/tcp/4101 ente-zero - Cualquier consumer (en otra máquina) puede luego dial-ar a ese multiaddr + descubrir Cards anunciadas via DHT + abrir handshake remoto firmado.
- La identidad del nodo (su
peer_id) sobrevive reboots, así que los nodos remotos pueden cachear "este peer_id es Arje en máquina X" sin invalidarse cada vez.
Pendientes futuros:
stop_providingal cleanup de sesión (records DHT con TTL ~24h).- Allowlist/Denylist de peers (PKI explícito).
- Rotación de keypair sin perder peer_id (multi-key identity).