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

4.3 KiB

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

  • 1. Add findRelatedActive function and enrich the GET / handler in backend/routes/ivantiArchive.js

    • 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
    • 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
  • 2. Checkpoint — Verify backend changes

    • Ensure the backend starts without errors, ask the user if questions arise.
  • 3. Update archive card rendering in frontend/src/App.js

    • 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
    • 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
    • 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
    • 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
    • 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
  • 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