- Updated the getHeldMessages window test to assert no `recipient` key and
added an explicit no-`to` assertion for searchDeliveredMessages
- Added a new test driving searchDeliveredMessages with 3 distinct `to`
addresses, asserting all appear in perRecipient and count toward
matched/delivered
- blast-radius: getHeldMessages called with same start/end window as
searchDeliveredMessages
- blast-radius: unrelated-sender held row excluded from held/matched and
perRecipient; matching-sender held row still counts and overrides
- client: getHeldMessages threads start/end into POST body data[0] when
provided, omits them when not
- getBlastRadius(input, options?) accepts an optional injected MimecastClient
and cacheScope; an injected client bypasses the global isMimecastConfigured()
gate since it carries its own credentials
- cache key namespaced by cacheScope to prevent cross-tenant collisions
- deliveredResult.error (previously swallowed) now rethrown so the outer
catch converts it to status: unavailable / reason: lookup_failed --
defense-in-depth against Bug 1 (future end-date rejected by Mimecast)
- test mock hygiene: getMimecastClientMock now cleared in beforeEach
- Fake tenant client via options.client bypasses getMimecastClient
- Injected tenant client runs fan-out even when global env unconfigured
- searchDeliveredMessages error field now expected to degrade to unavailable/lookup_failed
- Add getBlastRadius(): never-throwing orchestration that fans out to
searchDeliveredMessages + getHeldMessages + getThreatEvents (D-01,
unconditional fan-out) and merges into normalized matched/delivered/
held/rejected/clicked counts + perRecipient status array
- Config gate (BLAST-02): returns status:'unavailable' reason:'not_configured'
synchronously when Mimecast is unconfigured, never constructs the client
- Redis-backed 5-min cache (D-04) via redis-client.ts, short-circuits before
any MimecastClient call on hit
- clicked derived best-effort from getThreatEvents() analysis[] (D-02);
documents the /api/ttp/url/get-logs limitation in code
- Documents D-05 known limitation: single global getMimecastClient() only,
not per-company mimecast_tenants
- Unrecognized delivered-message status strings treated conservatively as
non-rejected (A3 unconfirmed enum), raw values logged at debug level
- Add lib/services/mimecast-blast-radius.test.ts covering config gate,
cache-hit short-circuit, fan-out merge, never-throw-on-error, and
unknown-recipient classification
- Log pre-existing unrelated itglue-search.test.ts failures to
deferred-items.md (out of scope for this plan)