feat(license): Lizenz-System mit Ed25519-Verify gegen license.netcell-it.com

Portiert mail-gateway/internal/license (Verify, Cache, Trial, Signature)
+ DB-Mirror (internal/services/license) + REST-Handler (status/verify/key/clear)
+ UI-Page /license (Activate, Status, Limits, Features, Re-verify)
+ <LicenseBanner /> neben UpdateBanner (trial-expiring, expired, verify-failed)
+ Scheduler: täglich Re-verify (24h-Tick)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Debian
2026-05-11 13:41:16 +02:00
parent 1324a34f11
commit 62505d547c
17 changed files with 1278 additions and 10 deletions

View File

@@ -22,6 +22,8 @@ import (
firewallrender "git.netcell-it.de/projekte/edgeguard-native/internal/firewall"
"git.netcell-it.de/projekte/edgeguard-native/internal/haproxy"
"git.netcell-it.de/projekte/edgeguard-native/internal/handlers"
"git.netcell-it.de/projekte/edgeguard-native/internal/license"
licsvc "git.netcell-it.de/projekte/edgeguard-native/internal/services/license"
chronyrender "git.netcell-it.de/projekte/edgeguard-native/internal/chrony"
squidrender "git.netcell-it.de/projekte/edgeguard-native/internal/squid"
unboundrender "git.netcell-it.de/projekte/edgeguard-native/internal/unbound"
@@ -45,7 +47,7 @@ import (
wgsvc "git.netcell-it.de/projekte/edgeguard-native/internal/services/wireguard"
)
var version = "1.0.46"
var version = "1.0.47"
func main() {
addr := os.Getenv("EDGEGUARD_API_ADDR")
@@ -234,6 +236,19 @@ func main() {
return chronyrender.New(pool).Render(ctx)
}
handlers.NewNTPHandler(ntpRepo, auditRepo, nodeID, withFW(chronyReloader)).Register(authed)
// License — node-local key store + DB-mirror of last verify
// result. Real verify runs against license.netcell-it.com via
// internal/license; the scheduler triggers daily re-verify.
licRepo := licsvc.New(pool)
licClient := license.NewClient()
licKeyStore := license.NewKeyStore()
handlers.NewLicenseHandler(licRepo, licKeyStore, licClient, auditRepo, nodeID).Register(authed)
// Kick off periodic re-verify in this process so a long-running
// api answers /license/status with fresh data even without the
// scheduler. StartPeriodicVerification is a no-op when the key
// is empty.
licClient.StartPeriodicVerification(licKeyStore.Get())
}
mountUI(r)