docs(PROJ-11): add technical design for chat feature

Direct browser-to-Synapse connection via matrix-js-sdk, backend only
mints a short-lived per-member access token (no chat proxy, no new
WebSocket server, no new DB table). Status set to In Progress.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
This commit is contained in:
patrickandClaude Sonnet 5 committed 2026-09-11 18:52:39 +02:00
1 parent 4cb2284ad9
commit 8b6114c3e8
2 files changed
+47 -1

No files matched your search

+1 -1
View File
@@ -22,7 +22,7 @@
| PROJ-8 | Audit Log | Deployed | [PROJ-8-audit-log.md](PROJ-8-audit-log.md) | 2026-09-11 |
| PROJ-9 | Synapse-Integration (Health Check, User Provisioning, Raum-Sync) | Deployed | [PROJ-9-synapse-integration-health-check.md](PROJ-9-synapse-integration-health-check.md) | 2026-09-11 |
| PROJ-10 | Deployment (Docker Compose + Synapse Installer) | Deployed | [PROJ-10-deployment.md](PROJ-10-deployment.md) | 2026-09-11 |
| PROJ-11 | Chat (Matrix Client-Server API) | Planned | [PROJ-11-chat.md](PROJ-11-chat.md) | 2026-09-11 |
| PROJ-11 | Chat (Matrix Client-Server API) | In Progress | [PROJ-11-chat.md](PROJ-11-chat.md) | 2026-09-11 |
| PROJ-12 | Automatische Löschfrist für ausgetretene Mitglieder (DSGVO) | Planned | [PROJ-12-mitglieder-loeschfrist.md](PROJ-12-mitglieder-loeschfrist.md) | 2026-09-11 |
Noch nicht gestartet (siehe [docs/PRD.md](../docs/PRD.md) Core Features): dedizierte Tenant-Isolation-Tests. P2 (Medien-Anhänge, Push) bewusst aus PROJ-11 ausgeklammert, siehe dessen Non-Goals.
+46
View File
@@ -44,3 +44,49 @@ Eigene Chat-Oberfläche für Team-Räume, die bereits über [[PROJ-9]] (Synapse-
## Notes
Matrix-Access-Token-Handling ist sicherheitsrelevant (Token-Mapping TalkTime-User → Matrix-User) — Architektur-Skill sollte hier besonders auf Token-Lifetime, Caching-Ort (nicht im Frontend!) und Re-Auth-Flow eingehen. `backend-security-coder`/`frontend-security-coder`-Subagenten bei der Umsetzung hinzuziehen.
## Tech Design (Solution Architect)
### A) Komponenten-Struktur
```
TeamsPage (bestehend)
└── Team-Detailansicht (bestehend, wird um Tabs erweitert)
├── Tab "Übersicht" (bestehend, unverändert)
└── Tab "Chat" (NEU)
├── Verbindungshinweis
│ ("Chat wird eingerichtet" | "Raum wird eingerichtet" | Verbindungsfehler)
├── Nachrichtenliste
│ ├── Nachrichten-Gruppen nach Tag
│ ├── Einzelne Nachricht (Absender, Zeit, Text)
│ └── Lesebestätigungs-Anzeige ("gelesen von: …")
├── Verlauf-Nachladen ("Ältere Nachrichten laden", beim Hochscrollen)
└── Eingabefeld + Senden-Button
```
Der Chat-Tab ist nur sichtbar/aktiv, wenn ein Team ausgewählt ist. Ungelesen-Zähler erscheint zusätzlich als kleines Badge auf der Team-Kachel/dem Tab selbst, damit Mitglieder neue Nachrichten auch außerhalb des offenen Chats bemerken.
### B) Datenfluss (in einfachen Worten)
TalkTime-Backend und Browser haben hier unterschiedliche Aufgaben:
1. **Backend (einmalig pro Sitzung):** Wenn der Chat-Tab geöffnet wird, fragt der Browser das TalkTime-Backend: "Gib mir Zugang zum Matrix-Chat." Das Backend prüft die normale TalkTime-Anmeldung (JWT), schaut nach, ob für dieses Mitglied schon ein Matrix-Konto existiert, und besorgt sich von Synapse — mit dem streng geheimen Admin-Zugang, der nie den Server verlässt — einen zeitlich befristeten Zugangsschlüssel *für genau dieses eine Mitglied*. Diesen Schlüssel bekommt der Browser, nicht den Admin-Zugang.
2. **Browser (laufend):** Mit diesem Schlüssel spricht der Browser direkt mit dem Matrix-Server (Synapse) — Nachrichten senden, neue Nachrichten empfangen (durch ständiges "gibt's was Neues?"-Nachfragen, das ist der Matrix-Standardmechanismus), Lesebestätigungen senden. Das TalkTime-Backend ist an diesem laufenden Austausch nicht mehr beteiligt und sieht die Nachrichteninhalte nicht — das passt zur Vorgabe, keine Nachrichteninhalte in der TalkTime-Datenbank zu speichern.
3. **Läuft der Zugangsschlüssel ab:** Der Browser merkt das am nächsten fehlgeschlagenen Versuch, fragt automatisch einen neuen beim Backend an und macht weiter — für das Mitglied unsichtbar, außer der allererste Versuch schlägt fehl (dann Fehleranzeige).
Kein neuer Datenspeicher in der TalkTime-Datenbank nötig — Mitglied-zu-Matrix-Zuordnung existiert bereits (`matrixUserId` aus [[PROJ-9]]), Nachrichten selbst liegen ausschließlich bei Synapse.
### C) Tech-Entscheidungen (Begründung)
- **Direkte Verbindung Browser ↔ Synapse statt Umweg über TalkTime-Backend:** Das TalkTime-Backend müsste sonst für jeden gleichzeitig aktiven Chat eine eigene Dauerverbindung zu Synapse offenhalten — das skaliert schlecht und macht das Backend zum Nadelöhr. Bei einer direkten Verbindung übernimmt Synapse selbst diese Last, wofür es gebaut ist.
- **Offizielle Matrix-Client-Bibliothek (matrix-js-sdk) statt Marke-Eigenbau:** Nachrichten-Abgleich, "was ist neu"-Erkennung und Lesebestätigungen nach Matrix-Standard sind fummelig selbst zu bauen und fehleranfällig. Die Bibliothek ist der De-facto-Standard für genau diesen Zweck.
- **Zugangsschlüssel wird vom Backend ausgestellt, nie ein Matrix-Passwort:** Mitglieder haben laut PRD kein eigenes Matrix-Passwort (DSGVO-Ziel: kein zusätzliches Konto-Geheimnis). Das Backend nutzt seinen Admin-Zugang, um im Namen des Mitglieds einen befristeten Schlüssel zu erzeugen, ohne ein Passwort zu kennen oder zu speichern.
- **Kein eigener Push-/WebSocket-Server:** Für "grundlegenden Chat" reicht der Matrix-Standardmechanismus; ein eigener Echtzeit-Server wäre zusätzlicher Betriebsaufwand ohne Mehrwert in diesem Umfang.
### D) Abhängigkeiten (neue Pakete)
- **Frontend:** `matrix-js-sdk` — offizielle Matrix-Client-Bibliothek, übernimmt Verbindungsaufbau, Nachrichtenabgleich, Lesebestätigungen
- **Backend:** keine neuen Pakete — nutzt die bereits vorhandene Synapse-Anbindung aus [[PROJ-9]]
### Offene Infrastruktur-Voraussetzung
Damit der Browser Synapse direkt erreichen kann, muss der Matrix-Server auch außerhalb des internen Netzes (bzw. für alle Nutzer-Endgeräte) erreichbar sein, inklusive TLS — aktuell (Testaufbau) läuft Synapse nur auf der internen LXC-IP ohne TLS. Das ist eine Deployment-Voraussetzung für den produktiven Einsatz dieses Features, keine Backend-/Frontend-Codeänderung.