Files
Lesstime/docs/superpowers/specs/2026-06-19-migration-modular-monolith-roadmap.md
T
Matthieu a510b2ca73 docs : add modular monolith migration roadmap and socle design
Plan de migration complet Lesstime vers modular monolith DDD (archi Starseed) : roadmap en 14 tickets ordonnés par dépendances + design technique détaillé du socle (Shared/, contrats, endpoints modules/sidebar, plan strangler).
2026-06-19 10:50:14 +02:00

8.8 KiB

Roadmap — Migration Lesstime → modular monolith DDD (archi Starseed)

Plan de migration complet validé le 2026-06-19. Référence architecture : repo Starseed (.claude/rules/*.md + implémentation réelle). Détail technique du socle : voir 2026-06-19-lst-56-modular-monolith-design.md.

Principes directeurs

  • Strangler progressif : legacy (src/Entity/…) et modules (src/Module/…) coexistent ; l'app reste fonctionnelle et make test vert à chaque merge. Aucune migration destructive (prod Docker, BDD peuplée → migrations additives nullable uniquement).
  • DDD pragmatique (= Starseed réel) : ORM attrs dans l'entité Domain, Repository interface (Domain)
    • impl Doctrine (Infra), Provider/Processor API Platform, contrats Shared/Domain/Contract pour le cross-module. Pas de CQRS bus, pas de multi-tenant.
  • Tranches verticales : chaque module de Phase 2 est livré back + front (layer Malio) + MCP d'un coup → fonctionnel de bout en bout à son merge. L'ancienne idée d'un « ticket refonte front » global est dissoute : chaque module arrive déjà en Malio ; un ticket de finition harmonise à la fin.
  • Ordre par dépendances : socle → Core (identité/RBAC/audit) → modules métier → transverse/finition.
  • Zéro import inter-modules : interfaces Shared/Domain/Contract + resolve_target_entities, ou domain events / contrat NotifierInterface.

Garde-fous Starseed (appliqués à chaque entité migrée)

declare(strict_types=1) · TimestampableBlamableTrait (4 colonnes nullable) + subscriber · pagination obligatoire · COMMENT ON COLUMN (helper ColumnCommentsCatalog) · #[Auditable]/#[AuditIgnore] (dès que 1.3 est livré) · front Malio* + usePaginatedList + useFormErrors · RBAC module.resource.action (dès 1.2).


Phase 0 — Socle (fondations, ne touche aucun métier)

0.1 · Socle back — infrastructure modulaire (réécrit depuis #56)

Dépend de : — src/Shared/Domain/Contract/ (UserInterface, UserResolverInterface, ClientInterface, NotifierInterface), Shared/Domain/Event/DomainEventInterface, Shared/Domain/Trait/TimestampableBlamableTrait, Shared/Infrastructure/Doctrine/TimestampableBlamableSubscriber, Shared/Infrastructure/Database/ColumnCommentsCatalog, Shared/Infrastructure/ApiPlatform/{Resource,State} (ModulesResource/ModulesProvider, SidebarResource/SidebarProvider), config/modules.php, config/sidebar.php, /api/version aligné. Config additive : mapping Doctrine module prêt, migrations_paths modulaire, api_platform.mapping.paths. AC : /api/modules + /api/sidebar répondent ; app verte ; aucune migration destructive.

0.2 · Socle front — shell + auto-détection des layers

Dépend de : 0.1 frontend/app/ (shell layouts/default.vue), frontend/shared/ (useApi déplacé, useSidebar, useModules, stores), middlewares auth.global.ts + modules.global.ts, auto-détection des layers modules/*/ dans nuxt.config.ts. Aucune page métier déplacée (app encore plate). AC : sidebar dynamique depuis /api/sidebar ; routes désactivées redirigées ; app verte.


Phase 1 — Module Core (identité, sécurité, traçabilité — transverse)

1.1 · Core — Identité & Notifications

Dépend de : 0.1, 0.2 Migrer User + Auth/JWT dans src/Module/Core/ (Domain/Entity, Repository interface + Doctrine impl, MeProvider, password hasher), User implements UserInterface, resolve_target_entities → Core\User. Notification exposée via NotifierInterface. CoreModule.php (REQUIRED=true). Front : layer modules/core/ (login, profile, admin users). AC : login/JWT OK ; app verte ; aucun import direct App\Entity\User hors Core.

1.2 · RBAC fin (réécrit depuis #57)

Dépend de : 1.1 Role/Permission, permissions() par module, commande app:sync-permissions, PermissionVoter, SidebarProvider filtrant par permission (en plus du module actif), seed RBAC. Front : gestion des rôles + usePermissions. AC : permissions module.resource.action ; sidebar gated par permission.

1.3 · Audit log (réécrit depuis #61)

Dépend de : 1.1 #[Auditable]/#[AuditIgnore] (Shared/Domain/Attribute), table audit_log (migration additive + COMMENT ON COLUMN), AuditListener/AuditLogWriter/RequestIdProvider, AuditLogResource + /api/audit-logs paginé/filtrable, page front + labels i18n audit.entity.*. AC : CRUD des entités #[Auditable] tracé ; endpoint paginé ; aucune migration destructive.


Phase 2 — Modules métier (tranches verticales back + front + MCP, strangler)

2.1 · Module TimeTracking (premier module — rodage)

Dépend de : 1.1 Migrer TimeEntrysrc/Module/TimeTracking/ (Domain/Entity, repo, ActiveTimeEntryProvider, TimeEntryExportService/controller, MCP TimeEntry tools), front layer modules/time-tracking/ (time-tracking.vue, components, services, store timer). Timestampable additif. Rode toute la mécanique modulaire à risque quasi nul. AC : time tracking fonctionnel en module ; activation/désactivation testée ; app verte.

2.2 · Module ProjectManagement (cœur métier — réécrit depuis #56 pilote)

Dépend de : 2.1, 1.1 Project, Task, Workflow, TaskStatus, TaskGroup, TaskEffort, TaskPriority, TaskTag, TaskRecurrence, TaskDocumentsrc/Module/ProjectManagement/ (vertical back + MCP Task/Project/TaskMeta/Workflow + front layer modules/project-management/). User/Client via contrats (Client encore legacy jusqu'à 2.4). Notifications via NotifierInterface. #[ApiResource] conservés (étendre le scan). Timestampable additif. AC : cœur en module sans régression API ; app verte.

2.3 · Module Absence

Dépend de : 1.1 AbsenceRequest/AbsencePolicy/AbsenceBalance + services (AbsenceBalanceService, AbsenceDayCalculator, PublicHolidayProvider) + controllers (calendar, preview, justificatif) + MCP absence tools → src/Module/Absence/, front layer modules/absence/. AC : module absences complet ; app verte.

2.4 · Module Directory — Clients + Prospects (réécrit depuis #58)

Dépend de : 1.1 (et après 2.2 qui référence Client via contrat) Clientsrc/Module/Directory/ + nouvelle entité Prospect. L'impl de ClientInterface migre du legacy vers le module (resolve_target_entities mis à jour). Front répertoire (clients + prospects). AC : Clients + Prospects en module ; contrats à jour ; app verte.

2.5 · Module Mail

Dépend de : 1.1, 2.2 (TaskMailLink → Task) Mail* + TaskMailLink + MailSyncService + controllers + settings → src/Module/Mail/, front layer. Intègre le WIP feat/mail-integration. AC : mail en module ; app verte.

2.6 · Module Integration — Gitea / BookStack / Zimbra / Share

Dépend de : 1.1, 2.2 (liens Task) Configs + services API (GiteaApiService, BookStackApiService, CalDavService, Share) + controllers + liens → src/Module/Integration/, front (onglets admin + sections task). AC : intégrations en module ; app verte.


Phase 3 — Transverse & finition

3.1 · Module Reporting (réécrit depuis #59)

Dépend de : Phase 2 (consomme les modules) Reporting natif transverse (agrège time tracking, tâches, absences) via contrats / API. Module src/Module/Reporting/ + front. AC : rapports natifs ; aucune dépendance directe inter-modules.

3.2 · Module Portail client

Dépend de : 1.1, 2.2, 2.4 Portail client (accès restreint), module src/Module/ClientPortal/ + front layer + RBAC dédié. AC : portail fonctionnel ; gated RBAC.

3.3 · Finition Malio + nettoyage legacy (réécrit depuis #60)

Dépend de : tout Harmonisation visuelle Malio finale, vidage de src/Entity/ legacy résiduel, suppression du mapping Doctrine legacy + des pages plates frontend/pages/ résiduelles, durcissement resolve_target_entities. AC : src/Entity vide ; 100 % modulaire ; app verte ; aucune route/legacy orpheline.


Ordre d'exécution recommandé

0.1 → 0.2 → 1.1 → 1.2 → 1.3 → 2.1 → 2.2 → 2.3 → 2.4 → 2.5 → 2.6 → 3.1 → 3.2 → 3.3

Les tickets 1.2 et 1.3 peuvent se paralléliser après 1.1. Les modules 2.3 (Absence) et 2.4 (Directory) peuvent se paralléliser après 2.2. Mail (2.5) et Integration (2.6) suivent 2.2.

Mapping avec les tickets Lesstime existants

Ancien Devient
#56 (1/5 Aligner archi) 0.1 Socle back (le reste éclaté en 0.2 + 2.2)
#57 (2/5 RBAC) 1.2 RBAC fin
#58 (3/5 Répertoire) 2.4 Directory
#59 (4/5 Reporting) 3.1 Reporting
#60 (5/5 Front Malio) 3.3 Finition Malio + nettoyage (le front se fait par module)
#61 (Audit) 1.3 Audit log
(créés) 0.2, 1.1, 2.1, 2.2, 2.3, 2.5, 2.6, 3.2