Files
unionflow-server-api/unionflow/CONSTITUTION.md
dahoud b1957c1c81 feat(unionflow): ajout Spec-Kit, constitution, mission mutuelles
- Config Spec-Kit pour Spec-Driven Development
- CONSTITUTION.md + .specify/memory/constitution.md
- Commandes Cursor /speckit.*, règles projet
- Mission: associations + mutuelles d'épargne et de financement
- .gitignore: versionner config spec-kit unionflow

Made-with: Cursor
2026-02-27 14:41:07 +00:00

22 KiB

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
    @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<Entity, UUID>
  • 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:

@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:

// 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:

<rules>
  <rule><limits>
    <limit><counter>INSTRUCTION</counter><minimum>1.00</minimum></limit>
    <limit><counter>BRANCH</counter><minimum>1.00</minimum></limit>
    <limit><counter>LINE</counter><minimum>1.00</minimum></limit>
    <limit><counter>METHOD</counter><minimum>1.00</minimum></limit>
  </limits></rule>
</rules>
<haltOnFailure>true</haltOnFailure>

Exclusions: NONE (including mappers, generated code)

5.2 Test Patterns

Service Tests:

@QuarkusTest
class MembreServiceTest {
    @Inject MembreService service;

    @BeforeEach
    void setup() {
        // Setup via service calls (own @Transactional)
    }

    @Test
    @TestTransaction  // Rollback after test
    void testMethod() { ... }
}

Resource Tests:

@QuarkusTest
class MembreResourceTest {
    @Test
    @TestSecurity(user = "admin@test.com", roles = {"ADMIN"})
    void testEndpoint() {
        given()
            .when().get("/api/membres")
            .then().statusCode(200);
    }
}

Entity Tests:

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:

# 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:

apiVersion: v1
kind: Secret
metadata:
  name: unionflow-secrets
type: Opaque
data:
  keycloak-client-secret: <base64>
  database-password: <base64>

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:

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):

{
  "id": "uuid",
  "nom": "Dupont",
  "prenom": "Jean",
  "email": "jean.dupont@example.com"
}

Error (4xx/5xx):

{
  "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: </api/membres?page=1&size=20>; 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:

resources:
  requests:
    memory: "512Mi"
    cpu: "250m"
  limits:
    memory: "1Gi"
    cpu: "1000m"

9.3 Deployment Pipeline (lionsctl)

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

@Provider
public class GlobalExceptionMapper implements ExceptionMapper<Exception> {
    @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

@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

// ❌ BAD - N+1 queries
List<Membre> 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<Membre> findAllWithCotisations();

13. Mobile Integration

13.1 Mobile App Configuration

Flutter Environment:

// 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:

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)
  • 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 <noreply@anthropic.com>
    
  • 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:

@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)