feat: Phase D-3 + D-4 — service_socket en Card, providers coexisten
Cierra el ciclo del swap automático Nous mock↔real:
- brahman-card: Card.service_socket: Option<PathBuf> y espejo en
WireCard. Path del data plane (distinto al Init). Cualquier
consumer que matchee con esta Card conecta directo, sin discovery
extra.
- brahman-broker: BrokeredCard propaga service_socket. Sin
participación en matching — sólo metadata.
- brahman-handshake::MatchEvent: nuevo campo
producer_service_socket. Server lo busca en BrokeredCard al emitir
Available.
- nouser-nous::transport: provider_socket_path(provider: &str)
devuelve nouser-nous-{provider}.sock por default. Mock y real
coexisten en sockets distintos (Phase D-4). default_socket_path()
conserva el comportamiento single-provider.
- Mock declara nouser-nous-mock.sock; real declara
nouser-nous-real.sock. La Card se construye DESPUÉS del bind.
- brahman-status imprime "socket:" por sesión cuando está presente.
Validación end-to-end:
$ ente-zero & nouser-nous-mock & nouser-nous-real &
$ ls /run/user/1001/nouser-nous-*.sock
nouser-nous-mock.sock
nouser-nous-real.sock
$ brahman-status
Sessions (2):
[ente] nouser.nous_real
socket: /run/user/1001/nouser-nous-real.sock
[ente] nouser.nous_mock
socket: /run/user/1001/nouser-nous-mock.sock
Pendiente (no crítico): nouser-core attract --remote usa todavía
NOUSER_NOUS_SOCKET hardcoded. Siguiente paso: subscribirse al
MatchEvent del broker y usar producer_service_socket directo, así
BRAHMAN_BROKER_CONTEXT=test/prod swapea provider sin tocar al
consumer.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -117,18 +117,32 @@ pub mod transport {
|
||||
/// Variable de entorno para sobreescribir la ruta del socket.
|
||||
pub const SOCKET_ENV: &str = "NOUSER_NOUS_SOCKET";
|
||||
|
||||
/// Nombre por default del socket dentro del runtime dir.
|
||||
/// Nombre genérico del socket cuando hay un solo proveedor.
|
||||
pub const SOCKET_NAME: &str = "nouser-nous.sock";
|
||||
|
||||
/// Ruta canónica al socket de Nous.
|
||||
/// Ruta canónica al socket cuando un único proveedor está activo
|
||||
/// (consumidores que no quieren elegir).
|
||||
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")
|
||||
runtime_base().join(SOCKET_NAME)
|
||||
}
|
||||
|
||||
/// Ruta default para un proveedor identificado (`"mock"`, `"real"`,
|
||||
/// etc). Permite que mock y real coexistan sin clash de socket.
|
||||
/// `NOUSER_NOUS_SOCKET` igual override esta función si está set.
|
||||
pub fn provider_socket_path(provider: &str) -> PathBuf {
|
||||
if let Ok(p) = std::env::var(SOCKET_ENV) {
|
||||
return PathBuf::from(p);
|
||||
}
|
||||
runtime_base().join(format!("nouser-nous-{}.sock", provider))
|
||||
}
|
||||
|
||||
fn runtime_base() -> PathBuf {
|
||||
std::env::var_os("XDG_RUNTIME_DIR")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(std::env::temp_dir);
|
||||
base.join(SOCKET_NAME)
|
||||
.unwrap_or_else(std::env::temp_dir)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user