From 91bac62dd8bdb13b3e9fedf9cb200c784cce798c Mon Sep 17 00:00:00 2001 From: lorentz Date: Wed, 15 Jul 2026 09:52:28 -0400 Subject: [PATCH] docs(phase-16): add validation strategy --- .../16-VALIDATION.md | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 .planning/phases/16-eml-mime-evidence-parser/16-VALIDATION.md diff --git a/.planning/phases/16-eml-mime-evidence-parser/16-VALIDATION.md b/.planning/phases/16-eml-mime-evidence-parser/16-VALIDATION.md new file mode 100644 index 0000000..71ebc86 --- /dev/null +++ b/.planning/phases/16-eml-mime-evidence-parser/16-VALIDATION.md @@ -0,0 +1,77 @@ +--- +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 `` 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