50 KiB
STATE — Simpl'Résultat
Derniere MAJ : 2026-09-27 (#346 mergée — PR #362,
main170b22d, merge API enfast-forward-only, SHA inchangés. « Obtenir Base » actif sur les écrans Base (page produit localisée), Premium désactivé avec une note honnête, parcours d'achat et « Télécharger la dernière version » en Gratuite, texte de la carte Compte./pr-reviewAPPROVE, ses suggestions appliquées dans170b22davec preuve du rouge : 12 mutations rejouées sur la tête finale, 11 rouges, la 12e demande un clic et reste à vérifier à la main ; 1257 → 1266 vitest, CI vérifiée dans le log (run 430). Contrainte de release : aucun tag tant que la-compagnie-maximus#141 et maximus-api#62 sont ouvertes, le checkout du site étant en mode test. Vague desktop à 2/3, reste #347.)Précédente MAJ : 2026-09-27 (#270 mergée — PR #359,
main0c9b8f8, merge API en rebase ff, SHA inchangés. Chemins/v1+product, contrat d'erreurLicenseError(JSON{code}commeFetchPriceError) et 14 messages FR/EN, hookuseLicenseMachinesà reducer testé, URL d'achat localisée. Trois passes/pr-review(APPROVE ×3), leurs 12 suggestions appliquées avec preuve du rouge ; 111 → 128 Rust, 1181 → 1246 vitest, CI vérifiée dans les logs à chaque tête. La 3e revue a trouvé un défaut serveur : réactiver une machine déjà désactivée répond 500 (contrainteuq_license_machinesans condition suris_active) → maximus-api#70, prérequis du go-live. Et #360 : un jeton d'une autre machine (réinstallation, migration de poste) bloque en Gratuite sans issue dans l'interface. Vague desktop à 1/3 (#346 → #347) ; volet site clos (la-compagnie-maximus#153, redirection de/simpl-resultaten prod).)
Position actuelle
v0.9.1 shippée (2026-05-10). Milestones spec-refonte-rapports, spec-refonte-seed-categories-ipc, spec-price-fetching, overnight-2026-04-26-bilan et overnight-2026-04-27-prices complétées et fermées. Maximus-api 0.3.0 LIVE en prod (api.lacompagniemaximus.com) — pubkey Ed25519 alignée, smoke test Phase B (#161) validé. Backlog actif concentré sur spec-monetisation (7/12) : activation en ligne (#53), pipeline Stripe desktop (#50, #52) et maximus-api Stripe webhooks (#135, #136).
Audit critique de la page Bilan livré (docs/audit-bilan-2026-05.md, revue CPA + UX). Étape 0 — quick wins terminologie « catégorie »→« type », symbole optionnel, date de snapshot déplaçable — mergée (#201, issues #198/#199/#200 fermées). Chantier structurel = Étapes 1-2 de l'audit (séparation véhicule fiscal × classe d'actif via vehicle_type, puis détail par titre balance_securities+holdings+book_cost, bascule agrégé→détaillé, réouverture ADR 0012). Étape 1 livrée (sprint 2026-06-01 : PRs #206-#209 mergées, milestone overnight-2026-06-01-bilan-axe-vehicule fermée 4/4) — vehicle_type nullable = enveloppe fiscale portée par le compte, catégorie = pure classe d'actif (5 classes), migrations additives v12/v13 (v1-v11 intactes), renommage via custom_label (fix bug I), axe graphique classe/enveloppe + rendements repliables persistés ; ADR 0014 Accepted, ADR 0012 Rejected. CHANGELOG sous [Unreleased] (pas encore taggé). Étape 2 livrée (merge manuel 2026-06-09 : pile de 9 PRs stackées #219-#227 mergées bottom-up, milestone overnight-2026-06-05-bilan-detail-titres à 9/10, issues #210-#218 fermées) — détail par titre via balance_securities + balance_snapshot_holdings, balance_accounts.kind ('simple'|'detailed') + detailed_since, migrations additives v14/v15/v16 (v1-v13 intactes), conversion des comptes cotés existants en détaillés 1-position (v16), service securities transactionnel, reducer holdings + dispatch account.kind, UI multi-titres (SecurityPicker), assistant détailler-un-compte (date pivot), drill-down par titre + gain latent, tests intégration/régression ; ADR 0015 Accepted. #228 mergé (PR #229, fix-forward : garde d'abort v16 scopée aux comptes convertibles via JOIN balance_categories + c.asset_type IS NOT NULL dans les 3 copies — Migration v16 / V16_SQL / V16_CORRUPT — + test régression ; CI vert car #229 ciblait main) → milestone overnight-2026-06-05-bilan-detail-titres complète 10/10 et fermée. v0.10.0 shippée (2026-06-29 : Étapes 1+2 du bilan, migrations v12→v16) puis hotfix v0.10.1 (2026-06-30, PR #230, déployé) — corrige un « database is locked » introduit en 0.10.0 (apparaissait après l'abandon d'un snapshot en cours) : tout l'accès DB est désormais sérialisé via withTransaction dans db.ts (tauri-plugin-sql = pool sqlx multi-connexions sans primitive de transaction JS → BEGIN/COMMIT en db.execute séparés pouvaient strander une transaction d'écriture = verrou zombie), appliqué aux 5 sites transactionnels ; + console de log live-update + API logInfo/logWarn/logError. 20 tables / 24 index, 16 migrations (v1→v16).
Milestone deps-security-2026-07 livrée (2026-07-01, 4/4 fermée) — 4 vulns de dépendances Defenseur remédiées en 2 PRs (#239 react-router-dom 7.18.1 ; #240 vite 6.4.3 + vitest 4.1.9) ; npm audit 5→0 — le dernier @babel/core low remédié le 2026-07-04 (override scopé @vitejs/plugin-react→@babel/core@^7.29.7, issue #241 / PR #242 mergée). Ce « 0 » n'est plus l'état courant : des advisories publiées depuis l'ont ramené à 3, traitées en #311 le 2026-07-27 → 2 restantes, acceptées (react-router, cf. entrée du jour). Nouveau milestone spec-ci-build-optimization (2/4) ouvert (baseline #231 : cause #2 = reserveCache timeout du runner ; #234 connectivité cache VPS, #232 split workflows).
v0.11.0 shippée (2026-07-05, tag v0.11.0 → CI release Windows/Linux + JSON updater) — milestone overnight-2026-07-05-bilan-rapports-ux complétée 5/5 et fermée via un run /autopilot (5 workers séquentiels, PRs #248-#252 toutes /pr-review APPROVE, puis merge local de la pile + réconciliation Forgejo). Contenu : rapport comparable réel-vs-réel hiérarchique avec sous-totaux (#247) ; netting des transferts ciblé (catégories type transfer → SUM signé ~0, autres types inchangés au byte) dans le compare (#243) ; landing Bilan en tuiles HubReportNavCard + guard empty-state découplé + gestion comptes accessible partout (#244) ; import CSV de titres dans un snapshot détaillé (front pur, autoDetectHoldingColumns, prix flexible) (#245) ; cible de migration catégories éditable sur chaque ligne + type-ahead CategoryCombobox feuilles-seulement (#246). Aucune migration DB (v1→v16 inchangées), 20 tables / 24 index, 16 migrations. Point de suivi non bloquant : nets de transfert signés traversent du code UI compare pensé pour des magnitudes positives (mord seulement les transferts déséquilibrés à une jambe).
v0.12.0 shippée (2026-07-05, tag v0.12.0 → CI release #311) — recadrage de #243 (montants de transfert inclus dans le comparable) par Max en « analyse de résultat » : deux rapports comparables refondus en états de résultat (income statement). Le compare réel-vs-réel (#253) et le tableau de tendance par catégorie (#256) affichent le revenu, un Résultat avant transferts (revenus − dépenses) et un Résultat net (après transferts), sections ordonnées revenu→dépense→transfert ; les rapports comparables ouvrent par défaut sur le mois complet précédent (#253). Modules purs extraits et testés (compareResults.ts, overTimeResults.ts) ; 2 blocages /pr-review corrigés (fuite du revenu dans les top-movers Cartes ; garde StrictMode sur le sync du mois de référence). Livré en 2 issues/PRs stackées #255→#257 (merge local + réconciliation Forgejo, branches supprimées), 701 vitest verts, aucune migration DB (v1→v16 inchangées), 20 tables / 24 index. Backlog ouvert au passage : #258 (db-locked proposeStarterAccounts) → fermé le 2026-07-07 (déjà corrigé v0.10.1, pas de nesting) ; #254 (collapse/expand) → livré le 2026-07-07 (PR #261) ; #259 (mapping manuel d'un compte standard sans similaire auto) et #260 (epic « rapports uniformes » — tous les rapports sur le modèle income-statement) ouverts.
v0.15.0 shippée (2026-09-12, tag v0.15.0 → CI release run 402, 7 artefacts + latest.json vérifiés) — première version où le gating par édition est actif : sans clé, Budget, Ajustements, rapports avancés, profils multiples, Bilan et mises à jour automatiques sont verrouillés (données intactes, ADR 0017). Les deux testeurs (Max, Michel) ont une clé Premium émise avant le tag. [Unreleased] vide. Aucune migration DB nouvelle (v1→v17). Étape 10 de /release consignée le 2026-09-13 : cycle réel v0.14.0 → v0.15.0 validé par les deux testeurs, trace rédigée pour le corps de la release Forgejo (invite polkit Linux non consignée, .rpm hors test → #320).
Decisions recentes
- 2026-09-27 : #346 mergée (PR #362) — « Obtenir Base » ouvre enfin la page produit, et la revue a trouvé que le câblage des boutons n'était gardé par aucun test. Livré par la PR :
upsellCtaFor(règle pure : Base achetable, Premium désactivé avec la note « pas encore offert en ligne ») ;PurchaseButton,HaveKeyButton(rendu seulement sous un routeur, viauseInRouterContext) etDownloadLatestButtonpartagés ;UpsellGatesuit la règle etProfileFormModalle réutilise (fin du mode upsell compact) ; carte Mises à jour et page d'erreur en Gratuite ; texte de la carte Compte tranché le 09-24 ; amendement de l'ADR 0017./pr-reviewAPPROVE, avec un constat principal : la PR supposait que sans jsdom seules les fonctions pures se testent, orrenderToStaticMarkuptourne dans l'environnement node de vitest etFilterPanel.test.tsxappelait déjà un composant comme une fonction ; six mutations des composants passaient la suite sans un rouge. Appliqué dans170b22d: 9 tests de rendu (UpsellCtas.render.test.tsx) ; unlogErrorsur l'échec d'openUrldans les trois sites qui ouvrent la page produit (initLogCapturene capte pasunhandledrejection, donc rien n'arrivait dans Journaux) ; un commentaire dansupsellCtaFor(le bouton ne vend que Base, donc rendre Premium achetable sans lui donner le palier ferait vendre Base sur le Bilan) ; la réserve sur la carte Compte dans l'ADR (check_account_editionaccorde encore Premium à un abonnement actif, chemin dormant tant qu'aucun abonnement n'est vendu) ; l'étape d'achat placée avant la saisie de la clé dans le guide et les docs intégrées ; trois corrections de CHANGELOG. Preuve : 12 mutations rejouées sur la tête finale dans un worktree jetable (npm ci), 11 rouges avec code de sortie 1. La 12e (ProfileFormModalsansonNavigate={onClose}) demande un clic et reste à vérifier à la main ;LicenseCardn'a pas de test, ses hooks réels empêchent de l'appeler comme une fonction. Merge par l'API enfast-forward-onlyépinglé surhead_commit_id, #346 fermée parFixes. Aucune migration DB (v1→v17). (ref #346, PR #362) - 2026-09-27 : #270 mergée (PR #359) — le client de licence parle
/v1, nomme chaque refus, et trois revues ont trouvé ce que les tests ne gardaient pas./fix-issue 270sur le corps réécrit par le/plan-rundu 09-24. Plan vérifié par le plan checker en 2 itérations (la 1re : un refus serveur sur cinq sans test). Livré :POST /v1/licenses/{activate,deactivate,verify}avecproductet clé rognée dans*_inner;LicenseErrorsérialisé{code}commeFetchPriceError, lu danserror.codede l'enveloppe (un 404 n'est jamais « route absente » ; un 404 sans code connu estserver) ; verify répond toujours 200, donc{valid:false}devient une erreur codée au lieu de la liste vide qui affichait « Aucune machine activée » pour une clé révoquée ; corps d'un non-2xx lu sans exiger de JSON (page HTML 502 →server), corps 2xx illisible →invalid_response. TS :parseLicenseError+ table vers 14 cléslicense.errors.*(pluriels i18next pour le délai), wrappers typés{ok, value|error}, hookuseLicenseMachinesà reducer exporté (erreur d'activation distincte de l'erreur de liste, parcours limite de machines en 4 requêtes sous le 5/min/IP du serveur, boutons inactifs pendant une désactivation ou un rechargement),purchaseUrldanssrc/shared/. Désactivation idempotente (no_active_activation= fait), écart assumé et documenté. Méthode : chaque défaut d'origine réintroduit sur l'arbre final et compté en rouge (11 mutations) ; puis 3 passes/pr-review, toutes APPROVE, dont les mutations ont trouvé 7 comportements corrects mais non gardés (un 404 lu comme clé introuvable, une table de messages comparée à elle-même, l'idempotence qui avalelicense_not_found, la relecture du statut après désactivation,machine_nameànull, un 2xx illisible, deux courses de boutons) — chacun épinglé puis prouvé rouge. Une puce du CHANGELOG retirée (l'édition ne change pas visiblement après une activation) et une reformulée (l'ancienne URL est redirigée par le site depuis la-compagnie-maximus#153). Hors PR, trouvés en route : maximus-api#70 (réactivation d'une machine déjà désactivée → 500 ;UNIQUE(license_id, machine_id)sans condition suris_active+INSERTsansonConflict; reproduit sur Postgres embarqué ; upsert recommandé, sans migration ; ajouté comme prérequis sur maximus-api#62) ; #360 (jeton d'une autre machine → Gratuite, section Machines masquée, ressaisie de clé inopérante ; trois pistes,status:triage). Merge par l'API (rebase ff,main0c9b8f8). Aucune migration DB (v1→v17). (ref #270, PR #359, #360, maximus-api#70) - 2026-09-24 : Vague paiements planifiée via
/plan-run spec-paiements— deux milestonesplanned-2026-09-24-paiements, un défaut de licence trouvé en revue, et des clés de 100 ans. Préambule :/warmup(audit quotidien vert, runs 415/416), puis commit des skills en attente depuis le 09-13 (11e12ab:/issue-license,verify-release.sh, garde « clés testeurs avant le tag » de/release) — le courriel personnel de Michel retiré avant le premier commit : le dépôtSimpl-Resultatest public et l'adresse n'était dans aucun fichier suivi ; celui de Max conservé, déjà présent dans 3 fichiers suivis. Le classifier a refusé de chargerpurge-secret-forgejo(« Git Destructive ») : scan des lignes ajoutées fait à la main. Étape 0 : spec d'origine dans la-compagnie-maximus (07-11), corps issus de/analyze 270(09-13) jamais passés en/review-spec, donc toutes les affirmations revérifiées contre le code et la prod. Résultats :verifyrépond toujours 200 ({valid:false}→ le client affiche « Aucune machine activée » pour une clé révoquée) ; un 404 d'activate est unlicense_not_foundmétier, pas une route absente ;ErrorPageest hors routeur ;machine_limitest déjà dans le JWT local ; le 429rate_limit_exceededn'était traité nulle part ;FetchPriceErrorest le modèle d'erreur à reproduire. Décisions de Max D1-D8 : #153 dans la vague (seule réparation du bouton « Acheter » des v0.15.0 gratuites, qui ne recevront jamais #270) ; 409 → message + liste dépliée via verify ; note Premium « pas encore offert en ligne » ; texte exact de la carte Compte ;removeLicenseretirée ; Windows d'abord sans détection ; #270 établit le contrat des codes d'erreur ; périmètre inchangé./review-spec(3 experts) → 🔴 : la tâche D2 effaçait le message 409 (loadMachines()commence parsetMachineError(null)) et « Aucune machine » restait affichée en erreur ; le repliactivateError(« Activation failed » en EN) contredisait #270. Constats chiffrés revérifiés à la source, aucun réfuté. Le défaut de fond :signActivationJwtsigne le jeton d'activation pour 2 ans, la clé pour 10, et le client valide le jeton avecstrict_validation()→ une machine qui a cliqué « Activer » retombe en Gratuite au bout de 2 ans, alors qu'une clé jamais activée garde son édition ; « Activer » ne rappelait pasrefresh(). D10 : un jeton expiré mais signé pour cette machine compte comme absent (#347), ce qui corrige aussi les jetons déjà émis. Durée des clés : retirer l'expiration est impossible (tous les binaires installés exigentexp, CWE-613) ; 100 ans passe partout, et les 10 ans de la décision #15 n'étaient que le maximum du schéma de/generate→ D9 : 100 ans hors vague (maximus-api#63, et la-compagnie-maximus#157 pour les CGV, dont « mises à jour pendant sa durée » est à reformuler) ; l'état « clé expirée le {date} » est abandonné, « Sans échéance » au-delà de 50 ans. D11 : lien « Télécharger la dernière version » en Gratuite, sans appel réseau. Lot de 9 corrections intégré : hookuseLicenseMachinesà reducer testé,PurchaseButtonpartagé, délai de 5 s et repli complet côté site, routes/telecharger/*et replilatest.jsonretirés, redirection sans langue, etc. Mécanique : milestones créées (simpl-resultat id 87, site id 88) plutôt que renommage despec-paiements, qui reste le parapluie des trois dépôts ; #350 ouverte (hachage HMAC de l'identifiant machine, avant go-live). Step 9 vérifié sur l'état réel de Forgejo. Gotcha skills :plan-runStep 6bis laisse entendre qu'un seul/autopilot <nom>couvre deux milestones homonymes, maisautopilotrefuse le multi-dépôts (SKILL.md:53) → un run par dépôt. Aucune migration DB (v1→v17). (ref #270, #346, #347, #350, la-compagnie-maximus#153/#157, maximus-api#63) - 2026-09-21 : RUSTSEC-2026-0285 (
rustls) corrigée — l'audit quotidien rouge depuis 7 jours, et la prémisse de #345 restreinte par la mesure. Trouvée au/warmup:audit.ymléchouait tous les matins depuis le 2026-09-15 (runs 405→411), dernier vert le 404 du 09-14, sans aucun push surmain— le dernier commit était97ee3c3du 09-13. Une seule vulnérabilité : RUSTSEC-2026-0285 / GHSA-2mjx-qc3c-rqvc,rustls0.23.36, datée du 09-14, CVSS 5.3 medium, vecteurC:L/I:N/A:N. L'advisory est parue après le tir du 09-14 à 06:00 UTC, d'où un premier rouge dès le lendemain — propagation plus rapide que les deux jours deh2. Ce n'est pas un contournement : rustls acceptait des messages de poignée de main TLS 1.3 au mauvais niveau de chiffrement lorsqu'ils suivaient un changement de clé dans le même enregistrement (unEncryptedExtensionsen clair collé auServerHello), là où la RFC 8446 §5.1 impose de fermer la connexion ; la transcription restant authentifiée, un attaquant en position réseau ne peut ni altérer ni compléter une poignée de main. Atteignabilité par triple explicite, jamais--target all: arbre identique sur les deux cibles livrées, mais un seul chemin —tauri-plugin-updater → reqwest 0.13.2, la mise à jour automatique. Plus étroit qu'h2en #343 : lereqwest 0.12.28déclaré enCargo.toml:43(licence, auth, cours, rétroaction) passe parhyper-tls → native-tls → opensslet est absent de l'arbre inverse derustls. Correctif publié + crate atteignable = règle 1 de.cargo/audit.toml: corrigé, pas suppressé ; ni le fichier de suppressions ni le garde-fou (CRATES="rsa") ne bougent. Le piège attendu ne s'est pas produit, et c'est le résultat intéressant : #345 annonce que tout bump atteignant le sous-arbre réseau/TLS fait redescendre les 7 pointeurswindows-sysde0.61.2— orcargo update -p rustls --precise 0.23.45n'en a déplacé aucun. Le déclencheur tient àhyperet à ce qu'il tire, pas à la couche TLS en général ; le corps de #345 est donc trop large et un commentaire l'y consigne, avec une suggestion : formuler le garde-fou sur la version résolue dewindows-sysplutô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é. Conséquence pratique : aucune strophe écrite à la main, la sortie de cargo est conservée, donc les checksums viennent de l'index et non du rédacteur.rustls-webpki0.103.13 → 0.103.15 l'accompagne et est requis : 0.23.45 resserre sa borne de^0.103.5à^0.103.14, même forme que lehttp ^1 → ^1.1relevé par la revue de #344, mais cette fois contraignante ; les quatre correctifs que #310 avait obtenus en posant 0.103.13 sont conservés. Preuves plutôt que déductions : contrôle sur l'ancien lock (exit 1 sur RUSTSEC-2026-0285) montrant que l'outil local reproduit le rouge de la CI ;cargo metadata --lockedacceptant le lock sans le réécrire ; checksums vérifiés ausha256sumdes.crate, et surtout les lignesDownloaded→Compiling rustls v0.23.45du run CI, qui prouvent l'archive réellement utilisée là oùcargo metadatane prouve que le graphe ; garde-fou tracé (Suppression guard: 2 checks, exit 0) ; 111 Rust ; etworkflow_dispatchd'audit.ymlsurmainaprès merge (run 414) plutôt que d'inférer le vert du run de PR./pr-reviewAPPROVE en re-prouvant depuis la source plutôt qu'en relayant — checksums authentifiés contre l'index crates.io, borne resserrée lue dans le champdepsde l'index, absence dereqwest 0.12.28de l'arbre inverse complet — et a levé une note fondée appliquée en9abf474: « aucun changement de comportement » valait pour le code de l'app, pas pour la couche TLS, où une poignée de main non conforme est désormais fermée. Deux acquis de process : (1) sur un événementpull_request, le filtrepathss'évalue contre le diff complet de la PR et non le delta du dernier commit — un commit markdown seul a donc rejouécheck-rust(run 413), ce qui est la bonne sémantique ; (2) merge par l'API Forgejo (rebase ff, SHA inchangé) plutôt qu'en local, ce qui évite la réconciliation manuelle des PRs. Pas de v0.15.1 : arbitrage de Max, l'entrée reste sous[Unreleased]. Aucune migration DB (v1→v17). (ref #348, #345, PR #349) - 2026-09-13 : Étape 10 de v0.15.0 consignée — le cycle de mise à jour réel passe, et le « code à 6 chiffres » reçu par un testeur n'est pas une étape de la mise à jour. Max rapporte que v0.14.0 → v0.15.0 fonctionne chez les deux testeurs. Corroboration Forgejo au 09-13 : les assets v0.15.0 comptent exactement 1
.debet 1-setup.exetéléchargés, 0.sig(l'updater lit les signatures danslatest.json) — cohérent avec une machine Linux et une Windows passées par l'updater, sans en être la preuve ; invite polkit Linux non consignée. Trace rédigée pour le corps de la release (Forgejo n'a pas de commentaires de release —docs/qa-update-cycle.mddisait « commentaire », corrigé avec lePATCHà rejouer) ; lePATCHlui-même est une écriture externe bloquée par le classifier du mode auto → payload préparé, commande remise à Max en!. Le code par courriel, retracé dans le code plutôt que deviné : nitauri-plugin-updater, ni la saisie de clé (validation Ed25519 locale), ni l'activation machine (license_key+machine_id; côtémaximus-api, seulfulfillmentServiceenvoie un courriel) n'en émettent. La seule surface est « Se connecter » de la carte Compte Maximus, première carte de Paramètres → Utilisateurs, juste au-dessus de la carte Licence où un testeur vient saisir sa clé — PKCE dans le navigateur système → page Logto, dont le connecteur SMTP (Resend) envoie un code à 6 chiffres valide 10 min pour trois flux, d'après lesign-in-exppublic du tenant : connexion par courriel + code (verificationCode: truesur l'identifiant email), « mot de passe oublié », inscription (signUp.verify: true) ; MFA = TOTP seul, donc exclu. Lequel des trois : seul le journal d'audit Logto le dit (console, ouGET /api/logs?userId=avec le secret M2M qui ne vit que sur le VPS). Sans effet sur l'édition :current_entitlementsne lit le compte que pour un abonnementactive, sinon retombe sur la clé Premium. Cause probable du clic : le texte de la carte (« Le compte est requis uniquement pour les fonctionnalités Premium », hérité de v0.7) contredit v0.15.0 où Premium vient de la clé — piège pour tout testeur qui arrive avec une clé ; reformulation à ouvrir en issue.logto-ops.mdenrichi (flux émetteurs du code + requête d'audit). Suite dans la même séance : évaluation pré-vente par 3 audits parallèles (desktop, API, site ; synthèse en mémoireproject-pre-sale-gaps) — la chaîne Stripe est prouvée en mode test depuis le 07-19, ce qui bloque est de l'alignement : #270, Premium verrouillé sans offre vendable, identité vendeur fictive (CGV +merchantInfo.ts), copie produit « gratuit/bêta » contradictoire, mode live (#62/#141), backup Postgres des licences non prouvé ; puis/analyze 270→ corps réécrit et 3 issues ouvertes (#346, #347, la-compagnie-maximus#153). Aucune migration DB (v1→v17). (ref v0.15.0, #320, #270, #346, #347) - 2026-09-12 : v0.15.0 taggée et publiée (
920dedd, run 402 vert) — et deux clés Premium émises juste avant, parce que la release ferme la porte derrière elle. Point de départ : Max demande comment les testeurs (lui et Michel) gardent l'accès une fois le gating actif. Lecture du code plutôt que de la spec : en v0.14.0FEATURE_TIERSlaisseauto-updateouvert en Free (« temporarily open until the license server is live »), v0.15.0 le passe Base+ — donc une installation sans clé reçoit v0.15.0 automatiquement et plus jamais rien ensuite, et se retrouve Free : profil actif seul, Budget/Ajustements/rapports avancés/Bilan verrouillés. Ni clause de grand-père ni période de grâce dans le code,SR_DEV_EDITIONcompilé hors des builds publiés. Réponse : une clé par testeur, saisie avant le tag (la carte Licence existe en v0.14.0 et la clé publique est identique entre v0.14.0 etmain), validation locale sans réseau ; l'activation machine n'est requise que pour les cours du Bilan (activation.tokenen Bearer vers/v1/prices), et l'ancien chemin/licenses/activatedu binaire passe par un 308 vers/v1/avec produit inféré du préfixeSR-(#48, vérifié en prod). Émission viaPOST /v1/licenses/generate(clé admin de Coolify déposée en~/.maximus-admin-key, bearer passé par process substitution, clés écrites en 600 hors transcription), puis vérification indépendante : signature Ed25519 contre la clé publique embarquée,exp+iatexigés parstrict_validation(), préfixe/édition cohérents, expiration 2036-09-09. Le détour qui a coûté la séance : le VPS répondaitConnection timed outsans lien de réauth — pas une attente navigateur maispeer's node key has expired(Tailscale, 180 j,last seen 16d), invisible depuis la console admin et sans réparation à distance ; l'IP publique54.39.97.77a le port 22 ouvert mais refuse la clé du ThinkPad, réparé par Max via le Terminal Coolify + Disable key expiry. Le classifier du mode auto bloque toutsshvers le VPS (Tailscale et IP publique) → commandes remises à Max en!. Lecture Logto : 4 comptes, Michel =michelt(04-14), les deux autres sont le second compte de Max et une reliquat de La Suite Booking. Tablelicenses: une seule vraie clé, la Base de Max du 07-19, révoquée (Stripe test + remboursement) — et le client ne voit jamaisis_revokedhors ligne, seul le serveur (activation, cours) la refuse. Release : pré-vol vert (111 Rust, 1181 vitest), 5 manifestes + 2 changelogs + ligneCLAUDE.md0.6.3→0.15.0, tag annoté confirmé par Max avant push (publielatest.jsonaux installations existantes), run 402 en 22 min, 7 artefacts etlatest.jsonvérifiés par script. Étape 10 à dérouler. (ref v0.15.0, #297-#301, #323-#331, #259, #310, #311, #343) - 2026-09-04 : #343 ouverte, #344 mergée — l'audit quotidien rouge depuis 17 jours, corrigé (
main5154c52). Découvert au/warmup:audit.ymléchouait tous les matins depuis le 2026-08-19 (runs 375→391), dernier vert le 08-18, aucun push surmaindans l'intervalle. Une seule vulnérabilité : RUSTSEC-2026-0258 / GHSA-q83h-524g-xf6h,h20.4.13, datée du 08-17 — DoS de sévérité faible, les frames HTTP/2DATAvides sont acceptées et mises en file sans aucune limite, donc sur un flux non drainé la mémoire croît sans borne et la longueur peut déborder en panique. Le délai 08-17→08-19 est la propagation dans l'advisory-db. Ces 17 jours sont le mode d'échec que l'ADR 0018 visait à empêcher — « alarme permanente = alarme ignorée » — cette fois par le haut : le gate criait, personne ne regardait. Atteignabilité par triple explicite, jamais--target all:h2est sur les deux cibles livrées par deux chemins,hyper←hyper-rustls←reqwest 0.13.2←tauri-plugin-updater(le chemin de la mise à jour automatique) ethyper-tls←reqwest 0.12.28déclaré directement enCargo.toml:43(licence, auth, cours, rétroaction — 4 modules). Correctif publié + crate atteignable = règle 1 de.cargo/audit.toml, donc corrigé et non suppressé ; ni le fichier de suppressions ni le garde-fou decheck-rust.ymlne bougent. Le piège, et la raison d'un diff de 2 lignes :cargo update -p h2donne bien 0.4.19 mais réaiguille au passage 7 pointeurswindows-sys(colored,dirs-sys,errno,rustix,rustls-platform-verifier,tempfile,winapi-util) de0.61.2vers 0.48/0.52/0.59 — exactement ce que #321 avait défait délibérément le 08-15. Laisser passer aurait régressé cette décision en silence, 3 semaines après. Le lock a donc été restauré et seule la stropheh2appliquée (version + checksum), après avoir retracé depuis la source —git show v0.14.0:src-tauri/Cargo.lock, les 7 crates comparés un à un — que0.61.2est bien l'état du tag, donc la seule configurationwindows-sysdont on ait la preuve qu'elle compile sous Windows ; relayer la note de #321 n'aurait pas suffi.cargo metadata --lockedaccepte le résultat sans le réécrire./pr-reviewAPPROVE et a trouvé ce que j'avais manqué : une strophe écrite à la main ne garantit plus ni checksum ni liste de dépendances, eth20.4.19 resserre sa bornehttpde^1à^1.1— le genre de changement qui invalide un lock épinglé ; satisfait ici (http 1.4.0), checksum authentifié parsha256sumdu.crate, et nuance utile qu'il pose :cargo metadata --lockedprouve le graphe, pas le checksum — c'est leDownloaded→Compilingdu run 392 qui le prouve. Preuves plutôt que déductions : contrôle sur l'ancien lock (exit 1 sur RUSTSEC-2026-0258) montrant que l'outil local reproduit le rouge de la CI ; log de la CI lu ligne à ligne parce que l'étapecargo auditdecheck-rustestcontinue-on-error: trueet qu'un job vert n'y prouve rien ; garde-fou tracé (Suppression guard: 2 checks, exit 0) ; 111 Rust ; etworkflow_dispatchd'audit.ymlsurmainaprès merge (run 393,Job succeeded) plutôt que d'inférer le vert du run de PR. Deux acquis au passage : (1) le globsrc-tauri/**est enfin prouvé — cette PR est le cas test isolé attendu depuis #232 (lock + 2.mdseulement) :check-rusta tourné,check-frontendcorrectement sauté par sa denylist ; le suivi peut être fermé ; (2) #345 ouverte — la contraintewindows-sys 0.61.2en est à sa 3e rencontre (#310 l'introduit, #321 la défait, #344 l'évite à la main) et ne vit dans aucun ADR, aucun commentaire deCargo.toml, aucun garde CI : seulement 3 lignes de prose de STATE.md et un message de commit, donc le prochaincargo updatela régressera en silence. Merge via l'API Forgejo (rebase ff, SHA inchangé) plutôt qu'en local, ce qui évite la réconciliation manuelle des PRs. Aucune migration DB (v1→v17). (ref #343, #345, PR #344) - 2026-08-15 : #321 + #322 mergées ff-only (
main97d376b) — deux PRs de 18 jours, deux revues du 08-14 jamais traitées, et une revue qui se corrige elle-même. Passes de re-vérification lancées depuis le main loop (jamais en sous-agent, feedback-pr-review-subagent-forks) et séquencées plutôt que parallélisées — deux revues concurrentes partagent le même chemin de scratch et s'écrasent entre le Write et le POST (gotcha du chantier import). Les deux passes ont retracé les claims depuis la source au lieu de relayer, et les deux ont trouvé une erreur dans la revue qu'elles re-vérifiaient. (1) Sur #321, la revue du 08-14 lisait les 7 réaiguillageswindows-syscomme une dérive de re-résolution et demandait un build Windows avant de tagger : le sens est l'inverse — #310 les avait fait descendre de0.61.2vers 0.48/0.52/0.59, cette PR les remonte à0.61.2, l'état exact du tagv0.14.0(git show v0.14.0:src-tauri/Cargo.lock, crate par crate). v0.14.0 taggée le 07-18, #310 mergée le 07-27 → le build NSIS de v0.14.0 a réellement compilé contre0.61.2. La configuration non prouvée sous Windows était celle demain; la PR réduit le risque. (2) Sur #322, la revue du 08-14 annonçait « trois » déclencheurs et mappaitUpdateCard.tsx:201à la page d'erreur — faux dans les deux sens ::201est le retry de l'étaterrorde la carte, etErrorPage.tsx:82est un 4e site distinct qui détecte seulement (handleCheckUpdates'arrête àsetUpdateStatus("available")). Appliquer « écrire trois » aurait échangé une inexactitude contre une autre. Le blocage de #322 était réel et non traité : la checklist demandait de cocherreadyToInstallavant l'invite d'authentification, alors quedownload_and_installfaitdownload(...).await?puisinstall(bytes)dans le même appel (updater.rs:723-729), queFinishedest un no-op côté UI (useUpdater.ts:119-121) et queREADY_TO_INSTALLn'est dispatché qu'après le retour dedpkg -i— l'invite pkexec s'ouvre donc par-dessus « Téléchargement en cours… ». Conséquence exacte de l'ordre des cases : sans agent polkit l'app se fige endownloading, le testeur guette un blocage aprèsreadyToInstall, et rapporte « le téléchargement bloque » au lieu de « pas d'agent polkit » — la page produisait la fausse trace qu'elle existe pour éliminer. Corrigé en97d376bavec 3 mineurs (les 4 déclencheurs, les préfixes/api/v1/packages/(DELETE) vs/api/packages/(PUT) querelease.yml:217-219commente déjà, ordre du changelogSKILL.md) + titre de PR (« step 9 » → « as step 10 »). Merge : rebase des 2 branches (15 commits de retard) en pile linéaire, preuve que le rebase préserve.cargo//.forgejo//Cargo.lockau byte près vs le commit validé par la CI run 338, puis CI re-jouée quand même (runs 370/371 verts, garde-fou exécuté et tracé,cargo audit0 vulnérabilité / 22 warnings autorisés) etcargo test111 passed — le « 106 » de la description de #321 était périmé, le chantier import ayant ajouté 5 tests. Issues #312/#313/#315 auto-fermées parResolves, PRs fermées à la main (Forgejo ne détecte pas un merge local comme merged), branches supprimées. #314 trouvée caduque au passage :audit.ymltire bien tous les jours à 06:00 UTC — 19 runsscheduleverts du 07-28 au 08-15 — et sonworkflow_dispatchde référence datait du 07-27 à 23:56Z, soit ~6 h avant le premier tir programmé possible. L'issue a été écrite avant que le scheduler ait pu s'exprimer, pas après l'avoir vu échouer. (ref #312, #313, #314, #315, PRs #321/#322) - 2026-08-14 : Import CSV — chantier complet livré (10 issues, migration v17). Cycle intégral en une session : revue d'implémentation →
/spec→/review-spec→/plan-run→/autopilot→/pr-review×10 → merge ff-only. Le diagnostic a tenu, mais trois choses ont été trouvées en cours de route que personne n'avait vues. (1) Au re-ancrage Phase 3b :dataExportServicene sérialise niimport_sourcesniimport_config_templateset faitDELETE FROM import_sourcesà la restauration — restaurer une sauvegarde détruisait toutes les configurations d'import, 3e voie de perte du format, indépendante du bug racine (→ #331, +withTransactionque le service n'avait nulle part). (2) Un worker a mesuré que l'exemple « Solde 2024 » de l'issue n'est pas défectueux (parseFloats'arrête sur leS) et a ajouté la fixture qui l'est vraiment. (3) Un autre a mesuré que chez RBCCAD$et unCheque Numberpresque vide sont sparse-complementary : le générique les apparie et une ligne de chèque s'importe à −234,05 au lieu de −6,95 — d'où l'override par signature. Correction de la revue initiale :parseFrenchAmount("50,00-")ne rend pas 50 mais 5000 —"100,00 CAD"→ 10000,"1 234,56 CR"→ 123456 : erreur de facteur 100 qui passaitisNaNet comptait donc la ligne comme VALIDE. Le ×100 atteignait aussi l'import de titres #245. Durcissement global assumé : un relevé à suffixe de devise produit désormais des lignes en erreur plutôt que des valeurs fausses./pr-reviewa bloqué 3 des 10 PRs, tous fondés : (a) #336 — la règle débit/crédit testaitisNaN(debit) && isNaN(credit), donc une cellule illisible à côté du remplissage0,00calculait 0 − 0 = 0 et importait en silence, le bug même que la PR fermait, une cellule plus loin (rejoué sur sa propre fixture : 6 transactions à 0,00 $, 0 erreur) ; (b) #337 —detectDescriptionColumnretournait la colonne préférée sans veto par les données, et le mot-clétransactioncapturait la colonne DEBIT/CREDIT de Tangerine, tuant la catégorisation ; (c) #340 — régression réelle : la signature Desjardins est 4 libellés génériques appariés par sous-ensemble, et une signature court-circuitait le scan sparse-complementary → un fichierDate;Description;Débit;Crédit;Montant;Soldelu correctement AVANT devenaitpositive_expenseAPRÈS, chaque dépôt en dépense. Corrigés en 3 commits sur la tête de pile (484c4be,ef7de3c,37b832e), chacun vérifié par mutation — et cette vérification a révélé qu'un de mes propres tests passait la mutation (le fix sur les signatures génériques empêchait la branche gardée d'être atteinte) : il a fallu un fichier reconnu par une signature légitime pour l'exercer. Leçon : un garde qui ne peut pas échouer ne garde rien, y compris quand c'est soi qui l'écrit. Incident run : le worker #331 tué par une limite de session pendant sa validation — travail récupéré depuis son worktree et revalidé de zéro (le rationale de sa PR est une reconstruction, signalé comme tel). Gotcha parallélisation : deux agents de revue partageaientscratchpad/review.md, l'un a écrasé l'autre entre Write et POST → donner un chemin de scratch unique par agent. Suivis ouverts : refus du format à indicateur borné àamountCol ± 1; dérives de comptes préexistantes dansCLAUDE.md/architecture.md(mesurées et documentées, non corrigées). (ref #323-#332, PRs #333-#342) - 2026-07-27 : #310 + #311 mergées —
cargo audit9→0,npm audit3→2 acceptées (maina14258b, ff-only ; PRs #316 → #318 stackées, CI verte des deux côtés). Parties d'un/analyse-vulnerabilite: rapport Défenseur écarté comme source (VPS injoignable — SSH Tailscale en attente d'auth navigateur, aucun lien imprimé ; rapport local du 2026-05-06, 82 jours) → vérité live =cargo audit 0.22.2+npm auditsurmain, advisory-db0bfde9d6. Le triage d'origine de #310 révisé sur un point :quick-xml(2× 7.5 high) n'est compilé sur aucune des deux cibles livrées —cargo tree -ivide surx86_64-pc-windows-msvcetx86_64-unknown-linux-gnu, présent seulement surx86_64-apple-darwinviaplist←tauri(dép. conditionnelle Apple). Il n'y avait donc rien à attendre de Tauri, contrairement au « probablement bloqué en amont » du corps. Méthode retenue : tracer par triple explicite, jamais--target all(qui répond « présent » pour des deps Apple jamais compilées ici) — mémoire reference-cargo-audit-reachability-par-cible. 6 advisories atteignables corrigées parcargo update -p rustls-webpki -p tar(0.103.9→0.103.13 couvrant les 4, 0.4.44→0.4.46) sans toucherCargo.toml; dérive de lock expliquée et bornée (7 pointeurswindows-sysrepointés vers des versions déjà présentes, 666 paquets avant/après, deps Windows-only → no-op sur Linux ;--precisedonne le même résultat, c'est la re-résolution de cargo 1.94.1). Les 3 restantes →.cargo/audit.tomlversionné, lu par les deux workflows sans qu'aucun ne le sache. Le plan checker a levé un MAJOR fondé : une liste de suppressions sans déclencheur de retrait inverse le problème de l'alarme (l'audit resterait vert siquick-xmlredevenait atteignable) — d'où 3 règles en ADR 0018 : admission sur preuve par cible livrée ou absence de correctif ; clé par ID d'advisory jamais par crate (une nouvelle advisory sur le même crate repasse au rouge) ; garde-fou bloquant danscheck-rust.yml, placé aprèscargo check(index chaud) avec--locked, testant le code de sortie séparément de la sortie (un crate absent et uncargo treeen panne impriment tous deux du vide) + canaritar. Le pendant — suppression devenue inutile — est #312. Leçon du 1er run CI : le garde était muet en cas de succès, donc indiscernable dans les logs d'une étape non exécutée — exactement le mode d'échec silencieux que la PR combat (même famille que le « globsrc-tauri/**non prouvé » de #232) → il logge maintenant chaque vérification (Suppression guard: 4 checks, exit 0, visible run 336). Preuve que.cargo/audit.tomlest bien lu en conteneur : leworkflow_dispatchdeaudit.ymlsur la branche est vert, alors que le bump seul n'aurait éliminé que 6 des 9. npm (#311) :postcss8.5.13→8.5.23 sans override —vitedéclare^8.5.3, seul le lock était périmé (≠ cas #241 où le parent pinnait) ;nanoidsuit dans sa borne ; CSS émis identique octet pour octet (postcss est le pipeline CSS, un build vert n'aurait prouvé que la compilation) ;react-routeraccepté — advisory mode RSC, orApp.tsx:109monte unBrowserRouterclient-only, etreact-router-domest figé à 7.18.1 (v8 a fusionné le paquet dansreact-router) donc le « fix » npm est un downgrade en 7.11.0 → sortir de la plage = migration, pas bump (#317, titre portantreact-routerpour la dédup par sous-chaîne de/analyse-vulnerabilite). Asymétrie à connaître : aucunnpm auditen CI, donc rien ne rougit côté front — écrit dansarchitecture.md+CLAUDE.mdpour que les 2 high permanents ne se lisent pas comme une régression. Gotchas Forgejo relevés : logs de job uniquement via l'URL web (l'API v1 répond 404 partout) ethead_branch=#<PR>sur les runspull_request→ reference-forgejo-ci-logs-et-head-branch. 106 Rust + 871 vitest + builds verts. Aucune migration DB (v1→v16). (ref #310, #311, PRs #316/#318, #312-#315, #317)
Blockers actifs
- Aucun blocker externe dur.
spec-monetisationfermée 12/12 (2026-07-08) — #50/#52/#53/#135/#136 livrées, ne sont plus des blockers. - Aucun tag avant le go-live du paiement. Depuis #346 (
main170b22d), « Obtenir Base » est actif et ouvre la page produit, dont le checkout reste en mode test tant que la-compagnie-maximus#141 et maximus-api#62 sont ouvertes (#141 porte déjà « release desktop re-gated ») : une release avant ce go-live livrerait un bouton d'achat dont le paiement ne peut pas aboutir. Vérification manuelle en attente : en Gratuite, le modal de création de profil ouvert depuisProfileSwitcher, puis « J'ai déjà une clé », doit se fermer sur la carte Licence (seule mutation que les tests ne gardent pas). - Backlog ouvert (
status:ready, non bloqué) : vagueplanned-2026-09-24-paiements(planifiée le 2026-09-24) — desktop 2/3 : #270 (PR #359) et #346 (PR #362) mergées le 2026-09-27, reste #347 (à partir demain) ; volet site clos (maximus/la-compagnie-maximus#153, redirection de/simpl-resultaten prod). Hors vague, avant go-live : maximus-api#70 (réactivation d'une machine déjà désactivée → 500, prérequis de maximus-api#62), #360 (jeton d'une autre machine → Gratuite sans issue, à trancher), #350 (hachage de l'identifiant machine), maximus-api#63 + la-compagnie-maximus#157 (clés de 100 ans + CGV, à déployer ensemble), #363 (tester unexpau-delà de 2^32 côté client, suivi de maximus-api#63, priorité basse) ; go-live = la-compagnie-maximus#141 + maximus-api#62 ;spec-paiementsreste le parapluie des trois dépôts ; #271 absorbé par #301, livré ;spec-ci-build-optimization3/4 (#232 livrée le 2026-07-27 ; reste #234 connectivité du serveur de cache runner, qui débloqueraitSwatinem/rust-cache— accès hôte VPS requis). Le suivi « globsrc-tauri/**non prouvé » ouvert avec #232 est levé : la PR #344 est le cas test isolé attendu (Cargo.lock+ 2.mdseulement) —check-rusta bien tourné,check-frontenda 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», oraudit.ymltire tous les jours à 06:00 UTC (19 runsscheduleverts 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.tomlest bien lu en conteneur surmain— l'ADR 0018 ne l'avait vérifié que par unworkflow_dispatchsur une branche. #343 fermée le 2026-09-04 (PR #344) — RUSTSEC-2026-0258 surh2, la seule vulnérabilité qui rougissait l'audit depuis le 08-19 ; l'audit est de nouveau vert surmain, prouvé parworkflow_dispatch(run 393) et non déduit du run de PR. #348 fermée le 2026-09-21 (PR #349) — RUSTSEC-2026-0285 surrustls, seule vulnérabilité rougissant l'audit depuis le 09-15 (7 runs, 405→411) ; vert reprouvé parworkflow_dispatchsurmain(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 (re-évaluerreact-routerà une migration v8), #319 (déclencheur de retrait pourrsa, désormais seule entrée de.cargo/audit.toml— le garde-fou est passé à 2 vérifications) et #345 (domicilier la contraintewindows-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 quelcargo update» mais tout bump atteignant le sous-arbre réseau/TLS — mesuré :-p anyhowne bouge rien,-p hyperfait 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 àhyperet à 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 dewindows-sysplutô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 dewindows-syscompilé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-rss'arrête surlib.exe, il faudraitcargo-xwin). Côté npm, #358 ouverte le 2026-09-26 par/analyse-vulnerabilite:npm auditremonte 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 avecnpx npm@11(npm 10 plante sur un bump de vitest 4.1.x). - Nouveau bug ouvert : #320 — les installations
.rpmne reçoivent aucune mise à jour (latest.jsonne porte qu'une entréelinux-x86_64construite depuis le.deb,release.yml:104-122), alors que les.rpmcontinuent d'être publiés en assets. Documenté en §3 dedocs/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 dansCLAUDE.mdetdocs/architecture.md(composants, pages, services,Version actuelle : 0.6.3vs tag v0.14.0) mesurées et documentées en revue, non corrigées. - Étape 10 de la release v0.15.0 consignée le 2026-09-13 — plus un blocker : cycle réel v0.14.0 → v0.15.0 validé par les deux testeurs ; trace rédigée pour le corps de la release (
PATCHà appliquer par Max) ; invite d'authentification Linux non consignée ; #320 reste ouverte (.rpm). Deux restes : (1) le texte de la carte Compte Maximus (« Le compte est requis uniquement pour les fonctionnalités Premium », hérité de v0.7) contredit v0.15.0 où Premium vient de la clé, et a vraisemblablement conduit un testeur à se connecter pour rien (code de vérification Logto reçu par courriel) — reformulation livrée par #346 (PR #362), avec une réserve notée dans l'ADR 0017 (exacte tant que le chemin abonnement → Premium reste dormant) ; (2) le flux Logto exact (connexion par code, mot de passe oublié ou inscription) reste à lire dans le journal d'audit. Position produit : v0.15.0 ;[Unreleased]porte l'entréerustlsdu 2026-09-21, puis #270 et #346.