Files
Lesstime/CLAUDE.md
2026-03-15 21:26:05 +01:00

7.0 KiB

Lesstime

Application de gestion de projet. Monorepo Symfony 8 (API Platform 4) + Nuxt 4.

Stack

  • Backend : PHP 8.4, Symfony 8.0, API Platform 4, Doctrine ORM, PostgreSQL 16
  • Frontend : Nuxt 4 (SSR off / SPA), Vue 3, Pinia, Tailwind CSS, @malio/layer-ui, nuxt-toast, @nuxtjs/i18n, @nuxt/icon
  • Auth : JWT HTTP-only cookie (lexik/jwt-authentication-bundle), login à /login_check, cookie BEARER
  • Docker : PHP-FPM + Node 24, Nginx (port 8082), PostgreSQL (port 5435)

Structure

src/Entity/          # Entités Doctrine (User, Client, Project, Task, TaskStatus, TaskEffort, TaskPriority, TaskTag, TaskGroup, TimeEntry, GiteaConfiguration, ClientTicket, Notification, TaskDocument)
src/ApiResource/     # Ressources API Platform (si découplées des entités)
src/State/           # Providers et Processors API Platform (MeProvider, AppVersionProvider, ActiveTimeEntryProvider, UserPasswordHasherProcessor, TaskNumberProcessor, ClientTicket*Provider/Processor, NotificationProvider, Gitea*Provider, Gitea*Processor)
src/Service/         # Services métier (NotificationService)
src/Controller/      # Controllers custom Symfony (NotificationUnreadCountController, MarkAllReadController)
src/Mcp/Tool/        # MCP tools organisés par domaine (Project/, Task/, TaskMeta/, TimeEntry/, Reference/)
src/Security/        # Authenticators custom (ApiTokenAuthenticator pour MCP HTTP)
src/Command/         # Commandes console (GenerateApiTokenCommand)
src/Repository/      # Repositories Doctrine
src/DataFixtures/    # Fixtures
config/              # Config Symfony (security, api_platform, lexik_jwt, nelmio_cors, doctrine)
config/jwt/          # Clés JWT (private.pem, public.pem)
migrations/          # Migrations Doctrine
docs/plans/          # Plans d'implémentation
docs/superpowers/    # Plans et specs superpowers
frontend/            # App Nuxt 4
frontend/pages/      # Pages (index, login, my-tasks, projects, projects/[id], projects/[id]/groups, projects/[id]/archives, time-tracking, admin, portal/, portal/projects/[id], portal/projects/[id]/new-ticket)
frontend/layouts/    # Layouts (default, portal)
frontend/components/ # Composants Vue organisés en sous-dossiers (ui/, client/, project/, task/, user/, admin/, time-tracking/, client-ticket/, notification/)
frontend/composables/# Composables (useApi, useAppVersion, useNotifications, useClientTicketHelpers)
frontend/stores/     # Stores Pinia (auth, ui, timer)
frontend/services/   # Services API (auth, clients, gitea, projects, tasks, task-statuses, task-efforts, task-groups, task-priorities, task-tags, users, time-entries, client-tickets, notifications, task-documents)
frontend/services/dto/ # Types TypeScript
frontend/i18n/locales/ # Fichiers de traduction (langDir résolu depuis i18n/)

Commandes

make start           # Démarrer les containers
make stop            # Arrêter les containers
make restart         # Redémarrer les containers
make install         # Install complet (composer, migrations, fixtures, build Nuxt)
make reset           # Tout supprimer et réinstaller (supprime la BDD)
make dev-nuxt        # Dev server Nuxt (hot reload, port 3002)
make shell           # Shell dans le container PHP
make shell-root      # Shell root 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

Conventions

Commits

Format : <type>(<scope optionnel>) : <message> (espace avant et après :)

Types autorisés (minuscules) : build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test

Exemples : feat : add login page, fix(auth) : prevent null token crash

Backend

  • Toujours declare(strict_types=1) en haut des fichiers PHP
  • API Platform : utiliser ApiResource, Providers (src/State/), Processors — pas de controllers
  • Routes API préfixées /api (via config/routes/api_platform.yaml)
  • Le login (/login_check) est hors prefix /api, nginx réécrit REQUEST_URI vers /login_check
  • PHP CS Fixer : règles Symfony + PSR-12 + strict types
  • Rôles : ROLE_ADMIN, ROLE_USER, ROLE_CLIENT — hiérarchie dans security.yaml
  • User::getRoles() n'ajoute PAS ROLE_USER si l'user a ROLE_CLIENT (isolation)
  • PostgreSQL : LIKE sur colonne JSON ne marche pas → utiliser roles::text LIKE via native SQL
  • Controllers custom sous /api/ : ajouter priority: 1 sur #[Route] pour éviter le conflit avec API Platform {id}
  • Serialization : pour embarquer une relation (pas IRI), ajouter le groupe du parent aux propriétés de l'entité cible

Frontend

  • TypeScript strict
  • Composable useApi() pour tous les appels API (gère cookies, erreurs, toasts, i18n)
  • Stores Pinia : useAuthStore (auth), useUiStore (ui), useTimerStore (timer)
  • Middleware global auth.global.ts protège les routes
  • Traductions dans frontend/i18n/locales/ (le module résout langDir depuis i18n/)
  • 4 espaces d'indentation
  • MalioSelect : options { label: string, value: number | null } uniquement — pas de string values, utiliser <select> natif pour les enums string
  • Portal client : pages sous /portal/, layout portal.vue, middleware redirige ROLE_CLIENT (sans ROLE_ADMIN) vers /portal
  • Users admin+client : ne pas bloquer — vérifier ROLE_CLIENT && !ROLE_ADMIN pour les restrictions

MCP Server

  • 22 tools MCP exposant projets, tâches, métadonnées, et time tracking
  • Transport STDIO (local) : docker exec -i php-lesstime-fpm php bin/console mcp:server
  • Transport HTTP (réseau) : POST /_mcp avec header Authorization: Bearer <token>
  • Auth HTTP : ApiTokenAuthenticator vérifie le champ apiToken de l'entité User
  • Générer un token : php bin/console app:generate-api-token <username>
  • Config : config/packages/mcp.yaml, firewall dans config/packages/security.yaml
  • Attribut #[McpTool] doit être sur la classe (pas la méthode __invoke) pour la discovery SDK

Nginx

  • /_mcp → Symfony (MCP HTTP transport)
  • /api/* → Symfony (via try_files + index.php)
  • /api/login_check → location exact match, fastcgi direct avec REQUEST_URI réécrit en /login_check
  • / → SPA frontend (frontend/dist/)

Docker

  • Container PHP : php-lesstime-fpm
  • Container Nginx : nginx-lesstime
  • Container DB : PostgreSQL sur port 5435 (interne et externe)
  • Config Docker : docker/.env.docker (override local : docker/.env.docker.local)
  • Après modif nginx : docker restart nginx-lesstime

Fixtures

  • User admin : admin / admin (ROLE_ADMIN)
  • Users internes : alice / alice, bob / bob, charlie / charlie (ROLE_USER)
  • Users client : client-liot / client (ROLE_CLIENT, client LIOT → SIRH), client-acme / client (ROLE_CLIENT, client ACME → CRM)
  • API token admin (dev) : dev-mcp-token-for-testing-only-do-not-use-in-production