state: sync after the v0.16.0 release
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
56fc612598
commit
1923f8f70b
1 changed files with 8 additions and 6 deletions
14
STATE.md
14
STATE.md
|
|
@ -1,8 +1,8 @@
|
|||
# STATE — Simpl'Résultat
|
||||
|
||||
> Derniere MAJ : 2026-10-03 (**#365 mergée — PR #368, `main` `b107cf4`, merge API en `fast-forward-only`.** Une clé révoquée par le serveur de licences retombe en Gratuite, mises à jour automatiques comprises, et y reste d'une session à l'autre : l'app la vérifie au démarrage, au plus une fois par 24 h, première requête qu'elle envoie d'elle-même. **#365 reste ouverte, en `status:blocked`** : la PR portait `Refs`, et une vérification manuelle avec la clé réellement révoquée du 2026-09-30 est due avant le tag. `/pr-review` APPROVE, ses suggestions appliquées avec preuve du rouge ; Max a tranché les deux autres. Suite ouverte : #367. Rust **187**, vitest **1348**.)
|
||||
> Derniere MAJ : 2026-10-03 (**v0.16.0 publiée — tag `v0.16.0` (`56fc612`), run 451 vert en 22 min.** Elle porte #270, #346, #347, #350, #365 et le correctif `rustls` de #348. `verify-release.sh` vert (7 artefacts, `latest.json` signé pour Linux et Windows), et le registre que lit l'updater sert la 0.16.0. Aucun autre utilisateur que les testeurs, d'après Max : les vérifications manuelles de #346, #350 et #365, et le cycle de mise à jour réel dû parce que `rustls` touche l'updater, se font sur la release publiée.)
|
||||
>
|
||||
> Précédente MAJ : 2026-10-01 (**#350 mergée — PR #366, `main` `0a9c9f7`, merge API en `fast-forward-only`.** L'activation envoie un identifiant dérivé de celui du système (`HMAC-SHA256` sous une clé figée, ADR 0020), et une machine déjà activée garde son activation. **#350 reste ouverte, en `status:blocked`** : la PR portait `Refs`, et une vérification manuelle est due avant le tag, sur un poste activé par la v0.15.0. `/pr-review` APPROVE, cinq suggestions appliquées avec preuve du rouge, dont une condition de retrait fausse dans l'ADR. Deux suites ouvertes : maximus-api#82 et la-compagnie-maximus#184. Rust **168**, vitest **1314**.)
|
||||
> Précédente MAJ : 2026-10-03 (**#365 mergée — PR #368, `main` `b107cf4`, merge API en `fast-forward-only`.** Une clé révoquée par le serveur de licences retombe en Gratuite, mises à jour automatiques comprises, et y reste d'une session à l'autre : l'app la vérifie au démarrage, au plus une fois par 24 h, première requête qu'elle envoie d'elle-même. **#365 reste ouverte, en `status:blocked`** : la PR portait `Refs`, et une vérification manuelle avec la clé réellement révoquée du 2026-09-30 est due avant le tag. `/pr-review` APPROVE, ses suggestions appliquées avec preuve du rouge ; Max a tranché les deux autres. Suite ouverte : #367. Rust **187**, vitest **1348**.)
|
||||
|
||||
## Position actuelle
|
||||
|
||||
|
|
@ -18,8 +18,11 @@ Audit critique de la page Bilan livré (`docs/audit-bilan-2026-05.md`, revue CPA
|
|||
|
||||
**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).
|
||||
|
||||
**v0.16.0 shippée** (2026-10-03, tag `v0.16.0` → CI release run 451, 7 artefacts + `latest.json` vérifiés, registre de l'updater en 0.16.0) — première version vendable de bout en bout : « Obtenir Base » ouvre la page produit (#346), le client de licence parle `/v1` et nomme chaque refus (#270), l'édition ne dépend que de la clé (#347), l'activation envoie un identifiant dérivé (#350), une clé révoquée retombe en Gratuite après un contrôle au démarrage (#365), et `rustls` 0.23.45 (#348). `[Unreleased]` vide. Aucune migration DB nouvelle (v1→v17). À dérouler sur la release publiée : les vérifications manuelles de #346, #350 et #365, et l'étape 10 de `/release` (cycle de mise à jour réel, Linux et Windows, trace à consigner dans le corps de la release).
|
||||
|
||||
## Decisions recentes
|
||||
|
||||
- 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`). Aucune migration DB (v1→v17). (ref v0.16.0, #270, #346, #347, #348, #350, #365, #370)
|
||||
- 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)
|
||||
|
|
@ -29,13 +32,12 @@ Audit critique de la page Bilan livré (`docs/audit-bilan-2026-05.md`, revue CPA
|
|||
- 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 sur `main` — le dernier commit était `97ee3c3` du 09-13. Une seule vulnérabilité : **RUSTSEC-2026-0285** / GHSA-2mjx-qc3c-rqvc, `rustls` 0.23.36, datée du **09-14**, CVSS 5.3 medium, vecteur `C: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 de `h2`. **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 (un `EncryptedExtensions` en clair collé au `ServerHello`), 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'`h2` en #343 : le `reqwest 0.12.28` déclaré en `Cargo.toml:43` (licence, auth, cours, rétroaction) passe par `hyper-tls → native-tls → openssl` et est **absent** de l'arbre inverse de `rustls`. 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 pointeurs `windows-sys` de `0.61.2` — or `cargo update -p rustls --precise 0.23.45` n'en a déplacé aucun. Le déclencheur tient à `hyper` et à 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 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é. 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-webpki` 0.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 le `http ^1 → ^1.1` relevé 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 --locked` acceptant le lock sans le réécrire ; checksums vérifiés au `sha256sum` des `.crate`, et surtout les lignes `Downloaded`→`Compiling rustls v0.23.45` du run CI, qui prouvent l'archive réellement utilisée là où `cargo metadata` ne prouve que le graphe ; garde-fou tracé (`Suppression guard: 2 checks, exit 0`) ; **111 Rust** ; et `workflow_dispatch` d'`audit.yml` **sur `main` après merge** (run 414) plutôt que d'inférer le vert du run de PR. `/pr-review` **APPROVE** 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 champ `deps` de l'index, absence de `reqwest 0.12.28` de l'arbre inverse complet — et a levé une note fondée appliquée en `9abf474` : « 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énement `pull_request`, le filtre `paths` s'é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 `.deb` et 1 `-setup.exe` téléchargés, 0 `.sig` (l'updater lit les signatures dans `latest.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.md` disait « commentaire », corrigé avec le `PATCH` à rejouer) ; le `PATCH` lui-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é** : ni `tauri-plugin-updater`, ni la saisie de clé (validation Ed25519 locale), ni l'activation machine (`license_key` + `machine_id` ; côté `maximus-api`, seul `fulfillmentService` envoie 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 le `sign-in-exp` public du tenant : connexion par courriel + code (`verificationCode: true` sur 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, ou `GET /api/logs?userId=` avec le secret M2M qui ne vit que sur le VPS). Sans effet sur l'édition : `current_entitlements` ne lit le compte que pour un abonnement `active`, 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.md` enrichi (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émoire `project-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.0 `FEATURE_TIERS` laisse `auto-update` **ouvert 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_EDITION` compilé 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 et `main`), validation locale sans réseau ; l'activation machine n'est requise que pour les cours du Bilan (`activation.token` en Bearer vers `/v1/prices`), et l'ancien chemin `/licenses/activate` du binaire passe par un 308 vers `/v1/` avec produit inféré du préfixe `SR-` (#48, vérifié en prod). Émission via `POST /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`+`iat` exigés par `strict_validation()`, préfixe/édition cohérents, expiration 2036-09-09. **Le détour qui a coûté la séance** : le VPS répondait `Connection timed out` sans lien de réauth — pas une attente navigateur mais **`peer's node key has expired`** (Tailscale, 180 j, `last seen 16d`), invisible depuis la console admin et sans réparation à distance ; l'IP publique `54.39.97.77` a 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 tout `ssh` vers 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. Table `licenses` : une seule vraie clé, la Base de Max du 07-19, **révoquée** (Stripe test + remboursement) — et le client ne voit jamais `is_revoked` hors ligne, seul le serveur (activation, cours) la refuse. Release : pré-vol vert (111 Rust, 1181 vitest), 5 manifestes + 2 changelogs + ligne `CLAUDE.md` 0.6.3→0.15.0, tag annoté confirmé par Max avant push (publie `latest.json` aux installations existantes), run 402 en 22 min, 7 artefacts et `latest.json` vé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é (`main` `5154c52`).** 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 sur `main` dans l'intervalle**. Une seule vulnérabilité : **RUSTSEC-2026-0258** / GHSA-q83h-524g-xf6h, `h2` 0.4.13, datée du 08-17 — DoS de sévérité faible, les frames HTTP/2 `DATA` vides 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` : `h2` est 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) et `hyper-tls`←`reqwest 0.12.28` déclaré directement en `Cargo.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 de `check-rust.yml` ne bougent. **Le piège, et la raison d'un diff de 2 lignes** : `cargo update -p h2` donne bien 0.4.19 mais réaiguille au passage 7 pointeurs `windows-sys` (`colored`, `dirs-sys`, `errno`, `rustix`, `rustls-platform-verifier`, `tempfile`, `winapi-util`) de `0.61.2` vers 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 strophe `h2`** appliqué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 — que `0.61.2` est bien l'état du tag, donc la seule configuration `windows-sys` dont on ait la preuve qu'elle compile sous Windows ; relayer la note de #321 n'aurait pas suffi. `cargo metadata --locked` accepte le résultat **sans le réécrire**. **`/pr-review` APPROVE et a trouvé ce que j'avais manqué** : une strophe écrite à la main ne garantit plus ni checksum ni liste de dépendances, et `h2` 0.4.19 **resserre sa borne `http` de `^1` à `^1.1`** — le genre de changement qui invalide un lock épinglé ; satisfait ici (`http 1.4.0`), checksum authentifié par `sha256sum` du `.crate`, et nuance utile qu'il pose : `cargo metadata --locked` prouve le graphe, **pas** le checksum — c'est le `Downloaded`→`Compiling` du 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'étape `cargo audit` de `check-rust` est `continue-on-error: true` et qu'un job vert n'y prouve rien ; garde-fou tracé (`Suppression guard: 2 checks, exit 0`) ; **111 Rust** ; et `workflow_dispatch` d'`audit.yml` **sur `main` après merge** (run 393, `Job succeeded`) plutôt que d'inférer le vert du run de PR. **Deux acquis au passage** : (1) le **glob `src-tauri/**` est enfin prouvé** — cette PR est le cas test isolé attendu depuis #232 (lock + 2 `.md` seulement) : `check-rust` a tourné, `check-frontend` correctement sauté par sa denylist ; le suivi peut être fermé ; (2) **#345 ouverte** — la contrainte `windows-sys 0.61.2` en est à sa 3e rencontre (#310 l'introduit, #321 la défait, #344 l'évite à la main) et ne vit dans **aucun** ADR, aucun commentaire de `Cargo.toml`, aucun garde CI : seulement 3 lignes de prose de STATE.md et un message de commit, donc le prochain `cargo update` la 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)
|
||||
## 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 est devenue une dépendance du go-live.** 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`. Sources : la-compagnie-maximus#141 (corps du 2026-09-30) et maximus-api#62 (revalidation du 2026-09-29), relus le 2026-09-30 ; depuis ce dépôt, seuls `/healthz` (200) et les CGV publiées ont été relus. Les deux issues restent ouvertes pour leur reliquat (réglages au Dashboard Stripe, la-compagnie-maximus#150 pour Link dans les textes légaux, ménage de configuration côté maximus-api), et la-compagnie-maximus#141 attend désormais ce dépôt : #346 et #347 publiées dans une release, puis l'updater vérifié (Free refuse et invite à acheter, Base accepte), ainsi que #365 et #350. **À trancher par Max : le contenu de la prochaine release.** #350 est mergée depuis le 2026-10-01 (PR #366) : la demande de la-compagnie-maximus#141, « avant que les ventes s'accumulent », est tenue si la release part avec elle. #365 est mergée depuis le 2026-10-03 (PR #368) ; la-compagnie-maximus#184 doit déclarer son contrôle avant la release qui l'embarque. **Trois vérifications manuelles en attente avant le tag** : (1) en Gratuite, le modal de création de profil ouvert depuis `ProfileSwitcher`, puis « J'ai déjà une clé », doit se fermer sur la carte Licence (seule mutation que les tests de #346 ne gardent pas) ; (2) pour #350, sur un poste activé par la v0.15.0 : état « Activée » et marqueur « Cette machine » conservés, puis « Désactiver » et « Activer » doivent donner un jeton dont le claim vaut le dérivé (commande dans #350, attendu `64 brut: False dérivé: True`). La dérivation devient définitive à la première activation en production, et rien d'autre ne tient le câblage de l'activation à l'identifiant réel du poste ; (3) pour #365, avec la clé réellement révoquée du contrôle d'achat du 2026-09-30 : l'enregistrer, redémarrer, lire « the license server says the key was revoked » dans le Journal, puis constater l'édition Gratuite et la révocation nommée (carte Licence, écran verrouillé, carte Mises à jour) ; étapes dans #365.
|
||||
- Backlog ouvert (`status:ready`, non bloqué) : **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). Hors vague, pour la release qui suit le go-live : **#365** (vérification en ligne de la révocation : mergée le 2026-10-03 par la PR #368, ouverte en `status:blocked` jusqu'à sa vérification manuelle), **#367** (`status:triage` : jeton d'activation d'une ancienne licence resté à côté d'une autre clé par la v0.15.0 ; carte « Activée », cours refusés, aucun moyen de réactiver), **#350** (hachage de l'identifiant machine : mergée le 2026-10-01 par la PR #366, ouverte en `status:blocked` jusqu'à sa vérification manuelle), 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, en `status:triage` : maximus-api#82 (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 (données d'activation absentes de la politique de confidentialité, à quoi s'ajoute le contrôle de révocation de #365, faits livrés consignés le 2026-10-03) ; clôture du go-live = la-compagnie-maximus#141 + maximus-api#62 ; `spec-paiements` reste le parapluie des trois dépôts (ici 3/5, restent #350 et #363) ; `spec-onboarding-phase1` **0/7** (#351 à #357, `status:ready`, pile linéaire ; spécifiée et passée en `/review-spec` le 2026-09-25, mise en issues le 2026-09-26 ; 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` **3/4** (#232 livrée le 2026-07-27 ; reste **#234** connectivité du serveur de cache runner, qui débloquerait `Swatinem/rust-cache` — accès hôte VPS requis). 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.
|
||||
- **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`. Sources : la-compagnie-maximus#141 (corps du 2026-09-30) et maximus-api#62 (revalidation du 2026-09-29), relus le 2026-09-30 ; depuis ce dépôt, seuls `/healthz` (200) et les CGV publiées ont été relus. Les deux issues restent ouvertes pour leur reliquat (réglages au Dashboard Stripe, la-compagnie-maximus#150 pour Link dans les textes légaux, ménage de configuration côté maximus-api), et la-compagnie-maximus#141 attendait ce dépôt : #346, #347, #350 et #365 sont publiées dans la v0.16.0 ; reste l'updater vérifié (Free refuse et invite à acheter, Base accepte). la-compagnie-maximus#184, qui déclare le contrôle au démarrage, est traitée par Max en parallèle de la release. **Trois vérifications manuelles en attente, sur la release publiée** : (1) en Gratuite, le modal de création de profil ouvert depuis `ProfileSwitcher`, puis « J'ai déjà une clé », doit se fermer sur la carte Licence (seule mutation que les tests de #346 ne gardent pas) ; (2) pour #350, sur un poste activé par la v0.15.0 : état « Activée » et marqueur « Cette machine » conservés, puis « Désactiver » et « Activer » doivent donner un jeton dont le claim vaut le dérivé (commande dans #350, attendu `64 brut: False dérivé: True`). La dérivation devient définitive à la première activation en production, et rien d'autre ne tient le câblage de l'activation à l'identifiant réel du poste ; (3) pour #365, avec la clé réellement révoquée du contrôle d'achat du 2026-09-30 : l'enregistrer, redémarrer, lire « the license server says the key was revoked » dans le Journal, puis constater l'édition Gratuite et la révocation nommée (carte Licence, écran verrouillé, carte Mises à jour) ; étapes dans #365.
|
||||
- Backlog ouvert (`status:ready`, non bloqué) : **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). Hors vague, pour la release qui suit le go-live : **#365** (vérification en ligne de la révocation : mergée le 2026-10-03 par la PR #368, ouverte en `status:blocked` jusqu'à sa vérification manuelle), **#367** (`status:triage` : jeton d'activation d'une ancienne licence resté à côté d'une autre clé par la v0.15.0 ; carte « Activée », cours refusés, aucun moyen de réactiver), **#370** (`status:triage` : retirer la clé enregistrée, seul moyen d'arrêter le contrôle quotidien d'une clé révoquée sans entrer une autre clé), **#350** (hachage de l'identifiant machine : mergée le 2026-10-01 par la PR #366, ouverte en `status:blocked` jusqu'à sa vérification manuelle), 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, en `status:triage` : maximus-api#82 (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 (données d'activation absentes de la politique de confidentialité, à quoi s'ajoute le contrôle de révocation de #365, faits livrés consignés le 2026-10-03) ; clôture du go-live = la-compagnie-maximus#141 + maximus-api#62 ; `spec-paiements` reste le parapluie des trois dépôts (ici 3/5, restent #350 et #363) ; `spec-onboarding-phase1` **0/7** (#351 à #357, `status:ready`, pile linéaire ; spécifiée et passée en `/review-spec` le 2026-09-25, mise en issues le 2026-09-26 ; 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` **3/4** (#232 livrée le 2026-07-27 ; reste **#234** connectivité du serveur de cache runner, qui débloquerait `Swatinem/rust-cache` — accès hôte VPS requis). 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** (re-évaluer `react-router` à une migration v8), **#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.
|
||||
- **É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ée `rustls` du 2026-09-21, puis #270, #346, #347, #350 et #365.
|
||||
- **É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.16.0 (2026-10-03) ; `[Unreleased]` vide.
|
||||
|
|
|
|||
Loading…
Reference in a new issue