Remplace le rangement plat projects/<slug>/ par une vraie arborescence
par compte créateur, sans toucher aux routes existantes (aucune ne
déclare de "/" dans son <slug> : le chemin composé "propriétaire_projet"
reste un détail interne à db/, décodé par db/games/project_slug.py, seul
fichier à modifier si la convention change un jour).
- db/game_dir.py, create_game.py, delete_game.py, list_games.py,
move_game.py : résolvent/construisent ce chemin composé. Bénéfice
direct : deux comptes différents peuvent chacun avoir un projet nommé
pareil sans collision (l'unicité ne se vérifie plus que par dossier
propriétaire). move_game.py renomme désormais le dossier PROPRIÉTAIRE
entier (changement d'email), prêt pour un futur multi-projet.
- scripts/migrate_flat_project_slugs.py : migration des projets déjà
créés sous l'ancien rangement plat (simulation par défaut, --apply
pour exécuter).
- routes/auth/profile.py, tests/conftest.py : suppression de compte/jeu
de test via db.delete_game (nettoie aussi le dossier propriétaire
devenu vide) plutôt qu'un shutil.rmtree direct du seul dossier projet.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Première brique du plan "Fondations d'une plateforme multi-éditeurs" —
l'utilisateur veut un éditeur dédié aux jeux 2D/serious games (scène à
coordonnées pixel fixes, objets en couches, collision, personnages
animés), distinct de l'éditeur générique actuel, sans dupliquer ce qui
peut être partagé (comptes, objets de données, moteur de logique de
flow, hébergement/publication).
- db/games/get_game_type.py (nouveau) : "document" (défaut, éditeur
actuel) ou "jeu_2d" (nouveau), stocké dans _meta comme
is_public_played — aucune migration pour les jeux déjà créés
(retombent sur "document"). Choisi obligatoirement à la création
(templates/index.html), jamais modifiable ensuite.
- screens/scenes/ (nouveau sous-module) : table _scene_objects (une
scène = des objets en pixels fixes, pas les % fluides de
_screen_elements — indispensable pour la collision/l'animation),
CRUD complet, rendu HTML. kind="personnage" réutilise TELLE QUELLE la
structure _personnage_data et les fonctions resolve_personnage_* déjà
écrites pour le widget "personnage" de l'éditeur document (Phase 8) —
même bibliothèque Forge, même moteur d'animation, juste une autre
table de stockage.
- screens/flow/ensure_flow_schema.py : += trigger_object_id/
target_object_id (ALTER TABLE sans contrainte FK, même patron que
cond_element_a) — le moteur de logique de flow (_flow_nodes/_flow_edges,
flow-engine.js) reste EXACTEMENT le même pour les deux éditeurs, seule
la palette de nœuds change (screens/scenes/flow_palette.py, nouveau :
sous-ensemble direct des triggers/actions existants, déjà génériques).
- screens/screens_repo/ensure_schema.py : += scene_width/scene_height
sur _screens (taille de scène fixe en pixels, sans effet sur un écran
"document").
Reste à faire (prochains commits) : route + template de l'éditeur de
scène, puis le rendu en mode jouable.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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>