# LÉZIDÉJOU — Architecture technique de la Phase 1

Date de référence : **14 août 2026**
Statut : **Socle technique de Phase 1 implémenté (en attente de validation distante)**

---

## 1. Contexte et vision d'architecture

LÉZIDÉJOU est la plateforme centrale et la marque ombrelle regroupant des applications, des jeux, de la musique et des créations indépendantes.

La phase 1 constitue le **premier socle technique** d'un futur monolithe modulaire. Son objectif exclusif est de fournir un portail public éditorial robuste, accessible, sécurisé et performant, ainsi qu'un espace d'administration protégé, sans intégrer par anticipation le code métier des projets existants ou futurs.

---

## 2. Socle technologique et versions

Les versions de l'environnement et des dépendances s'appuient sur les contraintes déclarées et les versions exactes verrouillées dans les manifestes (`composer.lock` et `package-lock.json`) :

* **Langage & Environnement d'exécution** :
  * PHP : version `8.4.24` (PHP 8.4.24 NTS Visual C++ 2022 x64 sous Windows).
  * Node.js : version `24.19.0 LTS`.
  * npm : version `11.17.0`.
  * Composer : version `2.10.1`.
* **Framework backend & composants PHP** :
  * `laravel/framework` : contrainte déclarée `^13.8`, version verrouillée **`v13.25.0`** (monolithe modulaire).
  * `filament/filament` : contrainte déclarée `^5.0`, version verrouillée **`v5.7.6`** (administration `/admin`).
  * `livewire/livewire` : contrainte déclarée `^4.0`, version verrouillée **`v4.4.0`** (composants dynamiques d'administration).
* **Frontend & Outillage d'actifs** :
  * `tailwindcss` : contrainte déclarée `^4.3.3`, version verrouillée **`4.3.3`**.
  * `@tailwindcss/vite` : contrainte déclarée `^4.3.3`, version verrouillée **`4.3.3`**.
  * `vite` : contrainte déclarée `^8.0.0`, version verrouillée **`8.2.1`**.
  * `laravel-vite-plugin` : contrainte déclarée `^3.1`, version verrouillée **`3.1.1`**.
  * Polices auto-hébergées : `Libre Franklin Variable` (WOFF2 local) et `IBM Plex Mono` (WOFF2 local, graisses 400 et 500) sous licence `OFL-1.1`.
* **Outillage d'analyse statique, qualité et tests** :
  * `larastan/larastan` / PHPStan : contrainte déclarée `^3.0`, version verrouillée **`v3.10.0`** (analyse niveau 5).
  * `laravel/pint` : contrainte déclarée `^1.24`, version verrouillée **`v1.30.5`** (style de code PSR-12 / Laravel).
  * `phpunit/phpunit` : contrainte déclarée `^12.0`, version verrouillée **`12.5.33`**.
  * `@playwright/test` : contrainte déclarée `^1.62.1`, version verrouillée **`1.62.1`**.
  * `@axe-core/playwright` : contrainte déclarée `^4.13.0`, version verrouillée **`4.13.0`**.
  * `@lhci/cli` : contrainte déclarée `^0.15.1`, version verrouillée **`0.15.1`**.

---

## 3. Architecture modulaire et domaines applicatifs

L'application est structurée selon une séparation stricte en domaines étanches sous le namespace `App\Domain\` :

```text
app/
├── Domain/
│   ├── Portal/                 # Domaine du portail public et du catalogue éditorial
│   │   ├── DTO/                # ProjectContent (DTO typé et immuable)
│   │   ├── Enums/              # DestinationType, ProjectCategory, ProjectStatus
│   │   ├── Services/           # CanonicalUrlGenerator (génération des URLs absolues HTTPS)
│   │   └── ProjectCatalog.php  # Service de catalogue instancié depuis resources/content/projects.php
│   └── Identity/               # Domaine d'authentification et gestion des administrateurs
│       ├── Models/             # User (modèle d'authentification unique de l'application)
│       └── Commands/           # CreateAdminCommand (commande artisan sécurisée)
├── Http/
│   └── Controllers/            # Contrôleurs HTTP fins (HomeController, ProjectController, etc.)
└── Providers/
    ├── AppServiceProvider.php          # Enregistrement singleton de ProjectCatalog et commande admin
    └── Filament/AdminPanelProvider.php # Configuration du panel Filament /admin
```

### Règles strictes d'étanchéité des domaines :
1. **Domaines autorisés en Phase 1** : Strictement `App\Domain\Portal` et `App\Domain\Identity`.
2. **Absence de domaines prématurés** : Aucun domaine `FuelPrice`, `MenuPlanner`, `Belote` ou `MathIslands` n'est créé en Phase 1.
3. **Modèle de données unique** : Le modèle `App\Domain\Identity\Models\User` remplace totalement le modèle par défaut `App\Models\User` (qui a été supprimé).

---

## 4. Architecture réelle du catalogue des projets

Le catalogue éditorial est administré via une structure DTO / Service typée sans couche d'abstraction superflue :

* **Manifeste source** : `resources/content/projects.php` retourne le tableau brut des définitions de projets.
* **DTO immuable (`App\Domain\Portal\DTO\ProjectContent`)** :
  * Propriétés typées en lecture seule : `id`, `slug`, `title`, `category`, `summary`, `description`, `status`, `destinationType`, `destinationUrl`, `image`, `imageAlt`, `seoTitle`, `seoDescription`.
  * Méthode d'aide : `isVisible()` (projets `published` ou `in_development`).
* **Service de catalogue (`App\Domain\Portal\ProjectCatalog`)** :
  * Instancie et valide l'unicité des identifiants, slugs et URLs de destination.
  * Hydrate les entrées en instances de `ProjectContent`.
  * Fournit les méthodes d'accès : `all()`, `visible()`, `findBySlug(string $slug)`, `byCategory(ProjectCategory $category)`.
* **Enregistrement et injection** :
  * `ProjectCatalog` est déclaré en singleton dans `AppServiceProvider::register()` :
    ```php
    $this->app->singleton(ProjectCatalog::class, fn () => new ProjectCatalog);
    ```
  * Il est injecté directement dans les contrôleurs (`HomeController`, `ProjectController`, `GameController`, `SitemapController`).
* **Énumérations typées (`App\Domain\Portal\Enums\`)** :
  * `ProjectCategory` : `application` (GoodGasoilPrice, Menu Planner, LivraSign), `game` (Belote Pro, Maths & Îles).
  * `ProjectStatus` : `published` (Good Gasoil Price), `in_development` (Menu Planner, Belote Pro, Maths & Îles, LivraSign), `hidden` (masqué).
  * `DestinationType` : `internal` (fiche éditoriale interne `/projets/{slug}`), `external` (lien externe).

---

## 5. Routage, navigation et URLs canoniques

### 5.1 Routes publiques de Phase 1

* **Accueil & Sélection** : `/` (`HomeController`)
* **Catalogue des projets** : `/projets` (`ProjectController@index`)
* **Fiches éditoriales individuelles** : `/projets/{slug}` (`ProjectController@show`)
  * `/projets/good-gasoil-price`
  * `/projets/menu-planner`
  * `/projets/belote-pro`
  * `/projets/maths-iles`
  * `/projets/livrasign`
* **Entrée directe Jeux** : `/jeux` (`GameController`)
* **Pages thématiques** : `/musique` (`MusicController`), `/boutique` (`ShopController`), `/a-propos` (`AboutController`)
* **Pages juridiques** : `/mentions-legales` (`LegalController`), `/confidentialite` (`PrivacyController`)
* **Endpoints techniques** : `/robots.txt` (`RobotsController`), `/sitemap.xml` (`SitemapController`)

### 5.2 Navigation principale
La navigation principale (`main-nav`) est strictement composée de 4 éléments :
1. **Projets** (`/projets`)
2. **Musique** (`/musique`)
3. **Boutique** (`/boutique`)
4. **À propos** (`/a-propos`)

Le mot-symbole `LÉZIDÉJOU` pointe vers l'accueil (`/`). `Jeux`, `Labo`, `LivraSign` et `Contact` ne font pas partie de la navigation principale.

### 5.3 Service d'URLs canoniques (`CanonicalUrlGenerator`)
Le service `App\Domain\Portal\Services\CanonicalUrlGenerator` centralise la construction d'URLs absolues HTTPS à partir de l'origine canonique configurée (`APP_URL`) en normalisant l'URL de base (suppression des slashs finaux de la base) et en ajoutant un unique slash de jonction avant le chemin fourni. Il ne supprime pas un slash terminal explicitement présent dans le chemin transmis.

### 5.4 Politique d'indexation par environnement
* **Hors production** : Toutes les pages reçoivent `<meta name="robots" content="noindex,follow">`, `robots.txt` applique `Disallow: /`, et `sitemap.xml` retourne un flux XML valide contenant un `urlset` vide.
* **Production** : Les 6 pages éditoriales complètes ainsi que la fiche Good Gasoil Price (statut `published`) sont indexables (`index,follow`, soit 7 URLs au sitemap). Les 4 fiches de projets avec statut `in_development` et les 2 pages légales conservent explicitement `noindex,follow` et sont exclues du sitemap.

---

## 6. Administration Filament et sécurité de l'identité

* **Point d'accès** : `/admin`, géré par Filament v5.7.6.
* **Filtrage d'accès** : Réservé aux utilisateurs disposant de `is_admin = true` sur le modèle `App\Domain\Identity\Models\User`.
* **Authentification multifacteur (MFA / TOTP)** :
  * TOTP obligatoire via `Filament\Auth\MultiFactor\App\AppAuthentication`.
  * Nom de marque configuré : `LÉZIDÉJOU`.
  * 8 codes de récupération à usage unique générés à l'enrôlement.
* **Chiffrement au repos** : Le secret d'application TOTP (`app_authentication_secret`) et les codes de secours (`app_authentication_recovery_codes`) sont chiffrés au repos en base de données via les casts Eloquent `encrypted` et `encrypted:array`.
* **Masquage à la sérialisation** : Tous les attributs sensibles (mot de passe, `remember_token`, secrets et codes TOTP) sont inclus dans `$hidden`.
* **Création d'administrateur sécurisée** : Commande console interactive `php artisan lezidejou:admin:create`, validant la complexité des mots de passe (longueur minimale 12 caractères, majuscule, minuscule, chiffre, symbole) sans jamais exposer de secret.
* **Aucun compte par défaut** : `DatabaseSeeder.php` ne crée aucun compte utilisateur automatiquement.

---

## 7. Architecture de base de données

* **Développement local & Tests rapides** : SQLite (`database/database.sqlite` ou base SQLite en mémoire pour les suites Unit et Feature).
* **Moteur SQL représentatif de référence** : MySQL 8.4 (version 8.4.11).
* **Base de test dédiée** : `lezidejou_test`, utilisant le compte applicatif dédié `lezidejou_test_user` sans privilèges administrateur / root.
* **Configuration d'intégration** : `phpunit.mysql.xml` utilisant l'environnement `.env.mysql-testing` (strictement ignoré par Git).
* **Migrations additives** : Conception de migrations sans clauses destructives, compatibles à la fois avec SQLite et MySQL 8.4 (encodage `utf8mb4_unicode_ci`).

---

## 8. Stratégie de tests et assurance qualité

La plateforme intègre une pyramide de contrôles automatisés :

1. **Tests unitaires (`Unit`)** : Enums, DTO immuable `ProjectContent`, invariants du catalogue et du service `CanonicalUrlGenerator`.
2. **Tests fonctionnels (`Feature`)** : Résolution des routes, conformité des statuts HTTP, présence d'un H1 unique par page, balises SEO et Open Graph, politique robots/sitemap par environnement, isolation du panel admin, enrôlement TOTP, et comportement de la commande console de création d'administrateur.
3. **Tests d'intégration (`Integration`)** : Vérification du schéma sous MySQL 8.4 réel, migrations, persistance de l'identité, chiffrement/déchiffrement effectif, et isolation transactionnelle.
4. **Tests de bout en bout (`Playwright E2E`)** : Tests Chromium sur 4 viewports (360px, 768px, 1024px, 1440px), validation du menu mobile `<details>/<summary>` au clavier (Entrée/Espace), absence de débordement horizontal, résolution des liens internes sans erreur 4xx/5xx, et audits d'accessibilité `@axe-core/playwright` (0 violation sérieuse ou critique).
5. **Audits de performance et qualité (`Lighthouse CI`)** : Audits de laboratoire sur les 10 URL publiques autorisées (30 collectes au total sur le port 8002 avec assertions pessimistes strictes dans `lighthouserc.cjs`). Les résultats historiques du Jalon 7 (scores 100% / 99%) sont des mesures de laboratoire synthétiques.
6. **Patch d'isolation Windows (`lighthouse-win-patch.cjs`)** : Module confiné pour la suppression différée des profils temporaires Chrome sous Windows, validé unitairement par `tests/Node/lighthouse-win-patch.test.cjs`.
7. **Analyses statiques et style** : PHPStan niveau 5 (0 erreur) via Larastan, Laravel Pint (conformité PSR-12 / Laravel), et validation stricte de `composer.json`.

---

## 9. Intégration continue (CI)

L'intégration continue est structurée en deux workflows GitHub Actions distincts :

### 9.1 Workflow CI rapide automatique (`.github/workflows/quality.yml`)
* **Déclencheurs** : Push sur `feat/phase-1-foundation` et `main`, Pull Requests vers `main`, et déclenchement manuel (`workflow_dispatch`).
* **Filtres** : Ignore les modifications exclusivement documentaires (`docs/**`, `README.md`).
* **Contrôles exécutés** :
  1. `composer validate --strict`
  2. `npm run test:lighthouse-patch` (tests unitaires Node du patch)
  3. `php vendor/bin/pint --test`
  4. `php vendor/bin/phpstan analyse`
  5. **`npm run build` (obligatoirement positionné avant les suites testant des vues Blade avec `@vite`)**
  6. `php artisan test --testsuite=Unit` (SQLite)
  7. `php artisan test --testsuite=Feature` (SQLite)
  8. `php artisan test --env=mysql-testing --configuration=phpunit.mysql.xml --testsuite=Integration` (MySQL 8.4.11)
* **Optimisations** : Aucun téléchargement de navigateur (Chromium), aucune exécution de Playwright ou de Lighthouse complet dans ce workflow rapide.

### 9.2 Workflow CI navigateur séparé (`.github/workflows/browser-quality.yml`)
* **Déclencheurs** : Push sur `feat/phase-1-foundation` et `main`, Pull Requests vers `main`, uniquement lorsque des fichiers pouvant influencer l'interface ou le navigateur sont modifiés (filtres de chemins sur `app/**`, `resources/**`, `public/**`, `tests/Browser/**`, `playwright.config.ts`, dépendances, etc.).
* **Contrôles exécutés** :
  * Installation de Chromium et exécution de Playwright E2E (`npm run test:e2e`) avec un seul worker.
  * Exécution de la suite complète Lighthouse CI (30 collectes) **uniquement lors d'un déclenchement manuel explicite** (`workflow_dispatch` avec option `run_lighthouse: true`). Lighthouse complet ne s'exécute jamais sur un push ou une pull request standard.
* **Archivage des artefacts** : Les rapports Playwright et Lighthouse sont archivés principalement en cas d'échec (`if: failure()`).

### 9.3 Fait historique et statut d'exécution distante
* L'échec GitHub Actions observé sur le checkpoint du jalon 7 (run `31749573088` sur le commit `3008462e`) était dû à l'exception `ViteManifestNotFoundException` (étape `npm run build` ordonnancée après les Feature tests dans l'ancien workflow unique).
* Les nouveaux workflows corrigent cet ordre et scindent les responsabilités. Ces workflows n'ayant pas encore été exécutés sur les serveurs distants de GitHub (aucun push non autorisé), leur bon fonctionnement distant reste à valider lors du premier déclenchement officiel.

---

## 10. Limites et périmètre non implémenté en Phase 1

Conformément au plan d'exécution normatif :
* **Aucun code métier source** : GoodGasoilPrice, Menu Planner, Belote Pro et Maths & Îles restent dans leurs dépôts historiques respectifs sous `sources/`.
* **Aucun module métier vide** : Aucun namespace ou dossier anticipé n'a été créé.
* **Application LivraSign** : Reste une application Laravel totalement autonome avec son propre cycle de vie ; seule une fiche éditoriale interne la présente sur le portail.
* **Rubrique Labo** : Non implémentée en Phase 1.
* **Comptes utilisateurs publics** : Aucun compte public, inscription, ou espace membre n'existe.
* **Monétisation et formulaires** : Aucun système de paiement, panier, ou formulaire de contact avec traitement de données n'est présent.
