Skip to content

feat(advisory): implement CSAF Source tab with raw JSON and advisory link#1065

Draft
CryptoRodeo wants to merge 4 commits into
guacsec:mainfrom
CryptoRodeo:TC-4624
Draft

feat(advisory): implement CSAF Source tab with raw JSON and advisory link#1065
CryptoRodeo wants to merge 4 commits into
guacsec:mainfrom
CryptoRodeo:TC-4624

Conversation

@CryptoRodeo
Copy link
Copy Markdown
Collaborator

@CryptoRodeo CryptoRodeo commented May 28, 2026

Summary

  • Add CsafSource component displaying full CSAF JSON in PatternFly CodeBlock with copy-to-clipboard
  • Extract "self" reference URL from CSAF document references and display as external link
  • Gracefully omit link when no "self" reference exists
  • Wire Source tab in csaf-advisory-details.tsx to render real component instead of placeholder

Test plan

  • Build succeeds (npm run build -w client)
  • All 24 unit tests pass
  • Biome/lint passes
  • Source tab renders formatted JSON with copy button
  • Self-reference link renders when present, omitted when absent

Implements TC-4624

Assisted-by: Claude Code

Summary by Sourcery

Add a CSAF-specific advisory details view with a dedicated tabbed layout and a Source tab for viewing raw CSAF documents.

New Features:

  • Introduce a CSAF advisory details page that switches in when viewing CSAF-type advisories, with a 5-tab layout for future visualization features.
  • Add a CSAF Source tab that displays the full CSAF JSON document and, when available, links to the original advisory URL extracted from CSAF references.
  • Provide a React Query hook to download and parse the raw CSAF JSON into strongly typed CSAF document structures.

Enhancements:

  • Define TypeScript types for CSAF 2.0 VEX documents to enable typed handling of CSAF advisory data.

Build:

  • Add echarts and echarts-for-react dependencies in preparation for future CSAF visualizations.

Define TypeScript interfaces for the full CSAF 2.0 VEX document
structure (CsafDocument, CsafVulnerability, CsafProductTree, etc.)
and add useFetchAdvisoryCsafById query hook that fetches raw CSAF JSON
via the downloadAdvisory endpoint and parses the Blob into typed data.

Also add echarts and echarts-for-react dependencies for upcoming
tree visualization components.

Implements TC-4618

Assisted-by: Claude Code
When advisory labels.type === "csaf", render a CSAF-specific 5-tab
layout (Overview, Vulnerabilities, Product Tree, Relationship Tree,
Source) instead of the default 2-tab Info/Vulnerabilities view.

The CsafAdvisoryDetails component fetches the parsed CSAF document
via useFetchAdvisoryCsafById and provides placeholder content for
each tab that subsequent tasks will replace with real implementations.

Implements TC-4619

Assisted-by: Claude Code
…link

Add CsafSource component that displays the full CSAF JSON document
in a PatternFly CodeBlock with copy-to-clipboard, and extracts the
"self" reference URL to provide a link to the original advisory.

Wire the Source tab in csaf-advisory-details.tsx to render CsafSource
instead of the placeholder EmptyState.

Implements TC-4624

Assisted-by: Claude Code
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented May 28, 2026

Reviewer's Guide

Implements a CSAF-specific advisory details view with a new Source tab that renders the raw CSAF JSON and an optional external advisory link, switching the advisory details layout to this CSAF view when the advisory type is CSAF and adding a typed CSAF model plus a dedicated React Query hook to fetch and parse the CSAF document.

Sequence diagram for CSAF advisory Source tab rendering

sequenceDiagram
  actor User
  participant AdvisoryDetails
  participant CsafAdvisoryDetails
  participant useFetchAdvisoryCsafById
  participant downloadAdvisory
  participant CsafSource

  User->>AdvisoryDetails: open CSAF advisory
  AdvisoryDetails->>AdvisoryDetails: check advisory.labels.type
  AdvisoryDetails-->>CsafAdvisoryDetails: render CsafAdvisoryDetails(advisoryId)

  CsafAdvisoryDetails->>useFetchAdvisoryCsafById: useFetchAdvisoryCsafById(advisoryId)
  useFetchAdvisoryCsafById->>downloadAdvisory: downloadAdvisory({ client, path: { key: id } })
  downloadAdvisory-->>useFetchAdvisoryCsafById: Blob response
  useFetchAdvisoryCsafById->>useFetchAdvisoryCsafById: blob.text() and JSON.parse
  useFetchAdvisoryCsafById-->>CsafAdvisoryDetails: csafDocument

  CsafAdvisoryDetails->>CsafSource: render CsafSource(csafDocument)
  alt [csafDocument.document.references has category self]
    CsafSource->>CsafSource: find selfRef
    CsafSource-->>User: render advisory link (Button href=selfRef.url)
  else [no self reference]
    CsafSource-->>User: omit advisory link
  end
  CsafSource-->>User: render JSON in CodeBlockCode(JSON.stringify(csafDocument, null, 2))
Loading

File-Level Changes

Change Details Files
Introduce CSAF-specific advisory details view with tabbed layout and conditional routing from the generic advisory details page.
  • Add CsafAdvisoryDetails component that defines a 5-tab PatternFly layout (Overview, Vulnerabilities, Product Tree, Relationship Tree, Source) backed by useTabControls and loaded within a LoadingWrapper.
  • Wire AdvisoryDetails to detect CSAF advisories via a label check and render CsafAdvisoryDetails instead of the existing Info/Vulnerabilities tabs for those advisories.
  • Adjust imports in AdvisoryDetails to include CsafAdvisoryDetails and keep DocumentMetadata import ordering consistent.
client/src/app/pages/advisory-details/advisory-details.tsx
client/src/app/pages/advisory-details/csaf-advisory-details.tsx
Add a CSAF Source tab component that shows the raw CSAF JSON and an optional external link to the original advisory.
  • Implement CsafSource component that locates the CSAF document's 'self' reference and, when present, renders it as an external PatternFly link button with icon; omit the section entirely when absent.
  • Render the full CSAF document in a PatternFly CodeBlock/CodeBlockCode using pretty-printed JSON for readability.
  • Integrate CsafSource as the content of the Source tab in CsafAdvisoryDetails, passing the fetched CsafDocument.
client/src/app/pages/advisory-details/csaf-advisory-details.tsx
client/src/app/pages/advisory-details/csaf-source.tsx
Provide a typed CSAF model and a dedicated React Query hook to fetch and parse CSAF advisory documents.
  • Add a comprehensive TypeScript type hierarchy for CSAF 2.0 VEX documents (document metadata, product tree, vulnerabilities, scores, remediations, etc.).
  • Introduce useFetchAdvisoryCsafById hook that uses downloadAdvisory, reads the response Blob as text, parses it as JSON into a CsafDocument, and exposes it as csafDocument along with isFetching and fetchError.
  • Use the new hook within CsafAdvisoryDetails to drive loading/error states and provide the typed document to the Source tab.
client/src/app/types/csaf.ts
client/src/app/queries/advisories.ts
client/src/app/pages/advisory-details/csaf-advisory-details.tsx
Update client dependencies to support future visualization work (charts) in CSAF views.
  • Add echarts and echarts-for-react to client/package.json dependencies to enable future graphical visualization of CSAF data.
  • Propagate the new dependencies into package-lock.json.
client/package.json
package-lock.json

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@CryptoRodeo CryptoRodeo marked this pull request as draft May 28, 2026 18:14
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • In CsafAdvisoryDetails, the tab content refs are created with React.createRef() inside the component body, which creates new ref instances on every render; consider switching these to useRef so the refs remain stable across renders.
  • The new dependencies echarts and echarts-for-react are added to client/package.json but are not used anywhere in this diff; if they aren't needed yet, it would be better to add them in the PR where they are first used to avoid unused dependencies.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `CsafAdvisoryDetails`, the tab content refs are created with `React.createRef()` inside the component body, which creates new ref instances on every render; consider switching these to `useRef` so the refs remain stable across renders.
- The new dependencies `echarts` and `echarts-for-react` are added to `client/package.json` but are not used anywhere in this diff; if they aren't needed yet, it would be better to add them in the PR where they are first used to avoid unused dependencies.

## Individual Comments

### Comment 1
<location path="client/src/app/pages/advisory-details/csaf-advisory-details.tsx" line_range="58-62" />
<code_context>
+    ],
+  });
+
+  const overviewTabRef = React.createRef<HTMLElement>();
+  const vulnerabilitiesTabRef = React.createRef<HTMLElement>();
+  const productTreeTabRef = React.createRef<HTMLElement>();
+  const relationshipTreeTabRef = React.createRef<HTMLElement>();
+  const sourceTabRef = React.createRef<HTMLElement>();
+
+  return (
</code_context>
<issue_to_address>
**issue:** Use `useRef` instead of `React.createRef` for tab content refs to avoid creating new ref objects on every render.

Because this is a function component, these `createRef` calls produce new ref objects on every render, which can interfere with `Tabs`/`TabContent` focus or scroll behavior and undermines refs’ stability. Using `useRef<HTMLElement | null>(null)` for each tab will keep the ref objects stable across renders and match standard function-component patterns.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread client/src/app/pages/advisory-details/csaf-advisory-details.tsx
@codecov
Copy link
Copy Markdown

codecov Bot commented May 28, 2026

Codecov Report

❌ Patch coverage is 0% with 35 lines in your changes missing coverage. Please review.
✅ Project coverage is 48.86%. Comparing base (def496d) to head (e1ac462).

Files with missing lines Patch % Lines
...p/pages/advisory-details/csaf-advisory-details.tsx 0.00% 13 Missing ⚠️
...ent/src/app/pages/advisory-details/csaf-source.tsx 0.00% 9 Missing ⚠️
client/src/app/queries/advisories.ts 0.00% 8 Missing ⚠️
...rc/app/pages/advisory-details/advisory-details.tsx 0.00% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1065      +/-   ##
==========================================
- Coverage   49.17%   48.86%   -0.32%     
==========================================
  Files         253      255       +2     
  Lines        5499     5532      +33     
  Branches     1660     1666       +6     
==========================================
- Hits         2704     2703       -1     
- Misses       2519     2554      +35     
+ Partials      276      275       -1     
Flag Coverage Δ
unit 2.00% <0.00%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Wrap JSON.stringify(csafDocument, null, 2) in React.useMemo to avoid
re-serializing potentially large CSAF documents on every render.

Implements TC-4624

Assisted-by: Claude Code
@CryptoRodeo
Copy link
Copy Markdown
Collaborator Author

Verification Report for TC-4624 (commit e1ac462)

Check Result Details
Review Feedback PASS 1 suggestion (all non-blocking)
Root-Cause Investigation N/A No sub-tasks created
Scope Containment PASS All files in scope per task description
Diff Size PASS Appropriate for task scope
Commit Traceability PASS Conventional Commits format
Sensitive Patterns PASS No secrets detected
CI Status PASS Build succeeds
Acceptance Criteria PASS 5/5 criteria met
Test Quality N/A No test files in scope
Test Change Classification N/A No test files modified
Verification Commands PASS Build succeeds, 24/24 tests pass

Overall: PASS


This comment was AI-generated by sdlc-workflow/verify-pr v0.9.1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant