diff --git a/lib/services/phishing-sweep-service.ts b/lib/services/phishing-sweep-service.ts index b598daa..26ea735 100644 --- a/lib/services/phishing-sweep-service.ts +++ b/lib/services/phishing-sweep-service.ts @@ -14,6 +14,7 @@ import { postgresClient } from './postgres-client'; import { detectPhishingTicket, type DetectableTicket } from './phishing-detector'; +import { groupReportIntoCampaign } from './campaign-grouping-service'; import { createSyncLogger } from '../utils/sync-logger'; export interface PhishingSweepResult { @@ -82,6 +83,13 @@ export async function sweepPhishingTickets(): Promise { } else if (detection.flagged) { result.flagged += 1; } + // D-01/D-08: grouping runs regardless of skippedUnchanged (a report + // could have been created by a previous sweep pass and still lack a + // campaign_id if grouping failed transiently that time); short-circuits + // internally if already grouped. + if (detection.flagged && detection.reportId) { + await groupReportIntoCampaign(detection.reportId, { skipIfAlreadyGrouped: true }); + } } catch (err) { result.errors += 1; logger.warn( diff --git a/lib/services/webhook-service.ts b/lib/services/webhook-service.ts index bf7ff67..f523396 100644 --- a/lib/services/webhook-service.ts +++ b/lib/services/webhook-service.ts @@ -15,6 +15,7 @@ import { ticketWorkflowEngine } from './ticket-workflow-engine'; import '../services/workflow-steps'; // Register all workflow step executors import { WorkflowEvent, TicketData } from '../types/workflow'; import { detectPhishingTicket, DetectableTicket } from './phishing-detector'; +import { groupReportIntoCampaign } from './campaign-grouping-service'; export class WebhookService { private _autotaskClient: AutotaskClient | null = null; @@ -486,7 +487,11 @@ export class WebhookService { }; console.log(`[WEBHOOK] Triggering phishing detection for ticket ${payload.entityId}`); - await detectPhishingTicket(ticket); + const detection = await detectPhishingTicket(ticket); + // D-01/D-08: automatic path short-circuits if already grouped. + if (detection.flagged && detection.reportId) { + await groupReportIntoCampaign(detection.reportId, { skipIfAlreadyGrouped: true }); + } } }