daef7ea190
Helper functions (matrix-mas capability group): - mas_client_register_bash_infra: register/sync OAuth clients via mas-cli - mas_syn2mas_migration_bash_infra: dry-run + apply user migration to MAS - synapse_msc3861_enable_go_infra: edit homeserver.yaml MSC3861 block (with diff) - wellknown_oidc_patch_go_infra: patch well-known JSON with msc2965.authentication - synapse_login_flows_check_go_infra: health-check post-migration login flows Flows + issues for custom Matrix clients (PC + Android): - 0010 matrix-client-pc: Wails + React+Mantine (issues 0147-0153) - 0011 matrix-client-android: Kotlin + Compose (issues 0154-0161) - 0162 enable MAS as auth provider (Synapse delegate) — EXECUTED on VPS - 0163 custom admin panel propio (sustituye synapse-admin) Production state (organic-machine.com): - Synapse migrated SQLite -> Postgres - MSC3861 active, password_config disabled - 21 users + 41 access_tokens migrated via syn2mas - 4 MAS clients registered (element, matrix_pc, matrix_android, admin_panel) - synapse-admin container removed + Coolify route deleted - well-known patched with org.matrix.msc2965.authentication Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
82 lines
4.9 KiB
Markdown
82 lines
4.9 KiB
Markdown
---
|
|
id: "0152"
|
|
title: "matrix-client-pc mini-webapps embebidas: Matrix Widget API v2"
|
|
status: pending
|
|
priority: high
|
|
created: 2026-05-24
|
|
related_flows: ["0010"]
|
|
related_issues: ["0151", "0153"]
|
|
dependencies: ["0151"]
|
|
tags: [matrix, widgets, webapps, iframe, sandbox, agents, postmessage]
|
|
---
|
|
|
|
## Objetivo
|
|
|
|
Implementar host de widgets segun Matrix Widget API v2 (MSC2762, MSC2871, MSC2974). Cada room puede tener widgets activos publicados como state events `m.widget`. Los widgets son URLs cargadas en iframes sandboxed con bridge postMessage que da capabilities controladas (leer eventos del room, enviar eventos, mostrar UI overlay, etc.). Agentes de `agents_and_robots` pueden publicar widgets en sus rooms (ej. dashboard telemetria, formulario, kanban inline, panel de control del agente).
|
|
|
|
## Tareas
|
|
|
|
1. Backend Go:
|
|
- `MatrixService.ListWidgets(roomID) -> []Widget` — lee state events `m.widget` del room.
|
|
- `MatrixService.AddWidget(roomID, widget Widget)` — publica state event.
|
|
- `MatrixService.RemoveWidget(roomID, widgetID)`.
|
|
- `MatrixService.GenerateWidgetURL(widget Widget, userID) -> string` — substituye `$matrix_user_id`, `$matrix_room_id`, `$matrix_display_name`, `$matrix_avatar_url`, `$matrix_widget_id`, `$theme` en la URL del widget.
|
|
- Slash command `/widget <url>` handler en composer (issue 0149) que crea state event con widget temporal.
|
|
- `MatrixService.MintWidgetScopedToken(widgetID, userID) -> string` — token efimero con scope reducido (solo el room donde esta el widget).
|
|
2. Frontend React:
|
|
- Hook `useWidgets(roomID)` — lista widgets activos.
|
|
- Componente `WidgetPanel`:
|
|
- Tabs por widget activo + boton "+" para anadir.
|
|
- Cada widget en iframe con `sandbox="allow-scripts allow-same-origin allow-forms allow-popups-to-escape-sandbox"`.
|
|
- `iframe.referrerpolicy="no-referrer"`.
|
|
- CSP: `frame-src https: data: blob:`.
|
|
- `WidgetBridge` — clase JS que escucha `postMessage` del iframe e implementa Widget API v2:
|
|
- `capabilities` handshake: el widget declara que necesita, el host pide consentimiento usuario (dialog Mantine).
|
|
- `read_events`, `send_event`, `send_to_device`, `get_openid`, `m.always_on_screen`, etc.
|
|
- Whitelist estricta de capabilities concedidas. Audit log de mensajes en `store.db`.
|
|
- Layout: widgets se abren en panel lateral derecho (toggleable) o en modal fullscreen.
|
|
3. Widgets internos primer batch (proof of concept):
|
|
- `widget-jitsi-fallback` — si LiveKit falla, fallback a Jitsi via widget (URL config).
|
|
- `widget-agent-panel` — panel de control de agente: estado, ultima ejecucion, restart, view logs. Servido por `agents_and_robots` HTTP API (issue 0113 ya creando agent runner API).
|
|
- `widget-kanban` — kanban inline embebido para tasks del room. Reusa `apps/kanban` (Go) servido en LAN.
|
|
- `widget-issue-tracker` — widget que abre issue API (`0109m`).
|
|
4. Tests:
|
|
- `e2e/test_widget_capabilities.sh` — widget pide capability, dialog aparece, deniega/acepta funciona.
|
|
- `e2e/test_widget_send_event.sh` — widget con capability `send_event` envia msg al room.
|
|
- `e2e/test_widget_sandbox.sh` — widget malicioso (intenta `top.location =`) es bloqueado por sandbox.
|
|
|
|
## Funciones del registry a crear
|
|
|
|
- `matrix_widget_state_go_infra` — CRUD state events `m.widget`.
|
|
- `widget_url_template_go_core` — substituye placeholders en URL.
|
|
- `widget_token_mint_go_infra` — token scoped a un widget+room+user.
|
|
- `WidgetBridge_ts_ui` — clase postMessage bridge Widget API v2 completa.
|
|
- `WidgetPanel_ts_ui` — UI tabs + iframes + permisos.
|
|
- `CapabilityConsentDialog_ts_ui` — dialog Mantine para consentimiento.
|
|
|
|
## Acceptance
|
|
|
|
- [ ] `/widget https://my.app` crea state event y abre iframe.
|
|
- [ ] Widget declara capability `m.send_event` -> dialog Mantine pide consentimiento.
|
|
- [ ] Widget concedido envia msg al room que aparece en timeline.
|
|
- [ ] Widget malicioso `<script>top.location='evil.com'</script>` bloqueado por sandbox.
|
|
- [ ] `agents_and_robots` publica widget panel y se ve embebido en el room del agente.
|
|
- [ ] Widget kanban inline funciona: drag&drop card persiste en DB del kanban.
|
|
|
|
## Notas
|
|
|
|
**Anti-criterios:**
|
|
- NO permitir `javascript:` ni `data:text/html` URLs (XSS).
|
|
- NO conceder capabilities sin consentimiento explicito del usuario (auditable).
|
|
- NO compartir el access_token Matrix del usuario al widget — usar siempre tokens scoped efimeros.
|
|
|
|
**Decisiones:**
|
|
- Widget API v2 (no v1) — soporta capabilities + tokens scoped.
|
|
- iframe sandbox sin `allow-top-navigation` (previene escape).
|
|
- CSP `frame-src https:` + permitir `data:`/`blob:` solo para widgets internos firmados.
|
|
|
|
**Roadmap post-DoD:**
|
|
- Widget marketplace interno: `widget-catalog` en `agents_and_robots` con widgets internos descubribles.
|
|
- Widget templates: un agente publica un widget HTML estatico subido al room (`mxc://`) y el cliente lo renderiza desde la URL `mxc -> http`.
|
|
- Cross-room widgets: widget que persiste entre rooms (TBD, requiere MSC propio).
|