Base del DM/greeter de carmen. Contrato Authenticator agnóstico:
authenticate(usuario, secreto) -> UserInfo (uid/gid/home/shell).
PamAuthenticator verifica contra PAM (/etc/pam.d/carmen); MockAuthenticator
con credenciales en memoria para tests. AuthError grueso: BadCredentials
vs AccountUnavailable, sin filtrar existencia de cuentas. resolve_user
vía getpwnam. data/carmen como servicio PAM; ejemplo auth-probe.
11 tests; el camino PAM real se ejercita.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Opción B: RemoteEngine orquesta en un host remoto tunelando el wire
del daemon sobre un canal SSH direct-streamlocal hacia el sandokan.sock
remoto. El protocolo es idéntico al de DaemonEngine (postcard
length-prefixed) — sólo cambia el transporte, así que read_frame/
write_frame se reusan tal cual.
- brahman-ssh-multiplex: + SshSession::forward_unix — abre un canal
direct-streamlocal y devuelve su ChannelStream (AsyncRead+AsyncWrite).
- sandokan-daemon: protocol ahora pub, exporta read_frame/write_frame.
- sandokan-remote: RemoteEngine { SshSession + remote_socket }.
connect() o with_session(); cada operación abre un canal nuevo
(multiplexado sobre la conexión maestra).
- sandokan umbrella re-exporta RemoteEngine.
Completa Fase B: sandokan tiene Local + Daemon + Remote + auto().
cargo check --workspace verde. RemoteEngine necesita un host remoto
con `sandokan daemon` para validación runtime (sin unit test).
Opción A (text-parse del CLI por compat) queda pendiente por decisión
del usuario.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Envuelve russh 0.54 con una API mínima: una SshSession mantiene el
Handle maestro; cada exec() concurrente abre su propio canal en
paralelo sobre la misma conexión TCP (SSH multiplexa canales por
diseño del protocolo).
- SshConfig (host/port/user/auth/keepalive) + SshAuth (Password | Key).
- SshSession::connect — config russh + keepalive + auth password o
clave privada en disco; verificación de host key TOFU por default.
- SshSession::exec — corre un comando en un canal nuevo, junta
stdout/stderr/exit_code.
- SshSession es Clone barato (comparte el Handle).
Base de sandokan RemoteEngine y del Linker SSH de matilda.
Compila contra russh 0.54. El test de conexión real requiere un
servidor SSH (fuera del unit test).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- index — CardIndex: índice en memoria con filtros (by_label
case-insensitive substring, by_kind, providing por Capability, by_id).
- registry — scan_dir: carga toda Card *.json de un directorio,
saltando ruido y archivos rotos.
- discovery — CardDiscovery: une el índice local con la malla P2P;
announce_all publica las Cards locales al DHT, find_remote busca
proveedores. Modo local-only sin DHT también soportado.
Lo consumen el card-browser de nahual-shell y agorapura.
7 tests verdes. cargo check --workspace verde.
settings.local.json: defaultMode bypassPermissions (sesión desatendida).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
brahman-net corre un único Kademlia para todo el ecosistema.
brahman-dht le pone arriba un esquema de claves namespaced para que
distintos dominios coexistan sin colisión en la misma malla.
- key — RecordKind (Code/Card/Persona/Service/Custom) + DhtKey.
Wire: [kind_tag] ++ blake3(id) = 33 bytes longitud fija. Custom(n)
usa 0x80|n: nunca choca con los kinds estándar.
- Dht — wrapper sobre BrahmanNet: announce/withdraw/find (modelo de
provider records).
Consumidores: minga (Code), brahman-card-discovery (Card), agorapura
(Persona). 5 tests verdes (incl. smoke async sobre un nodo libp2p real).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El loader vivía partido: arje-brain/loader.rs cargaba EntityCards Y
Rules, mientras brahman-cards tenía su propia infra de card-loading.
Resolución por linaje:
- Card-loading (load_card_file, extract_card_from_json) → brahman-cards
(entity_loader.rs). Toda card-loading del ecosistema vive ahí.
- Rule-loading (load_rules_file, extract_rules_from_json) → arje-brain-rules
(loader.rs), junto a la definición de Rule.
- arje-brain/loader.rs eliminado.
arje-brain re-exporta ambos para compat de consumidores (arje-zero).
cargo check --workspace verde. Tests: 13 arje-brain-rules + 31 brahman-cards.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Errores detectados al auditar afirmaciones técnicas contra el código:
1. minga-vfs: NO está relacionado con Mónadas (esas son de akasha).
Es FUSE que proyecta el índice de minga (git semántico) como
filesystem, resolviendo paths virtuales a blobs por hash.
2. protocol/SDD.md: Card tiene 19 campos, no 6. Añadido bloque con
anatomía completa del struct.
3. STATUS.md: LOC por capa corregidos contra wc -l real
- protocol: 6,260 → 7,278
- init: ~3,600 → 4,301
- compat: ~5,000 → 3,435 (estaba sobrestimado)
4. pineal: 6 stubs (<30 LOC c/u), no 5. Export (23 LOC) también es
stub funcional. LOC reales por sub-crate documentados.
5. init/SDD.md: ente-soma es wrapper de 44 LOC, no ~30.
6. akasha/SDD.md: fastembed está detrás de feature `embeddings`,
ort es transitivo. Sin feature, akasha-nous-real es stub mínimo.
7. vista/barra: LOC ajustados (vista-core 177, barra-core 108).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>