Skip to content

[Customer Portal] Improvements in the Security Center - #575

Merged
v15a1 merged 4 commits into
wso2-open-operations:mainfrom
shayanmalinda:main
Apr 24, 2026
Merged

v15a1 merged 4 commits into
wso2-open-operations:mainfrom
shayanmalinda:main

Conversation

@shayanmalinda

@shayanmalinda shayanmalinda commented Apr 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Add product name and version filters (with clear-filters control) and client-side filtering/pagination for vulnerabilities.
    • Expand vulnerability table to show product metadata, component type, component version, update level, and additional fields.
    • Details view redesigned into a single, standardized card with clearer field layout.
  • Improvements

    • Skeleton and loading states updated to match the expanded table layout.

@coderabbitai

coderabbitai Bot commented Apr 23, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@shayanmalinda has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 49 minutes and 51 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 49 minutes and 51 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3cf99f8e-1ea0-4515-b16c-f5ea02aca55d

📥 Commits

Reviewing files that changed from the base of the PR and between 485c0b1 and a52ab3a.

📒 Files selected for processing (2)
  • apps/customer-portal/backend/service.bal
  • apps/customer-portal/webapp/src/features/security/components/ProductVulnerabilitiesTable.tsx
📝 Walkthrough

Walkthrough

Adds product-level metadata (productName, productVersion, componentType, updateLevel) across backend types, OpenAPI, mapping and service logic (including bulk fetch + caching for large limits). Frontend gains product/version filters, client-side filtering/pagination, expanded table/DETAILS UI and updated constants/types.

Changes

Cohort / File(s) Summary
Backend: types, schema & service
apps/customer-portal/backend/modules/entity/types.bal, apps/customer-portal/backend/modules/types/types.bal, apps/customer-portal/backend/openapi.yaml, apps/customer-portal/backend/service.bal, apps/customer-portal/backend/utils.bal, apps/customer-portal/backend/Dependencies.toml
Added optional productName, productVersion, componentType, updateLevel to vulnerability types and OpenAPI schema; removed limit max constraint; extended mapping functions to populate new fields; implemented bulk-fetch (batched 50) + org-scoped caching for large limit requests; added ballerina/cache dependency.
Frontend: types, constants & utils
apps/customer-portal/webapp/src/features/security/types/security.ts, .../constants/securityConstants.ts, .../utils/productVulnerabilitiesTable.ts
Extended frontend types to include product fields and new filter props; added constants (column count → 12, product/version labels, all-fetch limit); updated active-filter counting to include product filters.
Frontend: filters, table, list & skeleton UI
apps/customer-portal/webapp/src/features/security/components/ProductVulnerabilitiesFilters.tsx, .../ProductVulnerabilitiesTable.tsx, .../ProductVulnerabilitiesList.tsx, .../ProductVulnerabilitiesTableSkeleton.tsx, .../VulnerabilityDetailsContent.tsx
Added product & product-version dropdowns, clear-filters handler, switched to client-side filtering/pagination using a FETCH_ALL request, derived product/version option lists, expanded table columns and skeleton to match new columns, refactored details view into a single card with standardized fields.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client(UI)
    participant Frontend as Frontend (Table)
    participant Service as Backend Service
    participant Entity as Entity Store
    participant Cache as Org Cache

    Client->>Frontend: request vulnerabilities (limit > 50)
    Frontend->>Service: FETCH_ALL_REQUEST (limit large)
    Service->>Cache: lookup cache(key=filters)
    alt cache hit
        Cache-->>Service: cached aggregated result
    else cache miss
        Service->>Entity: count(filters, limit=1)
        Entity-->>Service: totalCount
        loop batches (50)
            Service->>Entity: search(filters, limit=50, offset=N)
            Entity-->>Service: batchResults
            Service->>Service: map batchResults
            Service-->>Service: aggregate batches
        end
        Service->>Cache: store aggregated result (ttl=12h)
        Cache-->>Service: ack
    end
    Service-->>Frontend: aggregated response (totalRecords, items)
    Frontend->>Frontend: client-side filter/search/pagination
    Frontend-->>Client: rendered page
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

Type/Improvement, App/Customer Portal, Area/Backend, Area/Frontend, Type/UX

Suggested reviewers

  • Rashmika998
  • cloby99
  • suhand

Poem

🐰 Hopping through fields with glee,

New names and versions I do see.
Filters sprout and tables grow,
Batches fetch what caches know.
A carrot-toast to clearer rows! 🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is completely empty; no information was provided by the author despite a comprehensive template being available. Complete the description template with Purpose, Goals, Approach, User stories, Release notes, Documentation, and other required sections to explain the changes.
Title check ❓ Inconclusive The title 'Improvements in the Security Center' is vague and generic, lacking specificity about what improvements were made to the Security Center. Specify the main improvement or feature added. For example: 'Add product name and version filtering to Security Center vulnerabilities' or 'Implement bulk vulnerability search with client-side pagination'.
✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
apps/customer-portal/webapp/src/features/security/components/ProductVulnerabilitiesTable.tsx (1)

150-153: ⚠️ Potential issue | 🟠 Major

Clear stale product versions when the product changes.

Because version options are scoped to filters.productName, changing the product should also clear productVersion; otherwise the next request can send a version from the previous product and return an empty list.

Proposed dependent-filter reset
   const handleUpdateFilter = (field: string, value: string | number) => {
-    setFilters((prev) => ({ ...prev, [field]: value }));
+    setFilters((prev) => ({
+      ...prev,
+      [field]: value,
+      ...(field === "productName" ? { productVersion: "" } : {}),
+    }));
     setPage(0);
   };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/customer-portal/webapp/src/features/security/components/ProductVulnerabilitiesTable.tsx`
around lines 150 - 153, The handleUpdateFilter function should clear dependent
productVersion when productName changes: update handleUpdateFilter (used to
setFilters and setPage) so that when field === 'productName' you also remove or
reset filters.productVersion (e.g., set it to empty string or undefined) before
calling setFilters, ensuring the request won't send a stale version; keep
setPage(0) behavior unchanged.
apps/customer-portal/webapp/src/features/security/utils/productVulnerabilitiesTable.ts (1)

21-36: ⚠️ Potential issue | 🟡 Minor

Update the active-filter JSDoc to include product filters.

The implementation now counts productName and productVersion, but the doc still says only search + severity. As per learnings, ensure JSDoc is attached to the correct function/signature and kept accurate.

Proposed doc update
 /**
- * Counts search + severity filters for the product vulnerabilities table header.
+ * Counts search, severity, product name, and product version filters for the product vulnerabilities table header.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/customer-portal/webapp/src/features/security/utils/productVulnerabilitiesTable.ts`
around lines 21 - 36, The JSDoc for countProductVulnerabilityTableActiveFilters
is outdated (it only mentions search + severity) while the implementation also
counts productName and productVersion; update the JSDoc block above the function
to list search, severity, productName, and productVersion as counted filters and
ensure the doc is directly attached to the
countProductVulnerabilityTableActiveFilters function signature so tooling picks
it up.
apps/customer-portal/backend/modules/types/types.bal (1)

857-863: ⚠️ Potential issue | 🔴 Critical

Duplicate componentType and updateLevel declarations in ProductVulnerabilityResponse.

ProductVulnerability (lines 824–854) declares optional componentType? and updateLevel? at lines 844 and 846. ProductVulnerabilityResponse includes *ProductVulnerability at line 858, which pulls those fields into the record. Re-declaring them at lines 860–862 is redundant and causes a duplicate field compile error in Ballerina. The entity-side ProductVulnerabilityResponse in apps/customer-portal/backend/modules/entity/types.bal (lines 1455–1458) correctly omits these re-declarations, relying only on *ProductVulnerability.

🛠 Proposed fix
 # Product vulnerability information.
 public type ProductVulnerabilityResponse record {|
     *ProductVulnerability;
-    # Type of the component
-    string componentType?;
-    # Update level for the vulnerability
-    string updateLevel?;
 |};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/backend/modules/types/types.bal` around lines 857 - 863,
ProductVulnerabilityResponse currently embeds *ProductVulnerability and then
re-declares the optional fields componentType and updateLevel, causing
duplicate-field compile errors; to fix it, remove the redundant declarations of
componentType? and updateLevel? from the ProductVulnerabilityResponse record so
it only contains "*ProductVulnerability" and any truly new fields, leaving
ProductVulnerability (which already defines componentType? and updateLevel?) as
the single source of those fields.
🧹 Nitpick comments (2)
apps/customer-portal/webapp/src/features/security/types/security.ts (1)

83-92: Inconsistent nullability between productName/productVersion and componentType/updateLevel.

productName/productVersion are typed as string | null, while the sibling optional fields added in the same PR (componentType?: string, updateLevel?: string) are plain optional strings. The corresponding Ballerina backend fields are all declared the same way (string productName?;, string componentType?; — optional, non-nullable). Pick one convention (preferably ?: string to match backend, since these are serialized as absent when not present rather than null) and apply it consistently.

♻️ Proposed alignment
-  productName?: string | null;
-  productVersion?: string | null;
+  productName?: string;
+  productVersion?: string;

If backend can genuinely return null for these (verify against utils.bal mapping), then also make componentType/updateLevel string | null for consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/customer-portal/webapp/src/features/security/types/security.ts` around
lines 83 - 92, The ProductSecurity type mixes `string | null` (productName,
productVersion) with optional strings (componentType?, updateLevel?), causing
inconsistent nullability; update the declarations to use the backend-aligned
optional-string convention by changing `productName: string | null` and
`productVersion: string | null` to `productName?: string` and `productVersion?:
string` (or alternatively, if backend truly returns null, change
`componentType?: string` and `updateLevel?: string` to `componentType: string |
null` and `updateLevel: string | null`), and adjust any code that constructs or
reads these fields to treat absent values as undefined rather than null; use the
property names productName, productVersion, componentType, and updateLevel to
locate and update the type in the Security/Product-related type definitions.
apps/customer-portal/webapp/src/features/security/components/VulnerabilityDetailsContent.tsx (1)

283-341: Hardcoded UI strings — use existing constants.

The file already imports named constants for most labels (e.g., VULNERABILITY_DETAILS_PRODUCT_NAME_LABEL, VULNERABILITY_DETAILS_JUSTIFICATION_LABEL). However, "Product Vulnerabilities" (line 284), "CVE" / "Vulnerability ID" (lines 329–330), and "Severity" (line 340) are inlined. This is inconsistent and makes future i18n/rewording harder. Please extract them to securityConstants.ts alongside the existing VULNERABILITY_DETAILS_* constants.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/customer-portal/webapp/src/features/security/components/VulnerabilityDetailsContent.tsx`
around lines 283 - 341, The component VulnerabilityDetailsContent.tsx contains
hardcoded UI strings ("Product Vulnerabilities", "CVE", "Vulnerability ID",
"Severity"); add corresponding constants in securityConstants.ts (e.g.,
VULNERABILITY_DETAILS_PRODUCT_VULNERABILITIES_LABEL,
VULNERABILITY_DETAILS_CVE_LABEL, VULNERABILITY_DETAILS_VULNERABILITY_ID_LABEL,
VULNERABILITY_DETAILS_SEVERITY_LABEL) following the existing
VULNERABILITY_DETAILS_* naming pattern, export them, and update
VulnerabilityDetailsContent.tsx to import and use those constants in place of
the inline strings (replace the Typography title and the FieldBox label props
and the Severity caption).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/customer-portal/backend/openapi.yaml`:
- Around line 4639-4644: Update the OpenAPI schema for
ProductVulnerabilitySearchPayload so its filters object declares the missing
fields productName and productVersion (both type: string, with appropriate
descriptions) to match the response and frontend behavior; locate the
ProductVulnerabilitySearchPayload definition and add productName and
productVersion into the filters property (also ensure the same additions are
made to the other occurrence referenced around the second block for lines
~4697-4715 so both payload definitions stay in sync).

In
`@apps/customer-portal/webapp/src/features/security/components/ProductVulnerabilitiesList.tsx`:
- Around line 70-76: Headers in ProductVulnerabilitiesList.tsx are mismatched to
the rendered fields: the header for the column rendering row.updateLevel
currently reads "WSO2 Resolution" and the "Usecase" header has a typo; update
those TableCell labels to reflect the actual data (e.g. change "WSO2 Resolution"
to "Update Level" or another label matching row.updateLevel, and change
"Usecase" to "Use Case") and make the same corrections in the later duplicate
header block (the block referenced around lines 173–181) so headers align with
the rendered fields.

In
`@apps/customer-portal/webapp/src/features/security/components/ProductVulnerabilitiesTable.tsx`:
- Around line 35-39: OPTIONS_FETCH_REQUEST currently caps option fetching to
PRODUCT_VULNERABILITIES_OPTIONS_FETCH_LIMIT (500), causing missing filter
options; replace this one-shot request with either (a) a call to a dedicated
metadata/options endpoint that returns all distinct product name/version
options, or (b) implement paginated fetching that loops using the response's
totalRecords and pagination cursors (fetching subsequent pages until all records
are retrieved) and then deduplicate/aggregate product name/version options
before treating the set as complete; update the code paths that use
OPTIONS_FETCH_REQUEST (the option-population logic referenced around the current
constant and the blocks noted in the comment) to use the new metadata call or
the paginated-aggregate function and remove the hard cap constant usage.

In
`@apps/customer-portal/webapp/src/features/security/components/ProductVulnerabilitiesTableSkeleton.tsx`:
- Around line 36-47: PRODUCT_VULNERABILITIES_TABLE_COLUMN_COUNT is set to 10 but
the skeleton and actual data rows render 12 TableCell columns; update the
constant PRODUCT_VULNERABILITIES_TABLE_COLUMN_COUNT in securityConstants.ts from
10 to 12 so colSpan usage in ProductVulnerabilitiesList.tsx (error/empty state
rows) matches the 12-column layout used by
ProductVulnerabilitiesTableSkeleton.tsx and the data rows, ensuring aligned
table width.

In
`@apps/customer-portal/webapp/src/features/security/components/VulnerabilityDetailsContent.tsx`:
- Around line 404-422: The WSO2 Resolution FieldBox is incorrectly bound to
data.useCase; change its value prop to the correct field (e.g.,
value={data.resolution ?? VULNERABILITY_DETAILS_NOT_APPLICABLE_LABEL}) if WSO2
should show the existing resolution, or to value={data.wso2Resolution ??
VULNERABILITY_DETAILS_NOT_APPLICABLE_LABEL} if a new WSO2-specific field exists
on the ProductVulnerability model; update the mapping/props accordingly and
ensure you don't create an unintended duplicate with the existing "Resolution"
FieldBox (if both are required, add data.wso2Resolution to the model/mapping and
use that in the VULNERABILITY_DETAILS_WSO2_RESOLUTION_LABEL FieldBox).

---

Outside diff comments:
In `@apps/customer-portal/backend/modules/types/types.bal`:
- Around line 857-863: ProductVulnerabilityResponse currently embeds
*ProductVulnerability and then re-declares the optional fields componentType and
updateLevel, causing duplicate-field compile errors; to fix it, remove the
redundant declarations of componentType? and updateLevel? from the
ProductVulnerabilityResponse record so it only contains "*ProductVulnerability"
and any truly new fields, leaving ProductVulnerability (which already defines
componentType? and updateLevel?) as the single source of those fields.

In
`@apps/customer-portal/webapp/src/features/security/components/ProductVulnerabilitiesTable.tsx`:
- Around line 150-153: The handleUpdateFilter function should clear dependent
productVersion when productName changes: update handleUpdateFilter (used to
setFilters and setPage) so that when field === 'productName' you also remove or
reset filters.productVersion (e.g., set it to empty string or undefined) before
calling setFilters, ensuring the request won't send a stale version; keep
setPage(0) behavior unchanged.

In
`@apps/customer-portal/webapp/src/features/security/utils/productVulnerabilitiesTable.ts`:
- Around line 21-36: The JSDoc for countProductVulnerabilityTableActiveFilters
is outdated (it only mentions search + severity) while the implementation also
counts productName and productVersion; update the JSDoc block above the function
to list search, severity, productName, and productVersion as counted filters and
ensure the doc is directly attached to the
countProductVulnerabilityTableActiveFilters function signature so tooling picks
it up.

---

Nitpick comments:
In
`@apps/customer-portal/webapp/src/features/security/components/VulnerabilityDetailsContent.tsx`:
- Around line 283-341: The component VulnerabilityDetailsContent.tsx contains
hardcoded UI strings ("Product Vulnerabilities", "CVE", "Vulnerability ID",
"Severity"); add corresponding constants in securityConstants.ts (e.g.,
VULNERABILITY_DETAILS_PRODUCT_VULNERABILITIES_LABEL,
VULNERABILITY_DETAILS_CVE_LABEL, VULNERABILITY_DETAILS_VULNERABILITY_ID_LABEL,
VULNERABILITY_DETAILS_SEVERITY_LABEL) following the existing
VULNERABILITY_DETAILS_* naming pattern, export them, and update
VulnerabilityDetailsContent.tsx to import and use those constants in place of
the inline strings (replace the Typography title and the FieldBox label props
and the Severity caption).

In `@apps/customer-portal/webapp/src/features/security/types/security.ts`:
- Around line 83-92: The ProductSecurity type mixes `string | null`
(productName, productVersion) with optional strings (componentType?,
updateLevel?), causing inconsistent nullability; update the declarations to use
the backend-aligned optional-string convention by changing `productName: string
| null` and `productVersion: string | null` to `productName?: string` and
`productVersion?: string` (or alternatively, if backend truly returns null,
change `componentType?: string` and `updateLevel?: string` to `componentType:
string | null` and `updateLevel: string | null`), and adjust any code that
constructs or reads these fields to treat absent values as undefined rather than
null; use the property names productName, productVersion, componentType, and
updateLevel to locate and update the type in the Security/Product-related type
definitions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c3fd6994-55c7-410e-991e-86b8a7a72e80

📥 Commits

Reviewing files that changed from the base of the PR and between bc75e68 and c660471.

📒 Files selected for processing (12)
  • apps/customer-portal/backend/modules/entity/types.bal
  • apps/customer-portal/backend/modules/types/types.bal
  • apps/customer-portal/backend/openapi.yaml
  • apps/customer-portal/backend/utils.bal
  • apps/customer-portal/webapp/src/features/security/components/ProductVulnerabilitiesFilters.tsx
  • apps/customer-portal/webapp/src/features/security/components/ProductVulnerabilitiesList.tsx
  • apps/customer-portal/webapp/src/features/security/components/ProductVulnerabilitiesTable.tsx
  • apps/customer-portal/webapp/src/features/security/components/ProductVulnerabilitiesTableSkeleton.tsx
  • apps/customer-portal/webapp/src/features/security/components/VulnerabilityDetailsContent.tsx
  • apps/customer-portal/webapp/src/features/security/constants/securityConstants.ts
  • apps/customer-portal/webapp/src/features/security/types/security.ts
  • apps/customer-portal/webapp/src/features/security/utils/productVulnerabilitiesTable.ts

Comment thread apps/customer-portal/backend/openapi.yaml
…nalysis

- Add Product Name and Product Version filter dropdowns to the Component
  Analysis table; filter state resets version when product changes
- BFF transparently batches entity service calls (50/batch) when limit > 50,
  allowing the frontend to fetch all ~1500 records in a single request
- All filtering, pagination, and sorting now done client-side for instant UX
- 12-hour in-memory BFF cache for bulk vulnerability fetches (shared across
  users; keyed by server-side filter params)
- Remove maxValue: 50 constraint on Pagination.limit in entity types so the
  BFF can accept large-limit requests from the frontend
- Fix truncation in Use Case, Justification, and Resolution table columns
- Fix WSO2 Resolution field copy-paste bug in VulnerabilityDetailsContent
- Extract hardcoded strings to constants throughout the security feature
- Add productName/productVersion to search filter types (backend + frontend)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (1)
apps/customer-portal/webapp/src/features/security/components/VulnerabilityDetailsContent.tsx (1)

408-433: ⚠️ Potential issue | 🟠 Major

WSO2 Resolution still duplicates Resolution.

Both fields bind to data.resolution, so the page shows the same value twice under different labels. Unless the API is adding a separate WSO2-specific field, this should be a single field or the WSO2 box should bind to the intended distinct property.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/customer-portal/webapp/src/features/security/components/VulnerabilityDetailsContent.tsx`
around lines 408 - 433, The WSO2 Resolution FieldBox is incorrectly bound to
data.resolution and duplicates the Resolution field; update the WSO2 box (label
VULNERABILITY_DETAILS_WSO2_RESOLUTION_LABEL in VulnerabilityDetailsContent) to
bind to the correct property (e.g., data.wso2Resolution or the API-provided
WSO2-specific field) or remove the WSO2 FieldBox if no separate field exists so
it no longer duplicates the FieldBox using data.resolution; ensure the other
Resolution FieldBox remains bound to data.resolution and keep multiline/label
props as-is.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/customer-portal/backend/service.bal`:
- Around line 2992-2996: The cache key for responses is currently built in the
cacheKey variable using only payload.filters.searchQuery, severityId, and
statusId; include payload.filters.productName, payload.filters.productVersion,
and payload.filters.sortBy so different product filters or sort orders produce
distinct cache entries. Update the string template that builds cacheKey (the
cacheKey variable construction) to append productName, productVersion, and
sortBy (using the same null-coalescing pattern ?: "" as the existing fields) so
cache lookups and inserts account for those additional filter/sort dimensions.
- Around line 2999-3009: The cache-hit branch for productVulnerabilityCache.get
returns the full aggregated cachedEntry but still echoes reqOffset/reqLimit,
causing wrong pages; modify the productVulnerability cache-return logic (where
cachedEntry is used to build the types:ProductVulnerabilitySearchResponse) to
honor reqOffset and reqLimit by slicing the cachedEntry array to the window
[reqOffset, reqOffset + reqLimit) (or by starting aggregation at reqOffset and
collecting reqLimit entries) and set productVulnerabilities to that slice while
keeping totalRecords = cachedEntry.length(); update the same pattern in the
corresponding code paths around the product vulnerability bulk-fetch (the other
branch mentioned at 3048-3097) to ensure both cache hits and misses return the
requested page.

In
`@apps/customer-portal/webapp/src/features/security/components/ProductVulnerabilitiesTable.tsx`:
- Around line 159-161: The effect currently only signals errors to the parent by
calling onError(true) when isError is true, leaving the parent stuck in error
state after recovery; update the effect in the ProductVulnerabilitiesTable
component to call onError with the current isError value (i.e.,
onError(isError)) so the parent is notified both when an error occurs and when
the query recovers (isError becomes false), keeping the dependency array
[isError, onError] intact and guarding the call with onError?.
- Around line 146-153: The paginatedData useMemo can return an empty page when
filteredVulnerabilities shrinks because page isn't clamped; compute total =
filteredVulnerabilities.length and maxPage = Math.max(0, Math.ceil(total /
rowsPerPage) - 1) and ensure page <= maxPage before slicing (if page > maxPage,
call the page state setter to set it to maxPage) — implement this clamp either
inside a useEffect that watches filteredVulnerabilities and rowsPerPage or by
adjusting the logic in the paginatedData useMemo to set the page to maxPage when
needed; reference paginatedData, filteredVulnerabilities, page, rowsPerPage and
your page setter (e.g., setPage) when making the change.

---

Duplicate comments:
In
`@apps/customer-portal/webapp/src/features/security/components/VulnerabilityDetailsContent.tsx`:
- Around line 408-433: The WSO2 Resolution FieldBox is incorrectly bound to
data.resolution and duplicates the Resolution field; update the WSO2 box (label
VULNERABILITY_DETAILS_WSO2_RESOLUTION_LABEL in VulnerabilityDetailsContent) to
bind to the correct property (e.g., data.wso2Resolution or the API-provided
WSO2-specific field) or remove the WSO2 FieldBox if no separate field exists so
it no longer duplicates the FieldBox using data.resolution; ensure the other
Resolution FieldBox remains bound to data.resolution and keep multiline/label
props as-is.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 827c7c59-fd03-4e6c-bb14-937c729777a2

📥 Commits

Reviewing files that changed from the base of the PR and between c660471 and 485c0b1.

📒 Files selected for processing (11)
  • apps/customer-portal/backend/Dependencies.toml
  • apps/customer-portal/backend/modules/entity/types.bal
  • apps/customer-portal/backend/modules/types/types.bal
  • apps/customer-portal/backend/openapi.yaml
  • apps/customer-portal/backend/service.bal
  • apps/customer-portal/webapp/src/features/security/components/ProductVulnerabilitiesList.tsx
  • apps/customer-portal/webapp/src/features/security/components/ProductVulnerabilitiesTable.tsx
  • apps/customer-portal/webapp/src/features/security/components/VulnerabilityDetailsContent.tsx
  • apps/customer-portal/webapp/src/features/security/constants/securityConstants.ts
  • apps/customer-portal/webapp/src/features/security/types/security.ts
  • apps/customer-portal/webapp/src/features/security/utils/productVulnerabilitiesTable.ts
✅ Files skipped from review due to trivial changes (1)
  • apps/customer-portal/backend/Dependencies.toml
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/customer-portal/webapp/src/features/security/utils/productVulnerabilitiesTable.ts
  • apps/customer-portal/webapp/src/features/security/types/security.ts
  • apps/customer-portal/webapp/src/features/security/components/ProductVulnerabilitiesList.tsx

Comment thread apps/customer-portal/backend/service.bal Outdated
Comment thread apps/customer-portal/backend/service.bal
- Expand cache key to include productName, productVersion, and sortBy so
  distinct filter/sort combinations never share a cache entry
- Honor reqOffset/reqLimit when returning bulk-fetch results (both on cache
  hit and cache miss) so callers requesting a specific page get the correct
  window of records
- Clamp the active page to the last valid page when the filtered dataset
  shrinks (e.g. after applying a filter), preventing an empty-page render
- Pass the actual isError value to onError so the parent state is cleared
  when the query recovers after a transient failure

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@v15a1
v15a1 merged commit 5797436 into wso2-open-operations:main Apr 24, 2026
1 check passed
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