feat(matrix): MAS migration helpers + 2 flows + 15 issues + capability group
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>
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
---
|
||||
name: synapse_login_flows_check
|
||||
kind: function
|
||||
lang: go
|
||||
domain: infra
|
||||
version: "0.1.0"
|
||||
purity: impure
|
||||
signature: "func SynapseLoginFlowsCheck(cfg SynapseLoginFlowsCheckConfig) (SynapseLoginFlowsCheckResult, error)"
|
||||
description: "Verifica que el endpoint /_matrix/client/v3/login del homeserver Synapse devuelve m.login.sso con el IdP de MAS esperado y que m.login.password está desactivado. Hace polling con reintentos hasta confirmar el estado post-migración o agotar los intentos."
|
||||
tags: [matrix, mas, synapse, login, healthcheck, migration, mas-migration, infra, matrix-mas]
|
||||
params:
|
||||
- name: HomeserverURL
|
||||
desc: "URL pública del homeserver (ej. https://matrix-af2f3d.organic-machine.com). Sin trailing slash."
|
||||
- name: ExpectedSsoIdpID
|
||||
desc: "Identificador del IdP MAS esperado en m.login.sso.identity_providers[].id (ej. oidc-mas). Vacío = solo verificar que m.login.sso exista, sin comprobar IdP concreto."
|
||||
- name: MaxRetries
|
||||
desc: "Número máximo de intentos HTTP antes de abortar. Default: 10."
|
||||
- name: RetryDelaySeconds
|
||||
desc: "Segundos de espera entre intentos. Default: 3. Synapse tarda 10-30s en levantar tras restart."
|
||||
- name: HttpTimeoutSeconds
|
||||
desc: "Timeout HTTP por intento en segundos. Default: 5."
|
||||
output: "SynapseLoginFlowsCheckResult{Flows, SsoPresent, IdpFound, PasswordEnabled, LastResponseJSON, AttemptsUsed}. Error nil = migración confirmada. Error CONVERGENCE_FAILED = no convergió tras MaxRetries."
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: ["encoding/json", "fmt", "io", "net/http", "strings", "time"]
|
||||
tested: true
|
||||
tests:
|
||||
- "SSO + IdP expected -> success on first attempt"
|
||||
- "legacy response then SSO on 3rd attempt -> success after retries"
|
||||
- "response never changes -> error after maxRetries"
|
||||
- "HTTP timeout -> error"
|
||||
- "malformed JSON -> error"
|
||||
test_file_path: "functions/infra/synapse_login_flows_check_test.go"
|
||||
file_path: "functions/infra/synapse_login_flows_check.go"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
cfg := SynapseLoginFlowsCheckConfig{
|
||||
HomeserverURL: "https://matrix-af2f3d.organic-machine.com",
|
||||
ExpectedSsoIdpID: "oidc-mas",
|
||||
MaxRetries: 10,
|
||||
RetryDelaySeconds: 3,
|
||||
HttpTimeoutSeconds: 5,
|
||||
}
|
||||
res, err := SynapseLoginFlowsCheck(cfg)
|
||||
if err == nil && res.SsoPresent && !res.PasswordEnabled {
|
||||
fmt.Printf("MAS migration confirmed after %d attempt(s)\n", res.AttemptsUsed)
|
||||
// Continue with post-migration smoke tests
|
||||
} else if err != nil {
|
||||
fmt.Printf("Migration NOT confirmed: %s\n", err.Message)
|
||||
fmt.Printf("Last response: %s\n", res.LastResponseJSON)
|
||||
}
|
||||
```
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Usar en el paso 6 del issue 0162 (migración Synapse→MAS), inmediatamente tras reiniciar Synapse con MSC3861 activado. También útil como `e2e_check` continuo en `app.md` del servicio Synapse para detectar regresiones (ej. alguien comenta `msc3861.enabled: true` por error y vuelve a activar password login).
|
||||
|
||||
```yaml
|
||||
# En app.md del servicio matrix:
|
||||
e2e_checks:
|
||||
- id: mas_login_flows
|
||||
cmd: "go run . -check-login-flows https://matrix-af2f3d.organic-machine.com oidc-mas"
|
||||
expect_stdout_contains: "MAS migration confirmed"
|
||||
timeout_s: 60
|
||||
```
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Synapse tarda 10-30s en levantar** tras restart — los defaults (MaxRetries=10, RetryDelaySeconds=3) cubren 30s de espera total.
|
||||
- **PasswordEnabled == true post-migración**: probablemente `password_config.enabled: false` no se aplicó en `homeserver.yaml` o fue sobreescrito por include. Verificar config antes de reintentar.
|
||||
- **IdP id incorrecto**: el id del IdP depende de `mas/config.yaml` → sección `matrix.homeserver`. Verificar el valor exacto con `GET /_matrix/client/v3/login` manual antes de pasar a `ExpectedSsoIdpID`.
|
||||
- **TLS no válido**: si el certificado del HomeserverURL no es verificable, `net/http` retorna error de TLS — la función lo propaga como FETCH_ERROR con el mensaje original de Go (no lo ignora silenciosamente).
|
||||
- **Non-200 responses**: cualquier status HTTP != 200 se trata como error de fetch y dispara reintento.
|
||||
- **ExpectedSsoIdpID vacío**: solo verifica presencia de `m.login.sso` y ausencia de `m.login.password`. Suficiente para validación rápida; usar el ID completo para health-check de producción.
|
||||
Reference in New Issue
Block a user