Files
cve-dashboard/.kiro/specs/forecast-burndown-chart/tasks.md
Jordan Ramos a61d254ff9 Sync .kiro/ from master — v2.2.0 release batch
New specs: archer-template-library, ccp-metrics-view-restructure,
compliance-list-stale-after-sidebar-edit, compliance-metric-estimated-resolution-date,
compliance-remediation-display-fix, flexible-jira-ticket-creation,
forecast-burndown-chart, granite-loader-export, ivanti-queue-clear-completed-fix,
multi-item-jira-ticket, queue-collapsible-sections, vendor-issue-type-dropdown

New steering: archer-template-gen.md

Updated: migration-registration-check hook, remediation-plan-history spec,
gitlab-workflow, tech, versioning steering files
2026-06-04 11:27:31 -06:00

9.1 KiB

Implementation Plan: Forecast Burndown Chart

Overview

Add a per-metric forecast burndown chart to the CCP Metrics page. A pure helper function (computeMetricForecastBurndown) computes forecast projections from device records and historical snapshots. Two new API endpoints serve the metrics list and forecast data. A React frontend renders a metric selector and a ComposedChart (Bar + Line + ReferenceLine) using recharts. No database migrations are needed — the feature reads from existing compliance_items and compliance_snapshots tables.

Tasks

  • 1. Implement the computeMetricForecastBurndown helper function

    • 1.1 Add computeMetricForecastBurndown to backend/helpers/vclHelpers.js

      • Implement the pure function accepting currentDevices, totalAssets, and historicalSnapshots
      • Return object with historical, forecast, and current_snapshot fields
      • Compute current_snapshot.blockers (devices with no resolution_date) and current_snapshot.with_dates (devices with a resolution_date)
      • Compute compliance_pct as ROUND((total_assets - non_compliant) / total_assets * 100, 1), returning 0 when totalAssets is 0
      • Generate forecast months by iterating forward from current month, decrementing non_compliant as devices reach their resolution_date month
      • Treat past-due resolution dates as remediated in the current month
      • Hold total_assets constant across all forecast data points
      • Terminate forecast when all dated devices are remediated or at 12-month maximum
      • Return empty forecast array when all devices are blockers (no resolution dates)
      • Export the function for use in route handlers and tests
      • Requirements: 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 6.5
    • * 1.2 Write property test: Forecast structure invariant

      • Property 1: Forecast structure invariant
      • Validates: Requirements 1.4, 3.1, 3.6
      • Test file: backend/__tests__/forecast-burndown-chart.property.test.js
    • * 1.3 Write property test: Blocker and with_dates partition invariant

      • Property 2: Blocker and with_dates partition invariant
      • Validates: Requirements 3.2
      • Test file: backend/__tests__/forecast-burndown-chart.property.test.js
    • * 1.4 Write property test: Compliance percentage formula correctness

      • Property 3: Compliance percentage formula correctness
      • Validates: Requirements 3.3, 3.10
      • Test file: backend/__tests__/forecast-burndown-chart.property.test.js
    • * 1.5 Write property test: Forecast non_compliant monotonicity

      • Property 4: Forecast non_compliant monotonicity
      • Validates: Requirements 3.4
      • Test file: backend/__tests__/forecast-burndown-chart.property.test.js
    • * 1.6 Write property test: Per-month non_compliant computation correctness

      • Property 5: Per-month non_compliant computation correctness
      • Validates: Requirements 3.8
      • Test file: backend/__tests__/forecast-burndown-chart.property.test.js
    • * 1.7 Write property test: Forecast horizon bound

      • Property 6: Forecast horizon bound
      • Validates: Requirements 1.9, 3.9
      • Test file: backend/__tests__/forecast-burndown-chart.property.test.js
    • * 1.8 Write property test: Past-due resolution dates treated as current month

      • Property 7: Past-due resolution dates treated as current month
      • Validates: Requirements 6.5
      • Test file: backend/__tests__/forecast-burndown-chart.property.test.js
  • 2. Checkpoint - Helper function verified

    • Ensure all tests pass, ask the user if questions arise.
  • 3. Implement backend API endpoints

    • 3.1 Add GET /metrics-list endpoint to backend/routes/vclMultiVertical.js

      • Add route handler at /metrics-list with requireAuth() middleware
      • Query compliance_items for distinct metric_ids with active non-compliant devices where vertical IS NOT NULL
      • Return JSON array of { metric_id, device_count } sorted by metric_id ascending
      • Return empty array when no metrics have active devices
      • Return HTTP 500 with { "error": "Failed to fetch metrics list" } on database failure
      • Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 2.6
    • 3.2 Add GET /metric/:metricId/forecast-burndown endpoint to backend/routes/vclMultiVertical.js

      • Add route handler with requireAuth() middleware
      • Query active devices for the metric from compliance_items (status = 'active', vertical IS NOT NULL)
      • Determine the vertical from active devices and query compliance_snapshots for 3 months of historical data
      • Compute per-metric historical non_compliant using the ratio method from Requirement 7.2
      • Include current month as the most recent historical data point computed from live data
      • Pass data to computeMetricForecastBurndown helper
      • Return response with metric_id, historical, forecast, and current_snapshot
      • Return 200 with empty arrays and zeroed snapshot when metricId has no active devices
      • Return HTTP 500 with { "error": "Failed to compute forecast burndown" } on database failure
      • Requirements: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 1.10, 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7
    • * 3.3 Write unit tests for API endpoints

      • Test metrics-list returns correct shape with mocked database
      • Test forecast-burndown returns correct shape with mocked database
      • Test authentication middleware is applied to both endpoints
      • Test empty/error states
      • Test file: backend/__tests__/forecast-burndown-chart.test.js
      • Requirements: 1.7, 1.8, 1.10, 2.4, 2.5, 2.6
  • 4. Checkpoint - Backend complete

    • Ensure all tests pass, ask the user if questions arise.
  • 5. Implement frontend MetricSelector and ForecastBurndownChart components

    • 5.1 Add MetricSelector component to frontend/src/components/pages/CCPMetricsPage.js

      • Fetch metrics list from /api/compliance/vcl-multi/metrics-list on mount
      • Display dropdown showing each metric_id with active non-compliant device count
      • Auto-select first metric and trigger forecast data fetch on load
      • Handle loading state (non-interactive while fetching)
      • Handle empty state ("No metrics with active non-compliant devices")
      • Handle error state (inline error with AlertCircle icon, red border)
      • On selection change, trigger onMetricSelect callback
      • Requirements: 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8
    • 5.2 Add ForecastBurndownChart component to frontend/src/components/pages/CCPMetricsPage.js

      • Fetch forecast data from /api/compliance/vcl-multi/metric/:metricId/forecast-burndown when metric changes
      • Render recharts ComposedChart with:
        • Blue Bar for total_assets (left Y-axis)
        • Orange Bar for non_compliant (left Y-axis)
        • Green Line for compliance_pct (right Y-axis, 0-100%)
        • ReferenceLine as vertical divider between historical and forecast sections
      • Render forecast data points at 50% opacity
      • Display raw device count labels inside bars
      • Display compliance percentage labels on the trend line
      • X-axis labeled with months (YYYY-MM format)
      • Left Y-axis scaled to max total_assets, right Y-axis 0-100%
      • Handle loading state (loading indicator in chart area)
      • Handle error state (inline error with AlertCircle icon and description)
      • Handle empty data state ("No data available for this metric")
      • Handle historical-only state (no divider line when forecast is empty)
      • Discard stale responses on rapid metric switching (race condition handling)
      • Requirements: 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 4.10, 4.11, 4.12, 4.13, 4.14, 5.9
    • 5.3 Wire MetricSelector and ForecastBurndownChart into CCPMetricsPage layout

      • Add state for selected metric
      • Place MetricSelector above ForecastBurndownChart in a dedicated section
      • Connect selection change to chart data fetch
      • Follow existing inline-style patterns from AggregatedBurndownChart and TrendChart
      • Requirements: 4.1, 5.1, 5.4
  • 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
  • The helper function is pure and stateless — all 7 property tests exercise it in isolation without database mocks
  • All backend changes are in backend/helpers/vclHelpers.js and backend/routes/vclMultiVertical.js
  • All frontend changes are within frontend/src/components/pages/CCPMetricsPage.js
  • Property-based tests use fast-check (already in project dependencies)
  • No database migrations needed — uses existing compliance_items and compliance_snapshots tables

Task Dependency Graph

{
  "waves": [
    { "id": 0, "tasks": ["1.1"] },
    { "id": 1, "tasks": ["1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8"] },
    { "id": 2, "tasks": ["3.1", "3.2"] },
    { "id": 3, "tasks": ["3.3"] },
    { "id": 4, "tasks": ["5.1", "5.2"] },
    { "id": 5, "tasks": ["5.3"] }
  ]
}