docs(claude) : refactorise CLAUDE.md en index + extrait les regles dans .claude/rules/
- CLAUDE.md devient un index concis : contexte, stack, regles absolues numerotees, pointeurs vers les fichiers de regles detaillees via references @.claude/rules/*.md - Les conventions detaillees (architecture, backend, frontend, testing, naming, git, workflow) sont extraites dans .claude/rules/ pour rester chargees a la demande sans gonfler le context du CLAUDE.md principal - Ajoute la regle absolue "Ne jamais mentionner Claude/IA dans commits ou PR" (point 10) pour garder l'historique git signe par l'utilisateur
This commit is contained in:
66
.claude/rules/architecture.md
Normal file
66
.claude/rules/architecture.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# 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.
|
||||
55
.claude/rules/backend.md
Normal file
55
.claude/rules/backend.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Backend — Regles PHP / Symfony / API Platform
|
||||
|
||||
## Structure de fichier
|
||||
|
||||
- Toujours `declare(strict_types=1);` en tete de tout fichier PHP
|
||||
- PHP CS Fixer : regles Symfony + PSR-12 + strict types (commande : `make php-cs-fixer-allow-risky`)
|
||||
- Commentaires (docblock, inline, bloc) **en francais** ; code (classes, methodes, variables) en anglais
|
||||
|
||||
## API Platform (pas de controllers)
|
||||
|
||||
- Toujours utiliser `#[ApiResource]` + Providers + Processors — pas de controllers Symfony classiques
|
||||
- Routes prefixees `/api` (via `config/routes/api_platform.yaml`)
|
||||
- Le login `/login_check` est **hors** prefix `/api` (nginx reecrit `REQUEST_URI` vers `/login_check`)
|
||||
- **Exception** : si tu dois creer un controller custom sous `/api/`, mettre `priority: 1` sur `#[Route]` pour eviter le conflit avec API Platform `{id}`
|
||||
|
||||
## Repositories
|
||||
|
||||
- Interface : `*RepositoryInterface` dans `Domain/Repository/`
|
||||
- Implementation Doctrine : `Doctrine*Repository` dans `Infrastructure/Doctrine/`
|
||||
- Le domaine garde les attributs ORM (approche pragmatique)
|
||||
|
||||
## RBAC (permissions)
|
||||
|
||||
Format obligatoire : `module.resource[.subresource].action` en snake_case.
|
||||
- Exemples : `core.users.view`, `commercial.clients.contacts.edit`, `core.audit_log.view`
|
||||
- Declarees via la methode statique `permissions()` des `*Module.php`
|
||||
- Synchronisation : `app:sync-permissions`
|
||||
- Verification API Platform : `is_granted('module.resource.action')`
|
||||
- Verification front : `usePermissions()`
|
||||
|
||||
## Roles
|
||||
|
||||
- Hierarchie dans `config/packages/security.yaml` : `ROLE_ADMIN`, `ROLE_USER`
|
||||
- Le role ne remplace pas la permission RBAC — deux niveaux complementaires
|
||||
|
||||
## Audit (obligatoire)
|
||||
|
||||
- Toute entite metier (nouvelle ou existante) : `#[Auditable]` (de `Shared/Domain/Attribute/`)
|
||||
- Champs sensibles (password, token, secret) : `#[AuditIgnore]`
|
||||
- Audit ManyToMany : trace automatiquement `{fieldName: {added: [ids], removed: [ids]}}` — aucune action supplementaire
|
||||
- Spec complete : @doc/audit-log.md
|
||||
|
||||
## Serialization
|
||||
|
||||
Pour embarquer une relation dans le JSON (au lieu d'un IRI Hydra), ajouter le groupe du parent sur les proprietes de l'entite cible.
|
||||
|
||||
Exemple : pour qu'`User.profile` soit embarque au lieu d'un lien IRI sous le groupe `user:read`, annoter `Profile.$firstName` avec `#[Groups(['user:read'])]`.
|
||||
|
||||
## Upload de fichiers
|
||||
|
||||
- Valider cote serveur avec `$file->getMimeType()` — **jamais** `getClientMimeType()` (spoofable par le client)
|
||||
|
||||
## PostgreSQL
|
||||
|
||||
- Noms de colonnes toujours en **minuscules** dans le SQL brut (commun a tous les projets MALIO)
|
||||
69
.claude/rules/frontend.md
Normal file
69
.claude/rules/frontend.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# Frontend — Regles Nuxt 4 / Vue 3 / @malio/layer-ui
|
||||
|
||||
## Base
|
||||
|
||||
- TypeScript strict
|
||||
- 4 espaces d'indentation
|
||||
- Commentaires (JSDoc, inline, bloc) **en francais** ; code (variables, types) en anglais
|
||||
- Chaque module front = un layer Nuxt auto-detecte (`frontend/modules/*/nuxt.config.ts` minimal)
|
||||
|
||||
## Appels API
|
||||
|
||||
- Toujours `useApi()` — jamais `$fetch`, `ofetch`, `axios` en direct
|
||||
- `useApi()` gere : cookies JWT, erreurs, toasts i18n, parsing Hydra
|
||||
|
||||
## Stores (Pinia)
|
||||
|
||||
- `useAuthStore` pour l'authentification
|
||||
- `useUiStore` pour l'etat UI global (sidebar, modales, etc.)
|
||||
- Composables avec state singleton (refs module-level) : exposer une fonction `reset*()` et la rappeler au logout (ex: `useSidebar().resetSidebar()`)
|
||||
|
||||
## Middlewares globaux
|
||||
|
||||
- `auth.global.ts` protege les routes + charge la sidebar apres login
|
||||
- `modules.global.ts` redirige si la route demandee est dans `disabledRoutes`
|
||||
|
||||
## i18n et sidebar
|
||||
|
||||
- Labels de sidebar = cles i18n `sidebar.<module>.*`, jamais du texte brut
|
||||
- Le layout `default.vue` applique `t()` sur les labels retournes par `/api/sidebar`
|
||||
- Traductions dans `frontend/i18n/locales/`
|
||||
|
||||
## Composants formulaires — @malio/layer-ui obligatoire
|
||||
|
||||
Tout champ de formulaire / filtre doit utiliser les composants `Malio*` plutot que `<input>` / `<select>` bruts :
|
||||
|
||||
- `MalioInputText`, `MalioInputNumber`, `MalioInputAmount`, `MalioInputPassword`, `MalioInputTextArea`
|
||||
- `MalioSelect`, `MalioSelectCheckbox`, `MalioCheckbox`, `MalioRadioButton`
|
||||
- `MalioInputUpload`, `MalioTime`
|
||||
- `MalioButton`, `MalioButtonIcon`
|
||||
|
||||
**Exceptions autorisees** (commenter un `// TODO` pour migrer quand la lib couvrira le cas) :
|
||||
1. Type non couvert : `datetime-local`, `date`, color picker, file drag & drop
|
||||
2. Bug connu bloquant (ex: `MalioSelect` avec options string) — documenter le bug en commentaire
|
||||
|
||||
Toute autre exception requiert validation avant merge.
|
||||
|
||||
## Tableaux de donnees — MalioDataTable obligatoire
|
||||
|
||||
Tout affichage LISTE tabulaire (donnees metier paginees, CRUD admin) doit passer par `MalioDataTable` :
|
||||
- Pagination integree
|
||||
- Slots `#header-*` pour filtres, `#cell-*` pour rendu custom
|
||||
- Pas de `<table>` brut avec pagination custom
|
||||
|
||||
**Exception** : tableaux purement presentationnels non paginables (diff field/old/new, grille de comparaison, matrice RBAC d'admin, etc.) peuvent rester en `<table>` HTML brut.
|
||||
|
||||
## Etat des tableaux — pas de persistance URL
|
||||
|
||||
**Interdit** de persister l'etat d'un tableau (filtres, pagination, tri par colonne, selection, ligne active, scroll) dans la query string ou de le reinjecter depuis `route.query` au montage.
|
||||
|
||||
- L'etat vit uniquement dans le composant (`reactive`, `ref` locales)
|
||||
- Seuls les deep links "de navigation metier" (ex: ouvrir un detail precis `/users/42`) sont dans l'URL
|
||||
- Exceptions autorisees **sur demande explicite** de l'utilisateur
|
||||
|
||||
## Interdits
|
||||
|
||||
- `modules-loader.ts`, `.module.ts` — le scan des layers est automatique
|
||||
- Hardcode de la sidebar cote front — elle vient de `/api/sidebar`
|
||||
- Edition manuelle de `extends` dans `frontend/nuxt.config.ts` — les layers sont scannes
|
||||
- Import d'un module front depuis un autre module — passer par `frontend/shared/`
|
||||
39
.claude/rules/git.md
Normal file
39
.claude/rules/git.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Git
|
||||
|
||||
## Commits
|
||||
|
||||
Format : `<type>(<scope optionnel>) : <message>`
|
||||
**Espaces obligatoires** autour du `:`.
|
||||
|
||||
Types autorises (minuscules uniquement) : `build`, `chore`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `revert`, `style`, `test`
|
||||
|
||||
Exemples :
|
||||
- `feat : add login page`
|
||||
- `fix(auth) : prevent null token crash`
|
||||
- `chore : bump version to v1.2.3`
|
||||
|
||||
## Regles de commit
|
||||
|
||||
- **Jamais commit sans demande explicite** de l'utilisateur
|
||||
- **Jamais force push** sans confirmation
|
||||
- **Jamais modifier la config git**
|
||||
- **Jamais mentionner Claude, Anthropic ou une IA** dans un commit (message, titre, body, footer, trailer) ou une PR (titre, description). Concretement, aucun des elements suivants ne doit apparaitre :
|
||||
- Trailer `Co-Authored-By: Claude <...>` / `Co-Authored-By: Anthropic`
|
||||
- Footer type `Generated with Claude Code`, `Generated by AI`, etc.
|
||||
- Emoji robot `🤖` ou similaire en tete/fin de message
|
||||
- Toute phrase attribuant la paternite du changement a une IA
|
||||
Les commits sont signes **uniquement** par l'utilisateur. Si un hook ou un template ajoute ces elements automatiquement, les retirer manuellement avant push.
|
||||
|
||||
## Versioning & tags
|
||||
|
||||
La version de l'app est dans `config/version.yaml` (parametre `app.version`).
|
||||
|
||||
Workflow de release :
|
||||
1. Bump `config/version.yaml` a la nouvelle version
|
||||
2. Commit dedie : `chore : bump version to v<X.Y.Z>`
|
||||
3. Tag : `git tag v<X.Y.Z>`
|
||||
4. Push : `git push origin develop --tags`
|
||||
|
||||
**A chaque creation de tag**, toujours mettre a jour `config/version.yaml` avec la meme version — sinon l'app ne connait pas sa propre version.
|
||||
|
||||
CI Gitea automatise le bump sur push `develop` (cf. `.gitea/workflows/`), mais un tag manuel reste possible.
|
||||
18
.claude/rules/naming.md
Normal file
18
.claude/rules/naming.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Nommage
|
||||
|
||||
| Element | Convention | Exemple |
|
||||
|---------|-----------|---------|
|
||||
| Module back | PascalCase | `Module/Commercial/` |
|
||||
| Module front | kebab-case | `modules/commercial/` |
|
||||
| Module ID (dans code/config) | snake_case | `commercial`, `gestion_rh` |
|
||||
| Entity Doctrine | PascalCase singulier | `User.php` |
|
||||
| Repository interface | `*RepositoryInterface` | `UserRepositoryInterface.php` |
|
||||
| Repository impl Doctrine | `Doctrine*Repository` | `DoctrineUserRepository.php` |
|
||||
| DTO | `*Output` / `*Input` | `UserOutput.php` |
|
||||
| API Platform Resource | classe dans `Infrastructure/ApiPlatform/Resource/` | `UserResource.php` |
|
||||
| API Platform Provider | `*Provider` | `MeProvider.php` |
|
||||
| API Platform Processor | `*Processor` | `UserPasswordHasherProcessor.php` |
|
||||
| Module declaration back | `*Module.php` | `CommercialModule.php` |
|
||||
| Composable front | `use*` | `useSidebar.ts` |
|
||||
| Cles i18n sidebar | `sidebar.<module>.*` | `sidebar.commercial.overview` |
|
||||
| Permission RBAC | `module.resource[.subresource].action` | `core.users.view`, `commercial.clients.contacts.edit` |
|
||||
36
.claude/rules/testing.md
Normal file
36
.claude/rules/testing.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Tests
|
||||
|
||||
## Trois suites
|
||||
|
||||
| Suite | Commande | Outil | Where |
|
||||
|---|---|---|---|
|
||||
| Back | `make test` | PHPUnit | Container PHP ; fixtures dediees sous `tests/Fixtures/` |
|
||||
| Front unitaire | `make nuxt-test` | Vitest (happy-dom) | Container Node ; <30s ; composables/utils/stores |
|
||||
| Front E2E | `make test-e2e` | Playwright | **Host** (pas container, navigateur reel requis) |
|
||||
|
||||
Bootstrap E2E (une fois par poste de dev) : `make install-e2e-deps` (Chromium + libs systeme, sudo).
|
||||
Re-run uniquement si `@playwright/test` upgrade majeur.
|
||||
|
||||
Workflow E2E : `make start && make seed-e2e && make dev-nuxt` (terminal 1), `make test-e2e` (terminal 2).
|
||||
UI interactive pour debug : `make test-e2e-ui`.
|
||||
|
||||
## Regle d'or E2E
|
||||
|
||||
**Un nouveau test E2E ne s'ajoute QUE si un bug critique est passe en prod.**
|
||||
|
||||
Sinon, la bonne place est un test unitaire Vitest :
|
||||
- Plus rapide
|
||||
- Plus stable
|
||||
- Moins de faux positifs
|
||||
|
||||
Pour etendre la couverture RBAC, etendre un **persona existant** dans `frontend/tests/e2e/_fixtures/personas.ts` plutot que de creer un nouveau test.
|
||||
|
||||
## Matrice RBAC — 3 endroits obligatoires
|
||||
|
||||
Ajouter/modifier une permission testable = toucher les 3 miroirs (sinon drift garanti) :
|
||||
|
||||
1. `config/sidebar.php` — attacher `permission` au bon item
|
||||
2. `frontend/tests/e2e/_fixtures/personas.ts` — ajuster `permissions` + `expectedAdminLinks` d'un persona existant
|
||||
3. `src/Module/Core/Infrastructure/Console/SeedE2ECommand.php` — miroir back du meme persona
|
||||
|
||||
Tout changement sur l'un des trois sans les deux autres = test casse ou faux positif.
|
||||
66
.claude/rules/workflow.md
Normal file
66
.claude/rules/workflow.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# Workflow
|
||||
|
||||
## Langue
|
||||
|
||||
- **UI** : francais (tout ce qui est visible utilisateur)
|
||||
- **Communication avec l'utilisateur** : francais
|
||||
- **Code** (noms de classes, methodes, variables, types) : anglais
|
||||
- **Commentaires** (PHP, TS, Vue — docblock, inline, bloc) : **francais**. Objectif : faciliter la relecture par l'equipe FR sans polluer l'API publique du code
|
||||
|
||||
## Delegation Codex
|
||||
|
||||
Pour les taches mecaniques (generation de tests boilerplate, renommages massifs, refacto repetitif, scaffolding), **deleguer a Codex** via le plugin `codex` (skill `codex:rescue`).
|
||||
|
||||
- **Codex** = junior rapide et pas cher → executions mecaniques
|
||||
- **Claude** = senior qui verifie et reflechit → design, review, decisions
|
||||
|
||||
Ratio qualite/credits optimal : Claude conserve la reflexion et la validation, Codex avale le boilerplate.
|
||||
|
||||
## Avant d'implementer un ticket
|
||||
|
||||
Les specs fonctionnelles vivent sous `docs/{rbac,sites,modules}/ticket-*-spec.md`.
|
||||
|
||||
Avant de coder :
|
||||
1. Lire la spec correspondante en entier (elles sont longues mais exhaustives)
|
||||
2. Ne pas inventer de detail non specifie — demander a l'utilisateur ou citer explicitement la section manquante
|
||||
3. Si la spec contredit le code existant, poser la question avant de choisir
|
||||
|
||||
## Verification avant "c'est fini"
|
||||
|
||||
Ne jamais declarer une tache terminee sans avoir lance les verifications applicables :
|
||||
|
||||
| Ce qui a bouge | Commande a lancer |
|
||||
|---|---|
|
||||
| Fichiers PHP | `make test` + `make php-cs-fixer-allow-risky` |
|
||||
| Fichiers front (Vue/TS) | `make nuxt-test` |
|
||||
| Migrations | `make migration-migrate` (sur BDD fraiche ideal : `make db-reset`) |
|
||||
| Sidebar / permissions | Verifier que les 3 miroirs RBAC sont alignes (cf. @.claude/rules/testing.md) |
|
||||
| UI visible | Demarrer `make dev-nuxt` et verifier le golden path dans le navigateur |
|
||||
|
||||
Si une verification echoue ou ne peut pas etre lancee (ex : container pas demarre), le dire explicitement plutot que d'annoncer "fini".
|
||||
|
||||
## Time tracking Lesstime
|
||||
|
||||
Au demarrage de toute tache de dev sur Coltura, creer une time entry via l'API Lesstime (cf. `~/.claude/CLAUDE.md` pour la procedure complete).
|
||||
- Projet : `/api/projects/6` (COLTURA)
|
||||
- Tags : choisir selon le type (Backend `3`, Frontend `2`, Infra `5`, UI/UX `4`, Maintenance `6`, Gestion projet `9`, etc.)
|
||||
|
||||
## Fix `make cache-clear` (permissions `var/`)
|
||||
|
||||
Si `make cache-clear` echoue sur les permissions de `var/` :
|
||||
|
||||
```bash
|
||||
docker exec -t -u root php-coltura-fpm chown -R www-data:www-data /var/www/html/var
|
||||
docker exec -t -u www-data php-coltura-fpm php bin/console cache:clear
|
||||
```
|
||||
|
||||
A terme : integrer ce fix dans le `makefile` lui-meme.
|
||||
|
||||
## Docker — references utiles
|
||||
|
||||
- Container PHP : `php-coltura-fpm`
|
||||
- Container Nginx : `nginx-coltura` (port 8083)
|
||||
- Container DB : PostgreSQL port **5437** (interne et externe)
|
||||
- Config dev : `infra/dev/.env.docker` (override local : `infra/dev/.env.docker.local`)
|
||||
- Config prod : `infra/prod/` (Dockerfile multi-stage, `docker-compose.prod.yml`)
|
||||
- Apres modif nginx : `docker restart nginx-coltura`
|
||||
Reference in New Issue
Block a user