feat(18-02): wire groupReportIntoCampaign into webhook + cron sweep paths

- webhook-service.ts: triggerPhishingDetection calls groupReportIntoCampaign
  with skipIfAlreadyGrouped:true after a flagged detection (D-01, D-08)
- phishing-sweep-service.ts: per-ticket sweep loop calls the same, inside the
  existing try/catch so a grouping failure counts against result.errors
  without aborting the sweep
This commit is contained in:
lorentz 2026-07-15 19:31:18 -04:00
parent de013e6ec1
commit 19b8b4b415
2 changed files with 14 additions and 1 deletions

View file

@ -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<PhishingSweepResult> {
} 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(

View file

@ -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 });
}
}
}