Files
Forge-Engine/app.py
T
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

54 lines
2.6 KiB
Python

"""
app.py — moteur Forge, point d'entrée.
Lance un serveur web local. Fonctionnalités construites pour l'instant
(le reste viendra au fur et à mesure) :
1. Créer un jeu (dossier + index.html/css/js + base de données dédiée).
2. Définir des "objets" (comme des tables de base de données, avec des
champs typés, et des relations vers d'autres objets déjà définis).
3. Le moteur lit ces définitions et génère lui-même le formulaire adapté
pour saisir des données et les enregistrer dans la vraie base SQLite.
4. CRUD complet sur les trois niveaux (jeu / objet / donnée) : renommer
et supprimer un jeu, modifier une définition d'objet (ajouter/retirer
des champs) et la supprimer, modifier et supprimer une ligne de
données — avec blocage/avertissement quand une suppression casserait
une relation existante.
"""
import os
import threading
import webbrowser
import routes # noqa: F401 - enregistre toutes les routes sur `app`
from core import (
auth_guard, # noqa: F401 - enregistre la garde de connexion (après les routes)
csrf, # noqa: F401 - enregistre csrf_token() comme variable globale Jinja
csrf_guard, # noqa: F401 - enregistre la vérification du jeton CSRF
db_teardown_guard, # noqa: F401 - enregistre la fermeture des connexions SQLite fuitées
jinja_filters, # noqa: F401 - enregistre les filtres Jinja
recovery_codes_flash, # noqa: F401 - enregistre pop_recovery_codes() comme variable globale Jinja
)
from core.flask_app import app
def _open_browser() -> None:
webbrowser.open("http://127.0.0.1:5050/")
if __name__ == "__main__":
threading.Timer(1.0, _open_browser).start()
# threaded=True : le serveur de dev Werkzeug traite UNE requête à la
# fois par défaut — un jeu 2D charge des dizaines d'images (sprites de
# personnages, fonds...) en parallèle à chaque chargement de page, et
# sans ce réglage elles se mettaient en file d'attente une par une
# (bug remonté : un Ctrl+F5, qui recharge TOUT sans cache, laissait
# l'éditeur de scène "vide" le temps que les images finissent par
# arriver l'une après l'autre — un rechargement normal, servi surtout
# depuis le cache navigateur, le cachait).
# debug : jamais actif par defaut (Bandit B201 - le debogueur Werkzeug
# permet l'execution de code arbitraire) — activable en local via
# FORGE_DEBUG=1 dans .env, jamais utilise en production (gunicorn y
# sert app:app directement, ce bloc __main__ n'y tourne pas).
debug = os.environ.get("FORGE_DEBUG") == "1"
app.run(host="127.0.0.1", port=5050, debug=debug, use_reloader=False, threaded=True)