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>
Nautobot-Tooling
ingest-baseline.py
Idempotenter Basisdaten-Ingest (Locations, Rollen, Device-Types, Devices, VLANs/Prefixes, ap1-Interfaces + IPs, WLAN-Modelle). Bildet den Ist-Zustand ab, nicht den Zielzustand.
export NAUTOBOT_TOKEN=... # aus docs/nas-vlan20/stacks/210-nautobot.yml (gitignored)
python3 nautobot/ingest-baseline.py # Dry-Run
python3 nautobot/ingest-baseline.py --apply # schreiben
API-Fallen (teuer gelernt)
tagged_vlansliest sich per REST alsnull, obwohl korrekt gespeichert. Verifikation nur über GraphQL:POST /api/graphql/mit{interfaces(device:"ap1"){name mode untagged_vlan{vid} tagged_vlans{vid}}}.- Relationen kommen ohne
?depth=1ohnedisplay→ ein voll gepflegtes Device sieht leer aus. LocationType.content_typesmussipam.vlangroup/ipam.vlan/ipam.prefix/dcim.controllerenthalten, sonst 400 beim Anlegen.parent_interfacenur für virtuelle Interfaces — WLAN-VAPs können ihren Master nicht als Parent tragen.WirelessNetworkhat kein VLAN-Feld; die VLAN-Bindung hängt anwireless/controller-managed-device-group-wireless-network-assignmentsund braucht zwingend einenController(bei uns logisch,controller_deviceleer — kein CAPsMAN).RadioProfile.channel_widthwill Integer ([20,40,80]), nicht"20mhz".- IP↔Interface läuft über
/ipam/ip-address-to-interface/.
ingest-wifi-access-list-rule.py
Legt ComplianceFeature + ComplianceRule wifi-access-list an (Plattform RouterOS,
match_config=/interface wifi access-list). Idempotent, Dry-Run ist Standard.
export NAUTOBOT_TOKEN=...
python3 nautobot/ingest-wifi-access-list-rule.py --apply
Warum es die Rule braucht: ohne sie erzeugen Eintraege in der access-list keinen Drift
und lassen sich nicht als Config-Transaktion fuehren -- gc-transaktion.py verlangt eine
ComplianceRule als --scope. docs/tp25-pin-s22.sh schreibt dort bei jedem Messrundgang, und
TP25 Fund E (signal-range-Boden) landet dauerhaft dort.
Der Soll-Zustand ist leer und steht als Kommentarblock [6c] im Template. Waehrend eines
Messlaufs ist der Drift erwartet und gehoert als offene Transaktion gefuehrt.