summaryrefslogtreecommitdiff
path: root/internal/controlplane/mail_operations.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/controlplane/mail_operations.go')
-rw-r--r--internal/controlplane/mail_operations.go16
1 files changed, 10 insertions, 6 deletions
diff --git a/internal/controlplane/mail_operations.go b/internal/controlplane/mail_operations.go
index d42a328..fc7b81b 100644
--- a/internal/controlplane/mail_operations.go
+++ b/internal/controlplane/mail_operations.go
@@ -149,21 +149,25 @@ func (s *Store) queueBillingNotifications(ctx context.Context, config MailNotifi
FROM billing_ledger GROUP BY tenant_id)
SELECT w.tenant_id::text,w.currency,w.balance_micros-w.reserved_micros,u.email,u.display_name,
COALESCE(spend.today,0),COALESCE(spend.baseline,0),
- COALESCE(pref.low_balance_enabled,TRUE),COALESCE(pref.low_balance_threshold_micros,$1)
+ COALESCE(pref.low_balance_enabled,TRUE),COALESCE(pref.low_balance_threshold_micros,$1),
+ COALESCE(pref.spend_anomaly_enabled,TRUE),COALESCE(pref.spend_anomaly_multiplier,$2),
+ COALESCE(pref.spend_anomaly_min_micros,$3)
FROM tenant_wallets w JOIN console_users u ON u.tenant_id=w.tenant_id
LEFT JOIN spend ON spend.tenant_id=w.tenant_id
LEFT JOIN tenant_preferences pref ON pref.tenant_id=w.tenant_id
WHERE u.status='active' AND u.email_verified_at IS NOT NULL AND u.role IN ('tenant_admin','tenant_billing')
- AND NOT EXISTS (SELECT 1 FROM mail_suppressions s WHERE lower(s.recipient)=lower(u.email))`, config.LowBalanceMicros)
+ AND NOT EXISTS (SELECT 1 FROM mail_suppressions s WHERE lower(s.recipient)=lower(u.email))`,
+ config.LowBalanceMicros, config.SpendAnomalyMultiplier, config.SpendAnomalyMinMicros)
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
var tenantID, currency, email, name string
- var available, today, baseline, lowBalanceThreshold int64
- var lowBalanceEnabled bool
- if err := rows.Scan(&tenantID, &currency, &available, &email, &name, &today, &baseline, &lowBalanceEnabled, &lowBalanceThreshold); err != nil {
+ var available, today, baseline, lowBalanceThreshold, anomalyMultiplier, anomalyMinimum int64
+ var lowBalanceEnabled, anomalyEnabled bool
+ if err := rows.Scan(&tenantID, &currency, &available, &email, &name, &today, &baseline,
+ &lowBalanceEnabled, &lowBalanceThreshold, &anomalyEnabled, &anomalyMultiplier, &anomalyMinimum); err != nil {
return err
}
day := time.Now().UTC().Format("2006-01-02")
@@ -173,7 +177,7 @@ func (s *Store) queueBillingNotifications(ctx context.Context, config MailNotifi
return err
}
}
- if baseline > 0 && today >= config.SpendAnomalyMinMicros && today >= baseline*config.SpendAnomalyMultiplier {
+ if anomalyEnabled && baseline > 0 && today >= anomalyMinimum && today >= baseline*anomalyMultiplier {
body := fmt.Sprintf("Hi %s,\n\nAIGW detected unusual API spend today: %.6f %s versus a seven-day daily baseline of %.6f %s. Review API keys and usage in the console.\n", displayName(name), float64(today)/1_000_000, strings.ToUpper(currency), float64(baseline)/1_000_000, strings.ToUpper(currency))
if err := s.queueNotification(ctx, tenantID, email, "spend_anomaly", day, "Unusual AIGW API spend detected", body); err != nil {
return err