9.2 KiB
Requirements Document
Introduction
Replace two underperforming compliance dashboard charts with more actionable visualizations. Chart 4 (MTTR by Team) is replaced by an Aging Findings Distribution histogram, and Chart 5 (Most Persistent Findings) is replaced by a Net Change Waterfall chart. Both replacements use data already present in the existing SQLite schema (compliance_items.seen_count and compliance_uploads aggregate columns) and require no database migrations. The four other charts in ComplianceChartsPanel remain unchanged.
Glossary
- Dashboard: The compliance charts panel rendered by
ComplianceChartsPanel.js, containing six chart cards in a responsive grid. - Aging_Chart: The new Chart 4 replacement — a stacked bar / histogram showing active findings distributed across age buckets derived from
seen_count. - Waterfall_Chart: The new Chart 5 replacement — a waterfall chart showing net movement per upload cycle (starting count → +new → +recurring → −resolved → ending count).
- Cycle: A single compliance report upload. Each upload represents one weekly reporting period.
- Age_Bucket: A grouping of active findings by how many cycles they have been continuously observed: 1 cycle, 2–3 cycles, 4–6 cycles, 7+ cycles.
- Seen_Count: The
seen_countcolumn oncompliance_items, incremented each cycle an active finding persists. Starts at 1 on first appearance. - Compliance_API: The Express router at
cve-dashboard/backend/routes/compliance.jsserving/api/compliance/*endpoints. - ChartCard: The shared wrapper component providing title, subtitle, and dark-themed card styling for each chart in the Dashboard.
- Recharts: The React charting library used by the Dashboard for all visualizations.
- Design_System: The dark theme specification defined in
DESIGN_SYSTEM.md, including color palette, monospace fonts, and card styling.
Requirements
Requirement 1: Aging Findings Distribution Backend Endpoint
User Story: As a compliance analyst, I want an API endpoint that returns active findings grouped by age bucket, so that the frontend can render the Aging Findings Distribution chart.
Acceptance Criteria
- WHEN a GET request is made to the aging endpoint, THE Compliance_API SHALL return active findings from
compliance_itemsgrouped into four Age_Buckets: 1 cycle (seen_count = 1), 2–3 cycles (seen_countbetween 2 and 3), 4–6 cycles (seen_countbetween 4 and 6), and 7+ cycles (seen_count >= 7). - WHEN a GET request is made to the aging endpoint, THE Compliance_API SHALL include a per-team breakdown within each Age_Bucket so the frontend can render stacked segments.
- THE Compliance_API SHALL return the response as a JSON object with an array of bucket objects, each containing the bucket label, total count, and a count per team.
- WHEN no active findings exist, THE Compliance_API SHALL return an empty array with HTTP status 200.
- IF a database error occurs, THEN THE Compliance_API SHALL return HTTP status 500 with a JSON error message.
- THE Compliance_API SHALL replace the existing
/mttrendpoint path so that no new route paths are introduced and the old MTTR endpoint is removed.
Requirement 2: Aging Findings Distribution Frontend Chart
User Story: As a compliance analyst, I want to see a stacked bar chart showing how many active findings fall into each age bucket, so that I can understand the shape of the current backlog and identify stale findings.
Acceptance Criteria
- THE Aging_Chart SHALL render a vertical stacked bar chart using Recharts with one bar group per Age_Bucket (1 cycle, 2–3 cycles, 4–6 cycles, 7+ cycles) on the X-axis and finding count on the Y-axis.
- THE Aging_Chart SHALL use one stacked color segment per team, using the existing
TEAM_COLORSmapping defined in the Dashboard. - THE Aging_Chart SHALL be wrapped in a ChartCard with the title "Aging Findings Distribution" and a subtitle describing the chart purpose.
- THE Aging_Chart SHALL use the shared
DarkTooltipcomponent to display bucket label, per-team counts, and total on hover. - THE Aging_Chart SHALL render a
NoDataplaceholder when the API returns an empty array. - THE Aging_Chart SHALL occupy the same grid position (Chart 4 slot) previously held by the MTTR chart in the Dashboard layout.
- THE Aging_Chart SHALL conform to the Design_System by using monospace axis labels, the standard grid style, and the dark card background gradient.
Requirement 3: Net Change Waterfall Backend Endpoint
User Story: As a compliance analyst, I want an API endpoint that returns per-cycle waterfall data (starting count, new, recurring, resolved, ending count), so that the frontend can render the Net Change Waterfall chart.
Acceptance Criteria
- WHEN a GET request is made to the waterfall endpoint, THE Compliance_API SHALL return one row per upload cycle containing: the cycle report date, starting active count, new count, recurring count, resolved count, and ending active count.
- THE Compliance_API SHALL compute the starting count for each cycle as the ending count of the previous cycle, with the first cycle starting at zero.
- THE Compliance_API SHALL compute the ending count for each cycle as
starting_count + new_count + recurring_count - resolved_count. - THE Compliance_API SHALL read
new_count,recurring_count, andresolved_countdirectly from thecompliance_uploadstable without requiring additional aggregation queries. - WHEN no uploads exist, THE Compliance_API SHALL return an empty array with HTTP status 200.
- IF a database error occurs, THEN THE Compliance_API SHALL return HTTP status 500 with a JSON error message.
- THE Compliance_API SHALL replace the existing
/top-recurringendpoint path so that no new route paths are introduced and the old persistent-findings endpoint is removed.
Requirement 4: Net Change Waterfall Frontend Chart
User Story: As a compliance analyst, I want to see a waterfall chart showing net movement per cycle (starting count → +new → +recurring → −resolved → ending count), so that I can immediately tell whether the compliance posture is improving or degrading.
Acceptance Criteria
- THE Waterfall_Chart SHALL render a bar chart using Recharts where each cycle shows four visual segments: a transparent base (starting count), a red segment for new findings, an amber segment for recurring findings, and a green downward segment for resolved findings, producing a waterfall effect.
- WHEN a user hovers over any segment, THE Waterfall_Chart SHALL display a DarkTooltip showing the cycle date, starting count, new count, recurring count, resolved count, and ending count.
- THE Waterfall_Chart SHALL label the X-axis with cycle dates formatted as MM/DD/YY using the existing
fmtDatehelper. - THE Waterfall_Chart SHALL label the Y-axis with finding counts using monospace axis styling consistent with the Design_System.
- THE Waterfall_Chart SHALL render a
NoDataplaceholder when the API returns an empty array. - THE Waterfall_Chart SHALL be wrapped in a ChartCard with the title "Net Change Waterfall" and a subtitle describing the chart purpose.
- THE Waterfall_Chart SHALL occupy the same grid position (Chart 5 slot) previously held by the Most Persistent Findings chart in the Dashboard layout.
- THE Waterfall_Chart SHALL use
#EF4444for new findings,#F59E0Bfor recurring findings, and#10B981for resolved findings, matching the existing color conventions in the Dashboard.
Requirement 5: Frontend Data Fetching Integration
User Story: As a developer, I want the Dashboard to fetch data from the two new endpoints in place of the old ones, so that the panel loads the correct data for the replacement charts without breaking the other four charts.
Acceptance Criteria
- THE Dashboard SHALL replace the fetch call to
/compliance/mttrwith a fetch call to the aging endpoint and store the response in component state. - THE Dashboard SHALL replace the fetch call to
/compliance/top-recurringwith a fetch call to the waterfall endpoint and store the response in component state. - THE Dashboard SHALL continue to fetch
/compliance/trendsand/archer-tickets/status-trendwithout modification. - THE Dashboard SHALL load all four endpoints in parallel using
Promise.allon component mount, matching the existing loading pattern. - IF any individual fetch fails, THEN THE Dashboard SHALL render the corresponding chart in its
NoDatastate without affecting the other charts.
Requirement 6: Removal of Obsolete Code
User Story: As a developer, I want the old MTTR and Persistent Findings chart components and endpoints removed, so that the codebase does not contain dead code.
Acceptance Criteria
- THE Dashboard SHALL remove the
MttrChartcomponent function and all references to themttrstate variable. - THE Dashboard SHALL remove the
RecurringChartcomponent function and all references to therecurringstate variable. - THE Compliance_API SHALL remove the old
/mttrSQL query and handler logic, replacing it with the aging endpoint handler at the same route path. - THE Compliance_API SHALL remove the old
/top-recurringSQL query and handler logic, replacing it with the waterfall endpoint handler at the same route path.