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>