0e3299300f
Auto Tag Develop / tag (push) Successful in 11s
## Objectif
Seeder le RBAC métier de façon **rejouable et disponible en recette/prod** (commande applicative, pas fixture `require-dev`), durcir RG-1.04, et écrire le test de matrice (rôles enfin existants).
## A. `RbacSeeder` (Core) — source unique anti-drift
4 rôles (`bureau`/`compta`/`commerciale`/`usine`, isSystem=false), matrice § 2.7 (rôle → permissions) et comptes démo, définis en **un seul endroit**. Méthodes idempotentes `ensureRoles` / `attachMatrix` / `ensureDemoUsers`. `commerciale` référence `BusinessRoles::COMMERCIALE` (déjà consommé par RG-1.04).
## B. Commande `app:seed-rbac` (présente en build prod, idempotente, non destructive)
- Sans option : rôles + matrice § 2.7.
- `--with-demo-users` + `--password=<…>` ou env `RBAC_DEMO_PASSWORD` : 1 compte démo/rôle. **Aucun mot de passe en dur** côté serveur.
- Garde-fou : exit non-zéro + invite à lancer `app:sync-permissions` si les codes `commercial.clients.*` manquent.
## C. Fixture dev/test `RbacDemoFixtures` (DRY)
Appelle le **même seeder** (`ensureRoles` + `ensureDemoUsers`). La matrice est attachée juste après par l'étape `app:seed-rbac` du makefile (la table `permission` est purgée au moment du `fixtures:load`, donc `attachMatrix` ne peut pas tourner pendant le load). `make db-reset` / `test-db-setup` reproduisent l'état de recette.
## Déploiement (documenté README)
Après `migration-migrate` + `app:sync-permissions` : `app:seed-rbac` (prod) ; `app:seed-rbac --with-demo-users --password=…` (recette).
## D. Durcissement RG-1.04
Pour une Commerciale, complétude de l'onglet Information exigée sur **POST + tout PATCH** (suppression de la condition d'intersection). Conséquence : POST Commerciale → 422 (le POST n'expose pas le groupe Information), Admin → 201. Spec § 7 amendée.
## Compta ↔ onglet Comptabilité (§ 2.7)
Pour que `compta PATCH accounting → 200` (exigé par la matrice), la security du `Patch /clients/{id}` est élargie à `manage` **OU** `accounting.manage`, et un nouveau **`guardManage`** (mode strict RG-1.28) interdit à un porteur non-`manage` de modifier les onglets principal/Information (→ 403). Approche validée : élargir la security + guard in-processor (pas de nouvel endpoint).
## E. `ClientRBACMatrixTest`
Matrice § 2.7 complète via les comptes démo seedés (`app:seed-rbac --with-demo-users`) : bureau / compta / commerciale / usine (200/403 par verbe et par onglet) + RG-1.04 (POST Commerciale 422 / Admin 201).
## Tests
`make php-cs-fixer-allow-risky` OK ; `make test` **429 tests verts**. Idempotence vérifiée (rejeu de la commande : 0 rôle / 0 lien / 0 user). `test-db-setup` exécute la nouvelle étape `app:seed-rbac` sans erreur.
Cible : `develop`. Squash merge.
---------
Co-authored-by: Matthieu <contact@malio.fr>
Reviewed-on: #40
Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
217 lines
8.3 KiB
Markdown
217 lines
8.3 KiB
Markdown
# Starseed
|
|
|
|
CRM/ERP — Symfony 8 (API Platform 4) + Nuxt 4
|
|
|
|
## Stack
|
|
|
|
- **Backend** : PHP 8.4, Symfony 8, API Platform 4, Doctrine ORM, PostgreSQL 16
|
|
- **Frontend** : Nuxt 4 (SPA), Vue 3, Pinia, Tailwind CSS, @malio/layer-ui
|
|
- **Auth** : JWT HTTP-only cookie (Lexik)
|
|
- **Infra** : Docker Compose (dev + prod multi-stage)
|
|
- **CI/CD** : Gitea Actions (auto-tag + build Docker)
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
make start # Demarrer les containers Docker
|
|
make install # Composer, migrations, fixtures, build Nuxt
|
|
```
|
|
|
|
Dev frontend (hot reload) :
|
|
|
|
```bash
|
|
make dev-nuxt # Port 3003
|
|
```
|
|
|
|
## Ports
|
|
|
|
| Service | Port |
|
|
|------------|------|
|
|
| API (Nginx)| 8083 |
|
|
| Frontend | 3004 |
|
|
| PostgreSQL | 5437 |
|
|
|
|
## Commandes
|
|
|
|
| Commande | Description |
|
|
|----------|-------------|
|
|
| `make start` | Demarrer les containers |
|
|
| `make stop` | Arreter les containers |
|
|
| `make restart` | Redemarrer les containers |
|
|
| `make install` | Install complet |
|
|
| `make reset` | Tout supprimer et reinstaller |
|
|
| `make dev-nuxt` | Serveur dev Nuxt (hot reload) |
|
|
| `make shell` | Shell dans le container PHP |
|
|
| `make cache-clear` | Vider le cache Symfony |
|
|
| `make migration-migrate` | Lancer les migrations |
|
|
| `make fixtures` | Charger les fixtures |
|
|
| `make db-reset` | Reset BDD + migrations + fixtures |
|
|
| `make test` | PHPUnit (tests back) |
|
|
| `make nuxt-test` | Vitest (tests unitaires front) |
|
|
| `make test-e2e` | Playwright (tests E2E front) |
|
|
| `make test-e2e-ui` | Playwright UI interactive (debug) |
|
|
| `make seed-e2e` | Seed les 6 personas E2E |
|
|
| `make install-e2e-deps` | One-time : Chromium + libs systeme (sudo) |
|
|
| `make php-cs-fixer-allow-risky` | Fix code style PHP |
|
|
| `make logs-dev` | Tail logs Symfony |
|
|
|
|
## Tests
|
|
|
|
- **Back** : `make test` (PHPUnit). Fixtures dediees sous `tests/Fixtures/`.
|
|
- **Front unitaire** : `make nuxt-test` (Vitest, happy-dom). Composables, utils, stores — rapide, <30s.
|
|
- **Front E2E** : `make test-e2e` (Playwright). Couvre login + matrice RBAC sidebar. Suite volontairement minimaliste (11 tests) — voir la regle d'or dans `CLAUDE.md`.
|
|
|
|
**Bootstrap E2E (une fois par poste)** :
|
|
```bash
|
|
make install-e2e-deps # Telecharge Chromium + libs systeme via apt (sudo)
|
|
```
|
|
|
|
**Workflow E2E** :
|
|
```bash
|
|
# Terminal 1 : containers + dev server
|
|
make start && make seed-e2e && make dev-nuxt
|
|
|
|
# Terminal 2 : tests
|
|
make test-e2e
|
|
```
|
|
|
|
## Architecture
|
|
|
|
**Modular Monolith DDD** : chaque module est un bounded context autonome, activable/desactivable par tenant. Le backend est la seule source de verite pour l'activation et l'organisation de la sidebar.
|
|
|
|
- `config/modules.php` — liste des modules actifs
|
|
- `config/sidebar.php` — structure de la sidebar (sections + items avec module owner)
|
|
- `GET /api/sidebar` — retourne les sections filtrees par les modules actifs + les routes desactivees
|
|
- Frontend : chaque `frontend/modules/*/` est auto-detecte comme layer Nuxt, la sidebar est fetchee de l'API
|
|
|
|
Pour desactiver un module : commenter sa ligne dans `config/modules.php`, clear cache. Ses items de sidebar disparaissent et ses routes sont bloquees par le middleware front.
|
|
|
|
Pour reorganiser la sidebar (ex: deplacer un item d'une section a l'autre) : editer `config/sidebar.php` uniquement, le code des modules n'est pas touche.
|
|
|
|
## Structure
|
|
|
|
```
|
|
src/ # Backend Symfony
|
|
Kernel.php
|
|
Shared/ # Noyau technique partage
|
|
Domain/
|
|
ValueObject/ # Email, ...
|
|
Event/ # DomainEventInterface
|
|
Contract/ # Interfaces inter-modules
|
|
Application/
|
|
Bus/ # CommandBusInterface, QueryBusInterface
|
|
Infrastructure/
|
|
ApiPlatform/
|
|
Resource/ # AppVersion, ModulesResource, SidebarResource
|
|
State/ # AppVersionProvider, ModulesProvider, SidebarProvider
|
|
Module/
|
|
Core/ # Module obligatoire (auth, users)
|
|
CoreModule.php # Declaration (ID, LABEL, REQUIRED)
|
|
Domain/
|
|
Entity/ # User
|
|
Repository/ # UserRepositoryInterface
|
|
Event/ # UserCreated
|
|
Application/
|
|
DTO/ # UserOutput
|
|
Infrastructure/
|
|
Doctrine/ # DoctrineUserRepository, Migrations/
|
|
ApiPlatform/State/
|
|
Provider/ # MeProvider
|
|
Processor/ # UserPasswordHasherProcessor
|
|
Console/ # CreateUserCommand
|
|
DataFixtures/ # AppFixtures
|
|
Commercial/ # Autre module (exemple)
|
|
CommercialModule.php
|
|
config/
|
|
modules.php # Source de verite activation
|
|
sidebar.php # Source de verite navigation
|
|
version.yaml
|
|
packages/ # Config Symfony
|
|
jwt/ # Cles JWT
|
|
migrations/ # Anciennes migrations
|
|
frontend/ # App Nuxt 4 (SPA)
|
|
app/
|
|
layouts/ # default.vue, auth.vue
|
|
middleware/ # auth.global.ts, modules.global.ts
|
|
shared/ # Code partage (hors modules)
|
|
composables/ # useApi, useAppVersion, useSidebar
|
|
components/ui/ # AppTopNav, ...
|
|
stores/ # auth, ui
|
|
services/ # auth
|
|
types/ # SidebarSection, UserData
|
|
utils/ # api (Hydra)
|
|
modules/ # Modules auto-detectes comme layers Nuxt
|
|
core/
|
|
nuxt.config.ts # Marqueur layer
|
|
pages/ # index, login, logout
|
|
commercial/
|
|
nuxt.config.ts
|
|
pages/ # commercial.vue
|
|
app.vue
|
|
nuxt.config.ts # Scanne modules/*/ automatiquement
|
|
i18n/locales/ # Traductions (sidebar.*, etc.)
|
|
assets/ # CSS, images
|
|
public/ # Fichiers statiques
|
|
infra/
|
|
dev/ # Docker dev (Dockerfile, nginx, php.ini, xdebug)
|
|
prod/ # Docker prod (multi-stage, nginx, php-prod.ini)
|
|
.gitea/workflows/ # CI Gitea (auto-tag, build Docker)
|
|
.claude/
|
|
skills/create-module/ # Skill Claude Code pour scaffolder un module
|
|
```
|
|
|
|
## CI/CD
|
|
|
|
- **Auto Tag** : push sur `develop` → bump `config/version.yaml` → tag `vX.Y.Z`
|
|
- **Build Docker** : push tag `v*` → build image multi-stage → push Gitea Registry
|
|
|
|
Secrets requis dans Gitea :
|
|
- `RELEASE_TOKEN` — PAT avec droits `write:repository`
|
|
- `REGISTRY_TOKEN` — token pour le registry Docker
|
|
|
|
## Déploiement — seed RBAC (recette / prod)
|
|
|
|
Le RBAC métier (rôles `bureau` / `compta` / `commerciale` / `usine` + matrice § 2.7)
|
|
est seedé par une **commande applicative idempotente** (présente dans le build prod,
|
|
contrairement aux fixtures Doctrine en `require-dev`). À jouer dans l'étape de release,
|
|
**après** les migrations et la synchronisation des permissions :
|
|
|
|
```bash
|
|
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 (mot de passe
|
|
fourni explicitement, jamais en dur) :
|
|
|
|
```bash
|
|
php bin/console app:seed-rbac --with-demo-users --password='<mot-de-passe>'
|
|
# ou via la variable d'env RBAC_DEMO_PASSWORD
|
|
```
|
|
|
|
La commande est rejouable sans effet de bord (aucun doublon de rôle, de lien ou de compte).
|
|
En dev, `make db-reset` produit le même résultat (rôles + matrice + comptes démo).
|
|
|
|
## Credentials (dev)
|
|
|
|
| Username | Password | Role | RBAC métier |
|
|
|----------|----------|------|-------------|
|
|
| admin | admin | ROLE_ADMIN | bypass (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 |
|
|
|
|
## Conventions
|
|
|
|
### Commits
|
|
|
|
```
|
|
<type>(<scope optionnel>) : <message>
|
|
```
|
|
|
|
Types : `build`, `chore`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `revert`, `style`, `test`
|