f770812b7e2edcabb732fa3dc00b4d63d4c5a64a
115 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f770812b7e |
fix(front) : usePaginatedList — garde anti-reponse periemee, expose error, durcit buildQuery
- ajoute un jeton de sequence dans fetch() : ignore les reponses arrivees apres une requete plus recente (race page/tri/filtres sur reseau lent) - expose une ref error pour distinguer liste vide d'un echec reseau/403 (isEmpty ne suffit pas a lever l'ambiguite) - buildQuery : cles reservees (page/itemsPerPage/order) assignees en dernier pour qu'un filtre homonyme ne les ecrase pas - corrige le commentaire trompeur sur extraQuery (snapshot statique) - nettoie le test hors-borne qui testait en realite le cas standard + ajoute tests error/reset-error/race |
||
|
|
43c3220873 |
feat(front) : add usePaginatedList composable + paginate all admin lists via MalioDataTable
- frontend/shared/composables/usePaginatedList.ts : composable generique de liste paginee serveur (Hydra), branche directement sur MalioDataTable - 22 tests Vitest (navigation, bornes, parse Hydra, hors-borne, reset, filtres, tri, swallow erreur) - Migration des pages admin existantes : sites, users, roles, categories - Refactor de useCategoriesAdmin pour ne porter que le referentiel CategoryType (charge en une fois via ?pagination=false) - Etat page/tri/filtre 100% local dans le composable (respect regle ABSOLUE n°6 — pas de persistance URL) - Section dediee dans .claude/rules/frontend.md documentant le pattern obligatoire pour toute nouvelle liste ERP-73 — volet front de la pagination, depend du back ERP-72 deja merge. |
||
|
|
0c6919201e |
chore: bump version to v0.1.55
|
||
|
|
3e46394be1 |
[ERP-72] Paginer toutes les collections API + regle pagination obligatoire (#28)
Auto Tag Develop / tag (push) Successful in 7s
## 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> |
||
|
|
1d91b4dea9 |
docs(commercial) : fix § 3.5 incohérence AuditIgnore RIB (aligné sur § 2.5)
Auto Tag Develop / tag (push) Failing after 30s
|
||
|
|
c402418937 |
chore: bump version to v0.1.54
|
||
|
|
2866fb8865 |
[docs] M1 — Répertoire clients : specs front + back (#23)
Auto Tag Develop / tag (push) Successful in 36s
## Contexte Spécifications front + back du **Module 1 — Répertoire clients** (premier module métier Tiers, extension du module `Commercial` existant). Origine : V0 client `.docx` du 22/05/2026 (`M1-reportoire-clients.docx`) + maquette Figma `https://www.figma.com/design/jRYgT0T9c03VsEbjGhCwwS/Composants---Design-System?node-id=1132-31898`. Pattern de rédaction : strictement aligné sur `docs/specs/M0-categories/` (spec-front léger + spec-back très détaillé). ## Contenu - `docs/specs/M1-clients/spec-front.md` (289 lignes) — V0 client, structure UI, composants Malio, permissions par rôle, règles de formatage - `docs/specs/M1-clients/spec-back.md` (1056 lignes) — décisions archi, modèle données, migration SQL Postgres, API REST, RBAC matrice complète, 27 RG numérotées, tests à automatiser, 16 HP, liens & dépendances ## Décisions structurantes (validées avec Tristan le 28/05/2026) - **Module** : extension de `Commercial/` (pas nouveau module) - **Catégories Client** : M2M `client_category` + seed `CategoryType` (`DISTRIBUTEUR`, `COURTIER`, `SECTEUR`, `AUTRE`) - **Distributeur / Courtier** : 2 FK auto-référentes nullables sur `client` + contrainte CHECK mutex - **Workflow création** : sauvegarde incrémentale par onglet (POST formulaire principal → PATCH par onglet) - **Onglets « À venir »** (Transport / Statistiques / Rapports / Échanges) : placeholders blancs (frames vides, pas de message texte) - **Archive vs delete** : flag `is_archived` exposé au M1, colonne `deleted_at` préparée mais non exposée (HP M2) - **API adresse** : api-adresse.data.gouv.fr (BAN), appel direct front via `useAddressAutocomplete()` - **Unicité métier** : SIREN + `companyName` + email (indexes partiels Postgres, ignorent archivés et soft-deletés) - **Téléphones** : 2 colonnes plates `phone_primary` + `phone_secondary` - **Export** : XLSX uniquement (controller custom avec `priority: 1`) - **Compta = lecture seule** ⚠ s'écarte du tableau du `.docx` (ligne « Compta = Ajout/Modification Comptabilité uniquement » invalidée) — documenté en HP-M2-10 ## Seed M1 (référentiels comptables) | Référentiel | Valeurs | |---|---| | `tva_mode` | `FRANCE_VENTES`, `EXPORT_VENTES`, `INTRACOM_VENTES` | | `payment_delay` | `J15`, `J30`, `A_RECEPTION` | | `payment_type` | `VIREMENT`, `LCR`, `NON_SOUMISE`, `CHEQUE` | | `bank` | `SG`, `CIC`, `CA` (Société Générale / CIC / Crédit Agricole) | | `category_type` (extension M0) | `DISTRIBUTEUR`, `COURTIER`, `SECTEUR`, `AUTRE` | ## RG ajoutées au-delà du `.docx` - **RG-1.14** : ≥ 1 bloc Contact valide obligatoire (renforcement Tristan) - **RG-1.15/16/17** : unicités SIREN / nom / email - **RG-1.18** : `companyName` UPPERCASE serveur - **RG-1.19** : `firstName` / `lastName` Capitalize serveur - **RG-1.20** : téléphones chiffres seuls en BDD, formatage `XX XX XX XX XX` au front - **RG-1.21** : emails lowercase serveur - **RG-1.22/23** : archivage / restauration + conflit unicité à la restauration ## Permissions RBAC (à synchroniser dans les 3 miroirs au moment du dev) | Permission | Admin | Bureau | Compta | Commerciale | Usine | |---|---|---|---|---|---| | `commercial.clients.view` | ✅ | ✅ | ✅ | ✅ | ❌ | | `commercial.clients.manage` | ✅ | ✅ | ❌ | ✅ | ❌ | | `commercial.clients.accounting.view` | ✅ | ❌ | ✅ | ❌ | ❌ | | `commercial.clients.accounting.manage` | ✅ | ❌ | ❌ | ❌ | ❌ | | `commercial.clients.archive` | ✅ | ❌ | ❌ | ❌ | ❌ | ## Prochaines étapes (hors MR) 1. Revue / validation des specs par Matthieu 2. Création du **TaskGroup Lesstime** `M1 — Répertoire clients` (projet `ERP / Starseed`, projectId=6) 3. Découpage en ~14 tickets (ordre indicatif listé en bas du `spec-back.md`) ## Reviewer suggéré Matthieu (CP MALIO). ## Cible `develop`. --------- Co-authored-by: admin malio <malio@yuno.malio.fr> Co-authored-by: Matthieu <mtholot19@gmail.com> Reviewed-on: #23 Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> |
||
|
|
0ed131ce57 |
chore: bump version to v0.1.53
|
||
|
|
a948eed9b6 |
[ERP-67] Documenter toutes les colonnes BDD via COMMENT ON COLUMN + garde-fou (#24)
Auto Tag Develop / tag (push) Successful in 7s
Ticket Lesstime : ERP-67 — `[Convention SQL / Backend / L]` ## Objectif Documenter toutes les colonnes BDD via `COMMENT ON COLUMN` (visible dans DBeaver / DataGrip / pgAdmin sans lire le code Doctrine) et verrouiller la convention par un garde-fou de test architecture. ## Changements ### Convention (CLAUDE.md + rules) - `CLAUDE.md` regle ABSOLUE n°12 : toute migration creant ou modifiant une colonne doit poser un `COMMENT ON COLUMN` (FR, ≤ 200 caracteres). - `.claude/rules/backend.md` § Migrations Doctrine : exemples + helper standardise pour les 4 colonnes du `TimestampableBlamableTrait`. ### Garde-fou architecture - `tests/Architecture/ColumnsHaveSqlCommentTest` : echoue si une colonne `public` n'a pas de `col_description` (hors `doctrine_migration_versions` et `fake_site_aware_entity` fixture de test). - Whitelist metier `EXCLUDED_TABLES` volontairement vide. ### Retrofit des tables existantes - Migration `Version20260528120000` : 64 `COMMENT ON TABLE/COLUMN` sur les 11 tables metier (audit_log, category, category_type, permission, role, role_permission, site, user, user_permission, user_role, user_site). - Source unique de verite : `src/Shared/Infrastructure/Database/ColumnCommentsCatalog.php`. - Commande `app:apply-column-comments` (Module/Core/Infrastructure/Console) : rejoue le catalogue apres `doctrine:schema:update --force` (sinon l'ORM drop les commentaires absents du mapping PHP). Branchee dans `makefile test-db-setup` et `.gitea/workflows/pull-request.yml`. ## Validation - `make db-reset` puis `make test` : 312 tests verts, 0 regression. - `make php-cs-fixer-allow-risky` : 0 fix. - Couverture : 53/53 colonnes documentees sur `starseed` et `starseed_test`. ## Test plan - [ ] `make db-reset` passe sans erreur. - [ ] `make test` passe ; `ColumnsHaveSqlCommentTest` vert sur DB de test. - [ ] Verifier dans DBeaver / pgAdmin que les commentaires apparaissent sur les colonnes de `category`, `user`, `audit_log`. - [ ] Verifier que le workflow CI Gitea (`pull-request.yml`) passe. ## A noter pour la suite La convention `options: ['comment' => '...']` sur chaque `#[ORM\Column]` reste recommandee pour les nouvelles entites — Doctrine genere alors automatiquement le `COMMENT ON COLUMN` dans la migration et `schema:update` le preserve sans avoir a rejouer le catalogue. A discuter si on veut en faire une regle forte. --------- Co-authored-by: admin malio <malio@yuno.malio.fr> Co-authored-by: Matthieu <contact@malio.fr> Co-authored-by: Matthieu <mtholot19@gmail.com> Reviewed-on: #24 Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> |
||
|
|
fc78f434d1 |
chore: bump version to v0.1.52
|
||
|
|
53e19d61ac |
[ERP-51] Écrire les tests Vitest des composables Catalog (#26)
Auto Tag Develop / tag (push) Successful in 7s
## Résumé Couvre les deux composables Catalog extraits du refactor ERP-50 avec **42 tests Vitest unitaires** (happy-dom, sans dépendance backend). - 14 tests sur \`useCategoriesAdmin\` (fetchAll/fetchTypes, includeDeleted, loading, error, reset, singleton) - 28 tests sur \`useCategoryForm\` (validation RG-1.02/1.04/1.05 + trim, POST/PATCH/DELETE, mapping 409 RG-1.07 + 422 violations, isDirty, loadFrom, reset, isolation) Mocks via \`vi.stubGlobal\` (useApi / useI18n / useToast) et \`vi.mock\` (\`~/shared/stores/auth\` pour neutraliser l'auto-enregistrement \`onAuthSessionCleared\`). La suite tourne en **~1.2s**. Ticket Lesstime : #51 ## Tests automatisés - \`make nuxt-test\` ✓ 85 tests (dont 42 nouveaux), 0 échec, 1.2s ## Reviewer @matthieu ## À tester en local - [ ] \`make nuxt-test\` passe - [ ] Mock \`useApi\` reste stable si le pattern d'auto-import Nuxt évolue - [ ] Couverture jugée suffisante des cas back miroir Reviewed-on: #26 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr> |
||
|
|
ece8146c03 |
chore: bump version to v0.1.51
|
||
|
|
58589e93d0 |
[ERP-50] Implémenter les composables useCategoriesAdmin et useCategoryForm (#25)
Auto Tag Develop / tag (push) Successful in 6s
Lien Lesstime : #50 ## Résumé Refacto : extraction de la logique fetch/CRUD inline de la page categories (ERP-49) vers deux composables dédiés, conformément au pattern Starseed (useSidebar / useModules). - **useCategoriesAdmin** : singleton state (`categories` + `types` + `loading` + `error`). Pré-chargement des types au mount de la page (au lieu d'un fetch par ouverture du drawer). Reset au logout via `onAuthSessionCleared` + appel explicite dans `logout.vue`. - **useCategoryForm** : state local par form (pas singleton, contrairement à `useCategoriesAdmin`). Valide côté client en miroir des RG back (RG-1.02 / RG-1.04 / RG-1.05), mappe les erreurs 409 (RG-1.07 doublon) et 422 (violations API Platform) sur les bons champs. `submitCreate` / `submitUpdate` / `submitDelete` renvoient la ressource ou `null` pour découpler la décision de fermeture du drawer. La page et le drawer deviennent purement présentationnels — aucune régression UX attendue (mêmes validations, mêmes toasts, même bascule view → edit via `isDirty` exposé par le composable). ## Décisions - `useCategoriesAdmin` porte aussi les types (`fetchTypes`), pas seulement `categories` — sinon le drawer continuerait à fetcher tout seul et la refacto n'aurait rien centralisé. - `buildCreatePayload` retourne `Record<string, unknown>` (pas `CategoryCreateInput`) car la signature `useApi.post(body: AnyObject)` n'accepte pas les types stricts (variance TS). - Reset au logout : double mécanisme conservé (auto via `onAuthSessionCleared` pour 401, explicite dans `logout.vue` pour logout volontaire — pattern existant Starseed). ## Tests - `npx nuxi typecheck` ✓ 0 erreur nouvelle (1 erreur pré-existante sur `modules/catalog/nuxt.config.ts` héritée d'ERP-49) - `make nuxt-test` ✓ 43/43, 0 régression - PHPUnit ✓ 311/311 (pre-commit) - Manuel navigateur : à valider (cahier de test consigné dans Lesstime #50) ## ⚠ Note d'intégration La branche contient encore les 3 commits ERP-49 (`4046910`, `216f388`, `934a12b`) car elle a été créée depuis la branche ERP-49 avant son merge sur develop. Selon l'ordre de merge : soit ERP-49 est mergée d'abord (cette MR ne contiendra plus que le commit ERP-50 après rebase auto), soit cette MR embarque tout l'historique catalog. Reviewed-on: #25 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr> |
||
|
|
e0d59962d6 |
chore: bump version to v0.1.50
|
||
|
|
3ce40a707f |
[ERP-49] Créer la page Gestion des catégories (datatable + drawer) (#22)
Auto Tag Develop / tag (push) Successful in 7s
## Contexte Ticket Lesstime : [#49](https://lesstime.malio.fr/tasks/460) — premier ticket front du M0 (Gestion des catégories). Suit la chaîne back ERP-43..48 mergée sur develop. ## Contenu first draft (Claude Code) - Page Nuxt `/admin/categories` (`MalioDataTable` + bouton `+ Ajouter`) - Composant `<CategoryDrawer>` : modes création / consultation / édition, transition auto view → edit à la première modification, validation client miroir RG-1.02 (name requis) / RG-1.04 (longueur 2-120) / RG-1.05 (type requis), mapping erreurs 409 (doublon) et 422 (violations) - Composant `<CategoryDeleteModal>` : confirmation suppression (soft delete RG-1.12) - Types TS `Category`, `CategoryType`, `User` - i18n `admin.categories.*` ajouté dans `fr.json` - Fix latent en passant : ajout de `'categories'` à `AdminLinkSlug` du Page Object e2e (oublié lors d'ERP-47 quand l'item sidebar a été ajouté) ## Décisions marquantes - Logique `fetch` inline dans `categories.vue` (sera extraite en composables `useCategoriesAdmin` + `useCategoryForm` au ticket ERP-50 / 0.8) - Drawer dans composant séparé pour réutilisabilité - Aucun état de tableau persisté dans l'URL (règle ABSOLUE n°6) - Tous les composants formulaires sont `Malio*` (`MalioDataTable`, `MalioInputText`, `MalioSelect`, `MalioButton`, `MalioDrawer`) ## Polish à venir (Tristan) Tristan testera en navigateur et peaufinera : UX, classes Tailwind, animations, icônes, wording de toasts. Les commits de polish suivront sur la même branche. ## Tests - `npx nuxi typecheck` : net 0 nouvelle erreur (mêmes erreurs pré-existantes que sur `develop`, infrastructure auto-import) + 1 latente corrigée (AdminLinkSlug) - `make nuxt-test` : 43/43 passent (0 régression) - Tests manuels navigateur : voir cahier de test du ticket Lesstime #49 ## Note pre-commit hook Le hook a remonté un échec PHPUnit pré-existant sur `develop` (`CategoryDeleteTest::testPatchOnSoftDeletedReturns404` → 401 au lieu de 404, JWT non initialisé en test runner). Aucun PHP touché dans cette MR. Commit avec `--no-verify` autorisé par Tristan. ## Reviewer suggéré Matthieu (back ↔ front + permissions). --------- Co-authored-by: Matthieu <mtholot19@gmail.com> Reviewed-on: #22 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr> |
||
|
|
9613857650 |
chore: bump version to v0.1.49
|
||
|
|
2a0918bbfe |
[#ERP-42] Mettre à jour la lib Malio UI (#16)
Auto Tag Develop / tag (push) Successful in 9s
| Numéro du ticket | Titre du ticket | |------------------|-----------------| | | | ## Description de la PR ## Modification du .env ## Check list - [x] Pas de régression - [x] TU/TI/TF rédigée - [x] TU/TI/TF OK - [ ] CHANGELOG modifié Reviewed-on: #16 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr> |
||
|
|
8e31e1759c |
chore: bump version to v0.1.48
|
||
|
|
4824690923 |
[ERP-48] Écrire les tests PHPUnit RG-1.01 à RG-1.17 (#20)
Auto Tag Develop / tag (push) Successful in 9s
## Mode stacked PR — DERNIER ticket back du M0
**Cible : `feature/ERP-47-declarer-module-catalog-rbac`** (PAS develop).
Quand la MR ERP-47 sera mergée sur develop, repointer la cible de cette MR vers develop.
## Résumé
Suite PHPUnit complète qui mappe chaque RG (1.01 → 1.17) de la spec M0 Catalog vers un ou plusieurs tests ciblés. **63 nouveaux tests** dans 9 classes sous `tests/Module/Catalog/Api/`.
## Cahier de test
| RG | Test(s) |
|---|---|
| **RG-1.01** | `CategoryPermissionsTest::testPersonaWithoutCatalogPermissionGets403*` (4 personas × 4 verbes) + `testAnonymousGets401*` + `testAdminGets{200,201,204}*` + `testUserWithViewPermissionGets200*` |
| **RG-1.02** | `CategoryValidationTest::testNameRequiredReturns422` + `testNameEmptyStringReturns422` + `testNameWhitespaceOnlyReturns422` |
| **RG-1.03** | `CategoryValidationTest::testNameIsTrimmedOnCreate` |
| **RG-1.04** | `CategoryValidationTest::testNameTooShortReturns422` + `testNameTooLongReturns422` + `testNameAtMaxLengthIs201` |
| **RG-1.05** | `CategoryValidationTest::testCategoryTypeRequiredReturns422` + `testCategoryTypeNullIsRejected` |
| **RG-1.06** | `CategoryValidationTest::testCategoryTypeMustExistReturns4xx` |
| **RG-1.07** | `CategoryUniqueTest::testDuplicateNameSameTypeReturns409` + `testDuplicateNameCaseInsensitiveReturns409` + `testSameNameDifferentTypeAllowed` + `testRecreateAfterSoftDeleteAllowed` |
| **RG-1.08** | `CategoryListTest::testListExcludesSoftDeletedByDefault` |
| **RG-1.09** | `CategoryListTest::testIncludeDeletedFlagSurfacesSoftDeleted` |
| **RG-1.10** | `CategoryListTest::testDefaultSortIsNameAsc` |
| **RG-1.11** | `CategoryGetTest::testGetSoftDeletedReturns404` + `testGetSoftDeletedWithFlagReturns200` + `testGetNonExistentReturns404` + `testGetActiveCategoryReturns200` |
| **RG-1.12** | `CategoryDeleteTest::testDeleteReturns204AndPersistsSoftDelete` |
| **RG-1.13** | `CategoryDeleteTest::testPatchCannotSetDeletedAt` |
| **RG-1.11 étendue (404 sur soft-deleted)** | `CategoryDeleteTest::testPatchOnSoftDeletedReturns404` + `testDeleteOnSoftDeletedReturns404` |
| **Audit** | `CategoryAuditTest::testAuditLogOnCreate` + `testAuditLogOnUpdate` + `testAuditLogOnSoftDelete` + `testAuditLogPerformerCarriesAuthenticatedUsername` |
| **RG-1.15** | `CategoryTimestampableBlamableTest::testCreatedByAdminOnPost` + `testCreatedByNullInConsoleContext` |
| **RG-1.16** | `CategoryTimestampableBlamableTest::testPatchUpdatesUpdatedFieldsOnly` + `testSoftDeleteAlsoUpdatesUpdatedFields` |
| **RG-1.17** | `EntitiesAreTimestampableBlamableTest::testAllBusinessEntitiesImplementBothInterfaces` (déjà livré ERP-52, reste vert avec `Category` détectée Timestampable/Blamable et `CategoryType` whitelistée) |
## Side fixes révélés par la suite
### 1. `Category.php` — `normalizer: 'trim'` sur Assert\NotBlank + Length
Avant le fix, POST `{name: " "}` retournait **201** au lieu de **422** : le Processor trim après validation, mais NotBlank ne fait pas de trim natif. La RG-1.02 (whitespace-only → 422) combinée à la RG-1.03 (trim serveur) exige le `normalizer: 'trim'`. 1 ligne, aligne le contrat sans réordonnancer Validate/Process.
### 2. `makefile` — recréer l'index partiel `uq_category_name_type_active` après `schema:update`
`doctrine:schema:update --env=test --force` drop systématiquement l'index partiel `uq_category_name_type_active` (l'ORM ne sait pas exprimer un index fonctionnel + partiel via attribut Doctrine, donc le voit comme orphelin). Conséquence : POST doublon `(name, type)` retournait **201** au lieu de **409** (la `UniqueConstraintViolation` ne se déclenche plus). Fix : `dbal:run-sql "CREATE UNIQUE INDEX IF NOT EXISTS ..."` ajouté en fin de `test-db-setup`. Approche chirurgicale validée avec Matthieu, ne touche pas à `fake_site_aware_entity` (dépend de schema:update pour exister avant le purger fixtures:load).
## Helpers livrés
`tests/Module/Catalog/Api/AbstractCatalogApiTestCase.php` :
- Factories : `createCategory()`, `createCategoryType()`
- Auth : `createAdminClient()`, `createManageClient()`, `createViewClient()`, `createPersonaClient(string \$label)` (4 personas MALIO sans permission catalog)
- Cleanup : purge complète Category + CategoryType (aucune fixture au M0) + users/roles `test_*`
## Vérifications
- ✅ `make php-cs-fixer-allow-risky` (auto-applied via pre-commit)
- ✅ `make db-reset` (index partiel restauré, vérifié `\d category`)
- ✅ `make test` → **311 tests, 1071 assertions, 0 failure, 0 risky**
(248 existants + 63 nouveaux, dont 6 deprecations + 6 notices héritées des tests Core RBAC pré-existants — pas de régression introduite par ce ticket)
## Suite
DERNIER ticket back du M0. ERP-52, ERP-43, ERP-44, ERP-45, ERP-46, ERP-47, ERP-48 sont tous en review.
Quand la MR ERP-47 sera mergée sur develop, Matthieu repointera la cible de cette MR vers develop. Tristan reviewe la stack en série.
---------
Co-authored-by: Matthieu <mtholot19@gmail.com>
Reviewed-on: #20
Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
|
||
|
|
fceb1e0e83 |
[ERP-47] Déclarer le module Catalog et synchroniser RBAC (#19)
Auto Tag Develop / tag (push) Successful in 10s
## Contexte Ticket Lesstime #47 — M0 position 0.5. Wire le nouveau module **Catalog** dans Starseed et synchronise les 3 sources RBAC (sidebar + personas E2E + seed back). Couvre **RG-1.01** (Admin uniquement) côté infra. Spec : [`docs/specs/M0-categories/spec-back.md` § 5.1 + § 5.3](https://gitea.malio.fr/MALIO-DEV/Starseed/src/branch/feature/M0-spec-categories/docs/specs/M0-categories/spec-back.md). > ⚠ **Mode stacked PR** — cible `feature/ERP-46-exposer-category-type-lecture-seule`, **PAS** `develop`. Quand la MR ERP-46 sera mergée sur develop, repointer la cible de cette MR vers develop. ## Modifications (6 fichiers — règle ABSOLUE Starseed n°8 : les 3 sources RBAC bougent ENSEMBLE) | Fichier | Rôle | |---|---| | `src/Module/Catalog/CatalogModule.php` (nouveau) | Déclaration du module : `ID=catalog`, `LABEL=Catalogue`, `REQUIRED=true`, 2 permissions (`view` + `manage`) | | `config/modules.php` | Wire `CatalogModule::class` | | `config/sidebar.php` | Item « Gestion des catégories » dans section Administration, gate sur `catalog.categories.view` | | `frontend/i18n/locales/fr.json` | Clé `sidebar.catalog.categories` = `Gestion des catégories` | | `frontend/tests/e2e/_fixtures/personas.ts` | `user-full` reçoit les 2 permissions + `'categories'` dans `expectedAdminLinks`. `super-admin` et `ALL_ADMIN_LINKS` étendus avec `'categories'`. `user-readonly` inchangé (Admin-only au M0 — pas de mode read-only spec'é). | | `src/Module/Core/Infrastructure/Console/SeedE2ECommand.php` | Miroir back : `user-full` reçoit les 2 permissions | ## Décisions - **`REQUIRED = true`** : la spec § 5.1 + le prompt user disent `true` (Category sera FK NOT NULL côté futurs modules Tiers). Le ticket Lesstime dit `false` par erreur — j'ai suivi la spec. - **Personas E2E « Admin » = `user-full`** : pas de persona métier « Admin » explicite dans `personas.ts` (personas techniques : `super-admin` bypass, `user-full` = toutes permissions). `user-full` est l'équivalent fonctionnel. - **`user-readonly` NON touché** : RG-1.01 dit « Admin uniquement », pas de pattern read-only spec'é au M0. À rouvrir dans un futur ticket si besoin. ## Validation - `make php-cs-fixer-allow-risky` ✓ (0 fichier corrigé) - `make db-reset` ✓ (sync-permissions : 11 codes en base, dont les 2 nouveaux `catalog.categories.*` vérifiés via `dbal:run-sql`) - `make test` ✓ (248 tests, 0 régression) - **RG-1.01 vérifiée manuellement** via curl : - Admin → 200 sur `GET /api/categories` et `GET /api/category_types` - Bob (zéro permission) → 403 sur `GET /api/categories`, `POST /api/categories`, `GET /api/category_types` - Anonyme → 401 sur `GET /api/categories` --------- Co-authored-by: Matthieu <mtholot19@gmail.com> Reviewed-on: #19 Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> |
||
|
|
adda62c1e1 |
[ERP-46] Exposer le référentiel CategoryType en lecture seule (#18)
Auto Tag Develop / tag (push) Successful in 10s
## Contexte Ticket Lesstime #46 — position 0.4 (M0 Catalog, quick win). Expose `CategoryType` en lecture seule pour alimenter le `<MalioSelect>` du formulaire `Category` côté front. Pas d'écriture exposée au M0 (table vide à la livraison). ## Mode stacked PR ⚠ **Cible (base branch) : `feature/ERP-45-implementer-provider-processor-category`** (PAS develop). Quand MR ERP-45 sera mergée sur develop, repointer la cible de cette MR vers develop. ## Changement Le gros du travail (`#[ApiResource(operations: [GetCollection, Get])]`, security `is_granted('catalog.categories.view')`, groupes de sérialisation) a été livré dans le ticket ERP-44. Cette MR ajoute uniquement ce qui manquait à la spec § 4.6 : - `order: ['label' => 'ASC']` sur l'opération `GetCollection` → tri alphabétique stable pour le select front. ## Critères d'acceptation (spec § 4.6) - [x] `GET /api/category_types` retourne tous les `CategoryType` triés par `label ASC` - [x] `GET /api/category_types/{id}` retourne le détail - [x] POST / PATCH / DELETE → 404 (opérations non déclarées) - [x] Security `is_granted('catalog.categories.view')` sur les 2 opérations - [x] `make php-cs-fixer-allow-risky` passe (0 fix) ## Vérifications \`\`\` $ php bin/console debug:router | grep category_type _api_/category_types{._format}_get_collection GET /api/category_types.{_format} _api_/category_types/{id}{._format}_get GET /api/category_types/{id}.{_format} \`\`\` → Exactement 2 routes générées, aucune POST/PATCH/DELETE. - \`make php-cs-fixer-allow-risky\` ✓ (0 fix) - \`make test\` ✓ (248/248) --------- Co-authored-by: Matthieu <mtholot19@gmail.com> Reviewed-on: #18 Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> |
||
|
|
80fabcae91 |
[ERP-45] Implémenter Provider et Processor Category (#17)
Auto Tag Develop / tag (push) Successful in 7s
## Mode stacked PR — cible `feature/ERP-44-creer-entites-category` > ⚠ Cette MR a pour base la branche ERP-44 (en review). Quand ERP-44 sera mergée sur develop, **repointer la cible vers develop**. ## Résumé - Provider `CategoryProvider` : filtre soft-delete par défaut (RG-1.08), `?includeDeleted=true` (RG-1.09), tri name ASC (RG-1.10), 404 si soft-deleted hors flag (RG-1.11). - Processor `CategoryProcessor` : trim du `name` (RG-1.03), conversion DELETE → UPDATE (RG-1.12), mapping `UniqueConstraintViolationException` → HTTP 409 avec message exact (RG-1.07). - Câblage Provider/Processor dans `#[ApiResource]` de `Category`. Provider câblé aussi sur Patch + Delete (au-delà du scope strict du ticket) pour fermer la fuite RG-1.11 sur PATCH. - `DoctrineCategoryRepository` expose `createListQueryBuilder($includeDeleted)`. ## Décisions notables - **Filtre soft-delete via QueryBuilder** (choix `a` du ticket) : pas de filtre Doctrine global, lisibilité directe. - **Pas de `remove_processor` injecté** : la DELETE est convertie en UPDATE via le `persist_processor`. API Platform 4 utilise le processor déclaré sur l'opération sans fallback automatique. - **Provider sur Patch + Delete aussi** : décision prise pendant le dev pour fermer une fuite RG-1.11 sur PATCH. Coût : 2 lignes dans `Category.php`. ## Tests - `make php-cs-fixer-allow-risky` ✓ - `make test` ✓ (248 tests, 0 régression — pas de test métier Category, c'est ERP-48) - Tests manuels curl ✓ — 8 cas RG-1.03 → RG-1.13 validés (détail dans le ticket Lesstime #45) ## Tickets - Lesstime : #45 (ERP-45) → En review - Position M0 : 0.3 - Spec : `docs/specs/M0-categories/spec-back.md` § 4.1 + § 4.3 + § 4.4 + § 4.5 ## Suite - ERP-46 (0.4 CategoryType lecture seule) — base : cette branche --------- Co-authored-by: Matthieu <mtholot19@gmail.com> Reviewed-on: #17 Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> |
||
|
|
ff6086bc4d |
[ERP-44] Créer les entités Category et CategoryType (#15)
Auto Tag Develop / tag (push) Successful in 7s
## Objectif Couche Domain DDD du module Catalog (ticket M0 · position 0.2). Crée les entités `Category` et `CategoryType`, leurs repositories, et branche le pattern Timestampable + Blamable Shared. > **Mode stacked PR** : cible `feature/ERP-43-migrer-tables-category`. Quand la MR ERP-43 sera mergée sur develop, Matthieu repointera la cible de cette MR vers develop. ## Contenu - **`Category`** : `#[ApiResource]` (GetCollection, Get, Post, Patch, Delete), `#[Auditable]`, `TimestampableBlamableTrait` + interfaces, asserts (`NotBlank`/`Length` sur `name`, `NotNull` sur `categoryType`), soft delete via `deletedAt`. Provider/Processor branchés au ticket 0.3 (ERP-45). - **`CategoryType`** : référentiel statique en lecture seule (GetCollection + Get), embarqué dans `Category` via le groupe `category:read`. Pas de Trait — whitelisté dans `EntitiesAreTimestampableBlamableTest::EXCLUDED` (RG-1.17). - **Repositories** : interfaces Domain + implémentations Doctrine. - **`config/packages/doctrine.yaml`** : mapping ORM `Catalog` inconditionnel (miroir de `Sites`) — nécessaire pour que l'ORM reconnaisse les entités. La déclaration du module (`config/modules.php`) reste pour le ticket 0.5 (ERP-47). - Groupes : `category:read` / `category:write` + `default:read` (expose les 4 colonnes du Trait). ## Notes techniques - Index nommés déclarés sur les entités pour matcher la migration (cf. Role/Permission/Site). - L'index unique partiel `uq_category_name_type_active` (`LOWER(name), category_type_id WHERE deleted_at IS NULL`) reste possédé par la seule migration : Doctrine ORM ne sait pas exprimer un index fonctionnel + partiel. Seul diff résiduel de `doctrine:schema:validate`. ## Tests - `make php-cs-fixer-allow-risky` ✓ - `make test` ✓ (248 tests, 0 échec) - `make db-reset` ✓ - `debug:router` ✓ (7 routes exposées) - `doctrine:schema:validate` : mapping correct --------- Co-authored-by: Matthieu <mtholot19@gmail.com> Reviewed-on: #15 Reviewed-by: Autin <tristan@yuno.malio.fr> Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> |
||
|
|
d01bbfbc65 |
chore: bump version to v0.1.43
|
||
|
|
92a6343b66 |
[ERP-43] Migrer les tables Category et CategoryType (#14)
Auto Tag Develop / tag (push) Successful in 8s
## Ticket - Lesstime : [#43](https://gitea.malio.fr) — Migrer les tables Category et CategoryType (M0 Catalog, position 0.1) ## Contenu Migration Doctrine `migrations/Version20260527164000.php` (namespace racine `DoctrineMigrations`, règle ABSOLUE Starseed n°11) : - Table `category_type` : `id INT IDENTITY`, `code VARCHAR(40)` (UNIQUE), `label VARCHAR(120)` - Table `category` : `id`, `name`, `category_type_id` (FK RESTRICT), `deleted_at` (soft delete), + 4 colonnes Timestampable/Blamable (`created_at`/`updated_at` NOT NULL, `created_by`/`updated_by` nullable FK `"user"` ON DELETE SET NULL) - Index unique partiel `uq_category_name_type_active` sur `(LOWER(name), category_type_id) WHERE deleted_at IS NULL` → matérialise **RG-1.07** - Index `idx_category_deleted_at`, `idx_category_type_id`, `idx_category_created_by`, `idx_category_updated_by` ## Tests - `make php-cs-fixer-allow-risky` ✓ - `make db-reset` ✓ (migration exécutée sans erreur) - `make test` ✓ — 248 tests / 858 assertions, 0 échec - Vérification psql `\d category` ✓ (index partiel + 8 colonnes + 3 FK avec les bons ON DELETE) ## ⚠ Mode stacked PR Cette MR cible `feature/ERP-52-creer-pattern-timestampable-blamable-shared` au lieu de `develop`. Quand la MR #13 (ERP-52) sera mergée sur develop, Matthieu repointera la cible de cette MR vers develop. Reviewer suggéré : Tristan --------- Co-authored-by: Matthieu <mtholot19@gmail.com> Reviewed-on: #14 Reviewed-by: Autin <tristan@yuno.malio.fr> Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> |
||
|
|
02df221a0b |
chore: bump version to v0.1.42
|
||
|
|
6efe7aa8ea |
[ERP-52] Créer le pattern Timestampable + Blamable Shared (#13)
Auto Tag Develop / tag (push) Successful in 9s
## Contexte Ticket Lesstime : [#52](https://project.malio-dev.fr/projects/6/tasks/463) Position dans le groupe M0 : 0.0 (prérequis transverse) ## Implémentation - 2 interfaces (`TimestampableInterface`, `BlamableInterface`) dans `Shared/Domain/Contract/` - 1 trait (`TimestampableBlamableTrait`) dans `Shared/Domain/Trait/` - 1 Subscriber Doctrine (`TimestampableBlamableSubscriber`) dans `Shared/Infrastructure/Doctrine/` - 1 ligne `resolve_target_entities` ajoutée à `config/packages/doctrine.yaml` (`UserInterface` → `User`) - 1 test architecture (`EntitiesAreTimestampableBlamableTest`) garde-fou L3 de la spec § 2.8.bis - 1 test unitaire (`TimestampableBlamableSubscriberTest`) 4 cas ## Décision EXCLUDED (cf. réponse review) Les 4 entités préexistantes (`User`, `Role`, `Permission`, `Site`) sont **whitelistées** dans `EXCLUDED` avec justification par entrée, plutôt que rétrofitées dans ce ticket. Le rétrofit de `User` et `Site` est documenté en **HP-9 / HP-10** (récursion Blamable + migration → décision archi scopée). Doc mise à jour : spec § 2.8.bis, § 9, et `.claude/rules/backend.md`. ## Tests - PHPUnit : 5 nouveaux tests, 0 échec, 0 risky (248 tests / 874 assertions au total) - php-cs-fixer : OK ## Reviewer suggéré - Tristan --------- Co-authored-by: Matthieu <mtholot19@gmail.com> Reviewed-on: #13 Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> |
||
|
|
6c27ac8640 |
chore: bump version to v0.1.41
|
||
|
|
2ef344e22f |
ci : speed up PR workflow (nuxt build cache + remove broken runner cache) (#21)
Auto Tag Develop / tag (push) Successful in 11s
## Contexte 2 fixes CI extraits de la MR #13 (ERP-52) pour propreté. Ces commits sont indépendants du pattern Shared. ## Contenu - |
||
|
|
43d80df1e1 |
chore: bump version to v0.1.40
|
||
|
|
5db644d22e |
docs(catalog) : M0 categories specs (back + front) (#12)
Auto Tag Develop / tag (push) Successful in 10s
## Contexte Premier passage du workflow MALIO sur un module concret. Cette MR introduit **uniquement la documentation** (2 specs Markdown) du **Module 0 — Gestion des catégories**. Aucun code applicatif n'est touché. La spec back a été cadrée sur l'archi DDD réelle de Starseed (cf. `.claude/rules/architecture.md` + `backend.md`) après audit du repo (modules `Core`, `Commercial`, `Sites`). Elle introduit aussi un **nouveau module `Catalog`** (bounded context "référentiels partagés") — non créé dans cette MR, il viendra avec les tickets de dev. ## Contenu | Fichier | Lignes | Objet | |---|---|---| | `docs/specs/M0-categories/spec-back.md` | 700 | Spec back v1.1 : modèle data, API REST (5 endpoints + CategoryType lecture seule), 13 RG (RG-1.01 → RG-1.13), validation, autorisation, audit, tests, hors-périmètre | | `docs/specs/M0-categories/spec-front.md` | 113 | Spec front V0 client (validée 2026-05-22) : UI admin (datatable + drawer), 2 champs (Nom + Type), 3 actions (Ajouter / Consulter / Modifier), permissions par rôle | ## Décisions d'archi (auto-validation back-only) Toutes les décisions sont documentées dans `spec-back.md § 2` : - **Module `Catalog`** créé séparément de `Commercial` pour rester réutilisable par les futurs modules Tiers (M-Clients, M-Fournisseurs, M-Prestas) - **IDs INT IDENTITY** (cohérent avec `User`, `Role`, etc.) - **Soft delete** via `deleted_at TIMESTAMP(0) WITHOUT TIME ZONE NULL` — *pattern introduit par ce module* (aucune autre entité Starseed ne le portait) - **Index unique partiel Postgres** sur `(LOWER(name), category_type_id) WHERE deleted_at IS NULL` → unicité case-insensitive parmi non soft-deleted, recréation possible après suppression logique - **Granularité permissions = `view` + `manage`** (aligné sur `core.users.view` + `core.users.manage`) - **Référentiel `CategoryType`** = entité séparée, table vide à la livraison, valeurs seedées plus tard (HP-1) ## Règles métier (RG-1.01 → RG-1.13) Chaque RG est numérotée, stable, testable, et constituera un critère d'acceptation côté ticket Lesstime (cf. `spec-back.md § 7`). Couverture par catégorie : - Autorisation : RG-1.01 (Admin only) - Champ `name` : RG-1.02 (obligatoire), RG-1.03 (trim), RG-1.04 (longueur 2-120) - Champ `categoryType` : RG-1.05 (obligatoire), RG-1.06 (référence valide) - Unicité : RG-1.07 (case-insensitive sur couple, hors soft-deleted) - Liste : RG-1.08 (exclut soft-deleted), RG-1.09 (flag `?includeDeleted=true`), RG-1.10 (tri `name ASC`) - Détail : RG-1.11 (404 si soft-deleted) - Suppression : RG-1.12 (soft delete), RG-1.13 (`deletedAt` non modifiable via PATCH) ## Découpe en tickets Lesstime TaskGroup `#22 — M0 — Gestion des catégories` créé sur le projet **STARSEED**. 9 tickets en backlog : | # | Ticket Lesstime | Effort | Tag | |---|---|---|---| | 0.1 | `#43` Migrer les tables Category et CategoryType | S | Backend | | 0.2 | `#44` Créer les entités Category et CategoryType | M | Backend | | 0.3 | `#45` Implémenter Provider et Processor Category | M | Backend | | 0.4 | `#46` Exposer le référentiel CategoryType en lecture seule | S | Backend | | 0.5 | `#47` Déclarer le module Catalog et synchroniser RBAC | S | Backend | | 0.6 | `#48` Écrire les tests PHPUnit RG-1.01 à RG-1.13 | M | Backend | | 0.7 | `#49` Créer la page Gestion des catégories (datatable + drawer) | L | Frontend | | 0.8 | `#50` Implémenter les composables useCategoriesAdmin et useCategoryForm | M | Frontend | | 0.9 | `#51` Écrire les tests Vitest des composables Catalog | S | Frontend | **Total estimé** : ~15-25h (9 mini-MR de 1-4h). ## Hors-périmètre (HP) Pas codés / pas inclus dans cette spec (cf. `spec-back.md § 9`) : - HP-1 : CRUD du référentiel `CategoryType` (spec dédiée à venir) - HP-2 : Référencement par les Tiers (les FK `category_id` sur Clients/Fournisseurs/Prestas viendront avec leurs modules) - HP-3 : Restauration d'une catégorie soft-deleted - HP-4 : Hard delete - HP-5 : i18n du `name` - HP-6 : Recherche serveur / filtres avancés - HP-7 : Catégories hiérarchiques (parent / enfant) - HP-8 : Seed des rôles métier Bureau / Compta / Commerciale / Usine ## Checklist review Pas de code → review légère, lecture des 2 `.md` suffit. - [ ] Frontmatter YAML cohérent (module, version, dates, validation client, taskgroup, tags) - [ ] Décisions d'archi argumentées (`spec-back.md § 2`) - [ ] Modèle data réaliste (SQL Postgres rédigé directement, pas de pseudo-code) - [ ] API REST complète (codes HTTP succès + erreurs, payloads, exemples) - [ ] RG numérotées et testables (un humain peut écrire un test PHPUnit à partir de chaque RG sans réinventer) - [ ] Mapping rôles MALIO ↔ permissions RBAC clair (cohérent avec règle ABSOLUE n°8 — 3 sources à toucher) - [ ] Hors-périmètre explicite ## Stratégie de merge **Squash merge** vers `develop` (1 PR = 1 commit propre dans l'historique). ## Lien Lesstime - TaskGroup : `#22 — M0 — Gestion des catégories` (projet ERP / Starseed) - Tickets en backlog : `#43` → `#51` > ⚠️ **À faire manuellement après merge** dans l'UI Lesstime : rattacher les 9 tickets au groupe #22 et leur poser leur effort + tag + priorité (bug typing MCP empêche le wire automatique sur des champs `integer` sans `type` explicite dans le schéma). --------- Co-authored-by: Matthieu Tholot <mtholot19@gmail.com> Reviewed-on: #12 Reviewed-by: Autin <tristan@yuno.malio.fr> Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr> |
||
|
|
33599db5a3 |
chore: bump version to v0.1.39
|
||
|
|
34e75a35fb |
ci : add pull_request quality gate workflow (#11)
Auto Tag Develop / tag (push) Has been cancelled
|
||
|
|
1696602abb |
chore: bump version to v0.1.38
|
||
|
|
cacd8718e5 |
chore(prod) : ajuster conf prod pour HTTP en reseau local
Auto Tag Develop / tag (push) Has been cancelled
- .env.prod.example : JWT_COOKIE_SECURE=0, CORS_ALLOW_ORIGIN en http - prompt-rename-prod.md : retirer etape certbot/Let's Encrypt, verifier la resolution locale a la place - deployment-docker.md : aligner DEFAULT_URI, CORS et JWT_COOKIE_SECURE sur HTTP |
||
|
|
f7a50168d5 |
chore: bump version to v0.1.37
|
||
|
|
93cbd48bf5 |
chore : rename Coltura to Starseed
Auto Tag Develop / tag (push) Has been cancelled
- Rename project name across code, configs, docs, dev/prod infra - Dev: DOCKER_APP_NAME + POSTGRES_DB switched to starseed, containers become php-starseed-fpm / nginx-starseed / starseed-db-1 - Dev: mount nginx.conf on default.conf instead of starseed.conf to avoid alphabetical-order clash with image's default site - Makefile: export CURRENT_UID/CURRENT_GID at top level so docker compose builds (db-reset etc.) get them - Prod: image registry path, container_name, volumes, vhost server_name + paths, DATABASE_URL, CORS, CI workflow - Add doc/prompt-rename-prod.md with the migration runbook for the prod server (DB rename, FS move, vhost, Let's Encrypt) |
||
|
|
cd17248427 |
chore: bump version to v0.1.36
|
||
|
|
6bd7f3b059 |
fix : package-lock.json
Auto Tag Develop / tag (push) Has been cancelled
|
||
|
|
b1ea732155 |
chore: bump version to v0.1.35
|
||
|
|
99e96cb493 |
[#ERP-41] Mise à jour Malio UI (#10)
Auto Tag Develop / tag (push) Has been cancelled
| Numéro du ticket | Titre du ticket | |------------------|-----------------| | | | ## Description de la PR ## Modification du .env ## Check list - [ ] Pas de régression - [x] TU/TI/TF rédigée - [x] TU/TI/TF OK - [ ] CHANGELOG modifié Reviewed-on: MALIO-DEV/Coltura#10 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr> |
||
|
|
e6c8381b3c |
feat : audit log (table + writer + listener + API + admin UI + timeline) (#9)
## Résumé
Implémente le journal d'audit append-only couvrant les 5 tickets de `doc/audit-log.md` et embarque au passage plusieurs corrections périphériques (sidebar Admin/Mon compte, drawer RBAC, Swagger, schema_filter Doctrine) ainsi que l'initialisation de la suite e2e Playwright. Toutes les mutations Doctrine sur les entités portant `#[Auditable]` sont tracées dans une table PostgreSQL dédiée, exposée en lecture seule via API Platform et consultable par les admins dans une page dédiée.
## Ce qui change
### Audit log — cœur de la PR
**Backend**
- Migration : table `audit_log` (UUID v7 natif Postgres en PK, `jsonb changes`, 3 index pour tri chrono, par entité et par utilisateur).
- `AuditLogWriter` : service bas-niveau, écrit via une connexion DBAL dédiée `audit` (même DSN que `default`, service séparé) pour sortir de la transaction ORM en batch. Blacklist defense-in-depth `password`/`plainPassword`/`token`/`secret`.
- `RequestIdProvider` : UUID v4 généré au `kernel.request` principal, injecté dans chaque ligne d'audit de la requête.
- Attributs `#[Auditable]` / `#[AuditIgnore]` dans `src/Shared/Domain/Attribute/` (accessibles par tous les modules).
- `AuditListener` : capture `onFlush` / écriture `postFlush` avec pattern swap-and-clear contre les flushes ré-entrants. Erreurs loguées, jamais propagées. Entité `User` annotée (password / plainPassword ignorés).
- API Platform read-only `/api/audit-logs` (permission RBAC `core.audit_log.view`) : `GET` collection paginée + `GET` item, pas de POST/PUT/PATCH/DELETE. Filtres `entity_type`, `entity_id`, `action`, `performed_by`, `performed_at[after]`/`[before]`.
- `DbalPaginator` implémentant `PaginatorInterface` : `hydra:view` généré automatiquement par API Platform, pas de construction manuelle.
- Ressource `AuditLogEntityTypesResource` + provider dédié pour peupler le filtre par type d'entité côté UI (réponse cachée, pas de requête à chaque ouverture du drawer).
- Permission `core.audit_log.view` déclarée dans `CoreModule::permissions()`.
- `audit_log` exclu du `schema_filter` Doctrine : plus de faux diff sur `make migration-diff`.
**Frontend**
- Page admin `/admin/audit-log` : tableau paginé, filtres locaux (état dans le composant, non persistés dans l'URL — conforme règle CLAUDE.md « Tableaux : pas de persistance URL »), drawer de détail (diff + timeline complète de l'entité), badges colorés par action.
- Composable partagé `useAuditLog` avec `resetAuditLog()` auto-enregistré sur `onAuthSessionCleared` (règle CLAUDE.md composables singletons).
- Composant réutilisable `<AuditTimeline :entity-type :entity-id>` : garde permission (pas d'appel API sans le droit), lazy loading (10 items + bouton « Voir plus »), dates relatives FR via `Intl.RelativeTimeFormat`, skeleton loader.
- Entrée sidebar « Journal d'audit » gated sur `core.audit_log.view` + clés i18n imbriquées dans `fr.json`.
### Fixes embarqués
- **Review fixes audit-log** (commits `37eafd2`, `1505e84`, `99c77eb`) : précision des timestamps, `ESCAPE` sur les `LIKE`, plafond pagination, diverses remarques du 1er tour de review.
- **Sidebar** (`701a480`, `e2fbf51`) : nouvelle section « Administration » + groupe « Mon compte », gate de section sur permissions, « Tableau de bord » déplacé dans « Mon compte ». Convention admin documentée.
- **Drawer RBAC utilisateurs** (`617ee31`, `5f5afcc`) : corrige l'affichage des sites et l'écrasement via merge-patch (garde anti-écrasement + spec `GET /users/{id}/rbac` documentée).
- **Swagger UI** (`6db955f`) : réactivé en ajoutant `symfony/twig-bundle` aux deps (régression depuis l'arrivée d'API Platform 4.2).
- **`phpunit.dist.xml`** : `<env APP_ENV=dev>` forçait la suite à tourner sous `framework.test=false` (→ `test.service_container` introuvable) ; `JWT_PASSPHRASE` ne matchait pas les clés de dev. Corrigés pour débloquer la suite.
### E2E Playwright (nouveau, commit `4603ab2`)
- `playwright.config.ts` + structure `frontend/tests/e2e/` (personas, helpers `loginAs`, page objects `LoginPage` + `SidebarComponent`).
- Specs : `auth/login.spec.ts` + `permissions/sidebar-visibility.spec.ts` (vérifie la visibilité de la sidebar par rôle RBAC).
- Commande `SeedE2ECommand` pour préparer un jeu de données déterministe côté backend.
- `make e2e` ajouté au Makefile.
## Décisions techniques
- **UUID v7 natif Postgres** (16 octets vs 36 en varchar) : index `performed_at` ~40 % plus petit sur une table append-only à croissance infinie.
- **`entity_type` format `module.Entity`** (ex: `core.User`) : évite les collisions si deux modules ont des entités de même nom.
- **`performed_by` dénormalisé** (string, pas FK) : le nom persiste même après suppression de l'utilisateur.
- **Connexion DBAL dédiée `audit`** : évite l'entanglement transactionnel entre audit et ORM en batch.
- **`ManyToMany` non audité** : limitation connue (`getEntityChangeSet()` ne couvre pas les collections) ; extension future via `getScheduledCollectionUpdates()` si besoin.
- **Filtres locaux non persistés dans l'URL** : choix assumé (cf. CLAUDE.md) pour éviter le couplage table ↔ routeur.
## Test plan
- [x] `make test` : 218 tests passent (writer unitaires + listener intégration + API fonctionnels + UserRbacProcessor).
- [x] `npm run lint` + `npm run test` + `npm run build` (frontend).
- [x] Migration appliquée sur dev + test, `audit_log` ignoré par `schema_filter`.
- [x] Permissions synchronisées (`app:sync-permissions`).
- [x] Swagger `/api/docs` accessible de nouveau.
- [ ] Playwright : `make e2e` vert en local (login + sidebar-visibility).
- [ ] Vérifier en local : création/modif/suppression d'un user apparaît dans `/admin/audit-log`.
- [ ] Vérifier : user sans `core.audit_log.view` → 403 sur l'endpoint + item absent de la sidebar.
- [ ] Vérifier : expansion d'une ligne affiche la timeline de l'entité avec dates relatives FR.
- [ ] Vérifier : drawer RBAC utilisateur n'écrase plus la liste des sites au `PATCH`.
## Points d'attention pour le review
- `AuditListener` : pattern swap-and-clear sur `postFlush` — relire la gestion des flushes ré-entrants.
- `DbalPaginator` : vérifier que l'absence d'`Iterator` custom ne casse pas la normalisation API Platform sur collections vides.
- `UserRbacProcessor` : logique merge-patch + garde anti-écrasement des sites (régression corrigée dans `617ee31`).
- Playwright : nouvelle dépendance de dev, s'assurer que `make e2e` ne fait pas partie du pipeline CI par défaut (à brancher explicitement).
Co-authored-by: Matthieu <mtholot19@gmail.com>
Reviewed-on: MALIO-DEV/Coltura#9
Co-authored-by: matthieu <matthieu@yuno.malio.fr>
Co-committed-by: matthieu <matthieu@yuno.malio.fr>
v0.1.34
|
||
|
|
dce189d982 |
chore: bump version to v0.1.33
|
||
|
|
140dca9061 |
fix : resolve var/cache permission issue in Docker
Auto Tag Develop / tag (push) Has been cancelled
Create var/cache and var/log directories in Dockerfile and ensure correct ownership in Makefile before running composer install. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
93f47e9111 |
chore: bump version to v0.1.32
|
||
|
|
6cf5ef4cfc |
Module sites (#8)
Auto Tag Develop / tag (push) Successful in 6s
| Numéro du ticket | Titre du ticket | |------------------|-----------------| | | | ## Description de la PR ## Modification du .env ## Check list - [x] Pas de régression - [x] TU/TI/TF rédigée - [x] TU/TI/TF OK - [ ] CHANGELOG modifié Co-authored-by: Matthieu <mtholot19@gmail.com> Reviewed-on: MALIO-DEV/Coltura#8 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr> |
||
|
|
6b4868b261 |
chore: bump version to v0.1.31
|
||
|
|
e8c2789435 |
RBAC - Système complet de permissions (Backend + Frontend) (#7)
Auto Tag Develop / tag (push) Has been cancelled
## Résumé
Implémentation complète du système RBAC (Role-Based Access Control) pour Coltura.
### Backend
- Entités Permission et Role avec API Platform CRUD
- PermissionVoter : vérification des permissions effectives (rôles + directes), admin bypass
- Endpoints `PATCH /users/{id}/rbac` pour assigner rôles, permissions directes et isAdmin
- AdminHeadcountGuard : protection contre la suppression du dernier admin
- Commande `app:sync-permissions` pour synchroniser les permissions déclarées par les modules
- Filtrage sidebar par permission RBAC (`permission` key optionnelle dans sidebar.php)
- 115 tests PHPUnit (fonctionnels + unitaires)
### Frontend
- Composable `usePermissions()` avec `can()`, `canAny()`, `canAll()` et admin bypass
- Page `/admin/roles` : DataTable, création/édition via drawer, suppression avec confirmation
- Page `/admin/users` : DataTable, drawer RBAC avec rôles, permissions directes, résumé effectif
- PermissionGroup : checkboxes groupées par module avec "tout sélectionner"
- EffectivePermissions : résumé lecture seule avec badges source ("via Rôle X" / "Direct")
- Warning auto-édition, toggle isAdmin
- Tests Vitest pour usePermissions
### Permissions déclarées
- `core.users.view` — Voir les utilisateurs
- `core.users.manage` — Gérer les utilisateurs
- `core.roles.view` — Voir les rôles RBAC
- `core.roles.manage` — Gérer les rôles et permissions
- `GET /api/permissions` accessible à tout utilisateur authentifié (catalogue read-only)
## Tickets Lesstime
- ERP-23 (#343) — Entités Permission et Role
- ERP-24 (#344) — API CRUD Roles & Permissions
- ERP-25 (#345) — Voter Symfony + usePermissions
- ERP-26 (#346) — Interface Admin : Gestion des Rôles
- ERP-27 (#347) — Interface Admin : Permissions Utilisateur
## Test plan
- [ ] `make db-reset` puis vérifier les fixtures (admin/alice/bob, rôles système)
- [ ] Login admin : sidebar affiche Gestion des rôles + Utilisateurs
- [ ] Login alice : sidebar masque ces onglets (pas de permission)
- [ ] Page /admin/roles : CRUD rôles, permissions groupées, protection rôles système
- [ ] Page /admin/users : assignation rôles + permissions directes, résumé effectif
- [ ] Warning auto-édition quand admin modifie ses propres droits
- [ ] `make test` : 115 tests PHPUnit passent
- [ ] `cd frontend && npm run test` : tests Vitest passent
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Matthieu <mtholot19@gmail.com>
Co-authored-by: tristan <tristan@yuno.malio.fr>
Reviewed-on: MALIO-DEV/Coltura#7
Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
Co-committed-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
|
||
|
|
b59d0f8a44 |
chore: bump version to v0.1.29
|
||
|
|
5cb8cff4ce |
Merge branch 'feature/ERP-7-mise-en-place-du-modular-monolith' into develop
Auto Tag Develop / tag (push) Has been cancelled
# Conflicts: # docker-compose.yml |