Externalises what this session held that the migrated repo did not: - vision/threadnet.md: the three capabilities that justify the forks beyond rebranding (AV scanning into encrypted rooms, call-quality defaults with a client-side-only privacy line, expiring guest access via @concierge). - issue 0043 (M5): case-insensitive uniqueness in the matrix-invitation prompt stage — the open residual of ADR-0011. - issue 0044 (M5): auto-restart consumers on SOPS values-secret change — the footgun behind the on_conflict fix sitting inactive until a manual restart. - issue 0045 (M1): report_event.admin_message_md unset — content reports dead-end with no contact path (verified still open against live config). - sources/protokolle: the raw apo-call diagnosis history, including the four ruled-out hypotheses and the harmful DB write, as the source behind the AAR. STATUS.md regenerated (M5 appears for the first time). validate, gen_status --check, upstream_drift and pruefe_prosa all green in the CI image.
78 lines
4.2 KiB
Markdown
78 lines
4.2 KiB
Markdown
# Protokoll — Diagnose „@apo kann nicht telefonieren" (2026-08-11)
|
|
|
|
Rohes Verlaufsprotokoll der Fehlersuche, als Quelle zum AAR
|
|
[docs/aar/2026-08-11-apo-calls-profile-zeile.md](../../aar/2026-08-11-apo-calls-profile-zeile.md).
|
|
Der AAR verdichtet zu Befund und Lehre; dieses Protokoll hält die tatsächliche
|
|
Reihenfolge fest — **inklusive der Irrwege**, weil die Frage „wie konnte sich die
|
|
Diagnose so lange verlaufen?" nur am ungekürzten Weg zu beantworten ist.
|
|
|
|
## Ausgangslage
|
|
|
|
`@apo` konnte sich anmelden und schreiben, aber kein Call kam zustande. Dem
|
|
vorausgegangen war ein längerer Vorgang mit mehreren manuellen Eingriffen an
|
|
`@apo`s Konto, die das Problem nicht gelöst hatten — darunter ein selbst
|
|
ausgedachter, in die MAS-Produktions-DB geschriebener `sub`-Wert und das Beenden
|
|
aller Sitzungen. Diese Eingriffe waren real schädlich und haben Vertrauen und Zeit
|
|
gekostet; sie sind der Grund, warum der Nutzer auf strukturiertem Vorgehen bestand.
|
|
|
|
## Die vier Irrwege (jeder an einer Messung gescheitert)
|
|
|
|
1. **Fehlende Cross-Signing-Verifikation.** Entkräftet: `sorb`/`clark` haben
|
|
ebenfalls keine und telefonieren.
|
|
2. **Kaputter Browser-/Client-Zustand.** Entkräftet: ein frischer Client zeigte
|
|
dasselbe Verhalten → an das Konto gebunden, nicht an den lokalen Zustand.
|
|
3. **Safari-Spezifik.** Zurückgezogen.
|
|
4. **MAS↔Synapse-Geräte-Desync.** Entkräftet: beide Seiten kannten dieselben drei
|
|
Geräte.
|
|
|
|
Das Muster war der eigentliche Fehler: aus dem, was serverseitig sichtbar war,
|
|
wurde wiederholt auf eine Ursache geschlossen, ohne sie an einem funktionierenden
|
|
Konto gegenzuprüfen. Der teuerste Einzelfall war der erfundene `sub`-Wert —
|
|
`clark` hätte die Formel sofort widerlegt, wäre sie vor dem Schreiben geprüft
|
|
worden.
|
|
|
|
## Die Kette, die zum Fund führte
|
|
|
|
1. **Vergleich statt Einzelbetrachtung.** `open_id_tokens` über *alle* aktiven
|
|
Nutzer abgefragt: `@apo` = 0, alle anderen zweistellig+. Damit war klar: der
|
|
Call-Pfad scheitert für `@apo` am allerersten Schritt (kein OpenID-Token).
|
|
2. **Confounder entfernt.** Der Testraum war **unverschlüsselt** — Krypto/
|
|
Cross-Signing damit in einem Schritt raus (der ganze Block „18 Pseudo-Geräte
|
|
aus 6 Resets" war eine Sackgasse).
|
|
3. **Live-Mitschnitt beim echten Call-Klick.** Ergebnis: *nichts* — kein
|
|
`openid/request_token`, kein `call.member`-Event. Beides erzeugt das
|
|
Element-Call-Widget-iframe; beide fehlten → das iframe wird nie aktiv.
|
|
4. **Der Nutzer-Hinweis „Anzeigename konnte nicht gesetzt werden"** lieferte den
|
|
500er mit vollständigem Stacktrace: `TypeError: 'NoneType' object is not
|
|
subscriptable` in `_check_profile_size`.
|
|
5. **Der Kontext-Hinweis des Nutzers** — „`apo` ist ein Konto von vor der
|
|
Authentik-Integration" — drehte die Suche von „angesammelter Müll" auf
|
|
„Provisionierungs-Lücke".
|
|
|
|
## Grundursache und Fix
|
|
|
|
`@apo` fehlte die Zeile in Synapses `profiles`-Tabelle (Deaktivieren löscht das
|
|
Profil, Reaktivieren legt es nicht neu an; `@apo` ging durch sechs Resets).
|
|
Fehlende Zeile → jeder Displayname-Schreibvorgang crasht → kein Displayname →
|
|
Element-Call-Widget initialisiert nie → kein OpenID-Token, kein Call. Fix: die
|
|
fehlende Registrierungs-Default-Zeile per `INSERT` nachgetragen, an `clark`/
|
|
`calltest01` gegengeprüft. Danach: Displayname setzbar, `open_id_tokens` 0→6, Call
|
|
verifiziert. `@apo` war der einzige betroffene lebende Nutzer.
|
|
|
|
## Nebenstrang: die Sicherheitslücke
|
|
|
|
Beim Anlegen des Testkontos entstand die case-sensitive Dublette `boje`/`Boje`.
|
|
Der Faden führte zu einem Kontoübernahme-Vektor: MAS stand auf
|
|
`on_conflict: add` und hätte kollidierende Localparts an bestehende Konten
|
|
verknüpft. Fix `on_conflict: fail` (ADR-0011), erst nach MAS-Neustart aktiv —
|
|
was die zweite Lehre lieferte: eine SOPS-Secret-Änderung startet den Dienst nicht
|
|
neu.
|
|
|
|
## Was das Protokoll dem AAR voraushat
|
|
|
|
Der AAR nennt die Lehren; dieses Protokoll zeigt, dass sie **teuer erkauft** waren:
|
|
vier eingesammelte Hypothesen und ein schädlicher DB-Schreib gingen dem einen
|
|
`open_id_tokens`-Vergleich voraus, der die Sache in Minuten entschied. Die Lehre
|
|
„erst vergleichen, dann schreiben" steht im AAR als Satz — hier steht, warum sie
|
|
einen Satz wert ist.
|