diff --git a/backend/src/services/securityAlert.service.ts b/backend/src/services/securityAlert.service.ts index 961302d7..f3a54991 100644 --- a/backend/src/services/securityAlert.service.ts +++ b/backend/src/services/securityAlert.service.ts @@ -155,14 +155,16 @@ export async function detectThresholds(): Promise { }); for (const g of grouped) { if ((g._count as number) < b.threshold) continue; - // Prüfen ob wir für diese (IP+Type+Stunde) schon einen CRITICAL emittiert haben - const hourBucket = new Date(now.getTime() - (now.getTime() % (60 * 60 * 1000))); + // Debounce: pro IP max. 1 SUSPICIOUS-Alert pro 60min (sliding window). + // Vorher: floor(now, hour) → resettete bei Stundenwechsel und produzierte + // doppelte Alerts (Bug aus Runde 10). + const oneHourAgo = new Date(now.getTime() - 60 * 60 * 1000); const existing = await prisma.securityEvent.findFirst({ where: { type: 'SUSPICIOUS', severity: 'CRITICAL', ipAddress: g.ipAddress, - createdAt: { gte: hourBucket }, + createdAt: { gte: oneHourAgo }, }, }); if (existing) continue;