diff --git a/docs/teilprojekte-archiv.md b/docs/teilprojekte-archiv.md
index d9f2745..197e6d8 100644
--- a/docs/teilprojekte-archiv.md
+++ b/docs/teilprojekte-archiv.md
@@ -848,7 +848,7 @@ FT kaschierte das bisher als „Roaming" statt „schwache Abdeckung".
-### 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.
- ✅ **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.` 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*-`-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`).
diff --git a/docs/teilprojekte.md b/docs/teilprojekte.md
index be3da5f..2a4701d 100644
--- a/docs/teilprojekte.md
+++ b/docs/teilprojekte.md
@@ -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
> 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`) ·
-> 🔜 **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
> 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;**
@@ -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
> 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
-> **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
- **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
-### TP17.2 — einheitliches Geräte-Passwort (Shelly `SetAuth`) ▸ 🔜 **AKTIVIERT (2026-08-23)** — an die PSK-Rotation gekoppelt
-> **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.
-
-Ursprünglicher Text (historisch)
-- **Was:** je Gerät `Shelly.SetAuth` (User `admin`, realm-individueller `ha1` = sha256("admin::"), 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.
-
-
+### 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
@@ -670,7 +656,8 @@ des Dimmers (= Lichtausfall in Diele UG/Wohnzimmer) wurde daraufhin **nicht** au
#### Scope / Abgrenzung
- **Gehört hierher:** alles, was die Migration am **Gerät** verstellt hat (eco_mode, statische IP,
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,
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
@@ -929,10 +916,17 @@ die Redundanzfrage oben.
dahin kommt. **Kein Blocker für irgendetwas.**
-### 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
> 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,
> 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 |
| 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 |
-> ℹ️ **#3 ist TP17.2 und bleibt dort inhaltlich zu Hause** — hier steht es, weil es denselben
-> Geräte-Durchgang wie #2 benutzt (ein Reboot statt zwei), nicht als Duplikat.
+> ℹ️ **#3 war bis 2026-08-24 TP17.2** und ist jetzt vollständig hier (s. Detailabschnitt unten) —
+> 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"):
⏭️ ~~**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
**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.
+
+Ursprünglicher Text (historisch)
+
+- **Was:** je Gerät `Shelly.SetAuth` (User `admin`, realm-individueller `ha1` = sha256("admin::"), 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.
+
+
+
+#### 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
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`.