# UnionFlow Project Constitution > **Version:** 1.0 > **Date:** 2026-02-27 > **Status:** Active > **Scope:** Backend (unionflow-server-impl-quarkus), API (unionflow-server-api), Mobile (unionflow-mobile-apps) --- ## 🎯 Mission & Vision **Mission:** Fournir une plateforme complΓ¨te et sΓ©curisΓ©e pour la gestion d'associations, clubs et organisations Γ  but non lucratif, et **pour la gestion des mutuelles d'Γ©pargne et de financement**. **Vision:** Architecture DDD stricte, sΓ©paration claire API/Implementation, conformitΓ© RGPD, et qualitΓ© industrielle (100% test coverage). --- ## πŸ“ Architecture Principles ### 1. Domain-Driven Design (DDD) - STRICT #### 1.1 Layered Architecture ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Presentation Layer (Resources/API) β”‚ ← JAX-RS REST endpoints β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Application Layer (Services) β”‚ ← Business logic, transactions β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Domain Layer (Entities) β”‚ ← Rich domain models β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ Infrastructure Layer (Repositories) β”‚ ← Data persistence (Panache) β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Rules:** - βœ… **DO**: Resources call Services, Services use Repositories - ❌ **DON'T**: Resources directly access Repositories - ❌ **DON'T**: Entities contain business logic beyond validation - βœ… **DO**: All business logic lives in Services #### 1.2 Entity Pattern - **Base Class**: All entities extend `BaseEntity` ```java @MappedSuperclass public abstract class BaseEntity { @Id UUID id; LocalDateTime dateCreation; LocalDateTime dateModification; String creePar; String modifiePar; Long version; // Optimistic locking Boolean actif; // Soft delete } ``` - **Lifecycle Hooks**: `@PrePersist`, `@PreUpdate` for audit trail - **Immutability**: Use Lombok `@Builder` for construction - **Validation**: Jakarta Bean Validation annotations on fields #### 1.3 Repository Pattern - **Technology**: Hibernate Panache `PanacheRepositoryBase` - **Naming**: `{Entity}Repository` (e.g., `MembreRepository`) - **Custom Queries**: Native queries for complex business logic - **Pagination**: Use `Page` and `Sort` from Panache - **No Logic**: Repositories are ONLY for data access, no business rules #### 1.4 Service Pattern - **Naming**: `{Domain}Service` (e.g., `MembreService`, `CotisationService`) - **Transactions**: All mutating methods MUST be `@Transactional` - **Logging**: Use `Logger.getLogger(...)` for all service operations - **Error Handling**: Throw domain exceptions (`NotFoundException`, `IllegalArgumentException`) - **Security**: Inject `KeycloakService` for authorization checks --- ### 2. API/Implementation Separation - MANDATORY #### 2.1 Module Structure ``` unionflow/ β”œβ”€β”€ unionflow-server-api/ ← Pure Java 17, no dependencies β”‚ β”œβ”€β”€ dto/ β”‚ β”‚ β”œβ”€β”€ request/ ← Java records with validation β”‚ β”‚ └── response/ ← Java records (immutable DTOs) β”‚ └── enums/ ← Rich enums with business methods β”‚ └── unionflow-server-impl-quarkus/ ← Quarkus 3.15.1 implementation β”œβ”€β”€ entity/ ← JPA entities β”œβ”€β”€ repository/ ← Panache repositories β”œβ”€β”€ service/ ← Business logic β”œβ”€β”€ resource/ ← JAX-RS endpoints β”œβ”€β”€ mapper/ ← MapStruct mappers └── security/ ← Security config ``` #### 2.2 API Module Rules - βœ… **DO**: Use Java `record` for all DTOs (request/response) - βœ… **DO**: Use `@Builder` from Lombok for records - βœ… **DO**: Validation annotations (`@NotNull`, `@Size`, `@Pattern`, etc.) - ❌ **DON'T**: Any runtime dependencies (no Quarkus, no JPA) - ❌ **DON'T**: Mutable DTOs (records are immutable) **Example Request DTO:** ```java @Builder public record CreateMembreRequest( @NotBlank @Size(max = 100) String nom, @NotBlank @Size(max = 100) String prenom, @Email String email, @NotNull LocalDate dateNaissance ) {} ``` #### 2.3 Impl Module Rules - βœ… **DO**: Depend on `unionflow-server-api` for DTOs - βœ… **DO**: Use MapStruct for Entity ↔ DTO conversion - ❌ **DON'T**: Return entities directly from Resources (always map to DTOs) - ❌ **DON'T**: Accept entities in Resource methods (use DTOs) --- ### 3. Security - NON-NEGOTIABLE #### 3.1 Authentication & Authorization - **Provider**: Keycloak 23+ (OIDC/OAuth2) - **Realm**: `unionflow` - **Client**: `unionflow-mobile` (confidential) - **Token Type**: JWT (signed, encrypted) #### 3.2 JWT Validation Strategy | Layer | Validation | |-------|------------| | **Mobile** | Issuer (`iss`) + Expiry (`exp`) | | **Backend** | Signature verification + Claims extraction | **Rationale**: Mobile cannot verify JWT signatures securely (no secret storage), so backend is authoritative for signature validation. #### 3.3 Role-Based Access Control (RBAC) **Defined Roles** (in `SecurityConfig.Roles`): 1. `ADMIN` - Full system access 2. `PRESIDENT` - Organization management 3. `VICE_PRESIDENT` - Deputy authority 4. `TRESORIER` - Financial operations 5. `SECRETAIRE` - Administrative operations 6. `GESTIONNAIRE_MEMBRE` - Member management 7. `ORGANISATEUR_EVENEMENT` - Event management 8. `GESTIONNAIRE_SOLIDARITE` - Solidarity aid management 9. `AUDITEUR` - Read-only audit access 10. `MEMBRE` - Basic member access **Permission Checks**: ```java // In Services if (!keycloakService.hasRole("ADMIN") && !keycloakService.hasRole("GESTIONNAIRE_MEMBRE")) { throw new SecurityException("Insufficient permissions"); } // In Resources @RolesAllowed({"ADMIN", "TRESORIER"}) @GET public Response getFinancialData() { ... } ``` #### 3.4 RGPD Compliance - **Audit Trail**: All entities track `creePar`, `modifiePar`, dates - **Soft Delete**: Use `actif=false` instead of hard deletes - **Data Minimization**: Only collect necessary fields - **Right to be Forgotten**: Anonymization service (planned) - **Consent Management**: Explicit opt-in for communications #### 3.5 Transport Security - **HTTPS Only**: All external traffic via TLS 1.3+ - **Certificate Management**: Let's Encrypt + Cert-Manager (K8s) - **Ingress**: nginx ingress controller with SSL termination - **Mobile**: `network_security_config.xml` blocks cleartext HTTP --- ### 4. Data Management #### 4.1 Database Strategy - **Production**: PostgreSQL 15+ - **Testing**: H2 in-memory - **Schema Management**: Flyway migrations - **Connection Pooling**: HikariCP (via Quarkus) #### 4.2 Migration Policy - **Versioning**: `V{major}.{minor}__{description}.sql` - **Current**: `V2.0__create_all_37_entities.sql` - **Rules**: - ❌ NEVER modify existing migrations - βœ… Always create new migration for schema changes - βœ… Test migrations on staging before production - βœ… Migrations must be idempotent where possible #### 4.3 Primary Keys - **Type**: `UUID` (UUIDv4) - **Generation**: Database-generated (`gen_random_uuid()`) - **Foreign Keys**: Always use UUIDs - **Rationale**: Distributed system compatibility, no ID enumeration attacks #### 4.4 Optimistic Locking - **Field**: `@Version Long version` in `BaseEntity` - **Behavior**: Automatic conflict detection on concurrent updates - **Exception**: `OptimisticLockException` β†’ HTTP 409 Conflict --- ### 5. Quality Assurance #### 5.1 Test Coverage Requirements **JaCoCo Thresholds (STRICT - NO EXCEPTIONS):** - βœ… Instructions: **100%** - βœ… Branches: **100%** - βœ… Lines: **100%** - βœ… Methods: **100%** **Configuration:** ```xml INSTRUCTION1.00 BRANCH1.00 LINE1.00 METHOD1.00 true ``` **Exclusions**: NONE (including mappers, generated code) #### 5.2 Test Patterns **Service Tests:** ```java @QuarkusTest class MembreServiceTest { @Inject MembreService service; @BeforeEach void setup() { // Setup via service calls (own @Transactional) } @Test @TestTransaction // Rollback after test void testMethod() { ... } } ``` **Resource Tests:** ```java @QuarkusTest class MembreResourceTest { @Test @TestSecurity(user = "admin@test.com", roles = {"ADMIN"}) void testEndpoint() { given() .when().get("/api/membres") .then().statusCode(200); } } ``` **Entity Tests:** ```java class MembreTest { @Test void testPrePersist() { Membre m = new Membre(); // Invoke @PrePersist via reflection m.prePersist(); assertThat(m.getDateCreation()).isNotNull(); } } ``` #### 5.3 Test Organization - **Location**: `src/test/java` mirroring `src/main/java` structure - **Naming**: `{ClassName}Test.java` - **DisplayName**: French, descriptive (`@DisplayName("crΓ©e un membre valide")`) - **Assertions**: AssertJ (`assertThat(...).isNotNull()`) --- ### 6. Configuration Management #### 6.1 Environment Profiles | Profile | Purpose | DB | Keycloak | Logs | |---------|---------|----|----------|------| | **dev** | Local development | H2 | localhost:8180 | Console | | **test** | Automated tests | H2 | Mock (@TestSecurity) | Suppressed | | **staging** | Pre-production | PostgreSQL | staging.lions.dev | File + Console | | **prod** | Production | PostgreSQL | security.lions.dev | File only | #### 6.2 Configuration Hierarchy ``` 1. application.properties (defaults) 2. application-{profile}.properties (overrides) 3. Environment variables (highest priority) ``` **Example:** ```properties # application.properties quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/unionflow # application-prod.properties quarkus.datasource.jdbc.url=jdbc:postgresql://postgresql-service.postgresql.svc.cluster.local:5432/unionflow # Environment variable (highest priority) QUARKUS_DATASOURCE_JDBC_URL=jdbc:postgresql://custom-host:5432/unionflow ``` #### 6.3 Secrets Management - ❌ **NEVER** commit secrets to git - βœ… Use environment variables for production secrets - βœ… Use Kubernetes Secrets in K8s deployments - βœ… Use `.env` files locally (in `.gitignore`) **Example Kubernetes Secret:** ```yaml apiVersion: v1 kind: Secret metadata: name: unionflow-secrets type: Opaque data: keycloak-client-secret: database-password: ``` --- ### 7. Logging & Monitoring #### 7.1 Logging Standards **Levels:** - `ERROR`: System failures requiring immediate attention - `WARN`: Recoverable errors, deprecated usage - `INFO`: Business events (user login, payment, etc.) - `DEBUG`: Detailed diagnostic info (dev/staging only) - `TRACE`: Ultra-verbose (never in production) **Format:** ```java LOG.infof("Membre créé: ID=%s, Email=%s", membre.getId(), membre.getEmail()); LOG.warnf("Tentative d'accΓ¨s non autorisΓ©: User=%s, Resource=%s", user, resource); LOG.error("Erreur connexion base de donnΓ©es", exception); ``` #### 7.2 Production Logging - **File**: `/var/log/unionflow/app.log` (rotated daily) - **Console**: Disabled in production - **JSON Format**: For log aggregation (ELK stack) - **Sensitive Data**: NEVER log passwords, tokens, personal data #### 7.3 Metrics & Health - **Endpoints**: - `/q/health` - Health check - `/q/health/live` - Liveness probe - `/q/health/ready` - Readiness probe - `/q/metrics` - Prometheus metrics - **K8s Probes**: Configured for all 3 health endpoints --- ### 8. API Design #### 8.1 RESTful Conventions | Method | Path | Purpose | Status | |--------|------|---------|--------| | `GET` | `/api/membres` | List all | 200 | | `GET` | `/api/membres/{id}` | Get one | 200 / 404 | | `POST` | `/api/membres` | Create | 201 | | `PUT` | `/api/membres/{id}` | Full update | 200 / 404 | | `PATCH` | `/api/membres/{id}` | Partial update | 200 / 404 | | `DELETE` | `/api/membres/{id}` | Soft delete | 204 / 404 | #### 8.2 Response Formats **Success (200/201):** ```json { "id": "uuid", "nom": "Dupont", "prenom": "Jean", "email": "jean.dupont@example.com" } ``` **Error (4xx/5xx):** ```json { "timestamp": "2026-02-27T10:30:00Z", "status": 404, "error": "Not Found", "message": "Membre non trouvΓ© avec l'ID: {id}", "path": "/api/membres/{id}" } ``` #### 8.3 Pagination ``` GET /api/membres?page=0&size=20&sort=nom,asc ``` **Response Headers:** ``` X-Total-Count: 150 Link: ; rel="next" ``` #### 8.4 Versioning - **Strategy**: URL versioning (future) - **Current**: No versioning (v1 implicit) - **Future**: `/api/v2/membres` for breaking changes --- ### 9. Deployment & DevOps #### 9.1 Container Strategy - **Base Image**: `registry.access.redhat.com/ubi9/openjdk-17-runtime:1.20` - **Multi-stage Build**: Maven build β†’ JVM runtime - **Port**: 8080 (internal), 443 (external via ingress) - **Healthcheck**: `/q/health/live` every 30s #### 9.2 Kubernetes Deployment **Namespace Strategy:** - `applications` - User-facing apps (unionflow-server, lions-user-manager) - `infrastructure` - Supporting services (postgresql, keycloak) - `monitoring` - Observability (prometheus, grafana) **Resource Limits:** ```yaml resources: requests: memory: "512Mi" cpu: "250m" limits: memory: "1Gi" cpu: "1000m" ``` #### 9.3 Deployment Pipeline (lionsctl) ```bash lionsctl pipeline \ -u https://git.lions.dev/lionsdev/unionflow-server-impl-quarkus \ -b main \ -j 17 \ -e production \ -c k1 \ -p prod ``` **Steps:** 1. Clone from Gitea 2. `mvn clean package -Pprod` 3. `docker build -t registry.lions.dev/lionsdev/unionflow-server:{tag}` 4. `docker push registry.lions.dev/lionsdev/unionflow-server:{tag}` 5. `kubectl apply -f k8s/deployment.yaml` 6. Health check validation 7. Email notification #### 9.4 Rollback Strategy - **Version Tags**: Every build tagged with git commit SHA - **Immutable Images**: Never overwrite existing tags - **Rollback**: `kubectl rollout undo deployment/unionflow-server` --- ### 10. Code Conventions #### 10.1 Naming Conventions | Type | Convention | Example | |------|------------|---------| | **Packages** | `dev.lions.unionflow.server.{layer}` | `dev.lions.unionflow.server.service` | | **Classes** | PascalCase, singular | `MembreService`, `Cotisation` | | **Interfaces** | No `I` prefix | `Repository`, not `IRepository` | | **Methods** | camelCase, verb-first | `creerMembre()`, `trouverParId()` | | **Constants** | UPPER_SNAKE_CASE | `MAX_RETRY_ATTEMPTS` | | **Variables** | camelCase | `membre`, `listeMembres` | #### 10.2 Language - **Code**: English for technical terms (class names, method names) - **Business Domain**: French (`Membre`, `Cotisation`, `Adhesion`) - **Comments/Javadoc**: French - **Logs**: French - **Git Commits**: French **Rationale**: Business domain in French for client alignment, technical terms in English for global compatibility. #### 10.3 Lombok Usage **Allowed:** - `@Data` (entities) - `@Builder` (DTOs, entities) - `@Getter` / `@Setter` - `@NoArgsConstructor` / `@AllArgsConstructor` - `@Slf4j` (AVOID - use standard logger) **Forbidden:** - `@SneakyThrows` (hides exceptions) - `@Cleanup` (use try-with-resources) - `@val` (use explicit types) #### 10.4 Code Formatting - **Indentation**: 2 spaces (NOT tabs) - **Line Length**: 120 characters max - **Braces**: Always use braces, even for single-line if/for - **Import Order**: java.*, javax.*, jakarta.*, org.*, dev.lions.*, (blank), static imports --- ### 11. Error Handling #### 11.1 Exception Hierarchy ``` RuntimeException β”œβ”€β”€ IllegalArgumentException (400 Bad Request) β”œβ”€β”€ NotFoundException (404 Not Found) β”œβ”€β”€ SecurityException (403 Forbidden) β”œβ”€β”€ IllegalStateException (409 Conflict) └── UnsupportedOperationException (501 Not Implemented) ``` #### 11.2 Exception Mapping ```java @Provider public class GlobalExceptionMapper implements ExceptionMapper { @Override public Response toResponse(Exception e) { if (e instanceof NotFoundException) { return Response.status(404).entity(error(e)).build(); } // ... autres cas return Response.status(500).entity(error(e)).build(); } } ``` #### 11.3 Validation Errors ```java @POST public Response create(@Valid CreateMembreRequest request) { // Validation automatique par Jakarta Bean Validation // 400 Bad Request si validation Γ©choue } ``` --- ### 12. Performance #### 12.1 Database Performance - **Indexes**: On all foreign keys, frequently queried columns - **N+1 Queries**: Use `@EntityGraph` or JOIN FETCH - **Pagination**: ALWAYS paginate large result sets - **Connection Pool**: Min 5, Max 20 connections #### 12.2 Caching Strategy - **Level 1 Cache**: Hibernate session cache (automatic) - **Level 2 Cache**: Disabled (stateless REST API) - **Application Cache**: Caffeine for frequently accessed data (ex: roles, permissions) - **HTTP Cache**: `Cache-Control` headers for static resources #### 12.3 Query Optimization ```java // ❌ BAD - N+1 queries List membres = membreRepository.findAll(); membres.forEach(m -> m.getCotisations().size()); // Lazy load // βœ… GOOD - Single query with JOIN FETCH @Query("SELECT m FROM Membre m LEFT JOIN FETCH m.cotisations") List findAllWithCotisations(); ``` --- ### 13. Mobile Integration #### 13.1 Mobile App Configuration **Flutter Environment:** ```dart // lib/config/environment.dart abstract class AppConfig { static String get apiBaseUrl => const String.fromEnvironment('API_URL'); static String get keycloakUrl => const String.fromEnvironment('KEYCLOAK_URL'); static bool get enableLogging => const String.fromEnvironment('ENV') != 'prod'; } ``` **Build Command:** ```bash flutter build apk \ --dart-define=ENV=prod \ --dart-define=API_URL=https://api.lions.dev \ --dart-define=KEYCLOAK_URL=https://security.lions.dev ``` #### 13.2 OAuth2 Flow (Mobile) ``` 1. App β†’ Keycloak: Authorization request 2. User authenticates in browser 3. Keycloak β†’ App: Authorization code (via deep link) 4. App β†’ Backend: Exchange code for tokens 5. Backend validates, returns JWT 6. App stores JWT securely (flutter_secure_storage) ``` #### 13.3 Deep Link Configuration - **Scheme**: `dev.lions.unionflow-mobile://` - **Callback**: `dev.lions.unionflow-mobile://callback` - **Android**: Handled via `network_security_config.xml` - **iOS**: Handled via `Info.plist` --- ### 14. Change Management #### 14.1 Git Workflow - **Branches**: `main` (production), `develop` (integration), `feature/*`, `fix/*` - **Commits**: Conventional Commits format ``` type(scope): description [optional body] Co-Authored-By: Claude Sonnet 4.5 ``` - **Types**: `feat`, `fix`, `docs`, `refactor`, `test`, `chore` - **PR Required**: All merges to `main` require PR + review #### 14.2 Database Migrations **Process:** 1. Create migration: `V{version}__{description}.sql` 2. Test locally on H2 3. Test on staging PostgreSQL 4. Include in PR for review 5. Deploy to production with rollback plan #### 14.3 Breaking Changes **Definition**: Changes that break existing API contracts - ❌ Removing fields from DTOs - ❌ Changing field types - ❌ Removing endpoints - ❌ Changing authentication flow **Mitigation:** 1. Version the API (`/api/v2/...`) 2. Deprecate old version with 6-month sunset 3. Communicate to mobile team 3 months in advance --- ### 15. Documentation #### 15.1 Required Documentation - βœ… **OpenAPI/Swagger**: Auto-generated from JAX-RS annotations - βœ… **Javadoc**: All public methods in Services - βœ… **README.md**: Per-module setup instructions - βœ… **CONSTITUTION.md**: This document - βœ… **CHANGELOG.md**: Release notes #### 15.2 API Documentation **Access**: `https://api.lions.dev/unionflow/q/swagger-ui` **Annotations:** ```java @Path("/membres") @Tag(name = "Membres", description = "Gestion des membres") public class MembreResource { @GET @Operation(summary = "Liste tous les membres") @APIResponse(responseCode = "200", description = "SuccΓ¨s") public Response list() { ... } } ``` --- ### 16. Compliance & Governance #### 16.1 RGPD Requirements - **Data Minimization**: Only collect necessary data - **Purpose Limitation**: Use data only for stated purposes - **Storage Limitation**: Delete data after retention period - **Accuracy**: Allow users to update their data - **Integrity**: Encrypt data at rest and in transit - **Confidentiality**: Role-based access control #### 16.2 Audit Trail **Tracked Fields:** - `creePar` - User who created the record - `modifiePar` - User who last modified - `dateCreation` - Creation timestamp - `dateModification` - Last modification timestamp **Retention**: 7 years minimum (legal requirement for associations) #### 16.3 Data Retention Policy | Data Type | Retention Period | Action After | |-----------|------------------|--------------| | **Member Data** | Active + 2 years | Anonymize | | **Financial Records** | 10 years | Archive | | **Audit Logs** | 7 years | Archive | | **Session Tokens** | 24 hours | Delete | --- ## πŸ”„ Amendment Process This constitution is a living document. Amendments require: 1. **Proposal**: Submit PR with changes to `CONSTITUTION.md` 2. **Discussion**: Team review (minimum 3 business days) 3. **Approval**: Unanimous approval from tech leads 4. **Implementation**: Update dependent documentation 5. **Communication**: Announce changes to all teams **Version History:** - v1.0 (2026-02-27): Initial constitution --- ## πŸ“ž Contacts & Resources - **Tech Lead**: [Γ€ dΓ©finir] - **Repository**: `https://git.lions.dev/lionsdev/unionflow-server-impl-quarkus` - **Documentation**: `https://docs.lions.dev/unionflow` - **Deployment Tool**: `lionsctl` (`lions-infrastructure-2025/lionsctl/`) - **Support**: `support@lions.dev` --- **Last Updated**: 2026-02-27 **Next Review**: 2026-05-27 (quarterly review)