Commit Graph

26 Commits

Author SHA1 Message Date
05a3fd957f TP25 Fund E geschlossen: 7.24.1 war die Ursache, nicht ft-over-ds
Abschlussmessung 2026-09-02: reauthenticating 218->40->4 (09-02 nur 4 in
8,6 h, alle iPhone F2:62, 0 Ausfaelle). Vorbedingung geprueft (Core-Uptime
1d18h, caps joined=0 -> keine Reboot-Artefakte). Hebel 1 widerlegt+
zurueckgebaut, Hebel 2-4 entfallen, kein Geraete-Write (Compliance 140/140).
Offen bleibt nur ap2-Unterperformance.

- neu: docs/handoff-20260902-tp25-fund-e-messung.md
- teilprojekte.md: Quick-Index + Ist-Stand + TP25-Abschnitt + Hebel-Tabelle
- CLAUDE.md: Pflichtlektuere Punkt 5 auf geschlossen

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-02 08:44:32 +02:00
07b595c45a TP25 Fund E: Hebel 1 widerlegt und zurueckgebaut -- Ringpuffer-Messfehler korrigiert
Zwei Sessions haben denselben Fall bewertet und kamen zu entgegengesetzten
Schluessen. Aufgeloest zugunsten der Kollektor-Messung.

Der Widerspruch und sein Beleg:
- Die Nacht-Session las `get_log ... sinceMinutes=1440` -> total 0 und schloss
  auf "Fund E geheilt, Hebel 1 committen". Das ist der FLUECHTIGE Ringpuffer des
  Routers: live nachgemessen 1000 Zeilen, aeltester Eintrag 01.09. 00:38:58 --
  keine 9 h Tiefe. Der Core-Reboot 14:36 hatte ihn geleert, der 31.08. Vormittag
  war darin nicht enthalten. "total 0" hiess "im Puffer nichts", nicht "in 24 h
  nichts" -- genau die Falle, wegen der am 30.08. der Kollektor gebaut wurde.
- Im Kollektor stehen fuer 08:09-14:36 (Hebel 1 ALLEIN, vor dem Upgrade) 124x
  reauthenticating: 09h=1, 11h=2, 12h=20, 13h=31, 14h=70 -- alle vom iPhone
  allein, also Client-Befund nach der eigenen Merkregel. Dazu Christophs zwei
  erlebte Ausfaelle 13:16 und 14:23. Zwischen 09:00 und 14:36 lag kein Reboot.

Daraus gehandelt (User-Entscheid: symmetrisch am Geraet, jetzt):
- Backup pre-tp25-funde-rollback, dann ft-over-ds=yes + remote-cap provision
- Rueckbau-Diff zeigte genau eine Abweichung, kein Kollateral
- Abnahme: CAPs durchgehend Ok, ap2 9/9 und ap3 9/9 running, frische DHCP-Lease
  (~1 min alt), Transaktion "zurueckgebaut", Compliance 140/140
- Der Rueckbau IST das Experiment: bleibt es ruhig, war 7.24.1 die Ursache;
  kehrt das Haemmern zurueck, hatte die Nacht-Session recht. Bis zur Messung
  am 2026-09-02 frueh committet niemand.

Zwei Nebenbefunde:
- gc-configplan.py --refresh-compliance scheitert STILL ohne NAUTOBOT_TOKEN:
  Meldung ausgegeben, aber Exit-Code 0. Gehoert gefixt.
- Compliance ist 140/140, nicht 135/135: es gibt eine 28. ComplianceRule
  `interface-veth`, angelegt 31.08. 20:04, Urheber offen.

Der ap2-Befund der Nacht-Session (2 m Abstand, -80 dBm, 0 Clients auf ap2)
bleibt unberuehrt gueltig und ist weiter der beste Hinweis auf die
23:02-Stoerung. CLAUDE.md enthaelt in diesem Commit auch deren TP16.3-Zeile
(gemeinsame Datei, Hunks nicht trennbar).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 09:21:46 +02:00
3ea8d050d2 TP39: networking.service in vier LXCs repariert (Ursache = VLAN1-Altlast)
101 iob-master, 102 mqtt5, 106 influxdb2, 107 redis meldeten networking.service
und ifupdown-wait-online.service dauerhaft als failed, bei funktionierendem Netz.
Folge: alles mit After=network-online.target startet nach einem Reboot nicht --
influxdb2 kam gestern Nacht nicht hoch (Unit enabled, kein Startversuch im
Journal).

URSACHE, und es ist dieselbe Altlast wie beim toten Resolver:
in /etc/network/interfaces standen noch auto-Stanzas aus dem alten VLAN1-Schema
(eth0 -> 10.40.41.x, teils mit gateway 10.40.41.254) sowie aus frueheren
Versuchen (veth16, veth24, ein Tippfehler eth01) -- alle auf Interfaces, die es
im Container gar nicht gibt. ifup -a scheitert daran, waehrend das echte veth20
sauber hochkommt. Der VLAN-Umzug hat die Container umgehaengt, aber die alten
Stanzas nie entfernt.

FIX: nur Stanzas entfernt, deren Interface in ip -br link fehlt; lo, veth20 und
veth20.2 unangetastet. Backup je Container: /etc/network/interfaces.bak-20260901.

ABNAHME war ein echter Reboot, nicht systemctl is-active: 106 neu gestartet,
influxdb kam nach 5 s VON SELBST hoch, networking active, null failed units.
Endstand ueber alle 13 LXC: dns=10.40.20.1 durchgehend, networking ueberall
sauber. Ohne Netzbezug bleiben run-rpc_pipefs.mount (101, 150) und
proxmox-regenerate-snakeoil.service (108), beide vorbestehend.

MESSFALLE, mit in CLAUDE.md aufgenommen: nc -z meldete waehrenddessen neun
Dienste gleichzeitig als "Port zu" -- inklusive des SSH-Ports, ueber den diese
Session gerade arbeitete, waehrend curl vom selben Host HTTP 200 in 24 ms bekam.
Bei "alles gleichzeitig kaputt" zuerst das eigene Werkzeug verdaechtigen. Es
waere um ein Haar die zweite falsche Ausfallmeldung dieser Nacht geworden.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 00:39:19 +02:00
73fec72abe TP16.3 §5 durch: vier Namen auf bf-public + 10-Sekunden-DNS-Fund behoben
FLIP (User-Freigabe, vorgezogen)
n8n / gitea / hass / vw laufen jetzt ueber bf-public, der oeffentliche Verkehr
geht damit erstmals ueber Caddy statt an ihm vorbei. Je Name einzeln geflippt und
dazwischen gemessen; Antwortzeiten vorher/nachher unveraendert. Nachweise:
gitea echte Gitea-Antwort, hass WebSocket 101 Switching Protocols (der
Companion-App-Pfad, den das Runbook als "nur vom User pruefbar" fuehrte),
vw /alive + /api/config 200 und WS-Hub 401 von Vaultwarden selbst, n8n vom User
im Browser bestaetigt (von aussen nicht bis zum Origin pruefbar, s. TP14.4).
Die drei Alttunnel bleiben als Rueckfallebene stehen -- §6 ist NICHT Teil davon.

10-SEKUNDEN-ZOLL AUF gitea/vw/hass -- Ursache gefunden und behoben
gitea hing bei ~10% der Anfragen exakt 10,1 s, quer ueber Web-UI, /api/healthz
und den Git-Pfad. MariaDB (LXC 302) hatte skip-name-resolve auskommentiert und
machte bei JEDER NEUEN Verbindung einen Reverse-Lookup, waehrend ihr resolv.conf
auf den toten 10.40.41.254 zeigte: 10.010 ms je Lookup, Pool-Verbindungen
schnell -- daher wirkte es sporadisch. An derselben DB haengen Vaultwarden, Home
Assistant und gitea (per Verbindungstabelle belegt, nicht vermutet; die erste
Annahme "vaultwarden nutzt SQLite" war falsch und wurde vom User korrigiert).
Fix: nameserver 10.40.20.1 + Reboot fuer fuenf LXCs (302, 102, 106, 107, 150).
Nachher 21-24 ms und 0 von 25 Proben langsam.
Offen: skip-name-resolve selbst -- bricht Hostname-basierte Grants, vorher
mysql.user lesen (DB-Zugang fehlt).

LATENT, NICHT VON DIESER SESSION VERURSACHT
networking.service + ifupdown-wait-online.service sind in 101/102/106/107
failed; influxdb2 kam nach dem Reboot nicht hoch (Unit enabled, kein
Startversuch im Journal). 101 wurde nie angefasst und zeigt dasselbe -- die
Container liefen nur 13+ Tage ohne Neustart.

RUNBOOK-KORREKTUREN
§5.3 "Caddy sieht den Request" konnte nie funktionieren: im Caddyfile steht keine
log-Direktive, ein erfolgreicher Request hinterlaesst nichts. Ersetzt durch die
Werkzeuge, die tatsaechlich etwas beweisen -- erzwungener oeffentlicher Weg per
curl --resolve (Pflicht wegen Split-Horizon), Verbindungstabelle am Core statt
Firewall-Zaehler (cloudflared haelt die Origin-Verbindung offen, der Zaehler
steht still obwohl alles laeuft), Antwort-Fingerabdruck, WebSocket mit --http1.1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 00:25:39 +02:00
e474e5e38a Merge main + nervous-williams; Drift-Zuschreibung korrigiert
Der Branch enthaelt jetzt origin/main (0680cca, TP25 Fund E / TP27) und
die Korrektur c8b2a15 aus claude/nervous-williams-acf000.

Inhaltliche Korrektur an meinen eigenen Dateien
- Ich hatte die wifi-security-Drift (ft-over-ds=no auf sec-main) dem
  7.24.1-Upgrade zugeschrieben. Falsch: gc-transaktion.py status fuehrt
  TP25-fund-e-ft-over-ds als OFFEN -- der Hebel wurde 08:09 bewusst
  gesetzt, der Core erst 14:36 gehoben. Sie gehoert einer laufenden
  TP25-Session, braucht keine Entscheidung und darf nicht gruen gemacht
  werden. Korrigiert im §5-Prompt und im §2/§3-Handoff.
- Merkregel in CLAUDE.md: vor jeder Drift-Bewertung gc-transaktion.py
  status lesen. Dazu die Abgrenzung Transaktion (befristeter Versuch)
  vs. Soll/Template (Dauerzustand) -- die sechs AP-Drifts aus TP16.3
  §3.4 sind Dauerzustand und gehoeren deshalb ins Template, nicht in
  eine Transaktion.
- Notiert: gc-transaktion.py findet den Token aus einem Worktree heraus
  nicht (210-nautobot.yml liegt nur im Haupt-Checkout); die
  Transaktionsliste kommt trotzdem, nur die Compliance-Spalte fehlt.

Konflikt in teilprojekte.md (ROS-7.24.1-Zeile) zusammengefuehrt statt
eine Seite zu verwerfen: TP27-Erledigung samt Zeitstempeln aus main plus
die npk-Folge fuer TP16.3 aus diesem Branch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 19:34:40 +02:00
60360fc3cc TP16.3 §2/§3 durch: cloudflared auf ap1/ap2/ap3, bf-public healthy mit 12 Connectoren
Merge von claude/nervous-williams-acf000 (d5b3ce3) plus Ergebnis der
Vor-Ort-Session vom 2026-08-31.

Ergebnis
- je ein cloudflared 2026.6.1 auf ap1/ap2/ap3, bf-public healthy/12
  (vorher 0 Connectoren), Flash je AP 54-55 MiB frei, WLAN zurueck.

Drei Runbook-Fehler aufgedeckt und korrigiert (§2.2, §3.3, §3.5, §8)
- Flash-Budget war Faktor 2,5 zu optimistisch: cloudflared entpackt
  69,5 MiB (gemessen mit docker export), nicht 28 MB -- das offizielle
  Image passt auf keinen der drei APs. Ersatz: eigenes FROM-scratch-Image
  mit 35,3 MiB aus dem statisch gelinkten Binary, Binary-SHA e93824f6
  gepinnt, Neubau byte-identisch. tools/build-cfd-image.py.
- docker save schreibt seit Docker 25 OCI statt docker-v1 -> RouterOS
  meldet "no config found in manifest". tools/oci2docker.py als Konverter.
- /container/envs nimmt list=, nicht name= (auch MikroMCPs
  manage_container_env ist dadurch fuer dieses Feld unbrauchbar).

Weitere Funde
- Der device-mode-Bestaetigungs-Boot installiert keine Pakete; erst
  Paket-Reboot, dann device-mode.
- "A - AVAILABLE" in /system package print ist ein Download-Katalog,
  kein Paket auf dem Geraet (Gegenprobe am Core: 2,9 MB frei, listet
  10,1 MB wifi-qcom als verfuegbar).
- MikroMCPs export_config exportiert unvollstaendig (301 B statt 6,2 KiB).

Offen und entscheidungsbeduerftig
- Compliance 128/135: §3.4 verlangt Direkt-Writes fuer ip address/nat,
  die unter GC-Kontrolle stehen -> sechs neue extra-Drifts, zwei je AP.
  Inhaltlich richtig, gehoeren ins Soll -- kein Re-Baseline, kein Rueckbau.
- Zwei Nautobot-Tokens sind in dieser Session ins Transkript geraten
  (unzureichende sed-Maskierung) -> Rotation noetig, TP30. Merkregel in
  CLAUDE.md ergaenzt.

Merge-Konflikte aufgeloest
- Nummernkonflikt: beide Branches hatten ein TP37. main behaelt TP37
  (Nautobot als Netzwerkdoku, User-Okay 08-30), OOB-Mgmt wird TP38.
  Braucht noch Christophs Okay.
- Drei CF-Rollback-Snapshots hatten gleichen Namen bei verschiedenem
  Inhalt -> aelterer Stand als *-vor-hostname-schnitt.json erhalten,
  keiner verworfen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 16:15:13 +02:00
0680ccabc8 TP25 Fund E: Hebel 1 gescheitert, TP27 durchgezogen, Fund B entwarnt
Zwei von Christoph gemeldete Ausfaelle (13:16 Terrasse, 14:23 Arbeitszimmer)
stehen im Kollektor und tragen dieselbe Signatur: Reauth-Schwall, dann ein
Loch von 7 bzw. 5,5 Minuten. Beide liegen NACH dem Hebel von 08:09.

- Hebel 1 (ft-over-ds=no) hat nicht gegriffen: 124x reauthenticating nach
  dem Eingriff, Stundenvergleich auf gleicher Firmware 07h=79 vs 14h=70.
  Erfolgskriterium war ~0. Gewertet wird nur 08:09-14:36 (Christoph-Entscheid),
  danach kommt das Upgrade als zweite Variable dazu. Transaktion bleibt OFFEN,
  Compliance bleibt bewusst 134/135.
- TP27 erledigt: Flotte einheitlich auf 7.24.1 (ap2 08:56, core 14:36,
  ap1 14:50, branch 14:52; ap3 kam bereits so). Nach dem Upgrade live geprueft:
  3 CAPs Ok, 4 Provisioning-Regeln, ap2 9x running, 30 Clients, ft-over-ds=no
  hat den Reboot ueberlebt.
- Fund B entwarnt: die 13 CAP-joined / 4 activity timeout waren die
  Upgrade-Reboots, keine CAPWAP-Instabilitaet. Neuer Gotcha: ein Burst ueber
  VIELE MACs ist Infrastruktur, ueber EINE MAC ein Client.
- Zweiter Gotcha: die cap-wifiN-Karte verschiebt sich bei JEDEM Rejoin, nicht
  nur beim Provisionieren -- sie wanderte an einem Tag zweimal, womit die
  Tabelle im Vormittags-Handoff nach sechs Stunden falsch war. Interface-Namen
  in Logzeilen sind ohne zeitnahen Snapshot nicht zuschreibbar.
- Offen fuer die naechste Session: Hebel 2 (ft=no) ODER wpa2-psk,wpa3-psk --
  sec-main ist auch die einzige SSID ohne wpa2-psk, und "association rejected,
  no cached PMK" (157x am 31.08., 0x am 30.08.) ist eine SAE/PMKSA-Meldung.
  Vorher pruefen, ob 7.24.1 das Verhalten schon veraendert hat.
- wifi-p750w-coverage-and-map.md ist vom 2026-07-02 und als Coverage-Beleg
  unbrauchbar (vor CAPsMAN-Cutover, vor ap2-Umzug, vor ap3).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 15:27:57 +02:00
6f8ba8c8b5 sshpass -p repo-weit weg + vier TP15-Cutover-Skripte archiviert
sshpass -p schreibt das Passwort in argv, wo es in ps und jedem argv-Trace
steht -- die Klasse, an der am 2026-08-22 das Core-Passwort verbrannt ist.
Nach gc-transaktion.py (voriger Commit) jetzt auch die fuenf unter routeros/:
SSHPASS-Env + sshpass -e.

Nachweis, gemessen statt gelesen:
- alle 13 subprocess.run mit sshpass tragen env= (per AST geprueft; ohne env
  waere SSHPASS leer und alles still kaputt)
- Signaturen passen zu den Aufrufen (AST-Arity; py_compile findet das NICHT)
- echter Lauf des gepatchten Codes gegen den lebenden Core: backup-core.py
  importiert, IP zur Laufzeit auf 10.40.99.1 -> "name: crs326-core", rc=0
- Passwort in argv? nein. In ps waehrend der Verbindung? nein, 40 Stichproben
- Negativkontrolle: derselbe Test mit einem Dummy-Wert ueber die alte -p-Form
  -> 36 Treffer. Die Probe ist also nicht blind, das "nein" hat Aussagekraft

Mitgefixt, weil es im umgebauten Code lag: apply-core-cutover-l3.py griff in
run_silent auf ein pw zu, das dort gar nicht existierte -- jeder Fehlerfall
endete in einem NameError statt in der gedachten Meldung.

Fuer TP30 aendert das NICHTS: der Weg ist zu, der Wert bleibt verbrannt.
Posten #1 (MikroTik-admin) bleibt faellig. Im TP so hingeschrieben, damit es
niemand als erledigt liest.

--- Archivierung (Christoph-Entscheid) ---

Beim Fixen fiel auf, dass alle vier Cutover-Skripte auf tote Adressen zeigten:
  apply-core-cutover-l3.py  10.40.41.211    tot (VLAN41 seit 2026-08-27 weg)
  backup-core.py            10.40.41.211    tot
  restore-core.py           192.168.88.1    tot (Werks-Temp-Pfad)
  backup-ap1.py             10.40.10.1      ANTWORTET -- ist aber der CORE

backup-ap1.py war der gefaehrliche: er waere nicht gescheitert, er haette den
Core gesichert und die Datei ap1-pre-core-cutover-*.backup genannt. Wer das
spaeter zurueckspielt, spielt Core-Config auf einen AP.

Entscheid war archivieren, nicht reparieren -- der Cutover ist am 2026-08-08
durch, die Skripte haben ihre Aufgabe erfuellt. Sie liegen jetzt unter
routeros/archiv-tp15-cutover/ mit README nach dem Muster von switch/.
Die Pfad-Nebenwirkungen des Verschiebens sind ABSICHTLICH nicht repariert
(backup-core.py schriebe jetzt ins Archivverzeichnis, apply-core-cutover-l3.py
faende seine .rsc nicht mehr) -- sie zu reparieren hiesse, die Skripte wieder
lauffaehig zu machen, und das ist gerade nicht die Absicht.

Der sshpass-Fix wurde trotzdem VOR dem Verschieben gemacht: Archiv-Code wird
abgeschrieben, also soll dort das richtige Muster stehen.

import-core-rsc.py bleibt, wo es ist -- als einziges generisch nuetzlich. Sein
Default-Host ist ebenfalls tot (--host mitgeben), und in --host steckt ein
zweiter latenter Bug: sys.argv[1] wird als RSC-Pfad gelesen, bevor auf --host
geprueft wird. NICHT gefixt, eigene Runde.

Zeiger gesetzt in: CLAUDE.md (sshpass-Gotcha), teilprojekte.md (TP30),
teilprojekte-archiv.md (TP15), Handoff 2026-08-31.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 08:34:08 +02:00
a0a650eb48 TP25 Fund E Hebel 1: ft-over-ds=no auf sec-main, Messung laeuft
Ein Hebel, sonst nichts. 2026-08-31 08:09 am Manager crs326-core:
  /interface wifi security set [find name="sec-main"] ft-over-ds=no
  /interface wifi capsman remote-cap provision [find]
ft=yes bleibt -- FT laeuft weiter over-the-air, nur nicht mehr over-the-DS.
Nimmt exakt die Aenderung vom 2026-08-17 zurueck.

Abnahme (Lease, nicht Registration-Table):
- Manager, alle vier aktiven Master-VAPs cap-wifi3/4/5/6: ft=true ft-over-ds=false
- alle 3 CAPs state=Ok, alle VAPs running=yes AM CAP gelesen
- iPhone nach 71 s zurueck auf dirtyvader-main, frische Lease 10.40.10.196,
  auth-type=ft-wpa3-psk, -54 dBm; 30 Clients gesamt zurueck
- Log 08:13:20 zeigt sauberes "roamed to" zwischen zwei APs -> Roaming intakt
- Geraete-Backup vorher: pre-tp25-funde-ftoverds.backup

Governance: Transaktion TP25-fund-e-ft-over-ds OFFEN (Scope wifi-security,
Ablauf 2026-09-03). Compliance steht deshalb ABSICHTLICH auf 134/135; der Diff
ist exakt ft-over-ds=yes->no, kein Kollateral-Drift durch die Re-Provisionierung.
Das GC-Template wird erst beim COMMIT nachgezogen -- vorher gruen machen wuerde
den laufenden Versuch unsichtbar machen, und gc-transaktion.py verweigert den
Commit ohnehin, solange der Scope driftet. 135/135 kommt nach der Messung zurueck.

Messstand nach 25 min: weiter 93, letzter reauthenticating 07:34:43 (vor dem
Eingriff). Logging nachweislich lebendig (593 wireless-Zeilen heute, beide SSIDs).
Noch kein Ergebnis, nur ein sauberer Schnitt.

Drei Funde:
- cap-wifiN-Karte hat sich beim Re-Provisionieren VERSCHOBEN: ap2 war 1/2 ->
  jetzt 3/5, ap3 war 5/6 -> jetzt 4/6, ap1 hat 1/2 bekommen. Wer die 07:xx-Zeilen
  gegen die neuen liest, ordnet dem falschen AP zu.
- Korrektur am Vormittagsbefund: main unterscheidet sich in ZWEI Attributen, nicht
  einem -- es ist auch die einzige SSID ohne wpa2-psk. Die Kontrollgruppe trennt FT
  und WPA3-only nicht. Wenn Hebel 1 und 2 beide nichts bewegen, ist
  authentication-types der naechste Kandidat, NICHT signal-range.
- gc-transaktion.py rief sshpass -p auf (Passwort in argv, Klasse vom 2026-08-22).
  Auf SSHPASS-Env + -e umgestellt, weil das Skript laufen musste. Fuenf weitere
  Dateien unter routeros/ haben dasselbe Muster und sind bewusst NICHT angefasst
  (Stop-Bedingung; gehoert zu TP30). Entwarnung: /export auf 7.24 gibt Passphrasen
  gar nicht aus (live geprueft), die Transaktionsakte im Git ist sauber.

Nebenbei: .gitignore hatte docs/nas-vlan20/stacks/ MIT Schraegstrich -- im Worktree
liegt dort ein Symlink auf den Haupt-Checkout, der war damit nicht ignoriert.

Doku an allen drei Stellen nachgezogen (Quick-Index, TP25-Abschnitt, Ist-Stand-Block)
plus CLAUDE.md-Pflichtlektuere und neuer Handoff mit Entscheidungstabelle fuer 09-01.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 08:19:31 +02:00
40ffab1de8 TP25 Fund E: Befund nach einer Nacht Logging -- Reauth-Schleife haengt an ft=yes, Hebelreihenfolge korrigiert
Das gestern eingeschaltete wireless-Logging hat binnen 16 h geliefert, was der 75-Zeilen-
Ringpuffer nie konnte: 559 Zeilen, davon 439 (79 %) von Christophs iPhone.

Entscheidend ist nicht die Menge, sondern die Trennschaerfe:
- `reauthenticating` tritt 93 von 93 Mal bei GENAU EINEM Client auf (dem iPhone)
- und 93 von 93 Mal auf GENAU EINER SSID (dirtyvader-main)
- was `main` von den anderen fuenf unterscheidet, ist EIN Attribut: ft=yes ft-over-ds=yes

Dieselben APs, dieselben Radios, derselbe Zeitraum, dieselben Clients -- die SSIDs mit
ft=no zeigen null Ereignisse. Das ist eine saubere Kontrollgruppe. Die WPA3+802.11r-
Hypothese, die ich gestern ausdruecklich als "Forenwissen, nicht in der MikroTik-Doku"
gefuehrt habe, ist damit durch eigene Messung gestuetzt.

Verlauf 2026-08-31 auf cap-wifi6: 07:25 (10x) -> 07:34 (21x), eskalierend, teils mehrere
pro Sekunde, endend mit einem Roam auf cap-wifi2 bei -89 dBm -- also der Flucht auf einen
25 dB schlechteren AP. Genau so sieht "Link weg trotz gutem Kontakt, dann Mobilfunk" von
der Infrastrukturseite aus.

KORREKTUR an meiner eigenen Priorisierung von gestern: 2g-probe-delay war als Hebel 1
gesetzt, weil es der ungefaehrlichste ist. Das war vor diesem Befund und ist falsch --
2g-probe-delay adressiert Band-Steering, hier liegt ein Authentifizierungsproblem vor.
Neue Reihenfolge: (1) ft-over-ds=no, (2) ft=no, (3) 2g-probe-delay, (4) signal-range.

Ebenfalls festgehalten: die zwei erfassten "not responding"-Abbruecke liegen bei -80/-76
dBm und sind NICHT dasselbe wie der Schwall -- die Ursprungsmessung vom 08-20 hatte -47.
Nicht zusammenwerfen.

Noch nichts am Funk geaendert. Der Hebel ist beschrieben, das Messrezept steht im Handoff,
und wifi-security ist nicht deploybar (TP22-Regel 1) -- die Aenderung muss am Geraet
erfolgen und das Template danach von Hand nachgezogen werden.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 07:57:36 +02:00
810126c01b Doku: bf-infra hat seit 2026-08-30 ein Gitea-Remote (Backup-Luecke geschlossen)
CLAUDE.md und README.md behaupteten beide noch den Inventur-Stand vom
2026-08-27: "lokal, kein Gitea-Remote (Working-Copy). Verloren bei
Festplattencrash." bzw. "kein Gitea-Remote (Sicherheitsluecke, offen)".

Live geprueft: origin = https://gitea.emsenhuber.net/admin/bf-infra.git,
main lokal und remote identisch. Die Luecke ist zu.

Dazu der Hinweis, der die Aussage traegt: ein Remote ist nur so viel wert wie
der letzte Push - der Backup-Guard (TP35 Schicht 5) ist genau diese
Erinnerung und wird nicht mit --no-verify umgangen.

docs/handoff-20260827-inventur-und-architektur.md bleibt unveraendert - der
Handoff ist ein historischer Snapshot und war an dem Tag korrekt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 07:52:33 +02:00
175486221b TP25 Fund E wieder geoeffnet + WLAN-Logging persistent (27. ComplianceRule system-logging)
Auslöser war eine unabhaengige Meldung: seit Tagen/Wochen verliert das iPhone den
WiFi-Link bei gutem Signal und landet auf Mobilfunk. Auf Mobilfunk zu fallen ist KEIN
Roaming-Problem -- bei schlechtem Roaming bliebe das Telefon im WLAN und waere nur
langsam. Es heisst, die Assoziation ist gestorben und die Neuanmeldung gescheitert.

Der Manager-Log zeigt dasselbe iPhone (F2:62:4C:E1:AF:09) mit 16 Bandwechseln in 20
Minuten zwischen ap3s 5-GHz- und 2,4-GHz-Radio, zweimal im Abstand von einer Sekunde,
bei -53..-81 dBm -- kurz darauf dasselbe an ap2. Also nicht ap3-spezifisch.

Das stand schon im Repo: TP25 Fund E beschreibt es seit dem 2026-08-20, mit derselben
MAC und der Zeile "disconnected, not responding, signal strength -47" -- Abbruch bei
ausgezeichnetem Signal. Fund E war zurueckgestellt mit der Auflage "erst wieder
aufgreifen, wenn ein Sticky-Fall erneut gemessen ist". Die ist eingetreten. Das ist
heute der zweite Fall (nach dem TP25-Kanalplan fuer ap3), in dem eine fertige Analyse
im TP-Body stand und ich sie erst nach einer Extrarunde gefunden habe.

Der eigentliche Mangel war aber die Beweislage: `wireless` lief NUR nach action=memory,
nur `firewall` ging in den Kollektor. Der Ringpuffer fasste 75 Zeilen und war von einer
Stunde ap3-Arbeit fast ueberschrieben -- rueckwirkend war nichts diagnostizierbar.

Jetzt: zwei Regeln am Core (topics=wireless und topics=caps) in denselben Kollektor wie
TP5 (10.40.20.18:514). Gegenprobe auf beiden Seiten -- 32 Zeilen liegen bereits im
Tagesfile, inkl. `associated` (debug) und `connected` (info).

Und unter Drift-Kontrolle, denn /system logging stand unter KEINER der 26 Rules und gar
nicht im Template: neue ComplianceFeature/Rule `system-logging` (Muster: TP6 /queue,
TP26 /ip firewall filter), Template-Block [6a2] nur im Core-Zweig -- RouterOS exportiert
Defaults nicht, auf ap1/ap2/ap3/branch sind Soll und Ist beide leer.
Compliance 130/130 -> 135/135, 0 Drifts. Die Zahl MUSS sich bewegen: eine
gleichbleibende Zahl nach dem Hinzufuegen einer Regel waere ein Befund, kein Erfolg.

Zwei RouterOS-Fallen, beide als Gotcha in CLAUDE.md:
- Der Topic heisst `wireless`, NICHT `wifi` -- auch auf dem neuen wifi-qcom-Stack.
  Ein geratenes topics=wifi waere wirkungslos geblieben.
- RouterOS UND-verknuepft Topics innerhalb EINER Regel (`info,!firewall` = info UND
  NICHT firewall). `topics=wireless,caps` haette NICHTS gematcht -> zwei Regeln.

Recherche-Ergebnis gegen die offizielle MikroTik-Doku, das meine eigene erste Hypothese
widerlegt: transition-threshold steht per Default auf -80 dBm (-time 10s,
-request-period 30s, -count 3), und unsere Steering-Objekte setzen davon nichts. Bei
-53..-74 dBm wird das iPhone gar nicht Transition-Kandidat -- unsolicited BTM scheidet
als Treiber weitgehend aus. Die vielzitierte WPA3/802.11r-Inkompatibilitaet steht NICHT
in der Doku (dort nur: FT geht nicht ueber OWE); sie bleibt Hypothese.

BEWUSST NICHT geaendert: kein einziger Funk-Parameter. Drei Hebel sind dokumentiert und
priorisiert -- (1) 2g-probe-delay=yes, kann keinen Client stranden lassen, (2)
ft-over-ds=no, nimmt die Aenderung vom 2026-08-17 zurueck, (3) signal-range-Boden, der
invasivste und einzige, der Clients aussperren kann. Einzeln, je als Transaktion, erst
mit Daten.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 21:11:48 +02:00
1006f91e6a TP28: ap3 (cAP ax) live als CAP, ap1 funkstill, Compliance 130/130 ueber 5 Geraete
Der dritte Access-Point laeuft: 10.40.99.13 auf vlan99, Uplink ether1 -> core ether21,
reiner CAP unter crs326-core, Kanaele 5180/ax/Ce/I und 2437/ax (ch6) -- am Geraet
nachgemessen, nicht aus dem Plan abgeschrieben. Der Kanalplan stammt aus TP25 vom
2026-08-24; mein erster Entwurf hatte ihn neu erfunden und waere bei ch1 statt ch6
gelandet. Lehre: den TP-Body lesen, nicht nur den Quick-Index.

ap1 hat bewusst KEINE Provisioning-Regel mehr: es steht bis zu seinem Umzug ans
Sideboard direkt neben ap3 und wuerde auf 5180 kollidieren. Geraet bleibt erreichbar,
die Objekte ch-*-ap1 / cfg-main-*-ap1 bleiben fuer den Umzug stehen.

Bring-up in zwei Phasen ueber ein Patchkabel ap3 ether2 -> core ether22, weil ueber
ether1 nichts ging (s.u.). Loop-Schutz: ether21 war waehrend Phase 1 abgeschaltet und
wurde im selben Befehl gegen ether22 getauscht. RouterOS 7.20.8 -> 7.24.1 plus
RouterBOOT (zwei Reboots, TP27-Kriterium erfuellt). Die anderen vier stehen auf 7.24 --
die Angleichung ist ein eigener Durchgang, der Core-Reboot ist ein Standort-Ausfall.

Nautobot: DeviceType "cAP ax", Device ap3 mit 16 Interfaces, primary_ip4, secrets_group,
ConfigContext 5g=ch36 2g=ch6 extra_ports=[]. Nebenkorrektur: ap1 stand auf "Wohnzimmer
Sideboard", steht physisch aber in Technik UG (User-Bestaetigung).

Sechs Funde, alle als Gotcha in CLAUDE.md und im Handoff:
- ether1 ist am Werksgeraet WAN: Discovery aus, Input-TCP verworfen, ICMP aber erlaubt.
  Es pingt, und das liest sich wie "erreichbar". MikroMCP hilft nicht -- Port 80 ist zu.
- pvid ist Ingress, tagged/untagged ist Egress. Ein Lease hing ewig auf "offered", weil
  der ACK getaggt rausging und ein Werksgeraet das nicht versteht.
- `cap enabled=yes` reicht nicht: jedes Master-Radio braucht configuration.manager=capsman,
  sonst bietet der CAP seine Radios gar nicht an -- state=Ok, radio-Tabelle leer.
- Ein Geraet ohne secrets_group erzeugt eine LUECKE, keine Fehlermeldung: Backup scheitert
  still, keine Compliance-Eintraege, Zahl bleibt unauffaellig bei 104/104. Eine
  gleichbleibende Compliance-Zahl nach dem Hinzufuegen eines Geraets ist ein BEFUND.
- CAPsMAN verteilt keine Login-Passwoerter, nur WLAN-PSKs. Der Geraete-Login ist eine
  lokale DB pro Geraet; das einheitliche Admin-PW ist eine Konvention von Hand.
- Firewall-Regelnummern aus `print where` sind Handles, keine Positionen. Beweis ist der
  Zaehler, nicht die Zahl.

Abnahme: 3 CAPs state=Ok, VAP-Satz vollstaendig und running, 20 IOT-Clients auf ap3 mit
0 % Ping-Verlust ueber VLAN30 (bewusst nicht ueber die Registration-Table abgenommen),
Compliance 130/130 / 0 Drifts, Core-Temp-Pfad restlos abgeraeumt.

Offen: TP25-Messrunde (braucht Rundgang), PW-Rotation TP30, MikroMCP-Neustart.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 17:54:07 +02:00
fd05286e4b TP28 wieder geoeffnet: ap3 (cAP ax) vorbereitet, core ether21 Trunk, MikroMCP-Registry auf bf-infra
Dritter Access-Point ap3 (MikroTik cAP ax, cAPGi-5HaxD2HaxD) kommt dazu und loest
mittelfristig ap1 in Technik UG ab. Statt eines neuen TP wandert TP28 aus dem Archiv
zurueck -- neue Regel: ein archiviertes TP ist ein geschlossenes, kein versiegeltes
Ticket (Christoph-Direktive 2026-08-30).

Live am Core:
- ether21 ist AP-Trunk (10/20/30/40/50/90/99 tagged, Muster ether15). ⚠️ Erratum: erst
  war ether22 angenommen und getaggt; der Port hat keinen Link. Gegenprobe ueber die
  Bridge-Host-Tabelle: auf ether21 sitzt D0:EA:11:FF:16:9D = E01 vom ap3-Label.
  ether22 wieder leer.
- Backups vorher: pre-ap3-20260830.backup/.rsc auf core und ap1.
- Compliance vor und nach jeder Aenderung 104/104, 0 Drifts.

Golden Config (2 Pushes: e25d654b, 20472cdb):
- Core-L2-Block traegt ether21.
- AP-Zweig rendert die Bridge-Ports jetzt aus ap.extra_ports statt hartkodiert
  ether3/4/5. Das war die stille Annahme "AP == hAP ax2 mit 5 Ports"; der cAP ax hat
  zwei. Default in ap-common = hAP-ax2-Bestand, ap3 ueberschreibt mit [].
  Dass ap1/ap2 danach zeichengleich rendern, beweist die 0-Drift-Messung.

Kanalplan NICHT neu erfunden: TP25 hat ihn am 2026-08-24 fuer genau dieses Geraet
gerechnet (DFS vom User genehmigt). ap3 = 5180/Ce + 2437 (ch6, nicht ch1 -- ch1 bleibt
fuer ap1, damit 1/6/11 erstmals lueckenlos aufgeht). ap1/ap2 gehen beim Umzug auf
5260/Ce bzw. 5300/Ce, 5220/Ce bleibt Ausweichspur.

MikroMCP-Registry (MCP-Lifecycle, User-Freigabe 2026-08-30) -- zwei Drifts:
- MIKROMCP_CONFIG_PATH zeigte auf ~/dev/bf-network-r6 (Archiv-Repo); die identische
  Datei in bf-infra war wirkungslos. Jetzt bf-infra = SSoT.
- In opencode.jsonc fehlte MIKROMCP_CONFIG_PATH ganz, hinterlegt waren nur ap1/ap2 --
  opencode kannte core/branch gar nicht. Beide Clients zeigen jetzt auf dieselbe
  Registry; ap3 aufgenommen, rosVersion von stale 7.23/7.19.5 auf 7.24 korrigiert.
  Neustart des MCP noetig, Registry wird nur beim Start gelesen.

Noch offen: physischer Bring-up (Datei liegt bereit), ap1-Radios aus, CAPsMAN-Objekte
fuer ap3, Nautobot-Adoption, Messrunde -- und die Passwort-Rotation: das gemeinsame
MikroTik-Admin-PW ist in dieser Session durch eine ungefilterte Ausgabe des
mikromcp-env-Blocks ins Transkript geraten und gilt als verbrannt (Posten fuer TP30).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 12:14:21 +02:00
dd12ab505b Korrektur: bf-infra HAT ein Gitea-Remote (Inventur-Aussage vom 08-27 ueberholt)
CLAUDE.md behauptete "lokal, kein Gitea-Remote (Working-Copy). Verloren bei
Festplattencrash." Live geprueft 2026-08-30:
  origin = https://gitea.emsenhuber.net/admin/bf-infra.git
  origin/main = b917691 (Handoff 2026-08-28)
Das Remote existiert also seit spaetestens 2026-08-28. Die Aussage war bei
der Inventur am 08-27 richtig und ist seither ueberholt -- nicht falsch
erhoben, sondern nicht mitgezogen.

Anlass: eine Session hat die Zeile uebernommen und "lokaler Master ohne
Gitea-Remote" behauptet, statt `git remote -v` zu tippen. Genau der Fall aus
dem Lessons-Block "Kommentar in Code != Verhalten". Merkregel deshalb an der
korrigierten Zeile verankert.

CLAUDE.md: Zeile direkt korrigiert (lebende Anweisungsdatei).
Handoff 2026-08-27: Originalzeile bewusst erhalten, Korrekturvermerk
darunter -- historische Fassungen werden hier nicht umgeschrieben.

Die Backup-Luecke bleibt real, hat aber eine andere Ursache als notiert:
nicht fehlende Struktur, sondern ungepushte Commits (am 08-30 waren es vier).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 11:43:24 +02:00
b8fd42b3fd shelly-mcp: mcp<2 pinnen + TP30 Posten #3 hochstufen
Container crashte beim ersten Deploy mit 'No module named mcp.server.fastmcp':
PyPI hat mcp 2.x als aktuellste Version, FastMCP wurde dort zu MCPServer
umbenannt. Repo-Code (server.py) nutzt noch v1-API.

Fix: requirements.txt 'mcp[cli]>=1.0,<2' — hält den Server auf v1-kompatibel.

Deploy-Ergebnis:
- Container shelly-mcp auf DS923, IP 10.40.20.180 (macvlan vlan20)
- Health /health: 200, psk_configured:true, iot_ssid=dirtyvader-iot
- StreamableHTTP /mcp: serverInfo 'shelly-mcp 1.29.1'
- Live-Sweep 10.40.30.180-250: 23 Shellys erreichbar

TP30 Posten #3 (Shelly-Gerätepasswort) hochgestuft: SHELLY_DEVICE_PW ist im
Zuge dieses Deploys erneut in ein Sitzungstranskript geraten (sed-Pattern
'SHELLY_DEVICE_PW=.*' hat den Wert nicht maskiert, weil der Replacement-
String zu wenig greedy war — neuer Lessons-Block-Eintrag). Reihenfolge:
erst Werkzeug-Härtung (Stream-Filter statt cat+sed), dann Posten #3
rotieren. CLAUDE.md hat den Lessons-Eintrag, TP30 Posten #3 hat die
Hochstufungs-Begründung.
2026-08-28 21:27:05 +02:00
c25888acd9 Lessons: Skills sind IMMER global, niemals pro Projekt 2026-08-28 19:47:30 +02:00
b4cd417e8d Lessons: opencode-TUI-Leading-Space als bekannter Bug dokumentiert (Issue #27528, status 'Not planned') 2026-08-28 19:30:35 +02:00
55b3453d41 Lessons-Checkliste: Output-Länge als Regel 6 ergänzt 2026-08-28 19:27:21 +02:00
d06d505bc3 TP36 angelegt + Ist-Stand-Block aktualisiert + zwei Lessons-Eintraege
Befund 2026-08-28 nach Skill-Verifikation in opencode:
- Der 'Nächster Schritt (2026-08-26)'-Absatz war zwei Tage veraltet
  (drei Sessions waren parallel offen)
- Manuelle Doku mit Live-Daten verliert gegen die Realitaet, sobald
  die Datei lang wird (1940 Zeilen, drei Stellen pro Edit)

Reaktion:
1. 'Nächster Schritt' umgeschrieben: drei Folge-Sessions A/B/C aus
   dem gestrigen Handoff, klar als 'parallel' markiert. A ist erledigt
   (TP35 Schicht 6), B+C offen.
2. TP36 als Folge-TP neu angelegt: SSoT via Nautobot fuer
   teilprojekte-Live-Daten + Datei-Aufteilung (Index / Snapshot /
   Archiv). Eigene Session, nicht heute.
3. CLAUDE.md: zwei Lessons-Eintraege:
   a) opencode-TUI: fuehrendes Leerzeichen vor /command manchmal
      noetig (Beobachtung, kein Skill-Bug)
   b) Manuell gepflegte Doku verliert gegen Realitaet, Merkregel:
      drei Stellen pro Edit mitlesen (Quick-Index, TP-Abschnitt,
      Ist-Stand); strukturelle Antwort = TP36

Lessons-Block hat jetzt 7 Eintaege (Stand 2026-08-28).
2026-08-28 19:23:28 +02:00
8c1876c1d6 TP35 Schicht 6: /projektstatus-Skill in opencode aktiviert + Doku
- CLAUDE.md: zwei Lessons-Eintraege (opencode-Default-Pfad kopieren,
  nicht symlinken; Kommentar in Code != Verhalten)
- teilprojekte.md: TP35 Quick-Index auf 'Schicht 6 erledigt, Rest offen',
  Schicht-6-Befund im TP-Block, Ist-Stand auf 2026-08-28 mit MCP-Bestand-
  Korrektur
- handoff-20260828-session-a-projektstatus.md: Session-A-Bericht mit
  Drift, Befund, Entscheid, Lehren fuer Session B

Skill selbst liegt in ~/.config/opencode/skills/projektstatus/SKILL.md
(cp aus ~/.claude/skills/projektstatus/, byte-identisch) - opencode
scannt diesen Default-Pfad, kein skills.paths-Eintrag in der JSONC
noetig.
2026-08-28 19:15:02 +02:00
759491b512 MCP-Bestand korrigiert + Mac-mini-Performance-Restriktion
- gitea-mcp + n8n-mcp nachgetragen (waren real live, aber aus dem Inventar verschollen)
- pve-mcp: SSE-Doku -> StreamableHTTP-Realitaet
- shelly-mcp/portainer-mcp: bewusst KEIN MCP-Client (User-Direktive 2026-08-28)
- Mac mini = n8n-Host, NICHT zentraler MCP-Host (Performance-Restriktion)
- ~/.claude.json + opencode.jsonc: 9 MCPs identisch (vorher 7 vs. 11 Asymmetrie)
- docs/mcp-host-policy.md: SSoT fuer Host->FQDN/Stack-Mapping
- docs/handoff-20260828-mcp-bestand-und-performance.md: Folge-Sessions A/B/C

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-28 18:40:05 +02:00
046f103a89 claude.md + handoff: shelly-mcp-Tote erkannt, MCP-Lifecycle-Regeln
- shelly-mcp läuft auf keinem Host (kein Mac-Prozess, kein Container auf
  NAS/pve). INVENTORY-Handoff hatte den Stand nicht aktualisiert.
  Config jetzt enabled=false, neuer Punkt im Ist-Stand-Block.
- 3 neue Lessons-for-Sessions-Regeln: MCP-Änderungen aktiv melden,
  Host vor Edit verifizieren, tote MCPs ins Projekt-Repo.
- 'Was du sofort wissen musst' um shelly-mcp-Tote ergänzt.
2026-08-28 14:24:31 +02:00
c2b075eaf1 claude.md: Pflichtlektüre + Master-Struktur gekürzt, Lessons for Sessions ergänzt
- Header (Z.1–23): Inventur-Hinweise rein, Master-Struktur (bf-infra/bf-network-r6/
  bf-golden-config/blaueblueten-n8n) als eigener Block, terpene-Stand.
- Pflichtlektüre-Reihenfolge explizit (1. teilprojekte.md Quick-Index, 2. handoff,
  3. cf-tunnel-mapping/archiv bei Bedarf, 4. Inventur-Handoff).
- 'Lessons for Sessions' als neuer Abschnitt am Ende: 4 Verhaltensregeln
  (Bestandsaufnahme vor Plan, große Fragenrunde, Master-Frage früh,
  Drift vor Lösungen) + Checkliste vor Edit-Vorschlägen.
2026-08-27 21:36:46 +02:00
9b60bcc43a opencode: Permission + Quick-Index + TP-Management-Regel
- opencode.jsonc: permission=allow + mikromcp/pve-mcp/home-assistant/cloudflare MCPs
- docs/teilprojekte.md: Quick-Index-Tabelle (22 Zeilen) für 1-Read-Statusbaum
- CLAUDE.md: TP-Management-Regel (vorschlagen -> abstimmen -> anlegen)
2026-08-26 13:39:41 +02:00
5ee0716dda Initial import from bf-network-r6.opencode — opencode migration 2026-08-26 12:44:21 +02:00