- Task #6: WebSocket /ws/dashboard + Kafka events (5 topics) * Backend: KafkaEventProducer, KafkaEventConsumer * Mobile: WebSocketService (reconnection, heartbeat, typed events) * DashboardBloc: Auto-refresh depuis WebSocket events - Finance Workflow: approbations + budgets (backend + mobile) * Backend: entities, services, resources, migrations Flyway V6 * Mobile: features finance_workflow complète avec BLoC - Corrections DI: interfaces IRepository partout * IProfileRepository, IOrganizationRepository, IMembreRepository * GetIt configuré avec @injectable - Spec-Kit: constitution + templates mis à jour * .specify/memory/constitution.md enrichie * Templates agent, plan, spec, tasks, checklist - Nettoyage: fichiers temporaires supprimés Signed-off-by: lions dev Team
146 lines
9.0 KiB
Plaintext
146 lines
9.0 KiB
Plaintext
================================================================================
|
||
AUDIT INDÉPENDANT — CODE SOURCE UNIONFLOW
|
||
(Base strictement sur le code source ; aucun fichier .md lu)
|
||
================================================================================
|
||
|
||
1. STRUCTURE ET DÉPENDANCES
|
||
--------------------------------------------------------------------------------
|
||
• Trois modules Maven identifiés : unionflow-server-api, unionflow-server-impl-quarkus,
|
||
unionflow-client-quarkus-primefaces-freya. Pas de POM parent commun à la racine
|
||
unionflow/ ; parent déclaré via parent-pom.xml dans unionflow-server-api.
|
||
• API : Java 17, Lombok, Bean Validation, Jackson, MicroProfile OpenAPI, JUnit 5,
|
||
Mockito, AssertJ, Jacoco (seuils 1.00 sur lignes/instructions/méthodes/branches/classes).
|
||
• Impl : dépend de unionflow-server-api 1.0.0, lions-user-manager-server-api 1.0.0,
|
||
Quarkus 3.15.1, Hibernate Panache, Flyway, OIDC, MapStruct 1.6.3, POI, OpenPDF.
|
||
Jacoco : 1.00 lignes/instructions/méthodes, 0.30 branches. Checkstyle non exécuté
|
||
(executions commentées dans API).
|
||
• Client : dépend de unionflow-server-api 1.0.0, Quarkus PrimeFaces, OIDC, REST Client.
|
||
Pas de plugin Jacoco dans le client.
|
||
|
||
Risques : build multi-module non unifié (pas de reactor root) ; client sans couverture
|
||
automatique ; Checkstyle désactivé en API.
|
||
|
||
|
||
2. CONTRAT API / CLIENT – SERVEUR
|
||
--------------------------------------------------------------------------------
|
||
• Organisations : Le client (AssociationService) appelle GET /api/organisations?page=&size=
|
||
et attend PagedResponse<OrganisationResponse>. Le serveur (OrganisationResource)
|
||
renvoie PagedResponse<OrganisationSummaryResponse>. OrganisationSummaryResponse est un
|
||
record (id, nom, nomCourt, typeOrganisation, typeOrganisationLibelle, statut, …) ;
|
||
OrganisationResponse a plus de champs. Désérialisation possible mais type déclaré
|
||
incorrect et champs manquants côté client = risque PropertyNotFoundException ou
|
||
données incomplètes en vue.
|
||
• Membres : Client MembreService utilise GET /search et /search/advanced ; serveur expose
|
||
GET /recherche (param q), GET /recherche-avancee (déprécié), POST /search/advanced.
|
||
Incohérence de chemins pour recherche simple (client /search vs serveur /recherche).
|
||
• Types d’organisation : Client TypeOrganisationClientService appelle DELETE /{id}
|
||
(méthode disable()) ; serveur TypeOrganisationReferenceResource fait bien DELETE
|
||
(suppression réelle ou conditionnelle selon rôle). Alignement OK sur le chemin.
|
||
• DemandeAide : Client appelle GET /api/demandes-aide?page=&size= ; serveur renvoie
|
||
List<DemandeAideResponse> (pas PagedResponse). Pagination côté serveur faite manuellement
|
||
(subList). Contrat différent si le client attend un objet PagedResponse.
|
||
|
||
|
||
3. SÉCURITÉ (ANNOTATIONS)
|
||
--------------------------------------------------------------------------------
|
||
• HealthResource (/api/status) : aucune annotation @RolesAllowed ni @PermitAll.
|
||
Comportement dépend de la config globale (souvent ouvert pour health checks).
|
||
• DemandeAideResource, PropositionAideResource : aucune annotation @RolesAllowed sur
|
||
la ressource. Accès dépend de la politique par défaut (risque d’accès non restreint).
|
||
• RoleResource (/api/roles) : pas de @RolesAllowed.
|
||
• Incohérence des rôles : une partie des resources utilise des rôles en UPPER_CASE
|
||
(ADMIN, MEMBRE, SUPER_ADMIN, USER, SUPER_ADMINISTRATEUR, TRESORIER, etc.), d’autres
|
||
en lowercase (admin, admin_organisation, membre_actif, mutuelle_resp, vote_resp,
|
||
tontine_resp, ong_resp, coop_resp, culte_resp, registre_resp). AnalyticsResource
|
||
utilise MANAGER, MEMBER. Risque de refus ou d’accès inattendu selon le fournisseur
|
||
de rôles (Keycloak vs custom).
|
||
|
||
|
||
4. BASE DE DONNÉES ET MIGRATIONS
|
||
--------------------------------------------------------------------------------
|
||
• Migrations Flyway : V1__UnionFlow_Complete_Schema.sql, V2__Entity_Schema_Alignment.sql
|
||
(et README_CONSOLIDATION dans le même répertoire — non lu). Deux scripts principaux
|
||
uniquement = consolidation déjà faite. Les tests désactivent Flyway
|
||
(quarkus.flyway.enabled=false, migrate-at-start=false).
|
||
|
||
|
||
5. CLIENT JSF / PRIMEFACES
|
||
--------------------------------------------------------------------------------
|
||
• Convertisseur UUID : UuidConverter utilisé sur plusieurs pages (cotisations membre,
|
||
adhesion, organisation-form, membre-form, import/export membre, comptabilité,
|
||
documents). Un seul f:viewParam repéré avec converter="uuidConverter"
|
||
(membre/cotisations.xhtml, id → membreCotisationBean.membreId). Les autres liaisons
|
||
UUID sont surtout sur p:selectOneMenu. Toute vue qui lie une chaîne à un UUID sans
|
||
converter peut provoquer une ELException (conversion String → UUID).
|
||
• Gestion des erreurs : ViewExpiredExceptionHandler enveloppe l’exception handler JSF,
|
||
gère ViewExpiredException (redirection vers /, stockage redirectURL) et
|
||
PropertyNotFoundException (log WARNING, redirection vers liste organisations,
|
||
responseComplete). Typo dans le message de log : "already commited" (deux « m »).
|
||
En cas de réponse déjà envoyée, le handler log en WARNING pour "already commited"
|
||
/ "already committed".
|
||
• Scopes des beans : mélange ViewScoped (listes, détail, formulaires ciblés) et
|
||
SessionScoped (dashboard, demandes, rôles, adhesions, etc.). RolesBean en
|
||
SessionScoped pour une liste de rôles = risque de données obsolètes si l’utilisateur
|
||
garde l’onglet longtemps.
|
||
|
||
|
||
6. RESSOURCES REST SERVEUR – POINTS D’ATTENTION
|
||
--------------------------------------------------------------------------------
|
||
• OrganisationResource : GET sans path retourne PagedResponse<OrganisationSummaryResponse>
|
||
avec paramètres page, size, recherche (optionnel). Client n’envoie pas « recherche ».
|
||
• CotisationResource : deux chemins pour des stats (/stats et /statistiques) ; les deux
|
||
exposés pour compatibilité.
|
||
• TypeOrganisationReferenceResource : DELETE appelle supprimerPourSuperAdmin si
|
||
SUPER_ADMIN/SUPER_ADMINISTRATEUR, sinon supprimer(id). Logique métier cohérente
|
||
avec un rôle privilégié.
|
||
• Pas de @RolesAllowed sur DemandeAideResource, PropositionAideResource, RoleResource,
|
||
HealthResource : à documenter ou à aligner avec la politique de sécurité globale.
|
||
|
||
|
||
7. QUALITÉ ET TESTS
|
||
--------------------------------------------------------------------------------
|
||
• API : Jacoco exige 1.00 sur tous les compteurs (dont branches). Très exigeant ;
|
||
tout nouveau code non testé peut faire échouer le build.
|
||
• Impl : même politique 1.00 sauf branches à 0.30. Quarkus JUnit 5, RestAssured,
|
||
quarkus-test-security, quarkus-jacoco.
|
||
• Client : pas de Jacoco configuré dans le POM ; pas de mesure de couverture côté
|
||
client.
|
||
• Checkstyle (API) : exécutions en plugin commentées ; la qualité de style n’est pas
|
||
appliquée au build.
|
||
|
||
|
||
8. DIVERS
|
||
--------------------------------------------------------------------------------
|
||
• Client TypeOrganisationClientService.disable() : nom de méthode « disable » alors que
|
||
le serveur effectue une suppression (DELETE). Sémantique différente côté client.
|
||
• RestClientExceptionMapper (client) : mappe 4xx/5xx vers des exceptions dédiées ;
|
||
pour 5xx le message est volontairement générique (pas d’exposition de détail).
|
||
• Doublon possible de DTO dashboard : MembreDashboardSyntheseResponse déplacé dans
|
||
l’API (éviter split package) ; à confirmer qu’il n’existe plus dans l’impl.
|
||
• RolesBean (client) : supprimerRole() retire uniquement de la liste en mémoire ;
|
||
AdminUserService n’expose pas de DELETE pour les rôles. Comportement « suppression »
|
||
uniquement côté client.
|
||
|
||
|
||
9. SYNTHÈSE DES RISQUES ET RECOMMANDATIONS
|
||
--------------------------------------------------------------------------------
|
||
• Critique : Contrat liste organisations (PagedResponse<OrganisationResponse> vs
|
||
PagedResponse<OrganisationSummaryResponse>). Aligner le type retourné ou le type
|
||
attendu par le client (ex. adapter le client à OrganisationSummaryResponse ou
|
||
faire renvoyer OrganisationResponse par le serveur).
|
||
• Important : Ressources sans @RolesAllowed (DemandeAide, PropositionAide, Role,
|
||
Health). Définir une politique explicite (au moins pour DemandeAide, PropositionAide, Role).
|
||
• Important : Unification des noms de rôles (UPPER vs lowercase, MANAGER/MEMBER vs
|
||
ADMIN/MEMBRE) en fonction du répertoire (Keycloak) pour éviter 403 ou accès trop larges.
|
||
• Moyen : Recherche membres — aligner chemins client (/search) et serveur (/recherche)
|
||
ou documenter la différence et adapter le client.
|
||
• Moyen : Pagination demandes d’aide — retourner un PagedResponse si le client
|
||
l’attend, ou documenter que la réponse est une List.
|
||
• Mineur : Typo "already commited" dans ViewExpiredExceptionHandler.
|
||
• Mineur : Activer Checkstyle ou supprimer la config si non souhaitée ; documenter
|
||
l’absence de couverture côté client.
|
||
|
||
================================================================================
|
||
Fin de l’audit.
|
||
================================================================================
|