Commit graph

4 commits

Author SHA1 Message Date
58202e0dee fix(260721-mmf): broaden Mimecast blast-radius fan-out to whole tenant
- searchDeliveredMessages now called with from+subject+start+end only
  (no `to`) so it returns every delivered/rejected message matching the
  campaign across all recipients, not just the reporter's mailbox
- getHeldMessages now called with start+end only (no `recipient`) —
  domainsMatch() post-filter is the sole scoping mechanism for held rows
- Updated inline comments to document the tenant-wide fan-out and the
  per-recipient merge behavior it now produces
2026-07-21 16:25:08 -04:00
94f7dad29c fix(quick-260718-7v8): date-scope held-message lookup + sender-relevance guard
- getHeldMessages() accepts optional start/end, threaded into data[0] as
  siblings of admin/searchBy (backward compatible when omitted; 403
  fallback body inherits them automatically via the existing spread)
- getBlastRadius() passes the same startStr/endStr window already
  computed for searchDeliveredMessages into getHeldMessages()
- Added domainsMatch() sender-relevance guard: held rows whose sender
  domain doesn't match input.sender (exact-or-proper-subdomain) are
  filtered out before counting/merging, so unrelated same-window holds
  never inflate held/matched or override a delivered recipient
2026-07-18 05:44:56 -04:00
7c724cc489 feat(260716-n46): support per-tenant client injection + surface swallowed delivered-search errors
- 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
2026-07-16 16:44:23 -04:00
efbc437e2e feat(17-01): build mimecast-blast-radius.ts fan-out orchestration
- 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)
2026-07-15 14:30:00 -04:00