Skip to content

feat: security v2 UI#1774

Open
emlimlf wants to merge 9 commits intomainfrom
feat/security-v2-ui
Open

feat: security v2 UI#1774
emlimlf wants to merge 9 commits intomainfrom
feat/security-v2-ui

Conversation

@emlimlf
Copy link
Collaborator

@emlimlf emlimlf commented Mar 25, 2026

In this PR

  • Added a new section on the security page for the vulnerabilities
  • Wired the UI to the backend
  • Added Auth wall state for the vulnerabilities sections

Ticket

IN-1006

emlimlf added 8 commits March 24, 2026 16:06
Signed-off-by: Efren Lim <elim@linuxfoundation.org>
Signed-off-by: Efren Lim <elim@linuxfoundation.org>
Signed-off-by: Efren Lim <elim@linuxfoundation.org>
Signed-off-by: Efren Lim <elim@linuxfoundation.org>
Signed-off-by: Efren Lim <elim@linuxfoundation.org>
Signed-off-by: Efren Lim <elim@linuxfoundation.org>
Signed-off-by: Efren Lim <elim@linuxfoundation.org>
Signed-off-by: Efren Lim <elim@linuxfoundation.org>
Copilot AI review requested due to automatic review settings March 25, 2026 11:15
Signed-off-by: Efren Lim <elim@linuxfoundation.org>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “Vulnerabilities” section to the project Security view, wiring multiple UI widgets (summary, charts, tables, filters, drawer) to new backend endpoints and gating access behind authentication.

Changes:

  • Introduced vulnerability response types/config mappings and a TanStack query key for vulnerabilities.
  • Added VULNERABILITY_API_SERVICE with summary, breakdown, recent, and paginated “all vulnerabilities” queries.
  • Implemented the vulnerabilities UI (summary cards, severity/ecosystem charts, recent table + “view more” drawer, and auth-wall preview) and mounted it on the Security page.

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
frontend/types/vulnerabilities/responses.types.ts Adds vulnerability enums/types plus UI config mappings for severity/status.
frontend/setup/tailwind.ts Adds a Tailwind safelist for vulnerability-related color classes.
frontend/app/components/uikit/chart/configs/bar.chart.ts Adds a reusable horizontal bar chart config helper.
frontend/app/components/shared/types/tanstack.ts Adds a VULNERABILITIES query key.
frontend/app/components/modules/project/views/security.vue Mounts vulnerabilities section + auth wall based on authentication.
frontend/app/components/modules/project/services/vulnerability.api.service.ts Implements Vue Query calls for vulnerabilities summary/breakdowns/listing.
frontend/app/components/modules/project/components/vulnerabilities/vulnerability-table.vue Adds vulnerabilities table header + row rendering.
frontend/app/components/modules/project/components/vulnerabilities/vulnerability-summary.vue Adds top-level summary stats UI wired to the API.
frontend/app/components/modules/project/components/vulnerabilities/vulnerability-severity.vue Adds “by severity” stacked bar + legend wired to API.
frontend/app/components/modules/project/components/vulnerabilities/vulnerability-row.vue Adds a single vulnerability row renderer (badges, tooltips, status icon).
frontend/app/components/modules/project/components/vulnerabilities/vulnerability-filters.vue Adds filter/sort controls for the drawer list.
frontend/app/components/modules/project/components/vulnerabilities/vulnerability-ecosystem.vue Adds “by ecosystem” horizontal bar chart wired to API.
frontend/app/components/modules/project/components/vulnerabilities/vulnerability-drawer.vue Adds the “view more” drawer with infinite pagination and filters.
frontend/app/components/modules/project/components/vulnerabilities/vulnerabilities-section.vue Composes summary + charts + recent list + drawer into a card section.
frontend/app/components/modules/project/components/vulnerabilities/recent-vulnerabilities.vue Adds “recent vulnerabilities” list wired to API + view-more trigger.
frontend/app/components/modules/project/components/vulnerabilities/auth-wall-vulnerabilities.vue Adds unauthenticated preview/auth-wall CTA for vulnerabilities.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

</div>
</lfx-card>

<lfx-project-vulnerabilities-section
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LfxProjectVulnerabilitiesSection emits chooseRepository (used by the aggregated disclaimer CTA), but the parent doesn’t listen to it here. As a result, clicking “choose a specific repository” won’t open the repository switch modal. Wire the event to isSearchRepoModalOpen = true (kebab-case listener: @choose-repository).

Suggested change
<lfx-project-vulnerabilities-section
<lfx-project-vulnerabilities-section
v-if="isAuthenticated"
@choose-repository="isSearchRepoModalOpen = true"
/>

Copilot uses AI. Check for mistakes.
<!-- Table Body -->
<lfx-project-vulnerability-row
v-for="vulnerability in props.vulnerabilities"
:key="vulnerability.cveId"
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The v-for key uses vulnerability.cveId, which may not be unique (same CVE can appear across multiple packages/paths). Use a guaranteed-unique identifier like vulnerability.vulnerabilityId to avoid rendering/update issues.

Suggested change
:key="vulnerability.cveId"
:key="vulnerability.vulnerabilityId"

Copilot uses AI. Check for mistakes.
Comment on lines +130 to +131
const fixedCount = Math.round((data.value.fixedPercentage / 100) * data.value.count);
return data.value.count - fixedCount;
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

openVulnerabilities is derived from fixedPercentage using Math.round, which can produce inconsistent values (e.g., rounding can make fixedCount exceed count, yielding negative opens) and will drift when percentages are not exact. Consider having the API return open/fixed counts directly, or at least clamp the computed value to [0, count] and avoid rounding errors (e.g., compute fixedCount from a count field, or use a safer rounding strategy).

Suggested change
const fixedCount = Math.round((data.value.fixedPercentage / 100) * data.value.count);
return data.value.count - fixedCount;
const totalCount = typeof data.value.count === 'number' && data.value.count > 0 ? data.value.count : 0;
const rawFixedPercentage =
typeof data.value.fixedPercentage === 'number' ? data.value.fixedPercentage : 0;
// Clamp percentage to [0, 100] to avoid invalid values from the API
const clampedPercentage = Math.min(100, Math.max(0, rawFixedPercentage));
const rawFixedCount = (clampedPercentage / 100) * totalCount;
// Use floor and clamp to [0, totalCount] to avoid rounding beyond bounds
const fixedCount = Math.min(totalCount, Math.max(0, Math.floor(rawFixedCount)));
const opens = totalCount - fixedCount;
// Final guard to ensure non-negative open count
return Math.max(0, opens);

Copilot uses AI. Check for mistakes.

export enum VulnerabilityStatus {
OPEN = 'OPEN',
FIXED = 'RESOLVED',
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VulnerabilityStatus.FIXED is assigned the string value 'RESOLVED'. This mismatch between the enum member name and its actual value is confusing and easy to misuse in filters/logic. Consider renaming the enum member to RESOLVED (and keep label: 'Fixed' in the config), or make the value 'FIXED' if that’s what the API returns.

Suggested change
FIXED = 'RESOLVED',
FIXED = 'FIXED',

Copilot uses AI. Check for mistakes.
Comment on lines +81 to +83
'Median CVS of all vulnerabilities',
'Fix status',
'Vulnerability by severity',
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User-facing copy has a typo/inaccuracy: “Median CVS of all vulnerabilities” should be “Median/average CVSS …” (CVS is a different term) and currently doesn’t match the “Average CVSS” metric shown in the summary. Also “Vulnerability by severity” should be plural for consistency.

Suggested change
'Median CVS of all vulnerabilities',
'Fix status',
'Vulnerability by severity',
'Average CVSS of all vulnerabilities',
'Fix status',
'Vulnerabilities by severity',

Copilot uses AI. Check for mistakes.
getNextPageParam: (lastPage: AllVulnerabilitiesResponse) => {
const nextPage = lastPage.page + 1;
const totalPages = Math.ceil(lastPage.total / lastPage.pageSize);
return nextPage < totalPages ? nextPage : null;
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getNextPageParam returns null when there are no more pages. TanStack Query treats anything other than undefined as a valid next page param, so hasNextPage can stay truthy and fetchNextPage() may loop/refetch page 0 (since page=null becomes 0 server-side). Return undefined instead (and keep the return type aligned with the number pageParam generic).

Suggested change
return nextPage < totalPages ? nextPage : null;
return nextPage < totalPages ? nextPage : undefined;

Copilot uses AI. Check for mistakes.
params.value.severity,
params.value.ecosystem,
params.value.status,
params.value.sort,
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fetchAllVulnerabilities supports a pageSize param (and uses it in the queryFn), but pageSize is not included in the queryKey. If pageSize changes, Vue Query can reuse cached data from a different page size. Include params.value.pageSize (or the resolved default) in the key.

Suggested change
params.value.sort,
params.value.sort,
params.value.pageSize ?? DEFAULT_PAGE_SIZE,

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants