fix(deps): clear 6 reachable RustSec advisories, accept 3 unreachable ones
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 1m38s
PR Check — Rust / rust (pull_request) Successful in 8m40s

cargo update -p rustls-webpki -p tar moves rustls-webpki 0.103.9 -> 0.103.13
and tar 0.4.44 -> 0.4.46, both within the existing Cargo.toml bounds. They sit
under tauri-plugin-updater, which downloads and unpacks application updates, so
all six of their advisories were reachable in the shipped binary.

The remaining three can neither be fixed nor reached. quick-xml (2x 7.5 high)
is pulled by plist, which tauri only needs for Apple bundling: its per-target
trees are empty for both shipped targets and it appears solely under
x86_64-apple-darwin. Its fix is >= 0.41.0 while plist requires ^0.38, a
semver-incompatible boundary [patch.crates-io] cannot cross. rsa has no
published fix at all and is never compiled — its only parent is sqlx-mysql, an
artifact of sqlx's multi-backend graph on a SQLite project.

Leaving those three to red the daily gate forever would reproduce the signal
loss that #232 removed the `|| true` to fix, so they move into a versioned
.cargo/audit.toml. Entries are keyed by advisory ID, never by crate, so a new
advisory against the same crate still reds the gate; each carries its
reachability proof and its removal condition.

A blocking step in check-rust.yml re-proves that justification on every PR
touching src-tauri/ or .cargo/, and fails if a suppressed crate enters a
shipped target's graph — the scenario that would rot the list is itself a
src-tauri change. It separates cargo tree's exit status from its output (an
absent crate and a failed invocation both print nothing) and asserts a canary
crate is still found, so its silence proves something.

cargo audit: 9 vulnerabilities -> 0, warnings unchanged at 23
(cargo-audit 0.22.2, advisory-db 0bfde9d6 of 2026-07-27).
cargo check + cargo test green (106 tests); npm build + 871 vitest green.

Resolves #310

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
le king fu 2026-07-27 19:45:15 -04:00
parent 78e8be3f1a
commit f4b09b028e
10 changed files with 239 additions and 14 deletions

65
.cargo/audit.toml Normal file
View file

@ -0,0 +1,65 @@
# cargo-audit configuration — accepted advisories (#310).
#
# Every ID listed here is suppressed on EVERY `cargo audit` run, including the
# daily blocking gate in .forgejo/workflows/audit.yml. So a green audit means
# "no advisory outside this list", not "no advisory at all". See
# docs/adr/0018-suppression-advisories-non-atteignables.md.
#
# Two rules govern the list:
#
# 1. An advisory may only be listed if its crate is absent from the
# dependency graph of EVERY shipped target (Windows and Linux), or if no
# fix has been published at all. A reachable advisory with an available
# fix gets fixed, never suppressed.
#
# 2. Entries are keyed by advisory ID, never by crate. A new advisory filed
# against a crate already listed here re-reds the gate on purpose — each
# one is reviewed on its own merits. Widening an entry to a whole crate
# would defeat the gate.
#
# check-rust.yml carries a guard that re-proves rule 1 on every PR touching
# src-tauri/ or this file. ADDING AN ENTRY HERE REQUIRES ADDING ITS CRATE TO
# THAT GUARD'S CRATE LIST — otherwise the new entry gets no anti-rot coverage.
#
# To re-verify an entry (or before removing one), run from the repo root:
#
# cargo tree --manifest-path src-tauri/Cargo.toml -i <crate> --target x86_64-unknown-linux-gnu
# cargo tree --manifest-path src-tauri/Cargo.toml -i <crate> --target x86_64-pc-windows-msvc
#
# Empty output on both targets means the entry is still justified. Any output
# means it is not: drop the entry and fix the advisory for real.
[advisories]
ignore = [
# quick-xml 0.38.4 — RUSTSEC-2026-0194 (quadratic run time when checking a
# start tag for duplicate attribute names) and RUSTSEC-2026-0195 (unbounded
# namespace-declaration allocation enabling memory-exhaustion DoS), 7.5
# high each.
#
# Not compiled on either shipped target. quick-xml is pulled by `plist`,
# which tauri only depends on for Apple bundling: both per-target trees are
# empty, and it appears solely under x86_64-apple-darwin, which we do not
# ship.
#
# An override is not an option either — both advisories are patched only in
# >= 0.41.0 while plist requires ^0.38, a semver-incompatible boundary that
# `[patch.crates-io]` cannot cross.
#
# Removal trigger: plist (or tauri) shipping quick-xml >= 0.41.0 — see #312.
"RUSTSEC-2026-0194",
"RUSTSEC-2026-0195",
# rsa 0.9.10 — RUSTSEC-2023-0071 (Marvin attack: potential key recovery
# through timing side channels), 5.9 medium.
#
# Qualifies under both halves of rule 1. It has no fix at all — the
# advisory's patched list is empty, which is why suppression is the only
# option available. And it is unreachable: its sole parent in the lockfile
# is sqlx-mysql, an artifact of sqlx's multi-backend graph, while this
# project talks to SQLite through tauri-plugin-sql. `cargo tree -i rsa
# --target all` returns nothing at all.
#
# Removal trigger: a fixed rsa release, or sqlx dropping the crate from the
# graph.
"RUSTSEC-2023-0071",
]

View file

@ -14,6 +14,12 @@ name: Security audit
# Note: PATH is deliberately NOT overridden at job level (unlike check-rust,
# which needs /root/.cargo/bin for the toolchain) so that the install dir
# taiki-e/install-action appends to $GITHUB_PATH stays effective.
#
# This job reads .cargo/audit.toml from the checkout root, which lists the
# advisories accepted for this project (#310). A green run therefore means "no
# advisory outside that list", not "no advisory at all" — the justification and
# the removal criteria for each entry live in that file, and the policy behind
# it in docs/adr/0018-suppression-advisories-non-atteignables.md.
on:
schedule:

View file

@ -13,6 +13,7 @@ on:
pull_request:
paths-ignore:
- 'src-tauri/**'
- '.cargo/**'
- 'docs/**'
- 'reports/**'
- 'tasks/**'

View file

@ -15,6 +15,10 @@ on:
paths:
- 'src-tauri/**'
- '.forgejo/workflows/check-rust.yml'
# Whole directory, not just audit.toml: a later .cargo/config.toml
# (rustflags, linker, target dir) would change the Rust build, and an
# exact-path entry would let it skip Rust CI unnoticed.
- '.cargo/**'
# Cancel obsolete runs (e.g. on force-push) so only the latest commit runs.
# Distinct from the frontend group: a shared group would make the two
@ -68,6 +72,53 @@ jobs:
- name: cargo check
run: cargo check --manifest-path src-tauri/Cargo.toml --all-targets
# Anti-rot guard for the suppressions in .cargo/audit.toml (#310). Each
# entry there is justified by its crate being absent from every shipped
# target's graph — a property of today's resolved graph, not a permanent
# one. If a tauri/plist bump ever makes quick-xml unconditional, the
# suppression would silently hide a live advisory and the daily audit
# would stay green: the inverse of the permanent red #310 exists to kill.
#
# That bump would itself be a src-tauri change, which is exactly what
# triggers this workflow. Runs after cargo check so the registry index is
# already warm, and --locked so cargo tree cannot rewrite the lockfile the
# audit was taken against.
#
# CRATES must mirror the crates named in .cargo/audit.toml. Adding an
# entry there without adding its crate here leaves it unguarded.
- name: Verify suppressed advisories are still unreachable
run: |
set -u
CRATES="quick-xml rsa"
TARGETS="x86_64-unknown-linux-gnu x86_64-pc-windows-msvc"
rc=0
for crate in $CRATES; do
for target in $TARGETS; do
# An absent crate exits 0 with empty stdout ("nothing to print"
# goes to stderr). A non-zero exit means cargo tree itself failed
# — treat that as a failure rather than as proof of absence.
out=$(cargo tree --manifest-path src-tauri/Cargo.toml --locked \
-i "$crate" --target "$target" 2>/dev/null) || {
echo "cargo tree failed for $crate / $target — cannot verify the suppression"
rc=1
continue
}
if [ -n "$out" ]; then
echo "$crate is now compiled for $target — its .cargo/audit.toml suppression is no longer justified (see #310)."
rc=1
fi
done
done
# Canary: a crate known to be present. If this stops being found, the
# loop above is broken and its silence means nothing.
canary=$(cargo tree --manifest-path src-tauri/Cargo.toml --locked \
-i tar --target x86_64-unknown-linux-gnu 2>/dev/null) || true
if [ -z "$canary" ]; then
echo "Canary failed: 'tar' was not found although it is a known dependency. The guard is not proving anything."
rc=1
fi
exit $rc
- name: cargo test
run: cargo test --manifest-path src-tauri/Cargo.toml --all-targets

View file

@ -10,6 +10,10 @@
- L'application déverrouille désormais ses modules par édition — **Gratuite**, **Base** ou **Premium**, résolue depuis votre clé de licence. La Gratuite conserve le Tableau de bord, l'Import CSV, les Transactions, les Catégories, le rapport Tendances (et le hub Rapports), l'export/import chiffré et le journal des modifications, avec un seul profil. La **Base** débloque en plus le Budget, les Ajustements, les quatre rapports avancés (Faits saillants, Comparables, Analyse par catégorie, Cartes), les profils multiples et les mises à jour automatiques. La **Premium** débloque en plus le module Bilan complet (patrimoine, détail par titre, cours du marché). Les modules verrouillés restent visibles — un cadenas apparaît dans la barre latérale et sur les tuiles de rapports — et les ouvrir affiche un écran de déverrouillage avec un raccourci « J'ai déjà une clé » vers la carte de licence ; le bouton d'achat en ligne « Obtenir Base / Premium » est affiché mais désactivé pour l'instant (« bientôt disponible »). Le verrouillage n'est jamais destructif : quelle que soit l'édition, vos données sont conservées intactes et tout réapparaît dès qu'une clé valide est entrée — en Gratuite votre profil actif reste toujours accessible, seuls la création d'un profil supplémentaire ou le passage à un autre profil sont verrouillés (#297, #298, #299, #300, #301).
### Sécurité
- Mise à jour de deux dépendances Rust situées sur le chemin de la mise à jour automatique, corrigeant six advisories RustSec : `rustls-webpki` 0.103.9 → 0.103.13 (traitement des contraintes de nom de certificat et analyse des listes de révocation, dont une panique atteignable) et `tar` 0.4.44 → 0.4.46 (`chmod` de répertoires arbitraires en suivant des liens symboliques pendant l'extraction, et en-têtes de taille PAX mal pris en compte). Les deux sont tirées par `tauri-plugin-updater`, qui télécharge et décompresse les mises à jour de l'application : ce sont donc de vrais chemins de code du produit livré. Aucun changement de comportement. Trois autres advisories restent signalées sur le fichier de verrouillage mais ne s'appliquent pas au produit livré — `quick-xml` n'est compilé que pour des cibles Apple que nous ne livrons pas, et `rsa` n'est jamais compilé — elles sont désormais consignées comme acceptées, avec leur justification et les conditions de leur retrait, plutôt que de laisser l'audit de sécurité quotidien rouge en permanence (#310).
## [0.14.0] - 2026-07-18
### Modifié

View file

@ -10,6 +10,10 @@
- The application now unlocks its modules per edition — **Free**, **Base** or **Premium**, resolved from your license key. Free keeps the Dashboard, CSV Import, Transactions, Categories, the Trends report (and the Reports hub), encrypted export/import and the changelog, with a single profile. **Base** additionally unlocks Budget, Adjustments, the four advanced reports (Highlights, Compare, Category analysis, Cards), multiple profiles and automatic updates. **Premium** additionally unlocks the full Balance module (net worth, per-security detail, market prices). Locked modules stay visible — a lock badge shows in the sidebar and on the report tiles — and opening one shows an unlock screen with an "I already have a key" shortcut to the license card; the online "Get Base / Premium" purchase button is shown but disabled for now ("coming soon"). Locking is never destructive: whatever the edition, your data is kept untouched and everything reappears as soon as a valid key is entered — on Free your active profile always stays accessible, only creating or switching to another profile is locked (#297, #298, #299, #300, #301).
### Security
- Updated two Rust dependencies sitting on the automatic-update path, clearing six RustSec advisories: `rustls-webpki` 0.103.9 → 0.103.13 (certificate name-constraint handling and certificate-revocation-list parsing, including a reachable panic) and `tar` 0.4.44 → 0.4.46 (arbitrary directory `chmod` by following symlinks during extraction, and mishandled PAX size headers). Both are pulled in by `tauri-plugin-updater`, which downloads and unpacks application updates, so these are real code paths in the shipped app. No behaviour change. Three further advisories are still reported against the lockfile but do not apply to the shipped product — `quick-xml` is only compiled for Apple targets we do not ship, and `rsa` is never compiled at all — so they are now recorded as accepted, together with their justification and the conditions for removing them, instead of leaving the daily security audit permanently red (#310).
## [0.14.0] - 2026-07-18
### Changed

View file

@ -161,9 +161,9 @@ Pour maintenir l'éligibilité aux crédits d'impôt R&D (RS&DE fédéral + CRIC
Workflows Forgejo Actions dans `.forgejo/workflows/`. Le runner est à **capacité 1** — les jobs se suivent, ils ne tournent pas en parallèle.
- **`check-rust.yml`** — déclenché sur les PR touchant `src-tauri/**`. Lance `cargo check`, `cargo test` et un `cargo audit` informatif. Doit être vert avant tout merge.
- **`check-rust.yml`** — déclenché sur les PR touchant `src-tauri/**` ou `.cargo/**`. Lance `cargo check`, une vérification bloquante que les advisories acceptées restent non atteignables, `cargo test` et un `cargo audit` informatif. Doit être vert avant tout merge.
- **`check-frontend.yml`** — déclenché sur les PR, sauf si tous les fichiers modifiés sont du Rust, de la doc ou du markdown. Lance `npm run build` (tsc + vite) et `npm test` (vitest). Doit être vert avant tout merge.
- **`audit.yml`** — audit RustSec quotidien (06:00 UTC) + `workflow_dispatch`, pour couvrir les avis de sécurité entre deux PR Rust. Échec bloquant.
- **`audit.yml`** — audit RustSec quotidien (06:00 UTC) + `workflow_dispatch`, pour couvrir les avis de sécurité entre deux PR Rust. Échec bloquant. **Un run vert signifie « zéro advisory hors de la liste acceptée »**, pas « zéro advisory » : cette liste est dans `.cargo/audit.toml` (preuve de non-atteignabilité et condition de retrait par entrée), encadrée par l'[ADR 0018](docs/adr/0018-suppression-advisories-non-atteignables.md). Ne jamais y ajouter une advisory atteignable ni élargir une entrée à un crate entier.
- **`release.yml`** — déclenché par les tags `v*`. Build Windows (NSIS `.exe`) + Linux (`.deb`, `.rpm`), signe les binaires et publie le JSON d'updater pour les mises à jour automatiques.
Aucun workflow `check-*` ne filtre sur `branches:` : une PR stackée sur une autre branche de feature déclenche donc bien la CI. Le cache Actions est retiré partout tant que [#234](https://git.lacompagniemaximus.com/maximus/simpl-resultat/issues/234) (connectivité du serveur de cache) n'est pas réglé — restore et save échouent tous les deux. Le miroir `.github/workflows/` est dormant (aucune PR côté GitHub).

View file

@ -0,0 +1,90 @@
# ADR 0018 — Suppression d'advisories RustSec non atteignables : liste par ID, preuve par cible livrée, garde-fou anti-péremption
- Status: **Accepted**
- Date: 2026-07-27
- Issues: #310 (les 9 advisories découvertes, cette décision), #312 (déclencheur de retrait des entrées `quick-xml`), #314 (le cron de `audit.yml` n'a jamais démarré)
- S'appuie sur #232 (split de `check.yml`, création de `audit.yml`, retrait du `|| true` qui masquait la sortie de `cargo audit`)
## Contexte
#232 a retiré le `|| true` qui avalait la sortie de `cargo audit` et créé `audit.yml`, un job quotidien (06:00 UTC) **volontairement bloquant** : il *est* le canal de notification pour les advisories publiées entre deux PR Rust, `check-rust.yml` ne tournant que sur ~1 PR sur 40.
Le retrait du masque a découvert 9 advisories RustSec préexistantes dans `src-tauri/Cargo.lock`. Six sont atteignables et corrigeables par un simple `cargo update` (`rustls-webpki` ×4, `tar` ×2, tous sur le chemin de `tauri-plugin-updater`). Les trois restantes ne le sont pas :
| Crate | Advisories | Situation |
|---|---|---|
| `quick-xml` 0.38.4 | RUSTSEC-2026-0194, RUSTSEC-2026-0195 (7.5 high) | Tiré par `plist`, dont `tauri` ne dépend que pour le bundling Apple. Absent des arbres `x86_64-unknown-linux-gnu` et `x86_64-pc-windows-msvc` ; présent seulement sur `x86_64-apple-darwin`, cible que le projet ne livre pas. Corrigé en `>= 0.41.0` alors que `plist` exige `^0.38` — frontière semver-incompatible que `[patch.crates-io]` ne peut pas franchir. |
| `rsa` 0.9.10 | RUSTSEC-2023-0071 (Marvin, 5.9 medium) | Aucun correctif publié (liste `patched` vide). Seul parent dans le lock : `sqlx-mysql`, artefact du graphe multi-backend de sqlx ; le projet parle à SQLite via `tauri-plugin-sql`. `cargo tree -i rsa --target all` ne retourne rien. |
Le problème n'est donc pas de corriger ces trois advisories — c'est impossible — mais de décider ce que devient le gate quotidien. Le laisser rouge en permanence reproduit exactement le défaut que #232 venait de supprimer : une alarme qui sonne tous les jours sans qu'on puisse rien y faire finit ignorée, et la prochaine advisory réelle se noie dedans. C'est la même perte de signal que le `|| true`, obtenue par un autre chemin.
## Décision
**Une liste de suppressions par ID d'advisory, dans un `.cargo/audit.toml` versionné à la racine du dépôt**, encadrée par trois règles.
### Règle 1 — critère d'admission
Une advisory ne peut être listée que si son crate est absent du graphe de dépendances de **toutes** les cibles livrées (Windows et Linux), **ou** si aucun correctif n'a été publié. Une advisory atteignable dont le correctif existe se corrige, elle ne se supprime jamais.
La preuve est mécanique et reproductible, et doit être refaite contre le lock courant :
```
cargo tree --manifest-path src-tauri/Cargo.toml -i <crate> --target x86_64-unknown-linux-gnu
cargo tree --manifest-path src-tauri/Cargo.toml -i <crate> --target x86_64-pc-windows-msvc
```
Sortie vide sur les deux cibles = entrée justifiée. `--target all` ne suffit pas : il répond « présent » pour des crates conditionnels Apple qui ne sont compilés nulle part chez nous, ce qui est précisément le cas de `quick-xml`.
### Règle 2 — clé par ID, jamais par crate
Les entrées portent un ID d'advisory (`RUSTSEC-YYYY-NNNN`), jamais un nom de crate. Une nouvelle advisory déposée contre un crate déjà listé **repasse le gate au rouge**, volontairement : elle est examinée pour elle-même. C'est ce qui distingue une suppression justifiée d'un silence permanent, et un élargissement au crate entier suffirait à annuler le bénéfice du gate.
### Règle 3 — garde-fou anti-péremption
L'atteignabilité est une propriété du graphe **résolu aujourd'hui**, pas une propriété permanente. Un bump `tauri`/`plist` rendant `quick-xml` inconditionnel laisserait la suppression cacher une advisory devenue vivante, et l'audit resterait vert : l'inverse exact du rouge permanent que cette décision cherche à éviter.
`check-rust.yml` porte donc une étape bloquante qui rejoue la règle 1 pour chaque crate supprimé, sur les deux cibles livrées, et échoue si l'un d'eux entre dans un arbre. Elle est placée après `cargo check` (index de registre déjà chaud) et passe `--locked` pour que `cargo tree` ne réécrive pas le lock contre lequel l'audit a été pris. Le scénario qui périmerait la justification est lui-même une modification de `src-tauri/`, soit exactement ce qui déclenche ce workflow.
Trois détails la rendent fiable plutôt que décorative :
- le code de sortie de `cargo tree` est testé séparément de sa sortie standard — un crate absent sort en 0 avec un stdout vide, tandis qu'un échec de `cargo tree` sort en non-zéro avec un stdout vide lui aussi ; sans cette distinction, une panne de l'outil se lirait comme une preuve d'absence ;
- un **canari** (`tar`, dépendance réellement présente) doit être trouvé à chaque exécution, faute de quoi le silence de la boucle ne prouve rien ;
- `.cargo/**` est ajouté aux `paths` de `check-rust.yml` pour qu'une PR ne touchant que la liste déclenche bien la vérification.
Le pendant — une entrée devenue *inutile*, que rien ne signale — est couvert par une issue de suivi portant la condition de retrait (#312 pour `quick-xml`).
## Alternatives considérées
- **Laisser `audit.yml` rouge en permanence.** Rejeté : c'est la perte de signal que #232 venait de corriger, obtenue autrement. Une alarme toujours rouge n'est plus une alarme.
- **Remettre `continue-on-error` ou `|| true` sur le job quotidien.** Rejeté pour la même raison, en pire : cela supprime le signal pour *toutes* les advisories, pas seulement pour les trois inévitables.
- **Dupliquer des `--ignore` dans `audit.yml` et `check-rust.yml`.** Rejeté : deux listes à maintenir en phase, sans endroit naturel où écrire la justification. Le fichier `.cargo/audit.toml` est lu par les deux workflows sans qu'aucun n'ait à le savoir, et il porte les preuves à côté des entrées.
- **Ignorer au niveau du crate plutôt que de l'advisory.** Rejeté — voir la règle 2.
- **Un override / `[patch.crates-io]` pour `quick-xml`.** Impossible : le correctif est en `0.41.0` et `plist` exige `^0.38`. `[patch.crates-io]` ne franchit pas une frontière semver-incompatible.
- **Retirer `sqlx-mysql` du graphe pour éliminer `rsa`.** Écarté : `rsa` n'étant compilé sur aucune cible, l'opération serait un contorsionnement du manifeste pour un gain nul.
## Conséquences
### Positives
- `audit.yml` redevient un signal exploitable : rouge veut dire « quelque chose de nouveau et d'actionnable », et non « les trois mêmes advisories qu'hier ».
- Les six advisories réellement atteignables sont corrigées, sans toucher `Cargo.toml` (`rustls-webpki` 0.103.9 → 0.103.13, `tar` 0.4.44 → 0.4.46, dans les bornes existantes).
- La justification de chaque suppression vit à côté de l'entrée, avec les commandes pour la rejouer — un lecteur futur n'a pas à re-dériver l'analyse ni à re-litiguer la branche « override ».
### Négatives
- **Un audit vert ne signifie plus « zéro advisory »**, mais « zéro advisory hors de la liste ». Le contrat du gate a changé et doit être lu comme tel — d'où la mention dans `audit.yml`, dans `docs/architecture.md` et dans `CLAUDE.md`.
- La liste et la boucle du garde-fou sont **couplées à la main** : ajouter une entrée dans `.cargo/audit.toml` sans ajouter son crate dans `check-rust.yml` laisse la nouvelle entrée sans couverture. Les deux fichiers portent le rappel réciproque, mais rien ne l'impose mécaniquement.
- Le garde-fou ne tourne que sur les PR touchant `src-tauri/` ou `.cargo/`. C'est le bon déclencheur pour le scénario visé, mais ce n'est pas une vérification continue.
### Neutre
- Les 23 `warning` (bindings gtk-rs GTK3 non maintenus, `fxhash`, crates *yanked*) ne sont pas concernés : ils ne comptent pas dans le code de sortie de `cargo audit` et ne sont donc pas ce qui rend le gate vert ou rouge. Le crate *yanked* `tauri-plugin-deep-link 2.4.8`, dépendance directe, est traité séparément en #313.
- Un `workflow_dispatch` vert prouve que la commande sort en 0, **pas** que l'alarme quotidienne existe : au moment de cette décision, `audit.yml` n'a encore jamais été déclenché par son `schedule` (#314).
## Liens
- [`.cargo/audit.toml`](../../.cargo/audit.toml) — la liste, ses preuves et ses critères de retrait
- [`.forgejo/workflows/check-rust.yml`](../../.forgejo/workflows/check-rust.yml) — étape « Verify suppressed advisories are still unreachable »
- [`.forgejo/workflows/audit.yml`](../../.forgejo/workflows/audit.yml) — le gate quotidien bloquant
- [ADR 0009](0009-proxy-price-fetching-via-maximus-api.md) — récupération de cours via `reqwest`, l'un des deux chemins qui rendent `rustls-webpki` atteignable
- Issues #310 (cette décision), #312 (retrait `quick-xml`), #313 (`tauri-plugin-deep-link` yanked), #314 (cron jamais déclenché), #315 (smoke-test du cycle de mise à jour)

View file

@ -422,7 +422,9 @@ Quatre workflows Forgejo Actions dans `.forgejo/workflows/`. Le runner est à **
### `check-rust.yml` — Vérifications Rust sur PR
Déclenché sur les PR qui touchent `src-tauri/**` (ou le workflow lui-même). Lance `cargo check` puis `cargo test`, et un `cargo audit` informatif (non bloquant, binaire pré-buildé via `taiki-e/install-action`).
Déclenché sur les PR qui touchent `src-tauri/**`, `.cargo/**` (ou le workflow lui-même). Lance `cargo check` puis `cargo test`, et un `cargo audit` informatif (non bloquant, binaire pré-buildé via `taiki-e/install-action`).
Entre `cargo check` et `cargo test`, une étape **bloquante** rejoue la justification des advisories acceptées dans `.cargo/audit.toml` : elle vérifie par `cargo tree --locked` que chaque crate supprimé reste absent des deux cibles livrées, et échoue si l'un d'eux redevient atteignable. Un canari (`tar`, réellement présent) garantit que son silence prouve quelque chose. Voir [ADR 0018](adr/0018-suppression-advisories-non-atteignables.md).
Aucun `branches:` : une PR stackée sur une autre branche de feature — ce que produit `/autopilot` — déclenche donc bien la CI. Aucune étape de cache non plus : le conteneur de job n'atteint pas le serveur de cache du runner ([#234](https://git.lacompagniemaximus.com/maximus/simpl-resultat/issues/234)), le restore et le save échouent tous les deux. Le cache reviendra via `Swatinem/rust-cache` une fois #234 réglé.
@ -434,6 +436,8 @@ Déclenché sur les PR, sauf si tous les fichiers modifiés sont du Rust, de la
`schedule` quotidien (06:00 UTC) + `workflow_dispatch`. `check-rust.yml` ne tournant que sur les PR qui touchent le Rust — environ 1 PR sur 40 — ce workflow garantit qu'un avis de sécurité publié sur une dépendance inchangée ne passe pas inaperçu. Échec bloquant : c'est le canal de notification.
**Un run vert ne signifie pas « zéro advisory »** mais « zéro advisory hors de la liste acceptée ». Cette liste vit dans `.cargo/audit.toml`, à la racine du dépôt, avec pour chaque entrée sa preuve de non-atteignabilité et sa condition de retrait ; la politique qui l'encadre est l'[ADR 0018](adr/0018-suppression-advisories-non-atteignables.md). Au moment de sa mise en place, le `schedule` n'avait encore jamais déclenché ce workflow ([#314](https://git.lacompagniemaximus.com/maximus/simpl-resultat/issues/314)) — un `workflow_dispatch` vert prouve que la commande sort en 0, pas que l'alarme quotidienne fonctionne.
Les deux workflows `check-*` doivent être verts avant tout merge. Ils évitent de découvrir des régressions au moment du tag de release.
> Le miroir GitHub (`.github/workflows/check.yml`) est laissé tel quel : aucune PR n'est ouverte côté GitHub, un push-mirror ne déclenche pas d'événement `pull_request`.

22
src-tauri/Cargo.lock generated
View file

@ -589,7 +589,7 @@ version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34"
dependencies = [
"windows-sys 0.61.2",
"windows-sys 0.48.0",
]
[[package]]
@ -989,7 +989,7 @@ dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys 0.61.2",
"windows-sys 0.59.0",
]
[[package]]
@ -1209,7 +1209,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys 0.61.2",
"windows-sys 0.52.0",
]
[[package]]
@ -4044,7 +4044,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.61.2",
"windows-sys 0.52.0",
]
[[package]]
@ -4100,7 +4100,7 @@ dependencies = [
"security-framework",
"security-framework-sys",
"webpki-root-certs",
"windows-sys 0.61.2",
"windows-sys 0.52.0",
]
[[package]]
@ -4111,9 +4111,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
[[package]]
name = "rustls-webpki"
version = "0.103.9"
version = "0.103.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53"
checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
dependencies = [
"ring",
"rustls-pki-types",
@ -5058,9 +5058,9 @@ dependencies = [
[[package]]
name = "tar"
version = "0.4.44"
version = "0.4.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a"
checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840"
dependencies = [
"filetime",
"libc",
@ -5477,7 +5477,7 @@ dependencies = [
"getrandom 0.3.4",
"once_cell",
"rustix",
"windows-sys 0.61.2",
"windows-sys 0.52.0",
]
[[package]]
@ -6323,7 +6323,7 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys 0.61.2",
"windows-sys 0.48.0",
]
[[package]]