Files
cve-dashboard/.kiro/specs/archive-finding-clarity/tasks.md

71 lines
4.3 KiB
Markdown

# Implementation Plan: Archive Finding Clarity
## Overview
Enhance the Ivanti Archive Findings panel to display finding IDs, label severity as historical, detect related active findings server-side, and apply visual icon/border distinctions based on resolution status. Changes span `backend/routes/ivantiArchive.js` (matching logic + enriched response) and `frontend/src/App.js` (card rendering updates). No new components, endpoints, or migrations.
## Tasks
- [x] 1. Add `findRelatedActive` function and enrich the GET `/` handler in `backend/routes/ivantiArchive.js`
- [x] 1.1 Add the `findRelatedActive(archive, activeFindings)` helper function
- Add function above `createIvantiArchiveRouter` or inside the module scope
- Filter active findings where `hostName` exactly matches `archive.host_name`
- AND the archive's `finding_title` is a case-insensitive substring of the active finding's `title`, or vice versa
- AND the active finding's `id` is NOT equal to `archive.finding_id`
- If multiple matches, return the one with the highest `severity` as `{ id, title, severity }`
- If no matches, return `null`
- _Requirements: 3.1, 3.2, 3.3, 3.5_
- [x] 1.2 Modify the `GET /` handler to parse findings cache and enrich archive records
- After fetching archive rows, query `ivanti_findings_cache` (id=1) for `findings_json`
- Parse `findings_json` once with `JSON.parse`; default to empty array if NULL, missing row, or parse error
- Log a warning on parse failure, do not throw
- For each archive record, call `findRelatedActive(archive, parsedFindings)` and attach the result as `related_active`
- Return the enriched archives array in the existing `{ archives, total }` response shape
- _Requirements: 3.1, 3.4, 6.1, 6.2_
- [x] 2. Checkpoint — Verify backend changes
- Ensure the backend starts without errors, ask the user if questions arise.
- [x] 3. Update archive card rendering in `frontend/src/App.js`
- [x] 3.1 Add `AlertTriangle` and `CheckCircle` to the lucide-react import
- Locate the existing lucide-react import statement in `App.js`
- Add `AlertTriangle` and `CheckCircle` if not already imported
- _Requirements: 5.1, 5.2_
- [x] 3.2 Add Finding ID display below the finding title
- Inside the `archiveList.map()` block, add a new line below the title `<span>`
- Render `a.finding_id` in monospace font, `0.6rem` size, muted color `#64748B`
- If `finding_id` length exceeds 20 characters, truncate displayed text to 20 chars + ellipsis
- Set the full `finding_id` as the `title` attribute for hover tooltip
- _Requirements: 1.1, 1.2, 1.3_
- [x] 3.3 Change severity badge to "Last seen: X.X" format
- In the severity `<span>` within the archive card, replace `{a.last_severity?.toFixed(1) ?? '—'}` with `Last seen: {a.last_severity?.toFixed(1) ?? '—'}`
- Null or zero severity displays as "Last seen: —"
- _Requirements: 2.1, 2.2, 2.3_
- [x] 3.4 Add conditional "Similar finding active" badge
- When `a.related_active` is non-null, render a badge below the host info line
- Badge text: "Similar finding active" with the related finding's ID and severity
- Style with accent color `#0EA5E9`, monospace font, `0.6rem` size
- When `a.related_active` is null, render nothing
- _Requirements: 4.1, 4.2, 4.3_
- [x] 3.5 Add icon and left border color based on `related_active`
- When `a.related_active` is non-null: render `AlertTriangle` icon and set left border to `3px solid #F59E0B` (amber)
- When `a.related_active` is null: render `CheckCircle` icon and set left border to `3px solid #10B981` (green)
- Place the icon at the left side of the card header row, before the title
- Apply consistently regardless of archive lifecycle state (ARCHIVED, RETURNED, CLOSED)
- _Requirements: 5.1, 5.2, 5.3_
- [x] 4. Final checkpoint — Verify full feature
- Ensure the frontend compiles without errors, ask the user if questions arise.
## Notes
- No automated tests — feature is validated manually on the dev server per user preference
- No new components, endpoints, or database migrations required
- The `findRelatedActive` function parses the findings cache once per request for performance (Requirement 6.2)
- Each task references specific requirements for traceability