docs(17): fix plan-checker warnings (merge formula clarity + resolved open questions)
This commit is contained in:
parent
7303b16cbb
commit
3424812d60
2 changed files with 3 additions and 3 deletions
|
|
@ -179,7 +179,7 @@ Factory-convention analogs to mirror:
|
|||
2. Build the cache key `<service>:<resource>:<discriminators>` per addigy-devices precedent: with messageId → `mimecast:blast-radius:msgid:${input.messageId}`; else → `mimecast:blast-radius:composite:${input.sender}:${input.subject}:${input.dateWindow.start.toISOString()}:${input.dateWindow.end.toISOString()}`.
|
||||
3. `const cached = await getCachedData<BlastRadiusResult>(cacheKey); if (cached) return cached;` — a cache hit must short-circuit BEFORE any MimecastClient call (D-04).
|
||||
4. Inside a `try`: `const client = getMimecastClient();`. If `input.messageId` is present, optionally `await client.getMessageInfo(input.messageId)` for body/header evidence ONLY — never use its return to derive counts and never let it gate the fan-out (Pitfall 1). Then ALWAYS run the fan-out via `Promise.all([...])` (D-01 corrected — fan-out is unconditional, not a fallback): `searchDeliveredMessages({ to: input.recipient, from: input.sender, subject: input.subject, start, end })` where `start`/`end` are `input.dateWindow.start/end.toISOString().replace(/\.\d{3}Z$/, '+0000')`; `getHeldMessages({ recipient: input.recipient })`; `getThreatEvents()`.
|
||||
5. Merge per 17-RESEARCH Pattern 3: build `perRecipient[]` by grouping delivered + held rows on their single-string `to` field (delivered → 'delivered', held → 'held', neither → 'unknown'); `delivered` = count of delivered rows, `held` = count of held rows, `rejected` = delivered rows whose `.status` string indicates rejection, `matched` = total delivered + held rows. Because the exact `.status` rejection enum is UNCONFIRMED (17-RESEARCH A3), add a code comment noting this and treat unrecognized status strings conservatively as 'delivered' rather than hardcoding a guessed rejected value as confirmed; log the raw status values seen at debug level for first-real-tenant validation. Derive `clicked` best-effort by counting threat-event items whose `analysis[]` includes a click-type value, else `0` (comment the best-effort limitation).
|
||||
5. Merge per 17-RESEARCH Pattern 3: build `perRecipient[]` by grouping delivered + held rows on their single-string `to` field (delivered → 'delivered', held → 'held', neither → 'unknown'); first partition `searchDeliveredMessages` rows into non-rejected vs. rejected using `.status` (rejected = row's `.status` string indicates rejection); `delivered` = count of NON-rejected delivered rows (mutually exclusive with `rejected`), `rejected` = count of rejected delivered rows, `held` = count of held rows, `matched` = `delivered + held` (does not include `rejected` — a rejected recipient was never actually delivered). Because the exact `.status` rejection enum is UNCONFIRMED (17-RESEARCH A3), add a code comment noting this and treat unrecognized status strings conservatively as 'delivered' (i.e. not rejected) rather than hardcoding a guessed rejected value as confirmed; log the raw status values seen at debug level for first-real-tenant validation. Derive `clicked` best-effort by counting threat-event items whose `analysis[]` includes a click-type value, else `0` (comment the best-effort limitation).
|
||||
6. `await setCachedData(cacheKey, result, 300);` then return the result.
|
||||
7. `catch (err)`: `console.error('[MIMECAST-BLAST-RADIUS] lookup failed', err instanceof Error ? err.message : err)` — log err.message ONLY, never full Mimecast response bodies which may contain other recipients' subjects/content (T-17-02) — and return `{ status:'unavailable', reason:'lookup_failed', error: err instanceof Error ? err.message : String(err) }`. This satisfies BLAST-02: the public entry point never throws.
|
||||
|
||||
|
|
|
|||
|
|
@ -535,7 +535,7 @@ actually call, not `docs/mimecast-api-guide.md`.
|
|||
|
||||
## Open Questions
|
||||
|
||||
1. **Should this phase's abstraction resolve a per-company Mimecast tenant, or only use the
|
||||
1. **(RESOLVED: see CONTEXT.md D-05 — single global client for v1, multi-tenant gap documented in code)** Should this phase's abstraction resolve a per-company Mimecast tenant, or only use the
|
||||
single global env-var client?**
|
||||
- What we know: `mimecast_tenants` (migration 062) exists and is actively used by
|
||||
`/api/mimecast/held` and `/api/mimecast/delivered` (the two existing routes closest in
|
||||
|
|
@ -552,7 +552,7 @@ actually call, not `docs/mimecast-api-guide.md`.
|
|||
addition later (swap `getMimecastClient()` for a tenant lookup + `getMimecastClientForTenant()`,
|
||||
using the same fan-out logic).
|
||||
|
||||
2. **What are the real string values Mimecast returns for `status` in message-tracking search
|
||||
2. **(RESOLVED: deferred to runtime observation — 17-01-PLAN.md Task 2 treats unrecognized status strings conservatively as non-rejected and logs raw values at debug level rather than hardcoding a guessed enum)** What are the real string values Mimecast returns for `status` in message-tracking search
|
||||
results (delivered vs. rejected classification)?**
|
||||
- What we know: The TypeScript field exists (`MimecastDeliveredMessage.status: string`) and
|
||||
is populated from `e.status` in the raw API response, per `searchDeliveredMessages()`'s
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue