Skip to content

Publish how old the vulnerability database is - #295

Merged
haksungjang merged 1 commit into
mainfrom
feat/vuln-db-freshness-metric
Sep 3, 2026
Merged

Publish how old the vulnerability database is#295
haksungjang merged 1 commit into
mainfrom
feat/vuln-db-freshness-metric

Conversation

@haksungjang

Copy link
Copy Markdown
Contributor

O2. Sits beside the task-run series #291 added.

Why this needs a metric rather than a check

A vulnerability database that stopped updating does not make anything fail. Scans keep running, keep finding what it knew when it stopped, and report success. Nothing in the system objects.

A deployment was found 46 days behind with every scan green. Three layers could have said so:

Layer Why it did not
Bootstrap logs failed on every start and said so; nobody reads worker logs
metadata.json held the date the whole time
Admin health panel reads that file and shows it, but a screen has to be visited, and the reader still has to subtract two dates

What actually surfaced it was somebody looking at the disk for an unrelated reason.

Two gauges, no verdict

trusca_vuln_db_last_update_timestamp_seconds and trusca_vuln_db_refresh_interval_hours.

Neither answers alone. The timestamp says when the data stopped changing; the interval says how long that is supposed to be able to go on. An air-gapped install mirroring on a slower cadence is not broken, and only the interval separates it from one that is.

The panel's fresh / stale bucket is deliberately not published. That classification exists for a screen. A series carrying it would freeze one judgement into the metric and put it beyond the collector's reach, and the right threshold depends on a cadence only the deployment knows.

Zero when no database has been downloaded, rather than dropping the series. That is the worst state this can be in, and it is exactly where a disappearing series would leave a dashboard looking clean. Same reasoning as outcome=running in #291.

Where it reads from

Directly from the file. The backend already carries a read-only mount of the worker's Trivy cache, added when this same file being unreachable made the panel report "unknown", so no inference from task history is needed.

Task history answers a different question anyway (did the refresh run, did it succeed) and #291 already publishes that as trusca_task_runs_24h{task="...",outcome="failed"}. Reading both together is a runbook matter, not a third series.

Verification

5 unit tests, contract fixture updated, ruff and mypy clean, 239 related tests green. Admin guide in both locales explains why the two series belong together and why no verdict ships with them.

One test is worth noting: it asserts that the accessor never reads the snapshot's freshness attribute. Two earlier versions matched on the strings freshness and fresh and both failed on names that legitimately contain them (the accessor is named for what it measures, and refresh contains fresh). A test of spelling is not a test of behaviour.

A database that stopped updating does not make anything fail. Scans keep
running, keep finding what it knew when it stopped, and report success. One
deployment was found 46 days behind with every scan green, and what surfaced
it was somebody looking at the disk for an unrelated reason.

Three layers could have said so and none did. The bootstrap failed on every
start and logged it, but nobody reads worker logs. metadata.json held the date
all along. The admin panel reads that file and shows it, but a screen has to
be visited, and even then the reader has to subtract two dates themselves.

Two gauges: the upstream update time, and the configured refresh interval
beside it. Neither answers alone. The timestamp says when the data stopped
changing; the interval says how long that is supposed to be able to go on. An
air-gapped install mirroring on a slower cadence is not broken, and only the
interval separates it from one that is.

No staleness verdict is published, and the panel's fresh / stale bucket stays
out. That classification exists for a screen; a series carrying it would
freeze one judgement into the metric and put it beyond the collector's reach,
which is where the decision belongs because the cadence is a local fact.

Zero when no database has been downloaded, rather than omitting the series.
That is the worst state this can be in, and it is exactly where a series that
disappeared would leave a dashboard looking clean.

The backend already has a read-only mount of the worker's cache, added when
this same file being unreachable made the panel report "unknown", so the
metric reads it directly rather than inferring from task history.
@haksungjang
haksungjang merged commit 71f357d into main Sep 3, 2026
30 checks passed
@haksungjang
haksungjang deleted the feat/vuln-db-freshness-metric branch September 3, 2026 01:45
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.

1 participant