github Institut-du-Numerique-Responsable/perf-sentinel v0.39.0

latest release: chart-v0.39.0
2 hours ago

What's new in v0.39.0

v0.39.0 is about a result a team wants to show outside the Hub: a fix that removed waste, with figures nobody can quietly round up. Perf Sentinel now signs share cards, images and carousels that print what it measured over a closed period, and anyone who scans a card's QR code checks on perf-sentinel.dev/verifier that its figures are the ones signed. PerfSentinelHub 0.10.0 makes the cards from its own data and runs these commands to sign them.

Three commands that sign, render and check a card

perf-sentinel card keygen --out-dir <DIR> writes an Ed25519 key, mode 0600, and prints its fingerprint and public key. perf-sentinel card render --input card.json --signing-key <key> --out-dir <DIR> --format png|pdf|svg|jxl checks the Hub's card.json against every rule of the contract, refuses a card whose figures would claim more than they show, and writes a signed 1080 by 1350 PNG, a four-page PDF/A-3b carousel, an SVG or a lossless JPEG XL, in English or French. perf-sentinel verify-card <file|URL> checks a card offline, and with --online checks that the card's domain publishes the key, through its _perf-sentinel TXT record over DNS-over-HTTPS and its /.well-known/perf-sentinel-key file. The network is reached only with --online. Each command prints one JSON line with a closed list of reasons and exit codes, written up in docs/SHARE-CARD.md.

A second signature over the file itself

The QR code signs the figures, not the pixels: a reposted image keeps only its code. An original file carries a second signature over its own content, so a retouched PNG, SVG, JPEG XL or PDF reads content_modified, exit 1, and verify-card prints the signed figures for the reader to hold against the image. A revoked key caps every card it signed at level 1 (key_revoked), whatever date the card states, since that date is written by whoever holds the key. An --online lookup with one source unread answers binding_partial, exit 4, never a verified card.

Figures that never claim more than they measured

A card prints counts and CO₂ rounded down to two significant figures, with "at least" where the figure is a floor, and an everyday equivalent counted on the CO₂ as printed. The equivalences come from an embedded ADEME Base Carbone table (vintage V23.6, 2025-07-03, Licence Ouverte 2.0), refreshed by scripts/refresh-equivalences.py and never fetched at runtime.

The daemon counts the passes of a fixed finding under its threshold

A story card about a slow call cites the alert threshold the fix now stays under. The daemon reads a watch list of signatures in the reply to its detection push, counts per day the runs of those threshold-type signatures that stayed at or under their threshold, and exports them as below_threshold_passes on the count rows of GET /api/detections and of the push, a watched signature getting a row even with detections: 0. Each day gains thresholds, the slow, fanout, chatty, pool and serialized thresholds the daemon applied. Without a watch list nothing is counted, and the detectors run within noise of v0.38.0. With ten watched signatures detection takes about 6 percent longer on the synthetic bench, as docs/LIMITATIONS.md records. The new lab scenarios card-signal and card-cli check both halves end to end.

Smaller changes

  • The JPEG XL export uses the new crate jixel, pure Rust with no dependency, which grows the stripped release binary by about 2.5 MB.
  • Dependencies move to tokio 1.54.1, hyper 1.12.0, tonic 0.14.9, uuid 1.29.0, base64 0.23.1 and others.

Upgrade impact

  • PerfSentinelHub 0.10.0 sends the watch list and makes the cards. An older Hub ignores the new keys and sends no list, so the daemon counts nothing.
  • /api/detections count rows may carry detections: 0. A reader that sums rows is unaffected, one that reads a row as a detection must check the count. Days carry one more optional object, thresholds.
  • The card feature is on in the CLI and off in perf-sentinel-core. It adds the card and verify-card commands and their rendering crates to the default build.
  • No configuration key is added or removed, no route or metric changes, the acknowledgment signatures and the detection verdicts are untouched, the disclosure schema stays v1.8, and MSRV stays 1.99.1.

Full detail in CHANGELOG.md.

Verifying this release

# Binary integrity via SLSA build provenance attestation (Build Level 2)
gh attestation verify perf-sentinel-linux-amd64 \
  --repo Institut-du-Numerique-Responsable/perf-sentinel

# A periodic disclosure produced by this binary, with its attestation and bundle
perf-sentinel verify-hash --report perf-sentinel-report.json \
  --attestation perf-sentinel-report.intoto.jsonl --bundle perf-sentinel-report.sig \
  --expected-identity "https://github.com/Institut-du-Numerique-Responsable/perf-sentinel/.github/workflows/release.yml@refs/tags/v0.39.0" \
  --expected-issuer "https://token.actions.githubusercontent.com" \
  --verify-binary ./perf-sentinel-linux-amd64

gh CLI 2.49 or newer required for gh attestation verify. Releases up to v0.26.2 were attested under robintra/perf-sentinel and keep their own --repo and identity.

Don't miss a new perf-sentinel release

NewReleases is sending notifications on new releases.