tristan 296befe187 feat(sites) : outillage opt-in site-aware (ticket 4/4)
Livre l'infrastructure permettant aux modules metier de declarer leurs
entites comme "scopees par site" via SiteAwareInterface. Strictement
opt-in : aucune entite metier touchee, aucune migration sur tables
existantes.

Composants :
- SiteAwareInterface (Shared/Domain/Contract) : getSite/setSite
- CurrentSiteProvider + interface (Module/Sites/Application) : resolve
  ?Site selon 3 conditions (module actif, user authentifie, currentSite).
  Interface extraite pour mockabilite en tests (implementation reste final).
- SiteScopedQueryExtension : QueryCollection + QueryItem API Platform,
  ajoute WHERE site = :currentSite si resource SiteAware + provider
  non-null + pas sites.bypass_scope.
- SiteAwareInjectionProcessor : decorator de api_platform.doctrine.orm.
  state.persist_processor (#[AsDecorator]). Injecte currentSite sur
  entites SiteAware sans site ; throw 400 si provider null.
- Permission sites.bypass_scope declaree dans SitesModule::permissions().

Tests :
- FakeSiteAwareEntity dans tests/Fixtures/ + mapping when@test dans
  doctrine.yaml. Table creee a la volee via SchemaTool dans setUp.
  schema:update --force ajoute dans test-db-setup pour que fixtures:load
  ne crashe pas au purger.
- 17 tests dedies au ticket 4 (CurrentSiteProvider unitaire, Injection
  Processor unitaire, Extension integration avec 7 cas couvrant filtrage
  collection + item, bypass, no-op, resource non SiteAware).
- SitesModuleTest : verifie le set de 3 permissions + que le decorator
  est bien enregistre sur le persist processor.

Documentation docs/modules/site-aware.md : guide developpeur 8 sections
(quand/ne pas adopter, comment, migration, mode degrade, anti-patterns,
exemple d'adoption Supplier, cascade delete).

Upgrade @malio/layer-ui 1.4.0 → 1.4.2 (bug 1.4.0 : tailwind.config.ts
oublie dans les files publies npm → classe rounded-malio manquante sur
les DataTables). Simplification tailwind.config.ts Coltura : retrait des
colors/fontFamily/borderRadius dupliques, seule la specifique projet
(primary, secondary, tertiary, m.secondary, m.tertiary) est conservee.

Tests : 201/201 avec et sans SitesModule actif (2 skipped en disabled).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 15:11:07 +02:00
2026-04-07 10:56:57 +02:00
2026-04-07 10:56:57 +02:00
2026-04-07 11:42:56 +02:00

Coltura

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

make start           # Demarrer les containers Docker
make install         # Composer, migrations, fixtures, build Nuxt

Dev frontend (hot reload) :

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
make php-cs-fixer-allow-risky Fix code style PHP
make logs-dev Tail logs Symfony

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

Credentials (dev)

Username Password Role
admin admin ROLE_ADMIN
alice alice ROLE_USER
bob bob ROLE_USER

Conventions

Commits

<type>(<scope optionnel>) : <message>

Types : build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test

Description
No description provided
Readme 2.8 MiB
Languages
PHP 69.7%
Vue 14.1%
TypeScript 12.4%
Makefile 1.8%
Dockerfile 0.8%
Other 1.2%