docs: Wiederaufnahme 2026-10-07 - Tests/Benchmarks dokumentiert, SDK-Wettlauf + Abhaengigkeiten in ROADMAP

Neue Punkte: SDK-Sync-Wettlauf (Logout-Pfad pruefen), Abhaengigkeits-Updates
(sqlcipher_flutter_libs EOL - nie auf 0.7.0 heben, matrix 6.2 -> 13,
flutter_markdown eingestellt; WebRTC-Audio-Fix weiterhin nicht upstream).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Bernd Steckmeister
2026-10-07 11:55:32 +02:00
co-authored by Claude Opus 5.5
parent df1b392ed8
commit dbc0340eeb
5 changed files with 208 additions and 0 deletions
+49
View File
@@ -13,6 +13,55 @@ Schritt (und beim Abbruch mitten im Schritt den Zwischenstand). Format:
--- ---
## 2026-10-07 – Wiederaufnahme nach Pause: Bestandsaufnahme, Test-Runner, Benchmarks, Live-Test stabilisiert
**Erledigt:**
- **Bestandsaufnahme:** Repo synchron mit Gitea (0 vor/0 hinter), Arbeitsbaum
war sauber, Toolchain unverändert (Flutter 3.44.4 / Dart 3.12.2).
`flutter analyze` sauber (nur bekannter onUpdate-Hinweis), 36 Unit-Tests
grün. Autopilot (PC + Pi) weiterhin pausiert.
- **Lokale Suche als Modul:** `_localMessageSearch` aus `search_modal.dart`
nach `lib/features/search/local_message_search.dart` verschoben – gleiche
Deckel (1500/Raum, 60 Treffer, 500er-Blöcke), gleiche Schleife, nur der
Medien-Filter kommt jetzt als Parameter. 5 Vertragstests
(`test/local_message_search_test.dart`) auf der echten SDK-DB-Schicht.
- **Benchmarks** (`benchmark/`, `docs/TESTS_UND_BENCHMARKS.md`): Klartext vs.
SQLCipher (Sync-Schreiben, App-Start, Chat öffnen, Suche) + Migrationsdauer;
JSON-Berichte, Baseline in `benchmark/baseline/`, Regressionswarnung >25 %.
Ergebnis: SQLCipher-Aufschlag im Rauschen (±5–10 %), Migration ≈ 42 ms/MB,
Suche (Worst Case) 64 ms für 10 000 Nachrichten.
- **`scripts/test.ps1`:** Analyse + Unit-Tests (+ `-Live`, `-Bench`, `-All`,
`-UpdateBaseline`) mit Zusammenfassung; baut die SQLCipher-DLL bei Bedarf.
- **Live-Test sporadisch rot → Ursache gefunden, Test stabilisiert:** siehe
Befund unten. `live_encryption_e2e_test.dart` meldet sich jetzt über
`_logoutWithoutStraySync` ab (Sync anhalten, laufenden Long-Poll
auslaufen lassen, dann Logout). Danach 3 Läufe in Folge grün (Ergebnis
siehe unten).
**Befund (neu in ROADMAP, M1-Bereich):** matrix 6.2 `_innerSync` wirft den
Fehler einer Sync-Antwort, bevor geprüft wird, ob die Anfrage noch aktuell
ist. Die 401 eines alten Long-Polls nach einem Logout löst ein erneutes
`clear()` aus – nach einem schnellen Re-Login auf demselben Client würde das
die neue Session löschen. Im Test trat es als „databaseFactory not
initialized" nach `dispose()` auf. Upstream `main` unverändert (geprüft).
App-Logout-Pfad noch NICHT angefasst (heilig, braucht Gerätetest).
**Offen/Nächster Schritt:** Bernds Rückmeldungen aus der Beta-Testphase
(v0.1.36) einsammeln, dann Prioritäten setzen: Klick-Tests aus
`docs/PC_TESTPLAN.md`, App-Logout-Pfad gegen den SDK-Wettlauf prüfen,
Abhängigkeits-Updates (ROADMAP M2, Achtung `sqlcipher_flutter_libs` EOL).
**Stolperfallen:** (1) sqflite liefert für denselben Pfad dieselbe
Verbindung zurück – ein zweites Öffnen+Schließen kappt die erste
(Benchmark-„database_closed"). (2) Benchmark-Reihenfolge: der Dart-JIT wird
während des Laufs schneller, der zuerst gemessene Modus verlor ±20 % →
großer Aufwärm-Durchlauf + A-B-B-A. (3) `dart format` NUR auf neue Dateien
anwenden – Bestandsdateien sind nicht formatiert, sonst riesiger Diff.
(4) Vor einer Aussage nachmessen: Schreibkosten hängen NICHT nennenswert von
der Raumgröße ab (250 vs. 4000 Nachrichten/Raum ≈ +15 %).
---
## 2026-07-06 – Nacht-Session (C+B): 60-FPS-Streaming + Call mit ZWEI echten Test-Accounts real durchgeklickt ## 2026-07-06 – Nacht-Session (C+B): 60-FPS-Streaming + Call mit ZWEI echten Test-Accounts real durchgeklickt
**Erledigt:** Fokus (C) Streaming und (B) Calls – beides mit zwei echten **Erledigt:** Fokus (C) Streaming und (B) Calls – beides mit zwei echten
+2
View File
@@ -25,6 +25,7 @@ für die unterstützte Dart-Version).
flutter pub get flutter pub get
flutter run -d windows # schnellster Praxistest während der Entwicklung flutter run -d windows # schnellster Praxistest während der Entwicklung
flutter analyze # muss sauber bleiben flutter analyze # muss sauber bleiben
pwsh scripts/test.ps1 # Analyse + Tests (-Live, -Bench, -All: siehe docs/TESTS_UND_BENCHMARKS.md)
``` ```
Unterstützte Zielplattformen: Android, Windows, Linux, iOS, macOS (Ordner Unterstützte Zielplattformen: Android, Windows, Linux, iOS, macOS (Ordner
@@ -52,5 +53,6 @@ lib/
- `CLAUDE.md` – Arbeitsregeln und Infrastruktur für die Zusammenarbeit mit Claude - `CLAUDE.md` – Arbeitsregeln und Infrastruktur für die Zusammenarbeit mit Claude
- `ROADMAP.md` / `PROGRESS.md` – aktueller Stand und nächste Schritte - `ROADMAP.md` / `PROGRESS.md` – aktueller Stand und nächste Schritte
- `docs/TESTS_UND_BENCHMARKS.md` – Tests, Live-Tests, Benchmarks (ein Befehl)
- `docs/NOTIFICATIONS.md` – Push-Architektur (native Anzeige vs. Hintergrund-Entschlüsselung) - `docs/NOTIFICATIONS.md` – Push-Architektur (native Anzeige vs. Hintergrund-Entschlüsselung)
- `docs/matrix-sdk/` – Hinweise zum verwendeten Matrix-SDK - `docs/matrix-sdk/` – Hinweise zum verwendeten Matrix-SDK
+38
View File
@@ -169,6 +169,21 @@ Punkte abhaken (`[x]`), wenn erledigt UND in `PROGRESS.md` protokolliert.
E2EE-Empfang live belegt, auth_log unauffällig; App läuft seit 12:43 E2EE-Empfang live belegt, auth_log unauffällig; App läuft seit 12:43
für die Langzeit-Beobachtung weiter. **Offen (Klick/Bernd):** für die Langzeit-Beobachtung weiter. **Offen (Klick/Bernd):**
Senden, Logout-Warnung, Re-Login mit Lesbarkeits-Check. Senden, Logout-Warnung, Re-Login mit Lesbarkeits-Check.
- [ ] **SDK-Wettlauf: verspätete 401 einer alten Sync-Anfrage löscht ggf. die
NEUE Session** (gefunden 2026-10-07 über einen sporadisch roten
Live-Test, siehe PROGRESS.md). matrix 6.2 `Client._innerSync` wirft den
Fehler einer Sync-Antwort, BEVOR geprüft wird, ob die Anfrage noch
aktuell ist (`_currentSyncId`). Läuft beim Logout noch ein Long-Poll
(bis 30 s) mit dem alten Token, kommt dessen M_UNKNOWN_TOKEN danach an
und das SDK ruft `clear()` – nach einem schnellen Re-Login auf
demselben Client wäre das ein „Random-Logout" direkt nach dem Login.
Upstream (famedly/matrix-dart-sdk `main`, 2026-10-07) unverändert;
neuere SDKs versuchen bei vorhandenem Refresh-Token aber zuerst einen
Refresh statt `clear()` (entschärft). Im Live-Test per
`_logoutWithoutStraySync` umgangen. **Offen:** App-Logout-Pfad prüfen
(läuft der Re-Login auf demselben Client-Objekt? dann vor
`client.logout()` Sync anhalten + laufenden Long-Poll abwarten) –
heiliger Pfad, nur mit Gerätetest; ggf. Upstream-Issue melden.
## M2 – Das große Refactoring (erst nach M0/M1!) ## M2 – Das große Refactoring (erst nach M0/M1!)
@@ -253,6 +268,29 @@ lassen, ohne dass andere Module angefasst werden müssen.
prüfen), siehe „Fragen an Bernd"/Nächster-Schritt in den jeweiligen prüfen), siehe „Fragen an Bernd"/Nächster-Schritt in den jeweiligen
PROGRESS.md-Einträgen) PROGRESS.md-Einträgen)
- [ ] Nach JEDEM Schritt: App läuft, Kernflows getestet, Commit - [ ] Nach JEDEM Schritt: App läuft, Kernflows getestet, Commit
- [x] Test-/Benchmark-Gerüst: `scripts/test.ps1` (Analyse, Unit-, Live-Tests,
Benchmarks mit einem Befehl), `benchmark/` mit Baseline, lokale Suche
als testbares Modul (`lib/features/search/`). Siehe
`docs/TESTS_UND_BENCHMARKS.md`, PROGRESS.md 2026-10-07.
- [ ] **Abhängigkeiten aktualisieren (3 Monate Stand, 119 Pakete veraltet)** –
einzeln, jeweils mit `scripts/test.ps1 -All` abgesichert:
- **`sqlcipher_flutter_libs` ist EOL:** 0.7.0 ist ein leerer Platzhalter
(pub.dev). Unsere Bindung `^0.6.8` schließt ihn aus – NIEMALS per
`pub upgrade --major-versions` mitziehen, sonst fehlt SQLCipher und
die App kann die verschlüsselte DB nicht mehr öffnen
(`AppDatabase` wirft dann bewusst, kein Datenverlust, aber Aussperren).
Nachfolger: `sqlite3` 3.x mit `hooks: user_defines: sqlite3: source:
sqlcipher` – Kompatibilität mit `sqflite_common_ffi` und Android
vorher klären; Migrations-/DB-Tests + Gerätetest Pflicht.
- `matrix` 6.2 → 13.x (großer Sprung, Breaking Changes; heiliger
Login-/Krypto-Pfad), `flutter_vodozemac` 0.5 → 0.8 gehört dazu.
- `livekit_client` 2.7 → 2.13 (innerhalb der Bindung möglich),
`flutter_webrtc`-Override 1.4.1 → 1.6.2: der Windows-Audiogeräte-Fix
(libwebrtc #142) ist auch in 1.6.2+hotfix.4 NICHT enthalten
(Changelog geprüft 2026-10-07) → Dummy-PeerConnection-Workaround
bleibt nötig.
- `flutter_markdown` ist eingestellt (pub: „replaced by
flutter_markdown_plus“) → umstellen (Markdown-Vorschau im Dokument-Viewer).
## M3 – Calls: Logik, UI & Audio (Discord als Referenz) ## M3 – Calls: Logik, UI & Audio (Discord als Referenz)
+4
View File
@@ -21,6 +21,10 @@ Schnellster Weg: `flutter run -d windows`.
VoicePrefs-Vertragstests in `test/settings_prefs_test.dart`), VoicePrefs-Vertragstests in `test/settings_prefs_test.dart`),
mehrfach gelaufen (vor/nach jedem Umbau des Tages). mehrfach gelaufen (vor/nach jedem Umbau des Tages).
- [x] **Seit 2026-10-07: alles Automatisierbare mit EINEM Befehl** –
`pwsh scripts/test.ps1 -All` (Analyse, 41 Unit-Tests, Live-Test mit
Test-Account, Benchmarks). Details: `docs/TESTS_UND_BENCHMARKS.md`.
## 1. Härtetest Login/Krypto (M1 – PFLICHT, zuerst!) ## 1. Härtetest Login/Krypto (M1 – PFLICHT, zuerst!)
Deckt die Fixes 63e4919, 9dc83f7, 891f348 ab (Uta-Random-Logout + Guard). Deckt die Fixes 63e4919, 9dc83f7, 891f348 ab (Uta-Random-Logout + Guard).
+115
View File
@@ -0,0 +1,115 @@
# Tests & Benchmarks
Stand: 2026-10-07. Alles läuft mit **einem Befehl** aus dem Projektordner:
```
pwsh scripts/test.ps1 # Analyse + Unit-Tests (~1 min) – vor jedem Commit
pwsh scripts/test.ps1 -Live # + Live-Test gegen steggi-matrix.work (Test-Account)
pwsh scripts/test.ps1 -Bench # + Benchmarks (Datenbank/Verschlüsselung, Migration)
pwsh scripts/test.ps1 -All # alles (~4 min)
```
Am Ende steht eine Zusammenfassung mit OK/FEHLER je Schritt. Fehlt die
SQLCipher-Bibliothek (frischer Checkout), baut das Skript einmalig
`flutter build windows --debug`.
**Für Bernd in einem Satz:** Die Tests prüfen automatisch die heiklen Stellen
(Login-/Logout-Schutz, Verschlüsselung der Datenbank, Suche, Einstellungen),
die Benchmarks messen, ob die App dabei langsamer wird. Was man nur mit Klicken
oder zwei echten Geräten prüfen kann, steht weiterhin in `docs/PC_TESTPLAN.md`.
## Tests (`test/`)
| Datei | Prüft | Läuft wann |
|---|---|---|
| `app_database_test.dart` | SQLCipher: Bibliothek echt, Header-Erkennung, Klartext→verschlüsselt-Migration, falscher Schlüssel, Fehlschlag lässt Daten unangetastet | immer (braucht die DLL aus dem Windows-Build) |
| `soft_logout_guard_test.dart` | Uta-Random-Logout-Fix: Token-Refresh-Fehler enden nie im stillen Logout | immer |
| `auth_log_test.dart` | Login-Protokoll (Diagnose für Logout-Bugs) | immer |
| `power_levels_safety_test.dart` | Space-Admin kann sich nicht selbst aussperren | immer |
| `settings_prefs_test.dart` | VoicePrefs-Fassade (gespeicherte Spracheinstellungen) | immer |
| `streaming_presets_test.dart` | 60-FPS-Streaming-Presets (Auflösung/FPS/Bitrate) | immer |
| `local_message_search_test.dart` | Lokale Nachrichtensuche (Strg+K): Treffer, Sortierung, Groß-/Kleinschreibung inkl. Umlaute, Medien-Filter, Trefferdeckel | immer (neu 2026-10-07) |
| `live_encryption_e2e_test.dart` | Echter Login (pyramidtest1) → Platte verschlüsselt → Neustart → Logout → Re-Login → alte Nachricht lesbar; Utas Update-Fall mit echter Session | nur mit `-Live` |
| `live_call_setup_test.dart` | Kein Test im engeren Sinn: legt den Voice-Testraum für GUI-Call-Tests mit zwei Test-Accounts an | nur manuell mit `PYRAMID_LIVE_TEST=1` |
`test/support/synthetic_matrix_data.dart` erzeugt synthetische Räume und
Nachrichten über die **echte SDK-Speicherschicht** – komplett offline, ohne
Konten. Tests und Benchmarks nutzen sie gemeinsam.
Live-Tests: Zugangsdaten liegen AUSSERHALB des Repos
(`%USERPROFILE%\.pyramid-autopilot\test-accounts.txt` bzw. `PYRAMID_TEST_ACCOUNTS`).
Es sind die Test-Accounts `pyramidtest1/2`, nie Bernds oder Utas Konten.
## Benchmarks (`benchmark/`)
Laufen bewusst NICHT im normalen `flutter test` mit (nur `-Bench` bzw.
`flutter test benchmark --concurrency=1`).
| Suite | Misst |
|---|---|
| `db_benchmark_test.dart` | Klartext- vs. SQLCipher-DB mit derselben Bibliothek: Sync-Schreiben (Transaktionen wie beim echten Sync), App-Start (DB öffnen + Raumliste), Chat öffnen (50 Nachrichten), lokale Suche (ohne Treffer = Worst Case, mit Treffern) |
| `migration_benchmark_test.dart` | Dauer der einmaligen Klartext→SQLCipher-Migration beim ersten Start nach dem Update (exakt der App-Codepfad), danach Vollständigkeitsprüfung |
**Wie gemessen wird:** DB im eigenen Isolate wie in der App; ungemessener
Aufwärm-Durchlauf; Modi abwechselnd A-B-B-A (ohne das gewann einfach der
später gemessene Modus um ±20 %, weil der Dart-JIT während des Laufs schneller
wird); Median mehrerer Durchläufe.
**Baseline & Regressionen:** Jeder Lauf schreibt `build/benchmarks/<suite>.json`
und vergleicht mit `benchmark/baseline/<suite>.json`. Mehr als 25 % langsamer
(und bei Zeiten mehr als 2 ms absolut) wird als „⚠ LANGSAMER" markiert.
Umgebungsvariablen:
- `-UpdateBaseline` bzw. `PYRAMID_BENCH_UPDATE_BASELINE=1` – aktuelle Werte als
neue Baseline speichern (nach bewusster Änderung oder auf neuer Hardware).
Die Baseline gilt nur für den Rechner, auf dem sie entstand.
- `PYRAMID_BENCH_STRICT=1` – Regressionen lassen den Lauf scheitern.
- `PYRAMID_BENCH_SCALE=0.2` – kleinere Datenmenge für einen schnellen Probelauf
(andere Mengen sind mit der Baseline nicht vergleichbar).
### Erste Ergebnisse (2026-10-07, Bernds PC, 12 Kerne, Commit b2413ef)
20 Räume × 500 Nachrichten (DB-Suite), 20 × 1000 (Migration):
| Messung | Klartext | SQLCipher |
|---|---|---|
| Sync-Schreiben je Nachricht | 0,25 ms | 0,26 ms |
| App-Start (DB + Raumliste) | 4,1 ms | 4,3 ms |
| Chat öffnen (50 Nachrichten) | 0,33 ms | 0,32 ms |
| Suche ohne Treffer (10 000 Nachrichten) | 64 ms | 64 ms |
| Suche mit Treffern | 32 ms | 32 ms |
| Migration Klartext → SQLCipher | – | 325 ms für 7,8 MB (≈ 42 ms/MB) |
Was das heißt:
- **Die Verschlüsselung kostet praktisch nichts.** Alle Unterschiede liegen im
Messrauschen (±5–10 %, zwei Läufe hintereinander). Die Kosten stecken im
Matrix-SDK selbst (JSON-Verarbeitung), nicht in SQLCipher.
- **Sync-Schreiben** liegt bei ~0,26 ms pro Nachricht und hängt kaum von der
Raumgröße ab (nachgemessen: 250 vs. 4 000 Nachrichten pro Raum ≈ +15 %).
- **Suche** wächst linear mit der Zahl der gespeicherten Nachrichten
(gedeckelt auf 1 500 pro Raum). Hochrechnung, nicht gemessen: 100 aktive
Räume am Deckel ≈ 150 000 Nachrichten ≈ 1 s pro Suche auf diesem PC –
auf Handys entsprechend länger. Kandidat für einen Suchindex (FTS), falls
das in der Praxis stört.
- **Migration**: Hochrechnung für eine 100-MB-DB ≈ 4 s einmalig auf diesem
PC; auf Utas Handy vermutlich ein Mehrfaches davon (nicht gemessen).
## Bekannte Grenzen (ehrlich)
- Synthetische Daten: unverschlüsselte Räume, keine Olm/Megolm-Sessions
(vodozemac läuft im Host-Test nicht). Die DB-Struktur ist aber die echte.
- Gemessen auf Windows im JIT-Modus von `flutter test`; die Release-App läuft
AOT-kompiliert und ist eher schneller. Für Vergleiche über die Zeit taugt
das, für absolute Aussagen über Handys nicht.
- Nicht automatisiert: alles mit Klicks, echte Calls/Audio, 60-FPS-Streaming
zwischen zwei Geräten, Android-Push → `docs/PC_TESTPLAN.md`.
## Nächste sinnvolle Messungen
- **Streaming (M4 „Ursache messen"):** WebRTC-`getStats()` des Senders
auswerten (`framesPerSecond`, `qualityLimitationReason`, Encoder-Name) –
zeigt direkt, ob CPU, Bandbreite oder Encoder bremst. Braucht eine kleine
Diagnose-Anzeige im Call und zwei echte Geräte.
- **UI-Flüssigkeit:** `integration_test` mit Frame-Timing beim Scrollen der
Raumliste/Timeline (Windows, Test-Account-Profil über `PYRAMID_PROFILE_DIR`).