--- id: "0163" title: "Matrix admin panel propio: users, rooms, devices, sessions (sustituye synapse-admin)" status: pending priority: medium created: 2026-05-24 related_flows: ["0010", "0011"] related_issues: ["0162", "0147"] dependencies: ["0162"] tags: [matrix, admin, panel, react, mantine, mas, synapse, infra] --- ## Objetivo Panel admin propio que reemplaza `https://admin-0cc4d3.organic-machine.com/#/users` (synapse-admin actual). Funciones equivalentes: gestionar usuarios (crear, deactivate, reset password, list devices, list rooms), gestionar rooms (list, members, kick, force-leave, delete), ver sesiones activas + revoke, ver media (storage usage por user). Auth via MAS OIDC con scope admin. Stack: React+Vite+Mantine+`@fn_library` (consistente con flows 0010/0011 + resto del registry). ## Por que reemplazar synapse-admin - **Auth legacy**: synapse-admin usa admin token + password admin directo. Tras issue 0162 (MAS obligatorio) esto chirria. Mejor consume MAS OIDC + Synapse Admin API. - **UI ajena**: stack distinto al resto del registry. Sin theming propio, sin `@fn_library`, sin coherencia visual con cliente PC (flow 0010). - **Sin agentes**: no podemos integrar paneles especiales para `agents_and_robots`, devices del mesh (flow 0009), policies de widgets. - **No extensible**: anadir "ver telemetria de calls LiveKit" o "audit log MAS" requiere fork pesado. ## Tareas 1. **Scaffold app**: - `projects/element_agents/apps/matrix_admin_panel/`. - Stack: React+Vite+TS+Mantine+`@fn_library`+`@tabler/icons-react`. - Backend: Go con `mautrix-go` admin client + MAS OIDC client + `livekit-server-sdk-go` (para sesiones de call). - Empaquetado: backend Go sirve frontend estatico embebido (`embed.FS`). - Deploy: container Docker en `element_matrix_chat` stack o como service standalone via `deploy_server`. 2. **Auth flow MAS**: - Cliente registrado en MAS (issue 0162 paso 2) con scope `urn:synapse:admin:*`. - Login Web: OIDC redirect a MAS. - Token guardado en httpOnly cookie + CSRF token. 3. **Modulos UI**: - **Users**: - Tabla virtualizada con `data-table` (cuando exista TS equivalente) o `mantine-react-table`. - Columnas: localpart, displayname, avatar, admin, deactivated, last_seen, device_count. - Acciones por row: view detail, deactivate/reactivate, reset password (force MAS link), list devices. - Filtros: deactivated, admin, search. - **User detail**: - Sub-tabs: Profile, Devices (list + revoke individual), Rooms (membership list), Media (uploads + size), Sessions (MAS active sessions + revoke), Audit log (MAS). - **Rooms**: - Tabla: room_id, name, alias, members_count, encrypted, public, federated, state_events. - Acciones: view detail, force-leave usuarios, delete room (purge), shutdown notif. - **Room detail**: - Members + roles, state events viewer (read-only JSON), media in room, widgets activos (interop con flow 0010 widget API). - **Sessions** (MAS): - Lista sesiones activas global. - Filtro por user, IP, device, last_used. - Revoke individual o bulk. - **Federation**: - Estado federation (Synapse `federation_handler`). - Allowlist/blocklist servers. - **Stats**: - Resumen: users count, rooms count, mensajes/dia (ultima semana), media storage, calls activas (via LiveKit `RoomService.ListRooms`). - Graficas con `@mantine/charts` o `recharts`. 4. **Capability groups en panel**: - Reusa `AgentPanel` (flow 0010 issue 0153) para mostrar info de agentes registrados. - Reusa `DevicePanel` (cuando flow 0009 vivo) para devices del mesh. - Slot "Widgets policy": ver/aprobar capabilities concedidas globalmente, audit log. 5. **API endpoints backend Go**: - `GET /api/users` -> proxy a Synapse `/_synapse/admin/v2/users` con auth MAS. - `POST /api/users//deactivate`. - `GET /api/rooms`, `POST /api/rooms//delete`. - `GET /api/mas/sessions`, `POST /api/mas/sessions//revoke` (MAS admin API). - `GET /api/livekit/rooms` (active calls). - `GET /api/stats/summary`. 6. **Permisos**: - Solo users con flag `admin: true` (Synapse) o scope MAS admin claim. - Backend valida claim/flag en cada request. - UI muestra "Access denied" si user logueado no es admin. 7. **Deploy**: - Anadir container al `docker-compose.yml` de `element_matrix_chat`. - O bien standalone via `deploy_server` (registry function existente). - URL: `admin-af2f3d.organic-machine.com` o reusar `admin-0cc4d3.organic-machine.com` cuando se retire synapse-admin. 8. **Migracion synapse-admin -> panel propio**: - Coexistencia 2 semanas: ambos vivos, MAS audita uso de cada uno. - Cuando uso de synapse-admin = 0 durante 7 dias seguidos: detener container. - Documentar en `docs/admin_panel_migration.md`. 9. **Tests**: - `e2e/test_admin_login.sh` — MAS OIDC + scope admin valido -> acceso. - `e2e/test_admin_login_denied.sh` — user no-admin recibe 403. - `e2e/test_user_deactivate.sh` — flow completo deactivate + verify can't login. - `e2e/test_room_purge.sh` — purge room + verify gone en Synapse. - `e2e/test_session_revoke.sh` — revoke sesion MAS + user perdiendo acceso en <30s. ## Funciones del registry a crear - `synapse_admin_client_go_infra` — wrapper Synapse Admin API. - `mas_admin_client_go_infra` — wrapper MAS admin API (`/api/admin/v1/...`). - `livekit_admin_client_go_infra` — `RoomService.ListRooms`, kick participant, etc. - `oidc_admin_middleware_go_infra` — middleware Go que valida scope admin en cookie/Bearer. - `UsersTable_ts_ui` — componente Mantine con virtualization + filtros. - `RoomDetail_ts_ui` — componente con tabs Members/State/Media/Widgets. - `SessionsList_ts_ui` — lista sesiones + revoke action. - `StatsSummary_ts_ui` — componente con `@mantine/charts`. - `FederationStatusPanel_ts_ui` — componente federation diag. ## Acceptance - [ ] App compila + arranca como container Docker. - [ ] Login via MAS OIDC con scope admin funciona. - [ ] User no-admin recibe 403 al intentar entrar. - [ ] Tabla users con 50+ rows + filtros + actions. - [ ] Deactivate user end-to-end (verify cannot login despues). - [ ] Room detail muestra members + state events JSON. - [ ] Sessions MAS listadas + revoke individual. - [ ] Stats: counts + media usage + active calls visibles. - [ ] Tema visual coherente con cliente PC (flow 0010). ## Definition of Done ### Mecanica - `go build` + `pnpm build` verde. - Container Docker `<150MB` (Alpine + binary + static). - Health endpoint `/health` 200. - E2E suite pasa. ### Cobertura | Escenario | Evidencia | Resultado | |---|---|---| | Golden: admin login + ver users | `e2e/test_admin_full_flow.sh` | tabla con users reales, actions visibles | | Edge: 5000 users en tabla | benchmark scroll | 60fps, <300MB RAM | | Edge: user sin admin entra | request directo | 403 + audit log | | Edge: room con 200 members | view detail | render < 1s, paginacion OK | | Error: Synapse Admin API caida | mock 500 | UI muestra error claro, no crash | | Error: MAS session revoke fails | mock 500 | retry + toast error | ### Vida util (>=7 dias) | Metrica | Umbral | Donde | Ventana | |---|---|---|---| | Crashes container | `0` | docker logs | 7 dias | | Uso real | `>= 2 sesiones/semana` (operador) | nginx access log | 7 dias | | Latency p95 endpoint /api/users | `< 800ms` (Synapse Admin paginado) | metrics | 7 dias | | Acciones destructivas auditadas | `100%` (cada delete/revoke con audit row) | local audit DB | continuo | ### Anti-criterios - NO marcar done si admin panel acepta token sin claim/flag admin. - NO marcar done si delete room no purga media en DB Synapse. - NO marcar done si UI deja al operador sin confirmacion en acciones destructivas (deactivate, purge, revoke). - NO marcar done si lookalike de synapse-admin sin features propias (mejor mantener synapse-admin entonces). ## Notas **Ventajas reales sobre synapse-admin:** 1. Coherencia visual + Mantine + theme propio. 2. Integracion con `agents_and_robots` (panel agente embedded). 3. Integracion con widgets policy (audit + override capabilities). 4. Integracion con LiveKit calls (ver rooms activos, force-end). 5. Audit log local SQLite con todas las acciones admin (synapse-admin no lo tiene). 6. Extensible — anadir tabs para mesh devices (flow 0009), telemetria, etc. **Onboarding:** 1. `cd projects/element_agents/apps/matrix_admin_panel`. 2. `make dev` (Go backend + Vite frontend hot reload). 3. Visitar `http://127.0.0.1:8090` -> login MAS dev. 4. Deploy prod: ver `deploy/README.md`. **Decisiones:** - Backend Go > Python/Node: alinea con `mautrix-go` + reusa funciones del registry. Binario pequeno, deploy facil. - Embedded static (Go `embed.FS`): un binario, sin docker multi-stage compleja. - Audit log local SQLite > Postgres: panel admin no necesita HA, suficiente con SQLite local + backup periodico. **Gotchas:** - Synapse Admin API requiere `Bearer ` — el panel intercambia OIDC token + admin claim por admin_token (con MAS admin API o con cuenta admin shared). - MAS admin API esta en `/api/admin/v1/` — version unstable, monitorizar breaking changes. - Federation tab: si federation deshabilitada (caso actual, ver `homeserver.yaml`), tab muestra "disabled" en vez de error. **Roadmap post-DoD:** - Bulk actions (mass deactivate, mass invite). - Export reports CSV. - Slack/email alerts en eventos criticos (server cae, MAS down, federation block). - Multi-tenancy si llegan mas homeservers. ## Capability growth log - v0.1.0 (2026-05-24) — issue creada.