--- id: "0159" title: "matrix-client-android push FCM via sygnal + Firebase setup" status: pending priority: high created: 2026-05-24 related_flows: ["0011"] related_issues: ["0158", "0160"] dependencies: ["0154"] tags: [matrix, android, push, fcm, firebase, sygnal, infra] --- ## Objetivo Notificaciones push moviles via FCM (Firebase Cloud Messaging) usando `sygnal` (push gateway oficial de Matrix). Sygnal recibe push events de Synapse, traduce a payload FCM, enviado a Firebase, entregado al device. La app despierta para mostrar notificacion del mensaje, o trigger ringer para incoming calls. App en background o muerta tambien recibe. ## Tareas 1. Infra (modifica `element_matrix_chat` app): - Anadir container `sygnal` al `docker-compose.yml`. Config en `configs/sygnal.yaml`. - Service account JSON de Firebase en `configs/firebase-sa.json` (gitignored, instalado en VPS via secrets). - Synapse config: pushers habilitados (ya por defecto). - Reverse proxy: `https://push-.organic-machine.com/_matrix/push/v1/notify` -> sygnal:5000. - Documentar setup en `projects/element_agents/apps/element_matrix_chat/docs/sygnal_setup.md`. 2. Firebase: - Crear proyecto `fn-registry-matrix-push` en Firebase console. - Habilitar Cloud Messaging. - Generar service account JSON. - Anadir `google-services.json` al modulo Android (`app/google-services.json`). 3. Android app: - `build.gradle`: `com.google.gms:google-services`, `com.google.firebase:firebase-messaging`. - `FirebaseMessagingService` subclass: - `onNewToken(token)` -> registrar en sygnal via Synapse Pusher API `POST /_matrix/client/v3/pushers/set`. - `onMessageReceived(message)` -> parse data payload + mostrar notif. - Notification channels (Android 8+): - `messages` — IMPORTANCE_HIGH, sonido. - `calls` — IMPORTANCE_HIGH, full-screen intent (despertar pantalla). - `silent` — IMPORTANCE_LOW. - VoIP push para calls: payload con `prio=high`, `event_id_only=false` (incluir event para mostrar caller info sin sync completo). 4. Tests: - Instrumented `FCMTokenRegistrationTest` — mock Firebase, verificar pusher creado en Synapse. - Manual `PushDeliveryTest` — enviar msg desde Element Web a Android offline -> push aparece <3s. - Manual `PushCallTest` — start call desde PC -> Android offline despierta + ring. - Manual `PushBatterySaverTest` — Android en battery saver + Doze mode + push sigue llegando. ## Funciones del registry a crear - `sygnal_setup_bash_infra` — script setup container sygnal en VPS. - `sygnal_config_template_go_infra` — generador `sygnal.yaml` con Firebase SA. - `fcm_register_kotlin_infra` — onNewToken + register en Synapse Pusher API. - `synapse_pusher_set_go_infra` — Go helper REST `POST /pushers/set` (reutilizable PC + Android). - `NotificationBuilder_kotlin_ui` — helper notification channels + actions. ## Acceptance - [ ] Container `sygnal` activo en VPS, health check `:5000/_matrix/push/v1/notify` HEAD 200. - [ ] Firebase project creado + SA JSON instalada en VPS. - [ ] App Android registra FCM token + crea pusher en Synapse al primer login. - [ ] Msg desde Element Web a Android (app cerrada por user) -> push notif en <3s. - [ ] Start call desde cliente PC -> Android offline despierta + ring 30s. - [ ] Battery saver activo: push sigue llegando (FCM high priority bypasses Doze). - [ ] Multiple users: pusher por device, no se cruzan. ## Notas **Gotcha critico:** FCM no entrega push si: - App ha sido force-stopped por user (system requirement). - Device tiene "Restricted background usage" en battery settings. - Account Google no esta sincronizada en el device. Documentar en onboarding para que el user lo entienda. **Privacy:** payload FCM no debe contener contenido del msg en claro (Synapse E2EE). Solo: `room_id`, `event_id`, `unread_count`, `prio`. App hace sync interno al recibir push para obtener msg cifrado y descifrar local. **Coste:** FCM gratis para hosting Firebase. Sygnal CPU/RAM despreciable (<50MB). **Alternativas exploradas:** - UnifiedPush + ntfy: open-source, sin Google. Pro: privacy. Con: requiere infraestructura propia + onboarding mas duro. Post-DoD considerar como segunda opcion para users sin Google Play. **Decisiones futuras (post-DoD):** - iOS equivalent: APNs via sygnal mismo gateway. Cuando llegue cliente iOS.