# ThreadNet-Web: Fork-Anpassungen für axion1337.chat Dieses Dokument beschreibt alles, was dieser Fork gegenüber Upstream Element Web ändert. Der Rest der `docs/`-Ordner-Dateien und das Root-`README.md` sind unverändertes Upstream-Material und beschreiben absichtlich **nicht** diese Anpassungen - diese Datei ist der zentrale Anlaufpunkt dafür. ## 1. Discord-Style Room-List (Call-Teilnehmer in der Raumliste) Zeigt aktive Call-Teilnehmer direkt in der Raumliste an (ähnlich Discords Voice-Channel-UI), statt nur einen generischen "Call läuft"-Indikator. Betroffene Komponenten: `apps/web/src/room-list/RoomListItemView/RoomListItemView.tsx` und `RoomListItemView.module.css` (vertikale Ausrichtung der Teilnehmer-Avatare). ## 2. Client-seitiges ClamAV-Content-Scanning (Issue #19-Erweiterung) Der Server-seitige Content-Scanner (Synapse-Modul, siehe gitops-Repo [`docs/deployment-guides/06-moderation-content-scanning.md`](https://rohana.axion1337.de/sorb/axion1337.chat-gitops/src/branch/main/docs/deployment-guides/06-moderation-content-scanning.md)) sieht bei Ende-zu-Ende-verschlüsselten Räumen nur Ciphertext - eine strukturelle Grenze, kein Bug. Da dieser Client bereits geforkt wird, scannt er stattdessen selbst, auf beiden Seiten: - **Senden** (`apps/web/src/ContentMessages.ts`, `uploadFile()`): liest die Datei als ArrayBuffer, scannt sie über `scanContent()` **bevor** verschlüsselt/hochgeladen wird - der Upload wird bei Treffer gar nicht erst gestartet. - **Empfangen** (`apps/web/src/utils/DecryptFile.ts`, `decryptFile()`): scannt die entschlüsselten Bytes direkt nach dem Entschlüsseln, bevor das Blob an die UI zurückgegeben wird - schützt auch vor Dateien von unveränderten/fremden Matrix-Clients, die diesen Patch nicht haben. - Gemeinsame Scan-Logik: `apps/web/src/utils/ContentScanner.ts` - ruft den (im gitops-Repo deployten) `clamav-http-scanner`-Dienst per `fetch("/_scan", ...)` auf, mit dem eigenen Matrix-Access-Token als Bearer-Auth. Fail-open bei Netzwerk-/Scanner-Fehlern (blockiert Uploads/Downloads nicht bei einem Ausfall des Scanners). - Neuer Fehlertyp `ContentScanRejectedError`, verdrahtet durch die bestehenden Fehler-Rendering-Pfade in `MImageBody.tsx`, `MAudioBody.tsx`, `VideoBodyViewModel.ts`, `FileBodyViewModel.ts`. - Live getestet inkl. Hostile-Sender-Simulation (Datei per rohem API-Call ohne diesen Patch gesendet, Empfangs-Hook hat trotzdem geblockt). ### ⚠️ Bekannte Lücke: Electron/Desktop (Issue #2) Dieser Fix ist bestätigt nur für den **Web-Client-Build** wirksam. Der Electron-Desktop-Client bekommt ihn aktuell **nicht automatisch** - die CI-Workflow-Kette (`build_ew`-Job) checkt weiterhin `element-hq/element-web` (Upstream) statt diesen Fork aus, und es ist kein GitHub- Actions-Runner für dieses Repo registriert. Der aktuell veröffentlichte Desktop-Build (`desktop-v1.12.17-clientscan` Release) wurde manuell gebaut, nicht automatisiert. Details und Fix-Plan: [Issue #2](https://rohana.axion1337.de/sorb/ThreadNet-Web/issues/2). ## 3. Build-Fixes (historisch, Issue #12) Zwei Bugs blockierten einen vollständigen `docker build` von Grund auf (mussten für den Client-Scanning-Rebuild oben behoben werden): (1) mehrere Shell-Skripte waren mit Modus 644 statt 755 committet (nicht ausführbar); (2) der `matrix-js-sdk#develop`-Git-Ref-Pin in `pnpm-lock.yaml` war veraltet (fehlte `src/oidc/authorize.ts`, das `apps/web` importiert). Beide behoben. ## 4. Merge-Reibung: was ein Upstream-Update wirklich kostet *Arbeitspaket 3 aus ThreadNet-Web#7. Gemessen am 2026-08-06, nicht geschätzt.* ### Die unangenehme Grundlage zuerst **Dieses Repo enthält keine Upstream-Historie.** Element Web 1.12.17 wurde am 2026-05-10 als kompletter Baum importiert — und zwar in `3da3635`, zusammen mit dem ersten eigenen Feature im selben Commit. Davor liegt nur ein `Initial commit` mit zwei Dateien. Daraus folgt das Wesentliche: **es gibt keinen gemeinsamen Vorfahren mit `element-hq/element-web`.** Ein `git merge upstream/develop` ist nicht möglich; mit `--allow-unrelated-histories` erzwungen, kollidiert praktisch jede Datei. Wer „mal eben Upstream nachziehen" sagt, meint in diesem Repo also: neuen Upstream-Stand beschaffen und unsere Änderungen darauf neu auftragen. Das ist der Grund, warum die Zahl unten überhaupt zählt — sie ist der Aufwand jedes Updates. ### Unser Delta: 102 Dateien, davon 12 kritische `git diff --name-only 3da3635..main`: | Menge | Bereich | Konfliktrisiko | |---|---|---| | 46 | CI/Build (`.github/`, `.gitlab-ci.yml`, `dockerbuild/`) | gering — eigene Strecke, Upstreams Workflows brauchen wir nicht | | 22 | Config, Lockfiles, Upstream-Varianten | mittel — `pnpm-lock.yaml` konfliktet immer, wird aber regeneriert | | 13 | Web-Assets (`apps/web/res/`) | gering — meist eigene Dateien | | 4 + 3 | eigene Icons und `apps/desktop/axion1337/` | **keins** — kein Upstream-Pendant | | **12** | **Upstream-Quellcode** | **hier entsteht die Arbeit** | ### Die 12 Dateien, und warum sie angefasst wurden **Branding (5)** — flach, gut isolierbar: - `apps/web/src/SdkConfig.ts` — Defaults für `brand`, `welcome_background_url`, `desktopBuilds` - `apps/web/src/vector/index.html` — ``, Favicon-Link, PWA-Namen - `apps/web/src/async-components/structures/ErrorView.tsx` — Logo der Fehlerseite - `apps/web/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx` — Attribution + Danksagung - `apps/web/src/i18n/strings/en_EN.json` — einzelne Strings **ClamAV-Client-Scanning (7)** — tief in der Medien-Pipeline: - `apps/web/src/ContentMessages.ts`, `utils/ContentScanner.ts`, `utils/DecryptFile.ts` - `apps/web/src/components/views/messages/MImageBody.tsx`, `MAudioBody.tsx` - `apps/web/src/viewmodels/message-body/FileBodyViewModel.ts`, `VideoBodyViewModel.ts` ⚠️ **Die zweite Gruppe ist die teure.** Element baut die Medien-Anzeige gerade auf MVVM um (`docs/MVVM.md`, `docs/MVVM-v1.md`) — die beiden `viewmodels/`-Dateien existierten in älteren Ständen gar nicht. Genau dort, wo wir eingegriffen haben, bewegt sich Upstream also aktiv. Ein Update wird an ClamAV mehr Arbeit machen als am gesamten Branding zusammen. ### Was daraus für künftige Änderungen folgt 1. **Erst prüfen, ob es die Konfiguration schon kann.** Auth-Logo, `logo_link_url` und `brand` liefen ohne Rebuild über die ConfigMap; das Call-Widget wurde vollständig über `VITE_PRODUCT_NAME` umbenannt, ohne eine einzige Quelldatei. Jede so vermiedene Datei ist eine, die beim Update nicht kollidiert. 2. **Eigene Datei schlagen geänderte Datei.** `apps/desktop/axion1337/` und eigene Assets kosten beim Merge nichts. 3. **Wenn Upstream-Code sein muss: einen Kommentar mit `ThreadNet-Fork:` und der Begründung dazu.** Beim Neuauftragen auf einen neuen Stand ist die Frage nie „was steht hier", sondern „warum stand das da" — und die beantwortet sonst niemand mehr. ## Repo-Topologie (seit 2026-07-31) **Kanonisch ist `git.lab/axion1337.chat/ThreadNet-Web`** (Homelab-GitLab, nur im Lab auflösbar) — dort laufen Entwicklung und CI (`.gitlab-ci.yml`). Die Kopie auf `rohana.axion1337.de/sorb/ThreadNet-Web` ist ein **Push-Mirror** (automatisch, GitLab → Gitea) und dient als Lesekopie plus Standort für Issues, Container-Registry und Releases. **Niemals direkt nach rohana pushen** — der Mirror überschreibt divergente Stände.