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
This commit is contained in:
dahoud
2026-02-27 14:41:07 +00:00
parent 144b68f8e7
commit b1957c1c81
631 changed files with 104070 additions and 0 deletions

737
unionflow/CONSTITUTION.md Normal file
View File

@@ -0,0 +1,737 @@
# 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<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:**
```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
<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:**
```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: <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:**
```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: </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:**
```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<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
```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<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:**
```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 <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:**
```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)