TP17.2 in TP30 aufgeloest; TP30 ist das Sammelbecken fuer Credentials

User-Entscheid: TP30 sammelt jedes Credential, das neu gesetzt werden
muss -- nicht nur Rotationen. Das Shelly-Geraetepasswort (TP17.2) ist
eine Erstvergabe und gehoert damit dorthin; ausserdem teilt es sich mit
der PSK-Rotation den Geraete-Durchgang (ein Reboot statt zwei).

- TP17.2-Volltext nach TP30 verschoben (Posten #3), Stub bleibt als
  Wegweiser, damit die Nummer nicht ins Leere zeigt
- TP30-Titel/Scope geweitet: "neu setzen & rotieren", mit expliziter
  Trennung Erstvergabe vs. Rotation (Prioritaet unterschiedlich,
  Arbeitsaufwand identisch)
- Detailabschnitte symmetrisch als "Posten #1" / "Posten #3" benannt
- Querverweise nachgezogen: Naechster-Schritt-Block, Split-Regel,
  TP17.3-Abgrenzung, Archiv-Kopfzeile TP17

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-24 07:08:13 +02:00
parent baf97e2d85
commit 93c32a2ad7
2 changed files with 53 additions and 32 deletions

View File

@@ -848,7 +848,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
<a id="tp17"></a> <a id="tp17"></a>
### TP17 — Shelly-Übersiedelung VLAN1 → VLAN30 (IOT) + `shelly-mcp` ▸ ✅ **KOMPLETT (User-Bestätigt 2026-08-13): alle Shellys auf VLAN30** — Geräte-PW (TP17.2) weiterhin bewusst zurückgestellt — `mcp/shelly/`, Runbook `docs/tp17-shelly-go-runbook.md` ### TP17 — Shelly-Übersiedelung VLAN1 → VLAN30 (IOT) + `shelly-mcp` ▸ ✅ **KOMPLETT (User-Bestätigt 2026-08-13): alle Shellys auf VLAN30** — Geräte-PW *(war TP17.2, seit 2026-08-24 **TP30** Posten #3)* — `mcp/shelly/`, Runbook `docs/tp17-shelly-go-runbook.md`
- ✅ **Abschluss 2026-08-13 (User-Bestätigt):** auch die zuletzt offenen saisonalen Shellys (s1/s2/s3/s12) sind inzwischen umgeklemmt — **alle Shellys auf `dirtyvader-iot`/VLAN30**, kein VLAN1-Shelly-Rest mehr. Migration-Teil von TP17 damit vollständig abgeschlossen. - ✅ **Abschluss 2026-08-13 (User-Bestätigt):** auch die zuletzt offenen saisonalen Shellys (s1/s2/s3/s12) sind inzwischen umgeklemmt — **alle Shellys auf `dirtyvader-iot`/VLAN30**, kein VLAN1-Shelly-Rest mehr. Migration-Teil von TP17 damit vollständig abgeschlossen.
- ✅ **GO durchgezogen 2026-07-13 (16 Shellys VLAN1→VLAN30, 0 Fehler):** Pilot s26 + Welle A (s4–s9) + Welle B (s10/11/13/15/17/19/20/21/25) → alle auf `dirtyvader-iot`/`10.40.30.<octet>` verifiziert (SSID+IP+rssi). Mit den 6 Vorab-Migrierten (s14/16/18/22/23/24) = **22/26 auf VLAN30**; VLAN1-Sweep `.180-250` = **0 Shellys**. Restliche 4 saisonal ausgesteckte (s1/s2/s3/s12) inzwischen ebenfalls migriert (s.o.). - ✅ **GO durchgezogen 2026-07-13 (16 Shellys VLAN1→VLAN30, 0 Fehler):** Pilot s26 + Welle A (s4–s9) + Welle B (s10/11/13/15/17/19/20/21/25) → alle auf `dirtyvader-iot`/`10.40.30.<octet>` verifiziert (SSID+IP+rssi). Mit den 6 Vorab-Migrierten (s14/16/18/22/23/24) = **22/26 auf VLAN30**; VLAN1-Sweep `.180-250` = **0 Shellys**. Restliche 4 saisonal ausgesteckte (s1/s2/s3/s12) inzwischen ebenfalls migriert (s.o.).
- 🔧 **Anker-Verfahren (User-Idee, statt sta1-Backup):** je Gerät **vor** dem sta-Write die geräteeigene **AP-Funktion** aktiviert (`WiFi.SetConfig ap.enable` — Firmware verlangt WPA2, kein offenes AP → PSK=IOT-PSK, live/kein Reboot) = Notanker, falls VLAN30-Join scheitert (Gerät bleibt über `Shelly*-<mac>`-AP erreichbar, **kein physischer Reset**). Nach Verify alle 22 AP-Anker wieder `deanchor`t. Runner: `mcp/shelly/migrate.py` (`migrate`/`deanchor`/`auth`/`table`, Dry-Run default, stoppt bei erstem Fehler, reused `discover.py`). - 🔧 **Anker-Verfahren (User-Idee, statt sta1-Backup):** je Gerät **vor** dem sta-Write die geräteeigene **AP-Funktion** aktiviert (`WiFi.SetConfig ap.enable` — Firmware verlangt WPA2, kein offenes AP → PSK=IOT-PSK, live/kein Reboot) = Notanker, falls VLAN30-Join scheitert (Gerät bleibt über `Shelly*-<mac>`-AP erreichbar, **kein physischer Reset**). Nach Verify alle 22 AP-Anker wieder `deanchor`t. Runner: `mcp/shelly/migrate.py` (`migrate`/`deanchor`/`auth`/`table`, Dry-Run default, stoppt bei erstem Fehler, reused `discover.py`).

View File

@@ -90,7 +90,8 @@ ab jetzt bei jeder Änderung mitgezogen, nicht nur die TP-Abschnitte.)*
> ❌ **TP17.1 VERWORFEN 2026-08-23** (Zigbee-Weg bewiesen, Ziel damit nicht erreichbar — das Gerät > ❌ **TP17.1 VERWORFEN 2026-08-23** (Zigbee-Weg bewiesen, Ziel damit nicht erreichbar — das Gerät
> bleibt WLAN-Client; `s9` zurückgebaut) · ✅ **TP17.3 ERLEDIGT** (Ursache **`eco_mode`** bewiesen; > bleibt WLAN-Client; `s9` zurückgebaut) · ✅ **TP17.3 ERLEDIGT** (Ursache **`eco_mode`** bewiesen;
> `s23` + `s26` repariert; **`eco_mode` flottenweit aus**, 22/22 außer `s24`) · > `s23` + `s26` repariert; **`eco_mode` flottenweit aus**, 22/22 außer `s24`) ·
> 🔜 **TP17.2 aktiviert** (Shelly-Gerätepasswort, an die PSK-Rotation gekoppelt) · > ➡️ **TP17.2 ist am 2026-08-24 in TP30 aufgegangen** (Shelly-Gerätepasswort = Erstvergabe eines
> Credentials; TP30 ist das Sammelbecken dafür) ·
> 🔑 **Alle Passwort-/Token-Rotationen sind seit 2026-08-24 TP30** (Sammel-TP) — **bewusst > 🔑 **Alle Passwort-/Token-Rotationen sind seit 2026-08-24 TP30** (Sammel-TP) — **bewusst
> gebündelt gegen Projektende**, User-Entscheid. Damit ist die ältere Einreihung „hinter TP17.1" > gebündelt gegen Projektende**, User-Entscheid. Damit ist die ältere Einreihung „hinter TP17.1"
> gegenstandslos (TP17.1 ist verworfen). **Etappe 1 — die Service-Accounts — ist durch;** > gegenstandslos (TP17.1 ist verworfen). **Etappe 1 — die Service-Accounts — ist durch;**
@@ -146,7 +147,8 @@ nachmessen und dann entscheiden**. Blocker gibt es keine mehr. TP5 ist in der Na
> **[Archiv](teilprojekte-archiv.md)** (Volltext, mit Inhaltsverzeichnis) — die Zuordnung ist > **[Archiv](teilprojekte-archiv.md)** (Volltext, mit Inhaltsverzeichnis) — die Zuordnung ist
> mechanisch: *ein TP wandert erst dann ins Archiv, wenn nichts mehr daran zu tun ist.* Wo nur ein > mechanisch: *ein TP wandert erst dann ins Archiv, wenn nichts mehr daran zu tun ist.* Wo nur ein
> Sub-TP offen war, steht dieses hier und das erledigte Eltern-TP im Archiv (so bei > Sub-TP offen war, steht dieses hier und das erledigte Eltern-TP im Archiv (so bei
> **TP17.2** ↔ TP17 und **TP20.1** ↔ TP20). > ~~**TP17.2** ↔ TP17~~ *(TP17.2 ist am 2026-08-24 in **TP30** aufgegangen und kein eigenes TP mehr)*
> und **TP20.1** ↔ TP20).
### TP5.1 — DNS-Visibility & Flow-Observability für Low-Trust-Geräte (Airfryer-Fall) ▸ vorgemerkt ### TP5.1 — DNS-Visibility & Flow-Observability für Low-Trust-Geräte (Airfryer-Fall) ▸ vorgemerkt
- **Kontext (2026-07-08/09):** Airfryer „airschreier" (Philips/Versuni, ESP, `10.40.30.180`) bekam per DHCP-Option 6 `dns 1.1.1.1` als Override, weil das OTA-Update über den ap1-DoH-Gateway-Pfad nicht durchging (DoH-Latenz beim primitiven ESP-Stack — **kein** Content-Block, via Gateway-Logs bewiesen, s. `memory/ref_esp_ota_doh_not_block`). Nebenwirkung: public **1.1.1.1 = anonymer Consumer-Resolver ≠ accountgebundener Gateway-DoH** (`px35ynlol3.cloudflare-gateway.com`) → **DNS-Sicht auf das Gerät weg**, Gerät umgeht zudem die Filterung. - **Kontext (2026-07-08/09):** Airfryer „airschreier" (Philips/Versuni, ESP, `10.40.30.180`) bekam per DHCP-Option 6 `dns 1.1.1.1` als Override, weil das OTA-Update über den ap1-DoH-Gateway-Pfad nicht durchging (DoH-Latenz beim primitiven ESP-Stack — **kein** Content-Block, via Gateway-Logs bewiesen, s. `memory/ref_esp_ota_doh_not_block`). Nebenwirkung: public **1.1.1.1 = anonymer Consumer-Resolver ≠ accountgebundener Gateway-DoH** (`px35ynlol3.cloudflare-gateway.com`) → **DNS-Sicht auf das Gerät weg**, Gerät umgeht zudem die Filterung.
@@ -531,27 +533,11 @@ nachmessen und dann entscheiden**. Blocker gibt es keine mehr. TP5 ist in der Na
</details> </details>
### TP17.2 — einheitliches Geräte-Passwort (Shelly `SetAuth`) ▸ 🔜 **AKTIVIERT (2026-08-23)** — an die PSK-Rotation gekoppelt ### TP17.2 — einheitliches Geräte-Passwort (Shelly `SetAuth`) ▸ ➡️ **NACH [TP30](#tp30) VERSCHOBEN (2026-08-24)**
> **User 2026-08-23:** „außerdem haben wir einen punkt, um die shellys mit einem pwd zu schützen." > **User-Entscheid:** TP30 ist das Sammelbecken für Credentials, die neu gesetzt oder rotiert werden
> Damit ist der Zurückgestellt-Status von 2026-07-13 aufgehoben. **Begründung der Kopplung:** die > müssen — TP17.2 ist genau das (Erstvergabe) und teilt sich mit der PSK-Rotation den Geräte-Durchgang.
> PSK-Rotation fasst ohnehin jeden Shelly an und rebootet ihn — `SetAuth` gehört in denselben > Der vollständige Text steht dort als **Posten #3**. Diese Zeile bleibt nur, damit die Nummer nicht
> Durchgang, ein Reboot statt zwei. > ins Leere zeigt; **TP17.2 ist kein eigenes TP mehr.**
>
> ✅ **Werkzeugseitig ist nichts zu bauen:** `mcp/shelly/migrate.py` hat `cmd_auth` (setzt
> `Shelly.SetAuth` mit SHA-256-`ha1` gegen die Geräte-`realm`, Dry-Run als Default), und `_rpc` hat
> einen **Digest-Auth-Fallback** auf 401 mit `SHELLY_DEVICE_PW`.
>
> 🔴 **Der teure Teil ist nicht `SetAuth`, sondern Home Assistant.** Mit aktiver Auth verlangt die
> Shelly-Integration je Gerät einen **Re-Auth-Flow** — bei 23 Geräten ist *das* der Aufwand, und genau
> der Grund für die frühere Einstufung als „Kosmetik". ⇒ **Erst an EINEM Gerät machen und den
> HA-Aufwand messen** (Vorschlag `s15 technik_pve`, RSSI −36, unkritisch), bevor der Rest folgt.
> Sonst bündelt man ein ungemessenes Risiko in eine 23-Geräte-Aktion.
<details><summary>Ursprünglicher Text (historisch)</summary>
- **Was:** je Gerät `Shelly.SetAuth` (User `admin`, realm-individueller `ha1` = sha256("admin:<device-id>:<pw>"), einheitliches Klartext-PW) via `mcp/shelly/migrate.py auth --go`. `SHELLY_DEVICE_PW` liegt in `mcp/shelly/.env` (gesetzt, len 13). Runner + Digest-Auth-Fallback in `_rpc` fertig.
- **Warum zurückgestellt:** rein kosmetisch/Härtung; **bricht die HA-Shelly-Integration**, bis pro Config-Entry (22×) das Credential neu eingetragen ist → disruptiv, kein Mehrwert im abgeschotteten IOT-VLAN. **Erst nach** dem Netz-Teardown (TP19) neu bewerten.
</details>
### 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 ### 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 > **User-Meldung 2026-08-23:** „vor einiger zeit hast du an den shellys änderungen vorgenommen. das
@@ -670,7 +656,8 @@ des Dimmers (= Lichtausfall in Diele UG/Wohnzimmer) wurde daraufhin **nicht** au
#### Scope / Abgrenzung #### Scope / Abgrenzung
- **Gehört hierher:** alles, was die Migration am **Gerät** verstellt hat (eco_mode, statische IP, - **Gehört hierher:** alles, was die Migration am **Gerät** verstellt hat (eco_mode, statische IP,
AP-Anker) und was daraus an Fehlverhalten folgt. AP-Anker) und was daraus an Fehlverhalten folgt.
- **Gehört nicht hierher:** die Funkumstellung selbst (**TP17.1**) und das Geräte-Passwort (**TP17.2**). - **Gehört nicht hierher:** die Funkumstellung selbst (**TP17.1**, verworfen) und das Geräte-Passwort
(seit 2026-08-24 **TP30 Posten #3**, vormals TP17.2).
- 🔗 **Aber die Verzahnung mit TP17.1 ist der Hebel:** wenn ohnehin **alle** Shellys angefasst werden, - 🔗 **Aber die Verzahnung mit TP17.1 ist der Hebel:** wenn ohnehin **alle** Shellys angefasst werden,
ist das der Moment, `eco_mode` **grundsätzlich** zu entscheiden statt gerätweise zu pflegen. ist das der Moment, `eco_mode` **grundsätzlich** zu entscheiden statt gerätweise zu pflegen.
Christophs „ich muss vermutlich eh alle shellys neu machen" ist damit nicht Resignation, sondern der Christophs „ich muss vermutlich eh alle shellys neu machen" ist damit nicht Resignation, sondern der
@@ -929,10 +916,17 @@ die Redundanzfrage oben.
dahin kommt. **Kein Blocker für irgendetwas.** dahin kommt. **Kein Blocker für irgendetwas.**
<a id="tp30"></a> <a id="tp30"></a>
### TP30 — Credential-Rotation (Sammel-TP) ▸ 🔜 **ANGELEGT 2026-08-24, bewusst GEBÜNDELT gegen Projektende** ### TP30 — Credentials: neu setzen & rotieren (Sammelbecken) ▸ 🔜 **ANGELEGT 2026-08-24, bewusst GEBÜNDELT gegen Projektende**
> **User-Entscheid 2026-08-24:** „ich würde gerne daraus einen eigenen punkt machen. ich bin mir > **User-Entscheid 2026-08-24:** „ich würde gerne daraus einen eigenen punkt machen. ich bin mir
> sicher, dass es noch öfters passwörter zu rotieren geben wird. das machen wir dann alles gegen > sicher, dass es noch öfters passwörter zu rotieren geben wird. das machen wir dann alles gegen
> projektende." > projektende." — nachgeschärft am selben Tag: **„tp30 wird unser sammelbecken für credentials,
> die neu gesetzt werden müssen"**, und **TP17.2 wandert hierher.**
>
> 📥 **Scope ist damit breiter als „Rotation": jedes Credential, das neu gesetzt werden muss** —
> **Erstvergabe** (bisher gar keins vorhanden, z.B. Shelly `SetAuth`) **oder Rotation** (Wert
> verbrannt/abgelaufen). Die Trennung ist für die Priorität wichtig, für die Arbeit nicht: der
> Kostentreiber ist in beiden Fällen derselbe — die Konsumenten, nicht das Setzen.
> **Neue Credential-Aufgaben kommen ab jetzt hier hinein, nicht als eigenes TP.**
> >
> **Warum ein eigener TP und nicht vier verstreute Follow-up-Zeilen:** die Rotationen teilen sich Werkzeug, > **Warum ein eigener TP und nicht vier verstreute Follow-up-Zeilen:** die Rotationen teilen sich Werkzeug,
> Fallen und vor allem den **teuren Teil — den Konsumenten** (HA, Nautobot, MikroMCP, `~/.secrets`). > Fallen und vor allem den **teuren Teil — den Konsumenten** (HA, Nautobot, MikroMCP, `~/.secrets`).
@@ -947,13 +941,15 @@ die Redundanzfrage oben.
|---|---|---|---|---|---| |---|---|---|---|---|---|
| 1 | **MikroTik `admin`** | core · branch · ap1 · ap2 (**ein** geteilter Wert) | 🔴 **zweimal in ein Transkript geraten** (2026-08-22 via `sshpass -p`; 2026-08-23 durch einen Enumerationsfehler) | ✅ **Etappe 1 durch** (s.u.) | nach Etappe 2 nur noch `~/.secrets/credentials.env` + `~/.claude.json` + MikroMCP-Neustart | | 1 | **MikroTik `admin`** | core · branch · ap1 · ap2 (**ein** geteilter Wert) | 🔴 **zweimal in ein Transkript geraten** (2026-08-22 via `sshpass -p`; 2026-08-23 durch einen Enumerationsfehler) | ✅ **Etappe 1 durch** (s.u.) | nach Etappe 2 nur noch `~/.secrets/credentials.env` + `~/.claude.json` + MikroMCP-Neustart |
| 2 | **IoT-WLAN-PSK** (`sec-iot`) | `dirtyvader-iot`, 26 Clients | steht **im Klartext** im TP17-Text ⇒ auch in der **Git-Historie**; Redigieren holt ihn dort nicht raus | Hebel `multi-passphrase` am Core verifiziert vorhanden, Tabelle leer | 23 Shellys per Skript + **3 von Hand** (`.249` NSPanel Pro, `.244` Nuki Bridge, `.227` SwitchBot) | | 2 | **IoT-WLAN-PSK** (`sec-iot`) | `dirtyvader-iot`, 26 Clients | steht **im Klartext** im TP17-Text ⇒ auch in der **Git-Historie**; Redigieren holt ihn dort nicht raus | Hebel `multi-passphrase` am Core verifiziert vorhanden, Tabelle leer | 23 Shellys per Skript + **3 von Hand** (`.249` NSPanel Pro, `.244` Nuki Bridge, `.227` SwitchBot) |
| 3 | **Shelly-Gerätepasswort** | 23 Shellys | Härtung (bisher **keine** Auth auf den Geräten) | ✅ Werkzeug fertig (`migrate.py cmd_auth` + Digest-Fallback) | **je Gerät ein HA-Re-Auth-Flow** — das ist der Aufwand, nicht `SetAuth` | | 3 | **Shelly-Gerätepasswort** *(vormals TP17.2)* | 23 Shellys | Härtung (bisher **keine** Auth auf den Geräten) | ✅ Werkzeug fertig (`migrate.py cmd_auth` + Digest-Fallback) | **je Gerät ein HA-Re-Auth-Flow** — das ist der Aufwand, nicht `SetAuth` |
| 4 | **CF-Access-Service-Token** (`CF_API_TOKEN`) | Cloudflare-Zugang, s. TP14.4 | ⏳ **läuft am 2027-01-09 ohnehin ab** — harter Termin, unabhängig vom Projektende | Runbook liegt (`tp14.4-cf-access-token-runbook.md`) | Token neu ausstellen + `~/.secrets` nachziehen; **account-owned**, anderer verify-Endpoint | | 4 | **CF-Access-Service-Token** (`CF_API_TOKEN`) | Cloudflare-Zugang, s. TP14.4 | ⏳ **läuft am 2027-01-09 ohnehin ab** — harter Termin, unabhängig vom Projektende | Runbook liegt (`tp14.4-cf-access-token-runbook.md`) | Token neu ausstellen + `~/.secrets` nachziehen; **account-owned**, anderer verify-Endpoint |
> ℹ️ **#3 ist TP17.2 und bleibt dort inhaltlich zu Hause** — hier steht es, weil es denselben > ℹ️ **#3 war bis 2026-08-24 TP17.2** und ist jetzt vollständig hier (s. Detailabschnitt unten) —
> Geräte-Durchgang wie #2 benutzt (ein Reboot statt zwei), nicht als Duplikat. > es benutzt denselben Geräte-Durchgang wie #2, **ein Reboot statt zwei**. #4 gehört sachlich zu
> **TP14.4**, das als TP bestehen bleibt (dort steckt das CF-Access-Profil, nicht nur der Token).
#### Detail — Radius, Etappe 1 und Etappe 2 (am 2026-08-24 aus den Follow-ups hierher gezogen) #### Posten #1 im Detail — MikroTik `admin`: Radius, Etappe 1, Etappe 2
*Am 2026-08-24 aus den Follow-ups hierher gezogen — Text unverändert übernommen.*
**Vorgeschichte des Entscheids** (Stand bis 2026-08-23, User: „machen wir, aber erst später"): **Vorgeschichte des Entscheids** (Stand bis 2026-08-23, User: „machen wir, aber erst später"):
⏭️ ~~**Nachgelagert seit 2026-08-23: erst TP17.1, dann rotieren.**~~ ⏭️ ~~**Nachgelagert seit 2026-08-23: erst TP17.1, dann rotieren.**~~
@@ -1065,7 +1061,32 @@ Es ist **ein** Passwort für alle vier Geräte — die „Überlebensversicherun
steht er, damit die Rotationsliste vollständig ist. ⚠️ Der `CF_API_TOKEN` läuft ohnehin steht er, damit die Rotationsliste vollständig ist. ⚠️ Der `CF_API_TOKEN` läuft ohnehin
**2027-01-09** ab — spätestens dann ist dieser Posten fällig, unabhängig vom Projektende. **2027-01-09** ab — spätestens dann ist dieser Posten fällig, unabhängig vom Projektende.
#### Fallen, die für jede künftige Rotation gelten (nicht neu erheben) #### Posten #3 im Detail — Shelly-Gerätepasswort (`SetAuth`), vormals TP17.2
*Am 2026-08-24 als eigenes TP aufgelöst und hierher gezogen — Text unverändert übernommen.*
> **User 2026-08-23:** „außerdem haben wir einen punkt, um die shellys mit einem pwd zu schützen."
> Damit ist der Zurückgestellt-Status von 2026-07-13 aufgehoben. **Begründung der Kopplung:** die
> PSK-Rotation fasst ohnehin jeden Shelly an und rebootet ihn — `SetAuth` gehört in denselben
> Durchgang, ein Reboot statt zwei.
>
> ✅ **Werkzeugseitig ist nichts zu bauen:** `mcp/shelly/migrate.py` hat `cmd_auth` (setzt
> `Shelly.SetAuth` mit SHA-256-`ha1` gegen die Geräte-`realm`, Dry-Run als Default), und `_rpc` hat
> einen **Digest-Auth-Fallback** auf 401 mit `SHELLY_DEVICE_PW`.
>
> 🔴 **Der teure Teil ist nicht `SetAuth`, sondern Home Assistant.** Mit aktiver Auth verlangt die
> Shelly-Integration je Gerät einen **Re-Auth-Flow** — bei 23 Geräten ist *das* der Aufwand, und genau
> der Grund für die frühere Einstufung als „Kosmetik". ⇒ **Erst an EINEM Gerät machen und den
> HA-Aufwand messen** (Vorschlag `s15 technik_pve`, RSSI −36, unkritisch), bevor der Rest folgt.
> Sonst bündelt man ein ungemessenes Risiko in eine 23-Geräte-Aktion.
<details><summary>Ursprünglicher Text (historisch)</summary>
- **Was:** je Gerät `Shelly.SetAuth` (User `admin`, realm-individueller `ha1` = sha256("admin:<device-id>:<pw>"), einheitliches Klartext-PW) via `mcp/shelly/migrate.py auth --go`. `SHELLY_DEVICE_PW` liegt in `mcp/shelly/.env` (gesetzt, len 13). Runner + Digest-Auth-Fallback in `_rpc` fertig.
- **Warum zurückgestellt:** rein kosmetisch/Härtung; **bricht die HA-Shelly-Integration**, bis pro Config-Entry (22×) das Credential neu eingetragen ist → disruptiv, kein Mehrwert im abgeschotteten IOT-VLAN. **Erst nach** dem Netz-Teardown (TP19) neu bewerten.
</details>
#### Fallen, die für jedes Setzen/Rotieren gelten (nicht neu erheben)
- 🔴 **Niemals `sshpass -p`** — schreibt das Passwort in die Kommandozeile, sichtbar in `ps` und in - 🔴 **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. 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`. Der Repo-Stand ist bereits durchgängig `-e`.