# 🚀 Roadmap d'Implémentation - VoIP Config Refactoring + RBAC System

## 📋 Vue d'ensemble

**Objectifs** :
1. ✅ Refactoring du système VoIP Config (Clean Architecture)
2. ✅ API Tenant pour self-service VoIP
3. ✅ Système complet de Rôles et Permissions (RBAC)

**Effort total estimé** : ~12-15 heures
**Priorité** : 🔴 HAUTE

---

## 🏗️ Phase 1 : Refactoring VoIP Configuration (6 tâches)

### Objectif
Séparer les responsabilités admin vs runtime, corriger les bugs architecturaux, permettre aux tenants de gérer leur propre config.

### Tâche 1.1 : Créer les DTOs pour Runtime
**Fichiers à créer** :
- `src/main/java/com/saas/shared/dto/VoipConfigDTO.java`
- `src/main/java/com/saas/shared/dto/VoipConfigResolverDTO.java`

**Raison** : Découpler le runtime des entités admin

```java
// VoipConfigDTO.java - Immutable DTO pour runtime
@Value
public class VoipConfigDTO {
    String tenantId;
    Provider provider;
    String aiAssistantId;
    String aiType;
    String messagingProfileId;
    String streamUrl;
    boolean fromDatabase; // true = DB, false = .env
}
```

---

### Tâche 1.2 : Créer TenantVoipConfigRuntimeService
**Fichier** : `src/main/java/com/saas/shared/service/TenantVoipConfigRuntimeService.java`

**Responsabilité** : 
- Read-only
- Lookup de config pour les appels VoIP
- Fallback vers .env
- Cache

**Méthode principale** :
```java
@Service
public class TenantVoipConfigRuntimeService {
    
    @Cacheable("voipConfigs")
    public Optional<VoipConfigDTO> resolveVoipConfig(String tenantId, Provider provider) {
        // 1. Chercher en DB
        // 2. Si absent, fallback vers .env
        // 3. Retourner Optional<VoipConfigDTO>
    }
}
```

---

### Tâche 1.3 : Renommer service admin
**Action** : Renommer `TenantVoipConfigService` → `TenantVoipConfigAdminService`

**Responsabilité** :
- CRUD pour admins uniquement
- Éviction de cache après modifications

---

### Tâche 1.4 : Modifier TelnyxTeXMLController
**Action** : Remplacer dépendance admin par runtime service

```java
// ❌ AVANT
private final TenantVoipConfigService voipConfigService;

// ✅ APRÈS
private final TenantVoipConfigRuntimeService runtimeService;
```

---

### Tâche 1.5 : Corriger cache et entités synthétiques
**Actions** :
1. Remplacer `return new TenantVoipConfig()` par `return Optional.empty()`
2. S'assurer que `@CacheEvict` fonctionne même si entité absente
3. Ajouter tests unitaires

---

### Tâche 1.6 : Créer API Tenant
**Fichier** : `src/main/java/com/saas/tenant/controller/TenantVoipConfigController.java`

**Endpoints** :
```
GET    /api/tenant/voip-config          → Lire MA config
PUT    /api/tenant/voip-config          → Modifier MA config
PATCH  /api/tenant/voip-config/activate → Activer MA config
```

**Sécurité** : `@PreAuthorize("hasRole('TENANT_USER')")`

**Important** : Un tenant ne peut modifier QUE sa propre config (extraction du tenantId depuis JWT)

---

## 🔐 Phase 2 : Système de Rôles et Permissions (RBAC) (8 tâches)

### Objectif
Remplacer le système de rôles hardcodé (ADMIN/USER, SYSTEM_ADMIN/TENANT_USER) par un système flexible de rôles et permissions.

### Architecture proposée

```
User (1) ←→ (N) UserRole (N) ←→ (1) Role (1) ←→ (N) RolePermission (N) ←→ (1) Permission
```

**Exemple** :
- User "john@tenant1.com" a le rôle "Gestionnaire VoIP"
- Rôle "Gestionnaire VoIP" a les permissions : "voip.config.read", "voip.config.update"
- User peut donc lire et modifier les configs VoIP, mais pas les supprimer

---

### Tâche 2.1 : Créer entités Role et Permission

**Fichier** : `src/main/java/com/saas/admin/entity/Role.java`
```java
@Entity
@Table(name = "roles", schema = "saas_db")
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false, unique = true)
    private String name; // Ex: "VOIP_MANAGER", "TENANT_ADMIN", "BILLING_VIEWER"
    
    private String description;
    
    private Boolean isActive = true;
    
    // Pour savoir si c'est un rôle système (non modifiable) ou custom
    private Boolean isSystemRole = false;
    
    // Scope: SYSTEM (pour system admins) ou TENANT (pour tenant users)
    @Enumerated(EnumType.STRING)
    private RoleScope scope;
    
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}
```

**Fichier** : `src/main/java/com/saas/admin/entity/Permission.java`
```java
@Entity
@Table(name = "permissions", schema = "saas_db")
public class Permission {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false, unique = true)
    private String name; // Ex: "voip.config.read", "user.create", "tenant.delete"
    
    private String description;
    
    @Enumerated(EnumType.STRING)
    private PermissionCategory category; // VOIP, USER_MANAGEMENT, BILLING, etc.
    
    private LocalDateTime createdAt;
}
```

---

### Tâche 2.2 : Créer tables de liaison

**Fichier** : `src/main/java/com/saas/admin/entity/RolePermission.java`
```java
@Entity
@Table(name = "role_permissions", schema = "saas_db")
public class RolePermission {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @ManyToOne
    @JoinColumn(name = "role_id", nullable = false)
    private Role role;
    
    @ManyToOne
    @JoinColumn(name = "permission_id", nullable = false)
    private Permission permission;
    
    @Column(name = "created_at")
    private LocalDateTime createdAt;
}
```

**Fichier** : `src/main/java/com/saas/admin/entity/UserRole.java`
```java
@Entity
@Table(name = "user_roles", schema = "saas_db")
public class UserRole {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @ManyToOne
    @JoinColumn(name = "user_id", nullable = false)
    private User user;
    
    @ManyToOne
    @JoinColumn(name = "role_id", nullable = false)
    private Role role;
    
    private Boolean isActive = true;
    
    // Pour les rôles tenant-specific, on peut spécifier le tenant
    @Column(name = "tenant_id")
    private String tenantId;
    
    private LocalDateTime createdAt;
}
```

---

### Tâche 2.3 : Créer repositories

**Fichiers** :
- `RoleRepository.java`
- `PermissionRepository.java`
- `RolePermissionRepository.java`
- `UserRoleRepository.java`

**Méthodes clés** :
```java
public interface UserRoleRepository extends JpaRepository<UserRole, Long> {
    List<UserRole> findByUserIdAndIsActive(Long userId, Boolean isActive);
}

public interface RolePermissionRepository extends JpaRepository<RolePermission, Long> {
    List<RolePermission> findByRoleId(Long roleId);
}
```

---

### Tâche 2.4 : Créer services

**Fichier** : `src/main/java/com/saas/admin/service/RoleService.java`
```java
@Service
public class RoleService {
    // CRUD pour les rôles
    public Role createRole(Role role);
    public Role updateRole(Long id, Role updates);
    public void deleteRole(Long id);
    public List<Role> getAllRoles();
    public List<Role> getRolesByScope(RoleScope scope);
    
    // Gestion des permissions d'un rôle
    public void assignPermissionToRole(Long roleId, Long permissionId);
    public void removePermissionFromRole(Long roleId, Long permissionId);
    public List<Permission> getPermissionsForRole(Long roleId);
}
```

**Fichier** : `src/main/java/com/saas/admin/service/PermissionService.java`
```java
@Service
public class PermissionService {
    // CRUD pour les permissions
    public Permission createPermission(Permission permission);
    public List<Permission> getAllPermissions();
    public List<Permission> getPermissionsByCategory(PermissionCategory category);
    
    // Récupérer les permissions d'un user
    public Set<String> getUserPermissions(Long userId);
}
```

---

### Tâche 2.5 : Créer controllers Admin

**Fichier** : `src/main/java/com/saas/admin/controller/AdminRoleController.java`
```java
@RestController
@RequestMapping("/api/admin/roles")
@PreAuthorize("hasPermission('role.manage')") // Nouvelle approche !
public class AdminRoleController {
    
    @PostMapping
    public ResponseEntity<RoleResponse> createRole(@RequestBody CreateRoleRequest request);
    
    @GetMapping
    public ResponseEntity<List<RoleResponse>> getAllRoles();
    
    @PutMapping("/{roleId}")
    public ResponseEntity<RoleResponse> updateRole(@PathVariable Long roleId, @RequestBody UpdateRoleRequest request);
    
    @DeleteMapping("/{roleId}")
    public ResponseEntity<Void> deleteRole(@PathVariable Long roleId);
    
    // Gestion des permissions
    @PostMapping("/{roleId}/permissions/{permissionId}")
    public ResponseEntity<Void> assignPermission(@PathVariable Long roleId, @PathVariable Long permissionId);
    
    @DeleteMapping("/{roleId}/permissions/{permissionId}")
    public ResponseEntity<Void> removePermission(@PathVariable Long roleId, @PathVariable Long permissionId);
}
```

**Fichier** : `src/main/java/com/saas/admin/controller/AdminPermissionController.java` (similaire)

---

### Tâche 2.6 : Modifier UserPrincipal

**Action** : Charger dynamiquement les permissions depuis la DB au lieu d'utiliser role hardcodé

**Avant** :
```java
public Collection<? extends GrantedAuthority> getAuthorities() {
    List<GrantedAuthority> authorities = new ArrayList<>();
    authorities.add(new SimpleGrantedAuthority("ROLE_" + role));
    authorities.add(new SimpleGrantedAuthority("ROLE_" + userType));
    return authorities;
}
```

**Après** :
```java
public Collection<? extends GrantedAuthority> getAuthorities() {
    List<GrantedAuthority> authorities = new ArrayList<>();
    
    // Garder les rôles legacy pour backward compatibility
    authorities.add(new SimpleGrantedAuthority("ROLE_" + role));
    authorities.add(new SimpleGrantedAuthority("ROLE_" + userType));
    
    // Ajouter les permissions dynamiques
    Set<String> permissions = permissionService.getUserPermissions(userId);
    permissions.forEach(perm -> 
        authorities.add(new SimpleGrantedAuthority(perm))
    );
    
    return authorities;
}
```

---

### Tâche 2.7 : Créer système de permissions custom

**Fichier** : `src/main/java/com/saas/shared/security/PermissionEvaluator.java`
```java
@Component
public class CustomPermissionEvaluator implements PermissionEvaluator {
    
    @Override
    public boolean hasPermission(Authentication auth, Object targetDomainObject, Object permission) {
        if (auth == null || permission == null) {
            return false;
        }
        
        String permissionName = permission.toString();
        return auth.getAuthorities().stream()
            .anyMatch(grantedAuth -> grantedAuth.getAuthority().equals(permissionName));
    }
}
```

**Configuration** :
```java
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
    
    @Bean
    public MethodSecurityExpressionHandler methodSecurityExpressionHandler(
            CustomPermissionEvaluator permissionEvaluator) {
        DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
        handler.setPermissionEvaluator(permissionEvaluator);
        return handler;
    }
}
```

---

### Tâche 2.8 : Mettre à jour les controllers existants

**Exemple** : `AdminTenantVoipConfigController`

**Avant** :
```java
@PreAuthorize("hasRole('SYSTEM_ADMIN')")
```

**Après** :
```java
@PreAuthorize("hasPermission(null, 'voip.config.manage')")
```

---

## 📝 Phase 3 : Documentation

### Tâche 3.1 : Mettre à jour replit.md

**Sections à ajouter** :
1. Architecture RBAC
2. Liste des permissions disponibles
3. Exemples de rôles prédéfinis
4. Guide de création de rôles custom

---

## ✅ Ordre d'exécution

```
Phase 1 (VoIP Refactoring)
├── 1.1 DTOs
├── 1.2 RuntimeService
├── 1.3 Renommer AdminService
├── 1.4 Modifier TelnyxController
├── 1.5 Corriger cache
└── 1.6 API Tenant

Phase 2 (RBAC)
├── 2.1 Entités Role/Permission
├── 2.2 Entités RolePermission/UserRole
├── 2.3 Repositories
├── 2.4 Services
├── 2.5 Controllers Admin
├── 2.6 Modifier UserPrincipal
├── 2.7 PermissionEvaluator
└── 2.8 Mettre à jour controllers

Phase 3 (Documentation)
└── 3.1 Mettre à jour replit.md

Review Final
└── Architect review complet
```

---

## 🎯 Permissions prédéfinies suggérées

### VoIP Management
- `voip.config.read` - Lire configs VoIP
- `voip.config.create` - Créer configs VoIP
- `voip.config.update` - Modifier configs VoIP
- `voip.config.delete` - Supprimer configs VoIP
- `voip.config.manage` - Tous les droits VoIP

### User Management
- `user.read` - Lire utilisateurs
- `user.create` - Créer utilisateurs
- `user.update` - Modifier utilisateurs
- `user.delete` - Supprimer utilisateurs
- `user.manage` - Tous les droits utilisateurs

### Tenant Management
- `tenant.read` - Lire tenants
- `tenant.create` - Créer tenants
- `tenant.update` - Modifier tenants
- `tenant.delete` - Supprimer tenants
- `tenant.manage` - Tous les droits tenants

### Role Management
- `role.read` - Lire rôles
- `role.create` - Créer rôles
- `role.update` - Modifier rôles
- `role.delete` - Supprimer rôles
- `role.manage` - Tous les droits rôles

### Billing & Analytics
- `billing.read` - Voir coûts
- `analytics.read` - Voir analytics
- `reports.generate` - Générer rapports

---

## 🚀 Prêt à démarrer

**Validation** : ✅ Confirmé par l'utilisateur

**Prochaine étape** : Commencer Phase 1, Tâche 1.1

Temps estimé pour Phase 1 : ~4-5 heures
Temps estimé pour Phase 2 : ~7-8 heures
**Total** : ~12-13 heures

---

**Questions** ?
- Voulez-vous des rôles prédéfinis en plus des permissions ?
- Faut-il migrer les users existants vers le nouveau système ?
- Gardons-nous le système legacy (role/userType) en parallèle ?
