"0 DHCP-Server (!)" in Rot: In der Produktionsdatenbank stehen drei
ausgelieferte Messungen des entfernten Werkzeugs dhcpcheck mit Ergebnis
{"count":0,"server":[],"hinweis":""} und Status 2. Bei Kabelverbindung gibt
Android die DHCP-Angaben aber grundsaetzlich nicht heraus (nur DhcpInfo, nur
WLAN, deprecated) - gemessen wurde also nichts, "0 gefunden" war der
Rueckgabewert fuer "nicht ermittelbar". netdiagAltlastKorrektur() zeigt diese
Messungen jetzt als "nicht messbar" mit Erklaerung, in PDF und
Technikeransicht. Rohdaten bleiben unangetastet, korrigiert wird nur die
Darstellung - und die wird bei jedem Abruf neu erzeugt. Die Ergebniszahlen
werden dabei unterdrueckt: "Gefundene Geraete: 0" widerspraeche der Aussage
direkt darueber.
"Lease-Dauer: 864000 s s": aeltere App-Fassungen haben die Einheit in den Wert
geschrieben, die Feldtabelle haengt sie erneut an (Prod-Messung #42).
Adress- und Lease-Felder mit dem Wert 0 erscheinen jetzt als "nicht
ermittelbar" statt als "0" - das war nie eine Messung, sondern das
"nichts ermittelt" der alten Android-API.
Neu in der Whitelist: dhcpQuelle (system = LinkProperties ab Android 11 fuer
jeden Anschlusstyp, wlan = alter Weg nur fuer WLAN). Damit ist klaerbar, ob
eine fehlende DHCP-Angabe an der Leitung lag oder an der Android-Version.
Geprueft gegen die lokale Testinstanz mit einer Kopie der echten
Prod-Messungen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
191 lines
11 KiB
Markdown
191 lines
11 KiB
Markdown
# Changelog NetDiag
|
|
|
|
## 1.1.4 — 2026-08-16
|
|
|
|
### Drei Falschaussagen im Kundendokument, alle aus Altdaten
|
|
|
|
- **„0 DHCP-Server (!)" in Rot.** In der Produktionsdatenbank stehen drei
|
|
ausgelieferte Messungen des entfernten Werkzeugs `dhcpcheck` mit Ergebnis
|
|
`{"count":0,"server":[],"hinweis":""}` und Status 2. Bei einer Kabelverbindung
|
|
gibt Android die DHCP-Angaben aber grundsätzlich nicht heraus (nur `DhcpInfo`,
|
|
nur WLAN, deprecated) — gemessen wurde also nichts, „0 gefunden" war der
|
|
Rückgabewert für „nicht ermittelbar". `netdiagAltlastKorrektur()` zeigt diese
|
|
Messungen jetzt als „nicht messbar" mit Erklärung, in PDF **und**
|
|
Technikeransicht. Die gespeicherten Rohdaten bleiben unangetastet (Beleg);
|
|
korrigiert wird nur die Darstellung, und die wird bei jedem Abruf neu erzeugt.
|
|
Die Ergebniszahlen werden bei so korrigierten Messungen unterdrückt —
|
|
„Gefundene Geräte: 0" widerspräche der Aussage direkt darüber.
|
|
- **„Lease-Dauer: 864000 s s".** Ältere App-Fassungen haben die Einheit in den
|
|
Wert geschrieben, die Feldtabelle hängt sie erneut an. Nachgewiesen an
|
|
Prod-Messung #42. Die Einheit wird jetzt nur noch angehängt, wenn sie nicht
|
|
schon am Wert steht.
|
|
- **Adress- und Lease-Felder mit dem Wert 0** (`server`, `dhcpServer`,
|
|
`gateway`, `ipv4`, `lease` …) sind keine Messung, sondern das „nichts
|
|
ermittelt" der alten Android-API. Sie erscheinen jetzt als „nicht ermittelbar"
|
|
statt als „0".
|
|
|
|
Neues Feld in der Whitelist: `dhcpQuelle` — `system` (LinkProperties, ab
|
|
Android 11, gilt für jeden Anschlusstyp) oder `wlan` (alter Weg, nur WLAN, dafür
|
|
mit Lease-Dauer). Damit ist im Nachhinein klärbar, ob eine fehlende DHCP-Angabe
|
|
an der Leitung lag oder an der Android-Version.
|
|
|
|
## 1.1.3 — 2026-08-16
|
|
|
|
### Internet-Kette im PDF + ein Zeichenfehler, der jedes Protokoll betraf
|
|
|
|
- **`netdiagPdfKette()`** für das neue App-Werkzeug „Internet-Kette": Fehlerglied
|
|
als eigene hervorgehobene Zeile, darunter die vier geprüften Stufen einzeln,
|
|
dann Systemurteil und Hinweis. Ohne eigenen Zweig stünden die Stufen als
|
|
`|`-Kette in einer Zelle und das Fehlerglied — die eigentliche Aussage —
|
|
mittendrin.
|
|
- **`netdiagPdfText()`: Pfeile wurden als „?" gedruckt.** `pdf_getPDFFont()`
|
|
liefert hier Helvetica, einen Core-Font mit WinAnsi-Kodierung; alles außerhalb
|
|
dieses Zeichenvorrats setzt TCPDF wortlos als „?" (bekannt aus KB #1025).
|
|
Aufgefallen an „www.google.de → 142.250.185.67", das im Kundendokument als
|
|
„www.google.de ? 142.250.185.67" ankam — der Pfeil ist dort kein Schmuck,
|
|
er trennt Frage und Antwort. Die Ersetzung greift jetzt in **allen**
|
|
PDF-Zweigen, also auch für Altdaten und künftige Werkzeuge.
|
|
Bewusst keine Unicode-Schrift: `dejavusans` würde Schriftbild und Dateigröße
|
|
aller Protokolle ändern. Gedankenstrich, Mittelpunkt, Auslassungspunkte und
|
|
Anführungszeichen sind in WinAnsi enthalten und bleiben unangetastet
|
|
(im erzeugten Dokument nachgeprüft).
|
|
- Feld-Whitelist um `fehlerglied`, `stufen`, `systemUrteil`, `validated` und
|
|
`captivePortal` erweitert, Werkzeugname `internetkette` → „Internet-Kette".
|
|
`validated`/`captivePortal` kommen aus dem LinkInfo-Objekt und erscheinen
|
|
damit auch beim IP-Test an der Dose.
|
|
|
|
Geprüft an vier Fällen gegen die lokale Testinstanz, zwei davon sind die echten
|
|
Emulator-Messungen dieser Nacht (Gutfall und Flugmodus).
|
|
|
|
## 1.1.2 — 2026-08-16
|
|
|
|
### Geräte-Monitor bekommt einen eigenen PDF-Zweig
|
|
|
|
Die Dauerüberwachung lief bisher in den generischen `else`-Zweig von
|
|
`netdiag_pdf.lib.php` und wurde von `netdiagPdfFlattenResult()` zu **einer**
|
|
`|`-getrennten Zeile zusammengeschoben. Bei zehn überwachten Geräten standen
|
|
damit die zehn Geräte-Zeilen UND sämtliche Einzelausfälle in einer einzigen
|
|
Tabellenzelle — vollständig, aber beim Kunden nicht lesbar. Dauertest und
|
|
WLAN-Kanal hatten längst je einen Tabellen-Renderer, der Monitor nicht.
|
|
|
|
- **`netdiagPdfMonitor()`**: Kennzahlenzeile, Tabelle „Überwachte Geräte",
|
|
Tabelle „Einzelne Ausfälle" mit Uhrzeiten, Hinweis zum Messverfahren am Ende.
|
|
- **Die Falle dabei**, gegen die es einen Kommentar im Code gibt: beim Dauertest
|
|
führt ein gesetztes `hinweis` zum sofortigen Abbruch der Ausgabe. Der Monitor
|
|
legt aber IMMER einen Hinweis an (das Messverfahren gehört zur Aussage dazu) —
|
|
derselbe Aufbau hätte hier bei **jedem** Lauf alle Zahlen verschluckt. Nur
|
|
`fehler` bricht ab, der Hinweis steht am Schluss.
|
|
- Tabellenköpfe wiederholen sich nach einem Seitenumbruch („— Fortsetzung"),
|
|
wie in der Geräteliste.
|
|
- Obergrenze 200 Ausfallzeilen gegen den pathologischen Fall (ein im
|
|
Sekundentakt flappendes Gerät erzeugt über einen Arbeitstag vierstellig viele
|
|
Segmente). Gekürzt wird **sichtbar**: „… und N weitere Ausfälle" steht im
|
|
Dokument, sonst läse sich das Protokoll als vollständig.
|
|
- **`ausfallzeitSek` heißt jetzt „Ausfallzeit (schlechtestes Gerät)"** — der
|
|
Wert ist der des schlechtesten Geräts, nicht die Summe über alle. Bei zehn
|
|
überwachten Geräten las sich „Ausfallzeit: 8 min" wie eine Gesamtaussage.
|
|
Gleiche Korrektur in `app/src/lib/messfelder.ts`, damit App und PDF dasselbe
|
|
Feld gleich benennen.
|
|
|
|
Geprüft gegen die lokale Testinstanz mit vier konstruierten Fällen (10 Geräte
|
|
mit Aussetzern, ein durchgehend totes Gerät, 250 Einzelausfälle über sechs
|
|
Seiten, abgerissener Lauf) und gegen die echte Monitor-Messung aus ND2026-0016.
|
|
|
|
## 1.1.1 — 2026-08-16
|
|
|
|
### Vier stille Fehler im Kundendokument und im Sync
|
|
|
|
Alle vier waren bereits ausgeliefert und fielen nicht auf, weil das PDF ja
|
|
weiterhin erzeugt wurde — nur ohne die betroffene Zeile. Gefunden durch einen
|
|
systematischen Abgleich der Whitelist gegen den erzeugenden App-Code.
|
|
|
|
- **`'typ'` war ein toter Schlüssel.** Kein Werkzeug erzeugt ihn; die App reicht
|
|
ein `LinkInfo`-Objekt durch, dort heißt das Feld `'type'`. Folge: im
|
|
Abnahmebeleg für eine Netzwerkdose fehlte die Angabe, **ob per LAN oder WLAN
|
|
gemessen wurde**. Zusätzlich `'rssi'` aufgenommen — bei einer WLAN-Dose ist
|
|
der Empfangspegel der eigentliche Messwert und wurde bisher verworfen.
|
|
Die Rohwerte sind englisch; `netdiagKundentext()` bildet sie jetzt ab
|
|
(`ethernet` → „LAN (Kabel)"), sonst stünde „Anschlussart: ethernet" im
|
|
Abnahmeprotokoll eines deutschen Handwerksbetriebs.
|
|
- **Leeres Array druckte „Offene Ports: " ohne Wert.** Die Leerprüfung ist ein
|
|
`elseif` hinter dem Array-Zweig und wurde nie erreicht. Betraf ausgerechnet
|
|
die *guten* Ergebnisse: Portscan ohne offenen Port, IP-Konflikt ohne Konflikt,
|
|
IP-Scan ohne Veränderung. Jetzt „keine" — Weglassen wäre schlechter, weil der
|
|
Kunde sonst nicht unterscheiden kann, ob nichts gefunden oder nichts geprüft
|
|
wurde.
|
|
- **`'error'` fehlte in der Whitelist.** Der IP-Konflikt gibt im Abbruchfall
|
|
`{ error: … }` mit roter Ampel zurück — im Kundendokument stand eine rote
|
|
Ampel ohne einen Buchstaben Erklärung. Die App vereinheitlicht künftig auf
|
|
`'fehler'`, aber Altdaten lassen sich nicht ändern.
|
|
- **`tool`/`category`/`label` wurden beim Sync nicht auf die Spaltenlänge
|
|
gekürzt** (varchar 64/32/255). Bei striktem SQL-Modus kippt **ein** zu langes
|
|
Label den gesamten Sync per `rollback()` — der Techniker steht beim Kunden mit
|
|
einem Protokoll da, das sich nicht abschließen lässt, weil eine Beschriftung
|
|
zu lang war. Die App setzt Labels durch Verketten zusammen, 255 Zeichen sind
|
|
erreichbar. `found_via` wurde 20 Zeilen darüber längst gekappt.
|
|
|
|
### Rechteprüfung im GET-Zweig der Protokoll-API
|
|
|
|
Bisher prüfte der GET-Zweig **gar nichts**: jeder angemeldete Benutzer konnte
|
|
mit einer geratenen ID ein fremdes Protokoll samt Geräteliste, IP-Adressen und
|
|
offenen Ports abrufen (der POST-Zweig verlangte seit jeher `write`). Das ist
|
|
beim Kunden erhobene Netzstruktur und gehört hinter ein Recht.
|
|
|
|
`write` wird bewusst mit akzeptiert: die Rechte sind in Dolibarr einzeln
|
|
vergebbar, und ein Techniker mit Schreib- ohne ausdrückliches Leserecht dürfte
|
|
nicht ausgesperrt werden — das wäre erst beim Kunden aufgefallen.
|
|
|
|
### Geräte-Monitor erscheint jetzt im Kundendokument
|
|
|
|
Die App liefert ab dieser Version eine Auswertung der Dauerüberwachung als
|
|
richtige Messung (Verfügbarkeit, Ausfallzeit, Aussetzer je Gerät). Die sechs
|
|
neuen Schlüssel sind in der Whitelist ergänzt — ohne sie stünde im PDF nur die
|
|
Ampel.
|
|
|
|
### Kleinigkeit
|
|
|
|
`netdiagDauerLesbar()`: „1 Tage 0 Std" → „1 Tag". `floor()` liefert in PHP einen
|
|
Float, und `1.0 === 1` ist false — die Einzahl hatte deshalb nie gegriffen.
|
|
|
|
## 1.1.0 — 2026-08-14
|
|
|
|
### Anmeldung läuft über das zentrale Auth-Modul (awlauth)
|
|
|
|
NetDiag war die letzte AWL-App mit eigenem Login: eigenes JWT, eigener Schlüssel
|
|
(`NETDIAG_API_JWT_SECRET`), eigene Gültigkeitsdauer, keine Möglichkeit, ein verlorenes
|
|
Handy gezielt abzumelden. Ab sofort stellt awlauth das Token aus — dasselbe Token,
|
|
derselbe Schlüssel und dieselbe Sitzungs-Registry wie bei den sechs Browser-Apps.
|
|
|
|
- `api/auth.php` prüft das Passwort über `awlauth_login()`. Damit greifen dort auch die
|
|
**Brute-Force-Bremse** (5 Fehlversuche je IP in 15 min, 10 je Benutzername in 30 min)
|
|
und die einheitliche, nicht-verräterische Fehlermeldung. Das Token kommt aus
|
|
`awlauth_issue_bearer()` und legt eine Sitzungszeile an — das Gerät erscheint als
|
|
„NetDiag-App · Android" in der awlauth-Geräteliste und ist dort einzeln abmeldbar.
|
|
- `netdiag_api_authenticate()` prüft zuerst das awlauth-Token. Ein **abgelaufenes oder
|
|
widerrufenes** Token führt sofort zu 401, auch wenn die Signatur noch stimmt.
|
|
- **Übergangsweise** wird ein bereits ausgestelltes altes netdiag-JWT weiterhin akzeptiert,
|
|
damit die Umstellung niemanden mitten im Einsatz aussperrt. Dieser Pfad entfällt, sobald
|
|
alle Geräte einmal neu angemeldet sind.
|
|
- Ohne aktives awlauth-Modul läuft NetDiag unverändert mit dem eigenen JWT weiter.
|
|
|
|
**Die Antwortform von `auth.php` ist bewusst unverändert** (`{token, expiresIn, user}`).
|
|
Bereits installierte APKs laufen nach einer **einmaligen Neuanmeldung** ohne Update weiter.
|
|
|
|
### CORS enger gefasst
|
|
|
|
`Access-Control-Allow-Origin: *` ist raus. Die API liefert Kundendaten aus; ein Wildcard
|
|
erlaubt jeder beliebigen Webseite, die Antwort auszulesen, sobald sie an ein Token kommt.
|
|
Erlaubt sind jetzt nur die App-Origins (`https://localhost`, `capacitor://localhost`,
|
|
`http://localhost`, `ionic://localhost`) und der Vite-Dev-Server; dazu `Vary: Origin`.
|
|
Anfragen ohne Origin-Header (nativer HTTP-Client, der APK-Downloader im Kotlin-Plugin,
|
|
curl) bekommen wie bisher eine Antwort — dort greift die Same-Origin-Policy ohnehin nicht.
|
|
|
|
## 1.0.0
|
|
|
|
- Erstversion
|
|
- Datenmodell: Protokoll, Gerät, Messung
|
|
- JSON-API: auth, customers, orders, protocols (Sync), pdf
|
|
- Tab "Netzwerk-Diagnose" an Kunde und Auftrag
|
|
- PDF-Protokoll-Generator + ECM-Ablage
|
|
- Backend: Protokoll-Liste und Detailansicht
|
|
- Admin: Token-Einstellung, QR-Code zum App-Download
|