Files
cve-dashboard/.kiro/specs/cve-tooltip-hover/tasks.md
jramos 9b36a58959 feat: add CVE tooltip on hover in Reporting Page
- Add GET /api/cves/:cveId/tooltip backend endpoint with description truncation
- Create CveTooltip portal component with caching, severity badges, and viewport-aware positioning
- Integrate tooltip into ReportingPage with 300ms hover delay on CVE badge spans
2026-04-09 14:42:23 -06:00

5.9 KiB
Raw Blame History

Implementation Plan: CVE Tooltip Hover

Overview

Implement a hover tooltip for CVE badges in the Reporting Page findings table. The feature spans a backend endpoint (GET /api/cves/:cveId/tooltip) and a frontend CveTooltip portal component with in-memory caching and 300ms hover delay. Tasks are ordered backend-first, then frontend component, then integration, with property tests alongside each layer.

Tasks

  • 1. Add backend tooltip endpoint

    • 1.1 Add GET /api/cves/:cveId/tooltip route inline in backend/server.js

      • Place it alongside existing CVE endpoints (after /api/cves/:cveId/vendors)
      • Validate :cveId against existing CVE_ID_PATTERN; return 400 for invalid format
      • Query: SELECT cve_id, description, severity FROM cves WHERE cve_id = ? LIMIT 1
      • If no row: return { exists: false } with status 200
      • If row found: truncate description to 300 chars + "…" if needed, return { exists: true, cve_id, description, severity }
      • Protect with requireAuth(db) middleware
      • Requirements: 1.1, 1.2, 1.3, 1.4, 1.5
    • * 1.2 Write property test for tooltip endpoint data correctness

      • Property 1: Tooltip endpoint returns correct data for existing CVEs
      • Install fast-check as dev dependency in frontend/ (shared test runner)
      • Generate random CVE records with description lengths 01000 and all 4 severity levels
      • Verify response shape, truncation at 300 chars, and prefix preservation
      • Validates: Requirements 1.1, 1.3, 1.5
    • * 1.3 Write property test for description truncation

      • Property 2: Description truncation preserves content and enforces length
      • Extract truncation logic into a testable pure function
      • Generate random strings of length 02000, verify length invariant and prefix match
      • Validates: Requirements 1.5
  • 2. Checkpoint — Verify backend endpoint

    • Ensure all tests pass, ask the user if questions arise.
  • 3. Create CveTooltip frontend component

    • 3.1 Create frontend/src/components/CveTooltip.js

      • Portal-rendered component using ReactDOM.createPortal to document.body
      • Props: cveId (string|null), anchorRect (DOMRect|null), cache (useRef Map)
      • Internal state: data, loading
      • On cveId change: check cache → if miss, fetch from /api/cves/:cveId/tooltip with AbortController
      • If cached exists: false or fetch returns exists: false, render nothing
      • Show loading spinner (Loader from lucide-react) while fetching
      • Display: CVE ID in monospace, severity badge with design system colors, description text
      • Max-width 320px, dark theme gradient background, accent border, directional arrow
      • Position above anchor by default; flip below if insufficient viewport space above
      • Do not cache transient errors (network failures)
      • Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 3.1, 3.2, 3.3, 3.4, 3.5
    • * 3.2 Write property test for tooltip positioning logic

      • Property 3: Tooltip positioning flips based on available viewport space
      • Extract positioning calculation into a pure function
      • Generate random anchorRect.top (02000), tooltip height (50200), viewport height (4001200)
      • Verify tooltip never overflows top or bottom of viewport
      • Validates: Requirements 3.1, 3.2
    • * 3.3 Write unit tests for CveTooltip component

      • Test loading state renders spinner
      • Test exists: false renders nothing
      • Test severity badge uses correct color per level
      • Test max-width constraint
      • Test directional arrow element is present
      • Requirements: 2.4, 2.5, 2.6, 3.3, 3.5
  • 4. Checkpoint — Verify CveTooltip component

    • Ensure all tests pass, ask the user if questions arise.
  • 5. Integrate tooltip into ReportingPage

    • 5.1 Add hover state and cache ref to ReportingPage

      • Add state: tooltipCveId (string|null), tooltipAnchorRect (DOMRect|null)
      • Add useRef(new Map()) for tooltip cache
      • Add useRef for hover delay timer
      • Clear cache when findings data is re-synced (inside existing sync callback)
      • Requirements: 4.1, 4.4, 5.1
    • 5.2 Add mouseenter/mouseleave handlers to CVE badge spans

      • In the renderCell function for the 'cves' column case, wrap each CVE badge <span> with onMouseEnter and onMouseLeave
      • onMouseEnter: start 300ms setTimeout; on fire, set tooltipCveId and tooltipAnchorRect from getBoundingClientRect()
      • onMouseLeave: clear timeout, set tooltipCveId to null
      • Requirements: 2.1, 2.2, 5.1, 5.2
    • 5.3 Render CveTooltip instance in ReportingPage

      • Add single <CveTooltip> at the bottom of the ReportingPage return, passing tooltipCveId, tooltipAnchorRect, and cache ref
      • Requirements: 2.1, 4.2, 4.3
    • * 5.4 Write property test for cache round-trip behavior

      • Property 4: Cache round-trip — fetch then cache-hit avoids network call
      • Generate random CVE IDs and response payloads, store in Map, verify lookups return identical objects
      • Validates: Requirements 4.1, 4.2
    • * 5.5 Write unit tests for hover delay and cache integration

      • Test tooltip appears after 300ms delay (use fake timers)
      • Test tooltip cancelled if mouseout before 300ms
      • Test cached exists: false suppresses tooltip and API call
      • Test cache cleared on data sync/refresh
      • Requirements: 4.3, 4.4, 5.1, 5.2
  • 6. Final checkpoint — Ensure all tests pass

    • Ensure all tests pass, ask the user if questions arise.

Notes

  • Tasks marked with * are optional and can be skipped for faster MVP
  • Each task references specific requirements for traceability
  • Checkpoints ensure incremental validation
  • Property tests validate universal correctness properties from the design document
  • Unit tests validate specific examples and edge cases
  • The project uses plain JavaScript (no TypeScript), fast-check for PBT, and react-scripts test (Jest)