Hub: add POST /api/v1/notify endpoint for customer notifications

- New notification relay endpoint: receives events from customer controllers,
  looks up customer email preferences, sends via Resend HTTP API
- New tables: customer_notifications (per-customer email + event prefs),
  notification_log (audit trail for all notification attempts)
- Hungarian email template with severity, event type, timestamp
- Config: notifications.resend_api_key + notifications.from_email
- Test events always pass event-type filter

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-16 19:29:55 +01:00
parent 869ff55fd1
commit e531516cfa
4 changed files with 273 additions and 8 deletions
+8 -1
View File
@@ -31,6 +31,10 @@ type Config struct {
API struct {
ReportAPIKey string `yaml:"report_api_key"`
} `yaml:"api"`
Notifications struct {
ResendAPIKey string `yaml:"resend_api_key"`
FromEmail string `yaml:"from_email"`
} `yaml:"notifications"`
Retention struct {
MaxDays int `yaml:"max_days"`
PruneSchedule string `yaml:"prune_schedule"`
@@ -79,7 +83,7 @@ func main() {
}
// Initialize handlers
apiHandler := api.New(dataStore, cfg.API.ReportAPIKey, logger)
apiHandler := api.New(dataStore, cfg.API.ReportAPIKey, cfg.Notifications.ResendAPIKey, cfg.Notifications.FromEmail, logger)
webServer := web.New(dataStore, cfg.Auth.PasswordHash, staleThreshold, logger)
// Build HTTP mux
@@ -177,6 +181,9 @@ func loadConfig(path string, logger *log.Logger) *Config {
if cfg.Alerting.StaleThreshold == "" {
cfg.Alerting.StaleThreshold = "30m"
}
if cfg.Notifications.FromEmail == "" {
cfg.Notifications.FromEmail = "monitoring@felhom.eu"
}
return cfg
}