diff --git a/dev-scripts/agent/notify-developer.sh b/dev-scripts/agent/notify-developer.sh index 6dbc030..d2a6a71 100755 --- a/dev-scripts/agent/notify-developer.sh +++ b/dev-scripts/agent/notify-developer.sh @@ -105,14 +105,23 @@ send_dm() { local backoff=2 while [[ $retry -lt $max_retries ]]; do - # Crear DM room (o reutilizar existente) + # Crear DM room con E2EE habilitado (o reutilizar existente) ROOM_RESP=$(curl -sf -X POST "${MATRIX_HOMESERVER}/_matrix/client/v3/createRoom" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d "{ \"is_direct\": true, \"invite\": [\"${user_id}\"], - \"preset\": \"trusted_private_chat\" + \"preset\": \"trusted_private_chat\", + \"initial_state\": [ + { + \"type\": \"m.room.encryption\", + \"state_key\": \"\", + \"content\": { + \"algorithm\": \"m.megolm.v1.aes-sha2\" + } + } + ] }" 2>&1) || { retry=$((retry + 1)) if [[ $retry -lt $max_retries ]]; then diff --git a/dev/issues/README.md b/dev/issues/README.md index 5b72b2c..e92d542 100644 --- a/dev/issues/README.md +++ b/dev/issues/README.md @@ -55,3 +55,4 @@ afectados y notas de implementacion. | 42 | Auto-avatar con proveedores gratuitos | [0042-auto-avatar-providers.md](completed/0042-auto-avatar-providers.md) | completado | | 43 | Guardrails de seguridad para Father Bot | [0043-father-bot-security-guardrails.md](completed/0043-father-bot-security-guardrails.md) | completado | | 44 | Formalizar pipeline de creacion de agentes | [0044-formalize-agent-creation-pipeline.md](completed/0044-formalize-agent-creation-pipeline.md) | completado | +| 45 | DM rooms sin E2EE en notify-developer.sh | [0045-notify-encrypted-rooms.md](completed/0045-notify-encrypted-rooms.md) | completado | diff --git a/dev/issues/completed/0045-notify-encrypted-rooms.md b/dev/issues/completed/0045-notify-encrypted-rooms.md new file mode 100644 index 0000000..8c9c7b4 --- /dev/null +++ b/dev/issues/completed/0045-notify-encrypted-rooms.md @@ -0,0 +1,79 @@ +# 0045 — DM rooms creados por notify-developer.sh sin E2EE + +## Objetivo + +El script `notify-developer.sh` (paso 12 del pipeline de creacion de agentes) crea salas DM +sin encriptacion E2EE. Esto causa que Element muestre "End-to-end encryption isn't enabled" +en las conversaciones con bots creados recientemente (father-bot, test-bot, test-personality), +mientras que los bots mas antiguos (assistant-bot, asistente-2) tienen E2EE porque sus DMs +fueron iniciados desde Element Web (que encripta por defecto). + +## Contexto + +El `createRoom` actual usa `preset: trusted_private_chat` que configura permisos pero **no activa +E2EE**. Para activar encriptacion se necesita un `initial_state` con evento `m.room.encryption`. + +Archivo afectado: `dev-scripts/agent/notify-developer.sh` (linea ~109). + +## Arquitectura + +- `dev-scripts/agent/notify-developer.sh` — script bash (impuro, shell) +- No hay cambios en `pkg/` (puro) + +## Tareas + +### Fase 1: Fix + +- [ ] 1.1 Agregar `initial_state` con `m.room.encryption` (algorithm `m.megolm.v1.aes-sha2`) al + JSON del `createRoom` en `notify-developer.sh` + +### Fase 2: Tests + +- [ ] 2.1 Test de shell que valide que el JSON del createRoom incluye encryption + +### Fase 3: Docs + +- [ ] 3.1 Cerrar issue, mover a completed + +## Ejemplo de uso + +Antes (sin E2EE): +```json +{ + "is_direct": true, + "invite": ["@dev:server"], + "preset": "trusted_private_chat" +} +``` + +Despues (con E2EE): +```json +{ + "is_direct": true, + "invite": ["@dev:server"], + "preset": "trusted_private_chat", + "initial_state": [ + { + "type": "m.room.encryption", + "state_key": "", + "content": { + "algorithm": "m.megolm.v1.aes-sha2" + } + } + ] +} +``` + +## Decisiones de diseno + +- Se usa `m.megolm.v1.aes-sha2` que es el algoritmo estandar de Matrix para group encryption. +- El `preset: trusted_private_chat` se mantiene para los permisos (invite-only, admins). +- No se requieren cambios en el codigo Go — solo el script bash. + +## Prerequisitos + +Ninguno. + +## Riesgos + +- Bajo: cambio minimo y bien definido en un solo archivo. diff --git a/e2e/tests/notify-developer-e2ee.spec.ts b/e2e/tests/notify-developer-e2ee.spec.ts new file mode 100644 index 0000000..a7a98b6 --- /dev/null +++ b/e2e/tests/notify-developer-e2ee.spec.ts @@ -0,0 +1,38 @@ +import { test, expect } from "@playwright/test"; +import * as fs from "fs"; +import * as path from "path"; + +const REPO_ROOT = path.resolve(__dirname, "../.."); +const NOTIFY_SCRIPT = path.join( + REPO_ROOT, + "dev-scripts/agent/notify-developer.sh" +); + +test.describe("notify-developer.sh — E2EE en DM rooms", () => { + test("script existe y es ejecutable", () => { + expect(fs.existsSync(NOTIFY_SCRIPT)).toBe(true); + const stats = fs.statSync(NOTIFY_SCRIPT); + // Check executable bit (owner) + expect(stats.mode & 0o100).toBeTruthy(); + }); + + test("createRoom incluye initial_state con m.room.encryption", () => { + const content = fs.readFileSync(NOTIFY_SCRIPT, "utf-8"); + + // Must have initial_state in the createRoom call + expect(content).toContain("initial_state"); + expect(content).toContain("m.room.encryption"); + expect(content).toContain("m.megolm.v1.aes-sha2"); + }); + + test("createRoom mantiene preset trusted_private_chat", () => { + const content = fs.readFileSync(NOTIFY_SCRIPT, "utf-8"); + expect(content).toContain("trusted_private_chat"); + }); + + test("createRoom incluye is_direct e invite", () => { + const content = fs.readFileSync(NOTIFY_SCRIPT, "utf-8"); + expect(content).toContain("is_direct"); + expect(content).toContain("invite"); + }); +});