Handoff: M6-Stand + Gatekeeper-Testrunner-Hang dokumentiert

Neuer Abschnitt erklärt den xcodebuild-test-Hang (amfid/syspolicyd
Gatekeeper-Netzwerk-Check bei ad-hoc-signierten Binaries) als
Tooling-Eigenheit, nicht Code-Bug, und wie man ihn umgeht
(build-for-testing zum Compile-Check, echte Verifikation über Xcode).

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 19:58:55 +02:00
co-authored by Claude Sonnet 5
parent 772549c991
commit da5133245e
+40 -15
View File
@@ -1,12 +1,13 @@
# RouterOS Assistant — Handoff
Stand: nach M5 (WLAN-Schritt). M1M4 gegen ein echtes physisches
Mikrotik-Testgerät (RouterOS 7.24.2) verifiziert. M5: der
"kein-WLAN-erkannt"-Zweig ist gegen das echte Testgerät bestätigt (Gerät
hat keinen WLAN-Chip, wurde korrekt erkannt, Konfiguration lief sauber
durch ohne WLAN-Befehle). Der eigentliche SSID/Passwort-`.set`-Pfad
(Sicherheitsprofil anlegen + Interface konfigurieren) ist **weiterhin
ungetestet** — dafür fehlt ein Gerät mit echtem WLAN-Chip.
Stand: nach M6 (Firewall-Schritt). M1M4 gegen ein echtes physisches
Mikrotik-Testgerät (RouterOS 7.24.2) verifiziert. M5: nur der
"kein-WLAN-erkannt"-Zweig ist bestätigt (siehe Einschränkungen unten). M6
ist gebaut, Build + Test-Compile grün, aber **noch nicht gegen echte
Hardware angewendet** — der Nutzer verifiziert diesen Schritt direkt in
Xcode (Cmd+R), da `xcodebuild test` von der Kommandozeile aktuell an
einem macOS-Gatekeeper-Netzwerk-Check hängt (siehe eigener Abschnitt
unten, kein Code-Bug).
## Ziel
@@ -46,7 +47,7 @@ RouterOSAssistant/
Core/
Models/
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
WanConfig.swift, LanDhcpConfig.swift, VlanEntry.swift, WifiNetworkConfig.swift, FirewallConfig.swift — bauen je RouterOSCommand-Listen
DhcpServerCommandBuilder.swift — geteilte "Adresse+Pool+Server+Netzwerk"-Logik (LAN + VLAN)
RouterOSModels.swift — Credentials, DeviceInfo, Interface, RouterOSError
Networking/
@@ -61,7 +62,7 @@ RouterOSAssistant/
KeychainService.swift — Passwort-Speicherung
Features/
Wizard/Steps/Connect/ — Verbinden-Tab
Wizard/Steps/Setup/ — Einrichten-Tab: Wan → Lan → Vlan → Wifi → Review/Apply
Wizard/Steps/Setup/ — Einrichten-Tab: Wan → Lan → Vlan → Wifi → Firewall → Review/Apply
Backup/ — Sicherungen-Tab
RouterOSAssistantTests/ — reine Unit-Tests (Command-Builder, CLI-Parser, Fallback-Logik via Mock-Transport)
```
@@ -122,6 +123,27 @@ eigener Commit (`git log` zeigt Details):
neue View, die ein ObservableObject aus einem ViewModel liest, muss es
selbst separat als `@ObservedObject` halten.
## `xcodebuild test` hängt — Gatekeeper, kein Code-Bug
Bei M6 hing `xcodebuild ... test` dreimal reproduzierbar exakt beim
App-Start für ~5 Minuten, dann `"The test runner hung before establishing
connection."`. Ursache laut `log show` (Filter auf `RouterOSAssistant`/
`syspolicyd`/`amfid`): `amfid` markiert das ad-hoc-signierte Binary als
"signed by an unknown certificate chain", `syspolicyd` macht daraufhin
einen `GK performScan` mit einer echten Netzwerkverbindung zu Apples
Gatekeeper-Servern — normalerweise sehr schnell, an diesem Tag aber
hängend/langsam. Jeder Neu-Build ändert den Binary-Hash, jeder Hash
braucht (in der Theorie) einen neuen Check.
Betrifft nur den CLI-Weg (`xcodebuild test`, wodurch die App ohne
Debugger startet). Xcodes eigener Cmd+R-Weg ist davon nicht betroffen
(Debugger-gestützter Start bekommt von Xcode eine Gatekeeper-Ausnahme).
**Deshalb:** bei hartnäckigen `xcodebuild test`-Hängern erst
`xcodebuild ... build-for-testing` probieren (kompiliert nur, startet die
App nicht, kein Gatekeeper-Trigger) um Compile-Fehler auszuschließen,
und den eigentlichen Testlauf/die manuelle Verifikation dem Nutzer über
Xcode überlassen statt CLI-Versuche zu wiederholen.
## Bekannte Einschränkungen (bewusst, nicht vergessen)
- **SSH-Hostkey-TOFU fehlt** — `SSHTransport` nutzt `.acceptAnything()`,
@@ -161,17 +183,20 @@ selbst separat als `@ObservedObject` halten.
unterstützt) — "kein WLAN"-Zweig gegen echtes Gerät bestätigt, der
eigentliche SSID/Passwort-`.set`-Pfad **weiterhin ungetestet** (kein
WLAN-Chip am Testgerät)
- M6: Firewall-Schritt (sicherer Standard: NAT/Masquerade, WAN→LAN blocken)
- M6: Firewall-Schritt (opt-in, Standard aus; NAT/Masquerade + sicherer
Filter-Standard mit `place-before`-Sortierung; zeigt vorhandene
Regelanzahl vor dem Anwenden) — **gebaut, noch nicht gegen echte
Hardware angewendet**, Nutzer verifiziert selbst über Xcode
- ⬜ M7: Härtung — SSH-Hostkey-TOFU, Fehlerzustände, Politur, ggf. REST-Schreibpfad
gegen echtes Gerät mit aktivem `www-ssl` verifizieren
## Nächste Schritte
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.
M6 (Firewall) am Testgerät (Ersatzgerät, nicht Produktiv-Router)
anwenden und danach die Regel-Reihenfolge prüfen (`/ip firewall filter
print`, `/ip firewall nat print`) — das ist der bisher riskanteste
Schritt und noch nie live gelaufen. Danach M5 (WLAN) nachholen, sobald
ein Gerät mit echtem WLAN-Chip verfügbar ist. Dann M7.
Kein Gitea-Remote vorhanden — falls der Nutzer später eine Gitea-Instanz
aufsetzt (z.B. selbst gehostet auf der vorhandenen OMV-NAS, wo bereits