---
id: "0162"
title: "Matrix: migrar Synapse a MAS como unico auth provider (MSC3861)"
status: pendiente
priority: alta
created: 2026-05-24
related_flows: ["0010", "0011"]
related_issues: ["0147", "0154", "0163"]
dependencies: []
tags: [matrix, mas, synapse, msc3861, auth, oidc, migration, infra]
---

## Objetivo

Activar `matrix_authentication_service` en Synapse para que TODO login pase por MAS (Matrix Authentication Service) via MSC3861. Estado actual: MAS corre 6 semanas pero esta en pie sin clients registrados. Synapse usa login password legacy + application_service. Element Web, Synapse-Admin y clientes nuevos (flows 0010 + 0011) deben autenticarse exclusivamente contra MAS via OIDC.

Bloquea flows 0010 (matrix-client-pc) + 0011 (matrix-client-android) porque ambos asumen MAS funcional.

## Estado actual

```yaml
# synapse_data/homeserver.yaml — comentado, NO activo:
# matrix_authentication_service:
#   enabled: true
#   endpoint: "http://mas:8080/"
#   secret: "<shared_secret>"

experimental_features:
  msc3266_enabled: true
  msc4222_enabled: true
  msc4354_enabled: true
#  msc4108_delegation_endpoint: "https://auth-af2f3d.organic-machine.com/_matrix/client/unstable/org.matrix.msc4108/rendezvous"
```

```yaml
# mas/config.yaml
clients: []  # vacio
public_base: https://auth-af2f3d.organic-machine.com/
```

```
GET /_matrix/client/v3/login -> {"flows":[{"type":"m.login.password"},{"type":"m.login.application_service"}]}
GET /.well-known/matrix/client -> sin org.matrix.msc2965.authentication
```

## Tareas

1. **Pre-migracion: backup completo**
   - Snapshot postgres Synapse: `docker exec element_matrix_chat-postgres-1 pg_dump -U synapse synapse > /backup/synapse_$(date +%Y%m%d).sql`.
   - Snapshot postgres MAS: idem `mas-postgres`.
   - Snapshot `synapse_data/` + `mas/config.yaml`.
   - Guardar backups en VPS local + descargar copia a PC.

2. **Registrar clients en MAS** (`mas/config.yaml`):
   - Cliente para Synapse (admin/internal): `client_id` + `client_secret` o `client_auth_method: client_secret_basic`.
   - Cliente para Element Web: `redirect_uris: [https://element-a05ae4.organic-machine.com/]`.
   - Cliente para nuevo admin panel (issue 0163): `redirect_uris: [<admin_panel_url>]`.
   - Cliente para matrix_client_pc (flow 0010): `redirect_uris: [http://127.0.0.1:*]` (loopback dinamico).
   - Cliente para matrix_client_android (flow 0011): `redirect_uris: [matrix-client-android://callback]`.
   - Aplicar: `docker exec element_matrix_chat-mas-1 mas-cli config sync`.

3. **Activar MSC3861 en Synapse**:
   - Editar `synapse_data/homeserver.yaml`:
     ```yaml
     matrix_authentication_service:
       enabled: true
       endpoint: "http://mas:8080/"
       secret: "<shared_secret_matching_mas_config>"
     experimental_features:
       msc3861:
         enabled: true
       msc3266_enabled: true
       msc4222_enabled: true
       msc4354_enabled: true
       msc4108_delegation_endpoint: "https://auth-af2f3d.organic-machine.com/_matrix/client/unstable/org.matrix.msc4108/rendezvous"
     # Disable legacy password login:
     password_config:
       enabled: false
     ```

4. **Migrar usuarios existentes Synapse -> MAS**:
   - `docker exec element_matrix_chat-mas-1 mas-cli syn2mas --synapse-config /data/homeserver.yaml --dry-run` primero.
   - Revisar log (conflictos, usuarios huerfanos).
   - Ejecutar real: `mas-cli syn2mas --synapse-config /data/homeserver.yaml`.
   - Verificar: contar usuarios `mas-postgres` vs `synapse-postgres`, deben coincidir.

5. **Actualizar well-known** (`/.well-known/matrix/client`):
   - Servido por `element_matrix_chat-wellknown-1` (nginx).
   - Anadir:
     ```json
     "org.matrix.msc2965.authentication": {
       "issuer": "https://auth-af2f3d.organic-machine.com/",
       "account": "https://auth-af2f3d.organic-machine.com/account"
     }
     ```
   - Reload nginx.

6. **Restart ordenado**:
   - `docker compose restart mas` -> verificar logs sin errores 30s.
   - `docker compose restart synapse` -> verificar `_matrix/client/v3/login` ahora devuelve `m.login.sso` con `identity_providers` apuntando a MAS.
   - `docker compose restart element` (recarga config).

7. **Reconfigurar Element Web** (`element-config.json`):
   - Activar `oidc_native_flow: true` (Element Web soporta MSC3861 desde v1.11.50+).
   - Verificar version Element Web (`docker exec element_matrix_chat-element-1 cat /etc/nginx/conf.d/element.json | head` o image tag) >= v1.11.50.
   - Si version vieja: bump container image.

8. **Verificar end-to-end**:
   - Logout completo navegador.
   - Abrir Element Web -> debe redirigir a MAS para login.
   - Login con cuenta existente migrada -> redirect back a Element -> sesion activa.
   - Comprobar rooms historicos siguen visibles + msgs E2EE descifrados (las cross-signing keys NO se re-bootstrappean si la migracion va bien).

9. **Plan rollback** (escribir en `docs/mas_migration_rollback.md`):
   - Restaurar postgres Synapse desde dump.
   - Comentar bloque `matrix_authentication_service:` en homeserver.yaml.
   - `password_config.enabled: true`.
   - Restart Synapse.
   - MAS sigue vivo idle (no destruir).

## Funciones del registry a crear

- `mas_client_register_bash_infra` — `mas-cli config sync` wrapper + validacion idempotente.
- `synapse_msc3861_enable_go_infra` — edita `homeserver.yaml` con bloque MAS + experimental_features.
- `mas_syn2mas_migration_bash_infra` — wrapper migracion con dry-run obligatorio + log archive.
- `wellknown_oidc_patch_go_infra` — anade `org.matrix.msc2965.authentication` al well-known JSON servido por nginx.
- `synapse_login_flows_check_go_infra` — health-check post-migracion (espera ver `m.login.sso` en flows).

## Acceptance

- [ ] `GET /_matrix/client/v3/login` devuelve `m.login.sso` con identity provider MAS.
- [ ] `GET /.well-known/matrix/client` contiene `org.matrix.msc2965.authentication.issuer`.
- [ ] Element Web redirige a MAS para login (no muestra form propio).
- [ ] Login con cuenta existente funciona post-migracion.
- [ ] Rooms historicos + msgs E2EE siguen visibles tras re-login.
- [ ] `password_config.enabled: false` no rompe nada (todo va por MAS).
- [ ] Backup pre-migracion subido + documentado.
- [ ] `docs/mas_migration_rollback.md` escrito + probado en staging (ver Notas).

## Definition of Done

### Mecanica
- `docker compose ps` muestra todos los containers healthy.
- `mas-cli config check` exit 0.
- `synapse curl /health` 200.
- Tests humo: login + send msg + recibe msg propagado a otra cuenta.

### Cobertura

| Escenario | Comando / evidencia | Resultado |
|---|---|---|
| Golden: login Element Web via MAS | navegador Incognito -> ` element-a05ae4.organic-machine.com` | redirect MAS -> login -> sesion activa |
| Edge: usuario migrado con E2EE setup previo | post-login en Element Web | rooms cifrados se descifran sin re-bootstrap |
| Edge: app servicio (bot) usa application_service token | bot envia msg | sigue funcionando (AS no pasa por MAS) |
| Edge: device verification cross-platform | Element Web verifica device PC Wails (post flow 0010) | OK |
| Error: token MAS expira mid-session | esperar TTL (default 5min refresh) | refresh automatico, no logout |
| Error: MAS cae (kill container) | matar `mas-1` 60s | Synapse rechaza nuevos logins; sessiones activas siguen (access_token cached); restart MAS -> recovery |

### Vida util validada (7 dias post-migracion)

| Metrica | Umbral | Donde | Ventana |
|---|---|---|---|
| Login failures (causa MAS) | `< 1%` | `mas` logs + sentry-like | 7 dias |
| Latency `/oauth2/token` | `p95 < 500ms` | nginx access log VPS | 7 dias |
| Crashes MAS / Synapse | `0` | `docker logs --since` | 7 dias |
| Users migrados activos | `>= 95%` | `mas-cli admin user list` vs sesiones activas | 7 dias |

### Anti-criterios
- NO marcar done si algun usuario migrado pierde acceso a rooms cifrados.
- NO marcar done si Element Web sigue mostrando form de password (legacy flow).
- NO marcar done si rollback documentado no se ha probado al menos una vez en staging.

## Notas

**Staging recomendado:** levantar stack identico en VPS test o WSL local con docker-compose + datos fake antes de tocar prod. organic-machine.com lleva 6 semanas viva.

**Element Call (LiveKit):** ya usa OIDC del homeserver para tokens via `livekit-jwt` container -> migracion debe verificar que tokens siguen emitiendose contra el MAS auth.

**Synapse-Admin compat:** synapse-admin v0.10+ soporta MSC3861. Verificar version corriendo. Si vieja, bump O reemplazar por panel propio (issue 0163).

**Gotcha critico — shared_secret:**
- `mas/config.yaml` tiene `matrix.secret` que debe matchear `homeserver.yaml.matrix_authentication_service.secret`.
- Generar con `openssl rand -hex 32` si no existe.
- Si no matchean: Synapse rechaza requests MAS con 401.

**Gotcha — application_service tokens:**
- Los AS (bridges, bots) NO pasan por MAS. Siguen usando `as_token`/`hs_token` de su registration.
- `agents_and_robots` usa application_service? Verificar antes — si SI, no afecta. Si usa password login normal, tendra que pasar por MAS (re-config).

**Roadmap post-DoD:**
- Habilitar `device_code` grant en MAS para login CLI futuro.
- Habilitar QR-code login (MSC4108) ya pre-config con `msc4108_delegation_endpoint`.
- Multi-factor (TOTP) en MAS — config available.

## Capability growth log

- v0.1.0 (2026-05-24) — issue creada.
