Commit Graph

369 Commits

Author SHA1 Message Date
82c8f0e828 TP25: Raumkarte -- der Dead Spot ist die Terrasse, das Haus ist sauber
Zweiter Gehweg-Durchgang, diesmal methodisch sauber: Ping vom Core statt vom
Laptop, Konsole auf dem iPhone (Wake Lock haelt es wach, sonst misst man
Ruhezustand), Raumwechsel per Klick markiert.

Das Ergebnis ist eindeutig und macht die Roaming-Geschichte klein. Im ganzen Haus
null Paketverlust -- Technik UG und OG, Diele, Kinder-, Schlaf- und
Arbeitszimmer, Treppe, alle 0 %, und die Uebergaben ap1<->ap2 auf der Treppe
kosten 0,2 s. Auf der Terrasse dagegen 43 % Verlust ueber 162 Sekunden, am Stueck
fehlen 20,4 Sekunden, bei -72 dBm. Dort ist ein Call nicht gestoert, sondern weg.

Die Topologie erklaert es vollstaendig: ap2 steht in Technik OG, das nur ueber
das Arbeitszimmer zugaenglich ist -- zur Terrasse liegen Technik OG,
Arbeitszimmer, Diele OG und die Aussenwand dazwischen.

Das dreht die Massnahmen um. Ein signal-range-Boden (Fund E) wuerde die Terrasse
VERSCHLECHTERN, weil es dort keinen besseren AP gibt, auf den er steuern koennte
-- er wuerde nur rauswerfen. Stattdessen: 5 GHz auf 20 MHz (+3 dB, ein Wort im
Template), dann ap2 von Technik OG in die Diele OG umhaengen, die an Terrasse,
Arbeitszimmer und Treppe grenzt. Kein neuer AP noetig, damit ist auch die
User-Randbedingung erfuellt.

Konsole nachgezogen: Marker werden URL-dekodiert und behalten ihre Gross- und
Kleinschreibung (aus "RAUM=Diele OG" wurde "RAUM%3DDIELE%20OG"), Diele OG ist
ergaenzt, und das Raumraster steht jetzt oben -- ohne JavaScript laedt die Seite
nach jedem Klick neu, und dann muss der naechste Raum ohne Scrollen erreichbar
sein.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 15:43:33 +02:00
66035c3166 Gehweg-Messung: gepingt wird vom Core, nicht vom Laptop
Pingt der messende Laptop das Telefon an, laeuft der Weg ueber zwei
Funkstrecken -- Laptop -> AP -> Core -> AP -> Telefon. Fehlt dann ein Paket, ist
nicht entscheidbar, welches der beiden Geraete weg war, und genau diese
Trennschaerfe ist der ganze Zweck der Messung. Vom Core aus ist die Strecke bis
zum AP durchgehend Kabel.

Ausloeser war unfreiwillig: das MacBook ist mitten in einem Lauf vom Dock ans
WLAN gewechselt und hat dabei die IP gewechselt -- die Konsole war ploetzlich
nicht mehr erreichbar, und der Ping haette ab da zwei Funkstrecken gemessen.

Das Ping-Protokoll ist jetzt eine CSV (ts_local,seq,ms; leeres ms = Verlust), die
Auswertung liest beide Formate, damit die Laeufe von gestern lesbar bleiben.
RouterOS-Dauern kommen als "3ms441us" oder "529us" und werden entsprechend
geparst.

Eine Falle steckt im Skript-Kommentar: tr puffert blockweise, sobald die Ausgabe
in eine Pipe geht -- die ersten ~130 Zeilen haengen im Puffer und die Datei
bleibt scheinbar leer. Das \r kommt deshalb im Shell-Loop weg, nicht per tr.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 15:31:36 +02:00
41809fe43b Gehweg-Konsole: Raum-Buttons und Auswertung pro Raum
Die Gehweg-Messung erzeugte bisher eine Zeitachse, aus der niemand ablesen
konnte, WO es schlecht war -- der teure Abschnitt von gestern liegt bei
"15:07 bis 15:09", und das ist kein Satz, aus dem eine Massnahme folgt.

Die Konsole bekommt deshalb ein Raster mit einem Button je Raum; der aktive Raum
wird hervorgehoben und die Verweildauer mitgezaehlt. Die Liste steht per
TP25_ROOMS in der Umgebung, damit ein fehlender Raum kein Codeeingriff ist.

tp25-gehweg-auswertung.py verbindet die drei Mitschnitte -- Ping aufs Telefon,
Funkwerte vom Manager, Raum-Marken -- zu einer Tabelle mit Signal, Paketverlust
und laengster Luecke je Raum, samt AP, auf dem der Client dort haengt.

Dazu die Lehre aus dem ersten Durchgang, diesmal als Anleitung statt als Fussnote:
die Konsole gehoert waehrend der Messung auf DAS TELEFON. Der Wake Lock haelt das
Display an und das Polling das Geraet wach -- ohne das beantwortet ein iPhone die
Pings verzoegert oder gar nicht, und 44 % Verlust sind Ruhezustand statt Funk.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 15:23:43 +02:00
6cd41d5e9b TP25: Gehweg-Messung -- was eine WLAN-Uebergabe wirklich kostet
Die "~4 Sekunden je Wechsel" aus der Nachtmessung waren als Obergrenze markiert,
und die Vorsicht war berechtigt: 5 Pings/s auf das Telefon zeigen bei -48 bis
-55 dBm Uebergabekosten von 0 bis 2,6 s, meist unter einer halben Sekunde. Fast
Transition funktioniert. Der Zaehlerstand nach einer Neuanmeldung hatte die
Luecke vorgetaeuscht.

Der wahre Befund ist schlimmer und liegt woanders: bei -69 bis -77 dBm ist das
Telefon 6 bis 45 s nicht erreichbar, zweimal ueber 20 s am Stueck. Die Trennlinie
laeuft sauber entlang der Signalstaerke, nicht entlang der Wechsel -- es ist kein
Roaming-Problem, es ist ein Dead Spot.

Ehrlich dazu: ueber den ganzen Weg gingen 44 % der Pings verloren, und das ist
nicht alles Funk -- ein iPhone mit gesperrtem Display beantwortet ICMP verzoegert
oder gar nicht (RTT-Median 3,7 ms, Maximum 8,2 s). Power-Save haengt aber am
Display, nicht am Ort; dass alle langen Luecken in der schwachen Zone liegen und
alle kurzen in der starken, erklaert es nicht. Fuer eine exakte Zahl braucht es
ein waches Telefon.

tp6-monitor-core.sh bekommt eine Reconnect-Schleife: die SSH-Sitzung ist mitten
in der Messung weggebrochen und die Funkdaten endeten 2,5 Minuten vor dem
Ping-Mitschnitt -- ausgerechnet im interessanten Teil.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 15:15:56 +02:00
6262cd5b5d TP25: Gehweg-Messung -- was eine WLAN-Uebergabe wirklich kostet
Die Sampler-Daten zeigen bei jedem AP-/Bandwechsel ~4 s ohne Durchsatz, koennen
das aber nicht beweisen: nach einer Neuanmeldung starten die Zaehler der
Registration-Table ohnehin bei null. tp25-walk-messung.sh trennt beides, indem es
mit 5 Pings/s AUF das Telefon zielt -- Paketverlust ist echte Funkstille, kein
Verlust heisst, die 4 Sekunden waren Buchhaltung.

Laeuft ohne Call und ohne Last: Core-Sampler im 1-s-Takt plus der Ping, dazu eine
Anleitung auf der Klick-Konsole (Gehen/Stehen als Marker). Ein vorheriger Lauf
wird beiseitegelegt statt ueberschrieben.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 15:01:19 +02:00
cf44ce6a1e TP6 gemessen: Fall B, aber nicht hoerbar -- und der laute Befund liegt bei TP25
Die TP6-Praemisse ist ausgefuehrt: drei Messreihen von einem kabelgebundenen
Client in VLAN10, zwei davon mit laufendem Telegram-Videocall an zwei Orten.

Ergebnis (Runbook §5): unter Dauer-Upload steigt die Latenz von 13 auf 40--60 ms,
im Download auf 36--41 ms. Das sind +28 bis +47 ms und damit ueber der Schwelle
von 30 ms, die §3 VOR der Messung festgelegt hat -- formal Fall B, CAKE ist
begruendet. Die Einschraenkung gehoert zur Zahl: durch alle sechs Lastphasen lief
ein Videocall, und es wurde kein einziger Problem-Button gedrueckt. Messbar ja,
wahrnehmbar nein. waveform sagt zeitgleich Grade A -- kein Widerspruch, sondern
ein kuerzerer Test, dessen Upload-Verteilung zweigipflig ist (25. Perzentil
14,5 ms, 75. Perzentil 47,5 ms).

Erstmals dokumentiert: die tatsaechliche Linerate. Upload 9,6 Mbit, Download
54,6 Mbit. Die im Repo kolportierten "~10 Mbit" galten immer nur dem Upload.

Der lautere Befund ist ein Nebenprodukt: der Core-Sampler hat 2,5 Stunden lang
das iPhone mitgeschrieben. Sticky Client (ein Weg durchs ganze Haus, dreimal
direkt an ap1 vorbei, eine einzige Uebergabe -- und die erst oben bei -73 dBm)
und Band-Ping-Pong (zwoelf Wechsel in neun Minuten am selben Ort). Je Wechsel bis
zu 4 s ohne Durchsatz -- als Obergrenze notiert, denn die Zaehler starten nach
einer Neuanmeldung bei null; der saubere Test per ping auf das Telefon steht aus.
Das passiert TROTZ aktivem 802.11k/v und FT, live geprueft: damit ist die
Merkregel ref_ft_is_not_roaming historisch. Der Bandabstand von 8--10 dB ist
dabei normale Physik; das Problem ist, dass 5 GHz an den Telefonier-Orten bei
-75 bis -80 dBm landet.

Zwei Messfehler bleiben dokumentiert, weil sie die Methode betreffen und beide
denselben Typ haben -- die Anzeige war gruen, die Wirkung fehlte:
speed.cloudflare.com/__down antwortet ohne User-Agent mit 403 und einem Byte
(saubere Ping-Reihe ueber tote Flows), und ein Call lief 5,5 Minuten ohne
Treiber (Marker geschrieben, nichts gemessen).

Status nachgezogen -- Header inklusive: TP6 von "Praemisse pruefen" auf
"gemessen, Fall B, nachrangig", TP25 auf kritischen Pfad. Rohdaten liegen unter
docs/messdaten/tp6-20260820/, damit die Zahlen nachpruefbar bleiben.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 00:31:13 +02:00
3aac2eeb8a TP6 Durchlauf 2 messbar machen: Sampler, gefuehrte Konsole, Treiber
Durchlauf 1 ist gemessen (Ergebnis folgt separat im Runbook). Fuer den Durchlauf
mit laufendem Videocall brauchte es Werkzeug, das es noch nicht gab:

- tp6-monitor-core.sh haengt EINE persistente SSH-Sitzung an den Core und laesst
  dort eine Console-Schleife laufen, die im 2-s-Takt CPU, WAN-Rate und die
  Registration-Table-Werte eines WLAN-Clients als CSV ausgibt. Nur Lesezugriffe.
  Unter CAPsMAN fuehrt der Manager die Tabelle, deshalb wird der Core abgefragt
  und nicht ap1/ap2. Zwei RouterOS-Fallen sind im Code kommentiert: die Console
  parst eine per SSH uebergebene Mehrzeilen-Eingabe zeilenweise, und in der
  Einzeiler-Form braucht jeder do={}-Block ein abschliessendes Semikolon.

- tp6-marker/server.py ist die Konsole fuer die Person am Telefon: Phasenkarte
  mit Klartext-Anweisung, Countdown, Fortschritt, Marker-Buttons und Not-Aus,
  bedienbar vom iPad. Die Buttons sind server-seitig gerenderte Formulare und
  die Anleitung aktualisiert sich notfalls per meta-refresh -- auf dem iPad ist
  das JavaScript ausgefallen, uebrig blieb nur der eine statische Button.

- tp6-call-run.sh fuehrt Durchlauf 2 mit denselben Messparametern wie Durchlauf 1
  (3 Flows x 430 KB/s, 24 Pings, 30 s Settle) und ergaenzt Ruhephasen davor und
  danach, Phasenmarken, eine PID-Datei fuer den Not-Aus und einen Heartbeat.
  Der Heartbeat ist kein Detail: ohne ihn geht der Start-Klick still ins Leere,
  der Call laeuft ohne Last, und "keine Probleme" liest sich wie ein Ergebnis,
  obwohl es eine Nicht-Messung ist -- genau so passiert, 5,5 Minuten lang.

- tp6-auswertung.py schneidet die Sampler-CSV an den Phasenmarken auf und meldet
  neben min/avg/max auch die Ereignisse, die im Mittelwert untergehen: Roaming,
  Re-Assoc und Verschwinden des Clients.

- tp6-bufferbloat-messung.sh schickt jetzt User-Agent und Referer mit. Ohne die
  beantwortet speed.cloudflare.com /__down mit 403 und einem Byte: die Flows
  sind sofort tot, die Ping-Reihe sieht sauber aus, und die Download-Seite gilt
  faelschlich als bufferbloat-frei. Aufgefallen ist es nur, weil der Sampler am
  Core 164 kbit statt 50 Mbit zeigte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 22:51:11 +02:00
f3d8779c96 TP6-Messung ausfuehrbar machen: Skript + Anleitung fuer den Messenden
Das Messrunbook beschreibt die Methode, war aber nichts, das man jemandem in
die Hand druecken kann. Dazu jetzt zwei Artefakte:

- tp6-bufferbloat-messung.sh reproduziert die Methode von 2026-06-16
  (3 Flows Saettigung, 24 Pings idle/Last) und misst zusaetzlich die
  Download-Richtung, die damals nie gemessen wurde. Es prueft vorab die zwei
  Vorbedingungen, an denen die Messung sonst still scheitert: Default-Route
  ueber utun* = WARP-Verdacht, und mehr als eine 10.40er-Adresse = dual-homed.
  Beides nur als Warnung -- die definitive WARP-Kontrolle ist das
  Menueleisten-Icon, das kein Skript sehen kann.
  Es misst ausschliesslich und aendert nichts am Netz.

- tp6-messung-tutorial.md ist die Anleitung fuer die Person am Kabel (Geli),
  getrennt in den einfachen Browser-Weg und den exakten Skript-Weg. Das Warum
  bleibt im Runbook, hier steht nur das Machen.

Beide verweisen fuer die Auswertung auf tp6-praemisse-messrunbook.md §3/§5,
damit das Abbruchkriterium an genau einer Stelle steht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 10:49:05 +02:00
78eef95f12 Uebergabe fuer die TP6-Session + zwei fehlende Vorbedingungen im Messrunbook
Das Messrunbook verlangte einen kabelgebundenen VLAN10-Client, warnte aber
nicht vor WARP. Ein aktiver WARP-Client tunnelt alles durch Cloudflares
QUIC-Proxy -- gemessen waere der Tunnel statt der Leitung, und ICMP kaeme gar
nicht erst durch. Genau das ist hier schon zweimal passiert. Dazu die
Dual-Homing-Falle: das MacBook haelt zeitweise Leases in VLAN10 und VLAN20.
Beides steht jetzt als Vorbedingung vor Schritt 1, nicht als Fussnote.

Die Uebergabe traegt den live verifizierten Ist-Stand (92/92, 0 forward-Drops
heute), die fuer die Messung relevanten Randbedingungen -- Fasttrack ist
entschieden, /queue fehlt im Template, der Core ist ein 800-MHz-ARM -- und
was mit beiden moeglichen Ergebnissen zu tun ist.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 16:39:22 +02:00
1084f1978c Header von TP13/TP14.4/TP16.3 nachgezogen
Alle drei haben am 19. ein ausfuehrbares Runbook bekommen, trugen im Header
aber weiter "VORBEREITET (08-08)", "TODO" bzw. "Recherche durch, Umsetzung
offen". Dasselbe Muster, das heute schon TP3, TP3.3 und TP28 betroffen hat:
der neue Inhalt wird geschrieben, der Header bleibt stehen.

Die jeweils wichtigste Erkenntnis steht jetzt im Header-Vorspann, damit sie
nicht erst im Runbook gefunden werden muss -- bei TP13 vor allem der
Denkfehler "SSID ohne Security".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 16:34:28 +02:00
9a777a6d5c WLAN-Status: TP3/TP3.3-Header waren die eigentliche Drift-Quelle
Eine frische Session hat nach Core und CAPsMAN gefragt, weil die Datei sich
selbst widersprach. Ursache war nicht fehlende Information, sondern dass bei
Statuswechseln jeweils nur der neue Abschnitt geschrieben und der alte Header
stehengelassen wurde:

- TP3 trug im Header "beide hAP ax2 sind reine Standalone-APs, CAPsMAN
  abgeschafft", und sein Lesehinweis verwies als "Ist-Stand" auf den
  08-08-Eintrag. Wer die WLAN-Frage hatte, landete zuerst dort -- und bekam
  die falsche Antwort. TP3 ist jetzt als vollstaendig historisch markiert und
  verweist auf TP28.
- TP3.3 stand als "TODO (neue Session)", obwohl es seit 08-17 in TP25
  aufgegangen ist.
- TP28 selbst trug unter dem Header "KOMPLETT" noch einen Punkt "OFFEN -- das
  GC-Modell beschreibt weiter Standalone-APs" mit der stale Zahl 76/76. Das
  war mein Rest vom 18.: Header umgeschrieben, Punkte darunter nicht.
- Die Abnahme in doku-cleanup-session.md verlangte woertlich "kein CAPsMAN" --
  ein Kriterium, das den falschen Zielzustand beschreibt, bestaetigt genau die
  Session, die den ueberholten Stand wiedergibt.
- Dazu HW-Refresh-Zeile und die ft-over-ds-Notiz in TP25 nachgezogen.

Merkregel, die jetzt an drei Stellen im Dokument steht: bei einem Statuswechsel
nicht nur den Header umschreiben, sondern die Punkte darunter mitziehen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 16:28:06 +02:00
ff3c3a0ab3 Konsistenz nach TP5 E5: Kette, Header und CLAUDE.md nachgezogen
E5 war in teilprojekte.md beschrieben, aber an drei Stellen nicht
mitgezogen. Die Etappen-Kette im kritischen Pfad endete bei E4, der
TP5-Header trug "DURCH (2026-08-18)" -- E5 kam einen Tag spaeter -- und
CLAUDE.md nannte "IoT anlernen" weiter als Fall fuer jit-admin, obwohl
MAIN->IOT seit E5 dauerhaft offen steht.

Beim TP5-Header steht jetzt explizit, dass "DURCH" nicht "abgeschlossen"
heisst: unter deny-by-default braucht jeder neue Dienst ueber eine
VLAN-Grenze seine Regel, weitere Etappen sind Betrieb und kein
Rueckschritt. Sonst liest die naechste Session ein ✅ und wundert sich
ueber E6.

In CLAUDE.md steht jetzt, welche Paare dauerhaft offen sind (MAIN nach
INFRA/MEDIA/MGMT/IOT) und dass IOT->MAIN bewusst zu bleibt, plus die
SNMP-Merkregel: der Drucker faellt mit udp/161 auf, nicht mit 631 -- eine
Whitelist auf dem erwarteten Port haette nichts repariert.

Gegengeprueft: Compliance live 92/92, 0 Drifts; E5-Regel am Geraet aktiv
mit 100 Paketen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 16:21:58 +02:00
ef20616919 Doku-Rest: ip-plan, Aufraeum-Liste und Memories nachgezogen
ip-plan.md war als Statusdokument stale: ap1 stand als "Router/GW, ist GW,
kein Umzug" und sw1 als lebendes Geraet mit offenem Migrationsschritt.
Beides seit dem Core-Cutover falsch. Kopfblock mit der heutigen
Rollenverteilung davorgesetzt, die sechs betroffenen Zeilen nachgezogen --
die Planung von damals bleibt darunter lesbar, geloescht wurde nichts.

doku-cleanup-session.md: Punkt E geschlossen. Der Nachlauf haelt fest, dass
zwischen 16. und 19. zwei Runden Drift dazugekommen sind, und warum die
erste lehrreicher ist: nachgezogen wurden die TP-Abschnitte und CLAUDE.md,
stehen blieb ausgerechnet der Block, den eine frische Session zuerst liest.

Memories: project_tp3_ap_rebuild bekommt einen Superseded-Kopf (der Satz
"reine Standalone-APs, kein Manager/CAP" war bis 08-17 richtig), das
wifi-rebuild-Memory einen Hinweis, dass die CAPsMAN-Abschaffung inzwischen
selbst revidiert ist. In ref_nautobot_api_gotchas stand "kein CAPsMAN" als
Begruendung fuer den logischen Controller -- die Begruendung ist weg, der
Stand bleibt, und die Modellfrage ist jetzt als offen markiert statt still
falsch.

Neu: feedback_abnahme_wirkung_nicht_anzeige. Drei Fehlbefunde in einer
Nacht -- Registration-Table, Job-Status, 70-Sekunden-Zaehler -- hatten
dieselbe Ursache: gemessen wurde die Anzeige daneben, nicht die Wirkung am
Ziel. Der WLAN-Fall kostete 14 Stunden.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 16:04:20 +02:00
1eabd0434b TP5 E5: MAIN->IOT aufgemacht, Drucker und Shellys wieder erreichbar
Der Deny-by-default arbeitete korrekt — es gab nie eine vlan10->vlan30-Zeile.
Offen waren nur MAIN->MEDIA, MAIN->INFRA, MAIN->MGMT; IOT fehlte als einziges
Paar. Neue Regel voll einbahnig ohne Portfilter (User-Entscheid): MAIN steht zu
INFRA/MEDIA/MGMT ohnehin ungefiltert offen, und dort liegen NAS/Proxmox/Nautobot.
IOT->MAIN bleibt bewusst zu — dort sitzt der Wert der Segmentierung.

Merkregel aus dem Drop-Log: der Drucker faellt mit udp/161 auf, nicht mit 631.
macOS fragt zuerst den SNMP-Status ab und bricht ab, bevor es zu IPP kommt —
eine Whitelist auf 631 haette nichts repariert.

Abnahme von 10.40.10.82 (der Quelle aus dem Log): .30.5 ICMP 0% Loss,
snmpget sysName.0 -> P750W, tcp/631+9100+80 offen; Shellys .30.202/.203/.221
HTTP 200. Compliance 92/92, 0 Drifts. Seit dem Deploy keine neue
vlan10->vlan30-Zeile im Kollektor.

Nebenbei: gc-manual-plan.py --assert URL-encodet die Query jetzt. Ein Kommentar
mit Leerzeichen warf InvalidURL erst NACH dem erfolgreichen Deploy — man steht
mit einem Traceback da und weiss nicht, ob der Change gewirkt hat.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 16:02:29 +02:00
777ac95c3f TP13: Technikteil war seit TP28 falsch, plus ein Denkfehler
Zwei Sachen standen in TP13, die so nicht stimmen.

Erstens beschrieb der Technikteil noch Standalone-APs und wollte die
Beacon-SSIDs in ap{1,2}-prov-base.rsc ergaenzen. Seit dem CAPsMAN-Cutover
entstehen SSIDs am Manager auf dem Core -- was fuer TP13 sogar einfacher
ist, ein Deploy statt zwei.

Zweitens der eigentliche Fund: der Entwurf wollte "nur ssid=, kein
Security" und begruendete das damit, dass Namens-SSIDs ohne offenen Zugang
rechtlich unkritisch seien. Eine SSID ohne Security IST aber ein offenes
WLAN, also genau der Fall, den der Rechtsvorbehalt ausschliessen will.
Richtig ist ein PSK, den niemand kennt: beacont den Namen, niemand kommt
rein. Kostet nichts.

Dazu die Datapath-Falle: ein Slave-VAP ohne explizite vlan-id am Manager
landet ungetaggt in der Bridge, weil der CAP vom Manager-Datapath nur die
vlan-id uebernimmt. Gleiche Mechanik wie der 14-h-Ausfall. Die
Botschafts-SSID braucht deshalb beides -- PSK und toten Datapath.

VAP-Budget am Geraet nachgesehen statt geschaetzt: max-interfaces=16 je
Radio, belegt sind 4 bzw. 5. Die Zahl ist also nicht die Grenze, Airtime
ist es -- jeder VAP beacont eigenstaendig. Empfehlung steht im Runbook.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 16:00:15 +02:00
914ff980b5 TP16.3 und TP14.4 als ausfuehrbare Runbooks
Beide TPs waren "Recherche durch / Umsetzung offen" bzw. "TODO" -- also
jeweils eine Zeile, aus der eine frische Session nicht losarbeiten kann.

TP16.3: der Schnitt (nautobot aus dem bf-nas-Ingress) ausformuliert, mit
Vorbedingungen, PUT-Ablauf und Rollback. Zwei Dinge stehen jetzt explizit
drin, die den TP sonst kippen: Mesh-Hostname-Routes sind Egress und
veroeffentlichen nichts -- wer das verwechselt, baut den Public-Strang ab;
und Nautobot ist nicht nur eine Web-UI, sondern die Deploy-Pipeline, also
gehoert ein Job-Lauf zur Abnahme und nicht nur ein Browser-Aufruf.

TP14.4: Ist-Stand nachgesehen -- in mcp/cloudflare/.env stehen weder
CF_ACCESS_CLIENT_ID noch _SECRET, es ist also nichts halb erledigt. Das
Secret gibt es nur im Moment der Rotation, das steht jetzt als Warnung
davor. Abnahme braucht beide Faelle: mit Headern antwortet, ohne 403 --
sonst haette ein bypass-Hostname wie vw als Erfolg durchgehen koennen.

Kein CF-Write, kein Token rotiert. Beides bleibt Papier.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 15:58:06 +02:00
8b7ca8ddef TP6-Praemisse: Messrunbook + Fasttrack entschieden
Der kritische Pfad widersprach sich selbst: der Einleitungsabsatz sagte seit
dem 18. "Praemisse offen, erst messen", Punkt 2 der Liste darunter sagte
weiter "keine offenen Blocker mehr". Punkt 2 nachgezogen.

Neu: docs/tp6-praemisse-messrunbook.md. Reproduziert die Methode von
2026-06-16 (3 Flows Saettigung + 24 Pings idle/Last), damit die Zahlen
vergleichbar sind, und misst erstmals die Download-Richtung -- die wurde
damals nie gemessen und ist beim asymmetrischen Kabelanschluss die
wahrscheinlichere Problemseite. Das Abbruchkriterium steht VOR der Messung:
A/A+ heisst TP6 wird geschlossen statt gebaut.

Fasttrack (die Entscheidung, die der Handoff Christoph vorbehalten hat):
bleibt wie er ist, gilt ab jetzt aber als Absicht statt als Unfall. Bei
~10 Mbit WAN kostet der Verzicht nichts, fuer CAKE ist er sogar die
bequemere Ausgangslage. Gegenbedingung notiert: wer Inter-VLAN je auf
Gigabit will, muss vorher messen, was die Core-CPU ohne Fasttrack traegt.

Damit sind zwei offene Stellen zu -- das "Entscheidung noetig" in TP6 und
die TP21-Warnung, dass das Re-Baseline den Zustand zum Soll erklaert hat.
Die Merkregel dort bleibt: dass es diesmal gut ausging, war Glueck.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 15:56:22 +02:00
9fdfb06c1c Uebergabe korrigiert: der AP-Cleanup war falsch abgenommen
Ich hatte "30 Clients vorher, 30 nachher, kein Aussetzer" attestiert. Genau
diese Zahl hat einen laufenden Ausfall verdeckt: seit dem CAPsMAN-Cutover vom
17. war slaves-datapath auf beiden APs leer, IOT/MEDIA/UNTRUSTED/GUEST hingen
in keiner Bridge, Clients assoziierten und bekamen nie DHCP -- 14 Stunden.
Die Registration-Table zeigte derweil zufriedene Clients.

Abnahme fuer WLAN-Umbauten ist eine frische DHCP-Lease pro SSID, nicht die
Registration-Table. In der Uebergabe nachgetragen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 13:34:40 +02:00
0ec812c68e Doku-Drift beheben: Ist-Stand-Block, TP26/TP27, Fasttrack-Befund, Uebergabe
Eine parallele Session hat drei Befunde gemeldet, alle drei richtig. Sie sind
hier abgearbeitet.

1) Der "Ist-Stand (Kurz)"-Block war an vier Stellen ueberholt: Standalone-APs
   statt CAPsMAN, RouterOS 7.19.5/7.23 statt 7.24, "plain 1.1.1.1" statt DoH,
   68/68 statt 92/92. In der Nacht wurden die TP-Abschnitte und CLAUDE.md
   nachgezogen, aber ausgerechnet der Block, den eine frische Session zuerst
   liest, blieb stehen.

2) TP26 und TP27 existierten nur als Commits und .rsc-Dateien, ohne Abschnitt.
   Beide nachgetragen. TP27 (RouterBOOT 7.24) ist auf allen vier Geraeten
   abgeschlossen -- current-firmware = upgrade-firmware = 7.24, geprueft.

3) Fasttrack ist auf dem Core tot: 32,9 Mio Pakete auf der accept-Regel davor,
   0 auf Fasttrack, 0 von 445 Verbindungen fasttracked. Herkunft ist der
   Core-Cutover (ap1 hatte die Reihenfolge richtig). Und das Re-Baseline vom
   18. hat den Fehler als Absicht in die SoT geschrieben -- die Kehrseite von
   ingest-core-firewall.py, jetzt als Warnung in TP21.

Dazu: die TP6-Praemisse wackelt. call-quality-diagnosis.md misst A/A+ und
haelt CAKE fuer marginal; TP6 wird trotzdem als "DAS Ziel" gefuehrt. Naechster
Schritt ist deshalb eine Messung gegen den heutigen Edge, nicht eine Queue.

Uebergabe fuer die Doku-Session: docs/handoff-doku-session-20260818.md

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 13:33:24 +02:00
c2fdcb8efd Reboot-Abnahme ap2: slaves-datapath und CAPWAP ueberstehen den Neustart
ap2 durchgestartet, nach 40 s wieder da. slaves-datapath=dp-caps-slaves
steht noch, der CAP findet crs326-core durch die gehaertete input-Kette
wieder (MNDP/CAPWAP korrekt offen — seit TP5 Etappe 4 nie getestet), die
sieben Slave-VAPs kommen als dynamische Bridge-Ports mit pvid 30/40/50/90
von selbst zurueck. Abnahme per frischer Lease: IOT 10.40.30.8 nach 30 s.

Nebenbefund: /system reboot ist ueber MikroMCP auf 7.24 nicht machbar
(Tool sendet unbekanntes delay, run_command per Deny-Policy gesperrt).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 09:43:15 +02:00
9c31e62275 GC-Soll nachgezogen: 92/92 compliant, 0 Drifts
Template ueber push-gc-template.py nach bf-golden-config gepusht,
GitRepository-Sync, dann Backup -> Intended -> Compliance. Der erste
Sync-Versuch starb an einem redis broken pipe im Nautobot-Stack; Retry
ging durch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 09:19:18 +02:00
1ba82608f2 CAPsMAN: slaves-datapath fehlte, IOT+MEDIA lagen 14h
Seit dem CAPsMAN-Cutover (2026-08-17) war `/interface wifi cap
slaves-datapath` auf ap1 und ap2 leer. Das ist das einzige Feld, das die
vom Manager erzeugten Slave-VAPs lokal in die Bridge haengt: der Core
schickt `datapath.bridge=bridge` zwar mit, der CAP uebernimmt davon aber
nur die vlan-id. Ergebnis: -iot, -media, -untrusted und -guest hingen in
gar keiner Bridge — Clients assoziierten sauber und bekamen nie DHCP.
`dirtyvader-main` lief weiter, weil wifi1/wifi2 statische Bridge-Ports
sind; genau das hat den Ausfall getarnt.

Fix live auf beiden APs: dp-caps-slaves (bridge=bridge, bewusst ohne
vlan-id) + slaves-datapath darauf. Die VAPs stehen seither als dynamische
Bridge-Ports mit pvid 30/40/50/90 in der Bridge.

Nicht die TP5-Haertung: torch auf vlan30 am Core leer UND kein einziger
DHCP-Eintrag im Drop-Log — es wurde nichts verworfen, es kam nichts an.

tp28-ap-wifi-reste-abraeumen.rsc hat den Ausfall nicht ausgeloest, aber
zementiert: mit den geloeschten datapath-Objekten gab es lokal nichts
mehr, worauf slaves-datapath haette zeigen koennen.

Die TP28-Abnahme "ohne jeden Aussetzer" ist korrigiert — sie zaehlte
Registrations, also genau die Metrik, die hier luegt. Abnahmekriterium
fuer WLAN-Umbauten ist ab jetzt eine frische DHCP-Lease pro SSID.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 09:13:26 +02:00
c709c9da6b NTP-Governance, SSDP-Relay live, WLAN-Config zurueck unter Drift-Kontrolle
92/92 compliant, 0 Drifts (vorher 71/76 bei 19 Rules -- jetzt 23 Rules).

NTP: die Wurzel war doppelt. Der Core hatte keinen eigenen Client, UND sein
Server hielt Stratum 16 fest, weil er eingeschaltet wurde, bevor der Client
synchron war. Der Test, der es aufgeklaert hat: branch einmal auf
at.pool.ntp.org zeigen lassen -- 20 Sekunden bis synchronized, also war der
Client heil und der Server schwieg. Jetzt im Template, per DHCP-Option 42 an
alle Clients ausgeliefert und mit der Rule system-ntp ueberwacht.

TP7.1: SSDP-Relay laeuft als LXC 108 auf pve, zweibeinig in VLAN10+40.
User-bestaetigt: "sonos ist da!". core ether13 traegt dafuer jetzt beide VLANs.

TP28: die APs trugen noch die komplette Standalone-WLAN-Config aus TP3 --
wirkungslos, aber sie haette als Soll totes Zeug zur Absicht erklaert.
Abgeraeumt, ohne einen einzigen Client zu verlieren (30 vorher, 30 nachher).
Die fuenf wifi-*-Features haengen jetzt am Core, dazu drei neue Rules
(wifi-capsman, wifi-provisioning, wifi-cap).

Gelernt: [find !dynamic] ist auf /interface wifi configuration ein
SYNTAXFEHLER, kein Filter -- der erste Anlauf aenderte nichts und meldete
trotzdem "Plan Completed".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 06:04:28 +02:00
5cc62b29c1 NTP: Wurzel war der Core selbst, plus eine fehlende Compliance-Rule
Der Core hatte keinen eigenen NTP-Client bei use-local-clock=no. Ein Server
ohne Synchronisation liefert Stratum 16, das jeder Client verwirft -- die
Anfragen kamen an und wurden trotzdem nicht brauchbar beantwortet. Der
Standort hatte an keiner Stelle eine funktionierende Zeitsynchronisation.

Notiert ist auch, dass /system ntp gar keine Compliance-Rule hat -- derselbe
blinde Fleck, den TP26 fuer /ip firewall filter geschlossen hat.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 05:28:06 +02:00
600ad9d669 TP5 abgeschlossen, TP19 + TP3.2 geschlossen, TP23 Stufe 1 dokumentiert
TP5 ist durch: deny-by-default steht in forward UND input. Der kritische Pfad
besteht damit nur noch aus TP6 (CAKE).

Drei Funde, die den Drop sonst zum Ausfall gemacht haetten und die im
70-Sekunden-Fenster von Etappe 2 unsichtbar waren:
- der Netmiko-Deploy kommt von nautobot-worker (.20.31), nicht vom
  Web-Container (.20.30) -- der Drop haette den GC-Pfad selbst gekappt
- Matter laeuft ueber udp/5540, die IOT->INFRA-Regel war TCP-only
- die CAPs finden ihren Manager per Layer-2-Discovery (MAC, keine IP);
  der input-Drop verwarf MNDP, kaputt gewesen waere es erst beim naechsten
  AP-Reboot

TP19 geschlossen: VLAN1-ARP = 0, Prometheus ohne .41.x-Ziele, ap2-Kruecke weg.
Die zwei Reste sind dorthin verschoben, wo sie hingehoeren (tote CF-Tunnel
-> TP16, HA-Portainer setup_retry -> TP11), statt den TP offen zu halten.

Nebenbefund und behoben: der Standort hatte keine funktionierende Zeitquelle
(alle zeigten auf 10.40.99.1, wo kein NTP-Server lief; ap2 war 17 h versetzt).

TP21: der Nautobot-Stack hat sich zweimal selbst umgebracht -- Ursache war der
Image-Healthcheck (voller Django-Start alle 10 s, Aufrufe stapeln sich), nicht
Celery. Dazu zwei echte Template-Fehler: /ip service heisst seit 7.23
available-from, und hw-offload gehoert in die SKIP-Liste. 71/76 compliant.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 05:20:09 +02:00
b93514a045 RouterBOOT-Klickanleitung + TP5 E3/E4 abgenommen, NTP-Zeitquelle, Template-Fixes
docs/routerboot-firmware-klickanleitung.md: Schritt-fuer-Schritt fuer WinBox.
RouterOS ist auf allen vier bereits 7.24, nur der Bootloader haengt zurueck
(core/branch 7.19.5, ap1/ap2 7.23.2 -- live erhoben). Der Weg geht per Hand,
weil `/system routerboard upgrade` interaktiv nachfragt: MikroMCP blockt ihn per
Deny-Policy, und Netmiko bekommt den Prompt statt einer Antwort und quittiert mit
E3001 bei LEERER Fehlermeldung. Auf core/branch waere ein Scheduler-Umweg
moeglich, auf den APs nicht (device-mode=home sperrt ihn).
Reihenfolge ap1 -> ap2 -> core -> branch mit Ausfall je Geraet; branch zuletzt,
weil der Arbeitsplatz per Kabel daran haengt. Dazu Gegenprobe-Einzeiler fuer alle
vier und die Falle, dass ohne Schritt 7 (Reboot) `Current Firmware` alt bleibt.

Aus der Parallelsession dazugekommen:
- TP5 Etappe 3 UND 4 sind abgenommen, beide Auto-Reverts abbestellt. Die
  Abnahmen stehen in den Skriptkoepfen: forward-Drop hat in der Testphase 11
  Pakete gefressen, ausschliesslich die eigene pve->branch:22-Sonde; beim
  input-Drop war es reines Broadcast-Rauschen (NetBIOS, SSDP). Der GC-Deploy-Pfad
  wurde als Pfadbeweis mitgetestet (nautobot-worker -> ap2:22 = SUCCESS).
- E4-Nachtrag: MNDP und CAPWAP muessen in den input. Die CAPs finden ihren
  Manager per Layer-2-Discovery (`current-caps-man-address` ist eine MAC, keine
  IP) -- bestehende Sitzungen laufen ueber seal-est weiter, der Bruch schluege
  also erst beim naechsten AP- oder Manager-Neustart zu.
- TP19 NTP: alle drei Nicht-Core-Geraete fragten einen Zeitserver, den es nicht
  gab (`status=waiting`, branch hatte gar keinen). ap2 war 17 Stunden nach und
  hat einen Logeintrag von 04:57 als 12:19 gestempelt -- geraeteuebergreifende
  Korrelation war damit wertlos. Core wird Zeitquelle, die drei werden Clients.
- Template: `/ip service` exportiert `available-from=`, nicht `address=`. Das
  Soll war falsch und das Geraet hatte recht -- vier Dauer-Drifts. Und
  `hw-offload` fliegt aus dem Firewall-Renderer, weil REST es meldet und
  /export es weglaesst.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 05:15:28 +02:00
7cd31df1ee TP5 Etappe 4 vorbereitet (input haerten, MGMT isolieren, JIT-Gruppe)
Vorbereitet, NICHT ausgerollt: 0 TP5-E4-Regeln am Geraet, seal-lan weiter
aktiv, kein input-Drop.

Der riskantere Teil, riskanter als der forward-Drop: der Core ist DNS- und
DHCP-Server fuer alle sieben VLANs, und beides ist input-Verkehr, der heute
allein von TP10-seal-lan durchgewunken wird. seal-lan naiv auf vlan10 zu
verengen nimmt in derselben Sekunde jedem anderen VLAN DHCP und DNS. Das
Skript geht deshalb strikt: Ersatzregeln (dns udp+tcp, dhcp, MAIN, HA:8728,
Nautobot-ssh, cf-mesh) zuerst, dann seal-lan disabled, dann Log, dann Drop.
Auto-Revert steht als Schritt 0 und setzt BEIDE Schnitte zurueck.

Zwei am Geraet gepruefte Voraussetzungen sind darin festgehalten: /system ntp
server ist disabled, es braucht also keine udp/123-Regel; und HA pollt den
Core selbst auf 8728 als INPUT -- die forward-Regel aus Etappe 2 deckt das
nicht ab. Dazu die JIT-Admin-Gruppe aus D3: Dauerregel mit leerer Liste, die
nichts oeffnet, bis sich jemand mit timeout eintraegt.

Nachtrag zum vorigen Commit da452ce: der dort als "vorbereitet" beschriebene
Etappe-3-Drop ist inzwischen ausgerollt und greift (5 Pakete). Der
tp5autorevert-Scheduler laeuft und wuerde ihn um 05:02:29 wieder abschalten --
wer ihn behalten will, muss den Scheduler vorher entfernen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 04:53:35 +02:00
da452ce1f3 TP23 Stufe 1 (DoH) + TP5 Etappe-2-Nachtrag ausgerollt, Etappe-3-Drop vorbereitet
Drei Skripte aus der Folgesession. Stand am Geraet zum Commit-Zeitpunkt
(per REST gegengeprueft, nicht aus den Dateikoepfen abgeschrieben):

- tp23-stufe1-doh-core.rsc  -> LIVE. use-doh-server auf den
  Cloudflare-Gateway-Resolver, verify-doh-cert=true. Nur der GTS Root R4
  importiert statt eines Bundles: der Core hat ~2,8 MB freien Flash, und die
  Kette endet nachweislich dort. Der Root wurde per SFTP hochgeladen, nicht
  per fetch geholt -- fetch haette check-certificate=no gebraucht und damit
  genau die Pruefung ausgehebelt, die hier aufgebaut wird.
  Schliesst zugleich TP21.1 TODO 1.

- tp5-etappe2-nachtrag.rsc  -> LIVE. 17 TP5-E2-Whitelists (11 + 6).
  Vier Luecken, die der Kollektor ueber dreieinhalb Stunden gezeigt hat:
  Matter (udp/5540, 92 der 119 Zeilen -- die E2-Regel war protocol=tcp und
  liess Matter komplett durchfallen), der Nautobot-Deploy-Pfad (kommt von
  .20.31 = worker, nicht von .20.30 = web; jetzt als address-list, weil der
  scheduler dieselben Jobs faehrt), und zwei Rueckwege aus abgelaufenen
  Conntrack-Eintraegen. Dazu eine Vorratsregel fuer AdGuard, damit das
  spaetere DNS-Umstellen ein reiner DHCP-Change bleibt.

  Korrigiert meine Aussage vom Vortag: "die Log-Regel ist verstummt" beruhte
  auf einem 70-Sekunden-Fenster und war so nicht haltbar. Genau deshalb
  verlangt das Runbook ein mehrtaegiges Fenster.

- tp5-etappe3-drop.rsc  -> VORBEREITET, NICHT AUSGEROLLT. Kein Drop und kein
  Scheduler auf dem Geraet. Der Auto-Revert steht im Skript bewusst VOR dem
  Drop, sonst gibt es ein Fenster ohne Sicherung; der Drop kommt HINTER die
  Log-Regel, damit der Kollektor weiter sieht, was gefressen wird.

Gate fuer Etappe 3: die Log-Regel steht aktuell auf 0 Paketen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 04:52:40 +02:00
5fd8d4edb1 TP28 dokumentiert: CAPsMAN-Cutover durch, zwei Messfallen festgehalten
Der Cutover ist durch (34 Clients, iot=27, beide CAPs Ok, Roaming belegt).
Festgehalten sind vor allem die zwei Fallen, die mich Zeit und Christoph das
halbe IoT-Netz gekostet haben:

1. Unter CAPsMAN fuehrt der MANAGER die registration-table und die
   wireless-Logs, nicht der CAP. Auf ap1/ap2 sind beide leer, obwohl das WLAN
   laeuft — ich habe daraus zweimal faelschlich 'WLAN ist unten' geschlossen.

2. Drei uebereinstimmende .rsc-Dateien sind nicht drei Belege, wenn sie aus
   demselben Bring-up stammen. Genau daran habe ich wlan-psks.env fuer
   veraltet gehalten und ueberschrieben. Die Passphrasen sind am Geraet per
   REST lesbar — das ist der Weg, nicht der Dateivergleich.

Offen: das GC-Modell beschreibt weiter Standalone-APs; die 76/76 ist stale
(13:55 gemessen, Cutover 18:05). wifi-*-Features muessen auf den Core.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 18:41:57 +02:00
8945f9ef53 TP28: WLAN laeuft ueber CAPsMAN auf crs326-core — beide APs sind reine CAPs
Der Methodenwechsel ist vollzogen. Beide hAP ax2 sind CAPs, die gesamte
WLAN-Konfiguration liegt auf dem Core: 4 Kanaele, 6 Datapaths, 6 Security,
2 Steering, 9 Configurations, 4 Provisioning-Regeln je radio-mac.

Warum es diesmal traegt, obwohl CAPsMAN 2026-07-22 abgeschafft wurde: damals
war ap1 Manager UND AP, und ein Manager kann seine eigenen Radios nicht per
CAPsMAN provisionieren — genau diese Asymmetrie war die Ursache von TP3.1.
Mit dem Core als Manager sind beide APs symmetrisch. Der Core braucht dafuer
kein wifi-qcom: das capsman-Menue steckt im Basis-routeros, die 3,35 MB
freier Flash sind irrelevant.

Verifiziert am Geraet: beide remote-caps "Ok", alle 7 dynamischen VAPs je AP
mit korrekter SSID und VLAN, Kanaele exakt wie in TP25 gemessen (ap1
5180/ax/Ce/I + 2412/ax, ap2 5220/ax/Ce/I + 2462/ax), Bridge-Ports mit
richtigen PVIDs. "traffic processing on CAP" bestaetigt Local-Forwarding —
im neuen /interface/wifi gibt es ohnehin kein zentrales Forwarding mehr,
die datapath-Property existiert deshalb nicht.

ft-over-ds=yes ist jetzt aktiv (unter CAPsMAN erstmals verfuegbar), und
dirtyvader-guest hat eigenes Steering mit neighbor-group=bf-guest — nicht
bf-main mitbenutzt, sonst meldet 802.11k Gast-Clients BSSIDs einer SSID,
auf die sie nicht assoziieren koennen.

🔴 routeros/.secrets/wlan-psks.env war fuer infra/iot/untrusted VERALTET.
Die laufenden PSKs standen in ap1-prov-base.rsc. Mit den Datei-Werten
konnten die Shellys sich nicht mehr anmelden. Datei auf den laufenden Stand
korrigiert, PSKs auf dem Manager nachgezogen. Wer die Datei blind als
Wahrheit nimmt, sperrt das halbe IoT-Netz aus.

🔴 Eigener Messfehler, festhalten: /interface/wifi/registration-table auf dem
CAP zeigt unter CAPsMAN NICHTS. Die Registrierungen fuehrt der MANAGER.
Ich habe daraus faelschlich "WLAN ist unten" geschlossen, waehrend Christophs
Geraete mit vollem Ausschlag verbunden waren. Ab jetzt nur noch am Manager
zaehlen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 18:25:25 +02:00
2103774d1a TP26: /ip firewall filter ist drift-ueberwacht — 76/76, TP5 Etappe 3 entblockt
Bis heute gab es nur ip-firewall-nat. "72/72 compliant" sagte ueber die
Firewall gar nichts — und TP5 Etappe 3 wollte dort einen Deny-by-default
setzen, der dann als einzige Regel im Netz unbeobachtet gewesen waere.

Umsetzung datengetrieben statt als Templatezeilen: die 36 Regeln liegen in
local_config_context_data.firewall_filter, das Template rendert sie nur.
36 Regeln fest ins Jinja zu schreiben hiesse, dass jede TP5-Etappe einen
Template-Edit braucht — genau die Reibung, wegen der die Governance in
Verruf geraten ist. Neue Regel = ein Listeneintrag.

ingest-core-firewall.py ist ein RE-BASELINE-Werkzeug, kein Sync: es erklaert
den Ist-Stand zum Soll und macht blind ausgefuehrt die Drift-Erkennung
wertlos. Darum nur nach einer bewusst verifizierten Aenderung laufen lassen.

Drei Formatfallen beim Nachbau des /export-Formats, alle durch Vergleich mit
dem echten Geraete-Export bzw. durch die neue Rule selbst gefunden:
- REST liefert Booleans als STRINGS. `if rule.get("dynamic")` ist fuer
  "false" wahr und filterte erst alle 36 Regeln weg (0 statt 36).
- REST sagt hw-offload=true, /export schreibt yes. Und "!" bzw. Kommas
  werden NICHT gequotet (connection-nat-state=!dstnat, dst-port=8123,1883).
  Quoting nur bei Leerzeichen.
- /export laesst Default-Werte weg: `disabled=no` steht nie drin,
  `disabled=yes` dagegen schon. Das schlug beim ersten Lauf der neuen Rule
  als 75/76 auf — die Rule hat ihren Zweck damit sofort erfuellt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 15:55:57 +02:00
b1ddd3574d TP26: defconf-Firewall auf beiden APs abgeraeumt — --assert hat zwei Fehlschlaege gefangen
11 statische Werksregeln je AP entfernt (input-seal, fasttrack, ipsec, sogar
"accept to local loopback (for CAPsMAN)"). Ein reiner AP routet nicht; die
Regeln waren inert. Mgmt haengt an /ip service (TP16.1), nicht an der
input-Kette — kein Lockout-Risiko. ap2 danach: 2 Radios running, 7 Clients.

Der eigentliche Wert dieser Session steckt in den zwei Fehlschlaegen davor,
die --assert bei seinem ERSTEN echten Einsatz gefangen hat. Beide meldeten
"Plan-Status: Completed":

1. `remove [find]` erfasst die DYNAMISCHE Fasttrack-Dummy-Regel mit. RouterOS
   verweigert deren Entfernung, das ganze Kommando wirft, es wird NICHTS
   entfernt. Log: "tp26: remove warf".

2. Der naheliegende Fix `[find !dynamic]` ist ein SYNTAXFEHLER — korrekt ist
   `[find where !dynamic]`. Und Syntaxfehler schlagen beim Parsen zu:
   `:do {} on-error={}` faengt sie NICHT, der Handler laeuft nie. Symptom
   deshalb besonders tueckisch — kein Fehler im Log, keine Wirkung,
   Plan "Completed". Merkregel: on-error schuetzt vor Laufzeitfehlern,
   nicht vor Tippfehlern.

Ohne --assert waeren beide unbemerkt geblieben. Genau der Fehlermodus, den
Christoph mit "einstellungen werden nicht uebernommen, dir faellt das nicht
mal auf" benannt hat.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 15:48:23 +02:00
2f102b48de gc-manual-plan: --assert prueft die Wirkung am Geraet, nicht den Plan-Status
"Plan-Status: Completed" sagt nur, dass die Zeilen abgesetzt wurden. Am
2026-08-17 blieb ein `/interface/wifi/set ... !channel` wirkungslos ohne zu
werfen, und das Selbstprotokoll meldete trotzdem Erfolg — weil es das Profil
las, waehrend der Interface-Inline-Override gewann. Die Abnahme haengt seither
daran, dass jemand daran denkt nachzusehen. Das ist kein Mechanismus.

--assert prueft nach dem Deploy per RouterOS-REST am Geraet und bricht laut ab:

  --assert '/ip/firewall/filter|count=0'
  --assert '/interface/wifi?name=wifi1|channel.width=20/40mhz'
  --assert 'cmd:/interface/wifi/monitor?numbers=wifi1&once=|channel=5180/ax/Ce/I'

Format [cmd:]<pfad>[?query]|<feld-oder-count>=<erwartet>, mehrfach angebbar.
GET fuers Lesen, cmd: fuer POST-Kommandos wie monitor. Trenner ist |, nicht :,
weil MAC-Adressen in Werten Doppelpunkte haben.

Dokumentierte Regel dazu: bei Funkaenderungen muss die Assertion monitor lesen,
NIE das Profil — print detail zeigt aufgeloeste Werte, export die rohen, nur
monitor das, was auf der Luft ist. Genau diese Verwechslung war der Fehler.

Mgmt-IP kommt aus Nautobot (primary_ip4) statt hartkodiert. Passwoerter aus
$ENV, sonst aus ~/.secrets/credentials.env — mit eigenem KEY=VALUE-Parser, weil
die Datei WireGuard-[Interface]-Bloecke enthaelt, an denen `set -a; . datei` in
zsh still abbricht und alle Zeilen danach verschluckt. Fehlerausgaben
redacten das Passwort.

Getestet: count-GET, field-GET mit Query, monitor-POST (inkl. tx-power=18) und
der Fehlerfall, der korrekt abbricht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 15:44:13 +02:00
23c63d435d TP25: dirtyvader-infra offline, Firewall-Filter-Compliance vermessen
-infra auf beiden APs und beiden Baendern disabled (User-Entscheid). Am Geraet
gegengeprueft: aktive-vaps 11 -> 9, w2infra/w5infra disabled=true auf ap1+ap2.
sec-/dp-/cfg-infra bleiben stehen, die Zone ist ohne Neuaufbau reaktivierbar.

Zur Rueckfrage "hidden statt disabled?": Verstecken spart KEINE Airtime. Eine
versteckte SSID sendet ihr Beacon weiter, sie laesst nur das SSID-Feld leer.
Airtime spart ausschliesslich das Abschalten der VAP.

Reconnaissance fuer die /ip firewall filter Compliance-Rule: core 25 Regeln,
branch 0, ap1+ap2 je 12 defconf-Reste (inert, inkl. "accept to local loopback
(for CAPsMAN)"). Zwei Entscheidungen vor dem Template-Bau festgehalten —
AP-Defconf abraeumen vs. als Soll schreiben, und branch als leer rendern.
Ohne die meldet die Rule sofort flaechendeckend Drift.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 15:14:40 +02:00
77553c94af TP25: Drift-Luecke geschlossen (72/72) — und zwei fehlende Compliance-Sektionen aufgedeckt
Die neuen Funkparameter stehen jetzt in der SoT, nicht nur auf dem Geraet:
radios[5g].width 20/40/80mhz -> 20/40mhz, DEVICE_CHANNELS[ap2][5g] 149 -> 44.
Config-Context gepatcht, dann Backup -> Intended -> Compliance: 72/72, keine
Drifts. Ein kuenftiger Deploy kann die Fixes damit nicht zurueckdrehen.

Bemerkenswert: width fuer 2,4 GHz stand im Config-Context die ganze Zeit
korrekt auf 20mhz. Die SoT war richtig, das Geraet hat sie nicht befolgt —
der Beweis, dass das Problem der Inline-Override war und nicht die Datenlage.

Beim Nachpruefen, ob "72/72" die Funkparameter ueberhaupt abdeckt, sind zwei
Luecken aufgefallen (18 Compliance-Rules abgefragt):

- /interface wifi (Interface-Sektion) hat KEINE Rule. Die fuenf wifi-*-Features
  decken nur die Profilobjekte ab. Die Inline-Overrides leben in der
  Interface-Sektion — deshalb blieben Fund A und D seit 2026-08-08 unentdeckt,
  waehrend die Flotte durchgehend "compliant" meldete.

- /ip firewall filter hat KEINE Rule, es gibt nur ip-firewall-nat. Die
  TP5-Zeile "laeuft ueber ip-firewall-*-Features aus TP22" war damit
  irreführend. Die 11 Etappe-2-Regeln und der kommende Deny-by-default sind
  nicht drift-ueberwacht; "72/72" sagt ueber die Firewall nichts aus.
  -> als Vorbedingung fuer TP5 Etappe 3 eingetragen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 15:01:00 +02:00
14aa4f3142 TP5 Etappe 2 ausgerollt + TP25/TP16.3 angelegt, TP25 Schritte 1-3 durch
TP5 Etappe 2: 11 Whitelist-Regeln auf crs326-core, abgeleitet aus 43.027
Logzeilen (21 h) statt geraten. D1 = MAIN->INFRA pauschal, D4 = MGMT named
sources (HA:8728, Nautobot:22, MAIN, cf-mesh), D5 = 8123 + MQTT.
Log-Regel ist im Moment des Deploys verstummt; Zaehler steht. Etappe 3 bleibt
gated auf ein mehrtaegiges stilles Fenster + D2 (iPhone aus dem IOT-SSID).

TP25 neu — WLAN-Stabilisierung, Sammel-TP fuer Christophs Beobachtungen 1-6.
Schritte 1-3 durch, alles am Geraet gegengeprueft:
- w2-iot trug einen channel.*-Override auf einem Slave-VAP (auf ap1 sogar
  2ghz-n gegen einen 2ghz-ax-Master) -> Mechanismus hinter "-iot mal da,
  mal nicht". Danach auf beiden APs BR/running.
- 2,4 GHz lief auf 40 MHz, obwohl ch-2g width=20mhz sagt: ein Inline-Override
  auf wifi2 gewinnt gegen das Profil. Jetzt 20 MHz, ap1 ch1 / ap2 ch11.
- ap2s 5-GHz-Radio sendete mit 9 dBm, jetzt 18. Beide APs 40 MHz,
  ueberlappungsfrei (5170-5210 / 5210-5250).

Drei Korrekturen an eigenen Annahmen:
- Die 9 dBm sind NICHT das ETSI-Band C. Der Wechsel ins Indoor-Band liess sie
  bei 9; erst die Breite brachte 18. "80 MHz generell" traegt auch nicht,
  ap1 fuhr 80 MHz mit 18. Mechanismus offen, Hypothese + Test in TP25.
- `!channel` loescht Inline-Overrides nicht, nur !channel.width einzeln.
- Frequenz vor Breite zu aendern hat ap2 kurzzeitig in denselben 80-MHz-Block
  wie ap1 geschoben. Breite VOR Frequenz.

Die ch149-Notiz ist bis 03f328f (2026-06-18) zurueckverfolgt: geloest wurde
Co-Channel, nicht DFS. "non-DFS" war nachtraeglich mitgeschriebene Begruendung
fuer das FCC-Standardpaar 36/149, keine geprueft Anforderung. Und
skip-dfs-channels=10min-cac schliesst DFS gar nicht aus, nur das
Wetterradar-Band -> 5500-5700 liegt als Reservekanalraum brach.

TP16.3 neu — cloudflared-Reduktion: der Mesh IST schon der private Datenpfad
(137 Zeilen im TP5-Log belegen es), Container braucht nur der oeffentliche
Ingress. Mesh-Hostname-Routes fuer public hostnames sind Egress, nicht
Publishing — Verwechslungsfalle.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 14:44:40 +02:00
a78f385479 Merge branch 'tp5-etappe1-log-lauf'
# Conflicts:
#	docs/teilprojekte.md
2026-08-17 14:35:26 +02:00
d68e82d9ae TP16.1 Nachlauf: Mgmt-ACL via GC auf alle 4 Geraete (72/72), CF-Schalter entschieden
Neue Compliance-Feature ip-service (17->18 Regeln, 68->72 Checks). Sollzustand
einheitlich im Template: ssh/www/winbox/api = 10.40.0.0/16,100.96.0.0/12;
ftp/telnet/api-ssl disabled. Deploy gestaffelt (ap2 zuerst, am Geraet
gegengeprueft), Job liegt als 'mgmt-acl' in gc-configplan.py.

Befund war invertiert: branch/ap1/ap2 hatten GAR KEINE Address-Beschraenkung
und waren laengst per Mesh erreichbar; winbox war auf allen vier offen. Aus dem
Erreichbarkeits-Fix wurde eine Haertung. ftp/telnet/api-ssl dabei abgeschaltet.

CF-Schalter 'Allow all Cloudflare One traffic to reach enrolled devices':
recherchiert, bleibt AUS - er oeffnet die Client<->Client-Richtung, unsere laeuft
ohne ihn. Kein API-Feld, CF-Docs widersprechen sich (Profil- vs. globale
Einstellung).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 12:55:03 +02:00
63851ad0ad TP16.1 ABGESCHLOSSEN: privater Zugang via natives WireGuard, ICMP repariert
4.5 Abnahme bestanden: 0% Ping-Loss auf alle BF-VLANs (vorher 100%), TCP mit
echtem Datenfluss ok, FQDN-Smoke beweist cloudflared-Public-Teil unberuehrt.
4.6 Auflage #4 erfuellt: Ist-Stand als intended config nach Nautobot,
65/68 -> Template ergaenzt -> 68/68 keine Drifts.

Zentrale Falle dokumentiert: /ip service address=10.40.0.0/16 sperrt das
Router-Mgmt aus der Mesh-Range 100.96.0.0/12 aus - Ping geht, SSH/REST/MikroMCP
sterben. Fuer branch/ap1/ap2 noch offen. Und: nc -z ueber WARP ist kein
Reachability-Beweis, der CF-Proxy terminiert den Handshake.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 12:28:03 +02:00
44c1fbcca8 TP16.1 4.1-4.4 durch: Mesh-Tunnel steht auf crs326-core
Prereqs: use_zt_virtual_ip=true, Device-Profil 'Cloudflare Mesh', Split-Tunnel
auf beiden Profilen (100.64/10 -> /11 + 100.112/12).
Geraet: cf-mesh, 100.96.0.6/32, Peer 162.159.193.2:2408, Handshake steht,
Route 100.96.0.0/12 aktiv. Backup vorher (Auflage #4).
4.4 Weg A hat funktioniert - vnet-Gotcha trat NICHT ein.

Zwei Werkzeug-Fallen dokumentiert: MikroMCP manage_wireguard_interface kann
keinen Privkey annehmen (CF liefert ihn aber), und manage_wireguard_peer
verarbeitet endpoint 'IP:Port' falsch (endpoint-port=0 -> kein Handshake).

Offen: Dashboard-only-Schalter 'Allow all Cloudflare One traffic to reach
enrolled devices' + Ping-Abnahme 4.5.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 12:08:36 +02:00
7388cc8388 TP16.1 4.0 DURCH: Mesh-Node bf-core-mesh angelegt, Free-Plan-Gate offen
POST /warp_connector erfolgreich -> d1da7c8a-... Der LXC-Fallback ist vom Tisch.
Blocker war der Token, nicht der Plan: alter User-Token hatte 2 fehlende
Permissions, ersetzt durch account-owned Token (gueltig bis 2027-01-09).
Zwei Fallen dokumentiert: account-owned Tokens verifizieren an
/accounts/{id}/tokens/verify (am /user-Pfad melden sie faelschlich
'Invalid API Token'), und Zone-Permissions brauchen eine eigene Policy-Zeile
('Account tag in access policy must match tag in request uri').
Verifiziertes Permission-Set inkl. IDs in 4.0. Am Geraet weiterhin nichts angefasst.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 11:58:51 +02:00
52e79c427c TP16.1 Scharfschalten: Plan-Probe gescheitert (Token-Scope) — Blocker vollstaendig vermessen
POST /warp_connector -> 10000/403, identisch zu 2026-07-17. Neu: Gegenproben
zeigen, dass auch 4.1 blockiert ist (devices/settings GET 403) — es fehlen ZWEI
Permissions, nicht eine. MCP-Read-Gegenprobe belegt: Account kann es, Token darf
nicht -> Free-Plan-Frage bleibt offen. Am Geraet wurde nichts angefasst.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 20:06:36 +02:00
bb2c87c68e Compliance 68/68 + TP24 (USV) ausgeloest + Doku auf den Stand nach dem Core-Cutover
Zwei Straenge, die sich dieselben Dateien teilen — deshalb ein Commit.

1) COMPLIANCE-DRIFTS BESEITIGT (User: "beseitige autonom alle") -> 68/68, 0 Drifts

Entfernt wurden die 4 verbliebenen `extra`-Drifts (der fuenfte, core 10.40.41.211,
war schon ueber TP19-vlan1-core-address gefallen):
- ap1 + ap2: Werks-defconf `/ip dns static router.lan -> 192.168.88.1`. Auf beiden
  APs der einzige statische Eintrag, die IP existiert im Netz nicht. Der Core hat
  sein eigenes, korrektes router.lan -> 10.40.99.1 (im Template, compliant).
- crs326-branch: Bring-up-Rest SVI vlan10 + 10.40.10.2, Adresse zuerst.

Richtung bewusst "am Geraet entfernen" statt "ins Template aufnehmen" — genau so
steht es seit 2026-08-13 im Switch-Zweig des Templates. Der frueher notierte
Vorbehalt "potenzielle Rettungspfade" ist per User-Entscheid aufgehoben; der
Mgmt-Fallback aus VLAN10 auf dem branch entfaellt damit (Rueckweg = MAC-Winbox am
selben Draht).

Weg: 3 manuelle GC-ConfigPlans, kein Direkt-Write. Vorher /system backup je Geraet.
Deploy gestaffelt — erst die APs, am Geraet gegengeprueft, dann branch.

Verifikation am GERAET, nicht am Job: DNS-Statics total=0 bei unveraenderten 28
bzw. 3 WLAN-Clients; branch nur noch vlan99 + 10.40.99.2/24; Ping vom Core 4/4.
Entscheidende Gegenprobe: /interface bridge vlan/export byte-identisch — `bridge`
steht dort statisch als tagged-Member von VLAN10, das Entfernen des SVI hat also
weder Traffic-Wirkung noch neuen Drift. Danach Backup -> Intended -> Compliance,
alle 4 Geraete mit frischem Success-Datum.

Neue API-Falle, die erklaert warum es bisher kein Skript gab:
POST /plugins/golden-config/config-plan/ ist 405 — das ViewSet ist read-only.
ConfigPlans entstehen nur ueber den Job "Generate Config Plans" (plan_type=manual
+ commands-TextVar). plan_type=missing erzeugt ausserdem nur add-Zeilen, also muss
alles Entfernende zwangslaeufig ein manueller Plan sein.

Neu: nautobot/gc-configplan.py — loest Device-UUIDs einzeln per Name auf und
assertet plan.device UND config_set gegen das Ziel (die alphabetische
Sortier-Falle aus TP21.1 kann damit nicht wiederkommen), verweigert config_sets
mit <<REDACTED>> (Regel 1) und print-Zeilen, kann gestaffelt deployen
(--deploy-ids) und kapselt Backup -> Intended -> Compliance (--refresh-compliance).
Dry-Run ist Default.

2) TP16.1: GATE OFFEN, Runbook ausfuehrungsreif, Governance-Ausnahme #4

Die Bedingung "gated bis TP21 den CRS326 abdeckt" ist seit der Adoption am
2026-08-13 erfuellt. §3 neu gemessen, §4.3 von Platzhalter auf echte Werte.
Die letzte inhaltliche Unbekannte hat sich erledigt: "Rueckweg-Routing TBD" —
der Core IST L3-Gateway aller VLANs, es braucht keine Zusatzroute. wg-hub liegt
auf demselben Geraet und ist damit direktes Vorbild statt fernes Muster.

Klarstellung, weil leicht zu verwechseln: das Mesh ersetzt die Tunnel NICHT. Es
loest nur den privaten Zugang (10.40.0.0/16 per IP, inkl. ICMP); die oeffentlichen
FQDNs bleiben auf cloudflared. Relevant dabei: die Route 10.40.0.0/16 zeigt auf
bf-pve — und der faehrt derzeit nur einen Connector.

Ausnahme #4 (User 2026-08-16): die WG-Zeilen des Mesh-Bring-ups auf crs326-core
duerfen direkt gesetzt werden. Grund ist strukturell, nicht bequem — TP22-Regel 1
schliesst jede <<REDACTED>>-Sektion vom Push aus, ein Privkey ist ueber Golden
Config gar nicht deploybar. Auflage: Backup vorher, intended config danach zurueck
nach Nautobot. Scope: nur dieser Bring-up.

Damit das ein einmaliger Bootstrap bleibt, ist das Secret-Handling-Design
dokumentiert: ein privater Schluessel ist Geraete-Identitaet, keine Konfiguration
(wie ein SSH-Hostkey). Der private Teil entsteht am Geraet und geht nie weg, nur
der oeffentliche kommt in die SoT und wird in die Peer-Configs gerendert.
Stufe 2 (nautobot-secrets-providers + Vault) lohnt bei 4 Geraeten und einem Key
nicht. Nebenbefund: die WG-Peers fm/dw stehen mit hartkodierten public-keys im
Jinja-Template — Public Keys sind Daten, keine Templatezeilen.

3) TP24 — USV aus TP15 herausgeloest (User-Entscheid)

Die DC-USV war der letzte offene Rest in TP15 und hat mit Switching/Routing
sachlich nichts zu tun (eigene Einkaufs-, Verkabelungs- und Elektrik-Logik).
TP15 ist damit inhaltlich zu. TP24 traegt jetzt 48V-Bus, MeanWell/LiFePO4,
Laufzeiten, DC-Eingangs-Tabelle und die 5 offenen Entscheidungen — darunter neu
die Standortfrage, die sich durch den Core-Umzug ins UG neu stellt.

4) DOKU-AUFRAEUM-SESSION A-E abgearbeitet

- Ist-Stand-Block neu geschrieben, live gegen die Geraete geprueft. Alte Fassung
  als ausklappbare Historie, ⚠️-Provisorium entfernt.
- Reihenfolge-Abschnitt auf den echten Rest-Pfad TP5 -> TP6 eingedampft (Punkt 3
  sagte noch "Jetzt: Omada-PVID-Fix").
- Stale ap1-als-Router-Aussagen in TP3/TP4/TP15/TP16.1/TP21/TP-R korrigiert —
  fortgeschrieben, nicht ueberschrieben.
- CLAUDE.md: Mac mini .41.167 -> .20.167 (war stale, live per ARP bestaetigt),
  branch-Uplink "sw1 GE8" -> "core ether8", ALLNET-/Omada-Gotchas als Historie.
- switch/ als Archiv gekennzeichnet (Geraet ausgebaut, Runner nicht ausfuehrbar).
- omada-mcp + CF-Ingress live gegengeprueft: beides sauber, Punkt abgehakt.

Nebenbefund, eingetragen aber nicht angefasst: das CF-Tunnel-HA ist degradiert
(bf-nas und bf-pve mit je nur einem Connector), und vier tote Alt-Tunnel tragen
VLAN1-Origins — darunter die Aufloesung des "unidentifizierten VLAN1-Geraets
.41.133" aus TP19 (es ist das coolify-Origin).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 19:28:50 +02:00
0396321560 NAS: hms-mqtt stillgelegt (restart=always -> no)
Der Container war bereits beendet; entscheidend war die Restart-Policy.
Mit `always` waere er beim naechsten Daemon-Neustart wiedergekommen, ein
blosses `docker stop` haette also nicht gehalten.

Nebenbefund, nicht von mir ausgeloest: grafana, drawio-server und hms-mqtt
wurden am 2026-08-16 um 17:14:54-17:15:06 CEST innerhalb von zwoelf
Sekunden per Signal beendet (grafana exit 0 mit "System signal:
terminated", drawio-server 143, hms-mqtt 137). Kein OOM, Speicher frei,
restarts=0. Folge: das Prometheus-Ziel grafana steht auf down, n8n und
prometheus weiter up.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 17:39:25 +02:00
415be1ed24 TP5 Etappe 1: Sammelphase laeuft, VLAN1-Rueckbau abgenommen
Abnahme bestanden: out:bridge = 0 ueber ein 10-Minuten-Fenster (Logdatei
vorher geleert). Vorher waren vlan20 -> bridge 76 % des gesamten
Inter-VLAN-Verkehrs; die Rate fiel von ~166 auf ~34 Zeilen/min.

Beobachtete Matrix (339 Zeilen / 10 min) als Arbeitsmaterial fuer Etappe 2
festgehalten. Zwei Befunde daraus:

- D4 ist belegt statt geschaetzt: der Management-Pfad ist HA (10.40.20.105),
  das ueber seine mikrotik-Integrationen 8728 auf branch/ap1 pollt (je 67x).
  Ohne Whitelist sperrt der spaetere Drop die Netzverwaltung aus.
- Neuer Merkposten: same-VLAN-Verkehr erreicht die forward-Kette —
  vlan10 -> vlan10 unicast mDNS, erzeugt vom mDNS-Repeater auf dem Core.
  Harmlos, aber ein blanker Drop wuerde Discovery innerhalb von MAIN
  beschaedigen.

Damit sind drei Whitelist-Zeilen bekannt, bevor Etappe 2 beginnt:
LAN->WAN, der Mgmt-Pfad, und same-VLAN-mDNS.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 17:34:06 +02:00
49f2bfd98f NAS: Container-Manager-Neustart — Haenger weg, Portainer-Integration bleibt offen
synopkg stop/start ContainerManager auf nas-bf. Alle 14 Container aus der
Baseline sind zurueck, zusaetzlich kam hms-mqtt hoch (Restart-Policy, lief
vorher nicht).

Der Neustart hat den Haenger behoben: `docker system df` beendet sich wieder
(vorher rc=124 nach Ausgabe der Tabelle). Er reicht aber nicht — der Aufruf
bleibt mit 33s bis ueber 120s weit ueber dem pyportainer-Timeout, die
HA-Integration bleibt auf setup_retry.

Gemessen, wo die Zeit hingeht: images -q 84ms, ps -aq 95ms, volume ls 65ms,
system df 33-92+s. Also vollstaendig in der Groessenberechnung (Durchlauf der
overlay2-/Volume-Verzeichnisse auf NAS-Platten) — Plattformnachteil, kein
Defekt.

Aussichtsreichster Weg dokumentiert: eigener Portainer-Benutzer fuer HA ohne
Zugriff auf ep14. Zwei widerlegte Zwischenthesen sind als solche festgehalten
(odroid-m1 war es nicht; es ist kein Groessenproblem).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 18:57:04 +02:00
39e92d336d TP19: VLAN1-Adressen abgeraeumt (pve .41.100, core .41.211), Prometheus bereinigt
pve: /etc/network/interfaces vmbr0 von inet static auf inet manual, Adresse
raus, angewendet per `ip addr del` ohne ifreload -a. Alle 9 Gaeste weiter
running, Storage aktiv, nur noch vmbr0.20 traegt eine IP.

core: 10.40.41.211 ueber Nautobot GC entfernt. Mgmt .99.1 + 10.40.10.1
intakt, Compliance 17/17 gruen — der letzte offene Drift ist damit weg.

Prometheus: der pauschale 41->20-Ersatz war eine Falle. Gemessen statt
angenommen — nur grafana und n8n liefern echte Metriken. gitea hat /metrics
nicht aktiviert, vaultwarden gibt 404, portainer /api/status liefert JSON
statt Prometheus-Format, node/alertmanager/qdrant sind exited, pihole ist
abgewaehlt. 8 Jobs + alerting-Block auskommentiert, 3 Ziele aktiv und up.

Zwei Korrekturen an eigenen Aussagen:
- Die tote Portainer-Umgebung odroid-m1 war NICHT die Ursache des
  HA-Hangs. Sie ist entfernt, das Symptom blieb. Echte Ursache laut
  HA-Debug-Log: `docker system df` auf ep14 kommt nicht zurueck.
- Auf der NAS ist prometheus.yml fuer den Login-User nicht schreibbar
  (65534:65534, Verzeichnis gehoert adm.christoph). Zwei `cat >`-Pushes
  sind still gescheitert. Schreiben nur per sudo tee + md5sum-Gegenprobe.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 18:40:15 +02:00
10d93e6214 TP5 Etappe 1 pausiert + VLAN1-Restliste aus dem Log-Lauf
Etappe 1 ist aufgebaut und verifiziert, wird aber vor der Sammelphase
pausiert (User-Entscheid): 76 % des beobachteten Inter-VLAN-Verkehrs waren
.41.x-Altlasten. Eine Whitelist daraus haette nach dem Aufraeumen nicht
mehr gegolten.

- Log-Regel disabled=yes, Memory-Logging zurueck auf topics=info
- Kollektor + Logging-Action bleiben stehen -> Wiederaufnahme = zwei Zeilen
  (routeros/tp5-etappe1-pause.rsc dokumentiert beide Richtungen)
- D2 vollzogen: iPhone im MAIN-SSID, .30.201 im ARP auf failed

TP19 bekommt die konkrete Restliste, die der Log-Lauf sichtbar gemacht hat:
prometheus (.20.151) scrapet 10 tote 10.40.41.x-Ziele, .20.105 zieht auf
pve unter der alten .41.100. Umzugsregel 41->20 bei gleichem letzten Oktett.

Der gemeldete Timeout auf .20.100:8006 ist KEIN Firewall-/Portproblem:
pveproxy lauscht auf *:8006, pve-firewall disabled, HTTP 200 in 0,06 s aus
VLAN10 und VLAN20. Notiert ist auch die Fehlerquelle meines ersten Tests -
`timeout` existiert auf macOS nicht und meldet falsch-negativ.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 18:02:51 +02:00
bf07c642f7 TP5 Etappe 1: Log-Lauf live auf crs326-core
Log-only-Regel am Ende der forward-Kette (blockiert nichts) plus Syslog-
Kollektor, ausgerollt ueber Nautobot GC als manual Config Plans.

- routeros/tp5-etappe1-log-lauf.rsc: der ausgerollte Endzustand + die am
  Geraet belegten Lehren aus dem Rollout
- nautobot/gc-manual-plan.py: Push-Werkzeug (assertet plan.device, liest
  Plan-Status statt Job-Status, strippt Kommentarzeilen)

Zwei Korrekturen an bisherigen Annahmen:
- Ein gescheiterter Netmiko-Deploy hinterlaesst einen TEIL-Zustand. Die
  TP22-Notiz "sauberer Fehlschlag" galt dem NAPALM-Weg.
- Bindestriche in name= werden von RouterOS abgelehnt, Quoten hilft nicht.
  Die zuerst notierte target=/remote=-Erklaerung war falsch und ist raus.

Die Log-Regel steht auf out-interface-list="!WAN": bare fing sie auch allen
Internet-Verkehr. LAN->WAN ist eine garantierte Whitelist-Zeile, also
Rauschen - und ein Merkposten fuer Etappe 3, wo der Drop aus demselben
Grund nicht bare stehen darf.

D2 entschieden: iPhone .30.201 wird ins MAIN-SSID umgehaengt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 17:30:15 +02:00
f31172e4d9 TP5-Runbook: D3 entschieden (ICMP-Sweep = lanscan.app, gehoert in die JIT-Gruppe)
Der Dauersweep von .10.82 auf alle Shellys ist lanscan.app — ein Ad-hoc-Scan vom
Arbeitsplatz, kein Dienst. Also keine permanente MAIN->IOT-ICMP-Regel, sondern
Teil der selbstverfallenden JIT-Admin-Gruppe (deckt sich mit D4).

Hinweis fuer den Log-Lauf ergaenzt: der Scan erzeugt sonst Rauschen in Etappe 1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 16:38:29 +02:00