# Architecture — Modular Monolith DDD

## Principe fondamental
Le **backend est la source de verite unique**. Il dicte :
- Quels modules sont actifs (`config/modules.php`)
- L'organisation de la sidebar (`config/sidebar.php`, decouplee des modules)

Le frontend scanne `modules/*/` comme layers Nuxt et consomme l'API pour la navigation. Il ne decide rien.

## Endpoints API cles

- `GET /api/version` (public) — version de l'app
- `GET /api/modules` (public) — IDs des modules actifs
- `GET /api/sidebar` (public) — sections filtrees par modules actifs + `disabledRoutes` (items dont le module owner est inactif)
- `GET /api/me` (auth) — user courant

## Arborescence minimale (detail complet : @README.md)

```
src/
  Shared/               # Noyau technique partage (Domain/, Application/Bus/, Infrastructure/ApiPlatform/)
  Module/
    Core/               # Module obligatoire (auth, users)
      CoreModule.php    # ID, LABEL, REQUIRED, permissions()
      Domain/ Application/ Infrastructure/
    Commercial/         # Exemple d'autre module
frontend/
  app/                  # Shell (layouts, middlewares)
  shared/               # Code inter-modules (composables, stores, utils)
  modules/              # Layers Nuxt auto-detectes
    core/ commercial/
```

## Declaration d'un module

Chaque module expose un `*Module.php` avec :
- `ID` (snake_case, ex: `commercial`, `gestion_rh`)
- `LABEL`
- `REQUIRED` (bool)
- Methode statique `permissions()` retournant les RBAC du module

## Activer / desactiver un module

Editer uniquement `config/modules.php` (commenter la ligne). Cascade automatique :
1. `/api/modules` ne retourne plus l'ID
2. `/api/sidebar` filtre les items `module: '<id>'` et supprime les sections vides
3. Middleware front `modules.global.ts` redirige toute navigation vers une route desactivee
4. Le code reste dans le bundle (layer auto-detecte) → reactivation instantanee sans rebuild

## Reorganiser la sidebar

Editer uniquement `config/sidebar.php`. Le code des modules n'est pas touche — seule la place des items change. Chaque item reference son module owner via la cle `module`.

## Communication inter-modules

**Interdit** : import direct d'une classe d'un autre module.
**Autorise** :
- Via `Shared/Domain/Contract/` (interfaces : `UserResolverInterface`, `TenantAwareInterface`...)
- Via domain events (`Shared/Domain/Event/DomainEventInterface`)

## Migrations

- **Par defaut** : `src/Module/<Module>/Infrastructure/Doctrine/Migrations/` (namespace modulaire)
- **Exception** : les migrations d'initialisation critiques (setup user, RBAC, seed de base) vivent au namespace racine `DoctrineMigrations` dans `migrations/`.
  - Raison : avec plusieurs `migrations_paths`, Doctrine Migrations 3.x trie par FQCN alphabetique et non par version timestamp → ordre incorrect entre namespaces sur base vide.
  - A supprimer quand un `MigrationsComparator` custom ou un upgrade Doctrine resoudra le tri.
