docs(17): add research findings + tenant-scope decision

This commit is contained in:
lorentz 2026-07-15 13:35:21 -04:00
parent cacf41a493
commit 9dbc1e7510

View file

@ -22,12 +22,15 @@ whether Mimecast is present.
## Implementation Decisions
### Query Strategy
- **D-01:** Try `getMessageInfo(messageId)` first for an exact Message-ID
match. If that misses (no match, or Message-ID unknown/altered by
intermediate relays), fan out to `searchDeliveredMessages` +
`getHeldMessages` + `getThreatEvents` keyed on sender/subject/date-window
and merge results into one normalized blast-radius shape (matched/
delivered/held/rejected/clicked counts + per-recipient status). This is the
- **D-01 (corrected by research):** `getMessageInfo(messageId)` returns only
`{ messageId, bodyText, bodyHtml, headers }` — no status, no counts, no
per-recipient data. It is a supplementary body/header fetch only, never a
substitute for the counts. The fan-out — `searchDeliveredMessages` +
`getHeldMessages` + `getThreatEvents` keyed on sender/subject/date-window,
merged into one normalized blast-radius shape (matched/delivered/held/
rejected/clicked counts + per-recipient status) — runs **unconditionally**,
not as a fallback path. `getMessageInfo` may still be called opportunistically
for body/header evidence but must never gate whether the fan-out runs. This is the
most complete picture available from the existing `MimecastClient` methods,
at the cost of more API calls on the fallback path.
@ -57,6 +60,22 @@ whether Mimecast is present.
succession, while staying short enough that data doesn't go stale across a
single classification session.
### Tenant Scope
- **D-05 (added post-research):** Research surfaced an existing per-company
Mimecast multi-tenant setup (`mimecast_tenants` table, migration 062,
consumed via `getMimecastClientForTenant()` in the existing `/api/mimecast/
held` and `/api/mimecast/delivered` routes) that this phase's original
scope did not address. Decision: use **only the single global env-var
client** (`getMimecastClient()`) for v1 — do not resolve `reports.company_id`
to a per-tenant client in this phase. This must be documented explicitly in
code comments as a known limitation: reports from companies with their own
`mimecast_tenants` row (not covered by the global `MIMECAST_CLIENT_ID`) will
return `unavailable` even though Mimecast is technically configured for
that company. Per-tenant resolution is a small, mechanical follow-up later
(swap `getMimecastClient()` for a tenant lookup + `getMimecastClientForTenant()`,
same fan-out logic) if it turns out to be needed in practice — not blocking
for this phase.
### Claude's Discretion (explicitly deferred to research + planner)
- **`isMimecastConfigured()` helper.** `lib/services/mimecast-client.ts`
currently has `getMimecastClient()` (throws if `MIMECAST_CLIENT_ID`/