---
id: "0154"
title: "matrix-client-android scaffold: Kotlin + Compose + login MAS"
status: pendiente
priority: alta
created: 2026-05-24
related_flows: ["0011"]
related_issues: ["0155", "0162"]
dependencies: ["0162"]
tags: [matrix, android, kotlin, compose, mas, oidc, scaffold]
---

## Objetivo

Crear `projects/element_agents/apps/matrix_client_android/` con `init_kotlin_app` (pipeline ya existente del registry). Configurar Compose + Material 3 + tema propio. Implementar login MAS OIDC via Chrome Custom Tabs. Tokens persistidos en EncryptedSharedPreferences. Resultado: APK debug que abre Custom Tab al MAS, retorna con token y muestra perfil del usuario.

## Tareas

1. `./fn run init_kotlin_app matrix_client_android` — usa pipeline existente del registry (ver issues completados 0073-0078).
2. Sub-repo Gitea: `git init -b master` + crear `dataforge/matrix_client_android` + push inicial. **Antes** de salir del worktree (ver `apps_subrepo.md`).
3. `app.md` con frontmatter:
   - `lang: kotlin`, `framework: jetpack-compose`, `dir_path: projects/element_agents/apps/matrix_client_android`.
   - `tags: [matrix, android, kotlin, compose]`.
   - `uses_functions: []` (irlo rellenando issue a issue).
4. `build.gradle.kts`:
   - `compileSdk = 34`, `minSdk = 28`, `targetSdk = 34`.
   - Compose BOM `2024.x`.
   - `matrix-rust-sdk` Kotlin bindings (`org.matrix.rustcomponents:sdk-android:0.x`).
   - `androidx.security:security-crypto` para EncryptedSharedPreferences.
   - `androidx.browser:browser` para Chrome Custom Tabs.
5. Login MAS:
   - `LoginActivity` con boton "Sign in with Matrix".
   - Generar PKCE code_verifier + state.
   - Abrir Chrome Custom Tab a `<mas_url>/oauth/authorize?...`.
   - `MainActivity` con intent-filter para `matrix-client-android://callback` redirect.
   - Intercambiar code -> access_token + refresh_token.
   - Guardar en EncryptedSharedPreferences (`SecurityCryptoUserPrefs`).
6. `HomeScreen` Compose con `Text("Hola @<userId>")` + boton Logout.
7. Tema Material 3 propio (paleta accent acorde a flow 0010 cliente PC para coherencia).
8. Test instrumented: `LoginInstrumentedTest` que mocka MAS y verifica flow callback -> token saved.

## Funciones del registry a crear

- `matrix_client_kotlin_infra` — facade sobre `matrix-rust-sdk` (init, login, sync, logout).
- `mas_oidc_kotlin_infra` — Chrome Custom Tabs + PKCE + callback handler.
- `encrypted_prefs_kotlin_core` — wrapper EncryptedSharedPreferences (idempotente, generic put/get).
- `LoginScreen_kotlin_ui` — Compose screen Material 3.
- `HomeScreen_kotlin_ui` — Compose screen perfil + logout.

## Acceptance

- [ ] `./gradlew assembleDebug` produce APK valido.
- [ ] APK instala en Android 9+ y arranca.
- [ ] Login: boton -> Custom Tab MAS -> consent -> callback -> perfil visible.
- [ ] Token persiste entre re-aperturas (no re-login si vigente).
- [ ] `app.md` con frontmatter completo + 5 `uses_functions`.
- [ ] Sub-repo `dataforge/matrix_client_android` con commit inicial.
- [ ] Test instrumented `LoginInstrumentedTest` pasa en emulator API 31.

## Notas

- Chrome Custom Tabs > WebView para OAuth (security: comparte cookies con browser principal del user, mejor UX).
- Refresh token: implementar refresh proactivo 5min antes de expiry (corutina + WorkManager periodic).
- Gotcha conocido (ver issue 0074): `local.properties` con `sdk.dir` obligatorio en setup nuevo. El scaffolder lo crea.
- Gotcha (issue 0075): Material 3 sin AppCompat — usar `MaterialTheme` directamente, no `Theme.AppCompat.*`.
