From 64c1ff13f1f45be29688bfddd352b57cdf72c3ab Mon Sep 17 00:00:00 2001 From: Celia Amador Date: Wed, 9 Sep 2026 09:24:54 +0200 Subject: [PATCH 1/2] Update to latest API types Made-with: Cursor --- libs/types/alpha/models/Vulnerability.ts | 13 ++++++++++++- .../imagebuilder/models/ImageBuildSpec.ts | 5 ++++- libs/types/index.ts | 2 ++ libs/types/models/DeviceApplicationStatus.ts | 2 ++ libs/types/models/DeviceDeltaApplyStatus.ts | 18 ++++++++++++++++++ libs/types/models/DeviceLifecycleHookType.ts | 2 ++ libs/types/models/DeviceOsSpec.ts | 11 ++++++++++- libs/types/models/DeviceOsStatus.ts | 2 ++ libs/types/models/Event.ts | 2 ++ libs/types/models/EventDetails.ts | 3 ++- libs/types/models/OciRepoSpec.ts | 12 ++++++++++++ libs/types/models/PrepareDeltasDetails.ts | 18 ++++++++++++++++++ .../src/components/Events/useEvents.ts | 3 +++ 13 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 libs/types/models/DeviceDeltaApplyStatus.ts create mode 100644 libs/types/models/PrepareDeltasDetails.ts diff --git a/libs/types/alpha/models/Vulnerability.ts b/libs/types/alpha/models/Vulnerability.ts index 736cd5fa20..480fbbd0e6 100644 --- a/libs/types/alpha/models/Vulnerability.ts +++ b/libs/types/alpha/models/Vulnerability.ts @@ -4,7 +4,7 @@ /* eslint-disable */ import type { ApiVersion } from './ApiVersion'; /** - * A single vulnerability (CVE) finding. Vulnerabilities are global CVE records from Trustify; they are not tenant-owned resources. Tenancy is determined by the device or fleet context through which they are queried. + * A single vulnerability (CVE) finding. Vulnerabilities are global CVE records produced by the configured vulnerability scanner; they are not tenant-owned resources. Tenancy is determined by the device or fleet context through which they are queried. */ export type Vulnerability = { apiVersion: ApiVersion; @@ -44,6 +44,10 @@ export type Vulnerability = { * Advisory publish time when known. */ publishedAt?: string; + /** + * The vulnerability backend that produced this finding. + */ + source?: Vulnerability.source; /** * Image reference (name or URL) from the device context. */ @@ -69,5 +73,12 @@ export namespace Vulnerability { NONE = 'None', UNKNOWN = 'Unknown', } + /** + * The vulnerability backend that produced this finding. + */ + export enum source { + Trustify = 'trustify', + Quay = 'quay', + } } diff --git a/libs/types/imagebuilder/models/ImageBuildSpec.ts b/libs/types/imagebuilder/models/ImageBuildSpec.ts index 00faf0c0f4..e34d62ec2e 100644 --- a/libs/types/imagebuilder/models/ImageBuildSpec.ts +++ b/libs/types/imagebuilder/models/ImageBuildSpec.ts @@ -13,7 +13,10 @@ export type ImageBuildSpec = { source: ImageBuildSource; destination: ImageBuildDestination; binding: ImageBuildBinding; - onboarding?: boolean; userConfiguration?: ImageBuildUserConfiguration; + /** + * When true, installs the flightctl-onboarding RPM and enables flightctl-onboarding-setup.service for first-boot device configuration via a Cockpit-based onboarding wizard. Compatible with both early and late binding. Defaults to false. + */ + onboarding?: boolean; }; diff --git a/libs/types/index.ts b/libs/types/index.ts index 37264a0c9f..da0ecaf396 100644 --- a/libs/types/index.ts +++ b/libs/types/index.ts @@ -69,6 +69,7 @@ export type { DeviceConfigStatus } from './models/DeviceConfigStatus'; export type { DeviceConsole } from './models/DeviceConsole'; export type { DeviceDecommission } from './models/DeviceDecommission'; export { DeviceDecommissionTargetType } from './models/DeviceDecommissionTargetType'; +export type { DeviceDeltaApplyStatus } from './models/DeviceDeltaApplyStatus'; export type { DeviceIntegrityCheckStatus } from './models/DeviceIntegrityCheckStatus'; export { DeviceIntegrityCheckStatusType } from './models/DeviceIntegrityCheckStatusType'; export type { DeviceIntegrityStatus } from './models/DeviceIntegrityStatus'; @@ -182,6 +183,7 @@ export type { PatchRequest } from './models/PatchRequest'; export type { Percentage } from './models/Percentage'; export type { Permission } from './models/Permission'; export type { PermissionList } from './models/PermissionList'; +export type { PrepareDeltasDetails } from './models/PrepareDeltasDetails'; export type { QuadletApplication } from './models/QuadletApplication'; export type { ReferencedRepositoryUpdatedDetails } from './models/ReferencedRepositoryUpdatedDetails'; export type { RelativePath } from './models/RelativePath'; diff --git a/libs/types/models/DeviceApplicationStatus.ts b/libs/types/models/DeviceApplicationStatus.ts index c2b5f5ffbd..7b78df73e2 100644 --- a/libs/types/models/DeviceApplicationStatus.ts +++ b/libs/types/models/DeviceApplicationStatus.ts @@ -5,6 +5,7 @@ import type { ApplicationStatusType } from './ApplicationStatusType'; import type { ApplicationVolumeStatus } from './ApplicationVolumeStatus'; import type { AppType } from './AppType'; +import type { DeviceDeltaApplyStatus } from './DeviceDeltaApplyStatus'; export type DeviceApplicationStatus = { /** * Human readable name of the application. @@ -32,5 +33,6 @@ export type DeviceApplicationStatus = { * Status of volumes used by this application. */ volumes?: Array; + lastDelta?: DeviceDeltaApplyStatus; }; diff --git a/libs/types/models/DeviceDeltaApplyStatus.ts b/libs/types/models/DeviceDeltaApplyStatus.ts new file mode 100644 index 0000000000..235423cb35 --- /dev/null +++ b/libs/types/models/DeviceDeltaApplyStatus.ts @@ -0,0 +1,18 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +/** + * Result of the most recent delta apply attempt for this update target. + */ +export type DeviceDeltaApplyStatus = { + /** + * Set when the most recent update attempt fell back from a delta to a full image pull. Absent if no delta was attempted or the delta succeeded. Cleared when the next update attempt for this target starts. + */ + fallbackReason?: string; + /** + * Expected delta size in IEC units (KiB, MiB, GiB, or TiB). Absent when the size is not yet known. + */ + size?: string; +}; + diff --git a/libs/types/models/DeviceLifecycleHookType.ts b/libs/types/models/DeviceLifecycleHookType.ts index 0ac142c18f..a6578d3a65 100644 --- a/libs/types/models/DeviceLifecycleHookType.ts +++ b/libs/types/models/DeviceLifecycleHookType.ts @@ -7,4 +7,6 @@ export enum DeviceLifecycleHookType { DeviceLifecycleHookAfterUpdating = 'AfterUpdating', DeviceLifecycleHookBeforeRebooting = 'BeforeRebooting', DeviceLifecycleHookAfterRebooting = 'AfterRebooting', + DeviceLifecycleHookBeforeEnrolling = 'BeforeEnrolling', + DeviceLifecycleHookAfterEnrolling = 'AfterEnrolling', } diff --git a/libs/types/models/DeviceOsSpec.ts b/libs/types/models/DeviceOsSpec.ts index 03154a6335..4d3da1ace1 100644 --- a/libs/types/models/DeviceOsSpec.ts +++ b/libs/types/models/DeviceOsSpec.ts @@ -3,4 +3,13 @@ /* tslint:disable */ /* eslint-disable */ import type { ImageOrCatalogItemRefSpec } from './ImageOrCatalogItemRefSpec'; -export type DeviceOsSpec = ImageOrCatalogItemRefSpec; +/** + * Either a specific OCI image reference, or a reference to a catalog item version that can be resolved to an OCI image ref. + */ +export type DeviceOsSpec = (ImageOrCatalogItemRefSpec & { + /** + * Optional hint: a reference to a delta artifact the control plane's generation records indicate may be applicable to reach `image` from this device's current image. Absent does not imply no delta exists — the device independently discovers candidate delta artifacts (e.g. deltas published by a customer's own CI) regardless of this field, and falls back to a full pull only if none is usable. + */ + deltaImage?: string; +}); + diff --git a/libs/types/models/DeviceOsStatus.ts b/libs/types/models/DeviceOsStatus.ts index 1b1f744425..b65222aab5 100644 --- a/libs/types/models/DeviceOsStatus.ts +++ b/libs/types/models/DeviceOsStatus.ts @@ -2,6 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ +import type { DeviceDeltaApplyStatus } from './DeviceDeltaApplyStatus'; /** * Current status of the device OS. */ @@ -14,5 +15,6 @@ export type DeviceOsStatus = { * The digest of the OS image (e.g. sha256:a0...). */ imageDigest: string; + lastDelta?: DeviceDeltaApplyStatus; }; diff --git a/libs/types/models/Event.ts b/libs/types/models/Event.ts index 217c6322c6..d55842e4b4 100644 --- a/libs/types/models/Event.ts +++ b/libs/types/models/Event.ts @@ -108,6 +108,8 @@ export namespace Event { ENCRYPTION_MIGRATION_STARTED = 'EncryptionMigrationStarted', ENCRYPTION_MIGRATION_COMPLETED = 'EncryptionMigrationCompleted', APPLICATION_LIFECYCLE_CHANGED = 'ApplicationLifecycleChanged', + PREPARE_DELTAS = 'PrepareDeltas', + DELTA_GENERATION_COMPLETED = 'DeltaGenerationCompleted', } /** * The type of the event. One of Normal, Warning. diff --git a/libs/types/models/EventDetails.ts b/libs/types/models/EventDetails.ts index a59dd6b025..12f1b83491 100644 --- a/libs/types/models/EventDetails.ts +++ b/libs/types/models/EventDetails.ts @@ -17,11 +17,12 @@ import type { FleetRolloutFailedDetails } from './FleetRolloutFailedDetails'; import type { FleetRolloutStartedDetails } from './FleetRolloutStartedDetails'; import type { InternalTaskFailedDetails } from './InternalTaskFailedDetails'; import type { InternalTaskPermanentlyFailedDetails } from './InternalTaskPermanentlyFailedDetails'; +import type { PrepareDeltasDetails } from './PrepareDeltasDetails'; import type { ReferencedRepositoryUpdatedDetails } from './ReferencedRepositoryUpdatedDetails'; import type { ResourceSyncCompletedDetails } from './ResourceSyncCompletedDetails'; import type { ResourceUpdatedDetails } from './ResourceUpdatedDetails'; /** * Event-specific details, structured based on event type. */ -export type EventDetails = (ResourceUpdatedDetails | DeviceOwnershipChangedDetails | DeviceMultipleOwnersDetectedDetails | DeviceMultipleOwnersResolvedDetails | InternalTaskFailedDetails | InternalTaskPermanentlyFailedDetails | ResourceSyncCompletedDetails | ReferencedRepositoryUpdatedDetails | FleetRolloutStartedDetails | FleetRolloutFailedDetails | FleetRolloutCompletedDetails | FleetRolloutBatchDispatchedDetails | FleetRolloutBatchCompletedDetails | FleetRolloutDeviceSelectedDetails | DeviceVulnerabilityCveDetails | DependencyChangeDetectedDetails | DependencySyncProbeFailedDetails | ApplicationLifecycleChangedDetails); +export type EventDetails = (ResourceUpdatedDetails | DeviceOwnershipChangedDetails | DeviceMultipleOwnersDetectedDetails | DeviceMultipleOwnersResolvedDetails | InternalTaskFailedDetails | InternalTaskPermanentlyFailedDetails | ResourceSyncCompletedDetails | ReferencedRepositoryUpdatedDetails | FleetRolloutStartedDetails | FleetRolloutFailedDetails | FleetRolloutCompletedDetails | FleetRolloutBatchDispatchedDetails | FleetRolloutBatchCompletedDetails | FleetRolloutDeviceSelectedDetails | DeviceVulnerabilityCveDetails | DependencyChangeDetectedDetails | DependencySyncProbeFailedDetails | ApplicationLifecycleChangedDetails | PrepareDeltasDetails); diff --git a/libs/types/models/OciRepoSpec.ts b/libs/types/models/OciRepoSpec.ts index 346c0023f9..44e2083564 100644 --- a/libs/types/models/OciRepoSpec.ts +++ b/libs/types/models/OciRepoSpec.ts @@ -33,6 +33,18 @@ export type OciRepoSpec = { * Skip remote server verification. */ skipServerVerification?: boolean; + /** + * Optional OCI repository path under spec.registry (e.g. my-org/diffs). When set, this object is that repo (`my-registry.com/my-org/diffs`), not only a registry. Mutually exclusive with namespace. ImageBuild destination imageName must equal this value. + */ + repository?: string; + /** + * Optional org/subpath under spec.registry (e.g. my-org). Concrete names are spec.registry/namespace/. Mutually exclusive with repository. Used by delta push (`{registry}/{namespace}/{imageName}`). Invalid on an ImageBuild or ImageExport destination Repository. + */ + namespace?: string; + /** + * When true, generated deltas are pushed to this object (at most one per org). Auth is the existing ociAuth / accessMode. Placement follows repository / namespace / registry-only as above. + */ + deltaStorageTarget?: boolean; /** * Curated list of trusted base images available in this registry. When present, the Image Builder source picker surfaces these entries as selectable options. */ diff --git a/libs/types/models/PrepareDeltasDetails.ts b/libs/types/models/PrepareDeltasDetails.ts new file mode 100644 index 0000000000..2329ef2e94 --- /dev/null +++ b/libs/types/models/PrepareDeltasDetails.ts @@ -0,0 +1,18 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +/** + * Structured details for PrepareDeltas events. + */ +export type PrepareDeltasDetails = { + /** + * The type of detail for discriminator purposes. + */ + detailType: 'PrepareDeltas'; + /** + * Fleet only. The TemplateVersion this prepare is for. Required when involvedObject.kind is Fleet; omitted for Device. + */ + templateVersion?: string; +}; + diff --git a/libs/ui-components/src/components/Events/useEvents.ts b/libs/ui-components/src/components/Events/useEvents.ts index d42457f18d..117e3c115d 100644 --- a/libs/ui-components/src/components/Events/useEvents.ts +++ b/libs/ui-components/src/components/Events/useEvents.ts @@ -120,6 +120,9 @@ const getEventReasonTitles = (t: TFunction, kindType: string): Record Date: Wed, 9 Sep 2026 10:52:52 +0200 Subject: [PATCH 2/2] Display the Scanner name from the source Made-with: Cursor --- libs/i18n/locales/en/translation.json | 4 ++- .../VulnerabilityDetailsDrawer.tsx | 31 ++++++++++++++----- .../Status/VulnerabilitySeverityStatus.tsx | 2 +- .../src/utils/vulnerabilities.ts | 19 ++++++++++++ 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/libs/i18n/locales/en/translation.json b/libs/i18n/locales/en/translation.json index c5ecab72d3..13780d66a3 100644 --- a/libs/i18n/locales/en/translation.json +++ b/libs/i18n/locales/en/translation.json @@ -1089,6 +1089,8 @@ "Dependency sync probe failed": "Dependency sync probe failed", "Dependency change detected": "Dependency change detected", "Application lifecycle changed": "Application lifecycle changed", + "Preparing delta updates": "Preparing delta updates", + "Delta updates generation complete": "Delta updates generation complete", "Resource": "Resource", "Edit fleet": "Edit fleet", "Create fleet": "Create fleet", @@ -1850,8 +1852,8 @@ "Find by name": "Find by name", "Vulnerabilities table": "Vulnerabilities table", "Show more": "Show more", - "Published: {{ date }}": "Published: {{ date }}", "Scanner name": "Scanner name", + "Published: {{ date }}": "Published: {{ date }}", "<0>{deviceCount} devices in this fleet are running images affected by this vulnerability. Update or replace the affected images to remediate._one": "<0>{deviceCount} device in this fleet is running images affected by this vulnerability. Update or replace the affected images to remediate.", "<0>{deviceCount} devices in this fleet are running images affected by this vulnerability. Update or replace the affected images to remediate._other": "<0>{deviceCount} devices in this fleet are running images affected by this vulnerability. Update or replace the affected images to remediate.", "<0>{deviceCount} devices are running images affected by this vulnerability. Update or replace the affected images to remediate._one": "<0>{deviceCount} device is running an image affected by this vulnerability. Update or replace the affected image to remediate.", diff --git a/libs/ui-components/src/components/SecurityOverview/VulnerabilityDetailsDrawer.tsx b/libs/ui-components/src/components/SecurityOverview/VulnerabilityDetailsDrawer.tsx index b2e64a25b5..ddcd4a9a0f 100644 --- a/libs/ui-components/src/components/SecurityOverview/VulnerabilityDetailsDrawer.tsx +++ b/libs/ui-components/src/components/SecurityOverview/VulnerabilityDetailsDrawer.tsx @@ -1,6 +1,11 @@ import * as React from 'react'; -import { type Vulnerability, type VulnerabilityGroup, type VulnerabilityGroupItem } from '@flightctl/types/alpha'; -import { getPrimaryVulnerabilityGroupFinding, isRedHatIssuer, isVulnerabilityGroup } from '../../utils/vulnerabilities'; +import type { Vulnerability, VulnerabilityGroup, VulnerabilityGroupItem } from '@flightctl/types/alpha'; +import { + getPrimaryVulnerabilityGroupFinding, + getVulnerabilitySource, + isRedHatIssuer, + isVulnerabilityGroup, +} from '../../utils/vulnerabilities'; import { Content, @@ -21,6 +26,7 @@ import { import { VulnerabilitySeverityBadge, VulnerabilitySeverityDetails } from '../Status/VulnerabilitySeverityStatus'; import { getDateDisplay } from '../../utils/dates'; import { useTranslation } from '../../hooks/useTranslation'; +import { useAppContext } from '../../hooks/useAppContext'; import VulnerabilityImpact, { VulnerabilityImpactMessageSingleDevice } from './VulnerabilityImpact'; import VulnerabilityDescription from './VulnerabilityDescription'; @@ -34,6 +40,19 @@ type VulnerabilityDetailsDrawerProps = { onClose: VoidFunction; }; +const VulnerabilitySource = ({ vulnerability }: { vulnerability: Vulnerability }) => { + const { t } = useTranslation(); + const { settings } = useAppContext(); + + const source = getVulnerabilitySource(vulnerability, settings.isRHEM ?? false); + return ( + + {t('Scanner name')} + {source} + + ); +}; + const VulnerabilityDetailsDrawer = ({ vulnerability, isSingleDevice, @@ -86,7 +105,7 @@ const VulnerabilityDetailsDrawer = ({ )} - + {t('Severity')} @@ -97,10 +116,8 @@ const VulnerabilityDetailsDrawer = ({ )} - - {t('Scanner name')} - Trustify - + {/* API does not return the source for grouped vulnerabilities */} + {!isGrouped && } diff --git a/libs/ui-components/src/components/Status/VulnerabilitySeverityStatus.tsx b/libs/ui-components/src/components/Status/VulnerabilitySeverityStatus.tsx index 5f23ca1ce7..581f851c7c 100644 --- a/libs/ui-components/src/components/Status/VulnerabilitySeverityStatus.tsx +++ b/libs/ui-components/src/components/Status/VulnerabilitySeverityStatus.tsx @@ -63,7 +63,7 @@ export const VulnerabilitySeverityDetails = ({ severity, cvssScore }: Vulnerabil const { t } = useTranslation(); return ( - + diff --git a/libs/ui-components/src/utils/vulnerabilities.ts b/libs/ui-components/src/utils/vulnerabilities.ts index 6b527273a8..15ce628d97 100644 --- a/libs/ui-components/src/utils/vulnerabilities.ts +++ b/libs/ui-components/src/utils/vulnerabilities.ts @@ -51,6 +51,25 @@ export const getPrimaryVulnerabilityGroupFinding = ( return findingsWithLink.find((finding) => isRedHatIssuer(finding.issuer)) || findingsWithLink[0] || findings[0]; }; +const DEFAULT_VULNERABILITY_SOURCE_US = 'Trustify'; +const DEFAULT_VULNERABILITY_SOURCE_DS = 'Red Hat Trusted Profile Analyzer'; +const QUAY_VULNERABILITY_SOURCE = 'Quay'; + +export const getVulnerabilitySource = (vulnerability: Vulnerability, isRHEM: boolean) => { + switch (vulnerability.source) { + case Vulnerability.source.Trustify: + return isRHEM ? DEFAULT_VULNERABILITY_SOURCE_DS : DEFAULT_VULNERABILITY_SOURCE_US; + case Vulnerability.source.Quay: + return QUAY_VULNERABILITY_SOURCE; + case undefined: + // Source is missing, fallback to the default backend. + return DEFAULT_VULNERABILITY_SOURCE_US; + default: + // Source is unknown to the UI, return it as is. + return vulnerability.source; + } +}; + export const getSeverityCountValue = (severity: Severity, counts: CveCountsBySeverity) => { switch (severity) { case Vulnerability.severity.CRITICAL: