Files
bf-infra/docs/handoff-20260824-session.md

153 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Übergabe — Session 2026-08-23 (bis in den 24. hinein)
> **Einstieg:** diese Datei, dann [`teilprojekte.md`](teilprojekte.md).
> **Zustand am Netz: stabil und aufgeräumt.** Nichts steht halb offen, keine Config-Transaktion
> gelaufen, `s9` ist vollständig zurückgebaut, alle Shellys erreichbar.
## Was diese Session war
Begonnen mit TP17.3 (der Shelly-Regression), geendet bei einer Umstrukturierung der Router-Konten.
Fünf Commits: `d245d10`, `e8f7f80`, `0a7f2e2`, `2f18319`, `e9a5b36`.
| | |
|---|---|
| ✅ **TP17.3 gelöst** | Ursache **`eco_mode`** bewiesen, `s23` (Dimmer-Flackern) und `s26` (Doppeldruck) repariert. |
| ✅ **`eco_mode` flottenweit aus** | 13 Geräte umgestellt, null Fehler. **22/22 erreichbare Shellys auf `false`.** |
| ❌ **TP17.1 verworfen** | Der Zigbee-Weg wurde **vollständig bewiesen** — und damit auch, dass das Ziel mit ihm nicht erreichbar ist. |
| ✅ **Passwort-Rotation Etappe 1** | Dedizierte Service-Accounts `ha` + `nautobot` auf allen vier MikroTik. |
---
## 🔴 Womit die nächste Session anfangen sollte
> ⚠️ **ÜBERHOLT am 2026-08-24 (User-Entscheid):** die Rotation ist **nicht** der Sessionstart.
> Sie ist zu **[TP30 — Credential-Rotation](teilprojekte.md)** geworden, einem Sammel-TP, der
> **gegen Projektende gebündelt** abgearbeitet wird — Begründung: es kommen weitere Passwörter
> hinzu, und der teure Teil sind die Konsumenten (HA-Re-Auth, Stack-Redeploy), den man nicht
> mehrfach zahlen will. **Der Inhalt unten bleibt sachlich gültig** und steht jetzt in TP30.
**Passwort-Rotation, Etappe 2.** Die Vorarbeit steht komplett, der Rest ist die einzige Sache mit
echter Dringlichkeit — das `admin`-Passwort ist zweimal in ein Transkript geraten (22.08. und, durch
meinen eigenen Enumerationsfehler, nochmal am 23.08.; **derselbe Wert**, da alle vier Geräte ihn teilen).
**Was Etappe 2 verlangt, in dieser Reihenfolge:**
1. **Nautobot** auf den `nautobot`-User umstellen — `NAUTOBOT_ROUTEROS_USERNAME/PASSWORD` im Stack
`docs/nas-vlan20/stacks/210-nautobot.yml` (gitignored), dann **Portainer-Redeploy** auf der DS923.
⚠️ Beim Redeploy die Healthcheck-/`mem_limit`-Zeilen nicht verlieren — siehe CLAUDE.md-Gotcha,
der Stack hat am 17.08. zweimal die DS923 abgeräumt.
**Abnahme:** ein GC-Backup-Lauf, der durchgeht.
2. **HA**: die vier `mikrotik`-Integrationen (`.99.1`, `.99.2`, `.99.11`, `.99.12`) auf `ha` bringen.
🔴 **`supports_reconfigure: false` — nicht skriptbar.** Entfernen-und-neu-Anlegen *wäre* skriptbar
(`ha_set_integration domain="mikrotik"`), riskiert aber die **40 `device_tracker`-Entities**.
Sie heißen nach MAC (`device_tracker.10_20_ba_fa_f5_40`), kämen also identisch zurück — **aber nur,
wenn die alten Registry-Einträge vorher weg sind**, sonst hängt HA ein `_2` an. Dieselbe Falle wie
beim Shelly-Rename.
3. **Erst danach `admin` rotieren.** Dann berührt es nur noch `~/.secrets/credentials.env` und
`~/.claude.json` (+ MikroMCP-Neustart) — die Repo-Skripte ziehen automatisch nach.
### Was dafür schon fertig ist
Auf **allen vier** Geräten angelegt und abgenommen (vorher existierte dort **nur** `admin`/`full`):
| Gruppe | Policy | User |
|---|---|---|
| `grp-ha` | `read,api,rest-api,test` | `ha` |
| `grp-nautobot` | `ssh,read,write,test,sensitive` | `nautobot` |
Passwörter: `MIKROTIK_HA_PASS` / `MIKROTIK_NAUTOBOT_PASS` in `~/.secrets/credentials.env`.
🎯 **Der Export von `nautobot` ist byte-identisch zu dem von `admin`** (391/56/87/87 Zeilen) —
**die GC-Compliance driftet beim Umstellen nicht.** Das war das Hauptrisiko und ist geprüft.
`/user` wird von keiner ComplianceRule abgedeckt, die Konten erzeugen selbst keinen Drift.
---
## Danach, mit Vorsicht
- **C2 — IoT-PSK rotieren.** Der Hebel ist `/interface wifi security multi-passphrase`
(`group`/`passphrase`/`vlan-id`/`expires`), auf dem Core verifiziert vorhanden, Tabelle noch leer.
🔴 **Zuerst `multi-passphrase` gegen WPA3/SAE testen — auf einer Wegwerf-SSID, nie an
`dirtyvader-iot`.** `sec-iot` fährt `wpa2-psk,wpa3-psk`; trägt multi-passphrase SAE nicht, sperrt
man **26 IoT-Geräte auf einmal** aus, inklusive Nuki und NSPanel.
Danach: 23 Shellys per Skript (der erprobte Anker-Pfad in `migrate.py._migrate_one`), **3 Geräte von
Hand** — `.249` SONOFF NSPanel Pro (Touchscreen), `.244` Nuki Bridge (App), `.227` SwitchBot Floor
Lamp (App). ⚠️ `s1`/`s2`/`s3` sind ausgesteckt und kommen im Dezember mit dem **alten** PSK zurück.
⚠️ CAPsMAN: eine Profiländerung wirkt erst nach `remote-cap provision` für **beide** APs.
- **D — TP17.2 Shelly-Gerätepasswort**, an C2 gekoppelt (ein Reboot statt zwei). Werkzeug ist fertig
(`migrate.py cmd_auth`, Digest-Fallback in `_rpc`). 🔴 **Der Aufwand ist HA, nicht `SetAuth`:** je
Gerät ein Re-Auth-Flow, 23-mal. **Erst an EINEM Gerät messen** (Vorschlag `s15 technik_pve`, −36 dBm).
- **TP25 Fund F** (5:05-Takt IoT) und die Entscheidung **5 GHz auf 20 MHz**.
- **5-GHz-Umfeldscan** vor dem Einbau der zwei neuen APs.
---
## Die Entscheidung des Tages: warum TP17.1 gestorben ist
Der Pilot hat den Zigbee-Weg **technisch vollständig bewiesen** — `s9` lief auf `PowerStripZB`, trat
ZHA bei, ein Zigbee-Befehl schaltete das physische Relais, kein Broadcast-Sturm.
Christophs Einwand hat ihn trotzdem gekippt: *„zigbee sollte die antwort auf die vielen radios auf
-iot geben. nutzt aber wenig wenn man das wifi nicht abdrehen kann bzw. es nicht mehr aktivieren kann
ohne reset."* Und die Messung stützt ihn:
- **Das Gerät bleibt WLAN-Client** — Zigbee kommt *zusätzlich*, nicht *statt*.
- **Der Funkgewinn ist klein:** die 12 Gen4 sind 12 von 26 IoT-Clients, bewegen aber je nur
~150–200 KB rx / 0,6–3 MB tx in sechs Stunden.
- **Der Preis wäre dauerhaft:** die Zigbee-Firmware hat **keinen AP**, Shelly macht **kein Zigbee-OTA**,
`Shelly.InstallAlt` braucht IP. WLAN aus = nie wieder Update, kein Rückweg, bei 10 Unterputz-Modulen.
**Der Weg ist nicht gescheitert, das Ziel war mit ihm nicht erreichbar.** Das Runbook bleibt als
Wissensspeicher; einziger Restposten ist der **Frühindikator** (`Shelly.CheckForUpdate` auf einen
`…MT`/Thread-`alt`-Eintrag beobachten).
---
## Zwei Messungen, die vorherige Annahmen widerlegen
**1. `eco_mode` aus hebt die Sendeleistung NICHT an.** Ich hatte das als Airtime-Risiko notiert, das
TP25 berührt. Gemessen am Manager, vorher/nachher: **13 geänderte Geräte im Mittel −0,9 dB**, bei einer
**Kontrollgruppe von 13 unveränderten mit +0,0 dB** und derselben Streuung (±2 dB). Rauschen.
⇒ Die TP17-Aussage, `eco_mode` senke „den CPU-Takt **und** die WLAN-Sendeleistung", stimmt nur zur
Hälfte. Der Takt-Teil ist durch das Dimmer-Flackern bewiesen; der Rest ist nicht messbar.
**2. `restart_required` auf 14 Shellys war ein Fehlalarm.** Der Reboot von `s26` mit Config-Vergleich
davor/danach ergab **identische Configs**. Das Bit ist *sticky* und stand für keine abweichende
Konfiguration. **Nicht erneut untersuchen** — drei Wege (169 RPC-Methoden, Config-Diff über die
Gruppengrenze, Gerätelog) sind zu Ende gegangen, alle negativ.
---
## Zahlen und Fallen, die man nicht neu erheben muss
- **`dirtyvader-iot`: 26–27 Clients, alle auf EINEM VAP** (`cap-wifi4-virtual1`, ap1). Davon 23 Shellys
und **3 Fremde**: `.249` NSPanel Pro, `.244` Nuki Bridge, `.227` SwitchBot Floor Lamp.
- **`s4 kueche_mikrowelle` ist wieder online** (war den ganzen Tag als offline geführt) — und ist
**Gen3**, war also nie TP17.1-Kandidat. Bleibt der Härtefall bei −96 dBm (Geräte-Sicht).
- 🔴 **HA- und Repo-Nummerierung der Shellys weichen ab** — HA: `s10 = schlafzi/teststecker`,
Inventory: `s10 = bad_sonos`; ebenso `s17`. **Immer über MAC/IP zuordnen, nie über die s-Nummer.**
- 🔴 **`migrate.py _resolve` fällt ohne Argument auf den alten VLAN1-Sweep `10.40.41.180-250` zurück.**
Explizite Bereiche übergeben oder `SHELLY_SWEEP` setzen.
- 🔵 **`inventory/bf.csv` führt `s12` noch auf `10.40.41.219`** (live `10.40.30.219`).
- ⚠️ **Nach jedem Shelly-Firmwarewechsel den AP prüfen** — der Rückflash von `s9` zog einen **offenen**
AP hoch (`ap.enable=true, is_open=true`). Abgeschaltet und mit dem IoT-PSK abgesichert.
- 🔒 **`wifi-security` ist als ComplianceRule grün, aber NICHT deploybar** — die Passphrasen stehen als
`<<REDACTED>>` im Template. Ist-Stand immer per REST vom Gerät lesen
(`GET http://10.40.99.1/rest/interface/wifi/security`), **nie** aus `wlan-psks.env`.
### Der Firmware-Mechanismus der Shelly Gen4 (falls er je wieder gebraucht wird)
Zwei-Slot-Modell über drei **undokumentierte** RPCs, aus dem UI-JavaScript des Geräts extrahiert:
`Shelly.InstallAlt {app, stage}` lädt in den inaktiven Slot und rebootet hinein · `Shelly.SetAlternative
{name}` schaltet um (auf unseren Modellen **nicht vorhanden**) · `Shelly.ListAlternatives` (404 auf
beiden Builds). Die Shelly-Support-Seite beschreibt einen **Modus-Umschalter mit 5-Sekunden-Knopf** —
**das gilt für unsere Modelle nicht.**
---
## Neue und geänderte Dokumente
- [`tp17.1-shelly-gen4-funkmigration-runbook.md`](tp17.1-shelly-gen4-funkmigration-runbook.md) —
Kopf trägt jetzt „VERWORFEN"; enthält den kartierten Mechanismus, das 2,4-GHz-Bild und die
ZHA-Sturmzähler mit Baseline
- [`teilprojekte.md`](teilprojekte.md) — TP17.1 verworfen, TP17.2 aktiviert, TP17.3 erledigt,
PSK-Follow-up um Radius-Befund und Etappe 1 ergänzt
- `CLAUDE.md` — 🔴 empfahl bis gestern aktiv `sshpass -p` als Reboot-Weg, jetzt `sshpass -e`
- `mcp/shelly/migrate.py` — neues `eco`-Kommando (mit Retry je Gerät und Fehlerliste)