- campaign-classifier.test.ts: describe blocks for domainMatchesAllowlist, isKnownSimulationSender, effectiveAuthResults, hasHardAuthFail, computeConfidence, mapVerdictToActions, computeRequiresApproval - campaign-classifier.fixtures.ts: synthetic KnowBe4/BSN simulation fixtures plus non-simulation threat/clean-spam/suspicious-unwanted fixtures - Covers CLASSIFY-01/02/03/04/06 pure-function behavior (T-19-01, Pitfall 1/3)
118 lines
4.3 KiB
TypeScript
118 lines
4.3 KiB
TypeScript
/**
|
|
* Synthetic fixtures for campaign-classifier.test.ts (Phase 19). Nothing
|
|
* here is real customer content — all addresses, domains, and subjects are
|
|
* invented for testing only (per this milestone's explicit
|
|
* synthetic-fixture-only constraint).
|
|
*
|
|
* Both simulation fixtures (`knowbe4SimMessage`, `bsnSimMessage`) reproduce
|
|
* the forwarding-induced auth-verdict inversion described in
|
|
* 19-RESEARCH.md Pitfall 1 — the primary `authResults` header shows a hard
|
|
* fail (post-forward, DKIM invalidated by the forward hop) while
|
|
* `authResultsOriginal` shows the pre-forward pass. This lets the
|
|
* "simulation is never THREAT" test prove BOTH the D-06 allowlist
|
|
* short-circuit AND the D-05/authResultsOriginal precedence in one fixture.
|
|
*/
|
|
|
|
import type { NormalizedMessage } from './eml-parser';
|
|
|
|
function makeNormalizedMessage(
|
|
overrides: Partial<NormalizedMessage> & {
|
|
from: NormalizedMessage['from'];
|
|
authResults: NormalizedMessage['authResults'];
|
|
}
|
|
): NormalizedMessage {
|
|
return {
|
|
replyTo: null,
|
|
returnPath: null,
|
|
to: ['reporter@wulfconsulting.test'],
|
|
cc: [],
|
|
subject: 'Test subject',
|
|
date: '2026-07-15T12:00:00.000Z',
|
|
messageId: null,
|
|
receivedChain: [],
|
|
authResultsOriginal: null,
|
|
urls: [],
|
|
attachments: [],
|
|
bodyPreview: '',
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* KnowBe4 phishing-simulation fixture — From domain matches the
|
|
* `it-support.care` allowlist entry (19-RESEARCH.md D-07 finding #2).
|
|
*/
|
|
export const knowbe4SimMessage: NormalizedMessage = makeNormalizedMessage({
|
|
from: { displayName: 'IT Support', email: 'alert@it-support.care', domain: 'it-support.care' },
|
|
returnPath: 'bounce@it-support.care',
|
|
subject: 'Phishing Alert - Email Security Report',
|
|
authResults: { spf: 'fail', dkim: 'fail', dmarc: 'fail' },
|
|
authResultsOriginal: { spf: 'pass', dkim: 'pass', dmarc: 'pass' },
|
|
});
|
|
|
|
/**
|
|
* Breach Secure Now training-notification fixture — From.domain is null
|
|
* (Pitfall 3: From may lack a visible email address); the Return-Path
|
|
* domain is the only allowlist signal (19-RESEARCH.md D-07 finding #1).
|
|
*/
|
|
export const bsnSimMessage: NormalizedMessage = makeNormalizedMessage({
|
|
from: { displayName: null, email: null, domain: null },
|
|
returnPath: 'bounces-abc123@em8721.breachsecurenow.com',
|
|
subject: 'Security Awareness Training Notification',
|
|
authResults: { spf: 'fail', dkim: 'fail', dmarc: 'fail' },
|
|
authResultsOriginal: { spf: 'pass', dkim: 'pass', dmarc: 'pass' },
|
|
});
|
|
|
|
/**
|
|
* Non-simulation THREAT fixture — a real typosquat flavor per
|
|
* 19-RESEARCH.md D-07 finding #3 (`mlcrosoft.live`, NOT allowlisted). No
|
|
* `authResultsOriginal` — effectiveAuthResults falls back to the primary
|
|
* `authResults`, which itself shows a hard fail (no forwarding inversion
|
|
* here — the fail is the actual signal).
|
|
*/
|
|
export const threatMessage: NormalizedMessage = makeNormalizedMessage({
|
|
from: {
|
|
displayName: 'Microsoft Account Team',
|
|
email: 'security@mlcrosoft.live',
|
|
domain: 'mlcrosoft.live',
|
|
},
|
|
returnPath: 'bounce@mlcrosoft.live',
|
|
subject: 'Unusual sign-in activity detected',
|
|
authResults: { spf: 'fail', dkim: 'fail', dmarc: 'fail' },
|
|
authResultsOriginal: null,
|
|
});
|
|
|
|
/**
|
|
* Clean non-simulation SPAM fixture — generic bulk/newsletter sender, no
|
|
* spoofing, all auth verdicts pass, no attachment/url indicators.
|
|
*/
|
|
export const cleanSpamMessage: NormalizedMessage = makeNormalizedMessage({
|
|
from: {
|
|
displayName: 'Example Newsletter',
|
|
email: 'news@mail.example-newsletter.com',
|
|
domain: 'mail.example-newsletter.com',
|
|
},
|
|
returnPath: 'bounce@mail.example-newsletter.com',
|
|
subject: 'Your weekly digest',
|
|
authResults: { spf: 'pass', dkim: 'pass', dmarc: 'pass' },
|
|
authResultsOriginal: null,
|
|
});
|
|
|
|
/**
|
|
* Suspicious-but-contained UNWANTED fixture — a single suspicious signal
|
|
* (paired in Task 2 with exactly one url indicator, not shared across
|
|
* messages) with delivery contained to the reporter only — below the
|
|
* THREAT bar per D-04.
|
|
*/
|
|
export const suspiciousUnwantedMessage: NormalizedMessage = makeNormalizedMessage({
|
|
from: {
|
|
displayName: 'Vendor Promo',
|
|
email: 'promo@promo.some-vendor.net',
|
|
domain: 'promo.some-vendor.net',
|
|
},
|
|
returnPath: 'bounce@promo.some-vendor.net',
|
|
subject: 'Special offer just for you',
|
|
authResults: { spf: 'pass', dkim: 'pass', dmarc: 'pass' },
|
|
authResultsOriginal: null,
|
|
urls: ['http://promo.some-vendor.net/deal'],
|
|
});
|