Files
unionflow-server-impl-quarkus/pom.xml
dahoud ed0d74e124
Some checks failed
CI/CD Pipeline / pipeline (push) Failing after 3m3s
feat(sprint-17 backend 2026-04-25): Public KPI Sharing — token signé HMAC-SHA256 + endpoints admin/public
Transparency réglementaire (Sprint 16.D différé livré en S17). Permet aux autorités
externes (BCEAO, ARTCI, CENTIF, contrôleurs UEMOA) de consulter les KPI agrégés
d'une organisation sans login, via lien signé temporairement.

Architecture sécurité
- KpiShareTokenService : HMAC-SHA256 + base64url, format orgId.expiryMillis.signature
- Vérification time-constant via MessageDigest.isEqual (résistant timing attacks)
- Secret @ConfigProperty unionflow.kpi.share.secret (défaut TTL 7 jours)
- Pas de DB — token autosuffisant, révocable seulement par rotation du secret

KpiPublicService
- snapshotPublic(orgId) : extrait sous-ensemble safe de ComplianceSnapshot
- Audit chaque accès public (méta-traçabilité — qui/quand consulté quoi)

Endpoints
- GET /api/admin/kpi/share-link/{orgId}?ttlSeconds=...
  @RolesAllowed ADMIN_ORGANISATION, PRESIDENT, COMPLIANCE_OFFICER, SUPER_ADMIN
  Retourne {token, ttlSeconds, publicUrl, publicWebPath}
- GET /api/public/kpi?token=...
  @PermitAll (whitelist /api/public/* dans application.properties)
  Retourne KpiPublicSnapshot ou 401/404 si token invalide/expiré ou org introuvable

Bump dépendance api 1.0.9 → 1.0.10 (DTO KpiPublicSnapshot ajouté)

Tests KpiShareTokenService (9 tests)
- Round-trip orgId, ttl 0/<=0 défaut, orgId null exception
- Token expiré (signature fake), tampering signature, tampering orgId
- Malformé (< 3 parts, > 4 parts)
- Null/blank
- Encode/decode round-trip avec caractères spéciaux

ACTION USER : mvn install api 1.0.10 puis tester impl/web.
2026-04-25 16:48:47 +00:00

504 lines
20 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>dev.lions.unionflow</groupId>
<artifactId>unionflow-server-impl-quarkus</artifactId>
<version>1.0.7</version>
<packaging>jar</packaging>
<name>UnionFlow Server Implementation (Quarkus)</name>
<description>Implémentation Quarkus du serveur UnionFlow</description>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<maven.compiler.release>21</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<quarkus.platform.version>3.27.3</quarkus.platform.version>
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<lombok.version>1.18.38</lombok.version>
<!-- Overrides BOM : Docker Desktop 29.x compat -->
<testcontainers.version>1.21.4</testcontainers.version>
<docker-java.version>3.4.2</docker-java.version>
<!-- Jacoco -->
<jacoco.version>0.8.12</jacoco.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>${quarkus.platform.artifact-id}</artifactId>
<version>${quarkus.platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-bom</artifactId>
<version>${testcontainers.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Lombok : pas dans Quarkus BOM -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Dépendance vers l'API -->
<dependency>
<groupId>dev.lions.unionflow</groupId>
<artifactId>unionflow-server-api</artifactId>
<version>1.0.10</version>
</dependency>
<!-- Lions User Manager API (pour DTOs et client Keycloak) -->
<dependency>
<groupId>dev.lions.user.manager</groupId>
<artifactId>lions-user-manager-server-api</artifactId>
<version>1.1.0</version>
</dependency>
<!-- Quarkus Core -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client-jackson</artifactId>
</dependency>
<!-- Base de données PostgreSQL -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm-panache</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-h2</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-flyway</artifactId>
</dependency>
<!-- Sécurité Keycloak OIDC -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-keycloak-authorization</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc-client</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client-oidc-filter</artifactId>
</dependency>
<!-- WebSocket pour les notifications temps réel -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-websockets-next</artifactId>
</dependency>
<!-- Kafka pour Event Streaming -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-messaging-kafka</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-mailer</artifactId>
</dependency>
<!-- Configuration et santé -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-config-yaml</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-health</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-cache</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-scheduler</artifactId>
</dependency>
<!-- OpenAPI/Swagger -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>
<!-- Validation -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-validator</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- MapStruct pour le mapping DTO <-> Entité (1.6+ pour Jakarta EE) -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.6.3</version>
</dependency>
<!-- Apache POI pour Excel -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-lite</artifactId>
<version>5.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>5.2.5</version>
</dependency>
<!-- Apache Commons CSV pour CSV -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.10.0</version>
</dependency>
<!-- OpenPDF pour la génération PDF -->
<dependency>
<groupId>com.github.librepdf</groupId>
<artifactId>openpdf</artifactId>
<version>1.3.30</version>
</dependency>
<!-- Firebase Admin SDK — notifications push FCM (P2.2) -->
<dependency>
<groupId>com.google.firebase</groupId>
<artifactId>firebase-admin</artifactId>
<version>9.3.0</version>
<exclusions>
<!-- Éviter les conflits avec Netty/Vert.x de Quarkus -->
<exclusion>
<groupId>io.netty</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Tests -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-mockito</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-security</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.24.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
<!-- Quarkus Jacoco Extension for better coverage -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jacoco</artifactId>
<scope>test</scope>
</dependency>
<!-- Bridge Log4j2 to JBoss LogManager to avoid noise from libraries like Apache POI -->
<dependency>
<groupId>org.jboss.logmanager</groupId>
<artifactId>log4j2-jboss-logmanager</artifactId>
<scope>test</scope>
</dependency>
<!-- SmallRye In-Memory connector for Kafka tests (no broker needed) -->
<dependency>
<groupId>io.smallrye.reactive</groupId>
<artifactId>smallrye-reactive-messaging-in-memory</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>gitea-lionsdev</id>
<name>Gitea Maven Repository</name>
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<build>
<plugins>
<!-- Ajouter les sources générées par MapStruct comme source root pour la phase compile -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.4.0</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/annotations</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.6.3</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.platform.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>build</goal>
<goal>generate-code</goal>
<goal>generate-code-tests</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Maven Surefire pour les tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.5</version>
<configuration>
<argLine>@{argLine} -Xmx768m -XX:+UseSerialGC -XX:TieredStopAtLevel=1 -XX:CICompilerCount=2 -XX:ReservedCodeCacheSize=256m --add-opens java.base/java.util=ALL-UNNAMED -Djdk.attach.allowAttachSelf=true</argLine>
<environmentVariables>
<UNIONFLOW_DOMAIN>api.lions.dev</UNIONFLOW_DOMAIN>
</environmentVariables>
<systemPropertyVariables>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<!-- Exclure les migrations Flyway du classpath des tests -->
<quarkus.flyway.enabled>false</quarkus.flyway.enabled>
<quarkus.flyway.migrate-at-start>false</quarkus.flyway.migrate-at-start>
<!-- Chemin explicite pour quarkus-jacoco (même fichier que report/check) -->
<quarkus.jacoco.data-file>${project.build.directory}/jacoco-quarkus.exec</quarkus.jacoco.data-file>
<quarkus.jacoco.reuse-data-file>true</quarkus.jacoco.reuse-data-file>
</systemPropertyVariables>
</configuration>
</plugin>
<!-- Jacoco pour la couverture de code -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<!-- prepare-agent pour tests non-Quarkus; exclut QuarkusClassLoader (quarkus-jacoco s'en charge) -->
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${project.build.directory}/jacoco-quarkus.exec</destFile>
<append>true</append>
<exclClassLoaders>*QuarkusClassLoader</exclClassLoaders>
</configuration>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/jacoco-quarkus.exec</dataFile>
</configuration>
</execution>
<execution>
<id>check</id>
<phase>test</phase>
<goals>
<goal>check</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/jacoco-quarkus.exec</dataFile>
<haltOnFailure>true</haltOnFailure>
<excludes>
<!-- Service d'abonnement : nécessite un plan produit complet (non testé en CI) -->
<exclude>dev/lions/unionflow/server/service/SouscriptionService.class</exclude>
<exclude>dev/lions/unionflow/server/service/SouscriptionService$*.class</exclude>
<!-- Ressource abonnement : dépend du SouscriptionService non testé -->
<exclude>dev/lions/unionflow/server/resource/SouscriptionResource.class</exclude>
<!-- Ressource compte adhérent : tests d'intégration requièrent DB réelle -->
<exclude>dev/lions/unionflow/server/resource/CompteAdherentResource.class</exclude>
<!-- Repository Panache : nécessite une base de données réelle -->
<exclude>dev/lions/unionflow/server/repository/FormuleAbonnementRepository.class</exclude>
</excludes>
<rules>
<rule>
<element>BUNDLE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>1.00</minimum>
</limit>
<limit>
<counter>BRANCH</counter>
<value>COVEREDRATIO</value>
<minimum>0.30</minimum>
</limit>
<limit>
<counter>INSTRUCTION</counter>
<value>COVEREDRATIO</value>
<minimum>1.00</minimum>
</limit>
<limit>
<counter>METHOD</counter>
<value>COVEREDRATIO</value>
<minimum>1.00</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>native</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>${quarkus.platform.group-id}</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.platform.version}</version>
<executions>
<execution>
<goals>
<goal>native-image</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>