M26+M27: Seriennummer bei Bekannte Router, Schlüsselbund-Trennung, terse-Fallback verallgemeinert
M26: SavedRouter bekommt ein optionales serialNumber-Feld. Zwei physisch verschiedene Router mit identischem Host+Benutzername (Werks-Adresse) blieben bisher ein gemeinsamer "Bekannte Router"- Eintrag; recordSuccessfulConnection matcht jetzt zusätzlich nach Seriennummer, mit sauberer Migration bestehender Einträge ohne Seriennummer. Drei neue Tests. M27, beim Live-Test von M26 gefunden: - Passwort-Anzeige-Button (Augen-Symbol) im Verbinden-Tab - Bug 35: KeychainService speicherte Passwörter nur nach "username@host" — beide Router teilten sich denselben Schlüsselbund-Eintrag trotz getrennter SavedRouter-Einträge. Fix: optionaler serialNumber-Parameter qualifiziert den Account-Key, mit Fallback auf den alten Key für bereits gespeicherte Passwörter. - Bug 36: neuer Router zeigte keine Routerboard-Infos/Seriennummer — derselbe Root Cause wie der zuvor gemeldete "Jetzt prüfen"-Fehler: /system routerboard und /system package update scheitern auf diesem Router mit "expected end of command" statt dem bisher einzig abgefangenen "bad parameter terse". SSHTransport.fetchMenuItems erkennt jetzt beide Formulierungen. Alles live bestätigt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+94
@@ -1517,6 +1517,96 @@ Nutzerwünsche in einer Runde):
|
||||
setzt die Adressfelder jetzt explizit statt sich auf Modell-Defaults
|
||||
zu verlassen). Live bestätigt ("gut soweit").
|
||||
|
||||
**M26: "Bekannte Router" hinterlegt jetzt die Seriennummer**
|
||||
(2026-09-16). Nutzer-Szenario, live so passiert: mit einem zweiten
|
||||
Router desselben Modells verbunden (Werks-Adresse+Zugangsdaten
|
||||
identisch zum bisherigen Testrouter, `192.168.88.1`/`admin`) — die App
|
||||
hat daraufhin den *bestehenden* "Bekannte Router"-Eintrag des alten
|
||||
Testrouters einfach für den neuen umbenannt (`SavedRoutersStore.
|
||||
recordSuccessfulConnection` matchte bisher nur auf Host+Benutzername,
|
||||
kein Feld unterschied zwei physisch verschiedene Geräte an derselben
|
||||
Werks-Adresse). Klick auf den alten Eintrag verband danach zwangsläufig
|
||||
mit dem tatsächlich erreichbaren Gerät (dem neuen Router), nicht mit
|
||||
dem gemeinten alten. Fix (Nutzervorschlag: "ist es nicht besser die
|
||||
Seriennummer des Gerätes mit zu hinterlegen?"): `SavedRouter` bekam ein
|
||||
neues optionales `serialNumber`-Feld (`/system routerboard`s
|
||||
"serial-number", bereits seit M14 als `RouterBoardInfo.serialNumber`
|
||||
ausgelesen — "unbekannt" wird dabei wie `nil` behandelt, sonst würden
|
||||
zwei Geräte ohne auslesbare Seriennummer fälschlich als "gleich"
|
||||
gelten). `recordSuccessfulConnection` matcht jetzt gestuft: exakte
|
||||
Seriennummer gewinnt zuerst; ein einzelner bestehender Eintrag ohne
|
||||
gespeicherte Seriennummer (alte, vor diesem Feld gespeicherte Einträge,
|
||||
oder Geräte ohne physisches Routerboard) wird beim nächsten Connect
|
||||
einmalig nachträglich damit befüllt statt dupliziert; alles andere legt
|
||||
einen neuen, getrennten Eintrag an. In `SavedRouterRow` als kleine
|
||||
"SN: ..."-Zeile sichtbar gemacht, damit zwei gleich benannte/adressierte
|
||||
Einträge auch optisch unterscheidbar sind. Drei neue Tests
|
||||
(`testDifferentSerialAtSameHostUsernameCreatesSeparateEntry`,
|
||||
`testLegacyEntryWithoutSerialGetsUpgradedInPlaceNotDuplicated`,
|
||||
`testSameSerialReconnectUpdatesRecencyNotDuplicated`). Migrationshinweis
|
||||
für den konkreten Fall: der bereits verschmolzene Bestandseintrag zeigt
|
||||
aktuell die Seriennummer des neuen Routers — der nächste Connect zum
|
||||
alten Testrouter legt automatisch einen neuen, eigenen Eintrag an (da
|
||||
dessen Seriennummer nicht mehr passt), bei Bedarf danach umbenennen.
|
||||
Live bestätigt ("passt, funktioniert") — allerdings dabei zwei weitere,
|
||||
eng verwandte Bugs gefunden, siehe M27 direkt danach.
|
||||
|
||||
**M27: Passwort-Anzeige-Button, Schlüsselbund-Trennung, `terse`-Fallback
|
||||
verallgemeinert** (2026-09-16, beim Live-Test von M26 gefunden):
|
||||
|
||||
1. **Passwort-Anzeige-Button** (Nutzerwunsch: "setze hinter das Passwort
|
||||
eine Auge-Symbol zum aufdecken des Passwortes, so kann ich prüfen, ob
|
||||
die Daten übernommen wurden") — Augen-Icon neben dem Passwortfeld im
|
||||
Verbinden-Tab, schaltet zwischen `SecureField` und `TextField` um.
|
||||
War das Diagnose-Werkzeug, das die beiden folgenden Bugs erst
|
||||
aufdeckte.
|
||||
2. **Bug 35: Schlüsselbund teilte sich einen Eintrag zwischen zwei
|
||||
Routern** — beim Umschalten zwischen zwei "Bekannte Router"-Einträgen
|
||||
(seit M26 korrekt als getrennte Einträge geführt) blieb das
|
||||
angezeigte Passwort trotzdem identisch. Aufwendig eingegrenzt: ein
|
||||
temporärer Debug-Print bestätigte zunächst, dass `ConnectViewModel`s
|
||||
`@Published`-Werte bei jedem Klick korrekt gesetzt wurden (auch die
|
||||
View selbst rendert nachweislich jedes Mal frisch, per zweitem
|
||||
Debug-Print in `mainContent` bestätigt) — zwei SwiftUI-`.id()`-
|
||||
Reparaturversuche (erst auf Section-, dann auf Feld-Ebene) liefen
|
||||
deshalb ins Leere, weil das eigentliche Problem gar keins der
|
||||
Anzeige war. Tatsächliche Ursache: `KeychainService` speichert
|
||||
Passwörter nur nach `"username@host"` — zwei physisch verschiedene
|
||||
Router mit identischem Host+Benutzername (Werks-Adresse) teilen sich
|
||||
dadurch denselben Schlüsselbund-Eintrag, unabhängig davon, dass
|
||||
`SavedRoutersStore` sie seit M26 bereits korrekt als getrennte
|
||||
Einträge führt. Fix: `KeychainService.save`/`loadPassword`/
|
||||
`deletePassword` bekommen einen optionalen `serialNumber`-Parameter,
|
||||
der den Account-Key auf `"username@host#seriennummer"` erweitert;
|
||||
`loadPassword` fällt auf den alten, unqualifizierten Key zurück,
|
||||
wenn kein qualifizierter Eintrag existiert (Rückwärtskompatibilität
|
||||
für vor diesem Fix gespeicherte Passwörter). `ConnectViewModel.
|
||||
connect()`s Passwort-Speicherung musste dafür hinter den
|
||||
erfolgreichen Verbindungsaufbau verschoben werden (die Seriennummer
|
||||
ist vorher noch nicht bekannt). Die beiden zuvor eingebauten
|
||||
`.id()`-Umwege wieder entfernt, da wirkungslos und irreführend
|
||||
(falsche Fehlerursache im Kommentar).
|
||||
3. **Bug 36, direkt danach beim selben Live-Test gefunden: neuer Router
|
||||
zeigte gar keine Routerboard-Infos, keine Seriennummer** — derselbe
|
||||
Root Cause wie der vorherige "Jetzt prüfen"-Fehler (`/system package
|
||||
update`, siehe oben): `/system routerboard print ... terse` schlägt
|
||||
auf diesem Router/dieser RouterOS-Version mit `"expected end of
|
||||
command (line 1 column N)"` fehl statt mit dem bisher einzig
|
||||
abgefangenen `"bad parameter terse"`. `fetchMenuItems`s
|
||||
Singleton-Fallback (Bug 8/20) griff deshalb nicht,
|
||||
`routerBoardInfo` blieb `nil` (best-effort, Fehler wurde still
|
||||
verschluckt) — betraf gleichzeitig die Seriennummer (M26) und die
|
||||
komplette Routerboard-Anzeige im Verbinden-Tab. Fix:
|
||||
`SSHTransport.fetchMenuItems`s Erkennung in eine neue
|
||||
`rejectsTerse(_:)`-Hilfsfunktion ausgelagert, die jetzt beide
|
||||
bekannten Formulierungen abfängt. Sicher eingegrenzt, da die
|
||||
geprüfte Fehlermeldung ausschließlich vom exakten Aufruf `"<menuPath>
|
||||
print without-paging terse"` stammt — jeder Parserfehler dort betrifft
|
||||
per Konstruktion das anhängende `"terse"`. Behebt nebenbei auch den
|
||||
"Jetzt prüfen"-Fehler von vorhin (`/system package update`), da
|
||||
beide über denselben Code-Pfad laufen. Live bestätigt
|
||||
("passt, funktioniert").
|
||||
|
||||
## Nächste Schritte
|
||||
|
||||
1. ~~M16: restliche `RouterOSSchemaCatalog.swift`-Sektionen übersetzen~~,
|
||||
@@ -1713,6 +1803,10 @@ Nutzerwünsche in einer Runde):
|
||||
dieses Symptom nochmal auftritt: zuerst per `defaults read` prüfen,
|
||||
ob der Trust wirklich gespeichert wurde, nicht nur der UI-Bestätigung
|
||||
vertrauen.
|
||||
14. ~~M26 (Seriennummer bei "Bekannte Router") noch live testen~~ —
|
||||
erledigt, siehe M27 oben (dabei zwei weitere Bugs gefunden und
|
||||
gefixt: geteilter Schlüsselbund-Eintrag, `/system routerboard`s
|
||||
`terse`-Ablehnung mit anderem Fehlertext als bisher erkannt).
|
||||
|
||||
Gitea-Remote `origin` ist eingerichtet und wird laufend gepusht (siehe
|
||||
oben) — dieser Hinweis war veraltet, korrigiert am 2026-09-15.
|
||||
|
||||
Reference in New Issue
Block a user