Repository navigation
feat(assets): inventory on the redesign layout (#906) - #936
Merged
Merged
Conversation
The redesigned inventory shows, on each asset, its open vulnerabilities with a KEV tag and when a scan last reported something on it. GET /assets/exposure returns, per asset with a finding, the unresolved count, the unresolved KEV count and the last detection, from one grouped, tenant-scoped query. It is its own read, guarded by vulnerabilities:read: a member who may read assets but not vulnerabilities does not learn them through the inventory. The last detection is the latest last_seen of any finding, resolved ones included; it is not a last-scan date, since a scan that finds nothing leaves no row, and the contract says so. MAX() of a timestamp loses its column type on SQLite, so the query casts it to text and the repository parses either database's format; checked on Postgres against the same SQL by hand. Tests: use case Success / NotFound / Unauthorized, repository counts with a second tenant's finding on the same asset id, isolation decision registered. Signed-off-by: alex-dembele <alexandredembele16@gmail.com>
The inventory as the mockup lays it out: - Title with the asset and critical counts. Agent coverage is shown as "non mesurée": no agent reports per-asset inventory yet (#910), so the figure is signalled as unavailable rather than invented (D-069 E). - "Voir la topologie" and "Lancer une découverte". Discovery runs a real scan: one enabled source starts it and the toast follows the job, several ask which, none leads to Infrastructure to configure one. Shown only to members with scanner:scan. - Search and type pills with counts. - One dense table: name with its hostname, resource id or address, type with its icon, criticality, owner, location (location attributes), linked risks, open vulnerabilities with a KEV tag, last detection. Vulnerability columns come from /assets/exposure and are only fetched for members who may read vulnerabilities; others see a dash that says why. - A row opens the asset drawer. Kept outside the mockup: the typed attribute search (behind a toggle), selection with governed bulk delete, criticality filter, column chooser and export, edit / history / delete per row; creation, import and attribute schemas move to the "more" menu. Score and category columns stay available, hidden by default. All copy moves to fr/en keys. DataTable gains an optional searchClassName so a page can give the search box a fixed basis; the default is unchanged everywhere else. Signed-off-by: alex-dembele <alexandredembele16@gmail.com>
#906) The owner found the type pills above the table badly arranged, and a critique agreed: eleven equal pills over two lines, nine of them saying "1", then a third line of table buttons, all before the first row. Filtering now uses the design-system tabs on the schema's categories (Serveurs, Postes, Applications, Bases de données, Réseau, Cloud, Fournisseurs, Données, Non classés), only those present, with counts, keyboard navigation and the product's keyline. Free-text types stay in the Type column. The toolbar is one line at 1440 and 1280: search, a "KEV seulement" toggle with its count (only for members who may read vulnerabilities), the attribute search as an icon button, filters, columns and export. The DataTable searchClassName prop added for the pills has no use left and is removed. Signed-off-by: alex-dembele <alexandredembele16@gmail.com>
This was referenced Oct 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Seventh screen of the redesign epic (#899). Stacked on #933 (activity): the base is
feat/905-activity, so the diff shows only this issue. First PR checked against the owner's review (D-069) and its validation checklist.What changes for the user
The inventory is the dense table of the mockup:
"Lancer une découverte" runs a real scan:
scanner:scan.Backend
GET /assets/exposure: per asset with a finding, the open vulnerabilities, the open KEV findings and the last detection. One grouped, tenant-scoped query.vulnerabilities:read, separate from the inventory, so reading assets does not reveal vulnerabilities.last_detected_atis the latestlast_seenof any finding, resolved ones included. It is not a last-scan date: a scan that finds nothing leaves no row. The UI calls it "Dernière détection" and explains it in a tooltip.MAX(timestamp)loses its type on SQLite, so the query casts it to text and the repository parses either database's format. The live Postgres output matched the same SQL run by hand.Verified
go test ./...all packages pass. New tests:TestAssetExposure_Success/_NotFound/_Unauthorized,TestExposureByAsset_Success/_NotFound, and the isolation ratchet.npx tsc -b --noEmitclean, eslint and prettier clean on the touched files,npx vitest run117 files / 1054 tests.inventoryPage.test.tsx(9 tests) andinventoryRow.test.ts(4) cover:vulnerabilities:read;/assets?drawer=asset&entity=…./infrastructure.Deliberate differences from the mockup
Not done here
Closes #906