diff --git a/docs/cf-tunnel-mapping.md b/docs/cf-tunnel-mapping.md index 5fd6c3f..9f5e4ca 100644 --- a/docs/cf-tunnel-mapping.md +++ b/docs/cf-tunnel-mapping.md @@ -346,3 +346,58 @@ Letzte in §9.2/§8 als „bleibt `.41`" geführte Origin-Klasse (`pve .41.100`, - vnet-Route `5546dcb6…` von `bf-pve` auf den Mesh-Tunnel umhängen (Rollback = PATCH zurück; bf-pve bleibt Fallback). - Team-Domain gemessen: `emsenhuber.cloudflareaccess.com` → Node-Identität `warp_connector@emsenhuber.cloudflareaccess.com`. Noch kein `warp_connector`-Tunnel im Account. - Governance „Config nur via Nautobot" (TP21): CRS326-WG-Zeilen regulär via Golden Config, sobald das Device dort adoptiert ist — die alte ap1-Ausnahme gilt hierfür **nicht**. + +## 15. Incident 2026-07-21 → ✅ GEFIXT 2026-08-24 — macmini-Connectoren gestoppt, HA fünf Wochen degradiert + +**Symptom (erhoben 2026-08-16, gefixt 2026-08-24):** `bf-nas` und `bf-pve` liefen auf **je einem** +Connector statt zwei. Kein `530`, kein Round-Robin — reiner **Redundanzverlust**: die Dienste hinter +diesen Tunneln hingen an einem einzigen cloudflared-Prozess. + +**Ursache — nicht das erwartete QUIC-Flap.** Die beiden macmini-Container standen auf +`Exited (0)`, `finishedAt` **beide auf `2026-07-21T13:00:53`** (gleiche Sekunde, Exit 0, +`restart=unless-stopped`, `TUNNEL_TRANSPORT_PROTOCOL=http2` korrekt gesetzt). Ein Absturz sieht anders +aus: gleiche Sekunde + Exit 0 + kein Neustart trotz `unless-stopped` = **ein `docker stop` bzw. +`compose down` auf genau diese zwei**. Die übrigen macmini-Container liefen die ganze Zeit, der Daemon +ist seither auch neu gestartet — Docker hat die zwei also als „vom Benutzer gestoppt" geführt. +⇒ **Die Datierung in TP16 war falsch: degradiert seit 2026-07-21, nicht seit dem 08-16.** Der 08-16 war +nur der Tag, an dem es *aufgefallen* ist. Zwischen Eintritt und Entdeckung lagen **vier Wochen**. + +**Fix:** `docker start cloudflared-bfnas cloudflared-bfpve` auf dem macmini. Sonst nichts — +Tokens, Transport und Restart-Policy waren korrekt. + +**Abnahme (2026-08-24):** +- CF-API: `bf-mm` / `bf-nas` / `bf-pve` je **2 Connectoren / 8 conns**, alle `healthy`. +- Connector-Log: `Registered tunnel connection … protocol=http2` (Konvention aus §13 gehalten). +- **Smoke-Test gegen das Round-Robin-Muster: 6 FQDNs über beide betroffenen Tunnel + (`gitea`/`nautobot`/`grafana` = bf-nas, `portainer`/`hass`/`vw` = bf-pve), je 6 Läufe = 36 Anfragen, + `530er = 0`.** Das reziproke Design hält: macmini hostet weder NAS- noch pve-Origins, die + macvlan-Host-Isolation aus §9 kann dort also nicht zuschlagen. + +🔴 **Die eigentliche Lehre ist nicht der Fix, sondern die Nachweislücke.** Ein Tunnel mit einem von +zwei Connectoren meldet `healthy` — die Degradation ist über den Tunnel-Status **nicht sichtbar**, nur +über die **Connector-Anzahl**. Genau deshalb blieb sie vier Wochen unbemerkt und wurde beim +Doku-Aufräumen zufällig gefunden. **Ein HA-Design ohne Zähler auf die Redundanz ist kein HA-Design.** +⇒ Gehört als Check nach **TP11** (Monitoring): `connectoren < 2` je bf-Tunnel = Alarm. + +### Korrektur: die vier toten Alt-Tunnel sind harmloser als notiert +Stand 2026-08-24, live erhoben: `openclaw`, `coolify`, `johnny2`, `TeilzeitCharlie` sind `down`, +0 Connectoren. Ihre **Ingress-Configs beanspruchen weiterhin Hostnames** — `openclaw` unter anderem +`n8n.emsenhuber.net` → `10.40.41.147:5678` (toter VLAN1-Origin), dazu `oc`, `dashboard`, `drawio`; +`coolify` → `10.40.41.133`; `johnny2` → `jc`; `TeilzeitCharlie` → `charlie`. + +🔵 **Aber: kein einziger CNAME zeigt auf einen dieser vier Tunnel.** Alle 23 Tunnel-CNAMEs der Zone +zeigen auf `bf-mm`/`bf-nas`/`bf-pve`/`fm`/`terpene-db`; **`n8n.emsenhuber.net` zeigt korrekt auf +`bf-mm`**. ⇒ Die in TP16 notierte Sorge, ein wiederbelebter `openclaw` würde „exakt das alte +Round-Robin-Muster auf diesem Hostname" erzeugen, ist **so nicht richtig**: **welcher Tunnel einen +Hostname bedient, entscheidet das DNS**, nicht die Ingress-Config. Ein hochkommender `openclaw` wäre +inert, solange niemand `cloudflared tunnel route dns` dafür ausführt (was den CNAME umschreiben +*würde* — das ist der reale, aber aktive Angriffspfad). Das Round-Robin aus §9 war ein Problem +**mehrerer Connectoren auf EINEM Tunnel**, nicht mehrerer Tunnel auf einem Namen. +⇒ **Löschen bleibt richtig — als Hygiene und um die `route dns`-Falle zu entfernen, nicht als +Störungsbehebung.** Weiterhin user-gated (Löschen ist nicht umkehrbar). + +📌 **Doku-Drift mitkorrigiert:** §10 führt `bf-nas` als `70d6a4cf`; live ist die Tunnel-ID +**`220c9958`** (Tunnel am 2026-07-12 neu angelegt, s. §11). §10 gilt sonst unverändert. + +ℹ️ **Nicht Teil des BF-HA-Designs** (und daher kein Defekt, obwohl sie 1 Connector haben): +`fm.emsenhuber.net` (Standort FM) und `terpene-db` (eigenes Projekt). diff --git a/docs/teilprojekte.md b/docs/teilprojekte.md index 2a4701d..00913e3 100644 --- a/docs/teilprojekte.md +++ b/docs/teilprojekte.md @@ -278,12 +278,30 @@ nachmessen und dann entscheiden**. Blocker gibt es keine mehr. TP5 ist in der Na erneut rotieren. Abnahme = ein Aufruf **mit** den Headern (antwortet) **und** einer **ohne** (403) — der Erfolgsfall allein beweist nichts, der Hostname könnte auf `bypass` stehen. -### TP16 — CF-Tunnel: Round-Robin killen + reziprokes HA ▸ ✅ KERN UMGESETZT (2026-07-10) — ⚠️ **HA aktuell degradiert (Live-Befund 2026-08-16)** — `docs/cf-tunnel-mapping.md §10`, #1033 -- 🟠 **BEFUND 2026-08-16 (beim Doku-Aufräumen live über die CF-API erhoben, kein Eingriff): das reziproke HA läuft nur noch auf einem von drei Tunneln.** +### TP16 — CF-Tunnel: Round-Robin killen + reziprokes HA ▸ ✅ **HA WIEDER VOLL (2026-08-24)** — Kern 2026-07-10 — `docs/cf-tunnel-mapping.md §10 + §15`, #1033 +- ✅ **GEFIXT 2026-08-24 — Ursache war ein `docker stop`, kein QUIC-Flap.** Die beiden macmini-Connectoren + (`cloudflared-bfnas`, `cloudflared-bfpve`) standen auf `Exited (0)`, **beide `finishedAt` auf derselben + Sekunde `2026-07-21T13:00:53`**, bei korrekt gesetztem `restart=unless-stopped` und `http2`. Fix = + `docker start` der zwei, sonst nichts. **Abnahme: alle drei bf-Tunnel je 2 Connectoren / 8 conns, + und 36 Anfragen über 6 FQDNs beider betroffener Tunnel mit `530er = 0`.** Details `§15`. + - 🔴 **Die Datierung im Befund unten war falsch:** degradiert **seit 2026-07-21**, nicht seit dem 08-16 — + der 08-16 war der Tag der *Entdeckung*. **Vier Wochen unbemerkt.** + - 🔴 **Die eigentliche Lehre ist die Nachweislücke:** ein Tunnel mit 1 von 2 Connectoren meldet + `healthy`. Über den Tunnel-Status ist die Degradation **unsichtbar**, nur die **Connector-Anzahl** + zeigt sie. ⇒ Check nach **TP11**: `connectoren < 2` je bf-Tunnel = Alarm. **Ein HA-Design ohne + Zähler auf die Redundanz ist kein HA-Design.** +- 📜 **Ursprünglicher Befund 2026-08-16 (Historie, Ursache s.o.):** - `bf-mm` = **2 Connectoren** (je 4 conns) ✅ · `bf-nas` = **1 Connector** (3 conns) 🟠 · `bf-pve` = **1 Connector** (4 conns) 🟠. - **Bedeutung:** die Dienste hinter `bf-nas` (gitea, grafana, pve-mcp, **vw**, ds-bf, nautobot) und `bf-pve` (pve, ccu, iobroker, z2m25, portainer, **hass**, ha-mcp) hängen jeweils an **einem einzigen** cloudflared-Prozess. Fällt dessen Host aus, sind sie weg — genau der Zustand, den TP16 beseitigt hat. **Kein `530`/Round-Robin-Problem** (das bleibt strukturell gelöst), sondern **Redundanzverlust**. - - **Bekanntes Muster:** identisch zum Incident vom 2026-07-16 (macmini-Connectoren flappten unter QUIC → Fix `TUNNEL_TRANSPORT_PROTOCOL=http2`). Diesmal sind die *macmini*-Connectoren oben (bf-mm hat 2), es fehlt je **ein** Gegenstück auf NAS/pve. **Nächster Schritt (eigene Session):** auf NAS und pve nachsehen, welcher der beiden cloudflared-Container nicht läuft, und ob es der `http2`-Konventionsfall ist. -- 🧹 **Nebenbefund beim selben Sweep — Alt-Tunnel mit VLAN1-Origins (alle `down`, 0 Connectoren, daher aktuell harmlos):** `openclaw` (→ `10.40.41.147/.148/.139`), `coolify` (→ `10.40.41.133`), `johnny2`, `TeilzeitCharlie`. ⚠️ **`openclaw` beansprucht `n8n.emsenhuber.net`, das produktiv auf `bf-mm` läuft** — käme der Tunnel je wieder hoch, entstünde exakt das alte Round-Robin-Muster auf diesem Hostname. **Empfehlung: die vier toten Tunnel löschen** (user-gated, Löschen ist nicht umkehrbar) — gehört fachlich zu **TP19** (VLAN1-Retirement: `.41.133` war eines der „unidentifizierten VLAN1-Geräte" aus TP19 B1.2 — hiermit als coolify-Origin identifiziert). + - ~~**Bekanntes Muster:** identisch zum Incident vom 2026-07-16~~ 🔴 **war es NICHT** — s. Fix oben. Ursprungstext: + **Bekanntes Muster:** identisch zum Incident vom 2026-07-16 (macmini-Connectoren flappten unter QUIC → Fix `TUNNEL_TRANSPORT_PROTOCOL=http2`). Diesmal sind die *macmini*-Connectoren oben (bf-mm hat 2), es fehlt je **ein** Gegenstück auf NAS/pve. **Nächster Schritt (eigene Session):** auf NAS und pve nachsehen, welcher der beiden cloudflared-Container nicht läuft, und ob es der `http2`-Konventionsfall ist. +- 🧹 **Nebenbefund beim selben Sweep — Alt-Tunnel mit VLAN1-Origins (alle `down`, 0 Connectoren, daher aktuell harmlos):** `openclaw` (→ `10.40.41.147/.148/.139`), `coolify` (→ `10.40.41.133`), `johnny2`, `TeilzeitCharlie`. ⚠️ **`openclaw` beansprucht `n8n.emsenhuber.net`, das produktiv auf `bf-mm` läuft** — käme der Tunnel je wieder hoch, entstünde exakt das alte Round-Robin-Muster auf diesem Hostname. **Empfehlung: die vier toten Tunnel löschen** (user-gated, Löschen ist nicht umkehrbar) + 🔵 **Begründung korrigiert 2026-08-24:** die Sorge „käme der Tunnel wieder hoch, entstünde das alte + Round-Robin auf diesem Hostname" ist **so nicht richtig** — **welcher Tunnel einen Hostname bedient, + entscheidet das DNS**, und live zeigt **kein einziger CNAME** auf die vier (`n8n` zeigt korrekt auf + `bf-mm`). Ein hochkommender `openclaw` wäre inert. Der reale Pfad ist ein *aktives* + `cloudflared tunnel route dns`, das den CNAME umschreibt. ⇒ **Löschen bleibt richtig — als Hygiene + und um genau diese Falle zu entfernen, nicht als Störungsbehebung.** — gehört fachlich zu **TP19** (VLAN1-Retirement: `.41.133` war eines der „unidentifizierten VLAN1-Geräte" aus TP19 B1.2 — hiermit als coolify-Origin identifiziert). > **✅ Umgesetzt (2026-07-10, eigene Session):** reziprokes **3-Tunnel-HA** live (bf-nas `70d6a4cf` / bf-pve `f7fdf3a6` / bf-mm `7a322261`), 6 Connectoren (2/Host, je Fremdhost), 19 FQDNs Loop-Smoke **0×530**, HA per Host-Ausfall-Sim bewiesen. Round-Robin-#1033 **strukturell weg**. As-Built = `docs/cf-tunnel-mapping.md §10`. **Schritt 5 Access-Strang: ~~`vw` bypass→geschützt via WARP~~ — 🔴 GESTRICHEN (User-Constraint 2026-08-14, s. TP16.2). Verbleibend offen: `hass`/`ha-mcp` 400/403; `gateway-dw` (WG→404) klären.** - **Symptom (User):** FQDNs über CF werden **sporadisch / „sehr unsicher"** aufgelöst = #1033-Muster zurück („jeden 3. Schuss eine Niete"). User hat alle 3 cloudflared-Images + Container aktualisiert/neu gestartet. - **✅ Root-Cause endgültig (User-Diagnose bestätigt): macvlan/ipvlan-Host-Isolation.** Ein cloudflared-Connector ist **blind für macvlan/ipvlan-Container auf seinem EIGENEN Host** (Linux-Kernel-Regel), erreicht aber Fremdhost-L2 + co-lokierte Bridge-Container. Mehrere Connectoren auf EINEM Tunnel = geteilter Ingress + CF-**Round-Robin** → jede Origin, die auf dem Host *eines* Connectors liegt, fällt bei ~**1/N** aus. **Strukturell**, nicht durch „Origins fixen" heilbar. Bsp: `omada .20.175`/`pve-mcp .20.173`/`gitea .20.157`/`grafana .20.109` = NAS-macvlan → vom NAS-Connector NICHT erreichbar. @@ -533,12 +551,6 @@ nachmessen und dann entscheiden**. Blocker gibt es keine mehr. TP5 ist in der Na -### TP17.2 — einheitliches Geräte-Passwort (Shelly `SetAuth`) ▸ ➡️ **NACH [TP30](#tp30) VERSCHOBEN (2026-08-24)** -> **User-Entscheid:** TP30 ist das Sammelbecken für Credentials, die neu gesetzt oder rotiert werden -> müssen — TP17.2 ist genau das (Erstvergabe) und teilt sich mit der PSK-Rotation den Geräte-Durchgang. -> Der vollständige Text steht dort als **Posten #3**. Diese Zeile bleibt nur, damit die Nummer nicht -> ins Leere zeigt; **TP17.2 ist kein eigenes TP mehr.** - ### TP17.3 — Shelly-Regression nach der VLAN30-Migration ▸ ✅ **ERLEDIGT (2026-08-23, Folge-Session): beide Geräte repariert, Ursache `eco_mode` bewiesen** — offen nur noch der Flotten-Entscheid (gehört TP17.1) — aus TP17 herausgelöst, User-Meldung > **User-Meldung 2026-08-23:** „vor einiger zeit hast du an den shellys änderungen vorgenommen. das > hatte bei einigen einen bösen seiteneffekt: **lüfter-shelly musste ich doppelt drücken**. der übelste @@ -815,11 +827,49 @@ begründet** — er kaufte Redundanz, keine Abdeckung. Das ist eine andere Frage (c) das Gerät selbst mit 5-min-Duty-Cycle → dann bleibt es unverändert. 🚫 **Nicht die alte Power-Save-Merkregel wiederbeleben** — die ist am 2026-08-13 als Fehldiagnose zurückgezogen (`ref_wifi_powersave_multicast`). -2. ⚖️ **Entscheidung 5 GHz auf 20 MHz** (statt heute 20/40): **+3 dB Link-Budget**, für einen - 1,2-Mbit-Call an Durchsatz irrelevant. Ein-Wort-Change im Template. Steht seit dem Terrassen-Fix - ohne Dringlichkeit da — **Christophs Entscheidung**, keine Empfehlung mehr. +2. ⚖️ **Entscheidung 5 GHz auf 20 MHz** (statt heute 20/40) — **✅ 5-GHz-Umfeldscan durchgeführt + 2026-08-24, Empfehlung: NICHT verschmälern, Entscheidung an einen Auslöser hängen.** ⚠️ **2,4 GHz NICHT vorschnell drosseln** — dort hängen ~20 IoT-Geräte. + **Messung** (`/interface wifi scan` **am Manager**, cap-wifi3 = ap1 / cap-wifi1 = ap2, 10–12 s): + + | vom Radio auf | fremdes 5-GHz-Netz | Kanal | Signal | Abstand zum eigenen AP | + |---|---|---|---|---| + | **ap1** (5180/Ce) | `Drei_H288A_5G_acHG` | 5745/ac/**80 MHz** | **−86 dBm** | 19 dB darunter | + | **ap2** (5220/Ce) | `LiwestBB93-5G` | 5200/ac/**80 MHz** (Block 5180–5240) | **−89 dBm** | 24 dB darunter | + + ⇒ **Das 5-GHz-Band ist an beiden Standorten praktisch leer.** Genau **ein** Fremdnetz je AP, beide + rund 20 dB unter dem eigenen Pegel. Der Nachbar `LiwestBB93-5G` liegt mit 80 MHz zwar formal über + **beiden** unserer Blöcke — bei −89 dBm ist das ohne Wirkung. + + 🎯 **Warum das gegen 20 MHz spricht — die zwei üblichen Gründe treffen hier nicht zu:** + - **Fremdinterferenz:** existiert nicht (−86/−89). Ein schmalerer Kanal hätte nichts abzuwehren. + - **Selbstüberlappung:** existiert nicht. ap1 `5180/Ce` = ch36+40, ap2 `5220/Ce` = ch44+48 — + überlappungsfrei (Fund C, 08-17). + - **Bleibt allein das +3 dB Link-Budget** — und das ist zum guten Teil **schon vorhanden**: in einem + 40-MHz-BSS sendet die Ratenanpassung an schwache Clients ohnehin auf dem Primärkanal in 20 MHz. + Den Ceiling zahlen aber **alle** Clients dauerhaft. **Der Nutzen geht an die, die ihn schon haben.** + - **Und es löst das gemessene Problem nicht:** die offenen Schwachstellen sind die + Redundanz-Lücken (Schlafzimmer −84,6 / 38 %, Bad −82,3 / 24 %) **am Gegen-AP**. +3 dB macht aus + 38 % Verlust keine 0 % — das ist eine Platzierungs-/AP-Zahl-Frage, keine Kanalbreiten-Frage. + + 🔑 **Der echte Auslöser ist die AP-Zahl, nicht die Interferenz** — und das ist der Grund, die + Entscheidung *jetzt* zu treffen statt sie offenzulassen. Beide Kanäle stehen hart in **Band A** + (`ch-5g-ap1`=5180, `ch-5g-ap2`=5220, kein `skip-dfs-channels`), und Band A hat unter ETSI genau + **4 × 20 MHz = 2 × 40 MHz**. Mit zwei APs ist es damit **exakt aufgebraucht**: + + | Szenario | bei 40 MHz | bei 20 MHz | + |---|---|---| + | 2 APs (heute) | ✅ passt genau, überlappungsfrei | ✅ passt, +3 dB, halber Ceiling | + | **3.–4. AP** | ❌ Band A voll ⇒ **nur mit DFS** (Band B ch52–64: Radar-Events, 60 s CAC) | ✅ 4 saubere Kanäle, **kein DFS** | + + ⇒ **Empfehlung: 20/40 MHz beibehalten.** Die Verschmälerung ist heute ein Preis ohne Gegenwert. + Sie wird **fällig, sobald ein dritter AP dazukommt** — dann lautet die Wahl nicht mehr „20 gegen 40", + sondern **„20 MHz flottenweit" gegen „DFS akzeptieren"**, und dafür ist 20 MHz die ruhigere Antwort. + Ein Zwischenweg existiert (ap1 behält 40 MHz, AP 2+3 fahren 20 MHz auf 5220/5240) und braucht + ebenfalls kein DFS. + 📌 **Damit ist dieser Punkt entscheidungsreif und an einen Auslöser gebunden statt offen.** + **Fund E (`signal-range`-Boden am Manager) — abgestuft, NICHT umsetzen.** Der Sticky-Client vom 08-20 reproduzierte sich am 08-22 nicht (Treppe: sauberer Wechsel ap2→ap1, 0 % über 57 s). Und auf der Terrasse würde ein Boden **schaden**, weil es dort keinen besseren AP gibt, auf den gesteuert werden @@ -844,7 +894,12 @@ Kanalarbeit **Breite VOR Frequenz** ändern, sonst erzeugt man auf dem Weg eine ⚠️ `steering=`/Channel-Änderungen **re-applien alle VAPs und werfen jeden Client kurz raus** — nicht während eines Calls deployen, `/system backup` je AP vorher. -🔬 **Messwerkzeug — drei Regeln, jede aus einem Fehlbefund geboren:** +🔬 **Messwerkzeug — vier Regeln, jede aus einem Fehlbefund geboren:** +- 🔴 **Für einen Kanal-/Umfeldscan NICHT `list_wifi_interfaces` benutzen** (Fund 2026-08-24): das Tool + gibt `security.passphrase` **aller** Profile im Klartext aus — ein Read für die Kanalbreite hat so + fünf WLAN-Passphrasen in ein Transkript geschrieben, den IoT-PSK inklusive. Für Kanäle reicht + `/interface wifi channel print detail`; für die `cap-wifiN`-Zuordnung `… print where master=yes` + mit Feldauswahl. **Der Scan selbst (`/interface wifi scan`) ist unbedenklich.** - 🔴 **Die `cap-wifiN`-Nummern sind NICHT stabil.** Der Manager vergibt sie in der Reihenfolge, in der sich die CAPs anmelden — nach dem ap1-Rückbau sind `cap-wifi1/2` = **ap2** und `cap-wifi3/4` = **ap1**, umgekehrt zur früher fest verdrahteten Tabelle. ⇒ **Die Zuordnung gehört zum Messlauf**, nicht zur @@ -1086,7 +1141,22 @@ Es ist **ein** Passwort für alle vier Geräte — die „Überlebensversicherun +#### 🔴 Neues Leak-Ereignis 2026-08-24 — der IoT-PSK ist erneut exponiert +Beim 5-GHz-Umfeldscan für TP25 wurde `mcp__mikromcp__list_wifi_interfaces` gegen den Manager gefahren, +um die `cap-wifiN`-Zuordnung zu bestimmen. **Das Tool gibt `security.passphrase` aller Profile im +Klartext zurück** — damit stehen **alle fünf WLAN-Passphrasen** (`main`, `iot`, `media`, `untrusted`, +`guest`) in einem Sitzungstranskript. Kein Werkzeug hat versagt; es war das falsche Werkzeug für eine +Kanalabfrage. **Betrifft Posten #2 (IoT-PSK) und zusätzlich vier bisher unverbrannte Passphrasen.** +⚖️ **Nach der „harten Ausnahme" oben ist das ein Vorziehgrund** — Entscheidung gehört Christoph. +Gegenargument, das dieselbe Rechnung wie am 08-23 ergibt: der IoT-PSK lag ohnehin schon im Klartext +in der Git-Historie, neu exponiert sind vor allem `main`/`media`/`untrusted`/`guest` — und die kosten +beim Rotieren **wenige** Clients, nicht 26. ⇒ **`main` und `guest` wären billig und einzeln machbar, +unabhängig vom gebündelten Durchgang.** + #### Fallen, die für jedes Setzen/Rotieren gelten (nicht neu erheben) +- 🔴 **Kein Read auf `/interface/wifi`, wenn nur Kanäle/Interfaces gebraucht werden** — + `list_wifi_interfaces` liefert alle Passphrasen im Klartext mit (Leak vom 2026-08-24, s.o.). + Feldauswahl benutzen oder `/interface wifi channel print detail`. - 🔴 **Niemals `sshpass -p`** — schreibt das Passwort in die Kommandozeile, sichtbar in `ps` und in jedem argv-Trace. **Genau so entstand Leak #1.** `-e` hält es in der Umgebung des Kindprozesses. Der Repo-Stand ist bereits durchgängig `-e`.