#0099 geschlossen: Upstream-Anschluss vollzogen, v0.6.0 in Produktion

ThreadNet-Web:main auf 8ca03fe, Merge-Commit 88c4e15 mit beiden echten Eltern.
GHSA-wrcp-5v3v-3j6v ist mit dem Versionssprung erledigt.

Drei Anlaeufe: rc.1 erzeugte kein Image (.npmrc fehlte im Docker-Kontext, unter
pnpm 11 fatal), rc.2 ging live und brach die Raumliste, rc.3 bestand die Abnahme.

ADR-0022 um zwei Korrekturen ergaenzt, die erst die Ausfuehrung gezeigt hat:

Die stille Klasse verschwindet nicht ganz, sie dreht sich um. Der Merge meldet,
wenn Upstream eine Datei verschiebt - das hat gehalten. Er meldet nicht, wenn
beide Seiten die Aufloesung ueberleben und nur eine noch Sinn ergibt. Genau das
brach rc.2.

Und: ein gruener Build war nie eine Abnahme. Der web-Job baut nur, webpack
wirft Typen weg. tsc meldete den Fehler durchgehend, gefragt hatte ihn niemand.
Seit 8ca03fe fuehrt docker_web den Job typecheck als needs.

Daraus die stehende Regel fuer kuenftige Merges: nach der Konfliktaufloesung auf
ueberlebende Reste pruefen, nicht nur auf verlorene Zeilen. Wo Zeichenketten
statt Typen im Spiel sind, braucht es einen Abgleich gegen die Registry - fuer
Einstellungen einmalig gefahren, 135 abgefragte gegen 152 registrierte.
This commit is contained in:
Thore Cimbal
2026-08-19 12:00:00 +00:00
parent bae97e6ca6
commit 6652125ed3
3 changed files with 123 additions and 4 deletions
@@ -73,3 +73,31 @@ und ohne diese Messung wäre der Merge auf eine erfundene Grundlage gelaufen.
empfangen) ist der Merge nicht abgenommen.
- Schritt 4 aus #0099 — ein Verfahren zum Auftragen der Patches — wird damit
gegenstandslos.
## Nachtrag 2026-08-19: ausgeführt, und was die Ausführung korrigiert
Vollzogen. `ThreadNet-Web:main` steht auf `8ca03fe`, der Merge-Commit `88c4e15` trägt
beide echten Eltern. Produktion läuft auf `v0.6.0`. Zwei Annahmen dieser ADR haben sich
in der Praxis verschoben:
**Die stille Klasse verschwindet nicht ganz — sie dreht sich um.** Die Entscheidung
begründet sich damit, dass Git künftig meldet, wenn Upstream eine Datei verschiebt, die
wir angefasst haben. Das hat gehalten (`RoomListItemWrapper`-Umbenennung wurde als
Konflikt gemeldet). Was ein Drei-Wege-Merge **nicht** meldet, ist der umgekehrte Fall:
Beide Seiten überleben die Auflösung, aber nur eine ergibt noch Sinn. Genau das brach
`v0.6.0-rc.2` in Produktion — eine `getValue`-Zeile auf einen von Upstream entfernten
Einstellungsschlüssel, die niemand mehr liest und die trotzdem wirft.
**Ein grüner Build ist keine Abnahme, und war nie eine.** Diese ADR sagt richtig
„Abnahme ist kein Build, sondern ein Funktionstest" — gemeint war der ClamAV-Test. Der
rc.2-Vorfall zeigt die Lücke davor: Der CI-Job `web` **baut** nur, webpack entfernt
Typen ohne sie zu prüfen. `tsc` meldete den Fehler durchgehend, gefragt hatte ihn
niemand. Seit `8ca03fe` führt `docker_web` den Job `typecheck` als `needs`; kein Image
entsteht mehr ohne bestandene Typprüfung.
**Daraus die stehende Regel für künftige Upstream-Merges:** Nach der Konfliktauflösung
gehört eine Prüfung auf *überlebende* Reste — nicht nur auf verlorene Zeilen. Der
billigste Hebel ist die Typprüfung; sie fand beide Reste sofort. Wo Zeichenketten statt
Typen im Spiel sind (Einstellungsschlüssel, Feature-Namen, Übersetzungs-IDs), reicht sie
nicht, und es braucht einen Abgleich gegen die jeweilige Registry — für Einstellungen
wurde er einmalig gefahren: 135 abgefragte gegen 152 registrierte.
@@ -1,7 +1,7 @@
---
type: issue
id: "0099"
status: open
status: done
created: 2026-08-06
milestone: M1
priority: medium
@@ -295,3 +295,95 @@ bleibt im Klon liegen, damit der nächste Anlauf nicht wieder 600 MB holen muss.
**Nächster Schritt:** den Merge als eigenes Vorhaben fahren, mit Build und
ClamAV-Abnahme als Voraussetzung — nicht als Nebenschritt.
## Ausgeführt und abgenommen 2026-08-19 — `v0.6.0` läuft in Produktion
Der Merge ist vollzogen. `ThreadNet-Web:main` steht auf `8ca03fe`; der Merge-Commit
`88c4e15` trägt beide echten Eltern (`fa5dcc5` = unser bisheriger `main`,
`c43ef70b` = `v1.12.26`). Damit ist die Abstammung hergestellt, der Graft ist weg,
und `GHSA-wrcp-5v3v-3j6v` ist mit dem Versionssprung erledigt.
### Die beiden Produktentscheidungen aus dem Abschnitt davor
| Zeile | Auflösung | Beleg |
|---|---|---|
| `@sorb/threadnet-call-embedded` | **unsere** behalten, `0.19.2-threadnet.12` | auf `main` und im Zweig identisch — die KI-Geräuschunterdrückung (#0054) ist unberührt |
| `matrix-js-sdk` | **Upstreams** `42.2.0` genommen, Git-Ref-Pin fällt weg | Build läuft; der seinerzeitige Build-Fix hat sich erübrigt |
### Drei Anläufe, zwei davon gescheitert
| | |
|---|---|
| `v0.6.0-rc.1` | **kein Image.** `docker_web` scheiterte: `.npmrc` stand nie in der `COPY`-Zeile des Dockerfiles. Unter pnpm 10 folgenlos, weil `--frozen-lockfile` die gepinnte Tarball-URL nahm; pnpm 11 prüft mit `minimumReleaseAgeStrict` das Alter jedes Eintrags, löst den Scope wieder auf und landet ohne `.npmrc` bei npmjs → 404. Genau der Ablauf, den die `.npmrc` selbst vorhersagt (#0055). |
| `v0.6.0-rc.2` | **ging live und brach die Raumliste.** Nach wenigen Minuten auf `v0.5.4` zurückgenommen. Siehe unten. |
| `v0.6.0-rc.3` | Abnahme bestanden, als `v0.6.0` freigegeben. |
### Der rc.2-Vorfall — eine stille Leiche der anderen Sorte
`RoomListItemViewModel.ts` rief `SettingsStore.getValue("feature_room_list_sections")`
auf einen Labs-Schalter, den Upstream **entfernt** hat; Sektionen laufen dort über
`RoomList.showSections`. Die Auflösung hatte überall Upstreams Seite genommen — Menü,
View, Snapshot, Typen — und nur diese eine `const`-Zeile aus unserer Seite stehen
lassen. Sie wurde tree-weit von niemandem gelesen und warf trotzdem: bei **jedem**
Raumlisteneintrag, als `react-soft-crash`.
Bemerkenswert ist die Richtung: Dieses Issue warnt vor Zeilen, die *verschwinden*.
Hier ist eine Zeile **übrig geblieben**, die verschwinden musste. Der Merge meldet
Konflikte, wo Dateien wandern — er merkt aber nicht, wenn beide Seiten überleben und
nur eine davon noch Sinn ergibt.
Abgesichert statt gehofft: alle **135** im Quellbaum abgefragten Einstellungen gegen
die **152** in `Settings.tsx` registrierten verglichen — genau diese eine Leiche,
keine weitere. Ein zweiter Rest derselben Art (ungenutzter Import
`ElementDesktopLogoSvg` in `SdkConfig.ts`) war harmlos; geprüft wurde dabei
ausdrücklich, ob unser Rebrand gelitten hat — hat er nicht, `desktopBuilds` trägt
weiter eigenes Logo und eigenen Release-Pfad.
### Warum kein Build das fangen konnte — und was daraus folgt
Der CI-Job `web` führt ausschließlich `pnpm --dir apps/web build` aus. webpack
entfernt Typen, ohne sie zu prüfen; ein unbekannter Einstellungsschlüssel ist zur
Bauzeit bloß ein String. `tsc` dagegen meldete den Fehler die ganze Zeit — **zweimal**
(`TS2345` unbekannter Schlüssel, `TS6133` ungenutzte Konstante). Gefragt hatte ihn
niemand.
Konsequenz, umgesetzt in `8ca03fe`: neuer Job `typecheck`, den `docker_web` als
`needs` führt. **Kein Image mehr ohne bestandene Typprüfung.** Maßstab ist „kein
Fehler außerhalb von `node_modules`", weil Upstream v1.12.26 selbst nicht typrein ist
`matrix-js-sdk@42.2.0` wirft drei Fehler in der eigenen Quelle, in einem sauberen
v1.12.26-Checkout gegengeprüft.
⚠️ Das Tor wäre beim Bau selbst fast wertlos geworden: Das erste `grep "error TS"`
hätte nie gegriffen, weil nx auch in der Pipe färbt und zwischen `error` und `TS` eine
Escape-Sequenz steht. Es ist jetzt in **beide** Richtungen belegt — mit wieder
eingesetzter Zeile scheitert es und benennt beide Fehler, ohne sie besteht es — und
scheitert zusätzlich bei leerer `tsc`-Ausgabe, damit ein stiller Erfolg nicht als
Prüfung durchgeht.
### Die Abnahme, wie dieses Issue sie verlangt
Gefordert war „verschlüsselte Datei senden, abgelehnte empfangen" — geprüft am
laufenden System, nicht am Build:
| Prüfpunkt | Ergebnis |
|---|---|
| Raumliste lädt | ✅ mit konfigurierten Sektionen, also im kritischen Pfad |
| ClamAV Sendepfad | ✅ blockiert vor dem Upload — **ein** Scan-Aufruf, kein zweiter |
| ClamAV Empfangspfad (Datei) | ✅ EICAR erkannt, Abweisung wird angezeigt |
| ClamAV Bildpfad (`.png`) | ✅ zugestellt, beim Herunterladen abgewiesen, **Meldung gerendert** |
| Call-Teilnehmerliste | ✅ |
Der `.png`-Fall ist der wichtigste: Er ist der einzige, der den portierten Code
`ImageBodyViewModel.computeErrorLabel()` tatsächlich durchläuft. Wäre die Datei schon
beim Senden geblockt worden, hätte der Test den Sendepfad ein zweites Mal geprüft und
den Bildpfad gar nicht — beides sieht im Scanner-Log gleich aus, weil die Meldung
`flagged an upload/download` nicht unterscheidet.
### Stand
`v0.6.0` ist in Produktion (`gitops:d87c432`), `/version` liefert `0.6.0`.
Rückhebel bleibt der Tag-Revert auf `v0.5.4`.
**Alle vier Schritte dieses Issues sind beantwortet**; Schritt 4 ist wie in ADR-0022
vorhergesagt gegenstandslos geworden. Das nächste Upstream-Update ist ein gewöhnlicher
Merge.