Files
Starseed/CLAUDE.md
T
tristan 3e46394be1
Auto Tag Develop / tag (push) Successful in 7s
[ERP-72] Paginer toutes les collections API + regle pagination obligatoire (#28)
## Contexte

Ticket Lesstime : [#72](https://lesstime.malio.fr/project/6/task/491) (id 491) — ticket transversal, pas de spec dediee : la description du ticket fait foi.

## Implementation

- **Defaut global de pagination** dans `config/packages/api_platform.yaml` : `items_per_page=10`, `maximum_items_per_page=50`, `client_items_per_page=true`, **`client_enabled=true`** (echappatoire `?pagination=false` pour alimenter les `<select>` cote front).
- **`CategoryProvider` refondu** : retourne maintenant un `ApiPlatform\Doctrine\Orm\Paginator(Doctrine\ORM\Tools\Pagination\Paginator(...))` au lieu d'un array brut. Supporte `?pagination=false`.
- **`AuditLogResource`** : override `paginationItemsPerPage=30 / max=50 / clientItemsPerPage=true` supprime, herite du global (10/50). `AuditLogProvider` (`DbalPaginator`) inchange.
- **Autres ressources** (`Category`, `CategoryType`, `User`, `Role`, `Permission`, `Site`) : aucun changement de code, heritent automatiquement.
- **Regle « pagination obligatoire »** documentee : `CLAUDE.md` (regle ABSOLUE n°13 + section « A NE PAS faire ») + `.claude/rules/backend.md` (nouvelle section dediee avec standard, override, selects, providers customs, garde-fou).
- **Garde-fou CI** : `tests/Architecture/CollectionsArePaginatedTest` echoue si une `GetCollection` desactive la pagination sans whitelist `EXCLUDED`.

## Adaptation collaterale (non prevue au plan initial)

7 appels `GET /api/<collection>` dans les tests existants (`CategoryListTest`, `PermissionApiTest`, `RoleApiTest`) ont recu `?pagination=false` parce qu'ils asseyaient sur le contenu complet de l'array. Sans cette adaptation, le commit Task 1 cassait `PermissionApiTest::testCollectionFilterByOrphanFalse`.

## Criteres d'acceptation

- [x] Toutes les collections API existantes paginees (plus aucun retour complet)
- [x] `itemsPerPage` par defaut (10) + max borne (50)
- [x] Tri / filtres / recherche fonctionnent combines a la pagination
- [x] `hydra:totalItems` (cle `totalItems` en JSON-LD API Platform 4) expose pour le front
- [x] Regle documentee (`CLAUDE.md` + `.claude/rules/backend.md`)

## Tests

- `docker exec -t php-starseed-fpm php -d memory_limit=512M vendor/bin/phpunit` → **Tests: 320, 0 failures** (etait 312 avant ce ticket → +8 nouveaux : 5 `CategoryPaginationTest` + 2 `AuditLogPaginationRegressionTest` + 1 `CollectionsArePaginatedTest`)
- `make php-cs-fixer-allow-risky` → 0 fix
- Verifications HTTP manuelles : voir cahier de test dans le ticket Lesstime #72

## Note d'incident

Le tout premier commit (`9060f5d`, pose du standard YAML) a ete cree avec `--no-verify` par un subagent qui n'a pas respecte la consigne explicite « jamais de bypass de hook ». La cause sous-jacente du hook failure etait un drift BDD locale sur `ColumnsHaveSqlCommentTest`, resolu ensuite via `make db-reset`. Les 6 commits suivants ont passe le hook normalement. Le contenu de `9060f5d` est correct (15 lignes YAML ajoutees) — a re-verifier en review.

## Reviewer suggere

A definir (Tristan etant l'auteur).

## Suite

Debloque le volet front **ERP-73** (pagination `MalioDataTable` + composable reutilisable + cablage `?pagination=false` sur les composables de select Role/Permission/Site/CategoryType).

Reviewed-on: #28
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
2026-05-29 14:15:41 +00:00

5.3 KiB

Starseed

Contexte

CRM/ERP en architecture modular monolith DDD. Le backend est la source de verite unique (modules actifs, sidebar). Le frontend scanne frontend/modules/*/ comme layers Nuxt et consomme l'API pour la navigation. Multi-tenant : chaque module est activable/desactivable.

Doc humaine : @README.md — Spec audit : @doc/audit-log.md

Stack

  • Backend : PHP 8.4, Symfony 8, API Platform 4, Doctrine ORM, PostgreSQL 16 (port 5437)
  • Frontend : Nuxt 4 (SPA), Vue 3, Pinia, Tailwind, @malio/layer-ui, @nuxtjs/i18n
  • Auth : JWT HTTP-only cookie (Lexik), login a /login_check
  • Containers : php-starseed-fpm, nginx-starseed (port 8083), dev Nuxt port 3004

Regles ABSOLUES

  1. Ne jamais importer d'un module a un autre — passer par Shared/Domain/Contract/ (interfaces) ou domain events.
  2. Toujours declare(strict_types=1); en tete de tout fichier PHP.
  3. Toujours annoter #[Auditable] les entites metier ; #[AuditIgnore] sur champs sensibles (password, token, secret).
  4. Toujours utiliser useApi() pour les appels API cote front — jamais $fetch / ofetch direct.
  5. Toujours utiliser les composants Malio* (@malio/layer-ui) pour formulaires/filtres ; MalioDataTable pour listes paginees.
  6. Jamais persister l'etat de tableau dans l'URL (filtres, pagination, tri, selection) — state local uniquement.
  7. Jamais ajouter un test E2E sauf si un bug critique est passe en prod ; preferer un test Vitest.
  8. Toujours mettre a jour les 3 sources RBAC ensemble : config/sidebar.php, frontend/tests/e2e/_fixtures/personas.ts, src/Module/Core/Infrastructure/Console/SeedE2ECommand.php.
  9. Jamais commit sans demande explicite de l'utilisateur ; jamais force push sans confirmation.
  10. Jamais mentionner Claude, Anthropic ou une IA dans un commit (message, titre, body, footer, trailer) ou une PR (titre, description). Pas de Co-Authored-By: Claude, pas de Generated with Claude Code, pas de 🤖, pas d'emoji robot, rien. Les commits sont signes par l'utilisateur uniquement.
  11. Migrations d'initialisation au namespace racine DoctrineMigrations dans migrations/ (setup user, RBAC, seed de base). Les migrations modulaires (src/Module/*/Infrastructure/Doctrine/Migrations/) sont reservees aux evolutions post-schema (ajout de colonnes, index) — cf. @.claude/rules/architecture.md pour la raison.
  12. Toujours documenter chaque colonne BDD via COMMENT ON COLUMN dans la migration qui la cree ou la modifie. Description en francais, courte (≤ 200 caracteres), explique la semantique metier + contraintes implicites (unicite partielle, FK importante, lien RG). Garde-fou : tests/Architecture/ColumnsHaveSqlCommentTest echoue si une colonne public n'a pas de description (col_description IS NULL). Details et exemples : @.claude/rules/backend.md § Migrations Doctrine.
  13. Toujours paginer toute collection exposee par l'API. Aucun retour de collection complete (pas de provider qui retourne un array brut). Standard pose dans config/packages/api_platform.yaml : 10 items par defaut, max 50, le client peut basculer entre 10/25/50 et peut envoyer ?pagination=false pour alimenter un select. Garde-fou : tests/Architecture/CollectionsArePaginatedTest echoue si une GetCollection desactive la pagination sans whitelist. Details et exemples : @.claude/rules/backend.md § Pagination.

Conventions

@.claude/rules/architecture.md @.claude/rules/backend.md @.claude/rules/frontend.md @.claude/rules/testing.md @.claude/rules/naming.md @.claude/rules/git.md @.claude/rules/workflow.md

Commandes (liste complete dans @README.md)

  • Demarrer : make start
  • Dev front (hot reload) : make dev-nuxt (port 3004)
  • Shell PHP : make shell
  • Tests back : make test
  • Tests front unitaires : make nuxt-test
  • Tests E2E : make test-e2e (prerequis : make seed-e2e && make dev-nuxt)
  • Reset BDD : make db-reset
  • Lint PHP : make php-cs-fixer-allow-risky

Activer / desactiver un module

Editer uniquement config/modules.php (commenter la ligne). Cascade automatique via /api/modules, /api/sidebar, middleware front modules.global.ts. Details : @.claude/rules/architecture.md

A NE PAS faire

  • Pas de controller Symfony custom sous /api/ sans priority: 1 sur #[Route] (conflit API Platform {id}).
  • Pas de provider API Platform qui retourne un array brut sur une GetCollection — court-circuite la pagination Hydra (totalItems / view absents). Utiliser ApiPlatform\Doctrine\Orm\Paginator (ORM) ou un paginator implementant PaginatorInterface (DBAL — cf. DbalPaginator).
  • Pas de getClientMimeType() pour valider un upload — utiliser $file->getMimeType() (serveur).
  • Pas de hardcode de la sidebar cote front, pas de modules-loader.ts ni .module.ts.
  • Pas d'edition manuelle de extends dans frontend/nuxt.config.ts — les layers sont scannes automatiquement.
  • Pas de commentaires en anglais dans le code — commentaires en francais, code (noms) en anglais.
  • Pas d'<input> / <select> / <table> bruts quand un composant @malio/layer-ui existe (exceptions documentees dans @.claude/rules/frontend.md).
  • Pas de modification de la config git.

Skills projet

  • create-module — scaffolder un nouveau module back+front et wirer la sidebar.

Credentials (dev)

admin / admin (ROLE_ADMIN) ; alice / alice, bob / bob (ROLE_USER).