feat: improve archive finding clarity with finding IDs, historical severity labels, and related active finding indicators
This commit is contained in:
82
.kiro/specs/archive-finding-clarity/requirements.md
Normal file
82
.kiro/specs/archive-finding-clarity/requirements.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Requirements Document
|
||||
|
||||
## Introduction
|
||||
|
||||
The Ivanti Archive Findings panel on the STEAM Security Dashboard homepage displays findings that have transitioned through the archive lifecycle (Active, Archived, Returned, Closed). The current archive cards show the finding title, hostname, IP address, and a raw severity number — but lack clarity in several areas. Users cannot see the Ivanti finding ID for cross-referencing, the severity score appears to be a current value when it is actually a historical snapshot, and there is no indication when a related finding with the same title still exists on the same host under a different Ivanti finding ID.
|
||||
|
||||
This feature improves archive card clarity by adding finding IDs, labeling severity as historical, introducing a "related active finding" indicator, and using visual icon distinctions to communicate resolution status at a glance.
|
||||
|
||||
## Glossary
|
||||
|
||||
- **Archive_Card**: A single rendered entry in the archive findings list on the homepage, representing one row from the `ivanti_finding_archives` table.
|
||||
- **Archive_Panel**: The section of the homepage that contains the ArchiveSummaryBar stat cards and the expandable archive findings list.
|
||||
- **Finding_ID**: The stable Ivanti-assigned identifier for a host finding (stored as `finding_id` in `ivanti_finding_archives`). Finding IDs do not change with score drift or rescoring.
|
||||
- **Last_Severity**: The severity score recorded at the time a finding was archived or last transitioned between states. It is a historical snapshot, not a live risk assessment.
|
||||
- **Current_Findings_Cache**: The `ivanti_findings_cache` table containing the latest synced findings as a JSON array. Each cached finding has fields including `id`, `title`, `severity`, `hostName`, and `ipAddress`.
|
||||
- **Related_Active_Finding**: A finding in the Current_Findings_Cache that shares the same hostname and a similar title with an archived finding but has a different Finding_ID, indicating a genuinely distinct but related finding is still open on the same host.
|
||||
- **Archive_API**: The backend endpoint `GET /api/ivanti/archive` that returns archive records filtered by lifecycle state.
|
||||
- **Related_Findings_Endpoint**: A new backend endpoint that accepts archived finding details and returns matching active findings from the Current_Findings_Cache.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement 1: Display Finding ID on Archive Cards
|
||||
|
||||
**User Story:** As a security analyst, I want to see the Ivanti finding ID on each archive card, so that I can cross-reference archived findings with the Reporting page.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Archive_Card SHALL display the Finding_ID in monospace font below the finding title.
|
||||
2. WHEN the Finding_ID is longer than 20 characters, THE Archive_Card SHALL truncate the Finding_ID with an ellipsis and display the full value in a tooltip on hover.
|
||||
3. THE Archive_Card SHALL render the Finding_ID with a visually distinct style (muted color, smaller font size) so it is clearly secondary to the finding title.
|
||||
|
||||
### Requirement 2: Historical Severity Labeling
|
||||
|
||||
**User Story:** As a security analyst, I want the severity score on archive cards to be clearly labeled as a historical value, so that I do not mistake it for a current risk assessment.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Archive_Card SHALL display the Last_Severity with a "Last seen:" prefix label (e.g., "Last seen: 9.4").
|
||||
2. THE Archive_Card SHALL render the severity label in a muted, secondary style that visually distinguishes it from live severity badges used elsewhere in the dashboard.
|
||||
3. WHEN the Last_Severity value is null or zero, THE Archive_Card SHALL display "Last seen: —" as a placeholder.
|
||||
|
||||
### Requirement 3: Related Active Finding Detection API
|
||||
|
||||
**User Story:** As a security analyst, I want the system to detect when an archived finding has a related active finding on the same host, so that I can understand whether similar risk still exists.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Archive_API SHALL return a `related_active` field for each archive record, containing either `null` (no match) or an object with the matching active finding's `id`, `title`, and `severity`.
|
||||
2. WHEN matching archived findings to active findings, THE Related_Findings_Endpoint SHALL compare by exact hostname match AND case-insensitive substring containment of the archived finding title within the active finding title (or vice versa).
|
||||
3. WHEN multiple active findings match a single archived finding, THE Related_Findings_Endpoint SHALL return the match with the highest severity.
|
||||
4. IF the Current_Findings_Cache contains no findings or is empty, THEN THE Related_Findings_Endpoint SHALL return `null` for all `related_active` fields.
|
||||
5. THE Related_Findings_Endpoint SHALL exclude matches where the active finding's `id` is identical to the archived finding's Finding_ID.
|
||||
|
||||
### Requirement 4: Related Active Finding Indicator on Archive Cards
|
||||
|
||||
**User Story:** As a security analyst, I want to see a visual indicator on archive cards when a related active finding exists on the same host, so that I can quickly identify findings that may still represent active risk.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN an archive record has a non-null `related_active` field, THE Archive_Card SHALL display a badge reading "Similar finding active" with the related finding's ID and current severity.
|
||||
2. THE Archive_Card SHALL render the related active badge using the dashboard accent color (#0EA5E9) to distinguish it from the archive card's own severity display.
|
||||
3. WHEN an archive record has a null `related_active` field, THE Archive_Card SHALL not display any related-finding badge.
|
||||
|
||||
### Requirement 5: Visual Icon Distinction by Resolution Status
|
||||
|
||||
**User Story:** As a security analyst, I want archive cards to use different icons and border colors based on whether a related active finding exists, so that I can scan the list and quickly distinguish fully resolved findings from those with ongoing similar risk.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. WHEN an archive record has a non-null `related_active` field, THE Archive_Card SHALL display an alert-style icon (e.g., `AlertTriangle` from lucide-react) and use a warning-toned left border color (#F59E0B).
|
||||
2. WHEN an archive record has a null `related_active` field, THE Archive_Card SHALL display a check-style icon (e.g., `CheckCircle` from lucide-react) and use a success-toned left border color (#10B981).
|
||||
3. THE Archive_Card SHALL apply the icon and border color consistently regardless of the archive lifecycle state (ARCHIVED, RETURNED, or CLOSED).
|
||||
|
||||
### Requirement 6: Performance of Related Finding Lookup
|
||||
|
||||
**User Story:** As a security analyst, I want the archive panel to load promptly even when checking for related active findings, so that the feature does not degrade the homepage experience.
|
||||
|
||||
#### Acceptance Criteria
|
||||
|
||||
1. THE Archive_API SHALL compute related active finding matches server-side within the existing archive list query, avoiding separate per-card API calls from the frontend.
|
||||
2. WHEN the Current_Findings_Cache JSON is parsed for matching, THE Archive_API SHALL parse the cache once per request and reuse the parsed result across all archive records in the response.
|
||||
3. THE Archive_API response time for a filtered archive list SHALL remain under 500ms for up to 200 archive records.
|
||||
Reference in New Issue
Block a user