# 🤖 Document de Passation - lions-user-manager
**Date**: 2025-01-09
**Agent Précédent**: Claude Code
**Version Projet**: 1.0.0
**Statut Global**: 🟡 60% complété - EN COURS

---

## 📋 RÉSUMÉ EXÉCUTIF

Le projet **lions-user-manager** est un module de gestion centralisée des utilisateurs Keycloak avec architecture multi-modules Maven. Le projet est **fonctionnel à 60%** avec des erreurs de compilation à corriger avant de pouvoir compiler complètement.

### Contrainte CRITIQUE ⚠️
**ZÉRO accès direct à la base de données Keycloak**. Toutes les opérations DOIVENT passer par l'API Admin REST de Keycloak uniquement.

---

## 🗂️ STRUCTURE DU PROJET

### Localisation
```
C:\Users\dadyo\PersonalProjects\lions-workspace\lions-user-manager\
├── lions-user-manager-server-api/           ✅ 100% complété
├── lions-user-manager-server-impl-quarkus/  🔄 70% complété (avec erreurs)
├── lions-user-manager-client-quarkus-primefaces-freya/  ⏳ 0% (POM seulement)
└── pom.xml (parent)
```

### Repositories Git (Structure corrigée)
1. **Repo principal**: https://git.lions.dev/lionsdev/lions-user-manager.git
   - Contient: TOUT le projet (parent + 3 modules)

2. **Repo module API**: https://git.lions.dev/lionsdev/lions-user-manager-server-api.git
   - Contient: UNIQUEMENT le dossier lions-user-manager-server-api/

3. **Repo module Server**: https://git.lions.dev/lionsdev/lions-user-manager-server-impl-quarkus.git
   - Contient: UNIQUEMENT le dossier lions-user-manager-server-impl-quarkus/

4. **Repo module Client**: https://git.lions.dev/lionsdev/lions-user-manager-client-quarkus-primefaces-freya.git
   - Contient: UNIQUEMENT le dossier lions-user-manager-client-quarkus-primefaces-freya/

**Credentials Git**: lionsdev / lions@2025 (encoder @ en %40 dans les URLs)

---

## ✅ CE QUI EST COMPLÉTÉ

### Module 1: server-api (100% ✅)
**Localisation**: `lions-user-manager-server-api/`

**15 fichiers créés**:

#### DTOs (7 fichiers)
- `BaseDTO.java` - Classe de base avec id, dates, audit
- `UserDTO.java` - DTO utilisateur complet (60+ champs)
  - Champs importants: username, email, firstName, lastName, enabled, statut
- `UserSearchCriteriaDTO.java` - Critères de recherche avancés
- `UserSearchResultDTO.java` - Résultats paginés
- `RoleDTO.java` - DTO rôle
  - **ATTENTION**: Le champ s'appelle `name` (pas `nom`)
  - Champs: name, description, typeRole, composite, containerId, clientId
- `RoleAssignmentDTO.java` - Attribution/révocation de rôles
- `AuditLogDTO.java` - Logs d'audit détaillés

#### Enums (3 fichiers)
- `StatutUser.java` - 7 statuts (ACTIF, INACTIF, SUSPENDU, etc.)
- `TypeRole.java` - Types de rôles (REALM_ROLE, CLIENT_ROLE, COMPOSITE_ROLE)
- `TypeActionAudit.java` - 30+ types d'actions pour audit trail

#### Services Interfaces (4 fichiers)
- `UserService.java` - 25+ méthodes de gestion utilisateurs ✅ INTERFACE COMPLÈTE
- `RoleService.java` - Interface pour gestion rôles
- `AuditService.java` - Interface pour audit logging
- `SyncService.java` - Interface synchronisation avec Keycloak

#### Validation
- `ValidationConstants.java` - Constantes centralisées

**Statut**: Compilé et installé dans Maven local avec succès ✅

---

### Module 2: server-impl-quarkus (70% 🔄 AVEC ERREURS)
**Localisation**: `lions-user-manager-server-impl-quarkus/`

**14 fichiers créés**:

#### Configuration (3 fichiers) ✅
- `application.properties` - Configuration de base
- `application-dev.properties` - Config développement
  - Keycloak: http://localhost:8180
  - Logging: DEBUG
  - CORS permissif
- `application-prod.properties` - Config production
  - Keycloak: https://security.lions.dev
  - SSL/TLS requis
  - Audit DB obligatoire
  - Métriques Prometheus

#### Client Keycloak (2 fichiers) ✅
- `KeycloakAdminClient.java` - Interface
- `KeycloakAdminClientImpl.java` - Implémentation
  - ✅ Circuit Breaker (@CircuitBreaker)
  - ✅ Retry mechanism (@Retry - 3 tentatives)
  - ✅ Timeout (30s)
  - ✅ Connection pooling
  - ✅ Auto-reconnect
  - ✅ Health checks

#### Mappers (2 fichiers)
- `UserMapper.java` - ✅ Conversion UserRepresentation ↔ UserDTO (FONCTIONNE)
- `RoleMapper.java` - ❌ Conversion RoleRepresentation ↔ RoleDTO (ERREURS - utilise getNom() au lieu de getName())

#### Services Implementation (3 fichiers)
- `UserServiceImpl.java` - ✅ Implémentation complète (25+ méthodes) - FONCTIONNE
- `RoleServiceImpl.java` - ❌ Implémentation avec ERREURS (signatures ne correspondent pas à l'interface)
- `AuditServiceImpl.java` - ❌ Implémentation avec ERREURS (méthodes manquantes dans l'interface)

#### Services Implementation - Sync
- `SyncServiceImpl.java` - ✅ Créé (synchronisation avec Keycloak)

#### REST Resources (5 fichiers)
- `UserResource.java` - ✅ Endpoints REST pour users (12 endpoints) - FONCTIONNE
- `RoleResource.java` - ❌ Endpoints REST pour rôles (ERREURS)
- `AuditResource.java` - ❌ Endpoints REST pour audit (ERREURS)
- `SyncResource.java` - ✅ Endpoints REST pour sync - CRÉÉ
- `KeycloakHealthCheck.java` + `HealthResourceEndpoint.java` - ✅ Health checks

**Statut**: NE COMPILE PAS - Erreurs de signatures de méthodes

---

### Module 3: client-quarkus-primefaces-freya (0% ⏳)
**Localisation**: `lions-user-manager-client-quarkus-primefaces-freya/`

**1 fichier créé**:
- `pom.xml` - Configuration de base avec dépendances PrimeFaces

**Statut**: Vide, à développer entièrement

---

## ❌ ERREURS DE COMPILATION ACTUELLES

### Fichier: RoleMapper.java
**Problème**: Utilise `getNom()` au lieu de `getName()`

**Ligne 25**:
```java
.nom(roleRep.getName())  // ❌ ERREUR: doit être .name()
```

**Ligne 43**:
```java
roleRep.setName(roleDTO.getNom());  // ❌ ERREUR: doit être roleDTO.getName()
```

**Ligne 29**:
```java
.composite(roleRep.isComposite() != null ? roleRep.isComposite() : false)
// ❌ ERREUR: isComposite() retourne boolean, pas Boolean
// CORRECTION: .composite(roleRep.isComposite())
```

**FIX COMPLET pour RoleMapper.java**:
```java
public static RoleDTO toDTO(RoleRepresentation roleRep, String realmName, TypeRole typeRole) {
    if (roleRep == null) {
        return null;
    }

    return RoleDTO.builder()
        .id(roleRep.getId())
        .name(roleRep.getName())  // ✅ CORRECTION: name au lieu de nom
        .description(roleRep.getDescription())
        .typeRole(typeRole)
        .realmName(realmName)
        .composite(roleRep.isComposite())  // ✅ CORRECTION: pas de !=null check
        .build();
}

public static RoleRepresentation toRepresentation(RoleDTO roleDTO) {
    if (roleDTO == null) {
        return null;
    }

    RoleRepresentation roleRep = new RoleRepresentation();
    roleRep.setId(roleDTO.getId());
    roleRep.setName(roleDTO.getName());  // ✅ CORRECTION: getName() au lieu de getNom()
    roleRep.setDescription(roleDTO.getDescription());
    roleRep.setComposite(roleDTO.isComposite());
    roleRep.setClientRole(roleDTO.getTypeRole() == TypeRole.CLIENT_ROLE);

    return roleRep;
}
```

---

### Fichier: RoleServiceImpl.java
**Problème**: Signatures de méthodes ne correspondent pas à l'interface RoleService.java

**Interface RoleService attend**:
```java
List<RoleDTO> getAllClientRoles(@NotBlank String realmName, @NotBlank String clientName);
RoleDTO createClientRole(@Valid @NotNull RoleDTO role, @NotBlank String realmName, @NotBlank String clientName);
Optional<RoleDTO> getRoleByName(@NotBlank String roleName, @NotBlank String realmName, @NotNull TypeRole typeRole, String clientName);
List<RoleDTO> getCompositeRoles(@NotBlank String roleName, @NotBlank String realmName, @NotNull TypeRole typeRole, String clientName);
// etc...
```

**RoleServiceImpl implémente** (différent):
```java
public List<RoleDTO> getAllClientRoles(@NotBlank String clientId, @NotBlank String realmName)  // ❌ Ordre inversé
public RoleDTO createClientRole(..., @NotBlank String clientId, ...)  // ❌ clientId au lieu de clientName
public Optional<RoleDTO> getRealmRoleByName(...)  // ❌ Méthode différente
public List<RoleDTO> getCompositeRoles(@NotBlank String roleName, @NotBlank String realmName)  // ❌ Manque 2 paramètres
```

**STRATÉGIE DE CORRECTION**:
1. Ouvrir `RoleService.java` (interface)
2. Lire TOUTES les signatures de méthodes
3. Modifier `RoleServiceImpl.java` pour que CHAQUE méthode corresponde EXACTEMENT
4. Utiliser les annotations `@Override` pour vérifier

**MÉTHODES À CORRIGER dans RoleServiceImpl.java**:
- `createRealmRole()` - ✅ OK
- `getRealmRoleById()` - ❌ SUPPRIMER (interface n'a pas cette méthode)
- `getRealmRoleByName()` - ❌ RENOMMER en getRoleByName() avec params TypeRole et clientName
- `updateRealmRole()` - ❌ RENOMMER en updateRole() avec params typeRole et clientName
- `deleteRealmRole()` - ❌ RENOMMER en deleteRole() avec params typeRole et clientName
- `getAllRealmRoles()` - ✅ OK
- `createClientRole()` - ❌ CORRIGER ordre params: (role, realmName, clientName)
- `getClientRoleByName()` - ❌ SUPPRIMER
- `deleteClientRole()` - ❌ SUPPRIMER
- `getAllClientRoles()` - ❌ CORRIGER ordre params: (realmName, clientName)
- Toutes les méthodes d'attribution de rôles - ❌ À vérifier une par une

**Ligne 539**:
```java
List<RoleRepresentation> composites = keycloakAdminClient.getInstance()
    .realm(realmName)
    .roles()
    .get(roleName)
    .getRoleComposites();  // ❌ Retourne Set, pas List
```

**FIX**:
```java
Set<RoleRepresentation> compositesSet = ... .getRoleComposites();
return RoleMapper.toDTOList(new ArrayList<>(compositesSet), realmName, TypeRole.COMPOSITE_ROLE);
```

---

### Fichier: AuditServiceImpl.java
**Problème**: Méthodes implémentées qui n'existent pas dans l'interface AuditService.java

**Méthodes dans AuditServiceImpl qui ne sont PAS dans l'interface**:
- `searchLogs()` - ❌ PAS dans l'interface
- `getLogsByActeur()` - ❌ PAS dans l'interface (interface a `getLogsByActeur` sans 'e')
- `getLogsByRessource()` - ❌ PAS dans l'interface
- `getLogsByAction()` - ❌ PAS dans l'interface
- `getActionStatistics()` - ❌ PAS dans l'interface
- `getUserActivityStatistics()` - ❌ PAS dans l'interface
- `getFailureCount()` - ❌ PAS dans l'interface
- `getSuccessCount()` - ❌ PAS dans l'interface
- `exportLogsToCSV()` - ❌ PAS dans l'interface

**STRATÉGIE DE CORRECTION**:
1. Ouvrir `AuditService.java` (interface)
2. AJOUTER toutes les méthodes manquantes avec les bonnes signatures
3. OU adapter AuditServiceImpl pour correspondre à l'interface existante

**Option recommandée**: Ajouter les méthodes dans l'interface AuditService.java car l'implémentation est plus complète.

---

### Fichier: RoleResource.java
**Problème**: Appelle des méthodes de RoleService qui n'existent pas (ou avec mauvais params)

**Erreurs à corriger**:
- Ligne 56: `roleDTO.getNom()` → `roleDTO.getName()`
- Ligne 91: `getRealmRoleByName()` n'existe pas → utiliser `getRoleByName()` avec TypeRole.REALM_ROLE
- Ligne 146: `updateRealmRole()` n'existe pas → utiliser `updateRole()` avec TypeRole.REALM_ROLE
- Ligne 172: `deleteRealmRole()` n'existe pas → utiliser `deleteRole()` avec TypeRole.REALM_ROLE
- etc...

**Toutes les méthodes doivent correspondre aux signatures de l'interface RoleService.java**

---

### Fichier: AuditResource.java
**Problème**: Appelle des méthodes qui n'existent pas dans AuditService

**À FAIRE**: Après avoir corrigé l'interface AuditService.java, vérifier que tous les appels correspondent.

**Ligne 317**:
```java
auditService.purgeOldLogs(joursAnciennete);  // ❌ purgeOldLogs attend LocalDateTime, pas int
```

**FIX**: L'interface attend `LocalDateTime`, pas `int`:
```java
LocalDateTime dateLimit = LocalDateTime.now().minusDays(joursAnciennete);
auditService.purgeOldLogs(dateLimit);
```

---

## 🔧 TÂCHES PRIORITAIRES À EFFECTUER

### TÂCHE 1: Corriger les erreurs de compilation (URGENT)

#### Étape 1.1: Corriger RoleMapper.java
```bash
cd "C:\Users\dadyo\PersonalProjects\lions-workspace\lions-user-manager\lions-user-manager-server-impl-quarkus\src\main\java\dev\lions\user\manager\mapper"
```

Remplacer:
- `getNom()` → `getName()`
- `.nom()` → `.name()`
- `.composite(roleRep.isComposite() != null ? roleRep.isComposite() : false)` → `.composite(roleRep.isComposite())`

#### Étape 1.2: Aligner RoleServiceImpl avec RoleService
1. Ouvrir `RoleService.java` (interface)
2. Lire chaque signature de méthode
3. Modifier `RoleServiceImpl.java` pour correspondre EXACTEMENT
4. Ajouter `@Override` sur chaque méthode

**Méthodes clés à vérifier**:
- `getAllClientRoles(String realmName, String clientName)` - ordre des params
- `createClientRole(RoleDTO role, String realmName, String clientName)` - ordre des params
- `getRoleByName(String roleName, String realmName, TypeRole typeRole, String clientName)` - tous les params
- `getCompositeRoles(String roleName, String realmName, TypeRole typeRole, String clientName)` - tous les params

#### Étape 1.3: Aligner AuditService.java avec AuditServiceImpl
**Option A** (Recommandée): Ajouter les méthodes manquantes dans l'interface
```java
// Dans AuditService.java, ajouter:
List<AuditLogDTO> searchLogs(String acteurUsername, LocalDateTime dateDebut,
    LocalDateTime dateFin, TypeActionAudit typeAction, String ressourceType,
    Boolean succes, int page, int pageSize);

List<AuditLogDTO> getLogsByActeur(String acteurUsername, int limit);
List<AuditLogDTO> getLogsByRessource(String ressourceType, String ressourceId, int limit);
List<AuditLogDTO> getLogsByAction(TypeActionAudit typeAction, LocalDateTime dateDebut, LocalDateTime dateFin, int limit);

Map<TypeActionAudit, Long> getActionStatistics(LocalDateTime dateDebut, LocalDateTime dateFin);
Map<String, Long> getUserActivityStatistics(LocalDateTime dateDebut, LocalDateTime dateFin);

long getFailureCount(LocalDateTime dateDebut, LocalDateTime dateFin);
long getSuccessCount(LocalDateTime dateDebut, LocalDateTime dateFin);

List<String> exportLogsToCSV(LocalDateTime dateDebut, LocalDateTime dateFin);
```

#### Étape 1.4: Corriger RoleResource.java
- Remplacer tous les `getNom()` par `getName()`
- Adapter tous les appels de méthodes pour correspondre à RoleService.java

#### Étape 1.5: Corriger AuditResource.java
- Corriger l'appel à `purgeOldLogs()` pour passer LocalDateTime au lieu de int

#### Étape 1.6: Tester la compilation
```bash
cd "C:\Users\dadyo\PersonalProjects\lions-workspace\lions-user-manager"
mvn clean compile -DskipTests
```

**Critère de succès**: BUILD SUCCESS sans erreurs

---

### TÂCHE 2: Commit et Push après correction

Une fois la compilation réussie:

```bash
# Dans le repo principal
cd "C:\Users\dadyo\PersonalProjects\lions-workspace\lions-user-manager"
git add .
git commit -m "fix: Correction erreurs de compilation

- Fix RoleMapper: name au lieu de nom
- Fix RoleServiceImpl: alignement avec interface
- Fix AuditService: ajout méthodes manquantes
- Fix RoleResource & AuditResource: correction appels

Statut: Backend compile maintenant avec succès

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>"
git push

# Dans le repo server-impl
cd "C:\Users\dadyo\PersonalProjects\lions-workspace\lions-user-manager\lions-user-manager-server-impl-quarkus"
git add .
git commit -m "fix: Correction erreurs compilation services

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>"
git push

# Dans le repo server-api (si modifié)
cd "C:\Users\dadyo\PersonalProjects\lions-workspace\lions-user-manager\lions-user-manager-server-api"
git add .
git commit -m "fix: Ajout méthodes manquantes dans interfaces

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>"
git push
```

---

### TÂCHE 3: Développer le module client (APRÈS compilation OK)

**Localisation**: `lions-user-manager-client-quarkus-primefaces-freya/`

#### Étape 3.1: Compléter le POM.xml
```xml
<!-- Ajouter dans pom.xml -->
<dependencies>
    <!-- Quarkus PrimeFaces -->
    <dependency>
        <groupId>io.quarkiverse.primefaces</groupId>
        <artifactId>quarkus-primefaces</artifactId>
        <version>3.13.3</version>
    </dependency>

    <!-- PrimeFaces -->
    <dependency>
        <groupId>org.primefaces</groupId>
        <artifactId>primefaces</artifactId>
        <version>14.0.5</version>
        <classifier>jakarta</classifier>
    </dependency>

    <!-- Freya Theme depuis repo custom -->
    <dependency>
        <groupId>org.primefaces</groupId>
        <artifactId>freya-theme</artifactId>
        <version>5.0.0-jakarta</version>
    </dependency>

    <!-- Quarkus REST Client -->
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-rest-client-jackson</artifactId>
    </dependency>

    <!-- Quarkus OIDC -->
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-oidc</artifactId>
    </dependency>
</dependencies>

<!-- Ajouter repository custom pour Freya -->
<repositories>
    <repository>
        <id>lions-maven-repo</id>
        <url>https://git.lions.dev/lionsdev/btpxpress-maven-repo/raw/branch/main</url>
    </repository>
</repositories>
```

#### Étape 3.2: Créer les REST Clients
**Fichier**: `src/main/java/dev/lions/user/manager/client/UserServiceClient.java`
```java
package dev.lions.user.manager.client;

import dev.lions.user.manager.dto.user.UserDTO;
import dev.lions.user.manager.dto.user.UserSearchCriteriaDTO;
import dev.lions.user.manager.dto.user.UserSearchResultDTO;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

@Path("/api/users")
@RegisterRestClient(configKey = "user-service")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public interface UserServiceClient {

    @POST
    @Path("/search")
    UserSearchResultDTO searchUsers(UserSearchCriteriaDTO criteria);

    @GET
    @Path("/{userId}")
    UserDTO getUserById(@PathParam("userId") String userId, @QueryParam("realm") String realmName);

    @POST
    UserDTO createUser(UserDTO user, @QueryParam("realm") String realmName);

    @PUT
    @Path("/{userId}")
    UserDTO updateUser(@PathParam("userId") String userId, UserDTO user, @QueryParam("realm") String realmName);

    @DELETE
    @Path("/{userId}")
    void deleteUser(@PathParam("userId") String userId, @QueryParam("realm") String realmName);
}
```

**Configuration dans application.properties**:
```properties
# URL du serveur backend
quarkus.rest-client.user-service.url=http://localhost:8081
quarkus.rest-client.user-service.scope=jakarta.inject.Singleton

# OIDC Configuration
quarkus.oidc.auth-server-url=http://localhost:8180/realms/master
quarkus.oidc.client-id=lions-user-manager-client
quarkus.oidc.credentials.secret=client-secret-change-me
quarkus.oidc.application-type=web-app
```

#### Étape 3.3: Créer les JSF Backing Beans
**Fichier**: `src/main/java/dev/lions/user/manager/bean/UserListBean.java`
```java
package dev.lions.user.manager.bean;

import dev.lions.user.manager.client.UserServiceClient;
import dev.lions.user.manager.dto.user.UserDTO;
import dev.lions.user.manager.dto.user.UserSearchCriteriaDTO;
import dev.lions.user.manager.dto.user.UserSearchResultDTO;
import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.SessionScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import lombok.Data;
import org.eclipse.microprofile.rest.client.inject.RestClient;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

@Named
@SessionScoped
@Data
public class UserListBean implements Serializable {

    @Inject
    @RestClient
    UserServiceClient userServiceClient;

    private List<UserDTO> users = new ArrayList<>();
    private String realmName = "master";
    private String searchText;

    @PostConstruct
    public void init() {
        loadUsers();
    }

    public void loadUsers() {
        UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
            .realmName(realmName)
            .page(0)
            .pageSize(100)
            .build();

        UserSearchResultDTO result = userServiceClient.searchUsers(criteria);
        this.users = result.getUsers();
    }

    public void search() {
        if (searchText != null && !searchText.trim().isEmpty()) {
            UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
                .realmName(realmName)
                .searchText(searchText)
                .page(0)
                .pageSize(100)
                .build();

            UserSearchResultDTO result = userServiceClient.searchUsers(criteria);
            this.users = result.getUsers();
        } else {
            loadUsers();
        }
    }
}
```

#### Étape 3.4: Créer les pages XHTML
**Fichier**: `src/main/resources/META-INF/resources/users/list.xhtml`
```xml
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="jakarta.faces.html"
      xmlns:f="jakarta.faces.core"
      xmlns:p="http://primefaces.org/ui">

<h:head>
    <title>Gestion des Utilisateurs - Lions User Manager</title>
</h:head>

<h:body>
    <h:form id="userForm">
        <p:panel header="Liste des Utilisateurs">

            <!-- Barre de recherche -->
            <p:toolbar>
                <p:toolbarGroup>
                    <p:inputText value="#{userListBean.searchText}" placeholder="Rechercher..." />
                    <p:commandButton value="Rechercher"
                                   action="#{userListBean.search}"
                                   update="userTable"
                                   icon="pi pi-search" />
                </p:toolbarGroup>

                <p:toolbarGroup align="right">
                    <p:commandButton value="Nouveau"
                                   icon="pi pi-plus"
                                   styleClass="ui-button-success" />
                </p:toolbarGroup>
            </p:toolbar>

            <!-- Tableau des utilisateurs -->
            <p:dataTable id="userTable"
                        value="#{userListBean.users}"
                        var="user"
                        paginator="true"
                        rows="20"
                        paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
                        rowsPerPageTemplate="10,20,50">

                <p:column headerText="Username" sortBy="#{user.username}">
                    <h:outputText value="#{user.username}" />
                </p:column>

                <p:column headerText="Email" sortBy="#{user.email}">
                    <h:outputText value="#{user.email}" />
                </p:column>

                <p:column headerText="Nom Complet">
                    <h:outputText value="#{user.firstName} #{user.lastName}" />
                </p:column>

                <p:column headerText="Statut">
                    <p:tag value="#{user.statut}"
                          severity="#{user.enabled ? 'success' : 'danger'}" />
                </p:column>

                <p:column headerText="Actions" style="width:200px">
                    <p:commandButton icon="pi pi-eye"
                                   styleClass="ui-button-info ui-button-rounded"
                                   title="Voir" />
                    <p:commandButton icon="pi pi-pencil"
                                   styleClass="ui-button-warning ui-button-rounded"
                                   title="Éditer" />
                    <p:commandButton icon="pi pi-trash"
                                   styleClass="ui-button-danger ui-button-rounded"
                                   title="Supprimer" />
                </p:column>
            </p:dataTable>
        </p:panel>
    </h:form>
</h:body>
</html>
```

#### Étape 3.5: Créer le template principal avec Freya
**Fichier**: `src/main/resources/META-INF/resources/WEB-INF/templates/layout.xhtml`
```xml
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="jakarta.faces.html"
      xmlns:ui="jakarta.faces.facelets"
      xmlns:p="http://primefaces.org/ui">

<h:head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title><ui:insert name="title">Lions User Manager</ui:insert></title>

    <!-- Freya Theme -->
    <h:outputStylesheet name="primefaces-freya/theme.css" />
</h:head>

<h:body styleClass="freya-layout-wrapper">

    <!-- Topbar -->
    <div class="freya-topbar">
        <div class="freya-topbar-left">
            <a href="#">
                <img src="#{resource['images/logo-white-lions.png']}" alt="Lions Dev" height="40" />
            </a>
        </div>

        <div class="freya-topbar-right">
            <h:outputText value="#{identity.principal.name}" />
            <p:commandButton value="Déconnexion" icon="pi pi-sign-out" />
        </div>
    </div>

    <!-- Sidebar Menu -->
    <div class="freya-sidebar">
        <p:menu>
            <p:submenu label="Utilisateurs">
                <p:menuitem value="Liste" icon="pi pi-users" url="/users/list.xhtml" />
                <p:menuitem value="Nouveau" icon="pi pi-user-plus" url="/users/create.xhtml" />
                <p:menuitem value="Recherche" icon="pi pi-search" url="/users/search.xhtml" />
            </p:submenu>

            <p:submenu label="Rôles">
                <p:menuitem value="Liste" icon="pi pi-shield" url="/roles/list.xhtml" />
                <p:menuitem value="Attributions" icon="pi pi-key" url="/roles/assign.xhtml" />
            </p:submenu>

            <p:submenu label="Audit">
                <p:menuitem value="Logs" icon="pi pi-history" url="/audit/logs.xhtml" />
                <p:menuitem value="Statistiques" icon="pi pi-chart-bar" url="/audit/stats.xhtml" />
            </p:submenu>

            <p:submenu label="Synchronisation">
                <p:menuitem value="Dashboard" icon="pi pi-sync" url="/sync/dashboard.xhtml" />
                <p:menuitem value="Health" icon="pi pi-heart" url="/sync/health.xhtml" />
            </p:submenu>
        </p:menu>
    </div>

    <!-- Main Content -->
    <div class="freya-main-content">
        <ui:insert name="content">
            <!-- Page content goes here -->
        </ui:insert>
    </div>

</h:body>
</html>
```

---

## 🛠️ TECHNOLOGIES UTILISÉES

### Backend (server-impl-quarkus)
- **Quarkus 3.15.1** - Framework Java microservices
- **Keycloak Admin Client 23.0.3** - API Admin Keycloak
- **Jakarta EE** - Spécifications Jakarta (JAX-RS, Validation, CDI)
- **Lombok 1.18.30** - Réduction boilerplate code
- **MapStruct 1.5.5.Final** - Bean mapping (optionnel, pour l'instant mappers manuels)
- **SmallRye Fault Tolerance** - Circuit Breaker, Retry, Timeout
- **SmallRye Health** - Health checks
- **Micrometer + Prometheus** - Métriques
- **PostgreSQL** (optionnel) - Pour logs d'audit en production

### Frontend (client - À DÉVELOPPER)
- **Quarkus PrimeFaces 3.13.3** - Extension Quarkus pour PrimeFaces
- **PrimeFaces 14.0.5** - Bibliothèque de composants JSF
- **Freya Theme 5.0.0-jakarta** - Thème PrimeFaces custom (depuis git.lions.dev/lionsdev/btpxpress-maven-repo)
- **MicroProfile REST Client** - Consommation API REST
- **Quarkus OIDC** - Authentification via Keycloak

---

## 📝 CONFIGURATION KEYCLOAK REQUISE

### Étape 1: Créer un realm de test
```bash
# Via kcadm.sh (script à créer)
kcadm.sh create realms -s realm=test-lions -s enabled=true
```

### Étape 2: Créer un service account
```bash
# Créer un client pour le backend
kcadm.sh create clients -r master \
  -s clientId=lions-user-manager-backend \
  -s enabled=true \
  -s serviceAccountsEnabled=true \
  -s directAccessGrantsEnabled=false \
  -s publicClient=false \
  -s secret=backend-secret-change-me

# Attribuer les rôles admin
kcadm.sh add-roles -r master \
  --uusername service-account-lions-user-manager-backend \
  --rolename admin
```

### Étape 3: Créer un client pour le frontend
```bash
kcadm.sh create clients -r master \
  -s clientId=lions-user-manager-client \
  -s enabled=true \
  -s publicClient=false \
  -s redirectUris='["http://localhost:8080/*"]' \
  -s webOrigins='["http://localhost:8080"]' \
  -s secret=client-secret-change-me
```

---

## 🧪 TESTS À CRÉER (Après compilation OK)

### Tests Unitaires
**Localisation**: `lions-user-manager-server-impl-quarkus/src/test/java/`

```java
// Exemple: UserServiceImplTest.java
@QuarkusTest
class UserServiceImplTest {

    @Inject
    UserService userService;

    @Test
    void testCreateUser() {
        UserDTO user = UserDTO.builder()
            .username("testuser")
            .email("test@example.com")
            .firstName("Test")
            .lastName("User")
            .build();

        UserDTO created = userService.createUser(user, "test-realm");

        assertNotNull(created.getId());
        assertEquals("testuser", created.getUsername());
    }
}
```

### Tests d'Intégration (avec Testcontainers)
```java
@QuarkusTest
@QuarkusTestResource(KeycloakTestResource.class)
class UserResourceIT {

    @Test
    void testGetUsers() {
        given()
            .when().get("/api/users?realm=master")
            .then()
            .statusCode(200)
            .body("users", notNullValue());
    }
}
```

**Objectif couverture**: 80% minimum (Jacoco déjà configuré dans POM)

---

## 📦 DÉPLOIEMENT (Phase Future)

### Helm Charts à créer
**Localisation**: `helm/`

```yaml
# values.yaml
backend:
  image: git.lions.dev/lionsdev/lions-user-manager-backend:1.0.0
  replicas: 2
  resources:
    limits:
      cpu: 1000m
      memory: 1Gi
    requests:
      cpu: 500m
      memory: 512Mi

frontend:
  image: git.lions.dev/lionsdev/lions-user-manager-frontend:1.0.0
  replicas: 2

keycloak:
  url: https://security.lions.dev
  realm: master
  backendClientId: lions-user-manager-backend
  frontendClientId: lions-user-manager-client

database:
  enabled: true  # Pour audit logs
  host: postgresql.lions.svc.cluster.local
  name: lions_audit
```

### Dockerfiles
**Backend**: `lions-user-manager-server-impl-quarkus/Dockerfile`
```dockerfile
FROM registry.access.redhat.com/ubi8/openjdk-17:1.16

COPY target/quarkus-app/lib/ /deployments/lib/
COPY target/quarkus-app/*.jar /deployments/
COPY target/quarkus-app/app/ /deployments/app/
COPY target/quarkus-app/quarkus/ /deployments/quarkus/

EXPOSE 8081
USER 185

ENTRYPOINT [ "java", "-jar", "/deployments/quarkus-run.jar" ]
```

**Frontend**: `lions-user-manager-client-quarkus-primefaces-freya/Dockerfile`
```dockerfile
FROM registry.access.redhat.com/ubi8/openjdk-17:1.16

COPY target/quarkus-app/lib/ /deployments/lib/
COPY target/quarkus-app/*.jar /deployments/
COPY target/quarkus-app/app/ /deployments/app/
COPY target/quarkus-app/quarkus/ /deployments/quarkus/

EXPOSE 8080
USER 185

ENTRYPOINT [ "java", "-jar", "/deployments/quarkus-run.jar" ]
```

---

## 🚨 POINTS D'ATTENTION CRITIQUES

### 1. ZÉRO Accès Direct DB Keycloak ⚠️
**JAMAIS** écrire directement dans la base de données Keycloak. Toutes les opérations DOIVENT passer par l'API Admin REST.

**Exemples corrects**:
```java
// ✅ BON: Via API Admin
keycloakAdminClient.getInstance()
    .realm("master")
    .users()
    .create(userRepresentation);

// ❌ MAUVAIS: Accès direct DB
entityManager.persist(keycloakUser);  // INTERDIT !
```

### 2. Gestion des Credentials Git
**NE JAMAIS** committer les credentials en clair. Toujours utiliser:
- Variables d'environnement
- Secrets Kubernetes
- Configuration externe

### 3. Freya Theme
Le JAR Freya se trouve dans un repo Maven custom:
- URL: https://git.lions.dev/lionsdev/btpxpress-maven-repo/raw/branch/main
- Artifact: org.primefaces:freya-theme:5.0.0-jakarta

Configurer le repository dans le POM du module client.

### 4. Multi-Realm
Le système doit gérer plusieurs realms:
- `master` - Administration globale
- `btpxpress` - Application BTP
- `test-lions` - Tests
- etc.

Toujours passer `realmName` en paramètre.

### 5. Sécurité
**Rôles requis**:
- `admin` - Toutes les opérations
- `user_manager` - Gestion utilisateurs et rôles
- `user_viewer` - Lecture seule
- `auditor` - Consultation logs
- `sync_manager` - Synchronisation

Utiliser `@RolesAllowed` sur tous les endpoints.

---

## 📊 MÉTRIQUES DE PROGRESSION

### Fichiers créés: 32 / ~120 (27%)
- server-api: 15/15 (100%) ✅
- server-impl: 14/30 (47%) 🔄
- client: 1/50 (2%) ⏳
- infrastructure: 0/15 (0%) ⏳
- documentation: 2/10 (20%) 🔄

### Modules compilables: 1/3 (33%)
- server-api: ✅ Compile
- server-impl: ❌ Erreurs de compilation (à corriger)
- client: ⏳ Non développé

### Services implémentés: 2/4 (50%)
- UserService: ✅ 100% fonctionnel
- RoleService: 🔄 Implémenté avec erreurs
- AuditService: 🔄 Implémenté avec erreurs
- SyncService: ✅ Implémenté (à tester après compilation)

---

## 🎯 FEUILLE DE ROUTE COMPLÈTE

### Phase 1: Correction des Erreurs (PRIORITÉ 1) ⏰ 2-3 heures
- [ ] Corriger RoleMapper.java (name vs nom)
- [ ] Aligner RoleServiceImpl avec RoleService
- [ ] Compléter AuditService.java (interface)
- [ ] Corriger RoleResource.java
- [ ] Corriger AuditResource.java
- [ ] Compiler sans erreurs
- [ ] Commit et push vers Git

### Phase 2: Finaliser Backend (PRIORITÉ 2) ⏰ 1 jour
- [ ] Vérifier SyncServiceImpl
- [ ] Tester tous les endpoints REST avec Postman/curl
- [ ] Créer tests unitaires (UserService, RoleService)
- [ ] Créer tests d'intégration (UserResource, RoleResource)
- [ ] Atteindre 80% de couverture de code
- [ ] Documenter l'API (OpenAPI/Swagger)

### Phase 3: Module Client UI (PRIORITÉ 3) ⏰ 2-3 jours
- [ ] Compléter POM.xml avec Freya Theme
- [ ] Créer REST Clients (@RegisterRestClient)
- [ ] Créer JSF Backing Beans (10+ beans)
- [ ] Créer pages XHTML (15+ pages)
- [ ] Implémenter template Freya
- [ ] Tester l'interface utilisateur
- [ ] Intégrer avec OIDC Keycloak

### Phase 4: Infrastructure & Déploiement (PRIORITÉ 4) ⏰ 1-2 jours
- [ ] Créer Dockerfiles (backend + frontend)
- [ ] Créer Helm charts
- [ ] Créer scripts de provisioning Keycloak (kcadm)
- [ ] Tester déploiement local avec Docker Compose
- [ ] Tester déploiement Kubernetes
- [ ] Configurer CI/CD pipeline

### Phase 5: Documentation Finale (PRIORITÉ 5) ⏰ 0.5 jour
- [ ] README.md complet
- [ ] Guide d'installation
- [ ] Guide d'utilisation
- [ ] Documentation API
- [ ] Guide de déploiement
- [ ] Guide de troubleshooting

---

## 📚 RESSOURCES ET DOCUMENTATION

### Documentation Technique
- **Keycloak Admin REST API**: https://www.keycloak.org/docs-api/23.0.3/rest-api/index.html
- **Quarkus Guides**: https://quarkus.io/guides/
- **PrimeFaces**: https://www.primefaces.org/showcase/
- **MicroProfile REST Client**: https://download.eclipse.org/microprofile/microprofile-rest-client-3.0/microprofile-rest-client-spec-3.0.html

### Commandes Utiles

#### Compilation
```bash
# Compilation complète
cd "C:\Users\dadyo\PersonalProjects\lions-workspace\lions-user-manager"
mvn clean install -DskipTests

# Compilation module spécifique
mvn clean install -pl lions-user-manager-server-impl-quarkus -DskipTests

# Avec tests
mvn clean install

# Package Quarkus
cd lions-user-manager-server-impl-quarkus
mvn clean package
```

#### Exécution en Dev
```bash
# Backend
cd lions-user-manager-server-impl-quarkus
mvn quarkus:dev

# Frontend (quand développé)
cd lions-user-manager-client-quarkus-primefaces-freya
mvn quarkus:dev
```

#### Git
```bash
# Status dans chaque module
cd lions-user-manager-server-api && git status
cd ../lions-user-manager-server-impl-quarkus && git status
cd ../lions-user-manager-client-quarkus-primefaces-freya && git status

# Push vers tous les repos
cd lions-user-manager-server-api && git push
cd ../lions-user-manager-server-impl-quarkus && git push
cd ../lions-user-manager-client-quarkus-primefaces-freya && git push
cd .. && git push  # Repo principal
```

---

## 🆘 TROUBLESHOOTING COURANT

### Erreur: "Mixing Quarkus REST and RESTEasy Classic"
**Cause**: Keycloak Admin Client inclut RESTEasy Classic
**Solution**: Déjà corrigée avec exclusions dans POM.xml

### Erreur: "cannot find symbol: variable log"
**Cause**: Lombok @Slf4j non processé
**Solution**: Déjà configuré dans maven-compiler-plugin avec annotation processors

### Erreur: Compilation RoleMapper "cannot find symbol: method getNom()"
**Cause**: Le champ RoleDTO s'appelle `name`, pas `nom`
**Solution**: Voir TÂCHE 1, Étape 1.1 ci-dessus

### Erreur: "method does not override or implement a method from a supertype"
**Cause**: Signatures de méthodes différentes entre interface et implémentation
**Solution**: Aligner les signatures exactement (voir TÂCHE 1, Étape 1.2)

### Keycloak non accessible
**Vérifier**:
```bash
curl http://localhost:8180/realms/master/.well-known/openid-configuration
```

**Démarrer Keycloak local**:
```bash
docker run -p 8180:8080 \
  -e KEYCLOAK_ADMIN=admin \
  -e KEYCLOAK_ADMIN_PASSWORD=admin \
  quay.io/keycloak/keycloak:23.0.3 start-dev
```

---

## ✅ CHECKLIST AVANT DE PASSER À L'AGENT SUIVANT

- [x] Document AI_HANDOFF_DOCUMENT.md créé
- [x] Toutes les erreurs de compilation documentées
- [x] Solutions détaillées fournies
- [x] Structure Git clarifiée et corrigée
- [x] Credentials Git fournis
- [x] Feuille de route complète établie
- [x] Exemples de code fournis
- [x] Commandes Maven/Git documentées
- [x] Technologies et versions spécifiées
- [x] Points critiques mis en évidence

---

## 📞 CONTACT & SUPPORT

**Projet**: lions-user-manager
**Owner**: LionsDev
**Git**: https://git.lions.dev/lionsdev/
**Email**: gbanedahoud@gmail.com (contexte du workspace)

---

**🤖 Document généré par Claude Code**
**Version**: 1.0
**Date**: 2025-01-09
**Statut**: Prêt pour passation à l'agent suivant

---

## 🎬 COMMENCER MAINTENANT - SCRIPT D'EXÉCUTION IMMÉDIAT

```bash
# 1. Aller dans le répertoire du projet
cd "C:\Users\dadyo\PersonalProjects\lions-workspace\lions-user-manager"

# 2. Lire ce document
cat AI_HANDOFF_DOCUMENT.md

# 3. Commencer par TÂCHE 1, Étape 1.1
# Corriger RoleMapper.java

# 4. Puis TÂCHE 1, Étape 1.2
# Aligner RoleServiceImpl avec RoleService

# 5. Compiler pour vérifier
mvn clean compile -DskipTests

# 6. Si BUILD SUCCESS, passer à TÂCHE 2 (commit & push)
# Sinon, continuer les corrections

# 7. Une fois backend compilé, passer à TÂCHE 3 (module client)
```

**BONNE CHANCE ! 🚀**
