---
phase: 16
slug: eml-mime-evidence-parser
status: draft
nyquist_compliant: false
wave_0_complete: false
created: 2026-07-15
---

# Phase 16 — Validation Strategy

> Per-phase validation contract for feedback sampling during execution.

---

## Test Infrastructure

| Property | Value |
|----------|-------|
| **Framework** | vitest 4.1.5 |
| **Config file** | `vitest.config.ts` — `environment: 'node'`, `include: ['lib/**/*.test.ts']` |
| **Quick run command** | `npx vitest run lib/services/eml-parser.test.ts` |
| **Full suite command** | `npm test` |
| **Estimated runtime** | ~2 seconds (quick), ~5 seconds (full suite per prior-phase observation) |

---

## Sampling Rate

- **After every task commit:** Run `npx vitest run lib/services/eml-parser.test.ts` (and `lib/services/autotask-client.test.ts` once it exists)
- **After every plan wave:** Run `npm test`
- **Before `/gsd:verify-work`:** Full suite must be green
- **Max feedback latency:** 10 seconds

---

## Per-Task Verification Map

| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------|
| 16-01-xx | 01 | TBD | EVID-02 | T-16-DoS (size guard) | Selects `rfc.eml` over `OriginatingEmail.eml`, case-insensitive + `message/rfc822` content-type | unit | `npx vitest run lib/services/eml-parser.test.ts -t "selects rfc.eml"` | ❌ W0 | ⬜ pending |
| 16-01-xx | 01 | TBD | EVID-02 | — | Selects the non-`OriginatingEmail.eml` `message/rfc822` attachment when named differently (KnowBe4 shape) | unit | `npx vitest run lib/services/eml-parser.test.ts -t "KnowBe4"` | ❌ W0 | ⬜ pending |
| 16-01-xx | 01 | TBD | EVID-02 | — | Falls back to `OriginatingEmail.eml` when it is the only `.eml` attachment | unit | `npx vitest run lib/services/eml-parser.test.ts -t "fallback"` | ❌ W0 | ⬜ pending |
| 16-01-xx | 01 | TBD | EVID-03 | T-16-Spoofing (D-06) | Parses headers/auth-results/Received chain/URLs/attachment metadata from a synthetic fixture | unit | `npx vitest run lib/services/eml-parser.test.ts -t "normalizes"` | ❌ W0 | ⬜ pending |
| 16-01-xx | 01 | TBD | EVID-04 | T-16-SSRF (never fetch) | Never triggers a network call during parsing | unit | `npx vitest run lib/services/eml-parser.test.ts -t "no network"` | ❌ W0 | ⬜ pending |
| 16-01-xx | 01 | TBD | EVID-04 | — | Body preview is truncated/sanitized and distinct from raw body | unit | `npx vitest run lib/services/eml-parser.test.ts -t "body preview"` | ❌ W0 | ⬜ pending |
| 16-0x-xx | TBD | TBD | EVID-03 | — | `AutotaskClient.getAttachmentContent()` reads `response.items[0]`, not `response.item` | unit | `npx vitest run lib/services/autotask-client.test.ts -t "getAttachmentContent"` | ❌ W0 (no `autotask-client.test.ts` exists at all yet) | ⬜ pending |

*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*

---

## Wave 0 Requirements

- [ ] `lib/services/eml-parser.test.ts` — new file, covers EVID-02/03/04 per the map above
- [ ] Synthetic fixtures — at minimum: (a) `rfc.eml` + `OriginatingEmail.eml` pair, (b) KnowBe4-shaped pair (`phish_alert_sp2_2.0.0.0.eml`-style name + `OriginatingEmail.eml`), (c) `OriginatingEmail.eml`-only case, (d) a raw `.eml` buffer with multipart/mixed + text+html bodies + one attachment + an `Authentication-Results` header with spf/dkim/dmarc — all synthetic, no real customer content per REQUIREMENTS.md's explicit Out-of-Scope constraint
- [ ] `lib/services/autotask-client.test.ts` — does not exist yet in this repo for any method; Phase 16 introduces the first coverage for `AutotaskClient` if the planner wants unit coverage on `getAttachmentContent()` (mocking `fetch`)
- [ ] Framework install: none — vitest is already configured and used extensively elsewhere

---

## Manual-Only Verifications

All phase behaviors have automated verification (per the map above — this phase has no UI surface and no live-integration behavior that can't be exercised via synthetic fixtures/mocks).

---

## Validation Sign-Off

- [ ] All tasks have `<automated>` verify or Wave 0 dependencies
- [ ] Sampling continuity: no 3 consecutive tasks without automated verify
- [ ] Wave 0 covers all MISSING references
- [ ] No watch-mode flags
- [ ] Feedback latency < 10s
- [ ] `nyquist_compliant: true` set in frontmatter

**Approval:** pending
