From d715e21afb24813ee4604ade773f18d3e6884966 Mon Sep 17 00:00:00 2001 From: Kay Date: Sat, 12 Sep 2026 13:42:34 +0200 Subject: [PATCH] Handoff aktualisiert: M5-Stand, neues .set-Architekturprinzip Reflektiert den WLAN-Schritt, die erweiterte RouterOSCommand-Operation (.add/.set) und die noch fehlende Verifikation gegen echte WLAN-Hardware. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01HReLXMbmPvtQ23p1iWiJNW --- HANDOFF.md | 63 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/HANDOFF.md b/HANDOFF.md index 09dfcfe..577b00a 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -1,13 +1,16 @@ # RouterOS Assistant — Handoff -Stand: nach M4 (VLAN-Schritt), alle Milestones M1–M4 gegen ein echtes -physisches Mikrotik-Testgerät (RouterOS 7.24.2) verifiziert. +Stand: nach M5 (WLAN-Schritt). M1–M4 gegen ein echtes physisches +Mikrotik-Testgerät (RouterOS 7.24.2) verifiziert; M5 ist gebaut und +getestet (Build + Unit-Tests grün), aber noch **nicht gegen echte +WLAN-Hardware verifiziert** — unklar, ob das Testgerät überhaupt einen +WLAN-Chip hat. ## Ziel Native macOS-App (SwiftUI), die Laien per geführtem Interview-Wizard durch die häufigsten Mikrotik-RouterOS-Konfigurationen führt: Internet-Anschluss, -Heimnetzwerk/DHCP, zusätzliche VLAN-Netzwerke, (geplant: WLAN, Firewall). +Heimnetzwerk/DHCP, zusätzliche VLAN-Netzwerke, WLAN, (geplant: Firewall). Vollständiger Plan/Kontext: `~/.claude/plans/purrfect-puzzling-bunny.md` (ursprüngliche Architekturentscheidung — seither an mehreren Stellen weiterentwickelt, siehe unten). @@ -40,8 +43,8 @@ RouterOSAssistant/ App/RouterOSAssistantApp.swift — 3 Tabs, teilen sich EINE ConnectionService-Instanz Core/ Models/ - RouterOSCommand.swift — eine Änderung, zwei Renderer (CLI-Zeile / REST-JSON) - WanConfig.swift, LanDhcpConfig.swift, VlanEntry.swift — bauen je RouterOSCommand-Listen + RouterOSCommand.swift — eine Änderung, zwei Operationen (.add/.set), zwei Renderer (CLI-Zeile / REST-JSON) + WanConfig.swift, LanDhcpConfig.swift, VlanEntry.swift, WifiNetworkConfig.swift — bauen je RouterOSCommand-Listen DhcpServerCommandBuilder.swift — geteilte "Adresse+Pool+Server+Netzwerk"-Logik (LAN + VLAN) RouterOSModels.swift — Credentials, DeviceInfo, Interface, RouterOSError Networking/ @@ -56,16 +59,23 @@ RouterOSAssistant/ KeychainService.swift — Passwort-Speicherung Features/ Wizard/Steps/Connect/ — Verbinden-Tab - Wizard/Steps/Setup/ — Einrichten-Tab: Wan → Lan → Vlan → Review/Apply + Wizard/Steps/Setup/ — Einrichten-Tab: Wan → Lan → Vlan → Wifi → Review/Apply Backup/ — Sicherungen-Tab RouterOSAssistantTests/ — reine Unit-Tests (Command-Builder, CLI-Parser, Fallback-Logik via Mock-Transport) ``` -**Wichtiges Architekturprinzip:** `RouterOSCommand` unterstützt nur "add" -(CLI: `... add key=value ...`, REST: `POST`). Kein "set"/PATCH auf -bestehende Einträge — deshalb hat der VLAN-Schritt keine Port-Zuweisung -(Access/Trunk), das bräuchte RouterOS Bridge-VLAN-Filtering mit `set`. -Mit dem Nutzer abgestimmt, bewusste Scope-Entscheidung. +**Wichtiges Architekturprinzip (seit M5 erweitert):** `RouterOSCommand` +kennt zwei Operationen: `.add` (neuer Eintrag — CLI `... add key=value`, +REST `POST`) und `.set` (bestehenden Eintrag ändern, per `matchField`/ +`matchValue` gefunden — CLI `... set [find field=value] key=value` löst +das inline, REST muss dafür erst per GET das Item suchen, seine +RouterOS-interne `.id` auslesen, dann `PATCH restPath/` schicken, +siehe `RestTransport.findItemID`). Eingeführt für M5 (WLAN), weil +Wireless-Interfaces schon vor jeder Konfiguration existieren — kein +"add" möglich. VLAN (M4) hat trotzdem weiterhin keine Port-Zuweisung +(Access/Trunk): das bräuchte zusätzlich RouterOS Bridge-VLAN-Filtering, +technisch jetzt machbar, aber bewusst nicht rückwirkend nachgezogen +(Scope-Entscheidung, nicht mehr Architektur-Zwang). **ConnectionService ist der einzige geteilte State.** Alle drei Tabs bekommen dieselbe Instanz von der App-Ebene injiziert (kein @@ -120,11 +130,22 @@ selbst separat als `@ObservedObject` halten. - **Kein garantiertes Auto-Rollback** bei Verbindungsabbruch während "Jetzt anwenden" — nur Backup-vorher + Bestätigungspflicht. Steht auch im UI-Text auf dem Übersichtsschritt. -- **VLAN ohne Port-Zuweisung** (siehe oben, Architekturprinzip). +- **VLAN ohne Port-Zuweisung** (siehe oben, Architekturprinzip) — bewusste + Scope-Entscheidung, nicht mehr technisch erzwungen. - **REST-Pfad ungetestet für Schreibvorgänge** — beim Testgerät ist `www-ssl` (Port 443) aus, daher lief jeder bisherige Schreibtest über - SSH. Der REST-`apply()`-Pfad (`POST` mit JSON-Body) ist nur gegen Mocks - getestet, nicht gegen ein echtes Gerät mit aktiver REST-API. + SSH. Der REST-`apply()`-Pfad (`POST`/`PATCH` mit JSON-Body, + `findItemID` für `.set`) ist nur gegen Mocks getestet, nicht gegen ein + echtes Gerät mit aktiver REST-API. +- **WLAN-Schritt (M5) komplett ungetestet gegen echte Hardware** — nur + Build+Unit-Tests grün. Unklar ob das Testgerät WLAN hat. Vor Vertrauen + in diesen Schritt unbedingt gegen ein Gerät mit WLAN-Chip testen — + sowohl den Legacy-`/interface wireless`-Pfad als auch die Erkennung + von `wifi`-typisierten (neuerer Treiber, nicht unterstützt) Interfaces. +- **Neuer RouterOS-WiFi-Treiber (`/interface wifi`, wifiwave2/802.11ax) + nicht unterstützt** — wird erkannt und im UI erklärt, aber nicht + konfiguriert. Eigener Umbau nötig (andere Menüstruktur), falls + gebraucht. ## Stand der Milestones @@ -132,18 +153,20 @@ selbst separat als `@ObservedObject` halten. - ✅ M2: Backup-Service, Sicherungen-Tab - ✅ M3: WAN + LAN/DHCP-Wizard, Anwenden-Logik mit Vorab-Backup - ✅ M4: VLAN-Schritt (separates virtuelles Netz, kein Port-Tagging) -- ⬜ M5: WLAN-Schritt (SSID/Passwort, nur bei erkannter WLAN-Hardware) +- ✅ M5: WLAN-Schritt (SSID/Passwort, echte `.set`-Operation im Befehlsmodell, + nur bei erkanntem Legacy-Wireless; neuer WiFi-Treiber erkannt aber nicht + unterstützt) — **gebaut, aber noch nicht gegen echte WLAN-Hardware getestet** - ⬜ M6: Firewall-Schritt (sicherer Standard: NAT/Masquerade, WAN→LAN blocken) - ⬜ M7: Härtung — SSH-Hostkey-TOFU, Fehlerzustände, Politur, ggf. REST-Schreibpfad gegen echtes Gerät mit aktivem `www-ssl` verifizieren ## Nächste Schritte -M5 (WLAN) oder M6 (Firewall) als Nächstes — Nutzer hat noch nicht -festgelegt, was zuerst kommt. Vor Firewall-Arbeit besonders vorsichtig -sein: falsch gesetzte Regeln können den Fernzugriff auf den Router kappen, -unbedingt Backup-Pflicht vor Anwenden beibehalten und im Testgerät bleiben, -nicht am Produktivrouter. +Zuerst M5 gegen ein Gerät mit echtem WLAN-Chip testen, sobald verfügbar. +Danach M6 (Firewall) — dort besonders vorsichtig sein: falsch gesetzte +Regeln können den Fernzugriff auf den Router kappen, unbedingt +Backup-Pflicht vor Anwenden beibehalten und im Testgerät bleiben, nicht +am Produktivrouter. Kein Gitea-Remote vorhanden — falls der Nutzer später eine Gitea-Instanz aufsetzt (z.B. selbst gehostet auf der vorhandenen OMV-NAS, wo bereits