# Recherche & Décisions Techniques — Budget Tracker ## Authentification - **Décision** : JWT (tokens access 15min + refresh 7j) via `python-jose` + `passlib[bcrypt]` - **Rationale** : stateless, compatible SPA React, aucune session serveur à gérer, facile à dockeriser - **Alternatives** : - Session cookies (plus simple mais couplé au serveur, complexe en CORS) - OAuth2 externe / Keycloak (overkill pour usage personnel) - FastAPI-Users (bibliothèque haut niveau — ajoute de la magie, préférence pour la transparence) ## Base de données - **Décision** : PostgreSQL 16 - **Rationale** : ACID natif (critique pour données financières), types UUID, ENUM, support transactionnel, standard de l'industrie - **Alternatives** : - SQLite (suffisant en dev, mais limité en concurrence et types) - MySQL (moins bon support UUID/ENUM natif) ## ORM & Migrations - **Décision** : SQLAlchemy 2.0 (mode async) + Alembic - **Rationale** : async natif pour FastAPI, migrations versionées et réversibles, mature et bien documenté - **Alternatives** : - Tortoise ORM (async natif mais moins mature, moins d'intégrations) - SQLModel (wrapper SQLAlchemy+Pydantic — moins de contrôle sur les modèles) - Prisma (Node.js uniquement) ## Framework Backend - **Décision** : FastAPI 0.111+ - **Rationale** : OpenAPI/Swagger auto-généré (conforme principe I de la Constitution), validation Pydantic intégrée, async natif, typage strict - **Alternatives** : - Django REST Framework (sync-first, plus lourd) - Flask (pas d'async natif, validation manuelle) ## Framework Frontend - **Décision** : React 18 + TypeScript + Vite - **Rationale** : écosystème riche, SPA adaptée à une app de gestion, typage fort réduit les erreurs sur les montants financiers - **Alternatives** : - Next.js (SSR inutile pour usage authentifié perso) - Vue 3 (viable mais écosystème plus réduit) ## Styling Frontend - **Décision** : Tailwind CSS 3 + shadcn/ui - **Rationale** : utilitaires CSS rapides, shadcn/ui fournit composants accessibles (formulaires, modales, tableaux) sans dépendance lourde - **Alternatives** : - MUI / Ant Design (plus lourds, style moins personnalisable) - CSS Modules (trop verbeux pour une SPA) ## Graphiques Frontend - **Décision** : Recharts - **Rationale** : composants React purs (pas de D3 direct), bon support responsive, Tailwind-compatible, léger (~180 ko gzip) - **Alternatives** : - Chart.js + react-chartjs-2 (moins idiomatic React, state management externe) - Nivo (très complet mais plus lourd, over-engineering pour 2 types de graphiques) - Victory (moins maintenu) ## Gestion d'état Frontend - **Décision** : TanStack Query (React Query) v5 - **Rationale** : cache serveur, invalidation automatique après mutations (soldes recalculés), gestion loading/error intégrée — évite un store global Redux pour des données essentiellement serveur - **Alternatives** : - Redux Toolkit (overkill, état global inutile si les données viennent de l'API) - SWR (moins de fonctionnalités sur les mutations) - Zustand (utile pour état local UI uniquement, complémentaire) ## Export CSV - **Décision** : module `csv` Python stdlib - **Rationale** : aucune dépendance additionnelle, suffisant pour colonnes tabulaires de transactions, streaming possible via `StreamingResponse` FastAPI - **Alternatives** : - pandas (overkill, dépendance lourde) ## Export PDF - **Décision** : WeasyPrint - **Rationale** : rendu HTML→PDF côté serveur, templates Jinja2 réutilisables, CSS support correct, rendu fidèle - **Alternatives** : - ReportLab (API bas niveau, verbeux pour des tableaux) - pdfkit (dépendance système wkhtmltopdf, difficile à dockeriser) - Reportlab + xhtml2pdf (moins stable) ## Stockage des montants - **Décision** : entiers en centimes (`amount_cents INTEGER`) - **Rationale** : conforme au principe II de la Constitution — élimine toute erreur d'arrondi IEEE 754 sur les opérations financières (ex : 0.1 + 0.2 ≠ 0.3 en float) - **Règle** : la conversion euros↔centimes se fait uniquement aux frontières (serialisation Pydantic et affichage React) ## Soft Delete - **Décision** : champ `deleted_at TIMESTAMP NULL` sur `Transaction` et `Category` - **Rationale** : conforme au principe II (tracabilité historique), permet l'audit et la restauration éventuelle - **Implémentation** : filtre `WHERE deleted_at IS NULL` systématique dans les requêtes ; index partiel recommandé ## Conteneurisation - **Décision** : Docker Compose (backend + frontend + PostgreSQL) - **Rationale** : conforme au principe V de la Constitution, reproductibilité dev/prod, un seul `docker compose up` - **Structure** : - `backend/` — image Python 3.12-slim - `frontend/` — build Vite servi par Nginx - `db/` — PostgreSQL 16 officiel ## Tests Backend - **Décision** : pytest + httpx (client async) + pytest-asyncio + base de données de test dédiée - **Rationale** : conforme au principe III (80% coverage services/), tests d'intégration sur vraie BDD (pas de mock SQLAlchemy) - **Alternatives** : - unittest (moins expressif) - mocks SQLAlchemy (rejeté — risque de divergence mock/prod)