feat(brahman-handshake): Fase 2 — discovery remoto via DHT por flow type

Tercer paso del plan "el encuentro entre Entes no se restringe a
local". Cuando un Init local acepta una sesion cuya Card declara
outputs, anuncia al DHT (Kademlia, via brahman-net) que el provee
esos flow types. Cualquier nodo conectado al mismo DHT puede
consultar y obtener la lista de PeerId's que sirven el flow.

API nueva en brahman_handshake::network:
- flow_dht_key(flow_name, type_ref) -> [u8; 32]: blake3 hash de
  "brahman-flow|v1|{flow}|{type_canon}". Determinista cross-host.
  Cambiar la canonicalizacion rompe compatibilidad — el prefijo v1
  documenta version del esquema y obliga a bump al modificar.
- announce_outputs(net, card): start_providing por cada flow.output.
  Idempotente, fire-and-forget.
- find_remote_providers(net, flow_name, type_ref) -> Vec<PeerId>:
  query DHT. Lista vacia si nadie anuncia.

Wire en el server:
- ServerConfig gana pub net: Option<Arc<BrahmanNet>>. Si esta set,
  cada Card registrada con outputs se anuncia automaticamente al DHT
  desde register_session. None = server "ciego al DHT".
- Debug manual de ServerConfig (BrahmanNet no es Debug).

Canonicalizacion del TypeRef:
- Primitive { name } -> "prim:{name}"
- Wit { package, interface, name } -> "wit:{package}#{interface_or_empty}#{name}"

Tests: 2 nuevos en tests/network_discovery.rs:
- dht_discovery_finds_remote_provider: 2 nodos, A registra Card con
  flow.output = monad-list:json, B dial-ea a A, B llama
  find_remote_providers y descubre el peer_id de A.
- dht_discovery_negative_unknown_flow: B busca flow inexistente,
  devuelve [] sin colgarse.

Callers actualizados con net: None: tests existentes + ente-zero
(arje aun no expone red; pasar Some(Arc<BrahmanNet>) cuando quiera
publicar al DHT remoto).

Lo que esto desbloquea: un nouser daemon en maquina A puede ser
descubierto por nouser-explorer en maquina B sin conocimiento previo
del peer — solo necesitan compartir DHT (via bootstrap inicial).

Pendiente para Fase 3: trust (firma Ed25519 en Cards remotas) +
stop_providing al cleanup de sesion.
This commit is contained in:
Sergio
2026-05-09 14:37:15 +00:00
parent 73dadbb166
commit 2059af4fb9
9 changed files with 412 additions and 4 deletions
+51
View File
@@ -6,6 +6,57 @@ ratio/diff ver `git show <sha>`.
## 2026-05-09
### feat(brahman-handshake): Fase 2 — discovery remoto vía DHT por flow type
Tercer paso del plan "el encuentro entre Entes no se restringe a
local". Cuando un Init local acepta una sesión cuya Card declara
outputs, anuncia al DHT (Kademlia, vía `brahman-net`) que él provee
esos flow types. Cualquier nodo conectado al mismo DHT puede
consultar y obtener la lista de `PeerId`s que sirven el flow.
API nueva en `brahman_handshake::network`:
- `flow_dht_key(flow_name, type_ref) -> [u8; 32]`: blake3 hash de
`"brahman-flow|v1|{flow}|{type_canon}"`. Determinístico cross-host.
Cambiar la canonicalización rompe compatibilidad — el prefijo `v1`
documenta la versión del esquema y obliga a bump al modificar.
- `announce_outputs(net, card)`: llama `start_providing` en el DHT
por cada `Flow` en `card.flow.output`. Idempotente, fire-and-forget.
- `find_remote_providers(net, flow_name, type_ref) -> Vec<PeerId>`:
query DHT por la key derivada. Lista vacía si nadie anuncia o si
la query no resuelve dentro del timeout interno de Kad.
Wire en el server:
- `ServerConfig` gana `pub net: Option<Arc<BrahmanNet>>`. Si está set,
cada Card registrada con outputs se anuncia automáticamente al DHT
desde `register_session`. `None` = server "ciego al DHT" (correcto
cuando no hay conectividad o el operador no quiere exponer).
- `ServerConfig` ahora tiene `Debug` manual (BrahmanNet no implementa
Debug; loggeamos sólo presencia/ausencia).
Canonicalización del TypeRef:
- `Primitive { name }``prim:{name}`
- `Wit { package, interface, name }``wit:{package}#{interface_or_empty}#{name}`
Tests: 2 nuevos en `tests/network_discovery.rs`:
- `dht_discovery_finds_remote_provider`: dos nodos, A registra Card
con `flow.output = monad-list:json`, B dial-ea a A y descubre el
`peer_id` de A vía `find_remote_providers`. Asserts contains.
- `dht_discovery_negative_unknown_flow`: B busca un flow que nadie
anunció, devuelve lista vacía sin colgarse.
Lo que esto desbloquea:
- Un `nouser daemon` corriendo en máquina A puede ser descubierto por
un `nouser-explorer` en máquina B sin conocimiento previo del peer
— sólo necesitan compartir DHT (vía bootstrap inicial).
- La cadena completa "explorer → daemon → llm-provider" puede cruzar
máquinas, no sólo procesos.
Lo que queda para Fase 3 (trust):
- Cards remotas se aceptan hoy sin verificación. Para producción se
necesita firma Ed25519 sobre la Card y verificación antes de
aceptar el Hello remoto. Local sigue confiando en SO_PEERCRED.
- Stop-providing al cleanup de sesión (hoy records DHT viven hasta
TTL ~24h aunque la sesión cierre).
### feat(brahman-handshake): Fase 1 — handshake brahman sobre stream libp2p
Segundo paso del plan "el encuentro entre Entes no se restringe a
local". El protocolo brahman (Hello / HelloAck / Ping / Pong /