Files
unibus/app.md
T

6.7 KiB

name, lang, domain, version, description, tags, uses_functions, uses_types, framework, entry_point, dir_path, repo_url, service, e2e_checks
name lang domain version description tags uses_functions uses_types framework entry_point dir_path repo_url service e2e_checks
unibus go infra 0.1.0 Bus de mensajería unificado sobre NATS+JetStream con cifrado E2E por room (megolm/olm reducido): service de membresía/claves, librería cliente y peers demo.
service
messaging
nats
e2e
generate_identity_go_cybersecurity
seal_aead_go_cybersecurity
open_aead_go_cybersecurity
seal_key_box_go_cybersecurity
open_key_box_go_cybersecurity
sign_ed25519_go_cybersecurity
verify_ed25519_go_cybersecurity
cmd/membershipd projects/message_bus/apps/unibus https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com/dataforge/unibus
port health_endpoint health_timeout_s systemd_unit systemd_scope restart_policy runtime pc_targets is_local_only
8470 /healthz 3 null null none manual
lucas-linux
true
id cmd timeout_s
build CGO_ENABLED=0 go build ./... 180
id cmd timeout_s
vet CGO_ENABLED=0 go vet ./... 120
id cmd timeout_s
unit CGO_ENABLED=0 go test ./... 180
id cmd health timeout_s
smoke CGO_ENABLED=0 go build -o /tmp/unibus_membershipd ./cmd/membershipd && /tmp/unibus_membershipd --http-port 18470 --nats-port 14222 --db /tmp/unibus_smoke.db --store-dir /tmp/unibus_blobs --nats-store /tmp/unibus_js & http://127.0.0.1:18470/healthz 30

Qué es

unibus es un bus de mensajería unificado sobre NATS + JetStream. Una capa fina encima de NATS aporta lo que NATS no tiene: membresía de rooms, invitaciones con reparto de clave, y cifrado extremo a extremo (E2E) del payload por room, con rotación de clave activa (forward secrecy) al expulsar a un miembro.

Todos los participantes —procesos/workers, interfaces de chat humanas, agentes LLM— son peers de primera clase que hablan el mismo protocolo y se diferencian solo por las rooms a las que se unen y por lo que hacen con lo que reciben.

Piezas

Componente Ruta Rol
membershipd cmd/membershipd Service (control plane): metadata de rooms, directorio de miembros, reparto de claves selladas, object store de media. Arranca NATS embebido si no se pasa --nats-url.
librería cliente pkg/client La API que consume cualquier peer. Crear/unirse a rooms, invitar, publicar/suscribir, request/reply, kick con rotación de clave, media cifrada.
worker cmd/worker Peer demo: publica un contador incremental cada segundo a una room cleartext.
chat cmd/chat Peer demo: suscriptor en vivo (modo simple) + demo de cifrado E2E y forward secrecy (--demo-encrypted).

Dos planos

  • Control plane: HTTP autoritativo en membershipd. Quién está en cada room, sus claves públicas, y la clave de room K sellada por epoch para cada miembro.
  • Data plane: NATS. Los mensajes (frames) viajan por subject; los blobs de media NO viajan por el bus, se cifran y se suben al object store, y por NATS solo viaja una referencia (hash + nonce).

Criptografía (importada del registry, NO reescrita)

El cifrado E2E se compone de las 7 primitivas del capability group e2e-messaging (docs/capabilities/e2e-messaging.md), importadas del paquete fn-registry/functions/cybersecurity. Esta app no reimplementa ninguna primitiva criptográfica.

Ejemplo

Demo end-to-end con go run (NATS embebido, nada que instalar):

cd projects/message_bus/apps/unibus

# 1. Service de membresía/claves (NATS embebido en :4250, HTTP en :8470)
go run ./cmd/membershipd

# 2. En otra terminal: peer publicador (proceso) — publica ticks cada 1s
go run ./cmd/worker

# 3. En otra terminal: peer suscriptor (chat humano) — imprime cada tick en vivo
go run ./cmd/chat

# 4. Demo de cifrado E2E + forward secrecy (contra el membershipd ya corriendo):
#    A crea room cifrada, invita a B, A publica (B descifra), A expulsa a B,
#    A publica de nuevo en el nuevo epoch (B ya NO puede descifrar).
go run ./cmd/chat --demo-encrypted

Para apuntar a un NATS externo en producción: --nats-url nats://host:4222 en membershipd, worker y chat.

Cuando usarla

  • Cuando necesites un tejido de mensajería donde procesos, humanos y agentes LLM sean peers uniformes (mismo protocolo, distinta política por room).
  • Cuando quieras rooms cifradas E2E con forward secrecy (paridad con Matrix) sin montar un Synapse: room.ModeMatrix.
  • Cuando quieras fan-out cleartext rápido para telemetría/coordinación de procesos: room.ModeNATS.
  • Como sustituto de la capa de transporte Matrix de agents_and_robots (fase posterior; v1 valida el bus de forma autónoma).

Gotchas

  • El service NO está endurecido (v1). No hay TLS, ni rate-limit, ni auth en las rutas GET de lectura. Confía en la red interna. Las rutas mutantes (/rooms, /invite, /rekey) sí exigen firma Ed25519 del owner sobre los bytes canónicos de la request. Endurecer es fase posterior.
  • Identidad = secreto crítico. El archivo de identidad (worker.id, chat.id) contiene las claves privadas (Ed25519 + X25519). Se escribe 0600. Perderlo = mensajes ilegibles, sin recuperación. Trátalo como una clave SSH.
  • Las rooms reciben un ULID fresco al crearse. No hay "crear o unirse por nombre": cada CreateRoom produce un room nuevo. Los peers demo cleartext comparten el subject (NATS enruta por subject), así que worker→chat funcionan aunque cada uno tenga su propio room id mapeado al mismo subject.
  • La media no viaja por el bus. PublishMedia cifra, sube al object store y publica solo un BlobRef. El receptor, si ve Frame.Blob != nil, descarga y descifra con FetchMedia. El frame de media NO lleva payload inline (su nonce vive en BlobRef.Nonce); Subscribe no intenta descifrar payloads vacíos.
  • Forward secrecy depende del rekey. Kick rota K a un epoch nuevo y la re-sella solo para los miembros restantes. El expulsado pierde acceso a los mensajes publicados después del kick, pero conserva los anteriores (las claves de epochs pasados no se borran: cifraban datos que ya podía leer).
  • NATS embebido escribe JetStream en disco. --nats-store apunta a local_files/jetstream; borrarlo resetea el historial persistido.
  • Build sin CGO. Usa el driver modernc.org/sqlite (pure-Go) y el paquete cybersecurity del registry compila limpio con CGO_ENABLED=0. NO requiere fts5 ni gcc.

Convención de subjects

proc.<svc>.<canal>        telemetría/coordinación de procesos (proc.test.ticks)
rpc.<svc>                 request/reply (rpc.indexer)
room.<grupo>              chat humano/grupo (room.general)
agent.<nombre>.{in,out}   inbox/outbox de agente LLM (agent.scout.in)