Files
cve-dashboard/.kiro/specs/vcl-aggregated-burndown/tasks.md
2026-05-19 15:01:25 -06:00

6.8 KiB

Implementation Plan: VCL Aggregated Burndown

Overview

Implement an aggregated cross-vertical burndown forecast feature consisting of: two new pure helper functions (deduplicateByHostname and computeAggregatedBurndown) in vclHelpers.js, a new GET /api/compliance/vcl-multi/burndown endpoint in the existing vclMultiVertical.js route file, property-based tests validating 8 correctness properties, unit tests covering edge cases and API integration, and an AggregatedBurndownChart inline component in CCPMetricsPage.js.

Tasks

  • 1. Implement backend helper functions

    • 1.1 Add deduplicateByHostname function to backend/helpers/vclHelpers.js

      • Groups items by hostname
      • For each hostname, selects the earliest non-null resolution_date across all entries
      • If all entries for a hostname have null dates, the device is a blocker (null date preserved)
      • Preserves the vertical from the first entry for that hostname
      • Export the function from the module
      • Requirements: 1.6
    • 1.2 Add computeAggregatedBurndown function to backend/helpers/vclHelpers.js

      • Accepts an array of device objects with hostname, resolution_date, and vertical fields
      • Counts total devices, blockers (null date), and with_dates (non-null date)
      • Buckets with_dates devices by YYYY-MM of resolution_date into monthly object
      • Sorts monthly keys chronologically
      • Computes projection as cumulative remaining: starts at total, subtracts each month's count
      • Sets projected_clear_date to the last month key if blockers = 0, otherwise null
      • Groups devices by vertical for by_vertical, sorted descending by total, omitting verticals with zero devices
      • Each by_vertical entry has { vertical, total, blockers, with_dates }
      • Returns { total, blockers, with_dates, monthly, projection, projected_clear_date, by_vertical }
      • Export the function from the module
      • Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 5.1, 5.2, 5.4
    • * 1.3 Write property tests for deduplicateByHostname and computeAggregatedBurndown

      • Property 1: Partition Invariantblockers + with_dates = total for any input
      • Validates: Requirements 2.2
      • Property 2: Monthly Bucket Conservation — sum of monthly values = with_dates
      • Validates: Requirements 2.3, 1.5
      • Property 3: Chronological Monthly Ordering — monthly keys in ascending YYYY-MM order
      • Validates: Requirements 2.4
      • Property 4: Cumulative Projection Consistency — projection[month].remaining = total - cumulative sum
      • Validates: Requirements 2.5
      • Property 5: Projected Clear Date Logic — null when blockers > 0, last month key when blockers = 0
      • Validates: Requirements 1.7
      • Property 6: Hostname Deduplication with Earliest Date — one entry per hostname, earliest non-null date
      • Validates: Requirements 1.6
      • Property 7: Aggregation Consistency with Per-Vertical Computation — aggregated totals = sum of per-vertical totals
      • Validates: Requirements 4.1, 4.2, 4.3, 4.4
      • Property 8: By-Vertical Sorting and Filtering — sorted descending by total, no zero-total entries, sum = overall total
      • Validates: Requirements 5.1, 5.2, 5.4
      • Test file: backend/__tests__/vcl-aggregated-burndown.property.test.js
  • 2. Implement backend API endpoint

    • 2.1 Add GET /burndown route to backend/routes/vclMultiVertical.js

      • Query compliance_items for all active non-compliant devices across verticals
      • Call deduplicateByHostname on the query results
      • Call computeAggregatedBurndown on the deduplicated devices
      • Map the result to the API response shape: { total_non_compliant, blockers, with_dates, monthly_forecast, projected_clear_date, by_vertical }
      • Handle database errors with 500 status and { error: "Database error" }
      • Route is protected by requireAuth() (already applied via router.use)
      • Requirements: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9
    • * 2.2 Write unit tests for the burndown endpoint

      • Test empty DB returns zero/empty response (Requirement 1.8)
      • Test all-blocker scenario returns with_dates=0, monthly={}, projected_clear_date=null (Requirement 2.7)
      • Test single device single metric basic computation
      • Test duplicate hostnames across metrics — verify deduplication picks earliest date
      • Test duplicate hostnames where all dates are null — verify device is a blocker
      • Test response shape matches API contract
      • Test 401 without auth session (mock requireAuth to reject)
      • Test file: backend/__tests__/vcl-aggregated-burndown.test.js
      • Requirements: 1.1, 1.8, 1.9, 2.6, 2.7
  • 3. Checkpoint - Ensure all backend tests pass

    • Ensure all tests pass, ask the user if questions arise.
  • 4. Implement frontend component

    • 4.1 Add AggregatedBurndownChart component to frontend/src/components/pages/CCPMetricsPage.js
      • Add as an inline component following the existing pattern (StatsBar, DonutChart, TrendChart are all in the same file)
      • Fetch GET /api/compliance/vcl-multi/burndown on page load alongside existing stats/trend calls
      • Display summary header with total non-compliant, blockers, in-progress, and projected clear date
      • Render a Recharts BarChart with one bar per monthly bucket (purple fill #A78BFA, fillOpacity 0.7)
      • Below the chart, render a compact per-vertical contribution table sorted by total descending
      • Show "No non-compliant devices" message when total = 0
      • Show "All X non-compliant devices lack remediation dates" when monthly_forecast is empty but blockers > 0
      • Show <Loader /> spinner while fetching
      • Show inline error message on API failure
      • Place the component below the charts row (TrendChart + DonutChart), above the VerticalTable
      • Requirements: 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 5.3
  • 5. 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 design uses JavaScript — all implementations use Node.js/Express (backend) and React 19 (frontend)
  • The vclMultiVertical.js route file already exists with router.use(requireAuth()) applied globally

Task Dependency Graph

{
  "waves": [
    { "id": 0, "tasks": ["1.1"] },
    { "id": 1, "tasks": ["1.2"] },
    { "id": 2, "tasks": ["1.3", "2.1"] },
    { "id": 3, "tasks": ["2.2"] },
    { "id": 4, "tasks": ["4.1"] }
  ]
}