fix(wifi): Zugriffsschutz und AP-Daten beim Verlassen des Standalone-Modus

C1 (Merge-Blocker): Schaltet jemand den Standalone-Modus ab, waehrend keine
WLAN-Daten gespeichert sind, geht die Zustandsmaschine in den Onboarding-AP -
nl_wifi_sm_open_access() liefert dann true, obwohl der AP noch mit Name und
Passwort des Nutzers steht. Wer das AP-Passwort kennt, koennte system/settings
und system/command ohne Token benutzen: Token setzen, OTA anstossen,
Werksreset. Der Netz-Task reisst den AP in diesem Fall jetzt ausdruecklich ab
und baut ihn mit den Vorgabedaten neu auf - vor execute(ev) und nicht ueber die
Aktionsstruktur, weil execute() start_ap vor stop_ap ausfuehrt. Damit stimmt
auch die README-Zusage wieder, der AP heisse danach "ninlight-<mac4>".

I1: Der zweite Rueckfall nach drei abgelehnten tls_wifi_softap_create() setzte
ueber reset_ap_defaults() auch das Passwort auf das einkompilierte, das in der
README oeffentlich dokumentiert ist - eine Standalone-Lampe stuende dann mit
einem allgemein bekannten Passwort im Funkfeld, und sACN ist unauthentifiziert.
reset_ap_defaults() ist dafuer in reset_ap_identity() (Name und Kanal) und die
vollstaendige Rueckstellung aufgeteilt; der Rueckfall nimmt nur noch die
Identitaet. Kanal und SSID sind ohnehin die plausiblen Gruende, die
Passwortlaenge prueft die API selbst.

I2: destroy_ap() liess s_ap_live_ssid/-pass/-channel stehen. Nach dem Verlassen
des Standalone-Modus trugen diese Puffer weiter die Daten des Nutzers, und der
erste Rueckfallzweig holte sie Minuten spaeter zurueck - die Lampe pendelte
dann im 15-s-Takt zwischen Nutzerdaten und Vorgaben. Neu: forget_ap_live() in
beiden Abschaltwegen (clear_standalone und enabled:false), nicht in
destroy_ap() selbst, weil der Rueckfall auf zuletzt tragende Daten sonst auch
im Neuaufbau-Fall verlorenginge, fuer den er gedacht ist.

I3: s_ap_create_fails wurde nur bei Erfolg genullt und summierte damit ueber
verschiedene Datensaetze - nach einer Korrektur von Kanal 13 auf 6 loeste schon
ein einziger Fehlschlag den Rueckfall aus. Jetzt auch in destroy_ap() und bei
jedem neuen Wunsch aus MSG_STANDALONE.

Kleinigkeiten: nl_app_clear_standalone() wird auf seinen Rueckgabewert geprueft
und ein Schreibfehler protokolliert (sonst steht die Lampe im WLAN und nach dem
Neustart wieder im eigenen AP, ohne jede Spur). enabled:false auf einer Lampe,
die gar nicht standalone war, erzwingt keine Neuverbindung mehr, sondern tut
nichts und antwortet weiter mit 202.

Abnahmeliste: der Gerätebeleg für C1 als offener Punkt.
This commit is contained in:
Michael Sauer
2026-10-02 19:32:19 +02:00
parent 813d861cd1
commit ef321b37ef
2 changed files with 79 additions and 16 deletions
+1
View File
@@ -75,6 +75,7 @@ Für den echten Flottenbau `NINLIGHT_RECOVERY_PASSWORD` und `NINLIGHT_TOKEN` in
- [x] REST über den AP antwortet auf `192.168.4.1:3333` — 2026-10-02
- [ ] Startpuls als Sichtprüfung: läuft beim Start rund 5 s und gibt danach das normale Einschaltverhalten frei; mit `pulse: false` entfällt er ganz — *Logik ist hostgetestet, am Gerät hat noch niemand hingesehen*
- [ ] REST über den AP verlangt das Token (`GET system/settings` ohne Token → 401)
- [ ] `{"enabled":false}` **ohne** gespeicherte WLAN-Daten → der AP heißt danach wieder `ninlight-<mac4>` (nicht mehr wie vom Nutzer gesetzt), und der Tokenschutz passt zur AP-Umschaltung: solange der Nutzer-AP steht, gilt das Token; sobald der Vorgabe-AP steht, ist `system/settings` wie im Onboarding offen. Gerätebeleg für C1 — bis dahin nur hostseitig durchdacht
- [ ] WLAN eingeben, falsches Passwort → Gerät bleibt im eigenen AP mit eigenen Daten
- [ ] WLAN eingeben, richtiges Passwort → Gerät im Heimnetz, nach einem Neustart **nicht** wieder im AP
- [ ] Werksreset über 5× ein/aus → wieder unkonfigurierter Onboarding-AP