# E2EE (End-to-End Encryption) en agents_and_robots ## Resumen Los bots Matrix usan E2EE via mautrix-go + cryptohelper para comunicarse de forma cifrada. La implementación usa Olm puro en Go (`-tags goolm`, sin CGO). ## Arquitectura ``` config.yaml (encryption section) ↓ agents/runtime.go → Agent.New() llama a InitCrypto() ↓ shell/matrix/client.go → InitCrypto() configura cryptohelper ↓ crypto.db (SQLite) — estado persistente de claves ↓ mautrix sync loop → cifrado/descifrado transparente ``` ## Qué guarda la crypto store (`crypto.db`) | Dato | Qué es | Cuándo se crea | Cuándo rota | |------|--------|----------------|-------------| | **Olm Account** | Par de claves Curve25519 del dispositivo | Al primer `Init()` | Nunca — es la identidad del dispositivo | | **One-time keys** | Claves efímeras para sesiones 1:1 | Al `Init()` y cuando se agotan | Automáticamente cuando hay < 50% disponibles | | **Megolm sessions** | Claves de grupo para rooms | Al unirse a un room E2EE | Cada ~100 mensajes o ~1 semana | | **Device list cache** | Claves públicas de otros dispositivos | Al hacer sync | Se actualiza con cada sync | | **Cross-signing keys** | Master, self-signing, user-signing | Al ejecutar `cmd/verify` | Manualmente | ## Pickle key El pickle key cifra el material criptográfico en la SQLite. Se configura por agente en `.env`: ```env PICKLE_KEY_ASSISTANT_BOT= ``` Y se referencia en `config.yaml`: ```yaml encryption: enabled: true store_path: "./agents/assistant-bot/data/crypto/" pickle_key: "${PICKLE_KEY_ASSISTANT_BOT}" trust_mode: tofu ``` ### Generar un pickle key ```bash openssl rand -hex 32 ``` ### Por qué NO derivar del access token Si el token cambia (re-registro, nuevo login), el pickle key cambia y la DB existente se vuelve ilegible. Esto causa el error: ``` olm account is not marked as shared, but there are keys on the server ``` Un pickle key fijo por agente en `.env` evita este problema. ## Crypto store por agente Cada agente debe tener su propia crypto.db para evitar corrupción cruzada: ``` agents/assistant-bot/data/crypto/crypto.db agents/asistente-2/data/crypto/crypto.db ``` **No compartir** la crypto store entre agentes. ## Auto-recovery Si `cryptohelper.Init()` falla por inconsistencia (ej: "not marked as shared"), el runtime borra automáticamente la crypto.db y reintenta. Esto regenera las claves Olm y requiere re-verificar cross-signing. ## Cross-signing y verificación Elimina warnings de "Encrypted by a device not verified by its owner". ```bash go run -tags goolm ./cmd/verify \ --homeserver https://matrix-af2f3d.organic-machine.com \ --username \ --password \ --token ``` Esto genera y sube cross-signing keys al servidor. Si las claves ya existen, firma el dispositivo actual con la clave existente. ## Trust mode Configurado en `config.yaml` como `trust_mode`: - **tofu** (Trust-on-First-Use): confía en un dispositivo la primera vez que lo ve. Cambios posteriores generan warnings. - **cross-signing**: requiere verificación explícita (no implementado aún). - **manual**: cada dispositivo debe verificarse manualmente (no implementado aún). ## Build Siempre compilar con `-tags goolm`: ```bash go build -tags goolm -o bin/launcher ./cmd/launcher ``` El driver SQLite se registra como `"sqlite3"` via `modernc.org/sqlite` en `cmd/launcher/sqlite.go` y `cmd/verify/sqlite.go`. ## Troubleshooting ### "olm account is not marked as shared, but there are keys on the server" La crypto store local está desincronizada con el servidor. **Solución**: El runtime intenta auto-recovery. Si falla manualmente: ```bash rm agents//data/crypto/crypto.db # Reiniciar el bot # Re-verificar cross-signing ``` ### "database is locked (SQLITE_BUSY)" Dos procesos están accediendo la misma crypto.db simultáneamente. **Solución**: Asegurar que cada agente use su propia `store_path` y no corran múltiples instancias del mismo agente con E2EE habilitado sin coordinación. ### "unable to decrypt message" Las claves Megolm de la sesión se perdieron (DB borrada o corrupta). **Solución**: Los mensajes cifrados antes del reset son irrecuperables. Los nuevos mensajes se descifrarán normalmente tras regenerar las claves. ## Archivos clave | Archivo | Propósito | |---------|-----------| | `agents/runtime.go` | Inicializa E2EE por agente | | `shell/matrix/client.go` | `InitCrypto()` — setup de cryptohelper | | `cmd/verify/main.go` | Herramienta de cross-signing | | `cmd/launcher/sqlite.go` | Registro driver SQLite | | `internal/config/schema.go` | Schema de `EncryptionCfg` | | `agents/*/config.yaml` | Configuración E2EE por agente |