state: sync after the guided getting-started path (#396-#401)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
le king fu 2026-10-08 21:14:18 -04:00
parent ee17f31352
commit 6de73b3c22

View file

@ -1,8 +1,8 @@
# STATE — Simpl'Résultat
> Derniere MAJ : 2026-10-06 (**#390 mergée — PR #394 en avance rapide par l'API, `main` `5910387`.** L'étape 5 de la liste de démarrage se coche enfin. Les profils secondaires rattrapent les migrations qu'ils n'avaient jamais reçues. Sous Linux, les commandes cherchent les bases dans le bon dossier. #390 reste ouverte en `status:blocked` jusqu'à la liste post-merge (Linux, avec un vrai profil secondaire ancien). Suivis de revue en #395. Retours de Max sur l'onboarding triés le même jour : #390 (bug) et #391 (parcours guidé, `/plan-run` en cours).)
> Derniere MAJ : 2026-10-08 (**Parcours de démarrage guidé mergé — pile #402 → #407 en avance rapide par l'API, `main` `ee17f31`, milestone `planned-2026-10-06-onboarding-parcours-guide` fermée 6/6.** Six `/pr-review` APPROVE, puis sept commits en tête de pile sur décision de Max, dont la voie A : l'étape « Importer un premier fichier » ne compte plus qu'un fichier qui a amené une transaction. Suites #408 et #409. Restent les vérifications manuelles sur un build, à faire avec celles de #390.)
>
> Précédente MAJ : 2026-10-05 (**v0.17.0 taggée et publiée — tag sur `07255e1`, CI release run 491 vert en 22 min, 7 artefacts et `latest.json` vérifiés (release et endpoint de l'updater).** Elle porte l'onboarding phase 1 et les suites de licence. Le même jour : #234 close avec sa milestone `spec-ci-build-optimization` (4/4), et les deux textes des suites de licence postés sur la-compagnie-maximus#184. Restent les vérifications manuelles sur la release publiée, dans Blockers.)
> Précédente MAJ : 2026-10-06 (**#390 mergée — PR #394 en avance rapide par l'API, `main` `5910387`.** L'étape 5 de la liste de démarrage se coche enfin. Les profils secondaires rattrapent les migrations qu'ils n'avaient jamais reçues. Sous Linux, les commandes cherchent les bases dans le bon dossier. #390 reste ouverte en `status:blocked` jusqu'à la liste post-merge. Suivis de revue en #395.)
## Position actuelle
@ -26,8 +26,18 @@ Audit critique de la page Bilan livré (`docs/audit-bilan-2026-05.md`, revue CPA
**v0.17.0 shippée** (2026-10-05, tag `v0.17.0` sur `07255e1` → CI release run 491 en 22 min, 7 artefacts + `latest.json` vérifiés par `verify-release.sh`, endpoint de l'updater en 0.17.0) — onboarding phase 1 et suites de licence. `[Unreleased]` vidé au tag. Aucune migration DB nouvelle (v1→v17). Étape 10 de `/release` non exigée (chaîne de mise à jour inchangée), raison écrite sur la release. Restent les vérifications manuelles sur la release publiée (Blockers) et, de la v0.16.0, le cycle de mise à jour Windows (Michel).
**Parcours de démarrage guidé mergé sur `main`** (2026-10-08, `ee17f31`, non publié) — milestone `planned-2026-10-06-onboarding-parcours-guide` fermée 6/6 (#396-#401, PRs #402 → #407, produites par `/autopilot` le 2026-10-08, relues par six `/pr-review` APPROVE, suivis appliqués en tête de pile) : bandeau « Démarrage n/N · Étape suivante » sur chaque page, cartes d'étape avec mise en évidence du contrôle sur Import, Transactions et Budget, état partagé par un fournisseur et canal d'événements de données (ADR 0022), règle D9 (un profil déjà actif trouve le parcours masqué). `[Unreleased]` porte aussi #390. Aucune migration DB (v1→v17). Suivis : #408 (`db.ts` hors verrou pendant une transaction) et #409 (harnais de test).
## Decisions recentes
- 2026-10-08 : **Parcours de démarrage guidé livré de bout en bout — `/autopilot` (6 PRs stackées en 3 h, CI verte à chaque maillon) → six `/pr-review` APPROVE → sept commits en tête de pile → merge ff par l'API (`main` `ee17f31`).**
- **Revues** : aucun bloquant, un verdict indépendant par PR (commentaires 20659 à 20730) ; `status:approved` posé par les seuls relecteurs, les workers ayant laissé `status:review` (skill corrigé).
- **Décision de Max : voie A** sur le critère de #398 « pas de « Fait. » pour un import qui n'ajoute rien ». Le relecteur a corrigé le rapport du run : les doublons seuls sont sans effet (leurs transactions sont venues avec un fichier `completed`) ; le vrai cas est l'import sans ligne valide (en-tête seul, format mal détecté), qui cochait l'étape 4 et faisait boucler /transactions et /import. L'étape compte désormais les `imported_files` en `completed` ayant au moins une transaction (`EXISTS` sur `transactions.file_id`, index `idx_transactions_file`), avec une entrée Corrigé : la v0.17.0 a déjà le défaut.
- **Autres suivis en tête** : D9 lit son drapeau hors transaction, donc plus de `BEGIN`/`COMMIT` à chaque ouverture, pendant lesquels `db.ts` laisse tout passer hors verrou ; `:focus-visible { outline: revert }` sur le contrôle entouré (WCAG 2.4.7) ; carte Budget sans cible sur l'état vide ; épingles (séquence réelle du reducer, phrase selon le filtre, notification de restauration hors verrou, fuseau du test du mois) ; docs et liste QA à 44 cas.
- **Preuves** : 16 mutations sur ces correctifs, toutes rouges, dont 4 survivantes des revues ; compteur rejoué avec sqlite3 sur le schéma consolidé ; tip en worktree `npm ci` propre (sonde rc=1, build, 1904 vitest) ; CI 507. Les commits ajoutés après la revue, non relus, sont nommés dans le commentaire 20835 de #407.
- **Merge** : chaque enfant reciblé sur `main` puis mergé en ff épinglé, branches gardées jusqu'au dernier merge puis supprimées, donc 6 PRs `merged`. #384 : trois items cochés (réglés par la pile), #382 en partie.
- **Acquis** : au `/plan-run`, confronter un critère à la définition du compteur hérité qu'il suppose (celui de l'étape 4 venait de la phase 1).
- Aucune migration DB (v1→v17). (ref #396-#401, PRs #402-#407, #408, #409, #384)
- 2026-10-06 : **#390 mergée (PR #394, `main` `5910387`) — l'étape 5 de la liste de démarrage se coche, les profils secondaires rattrapent leurs migrations, et les bases sont cherchées dans le bon dossier sous Linux.**
- **Constat** : en testant l'onboarding de la v0.17.0, Max a vu que classer une transaction ne cochait pas l'étape 5.
- **Cause** : depuis la v0.1.0, `updateTransactionCategory` lie un booléen JS. tauri-plugin-sql 2.3.2 le stocke en texte `'true'`, que le compteur `= 1` ne trouve pas.
@ -58,15 +68,14 @@ Audit critique de la page Bilan livré (`docs/audit-bilan-2026-05.md`, revue CPA
- 2026-10-03 : **v0.16.0 taggée et publiée (`56fc612`, run 451 vert) — sur le constat de Max qu'il n'y a pas d'autres utilisateurs que les testeurs, les vérifications manuelles passent après la publication.** Aucune PR ouverte à merger. Pré-vol du skill sur le tip `6625d25` : build, vitest 1348, `cargo check` sans avertissement, 187 Rust ; aucun worktree résiduel ; les deux testeurs ont une clé Premium valide depuis la v0.15.0 et rien ne touche `FEATURE_TIERS`. Version mineure (fonctionnalités ajoutées) : 5 manifestes, 2 changelogs et la ligne de `CLAUDE.md`, `Cargo.lock` édité à la main et accepté par `cargo metadata --locked`. Tag annoté confirmé par Max avant le push, poussé seul (jamais `--tags`). Run 451 en 22 min ; `verify-release.sh` vert ; l'endpoint de `tauri.conf.json` (registre de paquets) sert la 0.16.0, au-delà de la copie attachée à la release que lit le script. **Correction faite en route** : j'avais écrit que les installations Base+ recevraient la mise à jour d'elles-mêmes ; `docs/qa-update-cycle.md` et le code disent l'inverse, aucune vérification automatique, quatre déclencheurs manuels. Personne ne reçoit donc la release sans cliquer « Vérifier les mises à jour ». **Étape 10 due** (`rustls` 0.23.45 est sur le chemin TLS de l'updater) : Linux par Max, enchaînée avec #350 sur le poste activé en v0.15.0 (à faire avant tout changement de clé, qui efface le jeton) ; Windows par Michel. Trace à consigner dans le corps de la release. En parallèle : la-compagnie-maximus#184 (politique de confidentialité) par Max ; #370 ouverte (retrait de la clé, `status:triage`). **Tests de Max le jour même** : mise à jour Linux v0.15.0 → v0.16.0 réussie, trace consignée dans le corps de la release (invite d'authentification apparue, type non noté ; Windows à dérouler par Michel) ; #365 vérifiée avec la clé réellement révoquée et fermée. Anomalie relevée : saisie en cours de session, cette clé gardait l'édition Base jusqu'au clic sur « Activer », comportement livré (contrôle au démarrage seulement) → **#373** propose le contrôle dès la saisie. La vérification de #346, qui demande une édition Gratuite propre, est reportée à #370 (instructions ajoutées à son corps) ; **#372** ouverte (la liste complète des versions repousse le Journal en bas de Paramètres → Systèmes). Aucune migration DB (v1→v17). (ref v0.16.0, #270, #346, #347, #348, #350, #365, #370, #372, #373)
- 2026-10-03 : **#365 mergée (PR #368, `main` `b107cf4`) — une clé révoquée retombe en Gratuite, et l'app envoie pour cela sa première requête non sollicitée.** Constat du go-live (09-30) : une licence remboursée, révoquée côté serveur, restait pleinement fonctionnelle, parce que l'édition se résout hors ligne depuis la clé et que le drapeau de #347 (D13) ne vivait que la session. `/analyze` (10-01) : **D1** contrôle au démarrage, au plus une tentative par 24 h ; **D2** révocation nommée là où le verrou apparaît, sans bandeau global ; **D3** fail-open ; **D4** un seul état. **Livré** : `license.check` à côté de la clé (`{key_sha256, attempted_at, revoked}`, condensé SHA-256, jamais la clé) ; `entitlements_from_dir` rend `("free", [])` pour une clé révoquée, `auto-update` compris ; `check_license_revocation` (`POST /v1/licenses/verify`, produit et clé seulement, rien sans clé valide, tentative écrite avant l'appel, seul `valid:true` lève et seul « révoquée » pose) ; l'activation, la liste et la désactivation enregistrent un `license_revoked` sous la clé envoyée ; `LicenseContext` lit `info.revoked` (fin de `markRevoked`), lance le contrôle une fois par démarrage, écrit son issue dans le Journal et ne recharge que si l'état change ; une clé révoquée ressaisie reste en Gratuite ; carte Licence, `UpsellGate` et carte Mises à jour nomment la révocation ; amendement #365 de l'ADR 0017. **Écart tranché par Max le 10-02**, après trois échecs du plan checker : la route des cours **nomme** le 403 `license_revoked` sans l'enregistrer, parce que `/v1/prices` juge la licence du jeton d'activation, que le client ne relie pas à la clé, et que la v0.15.0 laissait le jeton d'une clé précédente à côté d'une nouvelle (`git show v0.15.0`) : l'enregistrer aurait rétrogradé une clé valide. Ce jeton périmé est suivi en **#367**. **Preuves** : 33 mutations Rust et 27 front de l'auteur, toutes rouges ; la première passe en avait laissé 5 vertes pour 4 manques, corrigés dans `4225dad`, dont la tentative écrite après la requête (un test lit maintenant le fichier d'état depuis le serveur mockito, pendant que la requête est en vol) et l'intervalle de 24 h que suivaient les lignes construites depuis la constante (mesuré sur `e24c30f` : 184 verts avec l'intervalle à 1 h). Contrat sondé en production : `verify` d'une clé factice répond `200 {"valid":false,"reason":"not_found"}`. **`/pr-review` APPROVE** (37 mutations du relecteur, 35 rouges). Appliqué dans `b107cf4` : le test « une tentative non inscriptible n'envoie rien » (mutation de la revue : 0 rouge sur 185, puis 1 sur 187) et celui du verdict non inscriptible ; `storage` reformulé, puisqu'il couvre aussi un verdict non écrit. Décisions de Max le 10-03 : une clé révoquée **reste contrôlée** une fois par 24 h tant qu'elle est enregistrée, et c'est déclaré dans le guide (aucune interface ne retire une clé : seul l'enregistrement d'une autre l'arrête) ; la carte Mises à jour nomme la révocation, la page d'erreur non. Rust 168 → **187**, vitest 1314 → **1348**, CI lue dans les logs (runs 446/447 puis 449/450). Hors PR : la-compagnie-maximus#184 corrigée, son commentaire du 10-02 disant à tort que l'édition Gratuite ne fait jamais cette requête. **Non gardé par les tests** : l'effet du fournisseur React qui lance le contrôle, l'enregistrement de la commande dans `lib.rs` et la réponse réelle du serveur pour une clé révoquée, d'où la vérification manuelle. **Acquis** : la fermeture `match_request` de mockito tourne pendant que la requête est en vol, ce qui prouve un ordre « écrit avant la requête » ; une suite Rust rouge imprime `error: test failed`, donc seul `could not compile` signale une erreur de compilation. Aucune migration DB (v1→v17). (ref #365, PR #368, #367, la-compagnie-maximus#184)
- 2026-10-01 : **#350 mergée (PR #366, `main` `0a9c9f7`) — l'activation envoie un identifiant dérivé, et l'issue reste ouverte pour une vérification manuelle due avant le tag.** `/warmup` (audit quotidien vert, 10 runs d'affilée), puis `/analyze 350` : le corps du 09-24 n'avait jamais été édité (sa timeline ne porte que des références), et #270, #347 et le go-live l'avaient périmé sur quatre points — « avant go-live », « retomberaient en Gratuite » (faux depuis D12), `current_entitlements` qui ne compare plus rien au jeton, `get_machine_id` sans appelant. Trois sites manquaient : la suppression du jeton dans `deactivate_machine_impl`, le marqueur « Cette machine » de `LicenseCard`, et le Bearer des cours, qui envoie un jeton antérieur avec son claim brut. Décisions de Max : **D1** une machine déjà activée garde son activation (jeton brut accepté) ; **D2** le critère « aucun identifiant brut ne quitte le poste » est borné aux activations faites avec la version corrigée ; **D3** le client ne suppose rien du serveur. Deux suites ouvertes dans leurs dépôts : maximus-api#82 (identifiants bruts déjà stockés, lignes désactivées comprises) et la-compagnie-maximus#184 (la politique de confidentialité ne déclare aucune donnée d'activation). **Livré** : `derive_machine_id` (`HMAC-SHA256` sous la clé figée `com.simpl.resultat/license-machine-id/v1`, 64 caractères hexadécimaux, identifiant vide refusé) ; `MachineIds` (dérivé et brut) ; activation qui dérive juste avant l'appel et exige le dérivé dans le jeton reçu ; `is_this_machine` calculé côté Rust pour les deux formes ; règle de suppression du jeton à la désactivation ; `get_machine_id` retirée et `ActivationStatus` sans identifiant ; ADR 0020. Aucune dépendance ajoutée, `Cargo.lock` intact. **Écarts au corps de l'issue**, déclarés dans la PR : la règle de suppression est plus large que la phrase de l'issue (toute ligne de ce poste emporte le jeton, sauf l'ancienne ligne brute quand le jeton vaut pour la ligne dérivée), parce que la règle littérale laissait un jeton expiré sur le disque ; la liste, la désactivation et l'état d'activation n'échouent plus sur un identifiant du système illisible. Plan checker `pass` au premier tour, ses remarques mineures intégrées : tests épinglés sur les vecteurs en littéraux, « aucun appel » observé contre un mock et non déduit. **`/pr-review` APPROVE**, cinq suggestions appliquées dans `0a9c9f7` : la condition de retrait de l'ADR, reprise du corps de l'issue, comptait deux ans depuis la v0.15.0, or une v0.15.0 gratuite ne se met plus à jour et peut encore activer en brut des mois plus tard, donc la borne est la dernière émission d'un jeton brut, connue du serveur seul ; « plus aucune commande ne remet l'identifiant du système au webview » était plus large que le code (la liste porte encore la ligne brute d'une activation antérieure) ; deux lignes de test ; la seconde ligne que crée une réactivation tant que le serveur n'a pas rehaché ses lignes ; la vérification manuelle par la valeur et non par la longueur. **Preuves** : 17 mutations de l'auteur rouges ; la mutation de la revue restée verte remesurée à 0 rouge sur `e5662ad`, puis 1 rouge sur `0a9c9f7` ; vecteurs recalculés hors du code ; Rust 151 → **168**, vitest 1311 → **1314** ; CI lue dans les logs sur les deux têtes (runs 441 à 444). **Non gardé par les tests** : le câblage des commandes à l'identifiant réel du poste, d'où la vérification manuelle. **Acquis** : mockito sert le premier mock correspondant qui attend encore des hits, donc un mock `expect(0)` posé à côté d'un mock valide ne prouve rien ; un seul mock avec `match_request`. Merge par l'API en `fast-forward-only` épinglé sur la tête, branche supprimée. Aucune migration DB (v1→v17). (ref #350, PR #366, maximus-api#82, la-compagnie-maximus#184)
- 2026-09-30 : **#347 mergée (PR #364, ferme aussi #360) — l'édition ne dépend plus que de la clé, et deux revues ont trouvé ce que les tests ne gardaient pas.** `/analyze` (09-29) a revérifié le corps du 09-24 contre `main` et `maximus-api`, puis fait trancher deux décisions par Max. **D12** : le jeton d'activation ne fait plus jamais retomber en Gratuite. Une clé copiée sans son jeton gardait déjà son édition, donc la règle ne protégeait rien ; elle piégeait la restauration légitime de données (#360) et toute machine activée au bout des 2 ans du jeton. **D13** : clé révoquée = drapeau de session. Livré : `LicenseError` étendu aux erreurs de saisie (`invalid_prefix`, `invalid_signature`, `malformed`, `unknown_edition`), nommées à la source par `store_license_in` et `read_license_in` ; édition résolue depuis la seule `license.key` (`entitlements_from_dir`) ; `LicenseKeyForm` extrait ; compteur n/limite, dates `fr-CA`/`en-CA`, « Sans échéance » au-delà de 50 ans ; tests de #363 absorbés. **Écart au corps de l'issue** : le drapeau révoqué vit dans `LicenseContext`, parce que le plan checker a vu que le reducer du hook meurt avec la carte. **Revue 1 (APPROVE)** : 3 mutations vertes (état « Activée » non testé à son point de décision, filtre des erreurs sous Machines, coche verte) et un défaut préexistant, le jeton d'une clé précédente qui survivait à l'enregistrement d'une autre clé (« Activée » sans « Activer », cours refusés au nom de l'ancienne licence). Corrigés dans `3f90635` : `activation_status_in`, jeton supprimé au changement de clé, carte remontée par `licenseIdentity`, message `invalidSignature` qui renvoie d'abord à la copie (`jsonwebtoken` vérifie la signature avant de décoder la charge, donc une copie abîmée finit souvent en `InvalidSignature`). **Revue 2 (APPROVE)** : course activation / nouvelle clé, badge « Activée » d'une clé révoquée, renvoi de l'ADR ; corrigés dans `cdf4df8`. Preuves : reproduction rouge sur `5d549d6`, puis 27 + 8 + 4 mutations rouges ; Rust 128 → 151, vitest 1266 → 1311, CI vérifiée dans les logs à chaque tête. Trouvé en route : le 403 `license_revoked` des cours s'affiche comme « abonnement premium requis » (consigné sur #365). Merge par l'API en `fast-forward-only`, milestone `planned-2026-09-24-paiements` fermée 3/3. Aucune migration DB (v1→v17). (ref #347, #360, #363, PR #364)
## Blockers actifs
- Aucun blocker externe dur. `spec-monetisation` **fermée 12/12** (2026-07-08) — #50/#52/#53/#135/#136 livrées, ne sont plus des blockers.
- **Le paiement est live : « aucun tag avant le go-live » n'a plus de raison d'être, et la release desktop qu'attendait le go-live est publiée (v0.16.0, 2026-10-03).** Bascule live le 2026-09-29 (Product et Price live à 19 $ CAD, webhook, variables Stripe de production, redeploy `3673d09` de maximus-api, URL `cs_live_` vérifiée), puis achat réel de contrôle le 2026-09-30 : clé sur `/merci` et par courriel, activation dans l'app, remboursement complet et licence révoquée par `charge.refunded`. **Volet serveur clos le 2026-10-03** (derniers commentaires relus le 2026-10-04) : maximus-api#62 fermée, tous critères cochés (maximus-api 0.4.2 en prod, secrets en runtime seul), avec la milestone `spec-paiements` de maximus-api (12/12) ; la-compagnie-maximus#150 (Link dans les textes légaux) livrée et fermée le 2026-10-01. **Clôture du go-live = la-compagnie-maximus#141** (`status:blocked`), qui n'attend plus que ce dépôt : l'updater vérifié (Free refuse et invite à acheter, Base accepte), #350 étant fermée depuis le 2026-10-04. la-compagnie-maximus#184 (politique de confidentialité : données d'activation, contrôle au démarrage) est en `status:review` ; sa PR reste en brouillon jusqu'au déploiement de maximus-api#85 (commentaire du 2026-10-03). Les deux textes des suites de licence (contrôle à la saisie, retrait de la clé) y sont postés depuis le 2026-10-05 (commentaire 19724). **Vérifications manuelles sur la release publiée, toutes faites** : #365 le 2026-10-03, #346 et #350 le 2026-10-04 (voir Décisions). Reste l'étape 10 de `/release` sous Windows (Michel).
- **Vérifications post-merge de #390** (PR #394, sur le prochain build) : la case 5 se coche après un classement manuel ; sous Linux, un vrai profil secondaire ancien affiche « database updated with versions … » au Journal, sa copie est dans `~/.config/com.simpl.resultat/migration-backups/` et l'import y fonctionne ; supprimer un profil retire son `.db` ; les rendements du Bilan s'affichent. #390 reste en `status:blocked` jusque-là.
- **Vérifications manuelles dues sur la v0.17.0 publiée** (onboarding + suites de licence ; Linux puis Windows), dans un ordre qui ne détruit le jeton d'activation qu'à la fin de ce qui en dépend : (1) #370, machine activée hors ligne → « Retirer la clé » : seconde confirmation qui donne la raison, Annuler ne change rien, sauts de ligne des fenêtres ; (2) #367, s'il existe un second poste avec la même clé : y désactiver ce poste, puis ouvrir ici la liste des machines → « Activer » revient sans recharger, ligne au Journal ; (3) #370 en ligne → place libérée, carte en Gratuite ; (4) #373 et #370 avec la clé révoquée du 2026-09-30 : Base une à deux secondes puis Gratuite, ligne « License check: the license server says the key was revoked » ; retirée → aucune désactivation envoyée, puis au redémarrage « no valid key stored, nothing sent » ; ressaisie → reste en Gratuite ; (5) clé testeur Premium ressaisie, « Activer », `verif-350.py` rend `64 brut: False dérivé: True` ; (6) #367, dossier v0.15.0 (clé A à côté du jeton d'une licence B révoquée) : couvert par un test de bout en bout, à faire seulement si un tel dossier existe encore. Plus la liste QA de l'onboarding (`docs/qa-onboarding.html`).
- **Vérifications manuelles dues sur la prochaine release : parcours de démarrage guidé** (#396 à #401, milestone `planned-2026-10-06-onboarding-parcours-guide`), d'abord sous Linux avec Orca, puis sous Windows avec NVDA : les sections « Parcours guidé » de `docs/qa-onboarding.html` (profil neuf de bout en bout, bandeau et liste, « Passer » et « Reprendre », règle D9 sur un vrai profil ancien, édition Gratuite à 5/5, contour dans WebKitGTK et WebView2, mouvement réduit, clavier, annonces). #401 se ferme au merge ; la liste de la phase 1 pour la v0.17.0 reste lisible par `git show v0.17.0:docs/qa-onboarding.html`.
- Backlog ouvert : **vague `planned-2026-09-24-paiements` close 3/3** (milestone fermée le 2026-09-30) : #270 (PR #359) et #346 (PR #362) mergées le 2026-09-27, #347 (PR #364, ferme aussi #360) mergée le 2026-09-30 ; volet site **clos** (maximus/la-compagnie-maximus#153, redirection de `/simpl-resultat` en prod). **#365 fermée le 2026-10-03** après sa vérification manuelle. **Milestone `planned-2026-10-03-suites-licence` fermée 3/3 le 2026-10-05** (#373, #370, #367 mergées, voir Décisions ; suivi #389 en `status:triage`). Hors milestone, en `status:ready` : **#369** (réserver le fractionnement de transactions à l'édition Base) et **#372** (la liste complète des versions repousse le Journal en bas de Paramètres → Systèmes). **#350 fermée le 2026-10-04** (étape 3 vérifiée en production, voir Décisions) ; reste de #363 (plafond de `/issue-license` à 36525 jours et essai d'une vraie clé de 100 ans, débloqués par le déploiement de maximus-api#63) ; réglés côté serveur et site : maximus-api#63 (clés de 100 ans) et maximus-api#70 (réactivation d'une machine désactivée), fermées et contenues dans `3673d09`, le commit déployé à la bascule du 2026-09-29, et la-compagnie-maximus#157, fermée, dont les CGV sont publiées en tronc commun plus annexe Simpl-Résultat (annexe relue en production le 2026-09-30, plus aucune durée de 10 ans) ; côté serveur, `/v1/prices` ne vérifie pas qu'une machine est encore active (une machine désactivée garde les cours jusqu'à l'expiration de son jeton), issue maximus-api à ouvrir ; suites de #350 ouvertes le 2026-10-01 : maximus-api#82 (`status:triage` : identifiants machine bruts déjà stockés, lignes désactivées comprises ; à rehacher avant l'expiration des premiers jetons bruts, sinon une réactivation crée une seconde ligne) et la-compagnie-maximus#184 (`status:review`, voir ci-dessus) ; clôture du go-live = la-compagnie-maximus#141 seule, maximus-api#62 étant fermée ; `spec-paiements` reste le parapluie des trois dépôts (ici 4/5, reste #363) ; onboarding phase 1 **livrée** : milestone `planned-2026-10-03-onboarding-phase1` fermée 7/7 le 2026-10-04 (#351 à #357, mergées en avance rapide, `667e058`) ; suivis ouverts : **#384** (`status:ready`, suivis non bloquants des revues) et **#371** (`status:blocked`, hors `/autopilot` : en-têtes CSV BMO à fournir par Max depuis un compte réel, un par type de compte, chèques/épargne et Mastercard, avec des valeurs fictives) ; analyse d'origine dans `docs/analyse-onboarding-2026-09.md`, plan détaillé dans les `spec-*-onboarding-phase1.md` locaux, ignorés par git ; #271 absorbé par #301, livré ; `spec-ci-build-optimization` **fermée 4/4** le 2026-10-05 (#232 livrée le 2026-07-27 ; #234 close le 2026-10-05 avec ses quatre preuves : dispatch run 464, PR #386 run 480, run planifié 488, `actcache` à 999 Mo) ; **#376** (`status:triage` : Node 20, en fin de vie depuis le 2026-04-30, encore installé par `check-frontend.yml` et `audit.yml`, et commentaire `concurrency` de `check-rust.yml` démenti par `forgejo-ops.md` pour les runs de PR). Le suivi « glob `src-tauri/**` non prouvé » ouvert avec #232 est **levé** : la PR #344 est le cas test isolé attendu (`Cargo.lock` + 2 `.md` seulement) — `check-rust` a bien tourné, `check-frontend` a bien été sauté par sa denylist.
- **Vérifications manuelles dues sur la prochaine release : parcours de démarrage guidé** (#396 à #401, milestone `planned-2026-10-06-onboarding-parcours-guide`), d'abord sous Linux avec Orca, puis sous Windows avec NVDA : les sections « Parcours guidé » de `docs/qa-onboarding.html` (profil neuf de bout en bout, bandeau et liste, « Passer » et « Reprendre », règle D9 sur un vrai profil ancien, édition Gratuite à 5/5, contour dans WebKitGTK et WebView2, mouvement réduit, clavier et anneau de focus du contrôle entouré, annonces, et les limites connues renvoyées par les revues). Le même build sert aux vérifications post-merge de #390. #401 se ferme au merge ; la liste de la phase 1 pour la v0.17.0 reste lisible par `git show v0.17.0:docs/qa-onboarding.html`.
- Backlog ouvert : **vague `planned-2026-09-24-paiements` close 3/3** (milestone fermée le 2026-09-30) : #270 (PR #359) et #346 (PR #362) mergées le 2026-09-27, #347 (PR #364, ferme aussi #360) mergée le 2026-09-30 ; volet site **clos** (maximus/la-compagnie-maximus#153, redirection de `/simpl-resultat` en prod). **#365 fermée le 2026-10-03** après sa vérification manuelle. **Milestone `planned-2026-10-03-suites-licence` fermée 3/3 le 2026-10-05** (#373, #370, #367 mergées, voir Décisions ; suivi #389 en `status:triage`). Hors milestone, en `status:ready` : **#369** (réserver le fractionnement de transactions à l'édition Base) et **#372** (la liste complète des versions repousse le Journal en bas de Paramètres → Systèmes). **#350 fermée le 2026-10-04** (étape 3 vérifiée en production, voir Décisions) ; reste de #363 (plafond de `/issue-license` à 36525 jours et essai d'une vraie clé de 100 ans, débloqués par le déploiement de maximus-api#63) ; réglés côté serveur et site : maximus-api#63 (clés de 100 ans) et maximus-api#70 (réactivation d'une machine désactivée), fermées et contenues dans `3673d09`, le commit déployé à la bascule du 2026-09-29, et la-compagnie-maximus#157, fermée, dont les CGV sont publiées en tronc commun plus annexe Simpl-Résultat (annexe relue en production le 2026-09-30, plus aucune durée de 10 ans) ; côté serveur, `/v1/prices` ne vérifie pas qu'une machine est encore active (une machine désactivée garde les cours jusqu'à l'expiration de son jeton), issue maximus-api à ouvrir ; suites de #350 ouvertes le 2026-10-01 : maximus-api#82 (`status:triage` : identifiants machine bruts déjà stockés, lignes désactivées comprises ; à rehacher avant l'expiration des premiers jetons bruts, sinon une réactivation crée une seconde ligne) et la-compagnie-maximus#184 (`status:review`, voir ci-dessus) ; clôture du go-live = la-compagnie-maximus#141 seule, maximus-api#62 étant fermée ; `spec-paiements` reste le parapluie des trois dépôts (ici 4/5, reste #363) ; onboarding phase 2 (parcours guidé) **mergée** : milestone `planned-2026-10-06-onboarding-parcours-guide` fermée 6/6 le 2026-10-08 (#396 à #401, `ee17f31`), suivis **#408** et **#409** (`status:triage`) ; onboarding phase 1 **livrée** : milestone `planned-2026-10-03-onboarding-phase1` fermée 7/7 le 2026-10-04 (#351 à #357, mergées en avance rapide, `667e058`) ; suivis ouverts : **#384** (`status:ready`, suivis non bloquants des revues) et **#371** (`status:blocked`, hors `/autopilot` : en-têtes CSV BMO à fournir par Max depuis un compte réel, un par type de compte, chèques/épargne et Mastercard, avec des valeurs fictives) ; analyse d'origine dans `docs/analyse-onboarding-2026-09.md`, plan détaillé dans les `spec-*-onboarding-phase1.md` locaux, ignorés par git ; #271 absorbé par #301, livré ; `spec-ci-build-optimization` **fermée 4/4** le 2026-10-05 (#232 livrée le 2026-07-27 ; #234 close le 2026-10-05 avec ses quatre preuves : dispatch run 464, PR #386 run 480, run planifié 488, `actcache` à 999 Mo) ; **#376** (`status:triage` : Node 20, en fin de vie depuis le 2026-04-30, encore installé par `check-frontend.yml` et `audit.yml`, et commentaire `concurrency` de `check-rust.yml` démenti par `forgejo-ops.md` pour les runs de PR). Le suivi « glob `src-tauri/**` non prouvé » ouvert avec #232 est **levé** : la PR #344 est le cas test isolé attendu (`Cargo.lock` + 2 `.md` seulement) — `check-rust` a bien tourné, `check-frontend` a bien été sauté par sa denylist.
- Suivis des advisories : **#312, #313 et #315 fermées le 2026-08-15** (PRs #321/#322 mergées). **#314 fermée le 2026-08-15, prémisse infirmée** — elle affirmait « zéro run `schedule` », or `audit.yml` tire tous les jours à 06:00 UTC (**19 runs `schedule` verts** du 07-28 au 08-15, sans trou) ; elle a été écrite le 07-27 vers 23:56Z, ~6 h avant le premier tir programmé possible, et décrivait donc une fenêtre trop courte, pas un scheduler en panne. Ces 19 runs confirment au passage que `.cargo/audit.toml` est bien lu en conteneur **sur `main`** — l'ADR 0018 ne l'avait vérifié que par un `workflow_dispatch` sur une branche. **#343 fermée le 2026-09-04** (PR #344) — RUSTSEC-2026-0258 sur `h2`, la seule vulnérabilité qui rougissait l'audit depuis le 08-19 ; l'audit est de nouveau vert sur `main`, prouvé par `workflow_dispatch` (run 393) et non déduit du run de PR. **#348 fermée le 2026-09-21** (PR #349) — RUSTSEC-2026-0285 sur `rustls`, seule vulnérabilité rougissant l'audit depuis le 09-15 (7 runs, 405→411) ; vert reprouvé par `workflow_dispatch` sur `main` (run 414 : 666 paquets, zéro vulnérabilité, 12 warnings autorisés). Deux advisories en cinq semaines sur le même chemin, celui de la mise à jour automatique. Restent **#317** (prémisse caduque depuis le 2026-09-26 : `react-router-dom` 7.18.2 et suivantes corrigent l'advisory par un bump de patch dans `^7.18.1`, sans migration v8 ; absorbée par #358, dont la PR la fermera), **#319** (déclencheur de retrait pour `rsa`, désormais **seule** entrée de `.cargo/audit.toml` — le garde-fou est passé à 2 vérifications) et **#345** (domicilier la contrainte `windows-sys 0.61.2` — analysée le 09-04 : le corps d'origine, écrit de mémoire en fin de revue, se trompait sur trois points. Le déclencheur n'est pas « n'importe quel `cargo update` » mais tout bump atteignant le sous-arbre réseau/TLS — mesuré : `-p anyhow` ne bouge rien, `-p hyper` fait descendre les 7 — soit précisément là où tombent les advisories. **Prémisse restreinte le 2026-09-21 par #348** : `-p rustls`, au cœur de ce même sous-arbre, n'en déplace **aucun** — le déclencheur tient à `hyper` et à ce qu'il tire, pas à la couche TLS en général, donc « sous-arbre réseau/TLS » prédit une dérive là où il n'y en a pas et ferait écrire une strophe à la main sans nécessité. D'où la suggestion portée en commentaire sur l'issue : formuler le garde-fou sur la **version résolue de `windows-sys`** plutôt que sur une liste de crates déclencheurs — la liste est ce qui vient d'être trouvé faux, la version est ce qui est protégé. #310 avait **bien** vu la dérive et l'avait jugée inoffensive *sur Linux*, où elle l'est ; son coût tombe sur le build Windows que personne ne mesurait : **3 versions de `windows-sys` compilées contre 5**. Aucun risque de correction — les 7 crates déclarent des bornes larges couvrant les deux états. Et cargo annonce « Locking 1 package » en écrivant 8 changements, donc le silence est le sien. Décision : garde-fou CI sur la version + ADR portant la condition de sortie. Le check croisé Windows depuis Linux a été **testé et écarté** — `cc-rs` s'arrête sur `lib.exe`, il faudrait `cargo-xwin`). Côté npm, **#358** ouverte le 2026-09-26 par `/analyse-vulnerabilite` : `npm audit` remonte 7 findings (4 high, 3 moderate) sur 4 dépendances racines, contre les 2 acceptés au 07-27, et chaque correctif tient dans la borne déjà déclarée ; le lock se régénère avec `npx npm@11` (npm 10 plante sur un bump de vitest 4.1.x).
- Nouveau bug ouvert : **#320** — les installations `.rpm` ne reçoivent aucune mise à jour (`latest.json` ne porte qu'une entrée `linux-x86_64` construite depuis le `.deb`, `release.yml:104-122`), alors que les `.rpm` continuent d'être publiés en assets. Documenté en §3 de `docs/qa-update-cycle.md` (« ne pas tester : cassé, pas seulement non vérifié »).
- Suivis ouverts du chantier import (milestone fermée) : le refus du format « montant absolu + indicateur D/C » ne scanne que `amountCol ± 1`, donc une colonne D/C placée ailleurs passe encore ; dérives de comptes préexistantes dans `CLAUDE.md` et `docs/architecture.md` (composants, pages, services, `Version actuelle : 0.6.3` vs tag v0.14.0) mesurées et documentées en revue, non corrigées.