feat(15-03): register phishing-sweep schedule + migration 098

- extend sync_type union with 'phishing-sweep'
- add defaultSchedules entry (disabled by default, daily 5am cron)
- dispatch branch dynamically imports and calls sweepPhishingTickets
- migrations/098_phishing_sweep_schedule.sql seeds the row for existing installs
This commit is contained in:
lorentz 2026-07-15 07:49:01 -04:00
parent 194b58b196
commit b199d9991c
2 changed files with 40 additions and 1 deletions

View file

@ -22,7 +22,7 @@ export interface ScheduleConfig {
name: string;
description: string;
cron_expression: string;
sync_type: 'incremental' | 'full' | 'veeam-incremental' | 'veeam-full' | 'veeam-rpo-check' | 'contract-services' | 'engagement-daily' | 'zoom-daily' | 'morning-summary' | 'ticket-digest-daily' | 'ticket-digest-weekly' | 'ticket-digest-monthly' | 'device-link-reconcile' | 'integration-health' | 'qbo' | 'appgate-sessions' | 'appgate-daily' | 'tickets-reconcile' | 'pax8-daily';
sync_type: 'incremental' | 'full' | 'veeam-incremental' | 'veeam-full' | 'veeam-rpo-check' | 'contract-services' | 'engagement-daily' | 'zoom-daily' | 'morning-summary' | 'ticket-digest-daily' | 'ticket-digest-weekly' | 'ticket-digest-monthly' | 'device-link-reconcile' | 'integration-health' | 'qbo' | 'appgate-sessions' | 'appgate-daily' | 'tickets-reconcile' | 'pax8-daily' | 'phishing-sweep';
years_back?: number;
is_enabled: boolean;
last_run?: Date;
@ -299,6 +299,14 @@ class SyncScheduler {
sync_type: 'tickets-reconcile',
is_enabled: false,
},
{
id: 'phishing-sweep',
name: 'Phishing Detection Sweep',
description: 'Reconciles recently-modified tickets through the phishing detector to catch reports missed by the webhook path (bounded to 500 tickets, idempotent on content hash).',
cron_expression: '0 5 * * *',
sync_type: 'phishing-sweep',
is_enabled: false,
},
];
for (const schedule of defaultSchedules) {
@ -461,6 +469,12 @@ class SyncScheduler {
console.log(
`[SCHEDULER] tickets-reconcile: scanned=${result.scanned} updated=${result.updated} flippedComplete=${result.statusFlippedToComplete} softDeleted=${result.softDeleted} errors=${result.errors}`
);
} else if (config.sync_type === 'phishing-sweep') {
const { sweepPhishingTickets } = await import('@/lib/services/phishing-sweep-service');
const result = await sweepPhishingTickets();
console.log(
`[SCHEDULER] phishing-sweep: scanned=${result.scanned} flagged=${result.flagged} skippedUnchanged=${result.skippedUnchanged} errors=${result.errors}`
);
} else if (config.sync_type === 'pax8-daily') {
const { isPax8Configured } = await import('@/lib/services/pax8-factory');
if (!isPax8Configured()) {

View file

@ -0,0 +1,25 @@
-- Migration 098: Seed the phishing-sweep sync schedule.
--
-- The sync_scheduler.createDefaultSchedules() path only seeds defaults on a
-- virgin sync_schedules table; this migration covers existing installs.
-- Idempotent via ON CONFLICT (id) DO NOTHING. Disabled by default
-- (is_enabled=false) until an admin opts in via /admin.
INSERT INTO sync_schedules (
id,
name,
description,
cron_expression,
sync_type,
years_back,
is_enabled
) VALUES (
'phishing-sweep',
'Phishing Detection Sweep',
'Reconciles recently-modified tickets through the phishing detector to catch reports missed by the webhook path (bounded to 500 tickets, idempotent on content hash).',
'0 5 * * *',
'phishing-sweep',
NULL,
false
)
ON CONFLICT (id) DO NOTHING;