Files
PolyTraderSharp/docs/pruefplaene/BEFUND-Linux-Betrieb-2026-08-26.md
T
RichardandClaude Opus 5 62570cfdd8
CI / Build & Tests (Linux) (push) Canceled after 0s
CI / Plattformneutralität & Hygiene (push) Canceled after 0s
Sichtpruefung mit Testdaten: die Grids in Aktion, vier weitere Befunde
Testdaten in die Testdatenbank eingespielt (3 Demo-Konten, 5 Master-Trader,
3 offene Positionen, 7 Trades, 5 RF-Kandidaten), gesichert als
docs/pruefplaene/testdaten-ui.sql zur Wiederverwendung. Bewusst mit
42-stelligen Wallet-Adressen und langen englischen Marktfragen - kurze
Platzhalter haetten die Layoutbefunde verdeckt.

Mit Daten wirkt die Anwendung vollstaendig funktionsfaehig: Grids fuellen sich,
die Auswahl markiert Zeilen, das Detailformular uebernimmt den gewaehlten
Datensatz, zugewiesene Konten werden korrekt angehakt, KPI-Kacheln rechnen.

Vier weitere Befunde:
- B-13 (wichtig): Die Spalte "Name" im Master-Trader-Grid ist auf wenige Pixel
  zusammengequetscht - die Anzeigenamen sind NIRGENDS zu sehen, obwohl sie die
  wichtigste Information der Zeile sind. Die festen Breiten der elf uebrigen
  Spalten lassen der Sternbreite fast nichts uebrig.
- B-11 praezisiert: Nicht die Werte sind zu breit, sondern die Ueberschriften.
  Das RF-Grid zeigt lange Marktfragen mühelos, waehrend "Fee (bps)" zu
  "Fee (bp" verstuemmelt wird. Die Breiten sind auf die Datenwerte ausgelegt.
- B-14: Beschreibung und Reasoning sind einzeilige Felder fuer varchar(1000).
- B-15: Ein fehlerhafter Datensatz legt die gesamte Modul-Hydration lahm. Beim
  ersten Einspielen war AssignedAccountIds kein gueltiges JSON - daraufhin wurde
  kein einziger Trader geladen. Im Betrieb hiesse das: ein beschaedigter Eintrag
  legt das komplette Modul stumm, statt uebersprungen und gemeldet zu werden.

B-7 bestaetigt: In jeder KPI-Kachel steht der Modulname doppelt.

Nachgeprueft und KEIN Fehler: Copy-PnL zeigt 0,00, weil die Kennzahlen aus den
tatsaechlichen Copy-Trades berechnet werden und mod_copytrading_closed_trades
leer ist. Die Werte stehen auch in der Datenbank auf 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 22:59:15 +02:00

555 lines
28 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Befundbericht: Erster Linux-Lauf
**Datum: 26.08.2026** · Prüfplan: [PRUEFPLAN-Linux-Betrieb.md](./PRUEFPLAN-Linux-Betrieb.md) ·
Roadmap: [A4a](../ROADMAP.md)
**Testsystem:** Ubuntu 26.04 LTS, Kernel 7.0.0-30, x86_64, 31 GB RAM, 5 CPUs,
Zeitzone `Europe/Berlin`. .NET SDK 10.0.111 mit Runtime 10.0.11 bereits vorhanden.
Zugriff über SSH (WireGuard, Schlüssel-Authentifizierung).
> **Kernaussage: PolyTrader läuft auf Linux — als Dienst, mit Datenbank, mit echten Marktdaten.**
> Der Prüfplan ist **vollständig abgearbeitet** (Nachtrag ab Abschnitt 5). Drei Fehler gefunden,
> einer davon behoben. Offen bleibt nur die Sichtprüfung der Oberfläche, die einen Menschen am
> Bildschirm braucht.
---
## 1. Was funktioniert
| Prüfpunkt | Ergebnis |
|---|---|
| **Build** | `dotnet build -c Release`: **0 Fehler**, 15 Warnungen — exakt dieselben wie unter Windows. Keine plattformbedingte Abweichung |
| **Tests** | **476 von 476 grün**, 3 s Laufzeit — identisch zu Windows |
| **Publish** | `linux-x64`, framework-abhängig: 121 Dateien, 41 MB. Ausführbare Datei trägt bereits das Ausführungsrecht |
| **Start** | Die Anwendung startet mit `--headless` und durchläuft die komplette Startsequenz |
| **Native Abhängigkeiten** | **Keine nötig.** Die Vermutung aus dem Prüfplan ist bestätigt: `--headless` ruft `BuildAvaloniaApp()` nie auf, Skia und HarfBuzz werden nie geladen. `libfontconfig1` & Co. mussten **nicht** installiert werden |
| **Master-Key** | Wird beim ersten Start erzeugt und mit Rechten **`0600`** abgelegt — `FilePermissions` arbeitet unter Linux korrekt. AES-256-GCM meldet sich als aktiv |
| **Zeitzone** | `Europe/Berlin` wird korrekt erkannt und gemeldet |
| **Lizenz-Gate** | Verhält sich exakt wie dokumentiert: Warnung, „eingeschränkter Modus", **kein** Programmabbruch |
| **Logging** | `Logs/` wird angelegt und beschrieben |
**Bemerkenswert:** Zwischen Windows und Linux gibt es bei Build und Tests **keinen einzigen
Unterschied** — weder in der Fehler- noch in der Warnungszahl. Die Portierungsarbeit hat
gehalten.
---
## 2. Befunde
### B-1 · Absturz statt Fehlermeldung ohne Datenbank · **behoben**
**Beobachtet:** Ohne konfigurierten Connection-String lief die Anwendung an und starb tief im
DI-Aufbau:
```
Unhandled exception. System.ArgumentException: The string argument 'connectionString' cannot be empty.
at Microsoft.EntityFrameworkCore.Utilities.Check.NullButNotEmpty(...)
… rund 50 weitere Zeilen …
EXITCODE: 134 (SIGABRT)
```
**Warum das mehr ist als Kosmetik:** Für einen Serverbetrieb ist das doppelt schlecht. Der
Betreiber sieht nicht, *was* fehlt, und systemd startet den Dienst wegen `Restart=on-failure`
alle zehn Sekunden neu — im Journal stehen dann endlose Startversuche statt der Ursache. Und
genau dieser Zustand ist bei einer **Erstinstallation der wahrscheinlichste**: Software liegt da,
Zugangsdaten sind noch nicht gesetzt. Das betrifft direkt Schnitt D-5 (`setup.json`).
**Behoben** (Commit `Verstaendlicher Abbruch statt Absturz…`):
- `Program.Main` prüft die Verbindung, **bevor** der Host gebaut wird, und nennt Schlüssel,
Datei, Pfad und ein Beispiel — dazu den Hinweis, dass das Schema per
`dotnet ef database update` entsteht, weil die Anwendung nicht selbst migriert.
- Rückgabewert **78** (`EX_CONFIG` aus den BSD-sysexits) statt eines Absturzes.
- `deploy/polytrader.service` bekam **`RestartPreventExitStatus=78`** — ein Konfigurationsfehler
repariert sich durch Neustarts nicht, er wird dadurch nur unsichtbar.
- `AddCorePersistence` wirft als zweite Verteidigungslinie eine `InvalidOperationException` mit
derselben Aussage.
**Gegengeprüft auf der VM:** Verständliche Meldung, Exitcode 78, kein Stacktrace.
### B-2 · Zwei verschiedene Datumsformate in Logdateinamen · offen, klein
Im selben Lauf entstanden nebeneinander:
```
2026-08-26.jsonl ← ISO, yyyy-MM-dd
26-08-2026-Info.log ← dd-MM-yyyy
26-08-2026-Warning.log
```
Zwei Logger-Pfade mit unterschiedlicher Namenskonvention. Praktische Folgen: Eine
Logrotate-Regel braucht zwei Muster, und beim Sortieren im Dateimanager landen die `.log`-Dateien
in willkürlicher Reihenfolge, weil der Tag vorn steht. Kein Fehler, aber ein Stolperstein im
Betrieb — sinnvollerweise mit **T2** (TerminalLogger-Umbau) zusammen zu erledigen.
### B-3 · `--smoke-ui` verlangt jetzt eine Datenbank · offen, entscheidungsbedürftig
Die neue Prüfung aus B-1 läuft vor dem Host-Aufbau und trifft damit **auch** die
Konstruktionsprüfung `--smoke-ui`. Die ist als CI-Werkzeug gedacht, und ein Build-Server hat
typischerweise keine Datenbank.
**Wichtig: Das ist keine Verschlechterung.** Vorher scheiterte `--smoke-ui` ohne Datenbank
genauso — nur mit dem Stacktrace aus B-1 statt mit einer Meldung. Der Befund war vorher bloß
unsichtbar.
Sauber lösen ließe sich das, indem `--smoke-ui` die Persistenzschicht überspringt oder gegen
EF-InMemory baut (wie die Tests). Das ist ein eigener Schnitt und hängt daran, ob die CI diesen
Modus überhaupt nutzen soll — deshalb hier nur vermerkt, nicht gebaut.
---
## 3. Nicht geprüft — und warum
> **Überholt.** Dieser Abschnitt beschreibt den Zwischenstand, bevor MariaDB und `sudo`
> verfügbar waren. Alles hier Aufgeführte wurde im **Nachtrag ab Abschnitt 5** nachgeholt —
> bis auf die Sichtprüfung der Oberfläche. Der Abschnitt bleibt als Verlaufsspur stehen.
| Prüfpunkt | Fehlt |
|---|---|
| Betrieb **mit** Datenbank, Migrationen | Auf der VM läuft **keine** MySQL; der Datenbankhost ist nicht bekannt |
| systemd-Dienst, `WorkingDirectory`-Falle (D-11) | Braucht `sudo`; Passwörter gebe ich nicht ein |
| SIGTERM-Shutdown, `Restart=on-failure` | Setzt den laufenden Dienst voraus |
| **Zeitzonen-Nachweis (T2)** | Die VM steht auf `Europe/Berlin`; der Effekt zeigt sich erst unter **UTC**. Umstellen braucht `sudo` |
| Logrotate | Braucht `sudo` |
| Oberfläche unter Linux | Braucht eine Datenbank (siehe B-3) — die VM hat aber einen Desktop, der Test ist also möglich |
**Zum Weitermachen wird gebraucht:**
1. Eine **Testdatenbank** — entweder Adresse und Zugang zu einer bestehenden MySQL, oder
MariaDB lokal auf der VM installieren (`sudo`). **Nicht die Produktivdatenbank:** Der
`MarketSyncService` schreibt als Hintergrunddienst hinein.
2. Für die `sudo`-Schritte: Entweder Richard führt sie aus, oder er richtet für die Dauer des
Tests passwortloses `sudo` für sein Konto ein.
---
## 4. Nebenbefunde
- **Rider-Konfiguration im Repo:** Mit einem `git add -A` waren vier `.idea/`-Dateien in einen
Commit gerutscht. Sie blockierten den `git pull` auf der VM, wo Rider dieselben Dateien lokal
anlegt. Entfernt, `.idea/` steht jetzt in `.gitignore`.
- **Verbindungs-Multiplexing (`ControlMaster`) funktioniert nicht** — Windows-OpenSSH
unterstützt es nicht. Aus der SSH-Konfiguration entfernt; stattdessen werden mehrere
Prüfschritte pro Aufruf gebündelt.
- **Speicher ist reichlich vorhanden** (31 GB, davon 25 GB frei). Die Vermutung, der
Claude-Desktop-Absturz auf der VM könnte an Speichermangel liegen, ist damit **widerlegt**.
---
# Nachtrag: vollständiger Durchgang
Nach Einrichtung von MariaDB und befristetem passwortlosem `sudo` wurde der Rest des Prüfplans
abgearbeitet.
## 5. Betrieb mit Datenbank
| Prüfpunkt | Ergebnis |
|---|---|
| **MariaDB** | 11.8.6 installiert — **genau die Version**, die in `DatabaseServerVersion` gepinnt ist. Datenbank `polytrader_test` mit eigenem Benutzer angelegt |
| **Migrationen** | Alle fünf DbContexts (Core, CopyTrading, ResolutionFarming, Supervisor, Accounting) melden „Done.". **21 Tabellen** mit den Präfixen `core_`, `ct_`/`mod_copytrading_`, `rf_`, `acc_` |
| **Start mit Datenbank** | Läuft vollständig durch: Core-Hydration abgeschlossen, `MarketSyncService` gestartet |
| **Echter Datenverkehr** | **100 Märkte von der Polymarket-API geholt und geschrieben**, beim zweiten Lauf 100 aktualisiert. HTTP, TLS, JSON-Verarbeitung und Datenbankzugriff funktionieren unter Linux |
> Das ist der eigentliche Beweis: Die Anwendung *arbeitet* auf Linux, sie startet nicht nur.
## 6. Dienstbetrieb (systemd)
| Prüfpunkt | Ergebnis |
|---|---|
| **Dienst** | `active (running)`, 71,6 MB Speicher, 20 Tasks. Startet automatisch mit dem System |
| **`WorkingDirectory`-Falle (D-11)** | ✅ **Kein Problem.** Gezielt geprüft: `server_settings.xml` in `/opt/polytrader` mit Testzeitzone `America/New_York` angelegt — die Anwendung meldete genau diese Zone. Eine `find`-Suche über das gesamte Dateisystem fand **keine zweite** Datei. Die Unit setzt `WorkingDirectory` korrekt |
| **Nebenbefund** | `server_settings.xml` wird beim Start **nicht angelegt** — erst beim Speichern von Einstellungen. Ein frisch installierter Dienst läuft also mit Standardwerten und ohne Konfigurationsdatei |
| **Shutdown (SIGTERM)** | ✅ **0,08 Sekunden** — weit unter `TimeoutStopSec=45`. „Deactivated successfully", **kein `SIGKILL`** im gesamten Journal |
| **Neustart nach Absturz** | ✅ `kill -9` auf den Hauptprozess → `Restart=on-failure` greift, neue PID nach ~10 s |
| **Neustartschutz bei Konfigurationsfehler** | ✅ Verbindung entfernt → Status `failed`, **Exit-Code 78**, systemd meldet ihn als `78/CONFIG`. **Keine Neustartschleife.** Die verständliche Meldung steht im Journal. Damit wirkt der Fix aus B-1 im Dienstbetrieb nachweislich |
| **Dateirechte** | `master.key` `0600`, Eigentümer `polytrader` |
## 7. Logrotate
Regel mit **zwei Mustern** (wegen B-2) und `copytruncate` eingerichtet. Erzwungener Lauf: alle drei
Logdateien rotiert und komprimiert, Originale auf 0 Bytes gesetzt, **Dienst schreibt ohne
Unterbrechung weiter**.
`copytruncate` ist hier zwingend: Die Anwendung hält die Logdatei offen und bekommt ein Umbenennen
nicht mit — sie würde sonst in die rotierte Datei weiterschreiben.
## 8. Zeitzonen-Befund T2 — **belegt**
Bisher nur behauptet, jetzt bewiesen. Systemzeitzone auf UTC gestellt, App-Anzeigezone auf
`Europe/Berlin`:
```
System UTC : 2026-08-26 20:04:51
Berlin : 2026-08-26 22:04:51
Logzeile: [20:04:39] [Info] Anzeige-Zeitzone: Europe/Berlin
JSON-Zeile: {"ts":"2026-08-26T20:04:39.398+00:00", …}
```
**Der Widerspruch steht in derselben Zeile:** Die Anwendung meldet Berlin als Anzeigezone und
stempelt gleichzeitig mit UTC.
**Betriebliche Folge:** Auf einem UTC-Server — dem Normalfall — zeigen alle Logs UTC, während die
Oberfläche Berliner Zeit anzeigt. Wer einen Vorfall von „22:30" sucht, findet ihn unter 20:30, und
zwischen Mitternacht und 2 Uhr sogar in der Datei des **Vortags**. Das macht Fehlersuche im
Ernstfall unnötig schwer.
**Nicht behoben** — gehört zu T2 (Umstellung auf `Microsoft.Extensions.Logging`) und ist ein
eigener Schnitt. Die Systemzeitzone wurde nach dem Test auf `Europe/Berlin` zurückgestellt.
## 9. Oberfläche unter Linux
**Alle Fenster konstruieren fehlerfrei** (`--smoke-ui` unter `xvfb-run`):
```
[OK] core.start, core.dashboard, core.settings, core.jobs, core.terminal
[OK] copytrading.main, resolutionfarming.main, supervisor.main, accounting.main
[OK] ShellWindow konstruiert
[OK] ShutdownConfirmWindow konstruiert
[OK] Einstellungs-Editor: 7 Abschnitte, 17 Felder
[OK] Farbschema „Light": alle 27 Farben vorhanden
[OK] Farbschema „Dark": alle 27 Farben vorhanden
```
### B-4 · `--smoke-ui` braucht einen X-Server · offen
Ohne Display scheitert die Konstruktionsprüfung mit `System.Exception: XOpenDisplay failed` aus
`AvaloniaX11Platform.Initialize`. Sie ist aber als **CI-Werkzeug** gedacht, und ein Build-Server
hat typischerweise keinen Bildschirm.
**Zwei Wege:**
1. **`xvfb-run -a` vorschalten** — funktioniert nachweislich (siehe oben), erfordert nur das Paket
`xvfb` im Build-Image. Ein Einzeiler im CI-Workflow.
2. `Avalonia.Headless` verwenden statt des X11-Backends. Sauberer, aber eine Codeänderung.
Empfehlung: Weg 1, wenn A2 (CI-Runner) wieder aufgenommen wird — dann `xvfb` ins Image und
`--smoke-ui` als zusätzlichen Prüfschritt aufnehmen. Der Nutzen wäre erheblich: Die
Konstruktionsprüfung deckt neun Views und beide Farbschemata ab.
### Noch offen: Sichtprüfung
Die Anwendung wurde **nicht mit sichtbarem Fenster** geprüft — das braucht jemanden am Bildschirm
der VM. Schriftrendering, Spaltenbreiten und Dunkelmodus sehen unter GTK erfahrungsgemäß anders
aus als unter Windows. Das ist der verbleibende Rest von A1 auf der Zielplattform.
---
## 10. Zustand der VM nach dem Durchgang
**Bewusst stehen geblieben** (damit weitergetestet werden kann):
- MariaDB 11.8.6 mit Datenbank `polytrader_test`
- Dienst `polytrader.service` unter `/opt/polytrader`, aktiv
- Logrotate-Regel `/etc/logrotate.d/polytrader`
- Xvfb (allgemein nützlich)
- Anleitung `~/TESTUMGEBUNG.md`
**Zurückgestellt:** Systemzeitzone wieder `Europe/Berlin`.
**Noch offen:** Die befristete `sudo`-Freigabe `/etc/sudoers.d/99-testing` ist **aktiv** und sollte
entfernt werden, sobald nicht mehr getestet wird:
```bash
sudo rm /etc/sudoers.d/99-testing
```
Vollständige Aufräumbefehle: [TESTUMGEBUNG-Linux-VM.md](../TESTUMGEBUNG-Linux-VM.md) §7.
---
# Nachtrag 2: Sichtprüfung der Oberfläche
Durchgeführt **ohne Bildschirm**: Die Anwendung lief unter `Xvfb` (virtuelles Display
1600×1000), Navigation per `xdotool`, Aufnahmen mit `import`. Damit ist die Sichtprüfung
reproduzierbar und ohne Anwesenheit möglich.
⚠️ **Erst vier von neun Ansichten geprüft.** Ohne Lizenzschlüssel deaktiviert die Anwendung
**alle Module** (`BuildHost`: `if (!licensed) foreach (var m in allModules) disabled.Add(...)`),
sodass Copytrading, ResolutionFarming, Supervisor und Accounting in der Seitenleiste ausgegraut
bleiben. Für deren Prüfung wird ein Lizenzschlüssel gebraucht.
## Was gut aussieht
| | |
|---|---|
| **Schriftrendering** | Sauber und vollständig — Umlaute, typografische Anführungszeichen („…") und sogar Emoji werden korrekt dargestellt. Im Terminal auch die Monospace-Schrift. Unter Linux mit Fontconfig keineswegs selbstverständlich |
| **Diagramme (Skia)** | LiveCharts2 rendert: Achsen, Gitternetz, Beschriftungen, Rahmen |
| **Layout** | Keine Überlappungen, keine abgeschnittenen Texte, keine zerbrochenen Werkzeugleisten. Die Einfenster-Shell mit Seitenleiste sitzt |
| **Symbole** | Die nach `Assets/` verschobenen PNGs werden korrekt angezeigt — der Umzug beim Frühjahrsputz hat gehalten |
| **Dunkelmodus** | Durchgängig konsistent über alle geprüften Ansichten |
| **Einstellungs-Editor** | Der `PropertyGrid`-Ersatz funktioniert wie vorgesehen: Kategorie-Überschrift, Label links, Feld rechts, Hinweis darunter |
## Befunde
### B-5 · Windows-Pfad als Standardwert unter Linux · offen
Im Einstellungsfenster steht bei **Mullvad CLI Path**:
```
C:\Program Files\Mullvad VPN
esources\mullvad.exe
```
Auf einem Linux-System ist das sinnlos — dort liegt die ausführbare Datei üblicherweise unter
`/usr/bin/mullvad`. Der Standardwert stammt aus der Windows-Zeit und wurde bei der Portierung
nicht mitgezogen. Folge: Wer die VPN-Rotation auf dem Zielserver einschaltet, ohne den Pfad von
Hand zu korrigieren, bekommt einen Fehler, dessen Ursache nicht offensichtlich ist.
**Empfehlung:** Standardwert plattformabhängig setzen — unter Linux `/usr/bin/mullvad`, unter
Windows der bisherige Pfad.
### B-6 · Zu geringer Textkontrast in den KPI-Kacheln · offen
Der grüne Text in den Modul-KPI-Kacheln erreicht gegen den Kachelhintergrund nur
```
Textfarbe RGB(46, 104, 68)
Hintergrund RGB(35, 37, 39)
Kontrast 2,33 : 1
```
**WCAG AA verlangt 4,5:1** für normalen Text (3:1 erst ab 18,7 px fett). Der Wert liegt also
deutlich darunter — auf einem hellen Bildschirm oder aus normalem Sitzabstand sind die Zahlen
schwer zu lesen.
Betrifft die gedämpfte „positiv"-Farbe des Dunkelmodus. Anzuheben, ohne die Signalwirkung
(grün = positiv, rot = negativ) aufzugeben.
### B-7 · „Gesamt" erscheint doppelt in der KPI-Kachel · offen, klein
Die Kachel trägt die Überschrift **Gesamt** und darunter als erste Textzeile noch einmal
**Gesamt**. Sieht wie ein Darstellungsfehler aus; vermutlich wird der Modulname sowohl als Titel
als auch im Textblock gerendert.
### B-8 · Datumsachse der Equity-Kurve zeigt zwölfmal „01.01." · offen
Bei eingestelltem Zeitraum „30 Tage" trägt die X-Achse der Equity-Kurve **zwölf identische
Beschriftungen „01.01."**. Erwartet wären fortlaufende Daten über den Zeitraum.
Vermutlich werden die Achsen-Ticks nicht auf echte Datumswerte abgebildet, sondern auf einen
Standardwert — bei leerem Datenbestand fällt das besonders auf. **Nicht Linux-spezifisch:** Der
Fehler dürfte unter Windows genauso auftreten, ist dort nur nie jemandem aufgefallen.
Zu prüfen, sobald echte Trades vorliegen — falls die Achse dann korrekte Daten zeigt, ist es ein
reiner Leerzustands-Fehler und weniger dringend.
## Noch zu prüfen
Die vier **Modulfenster** (Copytrading, ResolutionFarming, Supervisor, Accounting). Genau dort
liegen laut A5 die interessanten Punkte: Splitter-Positionen, Spaltenbreiten der Grids und die
Frage, ob die acht KPI-Kacheln im Accounting sinnvoll umbrechen.
**Voraussetzung:** ein Lizenzschlüssel auf der VM. Das Deploymentcenter ist von dort erreichbar
(HTTP/2 302), und die Lizenz-CLI läuft bereits — sie meldet eine **HWID v2 auf Basis der
Linux-machine-id**. Ein Aktivierungsversuch wäre damit zugleich die Live-Abnahme von **D-2**
(Roadmap A3).
---
# Nachtrag 3: Modulfenster (nach Lizenzaktivierung)
Richard hat den Lizenzschlüssel auf der VM hinterlegt. Die Anwendung meldet
**„Lizenz gültig (online geprüft)"**, `--license-status` zeigt `Cache: valid`, Statusleiste
**„Module: 4"**.
> **Damit ist D-2 live abgenommen** — Lizenzaktivierung gegen das echte Deploymentcenter,
> einschließlich HWID v2 auf Basis der Linux-`machine-id`. Ein Stück von Roadmap **A3** ist
> nebenbei erledigt.
## B-9 · Kalendersymbol wird als sinnlose Zahl dargestellt · offen
In den Datumsfeldern des Accounting-Fensters erscheint rechts statt eines Kalendersymbols ein
Artefakt, das wie **„26" mit einem Punkt darüber** aussieht — in beiden Feldern („Von", „Bis").
**Ursache:** Das Symbol stammt aus einer Icon-Schriftart, die unter Linux fehlt. Fontconfig
ersetzt sie stillschweigend durch eine andere Schrift, in der derselbe Zeichencode etwas ganz
anderes bedeutet. Ein typischer Portierungsfehler: Es gibt keine Fehlermeldung, das Zeichen ist
einfach falsch.
**Nur im Bild zu sehen, nie im Log.** Unter Windows sieht dieselbe Stelle korrekt aus.
## B-10 · Kein einziges DataGrid wurde gerendert · **behoben** · **schwerwiegend**
**Der wichtigste Befund dieses Durchgangs.**
**Beobachtet:** Sämtliche Tabellen der Anwendung waren leer — keine Zeilen, keine Spaltenköpfe,
nur eine leere Fläche. Betroffen: Master-Trader, Offene Trades, Geschlossene Trades,
Account-Übersicht, Ledger, Jobs, schlicht alle.
**Ursache:** `Avalonia.Controls.DataGrid` liegt in einem **eigenen Paket** und bringt sein Theme
**nicht** über `<FluentTheme />` mit. In `App.axaml` fehlte:
```xml
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml" />
```
Die vorhandenen Anpassungen für `DataGrid` und `DataGridColumnHeader` in derselben Datei bauen auf
diesem Basis-Theme auf und liefen bisher ins Leere.
**Warum das monatelang unbemerkt blieb** — drei Gründe, die zusammenkamen:
1. **Keine Fehlermeldung, keine Bindungswarnung.** Das Steuerelement existiert, es zeichnet nur nichts.
2. **Die Konstruktionsprüfung bleibt grün**, weil das Fenster ja aufgebaut wird — sie prüft
Konstruktion, nicht Darstellung.
3. **Die Abnahme mit echten Daten (A5) stand noch aus.** Ohne Daten sieht eine leere Tabelle aus
wie fehlende Daten, nicht wie ein Fehler.
**Der Fehler war nicht linuxspezifisch** — er bestand unter Windows genauso. Er ist nur hier
aufgefallen, weil zum ersten Mal jemand systematisch hingesehen hat.
**Behoben und gegengeprüft:** Nach dem Fix erscheinen die Spaltenköpfe („#", „Wallet",
„Kategorie", „Trades", „Winrate", „PnL", „Copy-PnL" …). Vorher war die Fläche komplett leer.
## B-11 · Spaltenüberschriften werden abgeschnitten · offen
Direkt sichtbar, sobald B-10 behoben war — und **genau der A5-Punkt „Spaltenbreiten"**:
```
Trades (7 statt Trades (7T)
Winrate ' statt Winrate %
Copy-PnL statt Copy-PnL (30T)
```
Die letzten drei Spalten (Profit-Faktor, Ø PnL/Trade, Copy-Trades) zeigen **gar keinen Text
mehr** — für sie reicht die Breite des Fensterbereichs nicht.
**Ursache:** Die festen Pixelbreiten in
[`CopyTradingWindow.axaml`](../../src/PolyTrader.App.Avalonia/Views/Modules/CopyTradingWindow.axaml)
(50, 170, \*, 110, 50, 90, 90, 100, 110, 100, 100, 90) stammen aus der WinForms-Fassung. Die dort
verwendete Schrift war schmaler als die Avalonia-Standardschrift, sodass dieselben Werte jetzt
nicht mehr ausreichen.
**Nicht behoben** — Spaltenbreiten lassen sich sinnvoll erst mit echten Daten festlegen, sonst
optimiert man auf leere Zellen. Gehört zur A5-Abnahme.
## B-12 · Lizenzschlüssel liegt im Klartext · offen, klein
`--license-status` meldet: **„Gespeicherter Schlüssel (server_settings.xml): gesetzt (Klartext)"**.
Die Projektkonvention ist Verschlüsselung at-rest über den Master-Key (`enc:v1:` …), und der Code
unterstützt beides — `SecretProtection.Unprotect` reicht Klartext unverändert durch. `--license-set-key`
verschlüsselt aber offenbar nicht.
Ein Lizenzschlüssel wiegt weniger schwer als ein Wallet-Schlüssel, aber die Konvention sollte
einheitlich gelten. Zumal `server_settings.xml` auch den Watchdog-Token trägt.
## Bewertung der Modulfenster
| Fenster | Beobachtung |
|---|---|
| **Accounting** | **Die acht KPI-Kacheln brechen sinnvoll um** — sieben in einer Reihe, die achte darunter. Eine der offenen A5-Fragen ist damit beantwortet. Tabs, Datumswahl, Währungswahl und die drei Schaltflächen sitzen sauber |
| **Copytrading** | Alle vier Tabs vorhanden, die in A3 nachgerüsteten Schaltflächen „Neu" und „Löschen" sind da. Splitter funktioniert. Der rechte Bereich wirkt im Leerzustand zerrissen: „Zugewiesene Accounts" klebt am unteren Rand, weil es fest auf `DockPanel.Dock="Bottom"` mit `Height="220"` steht, während das Detailformular darüber leer bleibt. **Mit Daten neu zu beurteilen** |
| **ResolutionFarming, Supervisor** | Aufgenommen, aber im Leerzustand ohne Aussagekraft — beide leben von Tabellen, die vor B-10 ohnehin unsichtbar waren |
**Empfehlung:** Die Sichtprüfung der Modulfenster **mit echten Daten wiederholen**, sobald B-10
ausgeliefert ist. Erst dann lassen sich Spaltenbreiten (B-11), Splitter-Positionen und
Leerzustände sinnvoll beurteilen. Das Verfahren dafür ist dokumentiert und wiederholbar:
[TESTUMGEBUNG-Linux-VM.md](../TESTUMGEBUNG-Linux-VM.md) §4.7.
---
# Nachtrag 4: Sichtprüfung mit Testdaten
Nach der Behebung von B-10 wurden **Testdaten** in die Testdatenbank eingespielt, um die Tabellen
in Betrieb zu sehen: 3 Demo-Konten, 5 Master-Trader, 3 offene Positionen, 7 abgeschlossene Trades,
5 ResolutionFarming-Kandidaten. Wiederverwendbar als
[`testdaten-ui.sql`](./testdaten-ui.sql).
> **Bewusst realistisch:** 42-stellige Wallet-Adressen und lange englische Marktfragen. Kurze
> Platzhalter wie „Test 1" hätten die Befunde B-11 und B-13 verdeckt.
**Das war der entscheidende Schritt.** Mit Daten zeigt sich in Minuten, was ohne sie unsichtbar
bleibt — die Anwendung wirkt jetzt vollständig funktionsfähig: Grids füllen sich, die Auswahl
markiert Zeilen, das Detailformular übernimmt den gewählten Datensatz, zugewiesene Konten werden
korrekt angehakt, KPI-Kacheln rechnen, die Trade-Historie erscheint.
## B-13 · Die Spalte „Name" ist unsichtbar zusammengequetscht · offen · **wichtig**
Im Master-Trader-Grid ist die Spalte **Name** (`Width="*"`) auf wenige Pixel zusammengedrückt.
Die Anzeigenamen — *WeatherWhale*, *PolitiSniper*, *SportsEdge Capital* — sind **nirgends im Grid
zu sehen**, obwohl sie die wichtigste Information der Zeile sind. Sichtbar ist nur die
abgeschnittene Wallet-Adresse (`0x9e2b7f4a1c8d0e5b…`, 18 von 42 Zeichen).
**Ursache:** Die festen Breiten der elf übrigen Spalten summieren sich auf mehr, als der Bereich
links vom Splitter hergibt. Die Sternbreite bekommt, was übrig bleibt — und das ist fast nichts.
**Empfehlung:** Der Name gehört nach vorn (direkt hinter `#`) und braucht eine Mindestbreite;
die Wallet-Adresse ist ein Kandidat fürs Ausblenden oder für eine Kurzform (`0x9e2b…3b95`).
## B-11 · präzisiert: Nicht die Werte sind zu breit, sondern die Überschriften
Der Vergleich zweier Grids macht die Ursache eindeutig:
| Grid | Ergebnis |
|---|---|
| **ResolutionFarming-Kandidaten** | Sieht **gut** aus. Lange Marktfragen passen fast vollständig, die Zahlen sind lesbar |
| **Master-Trader** | Überschriften abgeschnitten: `Trades (7`, `Winrate '`, `Copy-PnL`; die letzten drei Spalten ohne Text |
Auch im ResolutionFarming-Grid stehen `Outcor` statt „Outcome" und `Fee (bp` statt „Fee (bps)" —
während die Werte darunter (`Yes`, `180`) mühelos passen.
**Die Spaltenbreiten sind auf die Datenwerte ausgelegt, nicht auf die Überschriften.** Das ist ein
Muster, kein Einzelfall: Wo Werte kurz und Titel lang sind, wird der Titel abgeschnitten. Zu
beheben durch breitere Spalten oder kürzere Titel (`Fee` statt `Fee (bps)`, Einheit in den
Tooltip).
## B-14 · Mehrzeilige Texte in einzeiligen Feldern · offen, klein
Im Detailformular sind **Beschreibung** und **Reasoning** einzeilige Textfelder, obwohl die
Datenbankspalten `varchar(1000)` fassen. Sichtbar ist nur ein Bruchteil
(„Setzt fast ausschliesslich auf Tem…"). Ein mehrzeiliges Feld wäre angemessen.
## B-15 · Ein fehlerhafter Datensatz legt die gesamte Modul-Hydration lahm · offen
Beim ersten Einspielen enthielt `AssignedAccountIds` versehentlich `"1,2"` statt des erwarteten
JSON-Arrays `"[1,2]"`. Ergebnis:
```
Copytrading-Hydration fehlgeschlagen: The JSON value could not be converted to
System.Collections.Generic.HashSet`1[System.Int32]. Path: $ | LineNumber: 0
```
**Es wurde kein einziger Master-Trader geladen** — ein einzelner unlesbarer Datensatz verhindert
das Laden aller anderen. Im Betrieb hieße das: Ein beschädigter Eintrag legt das komplette Modul
still, statt übersprungen und gemeldet zu werden.
Der Fehler war hier selbst verschuldet, das Verhalten dahinter ist es nicht. **Empfehlung:**
Datensatzweise behandeln — fehlerhafte Einträge überspringen, mit Kennung protokollieren, den
Rest laden.
## B-7 · bestätigt
Mit Daten ist es eindeutig: In **jeder** KPI-Kachel steht der Modulname doppelt — als Überschrift
und als erste Textzeile („CopyTrading / CopyTrading / Heute: +26,10 USDC …").
## Kein Fehler — nachgeprüft
Die Spalte **Copy-PnL** zeigt für alle Trader `0,00`, obwohl die Testdaten Werte enthielten. Ein
Blick in die Datenbank zeigt: Die Werte stehen auch dort auf 0. Die Anwendung berechnet die
Copy-Kennzahlen aus den tatsächlichen Copy-Trades neu, und `mod_copytrading_closed_trades` ist
leer. **Korrektes Verhalten.**
## Weitere Beobachtungen aus dem Datenlauf
- **Account-Übersicht (Dashboard):** „Demo Hauptkonto (De…" und „CopyTrading, ResolutionFar…"
abgeschnitten, während rechts neben „Overall P/L" rund 300 px ungenutzt bleiben. Dasselbe Muster
wie B-11.
- **Warnungen & Fehler (Dashboard):** Die Spalte „Nachricht" ist so schmal, dass keine Meldung
vollständig lesbar ist.
- **Leerzustände** melden nichts. Wo ResolutionFarming für ein Konto ohne Kandidaten steht, bleibt
die Fläche leer — ein Hinweis „Keine Kandidaten für dieses Konto" würde die Frage beantworten,
ob gefiltert oder gar nichts geladen wurde. (Die Filterung selbst arbeitet korrekt, geprüft.)
## Empfehlung
Die Befunde B-11, B-13 und B-14 sind **Layoutarbeit an einer Stelle** und sollten zusammen
angegangen werden — am besten mit eingespielten Testdaten, weil sich Spaltenbreiten nur so
sinnvoll festlegen lassen. Das Verfahren ist reproduzierbar:
[TESTUMGEBUNG-Linux-VM.md](../TESTUMGEBUNG-Linux-VM.md) §4.7 plus `testdaten-ui.sql`.