From f7516c04c783c234a42721df678399873d767331 Mon Sep 17 00:00:00 2001 From: lorentz Date: Thu, 16 Jul 2026 14:30:59 -0400 Subject: [PATCH] docs(22-03): complete evidence display plan --- .../22-03-SUMMARY.md | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 .planning/phases/22-approval-ui-livelink-addressable-campaign-review-and-approve/22-03-SUMMARY.md diff --git a/.planning/phases/22-approval-ui-livelink-addressable-campaign-review-and-approve/22-03-SUMMARY.md b/.planning/phases/22-approval-ui-livelink-addressable-campaign-review-and-approve/22-03-SUMMARY.md new file mode 100644 index 0000000..3522eb9 --- /dev/null +++ b/.planning/phases/22-approval-ui-livelink-addressable-campaign-review-and-approve/22-03-SUMMARY.md @@ -0,0 +1,106 @@ +--- +phase: 22-approval-ui-livelink-addressable-campaign-review-and-approve +plan: 03 +subsystem: ui +tags: [shadcn, radix, tooltip, react, tabs, phishing, xss-safety, clipboard] + +# Dependency graph +requires: [] +provides: + - "components/ui/tooltip.tsx — shadcn tooltip primitive (Tooltip/TooltipTrigger/TooltipContent/TooltipProvider)" + - "components/phishing/url-list.tsx — inert copy-only UrlList component (D-09)" + - "components/phishing/evidence-card.tsx — tabbed EvidenceCard (Headers/URLs/Attachments/Body preview/Blast Radius)" +affects: [22-04, 22-05, 22-06] + +# Tech tracking +tech-stack: + added: [] + patterns: + - "shadcn official-registry primitive addition via `npx shadcn add ` (no npm dependency delta — radix-ui already a project dependency)" + - "Inert-render pattern for attacker-controlled URLs: text + copy-to-clipboard button only, never /href/Link (D-09)" + - "Body-preview rendering exclusively inside a JSX-text
, never a raw-HTML injection prop, for attacker-controlled email content"
+
+key-files:
+  created:
+    - components/ui/tooltip.tsx
+    - components/phishing/url-list.tsx
+    - components/phishing/evidence-card.tsx
+  modified: []
+
+key-decisions:
+  - "EvidenceCard exports EvidenceMessage/EvidenceAttachment/BlastRadiusResult TypeScript interfaces alongside the component so plan 06 (review page composition) and the extended detail route can share the exact shape without re-declaring it."
+  - "Message selector (multi-report Select) keeps local useState for selectedId, defaulting to messages[0] (most-recently-linked, per the caller's expected sort order) rather than fetching/sorting inside the component — EvidenceCard stays a pure presentational component per the plan's stated purpose."
+  - "Used date-fns formatDistanceToNow for the Select's relative-date label, matching the existing precedent in components/admin/SyncDashboard.tsx and components/mobile/EngagementProfileHeader.tsx rather than introducing a new relTime() helper."
+
+patterns-established:
+  - "Pattern: inert-evidence-display — any future surface rendering attacker-controlled extracted data (URLs, hashes, raw text) should copy UrlList's stricter-than-sanitization approach: read-only /
 + copy button, zero interactive/navigating affordances."
+
+requirements-completed: [REVIEW-03]
+
+# Metrics
+duration: 20min
+completed: 2026-07-16
+---
+
+# Phase 22 Plan 03: Evidence Display (Tooltip primitive + UrlList + EvidenceCard) Summary
+
+**Tabbed, read-only EML evidence display (Headers/URLs/Attachments/Body preview/Blast Radius) built on a new shadcn tooltip primitive and a D-09-compliant inert URL list, with zero clickable-link surface and zero raw-HTML rendering of attacker-controlled email content.**
+
+## Performance
+
+- **Duration:** ~20 min
+- **Started:** 2026-07-16T18:10:33Z
+- **Completed:** 2026-07-16T18:29:40Z
+- **Tasks:** 2 completed
+- **Files modified:** 3 created
+
+## Accomplishments
+- Added the `tooltip` shadcn primitive via the official registry (`npx shadcn add tooltip`) — zero new npm dependency, since `radix-ui` was already a project dependency.
+- Built `UrlList` (`components/phishing/url-list.tsx`): extracted URLs render as inert `` monospace text with an icon-only copy-to-clipboard button; no ``/`href`, no ``, no navigating `onClick` anywhere in the file (D-09).
+- Built `EvidenceCard` (`components/phishing/evidence-card.tsx`): tabbed display of Headers (2-col definition list + SPF/DKIM/DMARC badges + collapsible received chain), URLs (delegates to `UrlList`), Attachments (metadata-only table with copy-hash affordance), Body preview (plain-text `
`, never raw-HTML rendering), and Blast Radius (explicit unavailable-state copy or stat row + per-recipient table).
+
+## Task Commits
+
+Each task was committed atomically:
+
+1. **Task 1: Add tooltip primitive + build UrlList (D-09 inert)** - `87008a5` (feat)
+2. **Task 2: EvidenceCard — tabbed EML evidence (REVIEW-03)** - `4ec5ba4` (feat)
+
+Additional commit: `2d5761b` (docs) — logged pre-existing, out-of-scope test failures to `deferred-items.md`.
+
+**Plan metadata:** SUMMARY commit (this file) follows below.
+
+## Files Created/Modified
+- `components/ui/tooltip.tsx` - shadcn tooltip primitive (Tooltip/TooltipTrigger/TooltipContent/TooltipProvider), generated by the official registry, no new npm dependency
+- `components/phishing/url-list.tsx` - inert, copy-only rendering of extracted URLs (D-09); exports `UrlList({ urls })`
+- `components/phishing/evidence-card.tsx` - tabbed EML evidence display; exports `EvidenceCard({ messages, blastRadius })` plus the `EvidenceMessage`/`EvidenceAttachment`/`BlastRadiusResult` shared TypeScript shapes
+
+## Decisions Made
+- Exported the evidence data shapes (`EvidenceMessage`, `EvidenceAttachment`, `BlastRadiusResult`) directly from `evidence-card.tsx` rather than a separate types file, since this plan is the sole owner of the shape today and plan 02's extended detail route / plan 06's review page can import from here without duplication.
+- Kept the multi-report `