Skip to content

Software: fleet inventory page (All Software / Updates / Vulnerabilities) - #361

Open
pavlo-flamingo wants to merge 8 commits into
mainfrom
feat/software-inventory-page
Open

pavlo-flamingo wants to merge 8 commits into
mainfrom
feat/software-inventory-page

Conversation

@pavlo-flamingo

Copy link
Copy Markdown
Contributor

Implements the Figma All Software page (node 209-15626) on Relay, against the softwares(...) connection that just landed in the schema.

What's in

  • /software — one row per software title aggregated across the fleet: search, infinite scroll, server-side sort on DEVICES and VULNS, result count from filteredCount.
  • Cells as designed: name + publisher; current version (Unknown when null) with the OUTDATED chip and the +N older versions line; device count; severity tag with N CVEs, or plus no CPE match.
  • /software/updates and /software/vulnerabilities reuse the same table with a fixed scope (versionStatuses: [OUTDATED] / minSeverity: LOW), so the three-tab bar from the design is real navigation.
  • Sidebar entry between Monitoring and Logs; every URL goes through routes.software.*.
  • schema.graphql re-fetched from test-3043 for the Software* types (the rest of the diff there is the backend reordering Mutation fields).

Assumptions worth a look

  • Sort fields devicesCount and severity are a guess — the schema documents no sortable fields for softwares(sort:), and the resolver isn't live yet, so I couldn't verify. A value outside that pair is clamped away in the URL, so a stale link falls back to the backend order instead of erroring.
  • Updates / Vulnerabilities tabs have no design of their own; the fixed scopes above are my reading. Only those two pages change if the product means something else (update jobs, a flat CVE list).

Deliberately out

  • Install Software button: installSoftware needs softwareId + machineIds, there is no picker design in this node and no "available software" query — softwares lists what is already installed.
  • Row open arrow: no software detail page yet (software(id), softwareDevices, softwareVulnerabilities are waiting in the schema for it).

Testing

npm run relay, type-check, prettier, eslint -c eslint.ci.mjs on the touched files, next build — all green.

Not verified against live data: on test-3043 Query.softwares returns null in a non-null field (NullValueInNonNullableField), i.e. the SDL is deployed but the resolver isn't. Until it is, the page shows its ContentErrorBoundary state.

Adds /software, built from the Figma "All Software" design: one row per
software title aggregated across the fleet, on Relay against the new
softwares(...) connection.

- Search, infinite scroll, server-side sort on DEVICES and VULNS.
- Cells per the design: name + publisher, current version with the OUTDATED
  chip and the "+N older versions" line, device count, severity tag with the
  CVE count or "no CPE match".
- Two sibling tabs share the table with a fixed scope: /software/updates
  (versionStatuses: OUTDATED) and /software/vulnerabilities (minSeverity: LOW).
- Sidebar entry between Monitoring and Logs; routes go through routes.software.
- schema.graphql re-fetched from test-3043 for the Software* types.
@pavlo-flamingo
pavlo-flamingo requested review from a team as code owners September 8, 2026 20:27
* two sortable headers (DEVICES / VULNS) so the header indicator and the
* backend field are the same string.
*/
const SORTABLE_COLUMN_IDS = ['devicesCount', 'severity'] as const;

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.

🦩 🟠 [warn/recommended] SortInput.field values sent to backend are not validated against SORTABLE_COLUMN_IDS before being passed as sort variable

SORTABLE_COLUMN_IDS is declared as the only values allowed to reach SortInput.field, but the truncated portion of software-table.tsx (not fully visible) needs to actually gate the sort object constructed from URL/searchParam state against this list before passing it as the sort variable to useLazyLoadQuery. If onSortChange or the sort state is derived directly from a header click id without checking membership in SORTABLE_COLUMN_IDS, arbitrary URL-controlled values could reach the GraphQL query's sort.field argument. This is worth confirming since the code comment asserts the invariant is enforced elsewhere in the file, but that logic is outside the visible diff/context excerpt.

Evidence
const SORTABLE_COLUMN_IDS = ['devicesCount', 'severity'] as const;
🤖 Prompt for AI agents
In src/app/(app)/software/components/software-table.tsx around line 41, address this code-review finding: SortInput.field values sent to backend are not validated against SORTABLE_COLUMN_IDS before being passed as sort variable.
SORTABLE_COLUMN_IDS is declared as the only values allowed to reach SortInput.field, but the truncated portion of software-table.tsx (not fully visible) needs to actually gate the sort object constructed from URL/searchParam state against this list before passing it as the `sort` variable to useLazyLoadQuery. If onSortChange or the sort state is derived directly from a header click id without checking membership in SORTABLE_COLUMN_IDS, arbitrary URL-controlled values could reach the GraphQL query's sort.field argument. This is worth confirming since the code comment asserts the invariant is enforced elsewhere in the file, but that logic is outside the visible diff/context excerpt.
The flagged code:
```
const SORTABLE_COLUMN_IDS = ['devicesCount', 'severity'] as const;
```
Make the minimal change that resolves the finding; do not refactor unrelated code.

confidence: 20 — react 👍/👎 to teach the reviewer

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

🦩 Flamingo Code Review

1 finding(s) — 0 action required · 1 recommended · 0 informational

Mode: advisory · 1 defect(s) outside any rule

React 👍/👎 on inline comments to teach the reviewer.

pavlo-flamingo and others added 7 commits September 8, 2026 21:33
… tabs

Adds /software/details?id=, built from the Figma detail design: the title
block, a Publisher / Type / Latest Version summary card, and the two tabs.

- Devices tab: every machine carrying the title, with its own installed
  version and lifecycle chip (OUTDATED / SCHEDULED UPDATE / UNINSTALLING /
  SCHEDULED UNINSTALL), a status funnel, version sort, search, and a per-row
  uninstall behind a confirmation. Machines are read through the existing
  deviceRowFields_machine ladder step.
- Vulnerabilities tab: CVE id, severity chip with its CVSS score, affected
  version and publication date with the CVE's age; severity funnel, sort on
  version and published, and a per-row link to the NVD record.
- The list rows now open the detail page (row click + the arrow column the
  design has always shown).
- Install Software page (/software/install): package-manager catalog search
  (searchPackages), install-now/schedule choice and device picker. "Run
  Installation" stays disabled: the schema has no install mutation.
- Vulnerabilities tab now lists fleet CVEs (vulnerabilities query) instead of
  vulnerable software titles; severity funnel maps to the minSeverity cut-off.
- CVE detail page (/software/vulnerability?id=): description, score, devices,
  resolved-in, published and the affected software table.
- Schema refresh from test-3043: software mutations and Software.type are gone,
  so the per-device "Uninstall Software" action and the Type summary cell are
  removed; searchPackages is now a connection.
- Schema refresh from test-3043: installSoftware / updateSoftware take catalog
  packages, plus software schedules and softwareExecutions.
- Install and Update Software share one page (SoftwareActionView): run now via
  installSoftware / updateSoftware, or schedule via createSoftwareSchedule with
  the script-schedule date / time / timezone grid.
- Software Update Details page (/software/executions): package summary
  (version, processed devices) over the shared executions table fed by
  softwareExecutions.
- "Update Software" action on the Software Update tab.
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