/** * verify-blast-radius-held-bug.ts * * Ticket 699687 (Tomlinson, Seubert) shows Blast Radius: Matched 16, * Delivered 1, Held 15, with btomlinson@seubert.com's per-recipient status * shown as "held" — despite this being the accidental Guardian Protection * report we already confirmed was cleanly delivered (spamScore 0, no * detection) via Mimecast's own trace. Hypothesis: getHeldMessages() in * lib/services/mimecast-blast-radius.ts is scoped ONLY by recipient (Mimecast's * get-hold-message-list API has no sender/subject/date filter), so it pulls * in EVERY message currently sitting in btomlinson's hold queue — unrelated * to Guardian Protection — and the per-recipient merge logic lets any held * row silently overwrite a same-recipient delivered row. This script * independently verifies by calling the same two Mimecast calls the blast * radius module makes and inspecting what's actually in the held queue. * * Usage: * POSTGRES_HOST=localhost npx tsx scripts/verify-blast-radius-held-bug.ts */ import { config } from 'dotenv'; import { resolve } from 'path'; config({ path: resolve('/opt/stacks/pulse/.env.local') }); import postgresClient from '../lib/services/postgres-client'; import { getMimecastClientForTenant } from '../lib/services/mimecast-client'; const SEUBERT_COMPANY_ID = 29683407; const SENDER = 'guardian_protection_do_not_reply@guardianprotection.com'; const RECIPIENT = 'btomlinson@seubert.com'; const SUBJECT = "Unexpected Activity for Tomlinson’s Home: The Front Door was left unlocked at 1:39 pm"; async function main() { const tenantRow = await postgresClient.query<{ client_id: string; client_secret: string; base_url: string | null; account_name: string | null; }>( `SELECT client_id, client_secret, base_url, account_name FROM mimecast_tenants WHERE company_id = $1 AND enabled = true`, [SEUBERT_COMPANY_ID] ); const tenant = tenantRow.rows[0]; if (!tenant) { console.log('No enabled Mimecast tenant for Seubert — cannot verify.'); process.exit(1); } console.log(`Using Mimecast tenant: ${tenant.account_name}`); const client = getMimecastClientForTenant({ client_id: tenant.client_id, client_secret: tenant.client_secret, base_url: tenant.base_url ?? undefined, }); const now = new Date(); const start = new Date(now.getTime() - 24 * 60 * 60 * 1000); const startStr = start.toISOString().replace(/\.\d{3}Z$/, '+0000'); const endStr = now.toISOString().replace(/\.\d{3}Z$/, '+0000'); console.log(`\n=== 1. searchDeliveredMessages (scoped: sender+recipient+subject+24h window) ===`); const delivered = await client.searchDeliveredMessages({ from: SENDER, to: RECIPIENT, subject: SUBJECT, start: startStr, end: endStr, }); console.log(`Delivered rows found: ${delivered.messages?.length ?? 0}`); console.log(JSON.stringify(delivered.messages, null, 2)); console.log(`\n=== 2. getHeldMessages (scoped ONLY by recipient — no sender/subject/date filter possible) ===`); const held = await client.getHeldMessages({ recipient: RECIPIENT }); console.log(`Held rows found: ${held.messages.length} (totalCount reported: ${held.totalCount})`); console.log( JSON.stringify( held.messages.map((m) => ({ from: m.from, subject: m.subject, dateReceived: m.dateReceived, reason: m.reason })), null, 2 ) ); const heldFromGuardianProtection = held.messages.filter((m) => (m.from ?? '').toLowerCase().includes('guardianprotection.com') ); console.log(`\n=== 3. Of those held messages, how many are actually from Guardian Protection? ===`); console.log(`${heldFromGuardianProtection.length} of ${held.messages.length}`); process.exit(0); } main().catch((err) => { console.error(err); process.exit(1); });