# Requirements Document ## Introduction The CVE Dashboard currently tracks three entity types — Archer tickets (risk acceptance exceptions), Jira tickets (work items), and CVEs (vulnerabilities) — but relationships between them are limited to a single primary CVE foreign key on each ticket. This feature introduces a generic `ticket_links` table that enables bidirectional, many-to-many associations between any combination of these entities. Users will be able to view, create, and remove links from ticket detail views in the UI. ## Glossary - **Link_Service**: The backend service responsible for creating, querying, and deleting ticket links. - **Link_UI**: The frontend component that displays linked items and provides controls for adding/removing links. - **Ticket_Links_Table**: The PostgreSQL table storing associations between entities. - **Entity**: One of the three linkable types in the system — an Archer ticket, a Jira ticket, or a CVE. - **Source**: The entity on the left side of a link record. - **Target**: The entity on the right side of a link record. - **Entity_Type**: A classification string identifying the kind of entity: `archer`, `jira`, or `cve`. - **Entity_ID**: The unique identifier for an entity within its type (e.g., `EXC-6056`, `STEAM-1234`, `CVE-2025-0905`). - **Relationship**: A label describing the nature of a link (e.g., `related`, `spawned_by`, `blocks`). ## Requirements ### Requirement 1: Create the ticket_links Table **User Story:** As a database administrator, I want a dedicated table for storing entity associations, so that any entity can be linked to any other entity without schema changes. #### Acceptance Criteria 1. THE Ticket_Links_Table SHALL store a source entity (source_type, source_id) and a target entity (target_type, target_id) in each row. 2. THE Ticket_Links_Table SHALL enforce a UNIQUE constraint on the combination of (source_type, source_id, target_type, target_id) to prevent duplicate links. 3. THE Ticket_Links_Table SHALL restrict source_type and target_type values to `archer`, `jira`, or `cve`. 4. THE Ticket_Links_Table SHALL store a relationship label defaulting to `related`. 5. THE Ticket_Links_Table SHALL record the user who created the link via a created_by foreign key to the users table. 6. THE Ticket_Links_Table SHALL record the creation timestamp defaulting to the current time. 7. THE Ticket_Links_Table SHALL include indexes on (source_type, source_id) and (target_type, target_id) to support efficient bidirectional queries. ### Requirement 2: Create a Link **User Story:** As a security analyst, I want to create a link between two entities, so that I can document relationships between Archer exceptions, Jira work items, and CVEs. #### Acceptance Criteria 1. WHEN a valid source entity, target entity, and relationship are provided, THE Link_Service SHALL insert a new row into the Ticket_Links_Table and return the created link record. 2. WHEN the source entity and target entity are identical (same type and same ID), THE Link_Service SHALL reject the request with a validation error. 3. WHEN a link between the same source and target already exists, THE Link_Service SHALL reject the request with a conflict error indicating the duplicate. 4. WHEN the source_type or target_type is not one of `archer`, `jira`, or `cve`, THE Link_Service SHALL reject the request with a validation error. 5. WHEN the entity ID format does not match the expected pattern for its type, THE Link_Service SHALL reject the request with a validation error. 6. THE Link_Service SHALL require the user to be authenticated before creating a link. 7. THE Link_Service SHALL log an audit entry when a link is successfully created. ### Requirement 3: Query Links for an Entity **User Story:** As a security analyst, I want to see all items linked to a given entity, so that I can understand the full context of a ticket or vulnerability. #### Acceptance Criteria 1. WHEN an entity type and entity ID are provided, THE Link_Service SHALL return all links where the entity appears as either source or target (bidirectional query). 2. THE Link_Service SHALL return each linked entity's type, ID, relationship label, creator, and creation timestamp. 3. WHEN no links exist for the given entity, THE Link_Service SHALL return an empty list. 4. THE Link_Service SHALL require the user to be authenticated before querying links. ### Requirement 4: Delete a Link **User Story:** As a security analyst, I want to remove a link between two entities, so that I can correct mistakes or remove outdated associations. #### Acceptance Criteria 1. WHEN a valid link ID is provided, THE Link_Service SHALL delete the corresponding row from the Ticket_Links_Table. 2. WHEN the provided link ID does not exist, THE Link_Service SHALL return a not-found error. 3. THE Link_Service SHALL require the user to be authenticated before deleting a link. 4. THE Link_Service SHALL log an audit entry when a link is successfully deleted. ### Requirement 5: Display Linked Items in the UI **User Story:** As a security analyst, I want to see a "Linked Items" section on ticket detail views, so that I can quickly navigate between related entities. #### Acceptance Criteria 1. WHILE viewing an Archer ticket detail page, THE Link_UI SHALL display a "Linked Items" section listing all entities linked to that Archer ticket. 2. WHILE viewing a Jira ticket detail page, THE Link_UI SHALL display a "Linked Items" section listing all entities linked to that Jira ticket. 3. WHEN no links exist for the displayed entity, THE Link_UI SHALL show an empty state message indicating no linked items. 4. THE Link_UI SHALL display each linked item with its entity type, entity ID, and relationship label. 5. THE Link_UI SHALL render each linked item's entity ID as a navigable link to that entity's detail view. ### Requirement 6: Add a Link from the UI **User Story:** As a security analyst, I want an "Add Link" button on ticket detail views, so that I can create associations without leaving the page. #### Acceptance Criteria 1. WHEN the user clicks the "Add Link" button, THE Link_UI SHALL display a form allowing the user to enter a target entity key and select a relationship type. 2. WHEN the user submits the form with a valid entity key, THE Link_UI SHALL call the Link_Service to create the link and refresh the Linked Items section. 3. WHEN the Link_Service returns a validation or conflict error, THE Link_UI SHALL display the error message to the user without clearing the form. 4. THE Link_UI SHALL auto-detect the entity type from the entered key format (EXC-XXXX for Archer, PROJECT-XXXX for Jira, CVE-YYYY-NNNNN for CVE). ### Requirement 7: Remove a Link from the UI **User Story:** As a security analyst, I want to remove a link directly from the Linked Items section, so that I can manage associations without navigating away. #### Acceptance Criteria 1. THE Link_UI SHALL display a remove control on each linked item in the Linked Items section. 2. WHEN the user activates the remove control, THE Link_UI SHALL prompt for confirmation before proceeding. 3. WHEN the user confirms removal, THE Link_UI SHALL call the Link_Service to delete the link and refresh the Linked Items section. 4. WHEN the Link_Service returns an error during removal, THE Link_UI SHALL display the error message to the user. ### Requirement 8: Bidirectional Link Symmetry **User Story:** As a security analyst, I want links to be visible from both sides of the association, so that navigating from either entity shows the connection. #### Acceptance Criteria 1. WHEN a link is created from Entity A to Entity B, THE Link_Service SHALL return that link when queried from Entity A. 2. WHEN a link is created from Entity A to Entity B, THE Link_Service SHALL return that link when queried from Entity B. 3. THE Link_Service SHALL treat (source=A, target=B) and (source=B, target=A) as the same logical link — creating one SHALL prevent creating the other. ### Requirement 9: Links are Optional **User Story:** As a security analyst, I want the linking feature to be purely additive, so that existing tickets without links continue to function normally. #### Acceptance Criteria 1. THE Link_Service SHALL not require any entity to have links — entities with zero links remain fully functional. 2. THE Link_Service SHALL not modify the existing cve_id and vendor foreign key columns on archer_tickets or jira_tickets. 3. WHEN an entity has no links, THE Link_UI SHALL display the empty state without errors or warnings.