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>
84 lines
4.2 KiB
Markdown
84 lines
4.2 KiB
Markdown
---
|
|
id: "0160"
|
|
title: "matrix-client-android mini-webapps: WebView + Widget API v2 bridge"
|
|
status: pending
|
|
priority: medium
|
|
created: 2026-05-24
|
|
related_flows: ["0011"]
|
|
related_issues: ["0159", "0161"]
|
|
dependencies: ["0159"]
|
|
tags: [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).
|