Pages auf PageHeader/StatusDot/ActionButtons-Pattern migriert:
* Dashboard — Komplett-Rewrite. KPI-Tiles (Domains, Backends, Iface,
FW-Rules, NAT, WG), Detail-Cards (WireGuard live status, Firewall
zone overview, SSL expiring soon, Cluster nodes, Routing summary,
System info). Polled queries pro Card.
* Domains, Backends, RoutingRules, Networks, IPAddresses, SSL,
Cluster, Settings, Firewall (index) — alle inline Action-Buttons
→ ActionButtons; alle Yes/No-Renders → StatusDot; Add-Button in
DataTable.extraActions; PageHeader oben.
WireGuard
---------
* Neuer /wireguard/status-Endpoint parsed `wg show all dump`,
liefert {iface, peer_pubkey, endpoint, last_handshake_unix, rx, tx}.
Sudoers im postinst um `wg show` erweitert.
* Server-Drawer Peer-Liste zeigt jetzt Live-Status (Online/Offline-
Dot, "vor Xs", Traffic-Counter) per 10s-Polling. Importierte
"Unify Home" peer kann jetzt im UI verifiziert werden.
* Importer-Bug fixed: nextName ("# Unify Home" comment) wurde beim
Sektionswechsel zu früh geresettet — jetzt nur nach echtem
flushPeer.
Routing-Rules
-------------
* Aus Sidebar entfernt. URL bleibt funktional, aber für 90% der
Setups reicht domains.primary_backend_id (das HAProxy ohnehin
als default_backend rendert). Path-basiertes Routing ist ein
Advanced-Feature und kommt später als Domain-Modal-Tab zurück.
* nav.routing-Sidebar-Eintrag + BranchesOutlined-Import entfernt.
Misc
----
* "Firewall (v2)" → "Firewall" im Nav (DE).
* Dashboard-i18n Block in DE+EN.
* Version 1.0.11 → 1.0.12.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Migration 0012: firewall_zones (id, name UNIQUE, description, builtin),
Seed wan/lan/dmz/mgmt/cluster als builtin. CHECK-Constraints auf
network_interfaces.role + firewall_rules.{src,dst}_zone +
firewall_nat_rules.{in,out}_zone gedroppt — Validation lebt jetzt
app-side (Handler prüft Existenz in firewall_zones).
* Backend: firewall.ZonesRepo (CRUD + Exists + References-Lookup),
/api/v1/firewall/zones, builtin geschützt (Name nicht änderbar,
Delete blockiert), Rename eines Custom-Zone aktuell ohne Cascade
(Handler-Sorge bei Rules/NAT/Networks).
* Handler-Validation in CreateRule/UpdateRule/CreateNAT/UpdateNAT +
NetworksHandler: Zone-Existence-Check pro Mutation, 400 bei Tippfehler.
* Frontend: Firewall-Tab "Zonen" (CRUD mit builtin-Schutz). Networks-
Form lädt Rollen aus /firewall/zones (statt hardcoded Liste); Rules-
und NAT-Forms ziehen die Zone-Auswahl ebenfalls aus der API.
* Domain-Form bekommt Primary-Backend-Picker (Field war im Modell,
fehlte im UI). Backends-Tabelle zeigt umgekehrt welche Domains
darauf zeigen — bidirektionale Sicht ohne Schemaänderung.
* HAProxy-Renderer: safeID-FuncMap escaped Server-Namen mit Whitespace
("Control Master 1" → "Control_Master_1"). Vorher ist haproxy beim
Reload an Spaces im Backend-Namen kaputt gegangen.
* Version 1.0.3 → 1.0.6.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Migration 0011: members JSONB für network_interfaces. Bridge/bond
brauchen ≥1 Member (NOT VALID-Constraint, schont bestehende Rows).
vlan/wireguard/ethernet ignorieren das Feld.
* Backend-Validation pro Typ: vlan→parent+vlan_id, bridge/bond→members,
ethernet/wireguard→keins. Repo serialisiert via JSONB.
* Form Networks: Members-Multi-Select für bridge/bond, Composition-
Spalte zeigt vlan-tag bzw. Member-Liste.
* Firewall-Rules-Tab zeigt jetzt SystemRulesCard ganz oben — Anti-
Lockout (SSH/443), stateful baseline, default-deny-Erklärung.
* Theme-Tokens 1:1 mail-gateway: fontSize 13, controlHeight 34
(vorher zu dichtes 12/28). Density kommt vom DataTable size="small".
* Makefile publish-amd64 lädt jetzt auch edgeguard-ui_*_all.deb und
edgeguard_*_all.deb hoch (vorher nur api).
* Version 1.0.0 → 1.0.3.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
DataTable (components/DataTable.tsx) gibt jeder CRUD-Tabelle drei
Baseline-Features auf einmal:
* Search-Input (Volltext über alle string-Felder, case-insensitive)
* Pagination 25/Seite mit showSizeChanger
* Auto-sorter pro Spalte mit dataIndex (string→localeCompare,
number→subtract, boolean→bool→Number) — Spalten mit eigenem
sorter behalten den.
Sweep aller 13 CRUD-Pages auf <DataTable>: Domains, Backends,
Routing-Rules, Networks, IP-Addresses, SSL, Cluster, sechs Firewall-
Tabs. Kleine Sub-Tabellen (System-Discovered IP-Card) bleiben
auf <Table> — read-only ohne CRUD braucht keine Pagination.
i18n: common.search, common.totalRows.
Version-Bump auf 1.0.0 (User-Direktive: ohne -dev): VERSION-Datei,
Go-Literale in cmd/edgeguard-{api,ctl,scheduler}/main.go,
package.json, Sidebar-Konstante. Live deployed auf 89.163.205.6 als
edgeguard 1.0.0 (api + ui + meta).
Memory: project_versioning.md hält die Patch-Bump-Konvention fest
(Gitea Package Registry 409't bei Doppel-Upload — bei jedem Release
zuerst die VERSION inkrementieren).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Backend:
* internal/services/tlscerts/ — Repo (List/Get/Upsert/Delete/
GetByDomain/ListExpiringSoon/MarkError) gegen tls_certs-Tabelle.
* internal/services/certstore/ — WriteCombined verifiziert cert/key
match via tls.X509KeyPair, schreibt /etc/edgeguard/tls/<domain>.pem
(HAProxy-format: cert + chain + key konkatenert). Parse extrahiert
NotBefore/After/Issuer/SANs aus dem PEM. Domain-Charset-Whitelist
gegen Path-Traversal beim Filename. 4 Tests (happy path, mismatched
key, hostile filename, parse).
* internal/services/acme/ — go-acme/lego v4 mit HTTP-01 über die
bestehende /var/lib/edgeguard/acme-Webroot (HAProxy proxied dort
schon hin). Account-Key persistent in /var/lib/edgeguard/acme-
account/account.key, Registrierung lazy beim ersten Issue().
* internal/handlers/tlscerts.go — REST CRUD + /upload (custom PEM)
+ /issue (LE HTTP-01) auf /api/v1/tls-certs. Reload HAProxy via
sudo nach jeder Mutation. Audit-Log pro Aktion.
Frontend:
* management-ui/src/pages/SSL/ — Tabs (Let's Encrypt / Eigenes
Zertifikat) plus Tabelle aller installierten Zerts mit
expires-in-Anzeige (orange ab <30 Tage, rot wenn abgelaufen) und
Status-Tags. Sidebar-Eintrag, i18n de/en.
* Networks-Form: Parent-Interface ist jetzt ein Select aus den
System-Discovered-Interfaces statt freier Input — User-Wunsch.
Packaging:
* postinst legt /var/lib/edgeguard/acme-account/ 0700 an.
* postinst installt /etc/sudoers.d/edgeguard mit NOPASSWD-Rule für
systemctl reload haproxy.service — damit der edgeguard-User
reloaden kann ohne root.
Live deployed auf 89.163.205.6. /api/v1/tls-certs antwortet jetzt
401 ohne Cookie (Route registriert), POST /tls-certs/upload + /issue
sind bereit. ACME-Issue gegen externe FQDN (utm-1.netcell-it.de)
braucht nur noch die Domain, die im wizard schon angelegt ist.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>