# Requirements Document ## Introduction Add a tab system to the existing Metric Graphs panel on the ReportingPage so that Atlas-specific coverage metrics live alongside the existing Ivanti donut charts without cluttering the current layout. The existing four donut charts (Open vs Closed, Action Coverage, FP Finding Status, FP Workflow Status) move under an "Ivanti Findings" tab. A new "Atlas Coverage" tab displays donut charts derived from the cached Atlas action plan data — plan coverage, plan type breakdown, and plan status distribution. A new backend endpoint on the existing Atlas router aggregates the cached data into chart-ready metrics, keeping server.js untouched. ## Glossary - **Dashboard**: The STEAM Security Dashboard frontend React application - **ReportingPage**: The existing frontend page (`frontend/src/components/pages/ReportingPage.js`) displaying Ivanti host findings, metric charts, and the findings table - **Metric_Graphs_Panel**: The existing panel on the ReportingPage containing four SVG donut charts and the IvantiCountsChart trend line - **Tab_System**: A horizontal tab bar added to the Metric_Graphs_Panel header that switches between Ivanti and Atlas chart views - **Atlas_Cache**: The existing `atlas_action_plans_cache` SQLite table storing per-host action plan status, including `plans_json` - **Atlas_Router**: The existing Express route module (`backend/routes/atlas.js`) mounted at `/api/atlas` - **Atlas_Metrics_Endpoint**: A new `GET /api/atlas/metrics` endpoint on the Atlas_Router that returns aggregated chart data - **Coverage_Donut**: A donut chart showing hosts with action plans vs hosts without action plans - **Plan_Type_Donut**: A donut chart showing the distribution of action plans across the five plan types (decommission, remediation, false_positive, risk_acceptance, scan_exclusion) - **Plan_Status_Donut**: A donut chart showing the distribution of action plans across their status values (e.g. active, expired, completed) - **Action_Plan**: A compliance plan in Atlas with a type, commit date, and status — stored in the `plans_json` column of the Atlas_Cache - **Host_ID**: The shared numeric identifier linking an Ivanti host finding to an Atlas host ## Requirements ### Requirement 1: Atlas Metrics Aggregation Endpoint **User Story:** As a frontend developer, I want a single endpoint that returns pre-aggregated Atlas metrics, so that the frontend can render donut charts without parsing raw plan JSON on the client. #### Acceptance Criteria 1. THE Atlas_Router SHALL expose a `GET /api/atlas/metrics` endpoint that requires authentication 2. WHEN the metrics endpoint is called, THE Atlas_Router SHALL query all rows from the Atlas_Cache table including the `plans_json` column 3. WHEN rows are retrieved, THE Atlas_Router SHALL compute and return a JSON object containing: `totalHosts` (integer count of all cached hosts), `hostsWithPlans` (integer count of hosts where `has_action_plan` equals 1), `hostsWithoutPlans` (integer count of hosts where `has_action_plan` equals 0), `plansByType` (object mapping each plan type string to its integer count across all hosts), `plansByStatus` (object mapping each plan status string to its integer count across all hosts), and `totalPlans` (integer sum of all plans across all hosts) 4. WHEN the Atlas_Cache table is empty, THE Atlas_Router SHALL return the metrics object with all counts set to zero and `plansByType` and `plansByStatus` as empty objects 5. IF a row's `plans_json` column contains invalid JSON, THEN THE Atlas_Router SHALL skip that row's plan details and continue processing remaining rows 6. THE Atlas_Metrics_Endpoint SHALL NOT modify server.js — the endpoint SHALL be added to the existing Atlas_Router module only ### Requirement 2: Tab System in Metric Graphs Panel **User Story:** As a dashboard user, I want the Metric Graphs panel to have tabs, so that I can switch between Ivanti findings metrics and Atlas coverage metrics without the panel becoming overcrowded. #### Acceptance Criteria 1. THE Dashboard SHALL display a horizontal tab bar in the Metric_Graphs_Panel header area, to the right of the "Metric Graphs" title 2. THE Tab_System SHALL contain exactly two tabs labeled "Ivanti Findings" and "Atlas Coverage" 3. WHEN the ReportingPage loads, THE Tab_System SHALL default to the "Ivanti Findings" tab as the active tab 4. WHEN the "Ivanti Findings" tab is active, THE Metric_Graphs_Panel SHALL display the existing four donut charts (Open vs Closed, Action Coverage, FP Finding Status, FP Workflow Status) in their current layout 5. WHEN the "Atlas Coverage" tab is active, THE Metric_Graphs_Panel SHALL display the Atlas-specific donut charts (Coverage_Donut, Plan_Type_Donut, Plan_Status_Donut) in a horizontal flex row matching the existing chart layout pattern 6. THE Tab_System SHALL visually indicate the active tab using the design system accent color and a bottom border highlight 7. THE Tab_System SHALL use monospace font, uppercase text, and letter spacing consistent with the existing Metric_Graphs_Panel header style 8. WHEN the user switches tabs, THE Metric_Graphs_Panel content SHALL update immediately without a full page reload ### Requirement 3: Atlas Coverage Donut Chart **User Story:** As a dashboard user, I want to see what percentage of cached hosts have Atlas action plans, so that I can gauge overall compliance coverage at a glance. #### Acceptance Criteria 1. WHEN the "Atlas Coverage" tab is active, THE Dashboard SHALL display a Coverage_Donut chart showing hosts with plans vs hosts without plans 2. THE Coverage_Donut SHALL use emerald (`#10B981`) for hosts with plans and amber (`#F59E0B`) for hosts without plans 3. THE Coverage_Donut SHALL display the total host count as center text with a "HOSTS" label below it 4. THE Coverage_Donut SHALL include a legend showing the count and percentage for each segment 5. WHEN the Atlas_Cache contains no data, THE Coverage_Donut SHALL display a "No data — run Atlas Sync" message instead of an empty chart 6. THE Coverage_Donut SHALL follow the same SVG donut dimensions and styling as the existing StatusDonut component (180px size, 72px outer radius, 48px inner radius) ### Requirement 4: Plan Type Distribution Donut Chart **User Story:** As a dashboard user, I want to see how action plans are distributed across plan types, so that I can understand the remediation strategy mix. #### Acceptance Criteria 1. WHEN the "Atlas Coverage" tab is active, THE Dashboard SHALL display a Plan_Type_Donut chart showing the count of plans per type 2. THE Plan_Type_Donut SHALL assign a distinct color to each plan type: decommission (`#EF4444`), remediation (`#0EA5E9`), false_positive (`#A855F7`), risk_acceptance (`#F59E0B`), scan_exclusion (`#64748B`) 3. THE Plan_Type_Donut SHALL display the total plan count as center text with a "PLANS" label below it 4. THE Plan_Type_Donut SHALL include a legend showing the label, count, and percentage for each plan type that has a count greater than zero 5. WHEN no plans exist in the Atlas_Cache, THE Plan_Type_Donut SHALL display a "No plans — run Atlas Sync" message instead of an empty chart 6. THE Plan_Type_Donut SHALL follow the same SVG donut dimensions and styling as the existing donut chart components ### Requirement 5: Plan Status Distribution Donut Chart **User Story:** As a dashboard user, I want to see how action plans are distributed across statuses, so that I can identify how many plans are active vs expired or completed. #### Acceptance Criteria 1. WHEN the "Atlas Coverage" tab is active, THE Dashboard SHALL display a Plan_Status_Donut chart showing the count of plans per status value 2. THE Plan_Status_Donut SHALL assign colors to known statuses: active (`#10B981`), expired (`#EF4444`), completed (`#0EA5E9`), and use a neutral color (`#64748B`) for any unrecognized status values 3. THE Plan_Status_Donut SHALL display the total plan count as center text with a "STATUS" label below it 4. THE Plan_Status_Donut SHALL include a legend showing the label, count, and percentage for each status that has a count greater than zero 5. WHEN no plans exist in the Atlas_Cache, THE Plan_Status_Donut SHALL display a "No plans — run Atlas Sync" message instead of an empty chart 6. THE Plan_Status_Donut SHALL follow the same SVG donut dimensions and styling as the existing donut chart components ### Requirement 6: Atlas Metrics Data Fetching **User Story:** As a frontend developer, I want the Atlas metrics fetched efficiently and kept in sync with the Atlas cache, so that the charts reflect the latest synced data without unnecessary API calls. #### Acceptance Criteria 1. WHEN the ReportingPage mounts, THE Dashboard SHALL fetch Atlas metrics from `GET /api/atlas/metrics` and store the result in component state 2. WHEN an Atlas sync completes successfully (via the existing Atlas sync button), THE Dashboard SHALL re-fetch Atlas metrics from `GET /api/atlas/metrics` to update the charts 3. WHILE the Atlas metrics fetch is in progress, THE Dashboard SHALL display a loading indicator in the Atlas Coverage tab content area 4. IF the Atlas metrics fetch fails, THEN THE Dashboard SHALL display an error message in the Atlas Coverage tab content area with the failure reason 5. THE Dashboard SHALL NOT fetch Atlas metrics on every tab switch — the data SHALL be fetched once on mount and refreshed only after a sync operation ### Requirement 7: IvantiCountsChart Visibility with Tabs **User Story:** As a dashboard user, I want the IvantiCountsChart trend line to remain visible when the Ivanti Findings tab is active, so that the existing reporting experience is preserved. #### Acceptance Criteria 1. WHEN the "Ivanti Findings" tab is active, THE Dashboard SHALL display the IvantiCountsChart trend line below the Metric_Graphs_Panel, matching its current position 2. WHEN the "Atlas Coverage" tab is active, THE Dashboard SHALL hide the IvantiCountsChart trend line since it is not relevant to Atlas metrics 3. THE IvantiCountsChart component SHALL continue to function identically to its current behavior when visible ### Requirement 8: Tab System Styling and Accessibility **User Story:** As a dashboard user, I want the tab system to be visually consistent with the existing design system and keyboard accessible, so that the interface feels cohesive and usable. #### Acceptance Criteria 1. THE Tab_System tabs SHALL use inline styles consistent with the design system: dark background, monospace font at 0.7rem, uppercase text, 0.08em letter spacing 2. THE active tab SHALL have a bottom border of 2px solid using the panel accent color (`#F59E0B`) and brighter text color (`#F59E0B`) 3. THE inactive tab SHALL have muted text color (`#64748B`) and no bottom border highlight 4. WHEN the user hovers over an inactive tab, THE tab SHALL display a subtle background color change to indicate interactivity 5. THE Tab_System tabs SHALL use `role="tab"`, `aria-selected`, and `role="tabpanel"` attributes for screen reader accessibility 6. THE Tab_System tabs SHALL be keyboard navigable using Tab and Enter keys