## Contexte Le README de `develop` ne distinguait pas clairement les parcours de dev avec/sans données de seed, ni la base de test dédiée. Refonte pour une doc projet complète et fidèle au `makefile` actuel. ## Contenu - **Dev local avec / sans données de seed** : `make install` (base vierge — schéma + RBAC structurel, aucun compte) vs `make db-reset` / `make fixtures` (comptes + données de démo). Explicite le piège : `install` ne charge pas les fixtures sur la base dev. - **Création de compte sans seed** : `app:create-user … --admin`. - **Bases de données dev vs test** : base `_test` dédiée et isolée (suffixe auto en `APP_ENV=test`), rôle détaillé de `make test-db-setup` (migrations, schema:update, column-comments, fixtures→sync→seed-rbac, index partiels uniques). - **Tests** : 3 suites (PHPUnit / Vitest / Playwright), prérequis et workflow E2E, règle d'or. - **Seed RBAC recette / prod** : `app:seed-rbac` (+ `--with-demo-users --password`), idempotent et non destructif, ordre de release. - Tableau des commandes `make`, sommaire, prérequis, correction du nom (Starseed) et des ports. Changement **docs uniquement**, aucun code touché. --------- Co-authored-by: admin malio <malio@yuno.malio.fr> Co-authored-by: Matthieu <contact@malio.fr> Reviewed-on: #56 Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
Starseed
CRM/ERP en architecture modular monolith DDD — Symfony 8 (API Platform 4) + Nuxt 4.
Le backend est la source de vérité unique : il décide des modules actifs et de
l'organisation de la sidebar. Le frontend scanne frontend/modules/*/ comme layers
Nuxt et consomme l'API pour la navigation.
Sommaire
- Stack
- Prérequis
- Démarrage rapide
- Dev local : avec ou sans données de seed
- Comptes (dev)
- Bases de données : dev et test
- Tests
- Déploiement : seed RBAC en recette / prod
- Commandes make
- Architecture
- Structure du dépôt
- CI/CD
- Conventions
Stack
- Backend : PHP 8.4, Symfony 8, API Platform 4, Doctrine ORM, PostgreSQL 16
- Frontend : Nuxt 4 (SPA, SSR off), Vue 3, Pinia, Tailwind CSS, @malio/layer-ui, @nuxtjs/i18n
- Auth : JWT HTTP-only cookie (Lexik), login sur
/login_check - Infra : Docker Compose (dev + prod multi-stage)
- CI/CD : Gitea Actions (auto-tag + build Docker)
| Service | Port |
|---|---|
| API (Nginx) | 8083 |
| Frontend dev | 3004 |
| PostgreSQL | 5437 |
Prérequis
- Docker + Docker Compose
makenvm(la version de Node est fixée par.nvmrc, voirmake node-use)
Toutes les commandes make s'exécutent dans le container PHP (php-starseed-fpm) ;
rien n'est requis sur l'hôte hormis Docker — sauf les tests E2E, qui tournent sur
l'hôte (navigateur réel, voir Tests).
Démarrage rapide
make start # Démarre les containers Docker
make install # Composer + clés JWT + migrations + permissions + BDD de test
make dev-nuxt # Serveur Nuxt avec hot reload (http://localhost:3004)
make install prépare une base de dev vierge (schéma + RBAC structurel, sans
données de démo) et la base de test. Pour obtenir des comptes et des données de
démo prêtes à l'emploi, lis la section suivante.
Override local possible :
makelitinfra/dev/.env.docker, surchargé parinfra/dev/.env.docker.locals'il existe (créé automatiquement parmake env-init).
Dev local : avec ou sans données de seed
Le projet distingue deux états de base de données de dev. Les fixtures Doctrine sont
en require-dev : elles n'existent qu'en dev, jamais dans le build de prod.
Sans données de seed (base vierge)
C'est ce que produit make install. La base contient :
- le schéma complet (toutes les migrations jouées) ;
- les rôles système
admin/user(seedés en SQL par la migration RBAC) ; - le catalogue de permissions synchronisé (
app:sync-permissions).
Mais aucun compte utilisateur ni donnée métier. Pour pouvoir te connecter, crée toi-même un compte :
make shell
php bin/console app:create-user admin monMotDePasse --admin # compte ROLE_ADMIN
Optionnel — provisionner les rôles métier (bureau / compta / commerciale / usine
- matrice RBAC § 2.7) sans comptes de démo :
php bin/console app:seed-rbac
Cet état est utile pour repartir d'une base propre, reproduire un bug sur données minimales, ou tester un parcours d'onboarding réel.
Avec données de seed (base de démo)
make db-reset (ou make fixtures après un make install) recharge la base de dev
avec un jeu complet de données de démonstration, idempotent :
make db-reset # ATTENTION : drop + recrée la base de dev, puis charge tout le seed
Ce que les fixtures posent :
- 3 utilisateurs système :
admin(ROLE_ADMIN),alice,bob(ROLE_USER), rattachés à des sites distincts ; - 3 sites : Chatellerault, Saint-Jean, Pommevic ;
- les comptes de démo RBAC métier (
bureau,compta,commerciale,usine, mot de passedemo) avec la matrice § 2.7 attachée ; - les référentiels et données métier des modules (catégories, clients de démo, référentiels comptables…).
Toutes les fixtures sont rejouables sans effet de bord (lookup par clé naturelle, aucun doublon).
Différence avec
make install:installne charge pas les fixtures sur la base de dev (il alimente uniquement la base de test). Utilisemake db-resetoumake fixturesquand tu veux des données de démo en dev.
Comptes (dev)
Disponibles uniquement après make db-reset / make fixtures (état « avec seed ») :
| Username | Password | Rôle | RBAC métier |
|---|---|---|---|
admin |
admin |
ROLE_ADMIN | bypass complet (is_admin) |
alice |
alice |
ROLE_USER | — |
bob |
bob |
ROLE_USER | — |
bureau |
demo |
ROLE_USER | clients : view + manage |
compta |
demo |
ROLE_USER | clients : view + accounting.view / manage |
commerciale |
demo |
ROLE_USER | clients : view + manage (Information obligatoire — RG-1.04) |
usine |
demo |
ROLE_USER | aucun accès clients |
Bases de données : dev et test
Deux bases distinctes vivent dans le même container PostgreSQL (port 5437) :
| Base | Environnement | Construite par | Usage |
|---|---|---|---|
<db> |
dev |
make install / make db-reset |
développement manuel, dev-nuxt |
<db>_test |
test |
make test-db-setup |
PHPUnit (jamais touchée à la main) |
Le suffixe _test est appliqué automatiquement par Doctrine quand APP_ENV=test
(config when@test dans config/packages/doctrine.yaml). La base de test est donc
totalement isolée de la base de dev : lancer make test ne touche jamais tes
données de dev.
make test-db-setup fait davantage que jouer les migrations, car certaines structures
ne sont pas portées par des migrations « métier » :
doctrine:migrations:migrate— schéma métier réel ;doctrine:schema:update --force— crée les tables mappées enwhen@testuniquement (entités de test) ;app:apply-column-comments— réapplique lesCOMMENT ON COLUMNqueschema:updateefface sur les tables managées par l'ORM (garde-fouColumnsHaveSqlCommentTest) ;fixtures:load→sync-permissions→seed-rbac— dans cet ordre précis (le purger des fixtures vide la tablepermission, donc la sync passe après) ;- recréation des index partiels uniques (
LOWER(...) WHERE ...) non exprimables en attributs ORM, indispensables aux tests d'unicité (RG-1.07, RG-1.16, RG-1.03/1.29).
make install et make db-reset appellent déjà test-db-setup : tu n'as à le
relancer à la main que si la base de test diverge (nouvelle migration, nouvelle
permission) sans vouloir reseed la base de dev.
Tests
| Suite | Commande | Outil | Où |
|---|---|---|---|
| Back | make test |
PHPUnit | container PHP, base <db>_test |
| Front unitaire | make nuxt-test |
Vitest (happy-dom) | container Node, < 30 s |
| Front E2E | make test-e2e |
Playwright | hôte (navigateur réel requis) |
| Tout (back+front) | make test-all |
PHPUnit + Vitest | — |
Tests back (PHPUnit)
make test # toute la suite
make test FILES=tests/Module/Commercial # un dossier / fichier ciblé
PHPUnit force APP_ENV=test (phpunit.dist.xml) : les tests tournent toujours
sur la base <db>_test, jamais sur la base de dev. Prérequis : que la base de test
existe — c'est le cas après make install. Si elle a divergé, rejoue
make test-db-setup (cf. Bases de données).
Tests front unitaires (Vitest)
make nuxt-test # composables, utils, stores — rapide et stable
C'est la place par défaut pour étendre la couverture (cf. règle d'or ci-dessous).
Tests E2E (Playwright)
Suite volontairement minimaliste (login + matrice RBAC sidebar). Règle d'or : un nouveau test E2E ne s'ajoute que si un bug critique est passé en prod — sinon, préférer un test Vitest ou étendre un persona existant.
Bootstrap (une fois par poste) :
make install-e2e-deps # télécharge Chromium + libs système (apt/dnf, sudo)
Workflow :
# Terminal 1 — containers, seed des personas, serveur dev
make start && make seed-e2e && make dev-nuxt
# Terminal 2 — tests
make test-e2e # headless
make test-e2e-ui # UI interactive (debug)
Toute permission testable touche 3 miroirs à garder alignés :
config/sidebar.php,frontend/tests/e2e/_fixtures/personas.ts,SeedE2ECommand.php.
Déploiement : seed RBAC en recette / prod
Les fixtures Doctrine étant en require-dev, elles sont absentes du build de prod.
Le RBAC métier (rôles bureau / compta / commerciale / usine + matrice § 2.7)
est seedé par une commande applicative idempotente, jouée dans l'étape de release,
après les migrations et la synchronisation des permissions :
php bin/console doctrine:migrations:migrate --no-interaction
php bin/console app:sync-permissions # pose les permissions (commercial.clients.*, …)
php bin/console app:seed-rbac # PROD : rôles + matrice § 2.7 (sans comptes démo)
En recette / staging, ajouter le flag pour disposer de logins de test. Le mot de passe est fourni explicitement (jamais en dur, jamais committé) :
php bin/console app:seed-rbac --with-demo-users --password='<mot-de-passe>'
# ou via la variable d'environnement RBAC_DEMO_PASSWORD
La commande est rejouable sans effet de bord (aucun doublon de rôle, de lien ou de compte). Pour créer un premier administrateur en prod :
php bin/console app:create-user <username> <password> --admin
Commandes make
make (sans argument) ou make help affiche l'aide colorée. Les principales :
| Commande | Description |
|---|---|
make start / stop / restart |
Cycle de vie des containers |
make install |
Install complet (base dev vierge + base de test) |
make reset |
Tout supprimer et réinstaller (drop la BDD) |
make dev-nuxt |
Serveur Nuxt hot reload (port 3004) |
make shell / shell-root |
Shell bash dans le container PHP |
make migration-migrate |
Jouer les migrations Doctrine |
make fixtures |
Charger les fixtures (données de démo dev) |
make sync-permissions |
Synchroniser le catalogue RBAC |
make seed-rbac |
Seed RBAC métier (rôles + matrice § 2.7) |
make db-reset |
Reset base dev : drop + migrate + fixtures + RBAC |
make test-db-setup |
(Re)construire la base de test |
make test |
PHPUnit (back) |
make nuxt-test |
Vitest (front unitaire) |
make test-all |
PHPUnit + Vitest |
make test-e2e / test-e2e-ui |
Playwright (E2E, sur l'hôte) |
make seed-e2e |
Seed des 6 personas E2E |
make php-cs-fixer-allow-risky |
Fix du code style PHP |
make php-cs-fixer-check |
Dry-run du fixer (CI / avant push) |
make logs-dev |
Tail des logs Symfony |
Architecture
Modular Monolith DDD : chaque module est un bounded context autonome, activable / désactivable par tenant. Le backend est la seule source de vérité pour l'activation des modules et l'organisation de la sidebar.
config/modules.php— liste des modules actifsconfig/sidebar.php— structure de la sidebar (sections + items avec module owner)GET /api/modules— IDs des modules actifs (public)GET /api/sidebar— sections filtrées par modules actifs + routes désactivées (public)
Désactiver un module : commenter sa ligne dans config/modules.php, vider le cache.
Ses items de sidebar disparaissent et ses routes sont bloquées par le middleware front.
Le code reste dans le bundle (layer auto-détecté) → réactivation instantanée.
Réorganiser la sidebar : éditer config/sidebar.php uniquement — le code des
modules n'est pas touché.
Communication inter-modules : jamais d'import direct d'un module à l'autre. Passer
par Shared/Domain/Contract/ (interfaces) ou des domain events.
Structure du dépôt
src/ # Backend Symfony
Shared/ # Noyau technique partagé (Domain/, Application/Bus/, Infrastructure/ApiPlatform/)
Module/
Core/ # Module obligatoire (auth, users, RBAC)
CoreModule.php # Déclaration (ID, LABEL, REQUIRED, permissions())
Domain/ Application/ Infrastructure/
Commercial/ Catalog/ Sites/ # Modules métier
config/
modules.php # Source de vérité : activation
sidebar.php # Source de vérité : navigation
packages/ # Config Symfony (doctrine, api_platform, security…)
migrations/ # Migrations d'initialisation (namespace racine : setup, RBAC, seed de base)
frontend/ # App Nuxt 4 (SPA)
app/ # Shell : layouts, middlewares (auth.global, modules.global)
shared/ # Code inter-modules (composables, stores, utils, types)
modules/ # Layers Nuxt auto-détectés (core/, commercial/…)
i18n/locales/ # Traductions (sidebar.*, audit.entity.*, …)
infra/
dev/ # Docker dev (Dockerfile, nginx, php.ini, xdebug, .env.docker)
prod/ # Docker prod (multi-stage, nginx, php-prod.ini)
.gitea/workflows/ # CI Gitea (auto-tag, build Docker)
CI/CD
- Auto Tag : push sur
develop→ bumpconfig/version.yaml→ tagvX.Y.Z - Build Docker : push tag
v*→ build image multi-stage → push Gitea Registry
Secrets requis dans Gitea :
RELEASE_TOKEN— PAT avec droitswrite:repositoryREGISTRY_TOKEN— token pour le registry Docker
Conventions
Commits
<type>(<scope optionnel>) : <message>
Espaces obligatoires autour du :. Types : build, chore, ci, docs, feat,
fix, perf, refactor, revert, style, test.
Langue
- UI et communication : français
- Code (classes, méthodes, variables) : anglais
- Commentaires (PHP, TS, Vue) : français
Règles détaillées :
CLAUDE.mdet.claude/rules/.