feat: add export feature using v2 endpoint for instance reports#685
feat: add export feature using v2 endpoint for instance reports#685marqode wants to merge 47 commits into
Conversation
Replace the client-side aggregation of four V1 endpoints with a single useGetComplianceReport call against GET computers/report, and redesign the side panel to match the Figma: a status bar table, a time-to-patch donut with a legend table, and clickable counts that deep-link to the filtered instances list. "60+ days outstanding" is now the headline USN debt metric (previously mislabelled "60 days"). - Snapshot the selection when the panel opens; warn and offer to regenerate when the live selection changes. - Wire the CSV download form's "Report by CVE" and range controls to the request and fetch on submit; note what the legacy CSV contains. - Gate the "View report" action behind the instance-reports feature flag from the features/ endpoint, removing the VITE_REPORT_VIEW_ENABLED build-time env var.
There was a problem hiding this comment.
Pull request overview
This PR introduces an asynchronous TSV export workflow for instance compliance reports using the v2 API, aligning report exports with the existing export-job pattern (instances/activities) and adding an Exports area in the dashboard for monitoring/downloading jobs.
Changes:
- Replaces the report panel’s synchronous CSV download flow with an async TSV export job (
computers/report:export) and adds shared download helpers. - Adds a new Exports page + routing/nav entry, plus MSW handlers and fixtures for export-job list/detail/retry/cancel/discard/download.
- Refactors instance/activity selection and export forms to support “select all” semantics and export scoping.
Reviewed changes
Copilot reviewed 171 out of 174 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/vite-env.d.ts | Removes deprecated report-view env flag type. |
| src/utils/browserDownload.ts | Adds shared blob-download + native save-picker detection helpers. |
| src/types/FeatureKey.ts | Adds instance-reports feature key. |
| src/tests/server/handlers/reports.ts | Adds v2 compliance report MSW handler + fixtures; keeps legacy CSV handler branch. |
| src/tests/server/handlers/instance.ts | Adds MSW handlers for instance exports + report export job creation; adjusts computers/:id handler matching. |
| src/tests/server/handlers/index.ts | Registers new exports handlers. |
| src/tests/server/handlers/features.ts | Forces instance-reports enabled under MSW even for “empty” feature responses. |
| src/tests/server/handlers/exports.ts | Adds MSW CRUD + download endpoints for export jobs. |
| src/tests/server/handlers/activity.ts | Adds MSW handler for activity export job creation. |
| src/tests/mocks/features.ts | Adds mock Feature entry for Instance Reports. |
| src/tests/mocks/exports.ts | Adds export-job fixtures used by MSW and tests. |
| src/templates/dashboard/UserInfo/UserInfo.tsx | Adds “Exports” navigation link. |
| src/routes/elements.tsx | Adds lazy-loaded ExportsPage. |
| src/routes/DashboardRoutes.tsx | Registers /exports dashboard route. |
| src/pages/dashboard/instances/ReportWidget/ReportWidget.tsx | Removes legacy report widget component. |
| src/pages/dashboard/instances/ReportWidget/ReportWidget.test.tsx | Removes tests for deleted widget. |
| src/pages/dashboard/instances/ReportWidget/ReportWidget.module.scss | Removes styles for deleted widget. |
| src/pages/dashboard/instances/ReportWidget/index.ts | Removes barrel export for deleted widget. |
| src/pages/dashboard/instances/ReportView/ReportView.tsx | Removes legacy report view implementation. |
| src/pages/dashboard/instances/ReportView/ReportView.test.tsx | Removes tests for deleted legacy report view. |
| src/pages/dashboard/instances/ReportView/ReportView.module.scss | Removes styles for deleted legacy report view. |
| src/pages/dashboard/instances/ReportForm/ReportForm.tsx | Removes legacy CSV form. |
| src/pages/dashboard/instances/ReportForm/ReportForm.test.tsx | Removes tests for deleted legacy CSV form. |
| src/pages/dashboard/instances/ReportForm/ReportForm.module.scss | Removes styles for deleted legacy form. |
| src/pages/dashboard/instances/ReportForm/index.ts | Removes barrel export for deleted legacy form. |
| src/pages/dashboard/instances/InstancesPage/InstancesPage.tsx | Adds selection-reset-on-query-change and mirrors selection to an external store (but currently missing required new props wiring). |
| src/pages/dashboard/instances/InstancesPage/helpers.ts | Re-exports instance query/list-param helpers from the feature. |
| src/pages/dashboard/instances/InstancesPage/helpers.test.ts | Adds coverage for list-param building and filter preservation. |
| src/pages/dashboard/instances/InstancesContainer/InstancesContainer.tsx | Adds required “select all / clear selection” props and passes them to InstanceList. |
| src/pages/dashboard/instances/InstancesContainer/InstancesContainer.test.tsx | Updates tests for new required props. |
| src/pages/dashboard/instances/[single]/tabs/activities/ActivityPanel/ActivityPanel.tsx | Adds all-selected selection mode wiring for activities panel export. |
| src/pages/dashboard/events-log/helpers.ts | Switches CSV download to shared downloadBlob. |
| src/pages/dashboard/activities/ActivitiesPage.tsx | Refactors to use ActivitiesContainer and adds all-selected state + export action support. |
| src/pages/dashboard/account/exports/index.ts | Adds Exports page entrypoint. |
| src/pages/dashboard/account/exports/ExportsPage.tsx | Implements Exports list page + side panel for details. |
| src/pages/dashboard/account/exports/ExportsPage.test.tsx | Adds Exports page tests for empty/loading/data states. |
| src/libs/routes/routes.ts | Adds exports route group. |
| src/libs/routes/paths.ts | Adds exports path group. |
| src/libs/routes/exports.ts | Defines exports route/path helpers. |
| src/hooks/useReports.ts | Removes most legacy report queries; now only exposes CSV compliance data (appears unused). |
| src/features/usg-profiles/hooks/useUsgProfileDownloadAudit.tsx | Uses shared downloadBlob helper. |
| src/features/usg-profiles/hooks/useUsgProfileDownload.tsx | Uses shared downloadBlob helper. |
| src/features/scripts/components/AttachmentFile/AttachmentFile.tsx | Uses shared downloadBlob helper. |
| src/features/saved-searches/components/SavedSearchForm/helpers/searchQueryValidation.ts | Adds validation support for new query keys/tokens (has, ping/usn numeric keys). |
| src/features/saved-searches/components/SavedSearchForm/helpers/searchQueryLanguage.ts | Adds Monaco suggestions for has:upgrade-profile. |
| src/features/saved-searches/components/SavedSearchForm/constants.ts | Adds new valid/numeric root keys. |
| src/features/reports/types.ts | Adds v2 compliance report types. |
| src/features/reports/index.ts | Exposes reports API + components. |
| src/features/reports/components/ReportView/ReportView.module.scss | Adds styles for new report view layout. |
| src/features/reports/components/ReportView/index.ts | Adds barrel export for new report view. |
| src/features/reports/components/ReportLegendTable/ReportLegendTable.tsx | Adds reusable legend table component for report visualizations. |
| src/features/reports/components/ReportLegendTable/ReportLegendTable.test.tsx | Adds tests for legend table behavior and accessibility labels. |
| src/features/reports/components/ReportLegendTable/ReportLegendTable.module.scss | Adds scoped table styling for legend table. |
| src/features/reports/components/ReportLegendTable/index.ts | Adds barrel export for legend table + types. |
| src/features/reports/components/ReportExportForm/ReportExportForm.tsx | Adds compliance-specific wrapper around shared ExportForm and queues report TSV export jobs. |
| src/features/reports/components/ReportExportForm/index.ts | Adds barrel export(s) for report export form. |
| src/features/reports/components/ReportExportForm/constants.ts | Defines bucket options and initial export values for report exports. |
| src/features/reports/components/ReportDonutChart/ReportDonutChart.tsx | Adds donut chart visualization + coordinated legend interactions. |
| src/features/reports/components/ReportDonutChart/ReportDonutChart.test.tsx | Adds tests for donut rendering, hover coordination, and ARIA description. |
| src/features/reports/components/ReportDonutChart/ReportDonutChart.module.scss | Adds chart styling and palette mapping to Vanilla tokens. |
| src/features/reports/components/ReportDonutChart/index.ts | Adds barrel export for donut chart + types. |
| src/features/reports/components/MetricBarTable/MetricBarTable.tsx | Adds bar-table metric visualization built on legend table. |
| src/features/reports/components/MetricBarTable/MetricBarTable.test.tsx | Adds tests for metric bar sizing, color classes, and link behavior. |
| src/features/reports/components/MetricBarTable/MetricBarTable.module.scss | Adds bar-table styling using Vanilla tokens. |
| src/features/reports/components/MetricBarTable/index.ts | Adds barrel export for metric bar table + types. |
| src/features/reports/api/useGetComplianceReport.ts | Adds v2 compliance report query hook. |
| src/features/reports/api/useExportComplianceTsv.ts | Adds mutation hook to create compliance report export jobs. |
| src/features/reports/api/index.ts | Exposes reports hooks. |
| src/features/instances/types/InstancesExportJob.ts | Defines export-job subtype for instance exports. |
| src/features/instances/types/index.ts | Exposes InstancesExportJob type. |
| src/features/instances/selectedInstancesStore.ts | Adds external store for selected instance IDs (used by report side panel). |
| src/features/instances/index.ts | Exposes export field groups, query helpers, and selection store functions. |
| src/features/instances/helpers.ts | Moves instances query/list-param helpers into the feature module for reuse. |
| src/features/instances/components/InstancesPageActions/helpers.ts | Replaces old notification helper with export-title helper for TSV export. |
| src/features/instances/components/InstancesHeader/InstancesHeader.tsx | Wraps column filter in a flex container for new header layout. |
| src/features/instances/components/InstancesHeader/InstancesHeader.test.tsx | Fixes test setup to create user per test instead of in describe. |
| src/features/instances/components/InstancesHeader/InstancesHeader.module.scss | Adds header actions layout styling. |
| src/features/instances/components/InstancesHeader/hooks/useInstanceSearchHelpTerms.tsx | Adds new search help terms for new query tokens. |
| src/features/instances/components/InstancesExportForm/InstancesExportForm.tsx | Adds Instances export form using shared ExportForm + v2 export job endpoint. |
| src/features/instances/components/InstancesExportForm/index.ts | Adds barrel export for instances export form. |
| src/features/instances/components/InstancesExportForm/helpers.ts | Derives initial selected export fields from visible table columns. |
| src/features/instances/components/InstancesExportForm/helpers.test.ts | Adds coverage for initial export-field selection logic. |
| src/features/instances/components/InstancesExportForm/constants.ts | Defines instance export field groups and default form values. |
| src/features/instances/components/InstanceList/InstanceList.tsx | Adds all-selected mode, subhead for cross-page selection, and last-ping accessor rename. |
| src/features/instances/components/InstanceList/InstanceList.test.tsx | Updates tests for new clear-selection callback and selection logic. |
| src/features/instances/components/InstanceList/helpers.tsx | Removes now-unused checkbox helpers; updates aria-label mapping for last ping. |
| src/features/instances/components/InstanceList/helpers.test.tsx | Removes tests for deleted checkbox helpers; updates last-ping id assertion. |
| src/features/instances/api/useExportInstancesTsv.ts | Adds mutation hook to create instance export jobs. |
| src/features/instances/api/index.ts | Exposes instance export mutation. |
| src/features/exports/types/ExportJob.ts | Adds export-job API type. |
| src/features/exports/types/ExportForm.ts | Adds shared export-form types (fields, groups, values). |
| src/features/exports/index.ts | Exposes exports components + helpers + types. |
| src/features/exports/helpers.ts | Adds export query/scope helpers and status/type label helpers. |
| src/features/exports/helpers.test.ts | Adds tests for export helpers. |
| src/features/exports/constants.ts | Adds polling interval and server-error threshold constants. |
| src/features/exports/components/SortableFieldList/SortableFieldList.module.scss | Adds sortable/reorder UI styling including overlay and FLIP animation helpers. |
| src/features/exports/components/SortableFieldList/index.ts | Adds barrel export for sortable list. |
| src/features/exports/components/SortableFieldList/hooks/useSyncSortableFields.ts | Syncs ordered fields state with props (skipping during drag). |
| src/features/exports/components/SortableFieldList/hooks/useSortableFieldRefs.ts | Maintains refs for stable drag handlers. |
| src/features/exports/components/SortableFieldList/hooks/useSortableFieldCleanup.ts | Cleans up rAF/timers on unmount. |
| src/features/exports/components/SortableFieldList/hooks/useRestoreFocusAfterMove.ts | Restores focus after reorder for keyboard accessibility. |
| src/features/exports/components/SortableFieldList/hooks/usePendingFieldScroll.ts | Scrolls moved field into view after animations. |
| src/features/exports/components/SortableFieldList/hooks/useFlipAnimation.ts | Implements FLIP animations for non-drag reorders. |
| src/features/exports/components/SortableFieldList/hooks/useDragOverlayPosition.ts | Positions drag overlay on mount. |
| src/features/exports/components/SortableFieldList/hooks/index.ts | Exports sortable list hooks. |
| src/features/exports/components/SortableFieldList/helpers.ts | Creates transparent drag image to suppress native drag ghost. |
| src/features/exports/components/SortableFieldList/constants.ts | Defines timing/constants and transparent gif data URI. |
| src/features/exports/components/ExportsListActions/index.ts | Adds barrel export for list actions. |
| src/features/exports/components/ExportsListActions/ExportsListActions.tsx | Adds per-job actions (download/retry/cancel/discard) with confirmation modals. |
| src/features/exports/components/ExportsListActions/ExportsListActions.test.tsx | Adds tests for actions visibility and modal behavior. |
| src/features/exports/components/ExportsList/types.ts | Defines table row wrapper type for export jobs. |
| src/features/exports/components/ExportsList/index.ts | Adds barrel export for exports list. |
| src/features/exports/components/ExportsList/helpers.ts | Adds status/type icon helpers for exports list. |
| src/features/exports/components/ExportsList/helpers.test.ts | Adds tests for exports list icon helpers. |
| src/features/exports/components/ExportsList/ExportsList.tsx | Implements exports list table with status/progress rendering and side-panel navigation. |
| src/features/exports/components/ExportsList/ExportsList.test.tsx | Adds tests for list rendering and empty state. |
| src/features/exports/components/ExportsContainer/index.ts | Adds barrel export for exports container. |
| src/features/exports/components/ExportsContainer/ExportsContainer.tsx | Implements exports container (empty state, search/type filter, pagination, polling). |
| src/features/exports/components/ExportsContainer/ExportsContainer.test.tsx | Adds container tests for empty/data/filter states. |
| src/features/exports/components/ExportsContainer/constants.ts | Defines export-type filter options. |
| src/features/exports/components/ExportProgressBar/index.ts | Adds barrel export for progress bar. |
| src/features/exports/components/ExportProgressBar/helpers.ts | Formats ETA labels for progress bar. |
| src/features/exports/components/ExportProgressBar/helpers.test.ts | Adds tests for ETA formatting helpers. |
| src/features/exports/components/ExportProgressBar/ExportProgressBar.tsx | Adds progress bar component with ARIA progressbar. |
| src/features/exports/components/ExportProgressBar/ExportProgressBar.test.tsx | Adds tests for progress bar rendering and clamping. |
| src/features/exports/components/ExportProgressBar/ExportProgressBar.module.scss | Adds progress bar styling (currently with a hard-coded fill color). |
| src/features/exports/components/ExportProgressBar/constants.ts | Defines progress/ETA constants. |
| src/features/exports/components/ExportForm/index.ts | Adds barrel export for export form. |
| src/features/exports/components/ExportForm/ExportForm.module.scss | Adds export form styling and accordion tweaks. |
| src/features/exports/components/ExportForm/constants.ts | Adds Yup validation schema for export form. |
| src/features/exports/components/ExportDetailsSidePanel/index.ts | Adds barrel export for details side panel. |
| src/features/exports/components/ExportDetailsSidePanel/helpers.tsx | Adds helper to render filter query snippet in details view. |
| src/features/exports/components/ExportDetailsSidePanel/helpers.test.tsx | Adds tests for filter rendering helper. |
| src/features/exports/components/ExportDetailsSidePanel/ExportDetailsSidePanel.tsx | Implements export-job details side panel with server-error vs not-found states. |
| src/features/exports/components/ExportDetailsSidePanel/ExportDetailsSidePanel.test.tsx | Adds comprehensive details-side-panel tests. |
| src/features/exports/api/useRetryExportJob.ts | Adds retry mutation with cache cleanup for discarded old job. |
| src/features/exports/api/useGetExportJob.ts | Adds job detail query with polling and list-cache synchronization. |
| src/features/exports/api/useGetAllExportJobsList.ts | Adds paginated list query with polling while jobs are processing. |
| src/features/exports/api/useDownloadExportJob.ts | Adds download mutation with native save picker + fallback download; invalidates job list after completion. |
| src/features/exports/api/useDiscardExportJob.ts | Adds discard mutation and list invalidation. |
| src/features/exports/api/useCancelExportJob.ts | Adds cancel mutation and list invalidation. |
| src/features/activities/types/ActivitiesExportJob.ts | Defines export-job subtype for activity exports. |
| src/features/activities/index.tsx | Exposes ActivitiesContainer. |
| src/features/activities/components/ActivitiesHeader/ActivitiesHeader.tsx | Passes export context into activities actions (including instance-scoped base query). |
| src/features/activities/components/ActivitiesExportForm/types.ts | Defines export params type for activities export form. |
| src/features/activities/components/ActivitiesExportForm/index.ts | Adds barrel export for activities export form. |
| src/features/activities/components/ActivitiesExportForm/constants.ts | Defines activity export field groups and defaults. |
| src/features/activities/components/ActivitiesExportForm/ActivitiesExportForm.tsx | Adds activities export form using shared ExportForm and v2 export job endpoint. |
| src/features/activities/components/ActivitiesExportForm/ActivitiesExportForm.test.tsx | Adds tests for activities export form flow and notifications. |
| src/features/activities/components/ActivitiesContainer/index.ts | Adds barrel export for activities container. |
| src/features/activities/components/ActivitiesContainer/ActivitiesContainer.tsx | Adds container to unify loading/empty/list wiring. |
| src/features/activities/components/ActivitiesActions/helpers.ts | Adds export-title helper for activities export. |
| src/features/activities/components/ActivitiesActions/ActivitiesActions.tsx | Adds export action that opens export form in side panel and builds export query from filters. |
| src/features/activities/components/Activities/Activities.tsx | Adds all-selected mode support, subhead “select all” row, and selection-clearing behavior. |
| src/features/activities/components/Activities/Activities.module.scss | Adds subhead styling for cross-page selection. |
| src/features/activities/api/useExportActivitiesTsv.ts | Adds activity export job creation mutation. |
| src/features/activities/api/index.ts | Exposes activity export mutation. |
| src/features/account-creation/api/useCreateStandaloneAccount.ts | Tightens mutation response type from unknown to void. |
| src/constants.ts | Removes deprecated REPORT_VIEW_ENABLED env-gate constant. |
| .gitignore | Ensures root /reports is ignored (not nested directories). |
| .env.production | Removes deprecated report-view env flag. |
| .env.local.example | Removes deprecated report-view env flag placeholder. |
| .changeset/ripe-planets-boil.md | Adds changeset entry for report TSV export feature. |
| .changeset/reports-side-panel.md | Adds changeset entry for report side panel redesign (currently mentions CSV). |
Comments suppressed due to low confidence (1)
src/features/instances/components/InstancesPageActions/InstancesPageActions.test.tsx:156
- This test renders
InstancesPageActionswith onlyisGettingInstancesandselectedInstances, but the component now requiresexportParams,instanceCount, andisAllSelected. This will fail TypeScript compilation.
Reuse the existing renderPageActions() helper (which supplies the full required props) for this case too.
| // Hide aggregate CVE columns when byCve=true — they are always empty in that | ||
| // mode because _build_cve_tsv emits one row per (instance, CVE) and never | ||
| // populates the resolved_cves/unresolved_cves metrics. | ||
| const CVE_AGGREGATE_IDS = new Set(["resolved_cves", "unresolved_cves"]); | ||
| const fieldGroups = useMemo( | ||
| () => | ||
| byCve | ||
| ? REPORT_EXPORT_FIELD_GROUPS.map((group) => ({ | ||
| ...group, | ||
| fields: group.fields.filter((f) => !CVE_AGGREGATE_IDS.has(f.id)), | ||
| })).filter((group) => group.fields.length > 0) | ||
| : REPORT_EXPORT_FIELD_GROUPS, | ||
| // eslint-disable-next-line react-hooks/exhaustive-deps | ||
| [byCve], | ||
| ); |
| const selectedFields = fieldGroups | ||
| .flatMap((group) => group.fields) | ||
| .filter((field) => values.selectedFieldIds.includes(field.id)); | ||
|
|
||
| if (step === 0) { | ||
| setOrderedFields(selectedFields); | ||
| setStep(1); | ||
| return; | ||
| } | ||
|
|
||
| const fieldsToExport = orderedFields.length | ||
| ? orderedFields | ||
| : selectedFields; | ||
|
|
||
| await onGenerate({ values, fieldsToExport }); |
| export const setSelectedInstanceIds = (ids: readonly number[]): void => { | ||
| // Copy and freeze so callers can't mutate the store's snapshot in place | ||
| // (which would change state without notifying useSyncExternalStore listeners). | ||
| // The readonly types make any such mutation a compile-time error. | ||
| selectedInstanceIds = Object.freeze([...ids]); | ||
| listeners.forEach((listener) => { | ||
| listener(); | ||
| }); | ||
| }; |
| // Hide aggregate CVE columns when byCve=true — they are always empty in that | ||
| // mode because _build_cve_tsv emits one row per (instance, CVE) and never | ||
| // populates the resolved_cves/unresolved_cves metrics. | ||
| const CVE_AGGREGATE_IDS = new Set(["resolved_cves", "unresolved_cves"]); | ||
| const fieldGroups = useMemo( | ||
| () => | ||
| byCve | ||
| ? REPORT_EXPORT_FIELD_GROUPS.map((group) => ({ | ||
| ...group, | ||
| fields: group.fields.filter((f) => !CVE_AGGREGATE_IDS.has(f.id)), | ||
| })).filter((group) => group.fields.length > 0) | ||
| : REPORT_EXPORT_FIELD_GROUPS, | ||
| // eslint-disable-next-line react-hooks/exhaustive-deps | ||
| [byCve], | ||
| ); |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 178 out of 181 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
src/features/instances/helpers.test.ts:142
- This test case is duplicated verbatim (same title and assertions) immediately above, which adds noise and can make failures harder to interpret. Remove the duplicate block (lines 122–142).
| export interface InstancesExportJob extends ExportJob { | ||
| readonly type: "instance"; | ||
| } |
| export interface ActivitiesExportJob extends ExportJob { | ||
| readonly type: "activity"; | ||
| } |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 177 out of 180 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
src/features/instances/helpers.test.ts:142
- This file contains the exact same test case twice (same title and assertions). This adds noise and slows the suite without increasing coverage. Please remove one of the duplicated
it("builds list params that preserve archived and WSL filters", ...)blocks.
## Summary - resolves LNDENG-4707 and [this launchpad bug](https://bugs.launchpad.net/landscape/+bug/2158126) - adds TablePagination label prop for resources to show eg "Mirrors per page" instead of "Instances per page" everywhere ## Release Impact Pick the target branch (see [RELEASES.md](../RELEASES.md) for the full model): - [ ] `dev` — internal testing → publishes to `ppa-build-dev` - [X] `main` — next beta → publishes to `ppa-build` - [ ] `release/YY.MM` — point release on a maintained cycle → publishes to `ppa-build-YY.MM` (and to `ppa-build-stable` if this is the currently-promoted branch). Specify cycle: `release/____` Change type (tick one): - [X] Patch (fix) - [ ] Minor (feature) - [ ] Major (breaking) > The change-type label is informational and only affects how the entry is rendered in the CHANGELOG. The actual version is computed from the branch and CalVer cycle — `pnpm changeset`'s `patch`/`minor` choice does not influence it. ## Checklist - [X] **Changeset added** — I have run `pnpm changeset` (or `pnpm changeset --empty` if no CHANGELOG line is warranted) and committed the resulting `.md` file. Required for PRs targeting `main` and `release/*`; enforced by the `Changeset check` workflow. - [X] **UI verified** — I have verified the changes locally. - [X] **Linting clean** — No linting errors are present (especially in `scripts/`). ## Versioning Reminder > [!IMPORTANT] > Landscape UI uses **CalVer** (`YY.MM.Point.Build`). Version derivation by branch: > > - `main` / `point/*` → `YY.MM.0.<run>-beta` > - `dev` → `YY.MM.0.<run>-dev` > - `release/YY.MM` → `YY.MM.1.<run>` (cycle pinned by branch name) --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
## What Re-integrates the two LRO features that were developed on `point/26.04.2` back onto `main`, so `main` becomes the single integration trunk again (the release slice will be cut closer to the August release). - **LRO Mirrors** (#666) — previously reverted on `main` via #668 (deferred), restored here. - **LRO Publications** (#680). ## Why this is a rebuild, not a plain merge `point/26.04.2` branched at `150fa0a45` (the LRO Mirrors commit), *before* the revert. A plain `git merge` hit the revert trap (modify/deletes silently dropping the feature) plus collisions with `main`'s later work. This PR reconciles the features with everything `main` did since: - **MirrorDetails** keeps `main`'s segmented-control redesign (#682/#686), now **operation-aware** — disabled "Updating" state while an operation runs — plus the Status row and failed-update notification. (The feature's standalone `MirrorDetailsActionBlock` was dropped in favour of the redesigned control.) - **MirrorsList** combines the operation-status column with `main`'s pagination (#686). - **Operations** types/hooks adapted from **openapi 0.0.60 → 0.0.70** (#681): renamed error types, local `Operation` typing retained. - `main`'s release-process overhaul (#674) is kept; `point/26.04.2`'s superseded versioning infra is dropped. - `main`'s intentional removals (the `snaps`/`EditSnap` feature) are **not** reintroduced. ## Reviewers Tagging the authors of the `main` changes that this had to reconcile against: - @marqode — mirror pagination (#686) and mirror type (#682) - @gesquivelgaghi — openapi 0.0.70 bump (#681) ## Verification - `tsc --noEmit`: clean (incl. the openapi 0.0.70 adaptation) - ESLint: 0 errors · Prettier: clean - Vitest: full suite green in isolation; **+55 tests** restored from the LRO feature. (3 unrelated, pre-existing load-sensitive tests flake only under full-suite CPU contention — they pass in isolation.) - Completeness audit: every revert-dropped feature file restored; only the intentionally-dropped `MirrorDetailsActionBlock` is absent. Both feature changesets (`fuzzy-toes-hug`, `better-boats-eat`) are included for the CHANGELOG.
Summary
Replaces the synchronous "Download as CSV" button in the compliance report panel with an async TSV export job, consistent with the existing instances and activities export pattern. A new ReportExportForm component wraps the shared ExportForm and adds three compliance-specific controls — bucket selector, "Include Other" checkbox, and "Report by CVE" checkbox — with the bucket's pre-computed instance IDs used directly as the query param to POST /api/v2/computers/report:export.
The old ReportForm (which had a pre-existing downloadCSV import bug from a prior merge) is removed entirely and replaced by the new flow. Test coverage includes 7 new tests for ReportExportForm and an updated ReportView test correcting the stale button label assertion, alongside a new MSW handler and mock fixture for the export endpoint.
Release Impact
Pick the target branch (see RELEASES.md for the full model):
dev— internal testing → publishes toppa-build-devmain— next beta → publishes toppa-buildrelease/YY.MM— point release on a maintained cycle → publishes toppa-build-YY.MM(and toppa-build-stableif this is the currently-promoted branch). Specify cycle:release/____Change type (tick one):
Checklist
pnpm changeset(orpnpm changeset --emptyif no CHANGELOG line is warranted) and committed the resulting.mdfile. Required for PRs targetingmainandrelease/*; enforced by theChangeset checkworkflow.scripts/).Versioning Reminder
Important
Landscape UI uses CalVer (
YY.MM.Point.Build). Version derivation by branch:main/point/*→YY.MM.0.<run>-betadev→YY.MM.0.<run>-devrelease/YY.MM→YY.MM.1.<run>(cycle pinned by branch name)