PAGE_TITLES in AppLayout fehlten 5 Einträge — diese Seiten zeigten
statt dem Seitennamen nur den generischen App-Titel im Header.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- internal/services/users: Repo mit CRUD, bcrypt (cost 12), Upsert für
setup-store-Admin-Migration, RecordLogin
- internal/handlers/users: GET/POST/PUT /users, POST /users/:id/password,
DELETE /users/:id; Schutz gegen Selbst-Löschung
- auth.go Login: DB-Nutzer first, Fallback auf setup-store-Admin;
bei erfolgreichem Fallback wird der Admin per Upsert in die DB
migriert (kein manueller Eingriff nötig)
- management-ui: /users-Seite mit Tabelle, Anlegen-, Bearbeiten-,
Passwort-setzen- und Löschen-Modals; "You"-Badge für eigenen Account
- Sidebar + Route + i18n (de/en) ergänzt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
User-Feedback: Tab fühlt sich falsch an, will eine eigene Page mit
URL-Pfad unter /firewall.
UI:
- pages/Firewall/LiveLog.tsx → pages/FirewallLive/index.tsx
- FirewallPage entfernt den live-Tab aus tabs[]
- App.tsx routet /firewall/live → FirewallLivePage
- Sidebar: neuer Eintrag „Firewall-Log" eingerückt direkt unter
„Firewall" in der Security-Section (child: true Flag → CSS-Klasse
sidebar-menu-item--child mit padding-left 28px + dünnem vertikalem
Trenn-Stab links). Sibling-Active-Logik exklusiv: /firewall matched
NICHT mehr wenn /firewall/live aktiv ist.
- AppLayout PAGE_TITLES bekommt /firewall/live VOR /firewall damit
der Title-Lookup den spezifischeren Pfad zuerst trifft.
Keine Backend-Änderungen.
Bekanntes Verhalten zu erklären: Im Live-Log sehen User aktuell nur
Smoke-Test-Events (oob.prefix=edgeguard:smoke / edgeguard:42, src/dst
127.0.0.1) — das sind die manuell-injizierten nft-Rules vom End-to-
End-Test der Pipeline. Reale Pakete fließen erst durch, wenn der
Operator auf einer firewall_rule den Log-Switch aktiviert (Firewall
→ Regeln → bearbeiten → Logging an). Aktuell hat keine einzige Rule
log=true.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
UI-Restruktur nach User-Feedback:
- Sidebar-Eintrag „Firewall-Live" entfernt — gehört thematisch unter
Firewall, kein Top-Level-Item. Standalone-Page /firewall-live raus.
- Neuer Firewall-Tab „Live-Log" zwischen NAT und Zonen.
- Default = AUS: zeigt Empty-State mit Start-Button. WebSocket
verbindet erst nach Klick. Stop-Button schließt explizit.
- Filter-Inputs (src/dst/rule_id) jetzt 300ms debounced — vorher
triggerte jeder Tastendruck einen WS-Reconnect.
Server-Pipeline „wirklich live" gepinnt:
- ulogd.conf NFLOG-Plugin bekommt qthreshold=1 + qtimeout=1. Default
des Kernels batched Pakete bis 1024 oder 1s; mit 1/1 fließt jedes
Paket sofort. Critical für die Wahrnehmung „live" statt „bursty".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Neue Page management-ui/src/pages/FirewallLive — Live-Tail der NFLOG-
Events aus /api/v1/firewall/log/live (WebSocket). Features:
- Status-Indicator (Live/getrennt), Auto-Reconnect alle 2s nach Drop
- Filter-Bar (action/proto/src/dst/rule_id) — bei Änderung wird der
WS neu verbunden, Server schickt frischen Snapshot
- Pause-Toggle: während Pause werden Events gebuffert (max 1000),
beim Resume in die Tabelle gemerged
- CSV-Export der aktuellen Tabelle (timestamp/rule/action/proto/src/
dst/iface/size)
- Color-coded Action-Tags (ACCEPT=grün, DROP=rot, REJECT=orange)
- Ring-Buffer 1000 im UI damit die DOM-Last bei Hochlast bleibt
- Sidebar-Eintrag "Firewall-Log" unter Sicherheit (Eye-Icon)
- DE/EN i18n
haproxy: backend api_backend bekommt `timeout tunnel 1h` damit der
WebSocket-Stream nicht nach `timeout server 60s` ohne Events stirbt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Scaffold und Core-Infrastruktur 1:1 nach enconf-Pattern (netcell-
webpanel/management-ui), reduziert auf EdgeGuard-Scope (kein reseller/
customer-Roles, keine codemirror/extensions). Stack: React 19 + AntD 6
+ TS strict + Vite + TanStack-Query + zustand + react-i18next.
Layout: AppLayout (Sider+Header+Content), Sidebar (Dashboard/Domains),
Header (User-Dropdown + Logout). i18n mit de/en common.json.
Pages: Login (POST /auth/login), Setup-Wizard (POST /setup/complete),
Dashboard (Health-Polling + Statistics), Domains (volles CRUD via
TanStack-Query gegen /domains-API). UpdateBanner-Komponente
(/system/package-versions, alle 5 min poll, /system/upgrade trigger)
ist von Tag 1 wie vom User gefordert eingebaut.
API-Wiring: cmd/edgeguard-api/main.go mountUI() — gin StaticFS für
/usr/share/edgeguard/ui/ (overridebar via EDGEGUARD_UI_DIR), echte
Files werden direkt geserved, alle nicht-API-Pfade fallen via
NoRoute auf index.html für React-Router-SPA. Wenn dist/ fehlt:
HTML-Placeholder mit Build-Hinweis.
Verifiziert: bun install + npx tsc -b strict (0 errors) + bun run
build (12 chunks). End-to-end gegen /tmp/eg-api: / serviert echte
React-index.html, /domains SPA-Fallback, /api/v1/* JSON, /assets/*
direkt, /api/v1/nonexistent korrekt 404.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>