fix(balance): v16 abort guard too broad — scope to convertible accounts (asset_type NOT NULL) #228
Labels
No labels
autopilot:pending-human
source:analyste
source:defenseur
source:human
source:medic
status:approved
status:blocked
status:in-progress
status:needs-clarification
status:needs-fix
status:ready
status:review
status:triage
type:bug
type:feature
type:infra
type:refactor
type:schema
type:security
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: maximus/Simpl-Resultat#228
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Trouvé par la review adversariale de PR #220 (#211). Fix-forward décidé : à appliquer sur
mainaprès le merge de la chaîne Étape 2, avant le tag de release (v16 n'a jamais été appliquée à un profil persistant — modifier sa SQL avant la première application respecte la règle d'immutabilité des migrations).Bug
La garde d'abort de la migration v16 (
src-tauri/src/lib.rs, sous-requête_v16_guard) clé sura.symbol IS NOT NULLau lieu de la convertibilité (c.asset_type IS NOT NULL).Un compte sous catégorie simple portant un symbole résiduel (l'AccountForm rend le champ symbole inconditionnellement ;
updateBalanceAccountpréserve le symbole lors d'une recatégorisation priced→simple) a des lignes àquantity NULLpar construction. Elles satisfont le prédicat de la garde (symbol NOT NULL AND qty NULL AND aucun holding) → la garde insère0→CHECK(ok=1)échoue → toute la migration v16 abort → l'app ne démarre plus pour ce profil (pas de perte de données, blocage de lancement non récupérable).La logique de conversion (étapes 1-3) est correcte ; seule la garde belt-and-suspenders est trop large.
Fix
Joindre
balance_categoriesdans la sous-requête de garde et exigerAND c.asset_type IS NOT NULL, dans les deux copies (le SQL deMigration { version: 16 }ET la constante de testV16_SQL, statement-equivalentes) :Test de régression
Ajouter un cas (style
db_pre_v16) seedant un compte sous catégorie simple avec unsymbolrésiduel + une ligne snapshot àquantity NULL, puis asserter que v16 s'applique proprement (pas d'abort) et laisse ce compte intact (non converti, qty/price préservés). Le test échoue avant le fix, passe après.Critères d'acceptation
c.asset_type IS NOT NULL(Migration v16 + constV16_SQL)cargo testvert