Commit Graph
3 Commits
Author SHA1 Message Date
williamandClaude Sonnet 5 c57420c8c9 Phase 3 : hardening qualite de code - typage strict, securite, dead code, a11y
Config strictement stricte partout (ruff, mypy --strict, bandit, vulture,
import-linter, eslint, stylelint), aucune regle desactivee "pour ne pas
casser le build" - l'existant a ete corrige pour la satisfaire plutot que
l'inverse. Hooks pre-commit locaux (language: system) bloquants.

- Typage mypy --strict propage a tout le moteur (db, screens, auth, core,
  ai, routes, puis publish/scripts/tests/app.py/build_css.py).
- Securite : fuite de handle fichier Windows corrigee dans l'export SCORM
  (routes/publish/export_scorm.py), CSRF/RNG non-crypto/xAPI documentes
  (# nosec, # NOSONAR justifies), nouveau db.json_for_script() (echappe
  "</script>" dans le JSON embarque en <script>, 25 sites).
- Architecture : imports circulaires/F811 nettoyes, contrats
  import-linter respectes, code mort retire (vulture).
- Accessibilite : 69 champs de formulaire sans label correctement
  associe corriges (for/id ou aria-label) sur 11 templates.
- ESLint/Stylelint : lot mecanique JS/CSS, regles ajustees puis
  appliquees (aucune desactivee sans verification individuelle).
- Tests : isolation du compte admin partage (nettoyage ponctuel +
  fixture de teardown automatique en filet de securite), suite complete
  verte (591 tests Python, 241 tests JS).
- SonarQube Community Build self-heberge (Docker + PostgreSQL) : rapport
  complet analyse point par point, faux positifs documentes.
- .gitattributes ajoute (LF force) : core.autocrlf=true sur cette machine
  faisait echouer ESLint (linebreak-style) via un bug connu de git
  (checkout "en place" qui ignore l'eol force sur un fichier deja
  present sur disque - contourne en supprimant puis recreant chaque
  fichier suivi).

djLint (H021, styles inline) volontairement saute pour ce commit -
backlog assume, deja documente, traite dans un lot separe.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-15 16:06:15 +02:00
williamandClaude Sonnet 5 c8c949c430 Ajoute la régénération des codes de récupération et le changement d'email
Depuis /profile :
- "Codes de récupération 2FA" : régénère les 10 codes (invalide les 10
  précédents d'un coup, voir auth.generate_recovery_codes) et les affiche
  une seule fois via le même modal qu'à l'inscription (session flash,
  core/recovery_codes_flash.py) — mot de passe actuel requis.
- "Adresse email" : change l'adresse (mêmes règles qu'à l'inscription —
  format valide, unicité — voir auth/email_validation.py, désormais
  partagé avec create_user.py au lieu d'être dupliqué). Pour un compte
  "user", le dossier de son unique projet porte le nom de son adresse
  (project_slug = slugify(email)) : il est renommé pour suivre le
  changement (db/games/move_game.py, même logique d'unicité par suffixe
  que create_game()), sans quoi project_slug ne correspondrait plus à
  aucun dossier réel. Un "admin" n'a pas de project_slug dédié : rien
  n'est renommé pour ce rôle.

18 nouveaux tests (tests/test_profile.py) : mauvais mot de passe refusé
pour les deux actions, mauvais format/email déjà pris refusés, dossier
bien renommé et project_slug mis à jour, connexion possible avec la
nouvelle adresse, anciens codes de récupération bien invalidés après
régénération, modal jamais réaffiché deux fois.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-29 06:29:38 +02:00
williamandClaude Sonnet 5 d90abc827b Ajoute l'authentification : inscription, mot de passe fort, 2FA obligatoire, isolation par utilisateur
Première des deux grandes fonctionnalités demandées (authentification
d'abord, export HTML/CSS/JS autonome ensuite) :

- Inscription (nom, prénom, email UNIQUE, mot de passe) avec schéma
  visuel du mot de passe (jauge + liste de critères qui passent au vert
  en direct — auth/password_strength.py, mêmes règles vérifiées côté
  serveur qu'affichées côté client).
- Double authentification (TOTP, compatible Google Authenticator/Authy)
  OBLIGATOIRE dès l'inscription : QR code (SVG, sans dépendance Pillow)
  à scanner puis code à confirmer avant que le compte soit utilisable —
  voir auth/create_user.py (totp_confirmed) et routes/auth/register_2fa.py.
- Connexion en 2 temps (mot de passe puis code TOTP), déconnexion.
- Isolation par utilisateur : un compte "user" est limité à un SEUL
  projet, dont le dossier est nommé d'après son adresse email (slugifiée)
  et créé automatiquement dès la 2FA confirmée — aucune page de gestion
  multi-jeux pour lui (redirigé directement vers son propre tableau de
  bord). Le rôle "admin" reste illimité, comme le moteur l'a toujours été
  (le TOUT PREMIER compte jamais créé sur une base de comptes vide devient
  automatiquement admin — voir auth/is_first_user.py — pas de mot de
  passe par défaut à faire circuler : s'inscrire en premier suffit).
  Un compte "user" ne peut pas non plus supprimer son unique projet
  (aucune façon d'en recréer un ensuite).
- Garde d'accès globale (core/auth_guard.py, un seul before_request) :
  toute page exige une connexion, sans avoir touché individuellement aux
  ~80 routes déjà existantes du moteur.

tests/conftest.py isole complètement les tests de la vraie base de
comptes (FORGE_USERS_DB_PATH/FORGE_SECRET_KEY_PATH vers un dossier
temporaire propre à la session de tests) et authentifie automatiquement
la fixture `client` partagée en tant que compte admin de test — les 155
tests déjà existants continuent de passer SANS AUCUNE modification de
leur côté, exactement comme avant l'authentification. 10 nouveaux tests
dédiés (tests/test_auth.py) : inscription/mots de passe/2FA/connexion/
isolation par projet/blocage de suppression, vérifiés en conditions
réelles (vrai client de test Flask, vraie base SQLite, vrais codes TOTP
calculés avec pyotp). 165 tests au total, tous au vert.

Nouvelles dépendances : pyotp, qrcode (requirements.txt).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-28 19:30:43 +02:00