# SSA Box Manager v2

Refonte Symfony 8 de l’application SSA Box Manager pour Saint Seiya Awakening.

L’objectif de cette v2 est de reprendre le socle de la v1, corriger ses limites, améliorer la maintenabilité et préparer les futures fonctionnalités communautaires.

## Stack technique

- Symfony 8
- PHP 8.4
- Doctrine ORM / Migrations
- Twig
- AssetMapper
- CSS natif
- JavaScript natif modulaire
- MySQL / MariaDB
- Composer
- Développement local Windows
- Déploiement prévu sur OVH mutualisé Pro

Le projet n’utilise pas Docker, Node, Webpack, SCSS, EasyAdmin ou SPA séparée.

## Installation locale

Cloner le projet puis installer les dépendances :

```bash
composer install
```

Créer le fichier local d’environnement :

```bash
copy .env .env.local
```

Adapter ensuite `.env.local`.

Exemple minimal :

```dotenv
APP_ENV=dev
APP_SECRET=change_me

DATABASE_URL="mysql://user:password@127.0.0.1:3306/ssa_boxmanager_v2?serverVersion=8.0.32&charset=utf8mb4"

MAILER_DSN=null://null
APP_MAILER_FROM_ADDRESS=no-reply@ssa-boxmanager.local
APP_MAILER_FROM_NAME="SSA Box Manager"
```

## Base de données

Créer la base si elle n’existe pas :

```bash
php bin/console doctrine:database:create --if-not-exists
```

Exécuter les migrations :

```bash
php bin/console doctrine:migrations:migrate
```

Vérifier le mapping Doctrine :

```bash
php bin/console doctrine:schema:validate
```

Vérifier l’état des migrations :

```bash
php bin/console doctrine:migrations:status
```

Avant de passer à une nouvelle US qui modifie le mapping Doctrine, l’état attendu est :

```text
New: 0
```

Si une migration est disponible mais pas exécutée, lancer :

```bash
php bin/console doctrine:migrations:migrate
```

## Fixtures de développement

Le Sprint 2 ajoute des fixtures de données jeu.

Installer le bundle si nécessaire :

```bash
composer require --dev doctrine/doctrine-fixtures-bundle
```

Charger les fixtures sans supprimer les utilisateurs locaux :

```bash
php bin/console doctrine:fixtures:load --append
```

Les fixtures créent ou mettent à jour notamment :

```text
Rangs : EX, SS, S, A, B, C
Rôles : dps, support, control, tank, heal
Sections : bronze_saints, gold_saints, specters, gods, asgard
Saints : Gemini Saga, Aries Mu, Pegasus Seiya, Asgard Siegfried
```

Fichier principal :

```text
src/DataFixtures/GameDataFixtures.php
```

## Lancement local

Avec Symfony CLI :

```bash
symfony server:start
```

Ou avec le serveur PHP natif :

```bash
php -S 127.0.0.1:8000 -t public
```

L’application est ensuite accessible sur :

```text
http://127.0.0.1:8000
```

Si le navigateur affiche `127.0.0.1 n’autorise pas la connexion`, vérifier d’abord que le serveur local tourne :

```bash
symfony server:status
```

Puis relancer si besoin :

```bash
symfony server:start
```

## Assets

Le projet utilise AssetMapper.

Entrée front :

```text
assets/app.js
```

Entrée admin :

```text
assets/admin.js
```

Les CSS sont factorisés par contexte.

CSS front :

```text
assets/styles/front/
├── 00-tokens.css
├── 01-base.css
├── 02-layout.css
├── 03-components.css
├── 04-auth.css
├── 05-saints.css
└── 06-errors.css
```

CSS admin :

```text
assets/styles/admin/
├── 00-tokens.css
├── 01-base.css
├── 02-layout.css
├── 03-components.css
├── 04-tables.css
├── 05-forms.css
└── 06-saints.css
```

JavaScript front :

```text
assets/js/front/
```

JavaScript admin :

```text
assets/js/admin/
```

Vérifier la carte des assets :

```bash
php bin/console debug:asset-map
```

Compiler les assets pour la production :

```bash
php bin/console asset-map:compile
```

En développement, Symfony peut servir les assets dynamiquement.

## Organisation applicative

Les éléments liés au front sont rangés dans des dossiers `Front`.

Les éléments liés à l’admin sont rangés dans des dossiers `Admin`.

Les éléments transverses restent dans les dossiers racine métier.

```text
src/
├── Controller/
│   ├── Admin/
│   ├── Api/
│   ├── Front/
│   └── Security/
├── DTO/
│   └── Api/
├── DataFixtures/
├── Entity/
├── Enum/
├── EventSubscriber/
│   └── Api/
├── Exception/
│   └── Api/
├── Form/
│   ├── Admin/
│   ├── Front/
│   └── Security/
├── Repository/
├── Security/
└── Service/
    ├── Admin/
    ├── Api/
    ├── Front/
    ├── Game/
    └── Security/
```

Conventions :

- les contrôleurs restent minces ;
- la logique métier va dans `src/Service/` ;
- les classes techniques Symfony Security vont dans `src/Security/` ;
- les contrôleurs API vont dans `src/Controller/Api/` ;
- les DTO API vont dans `src/DTO/Api/` ;
- les exceptions API vont dans `src/Exception/Api/` ;
- les subscribers API vont dans `src/EventSubscriber/Api/` ;
- les services API vont dans `src/Service/Api/` ;
- les formulaires sont rangés par contexte ;
- les enums transverses vont dans `src/Enum/` ;
- les repositories restent dans `src/Repository/`.

## Organisation des templates

Les templates sont séparés entre front et admin.

```text
templates/
├── front/
│   ├── account/
│   ├── partials/
│   ├── saint/
│   └── security/
├── admin/
│   ├── dashboard/
│   ├── rank/
│   ├── role/
│   ├── saint/
│   └── section/
└── bundles/
    └── TwigBundle/
        └── Exception/
```

Le layout front principal est :

```text
templates/front/base.html.twig
```

Les partials front sont dans :

```text
templates/front/partials/
```

Le layout admin principal est :

```text
templates/admin/base.html.twig
```

Les pages d’erreur personnalisées sont dans :

```text
templates/bundles/TwigBundle/Exception/
```

## Pages d’erreur

Le Sprint 2 ajoute des templates d’erreur personnalisés :

```text
templates/bundles/TwigBundle/Exception/error404.html.twig
templates/bundles/TwigBundle/Exception/error403.html.twig
templates/bundles/TwigBundle/Exception/error.html.twig
```

En environnement `dev`, Symfony affiche volontairement les pages d’exception techniques.

Pour prévisualiser les pages d’erreur personnalisées en dev, la route suivante peut être activée :

```text
config/routes/dev/framework.yaml
```

Contenu attendu :

```yaml
when@dev:
    _errors:
        resource: '@FrameworkBundle/Resources/config/routing/errors.php'
        prefix: /_error
```

Prévisualisation :

```text
/_error/404
/_error/403
/_error/500
```

## Authentification

Le Sprint 1 met en place le socle utilisateur :

- inscription ;
- confirmation email ;
- connexion ;
- déconnexion ;
- mot de passe oublié ;
- rate limits ;
- préparation migration v1 SHA-256.

### Identifiant de connexion

Le login se fait avec le `username`.

C’est volontaire pour assurer la compatibilité avec la v1, où le login historique est un username et non un email.

L’email reste nécessaire pour :

- les nouveaux comptes v2 ;
- la confirmation email ;
- la récupération de mot de passe ;
- la future liaison multi-box.

Les comptes legacy v1 peuvent temporairement ne pas avoir d’email en base.

### Confirmation email

Les nouveaux comptes v2 sont créés avec :

```text
is_verified = false
```

Ils doivent confirmer leur email avant de pouvoir se connecter.

En local, les emails ne sont pas réellement envoyés avec :

```dotenv
MAILER_DSN=null://null
```

Pendant le Sprint 1, les liens de confirmation sont loggés dans :

```text
var/log/dev.log
```

Rechercher :

```text
Email confirmation link generated.
```

### Mot de passe oublié

La récupération de mot de passe se fait uniquement par email.

Un compte legacy sans email ne peut pas demander de reset password via username, afin d’éviter une récupération de compte risquée.

Pendant le Sprint 1, les liens de reset password sont loggés dans :

```text
var/log/dev.log
```

Rechercher :

```text
Password reset link generated.
```

### Migration password v1

La v1 utilise un hash SHA-256 legacy.

La v2 prépare une migration transparente :

1. un compte legacy possède un hash SHA-256 en base ;
2. l’utilisateur se connecte avec son mot de passe habituel ;
3. Symfony accepte temporairement le hash legacy ;
4. après connexion réussie, le mot de passe est rehashé avec le hasher Symfony moderne ;
5. le hash legacy est nettoyé.

Champs concernés dans `app_user` :

```text
password
legacy_password_hash
legacy_password_migrated_at
```

## Rate limits

Le Sprint 1 ajoute des protections sur :

- login ;
- inscription ;
- demande de reset password.

Le login throttling est configuré dans :

```text
config/packages/security.yaml
```

Les limiters applicatifs sont configurés dans :

```text
config/packages/rate_limiter.yaml
```

Service dédié :

```text
src/Service/Security/AuthRateLimiterService.php
```

## Admin custom

Le Sprint 2 ajoute un début de backoffice custom, sans EasyAdmin.

Layout admin :

```text
templates/admin/base.html.twig
```

Dashboard :

```text
src/Controller/Admin/DashboardController.php
templates/admin/dashboard/index.html.twig
```

Route principale :

```text
/admin
```

La zone admin est protégée par :

```text
ROLE_ADMIN
```

Règle attendue dans `config/packages/security.yaml` :

```yaml
access_control:
    - { path: ^/admin, roles: ROLE_ADMIN }
```

Pour donner temporairement le rôle admin à un compte local :

```sql
UPDATE app_user
SET roles = '["ROLE_ADMIN"]'
WHERE username = 'TON_USERNAME';
```

## Données jeu — Sprint 2

Le Sprint 2 pose les fondations des données jeu administrables.

Enums transverses :

```text
src/Enum/AppLocale.php
src/Enum/SaintGender.php
src/Enum/SaintStatus.php
```

Locales supportées :

```text
fr
en
es
pt
de
```

Fallback applicatif de contenu :

```text
fr
```

Statuts de Saint :

```text
draft
published
upcoming
expected
archived
```

Différence métier importante :

- `upcoming` : Saint annoncé, teasé, bêta, CN ou probablement à venir ;
- `expected` : Saint souhaité ou proposé par la communauté, non confirmé officiellement.

## Référentiels jeu

Entités de référentiel :

```text
src/Entity/Rank.php
src/Entity/RankTranslation.php
src/Entity/Role.php
src/Entity/RoleTranslation.php
src/Entity/Section.php
src/Entity/SectionTranslation.php
```

Repositories :

```text
src/Repository/RankRepository.php
src/Repository/RoleRepository.php
src/Repository/SectionRepository.php
```

Tables SQL :

```text
game_rank
game_rank_translation
game_role
game_role_translation
game_section
game_section_translation
```

Routes admin :

```text
/admin/ranks
/admin/ranks/new
/admin/ranks/{id}/edit

/admin/roles
/admin/roles/new
/admin/roles/{id}/edit

/admin/sections
/admin/sections/new
/admin/sections/{id}/edit
```

Les référentiels ne sont pas supprimés physiquement au Sprint 2. Ils sont activables/désactivables avec `isActive`.

## Saints

Entités :

```text
src/Entity/Saint.php
src/Entity/SaintTranslation.php
```

Repository :

```text
src/Repository/SaintRepository.php
src/Repository/SaintTranslationRepository.php
```

Service de slug localisé :

```text
src/Service/Game/LocalizedSlugger.php
```

Service de préparation admin :

```text
src/Service/Admin/SaintAdminDataPreparer.php
```

Formulaires admin :

```text
src/Form/Admin/SaintType.php
src/Form/Admin/SaintTranslationType.php
```

Contrôleur admin :

```text
src/Controller/Admin/SaintController.php
```

Templates admin :

```text
templates/admin/saint/
```

Tables SQL :

```text
game_saint
game_saint_translation
game_saint_role
game_saint_section
```

Principes :

- `technicalSlug` est stable, unique, non localisé ;
- les slugs d’URL sont localisés dans `SaintTranslation.urlSlug` ;
- chaque Saint peut avoir plusieurs rôles ;
- chaque Saint peut appartenir à plusieurs sections ;
- le rang peut être nul pour les Saints en brouillon, à venir ou souhaités ;
- le fallback de contenu est le français ;
- une traduction française est garantie côté admin ;
- les traductions vides hors fallback ne sont pas persistées inutilement.

Exemples :

```text
technicalSlug = gemini_saga

/en/saints/gemini-saga
/fr/saints/saga-gemeaux
/es/saints/saga-de-geminis
```

Routes admin :

```text
/admin/saints
/admin/saints/new
/admin/saints/{id}/edit
```

## Front Saints

Le Sprint 2 ajoute une consultation front minimale des Saints publiés.

Contrôleur :

```text
src/Controller/Front/SaintController.php
```

Templates :

```text
templates/front/saint/index.html.twig
templates/front/saint/show.html.twig
```

Routes :

```text
/{_locale}/saints
/{_locale}/saints/{slug}
```

Exemples :

```text
/en/saints
/en/saints/gemini-saga
/fr/saints
/fr/saints/saga-gemeaux
/es/saints/saga-de-geminis
```

Seuls les Saints avec le statut suivant sont affichés :

```text
published
```

Les Saints `draft`, `upcoming`, `expected` et `archived` ne sont pas listés côté front public au Sprint 2.

## Box utilisateur — Sprint 3

Le Sprint 3 ajoute le socle de box utilisateur.

Tables SQL principales :

```text
user_box
user_box_saint
```

Entités principales :

```text
src/Entity/UserBox.php
src/Entity/UserBoxSaint.php
```

Repositories principaux :

```text
src/Repository/UserBoxRepository.php
src/Repository/UserBoxSaintRepository.php
```

Principes :

- un compte possède une box principale ;
- une box contient des Saints via `user_box_saint` ;
- un même Saint ne doit pas être présent deux fois dans la même box ;
- la box est affichée sous forme de grille de cartes côté front connecté ;
- l’édition d’un Saint de box se fait via modale ;
- la suppression d’un Saint de box demande confirmation ;
- le retrait d’un Saint supprime son entrée de box ;
- si le Saint est ajouté de nouveau ensuite, il repart sur les valeurs initiales ;
- l’admin ne modifie pas les box utilisateurs au MVP.

Données gérées au Sprint 3 pour un Saint de box :

```text
niveau
étoiles
réincarnation
amitié
éveil
RC
Starwill
niveaux de skills
8e sens alpha/beta/gamma/delta
skin affichée
favori
note privée
note publique
```

Maxxage :

- le bouton de maxxage prépare les valeurs maximales dans la modale ;
- l’utilisateur doit ensuite enregistrer pour persister ;
- le maxxage met niveau 80, étoiles/réincarnation 12, amitié 10 ;
- l’éveil, la RC, le Starwill, les skills et le 8e sens sont maxxés seulement si applicables.

Reset :

- le reset remet les valeurs initiales dans la modale ;
- l’utilisateur doit ensuite enregistrer pour persister.

## API publique — Sprint 4

Le Sprint 4 pose le socle REST JSON public sous :

```text
/api/v1/
```

L’API n’est pas préfixée par la locale dans l’URL. La locale est transmise avec le paramètre query `locale`.

Exemple :

```text
/api/v1/saints?locale=fr
```

Locales supportées :

```text
fr
en
es
pt
de
```

Locale par défaut et fallback API :

```text
fr
```

Format de réponse de succès :

```json
{
  "data": {},
  "meta": {
    "apiVersion": "v1"
  }
}
```

Format de réponse d’erreur :

```json
{
  "error": {
    "code": "error_code",
    "message": "Message lisible.",
    "details": {}
  },
  "meta": {
    "apiVersion": "v1"
  }
}
```

Services API principaux :

```text
src/Service/Api/ApiResponseFactory.php
src/Service/Api/ApiLocaleResolver.php
src/Service/Api/ApiReferenceProvider.php
src/Service/Api/ApiReferenceNormalizer.php
src/Service/Api/ApiSaintProvider.php
src/Service/Api/ApiSaintNormalizer.php
src/Service/Api/ApiChecksumManager.php
src/Service/Api/ApiChecksumCacheKeyBuilder.php
src/Service/Api/ApiChecksumInvalidator.php
```

DTO API :

```text
src/DTO/Api/ApiPagination.php
src/DTO/Api/SaintListQuery.php
```

Exceptions et subscribers API :

```text
src/Exception/Api/ApiException.php
src/EventSubscriber/Api/ApiExceptionSubscriber.php
src/EventSubscriber/Api/ApiPublicResourceInvalidationSubscriber.php
```

### Endpoints API socle

```text
GET /api/v1/status
```

Permet de vérifier que l’API est disponible et que la résolution de locale fonctionne.

### Endpoints API référentiels

```text
GET /api/v1/ranks
GET /api/v1/roles
GET /api/v1/sections
```

Paramètres :

```text
locale=fr|en|es|pt|de
```

Règles :

- seuls les référentiels actifs sont exposés ;
- les données sont retournées dans la locale demandée ;
- le fallback de contenu est le français ;
- les réponses utilisent le format `data` / `meta`.

### Endpoints API Saints

Liste :

```text
GET /api/v1/saints
```

Détail :

```text
GET /api/v1/saints/{technicalSlug}
```

Exemples :

```text
/api/v1/saints?locale=fr
/api/v1/saints/gemini_saga?locale=fr
```

Règles :

- seuls les Saints `published` sont exposés ;
- les Saints `draft`, `upcoming`, `expected` et `archived` ne sont pas exposés dans l’API publique ;
- le détail utilise le `technicalSlug`, stable et non localisé ;
- les slugs d’URL localisés restent utilisés côté front public.

Paramètres de liste :

```text
locale=fr|en|es|pt|de
page=1
limit=20
rank=SS
role=dps
section=gold_saints
search=saga
sort=name|technicalSlug|rank
direction=asc|desc
```

Pagination :

- `page` commence à 1 ;
- `limit` vaut 20 par défaut ;
- `limit` est plafonné à 100.

Recherche :

- nom canonique ;
- slug technique ;
- nom traduit ;
- slug d’URL traduit.

### Endpoints API checksums

Routes :

```text
GET /api/v1/checksums
GET /api/v1/checksums/{resource}
```

Ressources supportées au Sprint 4 :

```text
ranks
roles
sections
saints
```

Exemples :

```text
/api/v1/checksums
/api/v1/checksums?locale=fr
/api/v1/checksums/ranks?locale=fr
/api/v1/checksums/saints?locale=fr
```

Règles :

- les checksums sont calculés par ressource et par locale ;
- les checksums sont stockés dans le cache Symfony ;
- les checksums permettent à un client de savoir si ses données publiques cacheables sont encore valides ;
- les données utilisateur ne doivent pas être stockées dans le cache public côté client.

Clés cache applicatives :

```text
ssa_api_v1_checksum_{resource}_{locale}
```

Exemple :

```text
ssa_api_v1_checksum_saints_fr
```

Invalidation :

- modification d’un `Rank` ou `RankTranslation` : invalidation de `ranks` ;
- modification d’un `Role` ou `RoleTranslation` : invalidation de `roles` ;
- modification d’une `Section` ou `SectionTranslation` : invalidation de `sections` ;
- modification d’un `Saint` ou `SaintTranslation` : invalidation de `saints`.

L’invalidation est volontairement large : toutes les locales d’une ressource sont invalidées, afin d’éviter les incohérences liées au fallback.

## Convention de commentaire de fichier

Dans les fichiers autres que CSS ou HTML/Twig, le chemin complet du fichier est indiqué en haut du fichier sous forme de commentaire.

Exemple :

```php
<?php

// src/Service/Security/UserRegistrationService.php
```

Autres exemples :

```php
<?php

// src/Controller/Front/SaintController.php
```

```js
// assets/admin.js
```

Les fichiers CSS et Twig ne sont pas concernés par cette convention.

## Commandes de contrôle

Avant commit, lancer au minimum :

```bash
php bin/console cache:clear
php bin/console lint:twig templates
php bin/console lint:yaml config/packages
php bin/console doctrine:schema:validate
php bin/console debug:router
php bin/console debug:asset-map
```

Selon les changements, vérifier aussi :

```bash
php bin/console doctrine:migrations:status
php bin/console debug:container App\Service\Security\AuthRateLimiterService
php bin/console debug:container App\Repository\SaintRepository
php bin/console debug:container App\Service\Game\LocalizedSlugger
php bin/console debug:container App\Service\Api\ApiResponseFactory
php bin/console debug:container App\Service\Api\ApiLocaleResolver
php bin/console debug:container App\Service\Api\ApiReferenceProvider
php bin/console debug:container App\Service\Api\ApiSaintProvider
php bin/console debug:container App\Service\Api\ApiChecksumManager
php bin/console debug:container App\Service\Api\ApiChecksumInvalidator
```

Pour vérifier les routes du Sprint 2 :

```bash
php bin/console debug:router | findstr admin
php bin/console debug:router | findstr front_saint
```

Pour vérifier les routes API du Sprint 4 :

```bash
php bin/console debug:router | findstr api_v1
php bin/console debug:router | findstr checksums
```

Pour vérifier les fixtures :

```bash
php bin/console doctrine:fixtures:load --append
```

## Routes principales du Sprint 1

```text
/register
/register/success
/verify/email
/login
/logout
/account
/reset-password
/reset-password/check-email
/reset-password/reset/{token}
```

## Routes principales du Sprint 2

Admin :

```text
/admin
/admin/ranks
/admin/ranks/new
/admin/ranks/{id}/edit
/admin/roles
/admin/roles/new
/admin/roles/{id}/edit
/admin/sections
/admin/sections/new
/admin/sections/{id}/edit
/admin/saints
/admin/saints/new
/admin/saints/{id}/edit
```

Front :

```text
/{_locale}/saints
/{_locale}/saints/{slug}
```

Erreurs en dev :

```text
/_error/404
/_error/403
/_error/500
```

## Routes principales du Sprint 3

Les routes exactes de box peuvent être vérifiées avec :

```bash
php bin/console debug:router | findstr box
```

Fonctions front couvertes :

```text
consultation de la box courante
ajout d’un Saint à la box
édition d’un Saint de box
maxxage dans la modale
reset dans la modale
retrait d’un Saint de box avec confirmation
```

## Routes principales du Sprint 4

API :

```text
/api/v1/status
/api/v1/ranks
/api/v1/roles
/api/v1/sections
/api/v1/saints
/api/v1/saints/{technicalSlug}
/api/v1/checksums
/api/v1/checksums/{resource}
```

Vérification :

```bash
php bin/console debug:router | findstr api_v1
```

## Git

Branches de sprint utilisées :

```text
feature/sprint-1-auth-user-foundation
feature/sprint-2-game-data-foundation
feature/sprint-3-user-box-foundation
feature/sprint-4-api-cache-foundation
```

Flux recommandé en local, sans dépôt distant :

```bash
git status
git add .
git commit -m "Message clair"
```

Puis, après validation globale d’un sprint :

```bash
git checkout dev
git merge feature/nom-de-branche-du-sprint
git checkout master
git merge dev
git checkout dev
```

Créer ensuite la branche du sprint suivant depuis `dev` :

```bash
git checkout -b feature/nom-de-branche-du-sprint-suivant
```

## Sprint 1 — État fonctionnel

Fonctionnalités couvertes :

- US-001 : entité User
- US-002 : inscription
- US-003 : confirmation email
- US-004 : login/logout
- US-005 : mot de passe oublié
- US-006 : préparation migration password v1
- US-006.5 : login par username et email optionnel legacy
- US-007 : rate limits
- US-008 : premiers templates frontend
- US-009 : documentation du socle

## Sprint 2 — État fonctionnel

Fonctionnalités couvertes :

- US-010 : enums métier Saint ;
- US-011 : référentiels Rank / Role / Section ;
- US-012 : entité Saint ;
- US-013 : traductions Saint et slugs URL localisés ;
- US-014 : repositories données jeu ;
- US-015 : layout admin custom ;
- US-016 : CRUD admin référentiels ;
- US-017 : CRUD admin Saints ;
- US-018 : fixtures données jeu ;
- US-019 : consultation front minimale des Saints publiés ;
- US-019.5 : pages d’erreur et factorisation CSS ;
- US-020 : documentation Sprint 2.

## Sprint 3 — État fonctionnel

Fonctionnalités couvertes :

- US-021 : entité de box utilisateur ;
- US-022 : entité Saint de box ;
- US-023 : accès front à la box courante ;
- US-024 : ajout d’un Saint à la box ;
- US-025 : édition d’un Saint de box ;
- US-026 : maxxage et reset en modale ;
- US-027 : retrait d’un Saint de box ;
- US-028 : finalisation de la box utilisateur ;
- US-028.5 : confirmation avant suppression et réalignement des migrations Sprint 3.

## Sprint 4 — État fonctionnel

Branche :

```text
feature/sprint-4-api-cache-foundation
```

Fonctionnalités couvertes :

- US-029 : socle API v1, réponses JSON, locale API et erreurs API ;
- US-030 : endpoints API des référentiels `ranks`, `roles`, `sections` ;
- US-031 : endpoint API liste des Saints publiés ;
- US-032 : endpoint API détail d’un Saint publié par `technicalSlug` ;
- US-033 : checksums publics par ressource et par locale ;
- US-034 : cache Symfony des checksums et invalidation automatique après modification Doctrine ;
- US-035 : documentation Sprint 4.

## Validation globale de fin de Sprint 4

Avant commit ou merge, lancer :

```bash
git status
php bin/console cache:clear
php bin/console lint:twig templates
php bin/console lint:yaml config/packages
php bin/console doctrine:schema:validate
php bin/console doctrine:migrations:status
php bin/console debug:router
php bin/console debug:asset-map
```

Vérifier les routes API :

```bash
php bin/console debug:router | findstr api_v1
php bin/console debug:router | findstr checksums
```

Vérifier les services API :

```bash
php bin/console debug:container App\Service\Api\ApiResponseFactory
php bin/console debug:container App\Service\Api\ApiLocaleResolver
php bin/console debug:container App\Service\Api\ApiReferenceProvider
php bin/console debug:container App\Service\Api\ApiSaintProvider
php bin/console debug:container App\Service\Api\ApiChecksumManager
php bin/console debug:container App\Service\Api\ApiChecksumInvalidator
php bin/console debug:container App\EventSubscriber\Api\ApiPublicResourceInvalidationSubscriber
```

Tester les endpoints API principaux :

```text
/api/v1/status
/api/v1/ranks?locale=fr
/api/v1/roles?locale=fr
/api/v1/sections?locale=fr
/api/v1/saints?locale=fr
/api/v1/saints/gemini_saga?locale=fr
/api/v1/checksums
/api/v1/checksums/saints?locale=fr
```

Tester les erreurs API :

```text
/api/v1/status?locale=it
/api/v1/saints/inconnu
/api/v1/checksums/cosmos
```

Vérifier l’invalidation des checksums :

1. appeler `/api/v1/checksums/saints?locale=fr` ;
2. noter le checksum ;
3. modifier un Saint publié ou une traduction de Saint côté admin ;
4. rappeler `/api/v1/checksums/saints?locale=fr` ;
5. vérifier que le checksum a changé.

Si tout est OK :

```bash
git add README.md
git commit -m "Update README for sprint 4"
```

## Validation globale de fin de Sprint 2

Avant commit ou merge, lancer :

```bash
git status
php bin/console cache:clear
php bin/console lint:twig templates
php bin/console lint:yaml config/packages
php bin/console doctrine:schema:validate
php bin/console doctrine:migrations:status
php bin/console debug:router
php bin/console debug:asset-map
```

Vérifier les routes principales :

```bash
php bin/console debug:router | findstr admin
php bin/console debug:router | findstr front_saint
```

Vérifier les écrans admin :

```text
/admin
/admin/ranks
/admin/roles
/admin/sections
/admin/saints
```

Vérifier les écrans front :

```text
/en/saints
/fr/saints
/en/saints/gemini-saga
/fr/saints/saga-gemeaux
```

Vérifier les pages d’erreur en dev :

```text
/_error/404
/_error/403
/_error/500
```

Si tout est OK :

```bash
git add README.md
git commit -m "Update README for sprint 2"
```

Puis merge vers `dev` :

```bash
git checkout dev
git pull
git merge feature/sprint-2-game-data-foundation
```
