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:
737
unionflow/.specify/memory/constitution.md
Normal file
737
unionflow/.specify/memory/constitution.md
Normal 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)
|
||||
Reference in New Issue
Block a user