Files
fn_registry/dev/issues/0160-matrix-client-android-mini-webapps.md
T
egutierrez a3f75d61ec chore: avance acumulado de sesiones previas (reorg dev/issues + ajustes)
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).
2026-06-30 14:43:51 +02:00

4.2 KiB

id, title, status, priority, created, related_flows, related_issues, dependencies, tags
id title status priority created related_flows related_issues dependencies tags
0160 matrix-client-android mini-webapps: WebView + Widget API v2 bridge pendiente media 2026-05-24
0011
0159
0161
0159
matrix
android
webview
widgets
agents
sandbox

Objetivo

Host de widgets en Android equivalente al cliente PC (issue 0152). Mismo contrato Widget API v2. WebView con sandbox estricto + bridge JS-Kotlin implementa capabilities API. Widgets de los rooms operados por agentes (agents_and_robots) se ven embebidos: dashboard, formulario, kanban inline, control del agente.

Tareas

  1. ViewModel:
    • WidgetsViewModel(matrixClient, roomId):
      • Flow<List<Widget>> desde state events m.widget del room.
      • addWidget(widget), removeWidget(widgetId).
      • generateUrl(widget) -> String — substituye placeholders Matrix Widget API.
      • mintScopedToken(widgetId) -> String — token efimero scope room+widget.
  2. Compose:
    • WidgetsPanel (drawer lateral o bottom sheet en movil):
      • Tabs con widgets activos del room.
      • Cada tab = WidgetView que envuelve un WebView.
    • WidgetView composable:
      • WebView configurado:
        • settings.javaScriptEnabled = true.
        • settings.allowFileAccess = false.
        • settings.allowContentAccess = false.
        • settings.allowFileAccessFromFileURLs = false.
        • settings.allowUniversalAccessFromFileURLs = false.
        • settings.mixedContentMode = MIXED_CONTENT_NEVER_ALLOW.
        • webViewClient con CSP injection + URL allowlist.
      • addJavascriptInterface(WidgetBridge, "MatrixWidgetBridge") — bridge expone Widget API v2.
    • CapabilityConsentDialog Compose — pide consentimiento usuario para capabilities.
  3. WidgetBridge (Kotlin):
    • Implementa capabilities handshake postMessage (igual contrato que cliente PC):
      • read_events, send_event, send_to_device, get_openid, m.always_on_screen.
    • Audit log mensajes JS<->Kotlin en local DB.
    • Whitelist estricta de capabilities concedidas.
  4. Widgets internos primer batch (compartidos con cliente PC):
    • widget-agent-panel — control del agente.
    • widget-kanban — kanban inline.
    • widget-issue-tracker.
  5. Tests:
    • Instrumented WidgetCapabilitiesTest — dialog aparece + accept/decline funciona.
    • Instrumented WidgetSandboxTest — widget malicioso (intenta window.location='file:///etc/passwd') bloqueado.
    • Instrumented WidgetSendEventTest — widget con capability envia msg.

Funciones del registry a crear

  • WidgetView_kotlin_ui — Compose WebView wrapper sandboxed.
  • widget_bridge_kotlin_infra — JavascriptInterface implementando Widget API v2.
  • widget_url_template_kotlin_core — substituyente placeholders (puede compartirse logica con la Go version del PC, contrato identico).
  • CapabilityConsentDialog_kotlin_ui — Compose dialog.
  • widget_audit_log_kotlin_infra — append-only audit log en Room DB.

Acceptance

  • Widget publicado desde cliente PC se ve embebido en Android (mismo room).
  • Capability handshake: widget pide send_event -> dialog Compose -> accept -> widget envia msg.
  • Sandbox: widget intenta XMLHttpRequest a file:/// -> bloqueado.
  • Widget agent-panel funcional: muestra logs en vivo del agente + boton restart.
  • Audit log persiste en Room DB con timestamp + capability + accept/deny.

Notas

Critico:

  • Mismo contrato Widget API v2 que cliente PC. Widget HTML escrito una vez funciona en ambos.
  • WebView Android moderno (Chromium 100+) soporta WebRTC + WebGL + service workers. Suficiente para widgets ricos.

Gotcha:

  • WebView.addJavascriptInterface solo seguro en Android 4.2+ (API 17+, ya minSdk=28). Pero validar todo input desde JS — nunca confiar.
  • setAllowFileAccessFromFileURLs(false) solo aplica si la URL del widget es file://. Nuestros widgets son https:// -> hardcode CSP estricta.
  • Memory: WebView por tab + 5 widgets activos = ~200MB facil. Limitar a max 3 widgets simultaneos activos.

Roadmap post-DoD:

  • Widget marketplace catalog accesible via menu.
  • "Add to home screen" PWA mode para widgets favoritos (Android shortcut + launcher icon dedicado).