Skip to content

Conversation

@kahboom
Copy link
Collaborator

@kahboom kahboom commented Nov 10, 2025

Hey @stanislavsemeniuk , I'm leaving this as a draft PR until we have something usable. These are just dummy components most of them copy & pasted straight from PatternFly to demonstrate the idea. We need to update the code to use the API data, where possible. If we don't expect the data anytime soon we can remove it for now.

Screenshot 2025-11-10 at 3 17 30 PM Screenshot 2025-11-10 at 3 17 43 PM

We have an OpenAPI spec that gets updated when the relevant part of the API gets updated, and it's located here: https://github.com/securesign/rhtas-console-ui/blob/main/client/openapi/console.yaml

We have a manually-defined SDK file that refers to that spec for queries, it gets created locally at client/src/app/client/sdk.gen.ts.

Summary by Sourcery

Add a verification interface to the artifact details page, showcasing metadata summary cards and an interactive list of signatures with expandable details.

New Features:

  • Display artifact metadata in a PatternFly MultiContentCard with digest, media type, size, creation date, labels, identities, and verification counts
  • Render a compact DataList of signature entries with expandable details including code block views of signature data, a certificate chain TreeView, attestations panel, and Rekor entry display
  • Provide interactive controls such as clipboard copy buttons, popover term help, and dropdown actions for each signature entry

Enhancements:

  • Refactor ArtifactResults layout to leverage PatternFly components (CardHeader, DataList, Popover, TreeView, etc.)
  • Correct sidebar link label from 'Trust root' to 'Trust Root'

Chores:

  • Initialize artifactUri state with a default image in the Artifacts page for immediate preview

@sourcery-ai
Copy link

sourcery-ai bot commented Nov 10, 2025

Reviewer's Guide

This PR drafts the artifact verification UI by overhauling the ArtifactResults component: it replaces simple layout with PatternFly MultiContentCard for summary, DataList for signature listings, expandable CodeBlock and TreeView for certificate chains, and clipboard interactions, while also adjusting the sidebar link text and setting a default artifact URI.

Class diagram for updated ArtifactResults component

classDiagram
    class ArtifactResults {
      +artifact: ImageMetadataResponse
      +activeItems: TreeViewDataItem[]
      +sigDropdownOpen: Record<string, boolean>
      +expanded: string[]
      +copied: boolean
      +summaryCards: Card[]
      +options: TreeViewDataItem[]
      +clipboardCopyFunc(text)
      +onClick(text)
      +onSelectCertChain(event, treeViewItem)
      +setSigDropdownState(id, isOpen)
      +handleOpenSigDropdown(id)
      +handleToggleClick(id)
      +handleSelect(id)
      +toggle(id)
      +codeBlockActions
      +render()
    }
    ArtifactResults --> ImageMetadataResponse
    ArtifactResults --> TreeViewDataItem
    ArtifactResults --> Card
Loading

Class diagram for updated Artifacts page state

classDiagram
    class Artifacts {
      -artifactUri: string | null = "docker.io/library/nginx:latest"
      -labelHelpRef
    }
Loading

Class diagram for updated SidebarApp navigation

classDiagram
    class SidebarApp {
      +render()
      "Trust Root" link text updated
    }
Loading

File-Level Changes

Change Details Files
Refactor ArtifactResults to verification UI
  • Introduce state hooks for expanded items, dropdowns, and clipboard
  • Replace header layout with CardHeader + Flex + Button
  • Assemble summary cards in MultiContentCard using DescriptionList and Popovers
  • Swap digest/media-type panels for DataList with DataListItem, CodeBlock, TreeView
  • Remove old SyntaxHighlighter and Grid-based layout
  • Import new PatternFly components (DataList, CodeBlock, TreeView, ClipboardCopy, etc.)
ArtifactResults.tsx
Correct sidebar link text
  • Change 'Trust root' to 'Trust Root'
sidebar.tsx
Set default artifact URI
  • Initialize artifactUri state with sample image instead of null
Artifacts.tsx

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

kahboom and others added 8 commits November 17, 2025 23:48
feat(artifacts): update mock and query

feat(artifact): add form control and field validation

fix: re-add hook state

fix(ci): type issues with react-syntax-highlighter

enhancement(artifact): improve search results

enhancement(artifact): add metadata accordion

fix: use paths constant for route

fix: lazy load artifacts

chore: remove accordion, use content for titles

fix: add type for artifact uri

fix: fallback for uri type assertion

chore: remove gcTime setting

fix: remove unnecessary query dependency
fix: reusable handlers

fix: lint

fix: rm dummy artifact uri
feat(artifacts): add verification hook

feat(artifacts): add attestations tab
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

fix(branding): update favicon

fix(branding): update favicon

chore(artifacts): add attestation component, update hook

chore: add mutation hook and mock data

add attestation results
@kahboom kahboom force-pushed the artifact-verification branch from 3496e5e to 8864666 Compare November 17, 2025 23:49
Copy link
Contributor

@carlosthe19916 carlosthe19916 left a comment

Choose a reason for hiding this comment

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

@kahboom thanks for the PR.
I have reviewed this PR just in general terms. And added a couple of comments.

I was not able to make it work due to an error. But we can iterate it title by title

{
    "details": {
        "error": "error getting simple signing layer: error getting signature manifest: GET https://index.docker.io/v2/library/nginx/manifests/sha256-553f64aecdc31b5bf944521731cd70e35da4faed96b2b7548a3d8e2598c52a42.sig: MANIFEST_UNKNOWN: manifest unknown; unknown tag=sha256-553f64aecdc31b5bf944521731cd70e35da4faed96b2b7548a3d8e2598c52a42.sig"
    },
    "verified": false
}
Image

},
});
};

Copy link
Contributor

Choose a reason for hiding this comment

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

Generally speaking Mutations involve create/update/delete data performing server side-effects. Therefore I think there is no need to mock mutations.

The useMockableQuery was originally designed as a way or providing data so we can demo things without the need to wait for backend features and we can work in parallel.

I am inclined to mock things for read only purposes and don't mock things for create/update/delete; we will eventually make our code more complex without having too much gain in return.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good point about mocking things for CRUD. I was thinking more about having it still work with static pages but this could be the point of diminishing returns.

// - TData: ArtifactVerificationViewModel → what the UI consumes
// - TError: AxiosError<_Error> → error shape from the SDK
// - TVariables: IVerifyArtifactVariables → what the caller passes in (uri, expectedSAN, etc.)
return useMockableMutation<ArtifactVerificationViewModel, AxiosError<_Error>, IVerifyArtifactVariables>(
Copy link
Contributor

@carlosthe19916 carlosthe19916 Nov 19, 2025

Choose a reason for hiding this comment

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

I am not sure we we should use Mutations here. As mentioned in other comments here Mutations are for Create/Update/Delete of data. Seems to me that although we are using a POST HTTP request, the operation is a READ operation.

Generally speaking we should use:

  • useQuery: for READ operations. Those operations are idempotent. Usually used on GET HTTP requests. However, POST requests can also serve READ operations so we can use POST here too.
  • useMutation: for CREATE/UPDATE/DELETE data in the backend. Usually done by POST, PUT, DELETE. this is not an idempotent operation because we are changing data in the server side.

I might be wrong but I think we are doing a READ operation and we could use useQuery then combine it with POST, what do you think?

Note: I might be wrong in regards of this being only a READ operation though

return (
<div style={{ margin: "2em auto" }}>
<p>Showing 1 of 1</p>
<Card style={{ margin: "1.5em auto 2em", overflowY: "hidden" }}>
Copy link
Contributor

Choose a reason for hiding this comment

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

In multiple lines we are using style and Content H4. I would advocate for using the defaults as much as possible. So leave the default sizes of all components and only change the defaults by strict request of UX. It will help us maintain visual consistency with all pages in the long term

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

sure thing!

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.

4 participants