# Guide de Contribution ## Organisation du Code ``` e-voting-system/ ├── src/ │ ├── backend/ # API FastAPI │ │ ├── main.py # Point d'entrée │ │ ├── config.py # Configuration │ │ ├── models.py # Modèles SQLAlchemy │ │ ├── schemas.py # Schémas Pydantic │ │ ├── auth.py # Authentification │ │ ├── services.py # Logique métier │ │ ├── dependencies.py # DI FastAPI │ │ ├── database.py # Configuration BD │ │ └── routes/ # Routes API │ │ ├── auth.py │ │ ├── elections.py │ │ ├── votes.py │ │ └── __init__.py │ ├── crypto/ # Primitives cryptographiques │ │ ├── __init__.py │ │ ├── encryption.py # ElGamal, AES │ │ ├── signatures.py # RSA-PSS │ │ ├── zk_proofs.py # Fiat-Shamir │ │ └── hashing.py # SHA-256 │ └── frontend/ # Interface web │ └── index.html # SPA HTML5 ├── tests/ # Tests │ ├── test_crypto.py │ ├── test_backend.py # À créer │ ├── conftest.py │ └── __init__.py ├── docker/ # Configuration Docker │ ├── Dockerfile.backend │ ├── Dockerfile.frontend │ └── init.sql ├── rapport/ # Documentation (Typst) │ └── main.typ ├── pyproject.toml # Dépendances Python ├── docker-compose.yml # Orchestration ├── Makefile # Commandes de dev ├── README.md # Ce fichier └── .gitignore ``` ## Standards de Code ### Style Python - **Formatage** : Black (88 chars de limite) - **Linting** : Ruff - **Type Hints** : Obligatoires pour les fonctions publiques - **Docstrings** : Google style ```python def create_voter(db: Session, voter: schemas.VoterRegister) -> models.Voter: """ Créer un nouvel électeur. Args: db: Session de base de données voter: Données d'enregistrement Returns: Voter créé Raises: ValueError: Si l'email existe déjà """ pass ``` ### Naming Conventions - **Classes** : PascalCase (`VoterService`, `ElGamalEncryption`) - **Functions** : snake_case (`get_voter_by_email()`) - **Constants** : UPPER_CASE (`DB_HOST`, `MAX_RETRIES`) - **Private** : Prefix underscore (`_internal_function()`) ### Tests - Fichiers : `test_*.py` - Fonctions : `test_*_scenario()` - Assertions claires : `assert result == expected` - Coverage : Minimum 80% ## Git Workflow ### Branches - `main` : Code stable - `dev` : Développement en cours - `feature/*` : Nouvelles fonctionnalités - `bugfix/*` : Corrections - `doc/*` : Documentation ### Commits Format : ``` [TYPE] Titre du commit Description détaillée si nécessaire. - Point 1 - Point 2 Fixes #123 ``` Types : - `[FEAT]` : Nouvelle fonctionnalité - `[FIX]` : Correction de bug - `[DOCS]` : Documentation - `[REFACTOR]` : Restructuration - `[TEST]` : Tests - `[CHORE]` : Maintenance ### Pull Requests 1. Créer une branche depuis `dev` 2. Faire les changements 3. Écrire des tests 4. Formater le code : `make format` 5. Vérifier les lints : `make lint` 6. Commiter avec messages clairs 7. Ouvrir une PR sur `dev` 8. Review + merge ## Développement Local ### Setup ```bash make install cp .env.example .env make up ``` ### Développement ```bash # Terminal 1 : Backend make dev # Terminal 2 : Logs make logs # Terminal 3 : Tests make test ``` ### Avant de commit ```bash make format # Formater make lint # Vérifier make test # Tester ``` ## Ajouter une Nouvelle Fonctionnalité ### Exemple : Authentification multi-facteur (MFA) 1. **Design** : Planifier l'architecture - Comment stocker les secrets 2FA ? - QR codes ou SMS ? - Récupération ? 2. **Backend** : - Ajouter colonne `mfa_secret` à `voters` - Créer endpoints `/auth/mfa/enable` et `/auth/mfa/verify` - Tests dans `test_backend.py` 3. **Frontend** : - Ajouter Vue MFA dans `index.html` - Intégrer lib de QR code 4. **Documentation** : - Mettre à jour `DEPLOYMENT.md` - Commenter le code 5. **Tests** : - Tests unitaires du MFA - Tests d'intégration login+MFA 6. **PR** : - Décrire les changements - Lier les issues - Demander review ## Sécurité ### Checklist de Sécurité - [ ] Pas de secrets en dur (utiliser `.env`) - [ ] Validation des entrées (Pydantic) - [ ] Authentification sur tous les endpoints privés - [ ] Rate limiting si applicable - [ ] CORS restrictif - [ ] Logs pas de données sensibles - [ ] Dépendances à jour (check CVE) ### Dépendances ```bash # Vérifier les vulnérabilités poetry audit # Mettre à jour poetry update ``` ## Documentation ### Code ```python def homomorphic_add(a: Ciphertext, b: Ciphertext, p: int) -> Ciphertext: """ Additionner deux ciphertexts ElGamal. L'addition homomorphe ElGamal: E(m1) * E(m2) = E(m1 + m2) Mathématiquement: c1_sum = (a.c1 * b.c1) mod p c2_sum = (a.c2 * b.c2) mod p Cette propriété est cruciale pour le dépouillement sécurisé. Example: >>> vote1 = eg.encrypt(pk, 1) >>> vote2 = eg.encrypt(pk, 0) >>> total = homomorphic_add(vote1, vote2, p) >>> result = eg.decrypt(sk, total, p) >>> assert result == 1 """ pass ``` ### Rapports Tous les rapports vont dans `rapport/` en `.typ` (Typst) - Inclure diagrams et formules - Citer les sources - Expliquer les choix ## Performance ### Profiling ```python import cProfile cProfile.run('function_to_profile()', sort='cumulative') ``` ### Benchmarks ```bash # Exemple de benchmark time poetry run python -m pytest tests/test_crypto.py::TestElGamalEncryption -v ``` ## Troubleshooting ### Erreur d'import ```python # ❌ Mauvais from .models import Voter from .services import VoterService # ✅ Bon (depuis backend/) from backend.models import Voter from backend.services import VoterService ``` ### Type hints ```python # ❌ Mauvais def get_voters(db): return db.query(models.Voter).all() # ✅ Bon def get_voters(db: Session) -> List[models.Voter]: return db.query(models.Voter).all() ``` ## Ressources - [FastAPI Docs](https://fastapi.tiangolo.com/) - [SQLAlchemy ORM](https://docs.sqlalchemy.org/) - [Pydantic Validation](https://docs.pydantic.dev/) - [Python Cryptography](https://cryptography.io/) - [Typst Docs](https://typst.app/) ## Questions ? Consultez le rapport technique : `rapport/main.typ`