wulf-pulse/lib/services/campaign-classifier.fixtures.ts
lorentz f4e6baf505 test(19-01): add failing tests + synthetic fixtures for classifier pure rule functions
- 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)
2026-07-16 08:14:51 -04:00

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'],
});