All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 1m38s
Last link of the ten-link import-format stack. Links 1-9 deliberately wrote no changelog and no documentation, to avoid a conflict at every level of a linear pile; this link owes all of it. - ADR 0019 records the structuring decision: the import format is a fully persisted value, never re-inferred. It documents the three independent paths by which it used to be lost (hardcoded restore, header drift, data export), and why a single codec with a completeness test closes the class rather than a composed type -- the two carriers are structurally incompatible (`has_header` is boolean on one and number on the other). `template_id` is recorded as a provenance label, never re-read as format. - `docs/architecture.md` gains a dedicated "Import CSV" section covering the codec, the lexical detection layer and its separate dictionary module, the bank signatures, the now-mandatory preview step, and sources/templates in the SREF envelope. Migration v17 and its four CHECK-guarded columns are listed in the migrations table. - Stale counts corrected against the tree, not by arithmetic: 16 -> 17 migrations (both files), `src/components/import/` 13 -> 14, `src/utils/` 4 -> 13. Tables (20) and indexes (24) were re-measured and are NOT stale -- v17 is an ALTER TABLE only -- so they are left as they are, with the reason written down. ADR 0018, missing from the ADR table, is added. - The user guide and the `docs.*` keys in both locales carry the same new import journey: automatic detection, confidence score, mandatory preview with its signed recap, sign inversion, recognised bank formats, drift panel, and the safe repair path. - Both changelogs carry the same entries, translated, verified section by section including issue references. The `public/` copies sync automatically via `syncChangelogs()`. 1176 vitest green, build clean, cargo check clean. No DB migration. Resolves #332 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
179 lines
11 KiB
Markdown
179 lines
11 KiB
Markdown
# CLAUDE.md — Simpl'Résultat
|
|
|
|
@STATE.md
|
|
|
|
## Contexte du projet
|
|
|
|
**Simpl'Résultat** est une application de bureau desktop **privacy-first** pour la gestion des finances personnelles. Elle traite localement les fichiers CSV bancaires sans aucune dépendance cloud. Projet solo entrepreneurial, en développement par Max.
|
|
|
|
**Stack technique :** Tauri v2 + React 19 + TypeScript + Tailwind CSS v4
|
|
**Backend :** Rust (commandes Tauri)
|
|
**Stockage :** SQLite local (tauri-plugin-sql)
|
|
**Langues supportées :** Français (FR) et Anglais (EN)
|
|
**Plateformes :** Windows, Linux
|
|
**Version actuelle :** 0.6.3
|
|
**Licence :** GPL-3.0-only
|
|
|
|
---
|
|
|
|
## Principes fondamentaux
|
|
|
|
### Privacy-first — NON NÉGOCIABLE
|
|
- Zéro donnée envoyée vers un serveur tiers
|
|
- Tout le traitement CSV et toutes les données financières restent en local
|
|
- Aucune télémétrie, aucun analytics cloud
|
|
|
|
### Précision financière
|
|
- Toujours valider les montants selon les règles de parsing configurables (gestion des virgules/points, espaces, symboles monétaires)
|
|
- Gérer l'encodage des fichiers CSV (UTF-8, Windows-1252, ISO-8859-15)
|
|
|
|
### Internationalisation (i18n)
|
|
- Toute chaîne affichée à l'utilisateur doit passer par le système i18n (i18next + react-i18next)
|
|
- Jamais de texte en dur dans les composants React
|
|
- Fichiers de traduction : `src/i18n/locales/fr.json` et `src/i18n/locales/en.json`
|
|
|
|
---
|
|
|
|
## Architecture & structure du code
|
|
|
|
```
|
|
src/
|
|
├── components/ # 53 composants React organisés par domaine
|
|
│ ├── adjustments/ # Ajustements
|
|
│ ├── budget/ # Budget
|
|
│ ├── categories/ # Catégories hiérarchiques
|
|
│ ├── dashboard/ # Tableau de bord
|
|
│ ├── import/ # Wizard d'import (14 composants)
|
|
│ ├── layout/ # AppShell, Sidebar
|
|
│ ├── profile/ # Profils (PIN, formulaire, switcher)
|
|
│ ├── reports/ # Graphiques et rapports
|
|
│ ├── settings/ # Paramètres
|
|
│ ├── shared/ # Composants réutilisables
|
|
│ └── transactions/ # Transactions
|
|
├── contexts/ # ProfileContext (état global profil)
|
|
├── hooks/ # 13 hooks custom (useReducer)
|
|
├── pages/ # 11 pages
|
|
├── services/ # 14 services métier
|
|
├── shared/ # Types et constantes partagés
|
|
├── utils/ # Utilitaires (parsing, CSV, charts)
|
|
├── i18n/ # Config i18next + locales FR/EN
|
|
├── App.tsx # Router principal (react-router-dom)
|
|
└── main.tsx # Point d'entrée
|
|
|
|
src-tauri/
|
|
├── src/
|
|
│ ├── commands/ # 3 modules, 17 commandes Tauri
|
|
│ │ ├── fs_commands.rs # Système de fichiers (6 commandes)
|
|
│ │ ├── export_import_commands.rs # Export/import chiffré (5 commandes)
|
|
│ │ └── profile_commands.rs # Gestion des profils (6 commandes)
|
|
│ ├── database/ # Schémas SQL et migrations
|
|
│ │ ├── schema.sql # Schéma initial (v1)
|
|
│ │ ├── seed_categories.sql # Seed catégories (v2)
|
|
│ │ └── consolidated_schema.sql # Schéma complet (nouveaux profils)
|
|
│ ├── lib.rs # Point d'entrée, 17 migrations inline, plugins
|
|
│ └── main.rs
|
|
└── Cargo.toml
|
|
```
|
|
|
|
**Règles d'architecture :**
|
|
- La logique métier va dans `services/`, jamais directement dans les composants
|
|
- L'état de chaque domaine est géré par un hook `useReducer` dédié dans `hooks/`
|
|
- Les composants React sont responsables de l'affichage uniquement
|
|
- Toute opération sur les fichiers système passe par les commandes Tauri (Rust)
|
|
- Les requêtes SQL passent par les services TypeScript via `tauri-plugin-sql`
|
|
|
|
---
|
|
|
|
## Fonctionnalités principales
|
|
|
|
- **Import CSV** : wizard multi-étapes, détection auto (encodage, délimiteur, colonnes par libellé FR/EN, formats de banques connus) avec score de confiance, **aperçu obligatoire à récap signé** avant tout import, templates de config, déduplication par fichier. Le format d'import est **persisté en entier sur la source et jamais re-deviné** — [ADR 0019](docs/adr/0019-format-import-persiste.md)
|
|
- **Catégorisation** : automatique (mots-clés avec priorité) et manuelle, drag-and-drop pour réorganiser
|
|
- **Transactions** : filtrage, tri, split sur plusieurs catégories, notes
|
|
- **Budget** : grille 12 mois, templates réutilisables, budget vs réel
|
|
- **Rapports** : tendances mensuelles, répartition par catégorie, évolution dans le temps, graphiques interactifs (SVG patterns, menu contextuel)
|
|
- **Multi-profils** : bases de données séparées, protection par PIN (Argon2), switching rapide
|
|
- **Export/Import** : JSON/CSV avec chiffrement AES-256-GCM optionnel (format SREF)
|
|
- **Mises à jour** : auto-updater intégré (tauri-plugin-updater)
|
|
- **Changelog bilingue** : page `/changelog` avec historique complet, notes de version dynamiques FR/EN depuis `CHANGELOG.md` / `CHANGELOG.fr.md` (bundlés dans `public/`)
|
|
|
|
---
|
|
|
|
## Conventions de code
|
|
|
|
### React / TypeScript
|
|
- Un composant = un fichier `.tsx`, nommé en PascalCase
|
|
- Hooks custom dans `hooks/`, services dans `services/`
|
|
- État local via `useReducer` dans les hooks de domaine
|
|
|
|
### Rust / Tauri
|
|
- Toutes les commandes Tauri retournent `Result<T, String>` pour la gestion d'erreurs
|
|
- Documenter chaque commande avec un commentaire sur son rôle
|
|
|
|
### Général
|
|
- Commits en anglais, commentaires de code en anglais
|
|
- Messages d'interface en français ET anglais (via i18n)
|
|
- Tester les cas limites de parsing CSV (montants négatifs, cellules vides, formats inattendus)
|
|
|
|
---
|
|
|
|
## Base de données
|
|
|
|
- **20 tables** SQLite, **24 index** (voir `docs/architecture.md` pour le détail). Le module Bilan en représente 7 tables (`balance_categories`, `balance_accounts`, `balance_snapshots`, `balance_snapshot_lines`, `balance_account_transfers`, puis `balance_securities` + `balance_snapshot_holdings` ajoutées en Étape 2 — détail par titre) et 9 index. Ces deux comptes sont inchangés depuis v13 : v14-v16 ajoutent 2 tables + 2 index (déjà comptés), v17 est un `ALTER TABLE` pur
|
|
- **17 migrations inline** dans `lib.rs` (v1→v17, via `tauri_plugin_sql::Migration`). Étape 2 du Bilan (détail par titre) : v14 (`balance_securities` + `balance_snapshot_holdings` + 2 index), v15 (`balance_accounts.kind` + `detailed_since` + backfill), v16 (conversion des comptes cotés existants en détaillés 1-position) — voir [ADR 0015](docs/adr/0015-balance-detail-par-titre.md). Import : v17 (`import_sources.amount_mode` + `sign_convention`, les deux avec `CHECK`, + `header_signature` + `template_id`) — voir [ADR 0019](docs/adr/0019-format-import-persiste.md)
|
|
- **Schéma consolidé** (`consolidated_schema.sql`) pour l'initialisation des nouveaux profils
|
|
- Les migrations appliquées sont protégées par checksum — ne jamais modifier une migration existante, toujours en créer une nouvelle
|
|
|
|
---
|
|
|
|
## Documentation technique
|
|
|
|
La documentation technique est centralisée dans `docs/` :
|
|
- `docs/architecture.md` — Architecture technique complète (stack, BDD, services, hooks, commandes Tauri, routing, i18n, CI/CD)
|
|
- `docs/adr/` — Architecture Decision Records (décisions techniques structurantes)
|
|
- `docs/guide-utilisateur.md` — Guide utilisateur
|
|
- `docs/archive/` — Anciennes spécifications archivées
|
|
|
|
**Règle : quand un changement touche l'architecture, mettre à jour la documentation :**
|
|
- Nouveau service, hook, commande Tauri, page/route, ou table SQL → mettre à jour `docs/architecture.md`
|
|
- Décision technique structurante (choix de librairie, pattern architectural, changement de stratégie) → créer un nouvel ADR dans `docs/adr/`
|
|
- Changement affectant l'utilisation de l'app → mettre à jour `docs/guide-utilisateur.md` et les traductions i18n correspondantes (`src/i18n/locales/fr.json`, `src/i18n/locales/en.json`, clés sous `docs.*`)
|
|
|
|
**Règle CHANGELOG :** tout changement affectant le comportement utilisateur → ajouter une entrée sous `## [Unreleased]` dans **les deux fichiers** :
|
|
- `CHANGELOG.md` (anglais) — source principale
|
|
- `CHANGELOG.fr.md` (français) — traduction
|
|
- Catégories : Added/Ajouté, Changed/Modifié, Fixed/Corrigé, Removed/Supprimé
|
|
- Format [Keep a Changelog](https://keepachangelog.com/). Le contenu est extrait automatiquement par le CI pour les release notes et affiché dans l'app selon la langue de l'utilisateur.
|
|
- The `public/` copies are synced automatically: Vite copies them on `dev`/`build` start via `syncChangelogs()` in `vite.config.ts`. No manual sync needed.
|
|
|
|
---
|
|
|
|
## Points d'attention RS&DE / CRIC
|
|
|
|
Pour maintenir l'éligibilité aux crédits d'impôt R&D (RS&DE fédéral + CRIC Québec) :
|
|
- Documenter les **incertitudes technologiques** rencontrées pendant le développement
|
|
- Noter les expérimentations et les approches alternatives testées
|
|
- Garder un journal des avancées techniques (dans `/docs/rnd-journal/`)
|
|
- Les algorithmes de catégorisation automatique et le parsing multi-format sont des activités R&D éligibles
|
|
|
|
---
|
|
|
|
## CI/CD
|
|
|
|
Workflows Forgejo Actions dans `.forgejo/workflows/`. Le runner est à **capacité 1** — les jobs se suivent, ils ne tournent pas en parallèle.
|
|
|
|
- **`check-rust.yml`** — déclenché sur les PR touchant `src-tauri/**` ou `.cargo/**`. Lance `cargo check`, une vérification bloquante que les advisories acceptées restent non atteignables, `cargo test` et un `cargo audit` informatif. Doit être vert avant tout merge.
|
|
- **`check-frontend.yml`** — déclenché sur les PR, sauf si tous les fichiers modifiés sont du Rust, de la doc ou du markdown. Lance `npm run build` (tsc + vite) et `npm test` (vitest). Doit être vert avant tout merge. **Aucune étape `npm audit`** : les advisories npm ne sont pas un gate de CI. `npm audit` remonte 2 high en permanence — une seule advisory `react-router` (mode RSC, inatteignable dans une app de bureau sans serveur), acceptée et suivie en [#317](https://git.lacompagniemaximus.com/maximus/simpl-resultat/issues/317).
|
|
- **`audit.yml`** — audit RustSec quotidien (06:00 UTC) + `workflow_dispatch`, pour couvrir les avis de sécurité entre deux PR Rust. Échec bloquant. **Un run vert signifie « zéro advisory hors de la liste acceptée »**, pas « zéro advisory » : cette liste est dans `.cargo/audit.toml` (preuve de non-atteignabilité et condition de retrait par entrée), encadrée par l'[ADR 0018](docs/adr/0018-suppression-advisories-non-atteignables.md). Ne jamais y ajouter une advisory atteignable ni élargir une entrée à un crate entier.
|
|
- **`release.yml`** — déclenché par les tags `v*`. Build Windows (NSIS `.exe`) + Linux (`.deb`, `.rpm`), signe les binaires et publie le JSON d'updater pour les mises à jour automatiques.
|
|
|
|
Aucun workflow `check-*` ne filtre sur `branches:` : une PR stackée sur une autre branche de feature déclenche donc bien la CI. Le cache Actions est retiré partout tant que [#234](https://git.lacompagniemaximus.com/maximus/simpl-resultat/issues/234) (connectivité du serveur de cache) n'est pas réglé — restore et save échouent tous les deux. Le miroir `.github/workflows/` est dormant (aucune PR côté GitHub).
|
|
|
|
---
|
|
|
|
## Ressources clés
|
|
|
|
- [Tauri v2 Docs](https://v2.tauri.app/)
|
|
- [React Docs](https://react.dev/)
|
|
- [SQLite via Tauri](https://github.com/tauri-apps/tauri-plugin-sql)
|
|
- Architecture détaillée : `docs/architecture.md`
|
|
- Décisions techniques : `docs/adr/`
|