From f3417a4b241f3929ab258efe9ca39c0eb414cf18 Mon Sep 17 00:00:00 2001 From: Thore Cimbal Date: Tue, 11 Aug 2026 12:00:00 +0000 Subject: [PATCH] docs: capture session knowledge not yet in the repo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- STATUS.md | 7 +- ...tion-flow-eindeutigkeit-case-insensitiv.md | 38 +++++++++ ...cret-aenderung-startet-dienst-nicht-neu.md | 41 ++++++++++ ...eport-event-kein-kontaktweg-fuer-melder.md | 33 ++++++++ .../protokoll-2026-08-11-apo-call-diagnose.md | 77 +++++++++++++++++++ docs/wiki/vision/threadnet.md | 22 ++++++ 6 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 docs/issues/0043-invitation-flow-eindeutigkeit-case-insensitiv.md create mode 100644 docs/issues/0044-sops-secret-aenderung-startet-dienst-nicht-neu.md create mode 100644 docs/issues/0045-report-event-kein-kontaktweg-fuer-melder.md create mode 100644 docs/sources/protokolle/protokoll-2026-08-11-apo-call-diagnose.md diff --git a/STATUS.md b/STATUS.md index 0df6e8d..67b895f 100644 --- a/STATUS.md +++ b/STATUS.md @@ -2,9 +2,9 @@ -## Issues (36 open, 0 closed) +## Issues (39 open, 0 closed) -Verteilung: M1 9 · M2 25 · M4 2 +Verteilung: M1 10 · M2 25 · M4 2 · M5 2 | Issue | Status | Meilenstein | Priorität | Title | |---|---|---|---|---| @@ -44,6 +44,9 @@ Verteilung: M1 9 · M2 25 · M4 2 | [0040](docs/issues/0040-neckbeard-rueckmeldungen-einreichen.md) | open | M2 | low | neckbeard-Rückmeldungen aus dem Feldtest einreichen | | [0041](docs/issues/0041-wartegrund-der-importierten-waiting-issues.md) | open | M2 | low | wartegrund der 7 importierten waiting-Issues präzisieren | | [0042](docs/issues/0042-migration-in-betrieb-nehmen-push-spiegel-schedule.md) | open | M2 | high | Migration in Betrieb nehmen: Push, erster Spiegel-Lauf, CI-Schedule | +| [0043](docs/issues/0043-invitation-flow-eindeutigkeit-case-insensitiv.md) | open | M5 | medium | Invitation-Flow: case-insensitive Eindeutigkeitsprüfung im Prompt-Stage | +| [0044](docs/issues/0044-sops-secret-aenderung-startet-dienst-nicht-neu.md) | open | M5 | low | SOPS-Values-Secret-Änderung startet den konsumierenden Dienst nicht neu | +| [0045](docs/issues/0045-report-event-kein-kontaktweg-fuer-melder.md) | open | M1 | low | Inhalts-Meldung führt ins Leere: kein Kontaktweg für Melder | ## Active design docs (0) diff --git a/docs/issues/0043-invitation-flow-eindeutigkeit-case-insensitiv.md b/docs/issues/0043-invitation-flow-eindeutigkeit-case-insensitiv.md new file mode 100644 index 0000000..e6d6a3a --- /dev/null +++ b/docs/issues/0043-invitation-flow-eindeutigkeit-case-insensitiv.md @@ -0,0 +1,38 @@ +--- +type: issue +id: "0043" +status: open +created: 2026-08-11 +milestone: M5 +priority: medium +area: security +related: [docs/adr/0011-enrollment-localpart-kollision-verweigern.md] +--- +# Invitation-Flow: case-insensitive Eindeutigkeitsprüfung im Prompt-Stage + +> Offener Rest aus [ADR-0011](../adr/0011-enrollment-localpart-kollision-verweigern.md); GitLab-seitig als [gitops#61](https://git.lab/axion1337.chat/axion1337.chat-gitops/-/issues/61) verfolgt. + +## Problem / Motivation + +Die Kontoübernahme über kollidierende Localparts ist geschlossen — MAS steht auf +`on_conflict: fail` (ADR-0011, live nach MAS-Neustart). Das ist die harte +Sicherheitsgrenze, aber sie greift erst **beim Login**: Ein Nutzer, der bei der +Registrierung einen bereits vergebenen Namen (oder eine Schreibweise-Variante wie +`boje` neben `Boje`) wählt, bekommt kein Feedback im Flow, sondern läuft später in +einen fehlgeschlagenen Login. Authentiks eigene Eindeutigkeit ist case-sensitive +und deckt Kollisionen mit bestehenden Matrix-Konten nicht ab. + +## Acceptance + +- Der `matrix-invitation`-Flow prüft im Prompt-Stage den gewünschten + Benutzernamen **case-insensitive** gegen bestehende Konten und weist eine + Kollision schon bei der Registrierung sichtbar ab. +- Als Blueprint reproduzierbar (`apps/authentik/authentik-blueprints.yaml`), nicht + nur als Klick im Admin-UI. +- Gegenprobe: Registrierung mit einem existierenden Namen in abweichender + Schreibweise scheitert im Flow, nicht erst beim Login. + +## Notes + +Rein defensive Ergänzung / UX — der Übernahme-Vektor selbst ist bereits zu. +Deshalb M5 (Härtung, nicht Reparatur) und `priority: medium`. diff --git a/docs/issues/0044-sops-secret-aenderung-startet-dienst-nicht-neu.md b/docs/issues/0044-sops-secret-aenderung-startet-dienst-nicht-neu.md new file mode 100644 index 0000000..87d19ee --- /dev/null +++ b/docs/issues/0044-sops-secret-aenderung-startet-dienst-nicht-neu.md @@ -0,0 +1,41 @@ +--- +type: issue +id: "0044" +status: open +created: 2026-08-11 +milestone: M5 +priority: low +area: infrastructure +related: [docs/adr/0011-enrollment-localpart-kollision-verweigern.md] +--- +# SOPS-Values-Secret-Änderung startet den konsumierenden Dienst nicht neu + +## Problem / Motivation + +Beim Ausrollen des `on_conflict: fail`-Fixes (ADR-0011) trat ein Footgun zutage: +Flux aktualisierte das SOPS-verwaltete Secret `ess-mas-values-secret`, aber der +laufende MAS-Pod war älter als die Änderung und behielt die alte Config im +Speicher — MAS liest seine Config nur beim Start. Der Sicherheits-Fix stand auf +der Platte, war im Prozess aber **nicht aktiv**, bis ein manueller +`kubectl rollout restart` folgte. „committet ≠ deployed ≠ aktiv." + +Das betrifft nicht nur MAS: jeder Dienst, der ein von Flux/SOPS gepflegtes +Values-Secret nur beim Start liest, hat dieselbe stille Lücke. Aktuell ist die +einzige Absicherung die in ADR-0011 festgeschriebene **manuelle** Restart-und- +Verifikations-Regel — leicht zu vergessen. + +## Acceptance + +- Änderungen an einem konsumierten Values-Secret lösen automatisch einen Rollout + des abhängigen Deployments aus (z. B. Checksum-/Hash-Annotation auf dem + Pod-Template, ein Reloader wie stakater/Reloader, oder ein + `configMapGenerator`/`secretGenerator`-Namenshash in kustomize). +- Verifiziert an MAS: Änderung am Secret → neuer Pod ohne Handeingriff, jünger als + die Änderung. +- Mindestens MAS abgedeckt; idealerweise als wiederverwendbares Muster für weitere + von SOPS-Secrets gespeiste Dienste. + +## Notes + +Automatisiert nur den bereits in ADR-0011 vorgeschriebenen manuellen Schritt — +daher `priority: low`. M5, weil die Fähigkeit (Auto-Reload) neu ist, nicht kaputt. diff --git a/docs/issues/0045-report-event-kein-kontaktweg-fuer-melder.md b/docs/issues/0045-report-event-kein-kontaktweg-fuer-melder.md new file mode 100644 index 0000000..e7fd29e --- /dev/null +++ b/docs/issues/0045-report-event-kein-kontaktweg-fuer-melder.md @@ -0,0 +1,33 @@ +--- +type: issue +id: "0045" +status: open +created: 2026-08-11 +milestone: M1 +priority: low +area: element +related: [] +--- +# Inhalts-Meldung führt ins Leere: kein Kontaktweg für Melder + +## Problem / Motivation + +Der Web-Client kann Inhalte melden (`report_event`), aber +`report_event.admin_message_md` ist in `element-values.yaml` **nicht gesetzt** +(Stand 2026-08-11 gegen die Live-Config geprüft). Wer etwas meldet, sieht danach +keinen Kontaktweg — keine Angabe, an wen die Meldung geht oder wo man nachfassen +kann. Für einen Community-Betrieb mit Moderation (Draupnir) ist das eine offene +Kante: Melden funktioniert technisch, führt für den Nutzer aber ins Leere. + +## Acceptance + +- `report_event.admin_message_md` in + `apps/production/custom-configs/element-values.yaml` gesetzt, mit einem echten + Kontakt-/Meldeweg (Moderationsraum oder Kontaktadresse). +- Live sichtbar: nach einer Meldung erscheint der hinterlegte Hinweis. + +## Notes + +Braucht **eine Angabe von sorb**: welcher Raum bzw. Kontakt der Meldeweg sein +soll. Danach ist es eine Zeile Config. Bewusst nicht auf `waiting` gesetzt, weil +noch nicht begonnen — der fehlende Input ist im Text benannt. diff --git a/docs/sources/protokolle/protokoll-2026-08-11-apo-call-diagnose.md b/docs/sources/protokolle/protokoll-2026-08-11-apo-call-diagnose.md new file mode 100644 index 0000000..4ee7a83 --- /dev/null +++ b/docs/sources/protokolle/protokoll-2026-08-11-apo-call-diagnose.md @@ -0,0 +1,77 @@ +# 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. diff --git a/docs/wiki/vision/threadnet.md b/docs/wiki/vision/threadnet.md index bcbfdbb..6cc72eb 100644 --- a/docs/wiki/vision/threadnet.md +++ b/docs/wiki/vision/threadnet.md @@ -25,6 +25,28 @@ threadnet-operating. chirurgische Patches statt Umbauten. - CI beweist Releases: Tag → Pipeline → Artefakt, keine Handbuilds. +## Was die Forks über das Rebranding hinaus leisten + +Das Rebranding ist die sichtbarste, aber nicht die eigentliche Rechtfertigung der +Forks. Drei Fähigkeiten gehen bewusst über Upstream hinaus und sind der Grund, +dass ThreadNet eine eigene Produkt-Linie ist und kein umgefärbtes Element: + +- **Virenprüfung bis in verschlüsselte Räume.** Upstream Element scannt Uploads + nur serverseitig und nur in unverschlüsselten Räumen. ThreadNet-Web ruft den + Scan client-seitig **beim Senden und beim Empfangen** auf — damit greift die + Prüfung auch in verschlüsselten Räumen und DMs, wo der Server den Inhalt nie + sieht. Das ist die inhaltliche Begründung des Web-Forks, nicht die Optik. +- **Call-Qualität als Voreinstellung, Privatsphäre als Grenze.** threadnet-call + hebt die Medien-Defaults an (bis 1440p/60fps, H.264 für Hardware-Beschleunigung + v.a. auf iOS/Safari) und lässt die Rauschunterdrückung **bewusst + client-seitig** — kein server-seitiges ML, das bereinigtes Audio anderer + Teilnehmer verarbeiten würde. Startwerte, keine harten Grenzen; die + Privatsphäre-Linie ist die harte. +- **Gäste mit Ablaufdatum.** Registrierung läuft ausschließlich über Authentik; + der @concierge-Bot macht daraus einen nachvollziehbaren Vorgang mit eingebautem + Ablauf und zweiteiliger Berechtigung — die Gruppe entscheidet, der Raum macht + sichtbar, wer wen eingeladen hat. + ## Veröffentlichungsgrad **Die Forks werden öffentlich** (entschieden 2026-08-06) — aber erst nach einem