bd0c8c0dd3
agents/ ahora solo contiene carpetas de agentes (config, reglas, prompts). El runtime (Agent, Robot, Runner, registry, handler, commands, llm, memory) vive en devagents/ como package devagents. Cambios: - git mv agents/*.go → devagents/*.go - package agents → package devagents en todos los archivos movidos - Actualizar imports en agents/*/agent.go, cmd/launcher/, dev-scripts/ - Actualizar docs: CLAUDE.md, rules/, docs/e2ee.md, issues pendientes Build y tests pasan sin errores. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
153 lines
4.7 KiB
Markdown
153 lines
4.7 KiB
Markdown
# 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)
|
|
↓
|
|
devagents/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=<hex random 32 bytes>
|
|
```
|
|
|
|
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 <bot-id> \
|
|
--password <password> \
|
|
--token <access_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/<id>/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 |
|
|
|---------|-----------|
|
|
| `devagents/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 |
|