github robintra/perf-sentinel v0.9.11

latest release: chart-v0.9.11
4 hours ago

What's new in v0.9.11

v0.9.11 is a patch release confined to the self-contained HTML report. The dashboard's per-tab search inputs collapse into one global search box, and a set of report-only defects are fixed. Nothing outside the HTML sink moves: the pipeline, the detectors, ingest, the daemon routes, the JSON and SARIF output, and the Content-Security-Policy are untouched, and a report rendered from the same input embeds the same analysis payload, with only its version field advanced.

Report: one global search

The report previously carried five per-tab search inputs, and the topbar box was a proxy that mirrored into them. On pg_stat and mysql_stat one of those inputs stayed visible beside the topbar box, so typing in either filled the other, and on a tab with no searchable content the topbar box silently swallowed keystrokes. The topbar box is now the only search input and the single source of truth. One query filters every searchable tab at once, Findings, pg_stat, mysql_stat, Diff, and Correlations, and each tab reports its own match count in its sidebar badge, so a query typed from any tab, including Overview and Carbon, shows where the matches are before you switch. The query survives a tab switch, and matches are highlighted only in the panel on screen.

The Findings tab filters its data rather than its rendered rows. The list is paginated at eight rows, so hiding rows would only ever search the first page and cap the match count at eight. Findings match on their severity, their type as both the raw slug and the label the row shows so that N+1 SQL and n_plus_one_sql both match, their service, their endpoint, and their SQL template. The other four panels render every row and filter in place. Each tab's Export CSV downloads exactly the rows its query left visible.

Report: fixes

Clicking a cross-trace correlation card opened a detail pane titled "undefined". The synthetic finding it built carried neither a type nor a severity, and it described the source endpoint over a trace that belongs to the target. It now describes the target-side finding whose trace the card samples, so the head reads a real type, the trace tree highlights the offending span, and the pg_stat cross-reference resolves.

In live mode under a query, the Findings sidebar badge and the panel counter over-counted. They reported every match including the acknowledged findings that the "Show acknowledged" toggle keeps hidden, so the badge could read a higher number than the rows on screen. The acknowledgment filter now runs at the data level, so the badge, the counter, the pagination, and the CSV export all agree on the visible set.

Two panels overflowed on a narrow viewport. Wide tables, the acknowledgments list and the region breakdown, were clipped by the card with no way to scroll to the hidden columns, and in live mode the topbar overflowed and pushed the whole page into a horizontal scroll. Wide tables now scroll inside their card, and the topbar wraps its actions onto a second line, so the page itself never scrolls sideways at any width.

A query typed on another tab could blank the Diff and Correlations panels while their headers still claimed a stale count. Both panels now show an empty-state line when a query hides every row, the Diff section headers recount the rows actually visible, and the Severity changes and Endpoint metric deltas sections keep symmetric padding when they are empty.

A deep link naming a service that does not exist filtered the findings list to nothing with no active chip to explain the empty list, since the severity value was validated against the known set but the service was not. An unknown service is now ignored. Opening a top offender from the Overview that sits past the first rendered page now grows the page to reach it instead of doing nothing, and the "/" shortcut no longer steals a slash typed into a text field such as an acknowledgment reason.

Operator-visible behavior change

The five per-tab search boxes are gone, replaced by the single topbar box that now searches every tab. In live mode with acknowledged findings hidden, the Findings sidebar badge and the panel counter show the count of visible findings rather than the total, so both agree with the list. No CLI flag, configuration key, output schema, daemon HTTP route, metric, or Content-Security-Policy is added or changed. The JSON payload embedded in the report keeps its schema and its analysis data, with only version and binary_version advancing to 0.9.11.

Why this is a patch and not a minor

The release adds no new tool to the report. Where v0.9.10 added sorting, a density mode, and an acknowledgment undo, this release reunifies a search that already existed into one control and corrects the way it counts, highlights, and exports, alongside a set of visible defects in the correlation detail, the narrow-viewport layout, the empty panels, and the deep-link handling. Nothing an integration depends on moves: the payload schema, the CLI surface, the configuration, the daemon routes, the metrics, and the CSP are unchanged, and the minimum supported Rust version stays at 1.96.1.

Validation

The HTML surface is validated where it lives. The browser suite passes 27 of 27 against a report rendered by the release binary, including the specs added for this release: the single visible search input on every tab, per-tab match counts driven from a non-searchable tab, a query that survives a tab switch, the findings count that reaches past the first rendered page, the correlation detail that highlights the target span, and the narrow-viewport layout that never scrolls the page sideways. The demo suite passes 22 of 22 and regenerates every documentation still from the final template. The Rust suite asserts the template contract the report has to keep, the strict CSP with font-src data:, the embedded woff2 faces, the ban on innerHTML and eval that forces every script onto textContent and createElement, the ARIA tab panels, the escaped </script> in the embedded payload, and that no local-storage write carries the daemon API key. CI covers the build, the full test suite (cargo test --workspace, 2598 tests), clippy at -D warnings, cargo fmt, and both the default and --no-default-features builds.

Verifying this release

# Binary integrity via SLSA Build L3 attestation
gh attestation verify perf-sentinel-linux-amd64 \
  --owner robintra --repo perf-sentinel

# A periodic disclosure produced by this binary
perf-sentinel verify-hash --report perf-sentinel-report.json \
  --expected-identity "https://github.com/robintra/perf-sentinel/.github/workflows/release.yml@refs/tags/v0.9.11" \
  --expected-issuer "https://token.actions.githubusercontent.com"

gh CLI 2.49 or newer required for gh attestation verify.

Full Changelog: v0.9.10...v0.9.11

Don't miss a new perf-sentinel release

NewReleases is sending notifications on new releases.