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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HReLXMbmPvtQ23p1iWiJNW
This commit is contained in:
Kay
2026-09-12 13:42:34 +02:00
co-authored by Claude Sonnet 5
parent 016f57f613
commit d715e21afb
+43 -20
View File
@@ -1,13 +1,16 @@
# RouterOS Assistant — Handoff
Stand: nach M4 (VLAN-Schritt), alle Milestones M1M4 gegen ein echtes
physisches Mikrotik-Testgerät (RouterOS 7.24.2) verifiziert.
Stand: nach M5 (WLAN-Schritt). M1M4 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/<id>` 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