Minimal-Slice für Phase-3-Cluster:
* internal/cluster/node_id.go — stable UUID 'n-<16hex>' in
/var/lib/edgeguard/node-id, idempotent über reboots.
* internal/cluster/store.go — ha_nodes-Repo (List/Get/UpsertSelf)
via pgxpool. EnsureSelfRegistered upsertet die lokale Row beim
Boot mit FQDN aus setup.json.
* internal/handlers/cluster.go — GET /api/v1/cluster/nodes liefert
alle ha_nodes plus local_id (für UI-Highlighting).
* main.go: nach DB-Pool-Open wird EnsureSelfRegistered (nur wenn
setup.completed) ausgeführt, ClusterHandler registriert.
* management-ui/src/pages/Cluster/index.tsx — Tabelle mit Node-ID,
FQDN, Rolle, Beitrittszeit; eigene Node mit "diese Node"-Tag
markiert. Sidebar-Eintrag + i18n de/en.
Bewusst NICHT in dieser Runde: cluster-init/cluster-join CLIs, KeyDB
Active-Active config-gen, PG streaming replication, mTLS zwischen
Peers, License-Leader-Election. Diese kommen mit dem ersten echten
Multi-Node-Test (Phase 3.1) — sonst Code ohne Smoke-Möglichkeit.
End-to-end-Smoke: setup → restart → ha_nodes hat 1 Row mit
fqdn=eg.example.com, /cluster/nodes liefert sie korrekt mit
local_id-Markierung.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CRUD-Pages analog Domains:
* Backends: AntD Table + Modal-Form mit name, scheme, address, port,
health_check_path, active. TanStack-Query gegen /api/v1/backends.
* RoutingRules: Table mit Domain-Name- und Backend-Label-Resolution,
Modal mit Select-Pickern für Domain + Backend, Path-Prefix,
Priority, Active. Drei parallele Queries (rules, domains, backends)
liefern die Listen.
* Settings: read-only Descriptions-Cards mit /system/health und
/setup/status. Editable Werte folgen später.
Sidebar erweitert um Backends, Routing-Rules, Settings (mit AntD-
Icons). i18n de/en für alle drei neuen Seiten.
bun run build + npx tsc -b strict (0 errors). Live-Smoke gegen API:
SPA-Routes /backends, /routing-rules, /settings antworten 200 mit
index.html (NoRoute fallback wirkt).
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>