Neue IPs .110/.121/.130 werden zuerst am Core generiert (Sekundaer-IP auf
vlan20 + 1:1-NAT aufs Geraet), gemessen wird ab Tag 1 mit zwei Zaehlern
(neue IP = wer ist umgestellt, Alt-IP = ist noch was los). Das Geraet wird
erst angefasst, wenn seine Alt-IP still ist ("siedeln"). Alles ins Soll,
nicht als Transaktion. NAS siedelt zuletzt und gemeinsam.
Warum NAT statt Routing: im selben Subnetz antwortet das Geraet dem Client
direkt per L2 -- er verwirft die Antwort von .10 auf eine Verbindung zu .110.
Vorabcheck: NAS-NFS/iSCSI sind IP-ACL'd, aber ohne lebende Nutzer (pve hat
null NAS-Mounts) -- der src-nat-Umweg bricht nichts. Nebenbefund: die
Exports stehen auf totem 10.40.41.x plus drei 10.0.0.0/8-Freigaben.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Nach dem Streichen der Ausnahme durfte die Wortwahl nicht mehr nach
sofortiger Einzelrotation klingen. Posten #4 ist anlass- aber weiterhin
gebunden; beide Stellen sagen das jetzt explizit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Die Klausel zog bei einem neuen Leak eine sofortige Einzelrotation vor und
widersprach damit dem Buendelungszweck des TPs (Kostentreiber sind die
Konsumenten, nicht das Setzen) und der gelebten Praxis: auch die
leak-getriebenen Posten #1 und #5-#9 blieben gebuendelt.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Der Posten hing an einem harten Termin ("laeuft am 2027-01-09 ab"), der nicht
mehr existiert: dieses Datum gehoerte zum laengst revokten Alt-Token
9984078812bc..., waehrend das live CF_API_TOKEN (id 493ed8bd...) gar kein
Ablaufdatum hat (expires_on: null, verifiziert ueber /accounts/{id}/tokens/verify).
Damit ist die Rotation anlass- statt termingetrieben — Ausloeser ist jetzt der
Leak vom 2026-09-21 (Wert in einer Session-Ausgabe sichtbar geworden).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
36 DHCP-Reservierungen wandern aus dem Pool-Fenster (.5, .8, .202-.244)
in die Schema-Baender .11-.14 / .151-.176 / .177-.196. Dazu die CCU-Leiche
.232 (status=waiting, last-seen=never; die CCU lebt in VLAN20) entfernt und
SONOFF-NSPanelPro von einer dynamischen Lease auf .249 zu einer statischen
Reservierung auf .12 gepinnt.
Neuer Job `tp45-v30-leases` in gc-configplan.py. Er laedt MOVES/REMOVE/ADDS
per importlib aus tp45-leases.py, statt sie zu kopieren -- die Tabelle dort
ist die SSoT des Umzugs, eine zweite Kopie liefe still auseinander.
Warum der Job zwei Selektor-Formen traegt: die erste Fassung schrieb
ueberall `[/ip dhcp-server lease [find where ...]]`. In `[:len ...]` ist das
Syntaxfehler (`expected command name (line 1 column 55)`, live gemessen) --
Golden Config meldete trotzdem Job SUCCESS und Plan Completed, das Geraet
blieb unveraendert. Aufgefallen ist es an der Zahl der Log-Zeilen: von 38
`:if`-Statements hat kein einziger Zweig geloggt. Richtig ist
`[/ip dhcp-server lease find where ...]` ohne Klammerpaar um `find`;
die Argument-Form `set [find where ...]` bleibt.
Abnahme am Geraet, nicht am Plan-Status: 39 Leases im Soll-Schema, .232 und
.249 geraeumt, NSPanelPro dynamic=false; Compliance 145/145, keine Drifts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Erster Lauf nach dem Einbau ergab 144/145 -- und die eine Drift war mein Fehler,
nicht der des Geraets: backup_lines() strippte mit l[1:] nur das fuehrende '/',
nicht den ganzen Befehl. Das gerenderte Soll enthielt dadurch
`/ip dhcp-server lease ip dhcp-server lease add ...`.
Gefunden hat das die Compliance-Zahl selbst. Genau deshalb ist der NENNER die
Abnahme und nicht der Zaehler: 140 -> 145 beweist, dass die neue Rule auf allen
fuenf Geraeten auswertet; 145/145 beweist, dass das Soll stimmt.
Ausserdem: seed --force fuer einen bewussten Neuschnitt (der Guard gegen
versehentliches Re-Baseline bleibt).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Die 54 statischen Reservierungen des Cores standen in KEINEM Soll: das Template
rendert kein einziges /ip dhcp-server lease, und die Sektion stand unter keiner
ComplianceRule. Ein GC-Recovery von null haette einen Core ohne Reservierungen
erzeugt, in dem jedes IoT-Geraet in den Pool faellt -- und weil Compliance nur
prueft, was gerendert wird, waere die Zahl dabei gruen geblieben. Dieselbe
Luecke wie die handgelaufene `nautobot`-Adressliste.
- mikrotik_routeros.j2 [5b]: rendert local_config_context_data.dhcp_leases,
gleiches Idiom wie firewall_filter.
- tp45-leases.py: seed/move/check. Zeilen werden verbatim uebernommen und nur
im address=-Token getauscht -- das erhaelt Quoting und die 14 client-id-Felder.
Reihenfolge bleibt die Geraete-Reihenfolge (Einfuege-, nicht numerisch).
- ingest-dhcp-lease-rule.py: Feature+Rule `dhcp-lease` auf RouterOS,
config_ordered=False.
Noch KEIN Geraetewrite -- der Ist-Stand wurde als Soll gesetzt (Re-Baseline).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Die 7 DHCP-Pools starteten alle bei .100 und ueberlappten damit die beiden
Oktett-Baender, die dieses TP gerade belegt: .100-.149 (Server-Hosts) und
.150-.199 (App-Services). In VLAN20 ist das eine echte Kollisionsflaeche --
nautobot .154-.158, gitea .157, pve-mcp .173 und shelly-mcp .180 tragen ihre
IP GERAETELOKAL und stehen in keinem Lease-Eintrag, der Core kann sie also
nicht schuetzen und einem DHCP-Client .154 anbieten.
Entscheid 2026-09-21: nur pool-v20 und pool-v30 werden verengt, v20 zuerst.
VLAN10/40/50/90/99 bleiben bei .100-.200 -- dort gibt es kein Schema-Band,
das etwas gewoenne, und VLAN40/VLAN10 haetten sonst 11 Sonos (.191-.201),
den iPhone (.196) und den Mac (.82) mitgezogen.
VLAN20 kostet die Verengung nichts: eine statische Reservierung (nas-bf
.20.10, in .10x) und 0 dynamische Leases.
pool-v30 bleibt bewusst unangetastet -- dort liegen 35 statische
Reservierungen IM Fenster .200-.249 (26 Shellys .202-.226/.233, SwitchBot
.227, Twinkly .228, Withings .230/.231, lichterketten .236/.237, Nuki
.241/.244, CCU .232). Erst Schicht B zieht die um, dann pool-v30.
Nebenbei faellt damit die .30.250-Kollision: der Sonoff Dongle-M sitzt dort
statisch, der Pool reicht heute bis .250.
Neuer Job `tp45-pool-v20` (gc-configplan.py) mit gezaehltem Selektor: ein
`find where`, das 0 trifft, sieht wie "nicht vorhanden" aus statt wie
"kaputt" -- ein blankes `set [find where name=...]` liefe ins Leere und der
Job meldete Erfolg.
🔴 Lehre aus dem ersten Fehlversuch: jedes config_set-Statement muss auf EINER
Zeile klammer-vollstaendig sein. Mit `:if (...) do={` am Zeilenende geht
RouterOS in den Fortsetzungs-Modus und zeigt einen anderen Prompt, der
netmiko-Treiber verliert sein Muster und der Deploy stirbt mit
`E1015: Pattern not detected: ...@crs326\-core\].*$|#.*$)` -- Plan auf
Failed, ohne etwas geschrieben zu haben.
Abnahme: Gerate-Read pool-v20 = 10.40.20.200-10.40.20.249 (total=50,
used=0); DHCPOFFER-Probe auf vmbr0.20 -> 10.40.20.200 mit
Domain Name Server 10.40.20.30, 10.40.20.31; Probe-Lease wieder entfernt;
Compliance 140/140 ohne Drift.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Die vier Core-Forward-Regeln fuer den Resolver waren nachgezogen, die
DHCP-Antwort an die Clients noch nicht: /ip dhcp-server network trug
weiterhin dns-server=10.40.20.36,10.40.20.37. Ein Client haette nach dem
AGH-Umzug den Resolver unter der alten Adresse gesucht.
Template geaendert, nach bf-golden-config gepusht (Git-DataSource ist die
Wahrheit, nicht die lokale Datei), Git-Sync, am Core gesetzt (alle 7 Netze),
per DHCPOFFER-Probe auf vmbr0.20 bestaetigt (Domain Name Server:
10.40.20.30, 10.40.20.31), Compliance 140/140 ohne Drift.
Randbefund (nicht in diesem Commit): die 7 DHCP-Pools starten live bei .100
und ueberlappen die Schema-Baender .100-.199 — pool-v30 reicht sogar bis
.250, wo statisch der Sonoff Dongle-M sitzt. Entscheid 2026-09-21: nur
pool-v20 und pool-v30 werden auf .200-.249 verengt, v20 zuerst.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- nautobot/tp45-agh-firewall.py (neu): pflegt die vier `TP5-E2: LAN->AGH dns*`-
Regeln im `local_config_context_data.firewall_filter` (add/remove, Dry-Run
default, Unified Diff). Bewusst NICHT `ingest-core-firewall.py` -- das ist ein
RE-BASELINE-Werkzeug und wuerde die Aenderung mit sich selbst absegnen.
- gc-configplan.py: Jobs `tp45-agh-fw` (add + move vor die Log-Regel; `caddy`
dahinter, damit der AGH-Block zusammenbleibt) und `tp45-agh-dhcp`.
Fix in `create_plans`: unter derselben `change_control_id` liegen nach einem
zweiten Lauf zwei Plaene. Die Auswahl folgte der REST-Reihenfolge und traf den
ALTEN -> der config_set-Guard brach ab, obwohl der neue Plan korrekt erzeugt
war. Jetzt gewinnt der juengste; die alten bleiben Historie.
Fund: `find where dst-address=<bare-IP>` matcht in RouterOS nie (nur `~` als
Regex). Die Zeile stand als "Verifikation" in
docs/transaktionen/TP23-agh-firewall.commands.rsc:7 und hat dort seit dem
2026-08-25 immer `0` gemeldet, ohne je etwas zu pruefen. Gleiche Klasse wie
`nc -z` (09-01): eine Pruefung, die 0 meldet, sieht wie "fehlt" aus, nicht wie
"kaputt".
Abnahme: Reihenfolge am Geraet (vier neue Regeln vor dem Drop), Compliance
140/140 / 0 Drifts mit `RouterOS - ip-firewall-filter` (ordered, frisch
bewertet, `actual` traegt die neuen Zeilen), `dig` vom VLAN10-Client gegen
.30/.31/.36/.37 alle beantwortet.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Oktett-Klasse .150-.199 (App-Services). Nautobot gibt damit .30/.31 an
AGH frei. .157 ist gitea, deshalb nimmt redis .158.
- Datenmigration ueber neues nautobot/tp45-ip-move.py: Nautobot verbietet
das Aendern einer IP nach dem Anlegen -> anlegen/primary_ip4 umhaengen/
Altobjekt loeschen, in dieser Reihenfolge
- Stack-Redeploy (PUT /api/stacks/203), Caddy-Backend, Core-Literal *24
ueber GC deployt (Plan 51a90e25) mit Wirksamkeitspruefung am Geraet
- caddy/deploy.sh: push_verified() ersetzt den push||push-Fallback.
`pct push` meldet Exit 0 AUCH wenn es die Quelle nicht lesen kann, der
Fallback griff deshalb nie und `caddy validate` pruefte die ALTE Datei
-> gruene Abnahme bei unveraendertem Zustand (Symptom: 502 bei
gesundem Backend)
- 39 Referenzen in 28 Dateien mitgezogen; lebende Doku nachgezogen
(CLAUDE.md, ip-plan.md, cf-tunnel-mapping §0-Kopf, TP16.3/TP31-Prosa)
- GC-Compliance 140/140, 0 Drifts
Neue Funde (TP45-Prosa + CLAUDE.md):
- Die Core-Adressliste `nautobot` wird von GC nirgends gerendert -> ein
Recovery von null erzeugt einen Core, in den Nautobot nicht mehr per
SSH kommt. Gleiche Klasse wie die fehlenden DHCP-Reservierungen.
- Regel *24 (Literal) und *28 (Liste) sind Dubletten; der Literal steht
bei 0 Paketen. Zusammenlegung bleibt offen.
- gc-manual-plan.py: /api/extras/job-log-entries/ liefert 404 (Nautobot
3.x) -> bei gescheitertem Deploy fehlt die Fehlermeldung.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bestandsaufnahme 2026-09-21 ergab: die FQDNs sind nicht in Caddy/CF
verschwunden, sondern (a) AGH wertet DNS-Rewrites im Filter-Pfad aus und
ueberspringt sie fuer unfiltrierte Clients -> Fallback auf den Core, der
nur 10 von 26 Namen haelt; (b) ds-bf ist der einzige Ingress-Eintrag, der
Caddy umgeht, und faellt damit unter TP5 deny-by-default.
- TP32-Oktett-Tabelle: .10-.19/.20-.29-Split, Server-Block .100-.149,
Broker/Funk .9x, Platform .8x, Alt-IP-Reservierung dokumentiert
- TP32-Ordnungsgruppe 40 auf 102/112 reduziert (CCU gehoert zu haos)
- TP37-Status: P1+2 waren als "offen" notiert, live sind 28 VMs/26 Services
- TP45 (VLAN20/30 ins Schema + DNS/FQDN) + TP46 (CF-SSoT/Recovery) als
Prosa-Abschnitt, Zeiger in der Pflichtlektuere
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
RouterOS exportiert comment=TP38-OOB-MGMT ohne Quotes (kein Leerzeichen),
das Template hatte sie gesetzt -> bridge-port Drift. Fix: unquoten.
Der Deploy-`place-before=[find ...]` wurde von Netmiko ignoriert (Regel
landete hinter dem drop); im Job jetzt add + move.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Template mikrotik_routeros.j2: ether23 auf core+branch als OOB-Port
(pvid=99, admit-only-untagged-and-priority-tagged) + VLAN99 untagged=ether23.
Branch bekommt einen deny-by-default-Input-Filter (8 Regeln, src-Rahmen
spiegelt /ip service available-from), Core eine Regel "OOB->core mgmt".
Neue Skripte: ingest-tp38-oob.py (seedet firewall_filter in beiden
local_config_context_data) und der gc-configplan.py-Job tp38-oob (Deploy).
ConfigPlans angelegt+approved, Deploy steht noch aus.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
RouterOS exportiert transition-threshold vor wnm; Template-Reihenfolge ans
Export-Format angepasst. Deploy über manuellen Plan (Plan cc8340a8) — 140/140.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Terrasse saß am Rundgang 09-15 auf der -80/5G-Kante. transition-threshold
-80→-72, transition-threshold-time 10s→5s — nur für 5G; 2,4G bleibt auf
st-main (unset -80) für Reichweite draußen.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Letzter offener TP25-Posten: Terrasse ein eindeutig dominantes Signal
geben (Ende von Band-Thrash und -89-Kollaps-Roams). Plan gemess Variante 3
(Deckenstrahler an den guten Platz, hAP in den Drei-Raeume-Schatten),
Vorher/Nachher-Terrassenmessung + Anruf-Abnahme, Kanalplan unberuehrt,
Config nur ueber GC-Weg. Issue #17, Kommentar #232.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Wireshark-Analyse (hms-mqtt-publisher PR #110, HMS-800W-2T): Poll <30 s
resettet den Countdown, Cloud-Updates fallen aus; nach 4-5 min startet
die DTU eine neue TCP-Session -- und dabei (Log-Beweis 09-14) eine
vollstaendige WiFi-Disassoziation inkl. DHCP-Churn. Zyklus-Abstaende
decken sich aufs Minutenkomma. Fund F damit neu interpretiert.
- Ursache: hmsmqtt 30500 ms (Grenzzone). Hebel = Poll-Rate, nicht
DNS-Hoheit: Christoph hat 45000 ms gesetzt (09-14 abends).
- Verifikation ab 09-15 frueh (Log-Lauf ohne 4-5-min-Zyklen = Fund-F-
Abschlussbeweis); Fallback: DTU-Firmware klaeren (ha-hoymiles-wifi#134).
- Issue #17, Kommentar #228.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Recherche 09-14 abends: HMS-XXXXW-2T (W = eingebaute DTU, protobuf-
Protokoll) wird von AhoyDTU/OpenDTU nicht unterstuetzt (lumapu/ahoy#1189
seit 09-2023 offen; Christophs eigene AhoyDTU inkompatibel). Lokale Tools
(hmsmqtt, dtuGateway, ha-hoymiles-wifi) nehmen die DTU nicht von der Luft.
Einziger Airtime-Heibel bleibt DNS-Hoheit ueber die Cloud -- von Christoph
bewusst zurueckgestellt (Cloud-Aufzeichnungen bis hmsmqtt + WLAN stabil).
Korrektur auch als Issue-17-Kommentar #227; Messplan #225 bleibt gueltig.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- DTU geht mit der Sonne an/ab (09-14: 07:09-19:35) -- nachts unbetelligt,
20:37-Verlust passierte ohne sie. Tagsueber ~5:05-Zyklus auf ch11 bei -53.
- Messplan (Issue #17, Kommentar #225): Referenz-Client auf ch11 pinnen,
30-60 min Ping, Korrelation gegen die 5:05-Taktmarken.
- Hebel falls messbar: OpenDTU/AhoyDTU-Dongle statt Cloud-DTU (5-Min-Takt
ist S-Miles-Telemetrie per Design, kein Ethernet an der DTU-WLite,
Pin auf anderen AP kontraindiziert).
- 20:37-Nachtrag zur Abnahme: Totalverlust eigener Klasse (-89-Roam +
iOS-Aufgeben, identisch 19:01 mit ft=no) -- keine ft=yes-Regression.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Live-Beleg 2026-09-14 20:33-20:34, Terrasse: nur roamed-to-Events, keine
disconnected-Zeile mehr im Fenster (davor 20:29/20:31 noch zwei volle
Trennungen). Hebel (1) damit komplett abgenommen; offen bleibt nur noch
der Deckungsfix Variante 3.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- CLAUDE.md: 09-04-Entscheid (ft=no) mit Ruecknahme 09-14 konsistent gemacht —
Weg, Plan-ID, Compliance-Stand und CAP-Abnahme vermerkt, damit keine
Folgesession einen ft=no-Zustand liest, der nicht mehr existiert.
- teilprojekte.md TP25: Hebel (1) auf DURCH gesetzt (Sequenz, Plan b1135f3e,
Asserts, Polling-Timeout-Folgenlosigkeit), offene Abnahme = Terrassen-Anruf.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kontextkommentar ueber der sec-main-Zeile dokumentierte noch den 09-04-Entscheid
(ft=no); nach der Ruecknahme am 09-14 konsistent gemacht (Entscheid-Historie bleibt
als Zeile erhalten).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Go Christoph 2026-09-14 nach Terrasse-In-situ-Session: mit ft=no ist jeder
Roam eine Voll-Reassoziation -- darin starben 2 Anrufe.
- Known-Good-Stand vor Hebel-2: Fund-E-Abschlussmessung 09-02 lief auf
ft=yes/ft-over-ds=yes + 7.24.1 ruhig (4 reauth/8,6 h, 0 Ausfaelle).
- Template [6c]-Kommentar auf Stand 09-14 gebracht: signal-range-Boden
geprueft und gescheitert (kein band-Property, cap-wifiN-Rejoin-Falle).
- Commands-File docs/transaktionen/TP25-ft-yes-secmain.commands.rsc fuer
den GC-Deploy via gc-manual-plan.py (Dry-Run gelesen).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Handoff 2026-09-14: iPhone-Flapping auf der Terrasse = 5-GHz-Zellkante
(-76..-81) plus client-getriebene Band-Wechsel in der Uberlappungszone
-70..-77; vor ap2 (1-2 m) -49..-51 dBm, >2 min stabil => HW-Verdacht
(23:02-Befund 2 m/-80) in situ widerlegt, kein Tausch begruendet.
- Hebel "Access-List-Band-Boden < -76 auf 5G" nicht sauber ausdrueckbar:
kein band-Property, Interface-Scoping bricht am cap-wifiN-Rejoin,
SSID-/MAC-Scope trae fen 2,4 GHz mit (Lockout-Risiko). Nicht umgesetzt.
- TP30: Posten #9 vorgemerkt -- GITEA_ACCESS_TOKEN am 09-14 ueber einen
Fehlerpfad (URL-Konstruktion -> ValueError-Traceback) ins Transkript
geraten; sechster Vorfall der Leak-Familie, neue Unterklasse.
- Gitea: TP25-Issue #17 Kommentar 217, TP30-Issue #20 Kommentar 218.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
5/6 Schichten durch; Schicht-3-pro-Projekt-Rollout laut Abgrenzung eigene
Sessions; On-Network-mikromcp-Smoketest als Merkposten → TP30 #20.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diagnose: die GC-Backups standen seit 2026-09-04, weil NIE ein Scheduler
existierte — Backup/Intended/Compliance liefen nur manuell aus Sessions. Die
"2×/Tag per SSH"-Annahme (CLAUDE.md Bot-Master-Zeile + gc-snapshot.py-Docstring)
war nie real; beide korrigiert.
Fix: Nautobot-Job "Execute All Golden Configuration Jobs - Multiple Device"
enabled + ScheduledJob "GC Backup+Compliance – taeglich" (platform=RouterOS,
täglich 03:30 UTC, Backup→Intended→Compliance). Sofort-Lauf SUCCESS, alle 5
Geräte backup/compliance auf 2026-09-12 10:35, frischer bf-golden-config-Commit.
Announcement-Eintrag ergänzt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
exports.zsh um die 3 von opencode bereits referenzierten, aber fehlenden
MCP_MIKROMCP_{ROUTER_AP3,CRS326_CORE,CRS326_BRANCH}_PASS ergänzt (25 Vars,
gui-env-sync 25/25 in launchd-Env). claude.json hält noch 7 Klartext-Secrets;
DRY-RUN bestätigt alle Ziel-Vars MATCH. Flip läuft bei BEENDETER App über
~/dev/.bin/schicht2-claude-json-migrate.py --apply-claude (nicht aus laufender
Session — Claude Code schreibt State in die Datei). Announcement-Eintrag ergänzt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Schicht 4 (Announcement): docs/announcements.md angelegt (Format
## YYYY-MM-DD — Titel + Betrifft/Aktion, neueste oben) + globaler Skill /news
(liegt in ~/.claude/skills/news/ UND ~/.config/opencode/skills/news/, cp kein
Symlink). /news zeigt Einträge seit dem letzten Lauf (Seen-State ~/.news-seen/).
Erste Einträge: SSoT-Cutover + TP36-Live.
Schicht 5 (Backup-Guard): abgenommen — Guard + pre-commit-Hook live verdrahtet,
hat beim TP36-Live-Commit real gegriffen. Grenze dokumentiert (check prüft nur
Existenz der Guard-Datei, nicht deren Alter).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Legt die fünf TP36-Live-CustomFields (grouping TP36-Live) auf dcim.device an
und befüllt sie für alle 5 RouterOS-Geräte (ap1/2/3, crs326-branch/core)
ausschließlich aus Nautobot/Golden-Config — kein Geräte-Kontakt:
ros_version 7.24.1 (flotte), compliance_pct 100, dhcp_server_count
(core 7, Rest 0), dns_upstream_mode (core doh, Rest plain), mgmt_ip.
Idempotent (get-or-create CF, PATCH Device), Dry-Run default, --commit schreibt.
Token aus gitignored 210-nautobot.yml, Backup-Text nur intern geparst (nie ausgegeben).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Christoph on-site: Upstream 10.40.20.36 + .37, DNS-Rebind-Schutz-Ausnahme
bf.emsenhuber.net, Fallback-Haken "öffentliche NS bei Unreachbarkeit der
primären" gesetzt (existiert auf diesem FRITZ!OS-Stand) → Ideal-Variante,
.37-Redundanz bleibt, BF-down fällt auf public. Gitea #32 closed (status:done).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
dw-FritzBox kann per DHCP nur eine DNS-IP ausliefern → "mehrere NS an die
Clients" scheidet aus. Neue Richtung: Clients → 10.95.10.1 (FB), die FB
forwardet an Upstream 10.40.20.36 + .37 (beide BF, Voll-Resolver).
- Zwingend: DNS-Rebind-Schutz-Ausnahme bf.emsenhuber.net (sonst filtert die FB
die Privat-IP-Antworten 10.40.x als Rebind weg).
- BF-down-Fallback: FRITZ!OS-"öffentliche NS bei Unreachbarkeit"-Setting, sonst
public im Alternativ-Slot (kostet .37, dann strikt-primär verifizieren).
- Sauberer als DHCP-Multi: FB ist einziger Client-Resolver, .36 löst
intern+public → public nie "zuerst" gefragt, kein NXDOMAIN-Leak.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Auslöser: portainer.bf.emsenhuber.net vom dw-Standort (WG-Tunnel up) nicht
auflösbar — dw-FritzBox kennt die interne Zone bf.emsenhuber.net nicht.
- Gitea #32 reopened (status:todo, thema:firewall-dns), Prosa aus dem Archiv
zurück nach teilprojekte.md (Archiv = ♻️-Zeiger).
- fm-Einwand live entkräftet (dig @.36): bf-Namen → 10.40.0.0/16 (über WG
erreichbar), fm-Namen → Cloudflare-Anycast, nie 10.101.x.
- Entscheidung: FritzBox verteilt per DHCP die DNS-Liste .36/.37/9.9.9.9;
.37-Redundanz bleibt, FB entlastet. NXDOMAIN-Failover-Haken + zwei
On-site-Verifikationen dokumentiert. Umsetzung = eigene On-site-Session.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- TP41 abgeschlossen: Gelis WARP via Android eingerichtet (letzter Blocker weg)
- TP43 verworfen: 420 = public CF-Worker, kein BF-Split-Horizon nötig; keine Altlasten
- TP42-Prosa nachgezogen (war closed in Gitea, Prosa stand noch in teilprojekte.md)
- Status-SSoT-Änderungen in Gitea gesetzt (#30 done, #32 dropped, #31 title-Fix)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Volltext TP44 (✅ DURCH) nach teilprojekte-archiv.md (Anker #tp44 + TOC-Zeile),
aus teilprojekte.md entfernt, Control-Plane-Themenzeile + gebrochenen intra-file
Link auf teilprojekte-archiv.md#tp44 gefixt. Gitea #33 war bereits closed/status:done.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die Zeile "Repo-CF_API_TOKEN darf kein Workers-VPC" war falsch (live: liest
14/14). Handoff als Snapshot belassen, aber Korrektur-Hinweis ergänzt. Damit
ist die letzte Wiederholung der stale Gotcha markiert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nautobot verweigert das Scheduling von Jobs mit has_sensitive_variables
(Default True): "Job may have sensitive input variables". Der Job nimmt nur
ein Boolean (dryrun); das CF-Token stammt aus dem Nautobot-Secret, nicht aus
einer Job-Variable — daher unbedenklich abschaltbar.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>