a3f75d61ec
Reorganizacion de dev/issues en subcarpetas (completed/, cpp/, gamedev/, kanban/, trading/, imagegen/, matrix/) y cambios acumulados en cmd/fn/pyrunner, .claude/commands y settings. Trabajo de otro LLM/sesion, commiteado a peticion del usuario para desbloquear el working tree. Excluido logs/ardour_mcp_server.log (ruido).
4.9 KiB
4.9 KiB
id, title, status, priority, created, related_flows, related_issues, dependencies, tags
| id | title | status | priority | created | related_flows | related_issues | dependencies | tags | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0152 | matrix-client-pc mini-webapps embebidas: Matrix Widget API v2 | pendiente | alta | 2026-05-24 |
|
|
|
|
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
- Backend Go:
MatrixService.ListWidgets(roomID) -> []Widget— lee state eventsm.widgetdel 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,$themeen 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).
- 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 escuchapostMessagedel iframe e implementa Widget API v2:capabilitieshandshake: 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.
- Hook
- 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 poragents_and_robotsHTTP API (issue 0113 ya creando agent runner API).widget-kanban— kanban inline embebido para tasks del room. Reusaapps/kanban(Go) servido en LAN.widget-issue-tracker— widget que abre issue API (0109m).
- Tests:
e2e/test_widget_capabilities.sh— widget pide capability, dialog aparece, deniega/acepta funciona.e2e/test_widget_send_event.sh— widget con capabilitysend_eventenvia msg al room.e2e/test_widget_sandbox.sh— widget malicioso (intentatop.location =) es bloqueado por sandbox.
Funciones del registry a crear
matrix_widget_state_go_infra— CRUD state eventsm.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.appcrea 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_robotspublica 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:nidata:text/htmlURLs (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:+ permitirdata:/blob:solo para widgets internos firmados.
Roadmap post-DoD:
- Widget marketplace interno:
widget-catalogenagents_and_robotscon widgets internos descubribles. - Widget templates: un agente publica un widget HTML estatico subido al room (
mxc://) y el cliente lo renderiza desde la URLmxc -> http. - Cross-room widgets: widget que persiste entre rooms (TBD, requiere MSC propio).