CIA/e-voting-system/.claude/CONTRIBUTING.md
E-Voting Developer 5bebad45b8 Initial commit: Complete e-voting system with cryptography
- FastAPI backend with JWT authentication
- ElGamal, RSA-PSS, ZK-proofs crypto modules
- HTML5/JS frontend SPA
- MariaDB database with 5 tables
- Docker Compose with 3 services (frontend, backend, mariadb)
- Comprehensive tests for cryptography
- Typst technical report (30+ pages)
- Makefile with development commands
2025-11-03 16:13:08 +01:00

6.7 KiB

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
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

make install
cp .env.example .env
make up

Développement

# Terminal 1 : Backend
make dev

# Terminal 2 : Logs
make logs

# Terminal 3 : Tests
make test

Avant de commit

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

# Vérifier les vulnérabilités
poetry audit

# Mettre à jour
poetry update

Documentation

Code

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

import cProfile
cProfile.run('function_to_profile()', sort='cumulative')

Benchmarks

# Exemple de benchmark
time poetry run python -m pytest tests/test_crypto.py::TestElGamalEncryption -v

Troubleshooting

Erreur d'import

# ❌ Mauvais
from .models import Voter
from .services import VoterService

# ✅ Bon (depuis backend/)
from backend.models import Voter
from backend.services import VoterService

Type hints

# ❌ 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

Questions ?

Consultez le rapport technique : rapport/main.typ