NeahNew/MISSIONS_CENTRALE_WORKFLOW_ANALYSIS.md
2026-01-04 12:51:58 +01:00

931 lines
25 KiB
Markdown

# Analyse Complète : Pages Missions et Centrale - Workflow Complet
## 📋 Table des Matières
1. [Vue d'ensemble](#vue-densemble)
2. [Architecture des Pages](#architecture-des-pages)
3. [Workflow de Navigation](#workflow-de-navigation)
4. [Workflow de Création de Mission](#workflow-de-création-de-mission)
5. [Workflow de Consultation](#workflow-de-consultation)
6. [API Routes](#api-routes)
7. [Base de Données](#base-de-données)
8. [Intégrations Externes](#intégrations-externes)
9. [Stockage de Fichiers](#stockage-de-fichiers)
10. [Composants Réutilisables](#composants-réutilisables)
---
## 🎯 Vue d'ensemble
### Page "Centrale"
- **Route**: `/missions`
- **Nom dans le menu**: "Centrale"
- **Accès**: Rôles `entrepreneurship` ou `admin` (défini dans `components/main-nav.tsx`)
- **Description**: Centre d'Administration et de Pilotage (CAP) - Interface principale pour gérer les missions
### Page "Missions"
- **Route principale**: `/missions`
- **Sous-routes**:
- `/missions` - Liste des missions de l'utilisateur
- `/missions/new` - Création d'une nouvelle mission
- `/missions/[missionId]` - Détails d'une mission
- `/missions/[missionId]/edit` - Édition d'une mission
### Page "Mission Tab" (Tableau des Missions)
- **Route**: `/mission-tab`
- **Description**: Vue publique de toutes les missions disponibles
- **Sous-routes**:
- `/mission-tab` - Liste de toutes les missions
- `/mission-tab/[missionId]` - Détails d'une mission (vue publique)
---
## 🏗️ Architecture des Pages
### 1. Layout Principal - Missions (`app/missions/layout.tsx`)
**Structure**:
```
┌─────────────────────────────────────────┐
│ Sidebar (CAP) - Fond rose clair │
│ ┌───────────────────────────────────┐ │
│ │ CAP │ │
│ │ Centre d'Administration et de │ │
│ │ Pilotage │ │
│ └───────────────────────────────────┘ │
│ • Mes Missions (/missions) │
│ • Nouvelle Mission (/missions/new) │
└─────────────────────────────────────────┘
│ Contenu Principal (children) │
└─────────────────────────────────────────┘
```
**Fonctionnalités**:
- Sidebar fixe avec navigation
- Fond rose clair (`bg-pink-50`) pour la sidebar
- Fond blanc pour le contenu principal
- Navigation active highlightée
### 2. Page Liste des Missions (`app/missions/page.tsx`)
**Fonctionnalités**:
- Affichage en grille (responsive: 1/2/3 colonnes)
- Recherche par nom, niveau, type, ODD scope
- Filtrage en temps réel
- Cartes de mission avec:
- Logo (ou initiales si pas de logo)
- Nom de la mission
- Badge niveau (A/B/C/S) avec couleurs
- Icône ODD (Objectifs de Développement Durable)
- Services associés
- Description (intention) tronquée
- Date de création
- Bouton "Voir détails"
**API utilisée**: `GET /api/missions`
- Retourne uniquement les missions où l'utilisateur est:
- Créateur (`creatorId`)
- Ou membre (`missionUsers`)
### 3. Page Création de Mission (`app/missions/new/page.tsx`)
**Composant principal**: `MissionsAdminPanel`
- Formulaire multi-onglets (5 onglets)
- Navigation séquentielle avec boutons Précédent/Suivant
### 4. Page Détails Mission (`app/missions/[missionId]/page.tsx`)
**Fonctionnalités**:
- Affichage complet des informations
- Logo de la mission
- Grille d'informations (Type, Donneur d'ordre, Durée, Niveau, Participation, ODD)
- Description complète
- Liste des documents/attachments
- Profils recherchés
- Services
- Bouton de suppression (si créateur ou admin)
**API utilisée**: `GET /api/missions/[missionId]`
### 5. Page Mission Tab (`app/mission-tab/page.tsx`)
**Différences avec `/missions`**:
- Affiche **TOUTES** les missions (pas de filtre utilisateur)
- API utilisée: `GET /api/missions/all`
- Vue publique pour découvrir toutes les missions disponibles
---
## 🔄 Workflow de Navigation
### Accès à la Centrale
```
1. Utilisateur connecté avec rôle "entrepreneurship" ou "admin"
2. Menu déroulant utilisateur (MainNav)
3. Clic sur "Centrale" (href: '/missions')
4. Redirection vers /missions
5. Layout Missions s'affiche avec sidebar CAP
6. Page Liste des Missions (/missions/page.tsx)
```
### Navigation dans la Centrale
```
┌─────────────────────────────────────────┐
│ Sidebar CAP │
│ ├─ Mes Missions (/missions) │
│ └─ Nouvelle Mission (/missions/new) │
└─────────────────────────────────────────┘
│ │
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────┐
│ Liste Missions │ │ Création Mission │
│ │ │ │
│ [Carte Mission] │ │ [Formulaire] │
│ └─► Détails │ │ │
└─────────────────┘ └──────────────────┘
┌─────────────────┐
│ Détails Mission │
│ │
│ [Éditer] │
│ [Supprimer] │
└─────────────────┘
```
---
## 🚀 Workflow de Création de Mission
### Étape 1: Accès au Formulaire
```
User → /missions/new → MissionsAdminPanel
```
### Étape 2: Formulaire Multi-Onglets
**Onglet 1: General**
- Nom de la mission (requis)
- Logo (upload)
- ODD scope (requis) - Sélection parmi 17 ODD
- Niveau (requis) - A/B/C/S
- Intention (requis) - Description avec éditeur de texte
**Onglet 2: Details**
- Type de mission (requis) - Remote/Onsite/Hybrid
- Donneur d'ordre (requis) - Individu/ONG/Start-ups
- Projection (requis) - Short/Medium/Long term
- Services - Checkboxes (Gite, ArtLab, Calcul)
- Participation (requis) - Volontaire/Cooptation
- Profils - Checkboxes (DataIntelligence, Expression, Mediation, Investigation, Coding, Lean)
**Onglet 3: Attachments**
- Upload de fichiers (PDF, DOC, DOCX, XLS, XLSX, JPG, JPEG, PNG)
- Liste des fichiers sélectionnés
- Upload immédiat vers Minio (bucket 'missions')
**Onglet 4: Skills**
- Liste de compétences (non fonctionnel actuellement - placeholders)
**Onglet 5: Membres**
- **Les Gardiens de l'Intention** (3 gardiens requis):
- Gardien du Temps
- Gardien de la Parole
- Gardien de la Mémoire
- **Volontaires** (optionnel)
- Recherche d'utilisateurs ou groupes
- Assignation de rôles
### Étape 3: Validation et Soumission
**Validation**:
```typescript
const requiredFields = {
name: !!missionData.name,
oddScope: Array.isArray(missionData.oddScope) && missionData.oddScope.length > 0,
niveau: !!missionData.niveau,
intention: !!missionData.intention,
missionType: !!missionData.missionType,
donneurDOrdre: !!missionData.donneurDOrdre,
projection: !!missionData.projection,
participation: !!missionData.participation,
gardiens: gardienDuTemps !== null &&
gardienDeLaParole !== null &&
gardienDeLaMemoire !== null
}
```
**Soumission**:
```typescript
POST /api/missions
Body: {
name, oddScope, niveau, intention, missionType,
donneurDOrdre, projection, services, profils,
participation, guardians, volunteers, logo, attachments
}
```
### Étape 4: Traitement Backend
**Séquence d'exécution**:
1. **Création de la mission en base de données**
```typescript
prisma.mission.create({
data: { name, oddScope, niveau, intention, ... }
})
```
2. **Création des MissionUsers (gardiens + volontaires)**
```typescript
prisma.missionUser.createMany({
data: [
{ missionId, userId, role: 'gardien-temps' },
{ missionId, userId, role: 'gardien-parole' },
{ missionId, userId, role: 'gardien-memoire' },
{ missionId, userId, role: 'volontaire' }, // pour chaque volontaire
]
})
```
3. **Upload du logo vers Minio**
- Path: `missions/{missionId}/logo{extension}`
- Bucket: `missions`
- Mise à jour du champ `logo` dans la mission
4. **Upload des attachments vers Minio**
- Path: `missions/{missionId}/attachments/{filename}`
- Création des enregistrements `Attachment` en base
5. **Vérification des fichiers dans Minio**
- Vérifie que tous les fichiers sont bien présents avant de continuer
6. **Déclenchement du workflow N8N**
```typescript
n8nService.triggerMissionCreation({
...missionData,
creatorId,
logoPath,
config: { N8N_API_KEY, MISSION_API_URL }
})
```
7. **Intégrations externes (via N8N)**:
- Création projet Leantime (si applicable)
- Création collection Outline (si applicable)
- Création canal RocketChat (si applicable)
- Création repository Gitea (si applicable)
- Création projet Penpot (si applicable)
8. **Retour succès/erreur**
- Si succès: Redirection vers `/missions`
- Si erreur: Nettoyage des fichiers uploadés + message d'erreur
---
## 👀 Workflow de Consultation
### Consultation Liste des Missions
**Route**: `/missions` ou `/mission-tab`
**Flux**:
```
1. Chargement de la page
2. useEffect → fetch('/api/missions') ou fetch('/api/missions/all')
3. Affichage du loader
4. Réception des données
5. Transformation des données:
- Ajout des logoUrl (si logo existe)
- Formatage des dates
- Calcul des couleurs de badges
- Extraction des infos ODD
6. Filtrage par terme de recherche (si présent)
7. Affichage en grille
```
**Recherche**:
- Filtre en temps réel sur: nom, niveau, type, ODD scope
- Pas de requête API supplémentaire (filtrage côté client)
### Consultation Détails Mission
**Route**: `/missions/[missionId]` ou `/mission-tab/[missionId]`
**Flux**:
```
1. Chargement de la page
2. Récupération du missionId depuis les params
3. useEffect → fetch(`/api/missions/${missionId}`)
4. Affichage du loader
5. Réception des données complètes:
- Mission avec tous les champs
- Creator (id, email)
- MissionUsers (avec user details)
- Attachments (avec publicUrl)
6. Transformation:
- Ajout des logoUrl
- Formatage des dates
- Labels pour les types/niveaux
- URLs publiques pour les attachments
7. Affichage des sections:
- Header avec nom et logo
- Grille d'informations
- Description
- Documents
- Profils recherchés
- Services
- Actions (Éditer/Supprimer)
```
---
## 🔌 API Routes
### 1. `GET /api/missions`
**Fichier**: `app/api/missions/route.ts`
**Fonctionnalité**: Liste les missions de l'utilisateur connecté
**Filtres**:
- `limit` (default: 10)
- `offset` (default: 0)
- `search` (recherche dans name et intention)
- `name` (filtre exact)
**Where Clause**:
```typescript
{
OR: [
{ creatorId: userId },
{ missionUsers: { some: { userId } } }
]
}
```
**Retour**:
```json
{
"missions": [
{
"id": "...",
"name": "...",
"logo": "missions/{id}/logo.png",
"logoUrl": "/api/missions/image/missions/{id}/logo.png",
"oddScope": ["odd-3"],
"niveau": "a",
"missionType": "remote",
"projection": "short",
"services": ["Gite"],
"intention": "...",
"createdAt": "...",
"creator": { "id": "...", "email": "..." },
"missionUsers": [...],
"attachments": [...]
}
],
"pagination": {
"total": 10,
"offset": 0,
"limit": 10
}
}
```
### 2. `POST /api/missions`
**Fichier**: `app/api/missions/route.ts`
**Fonctionnalité**: Crée une nouvelle mission
**Body**:
```typescript
{
name: string;
oddScope: string[];
niveau?: string;
intention?: string;
missionType?: string;
donneurDOrdre?: string;
projection?: string;
services?: string[];
profils?: string[];
participation?: string;
guardians?: {
"gardien-temps": string;
"gardien-parole": string;
"gardien-memoire": string;
};
volunteers?: string[];
logo?: {
data: string; // base64
name?: string;
type?: string;
};
attachments?: Array<{
data: string; // base64
name?: string;
type?: string;
}>;
}
```
**Retour**:
```json
{
"success": true,
"mission": { ... },
"message": "Mission created successfully with all integrations"
}
```
### 3. `GET /api/missions/[missionId]`
**Fichier**: `app/api/missions/[missionId]/route.ts`
**Fonctionnalité**: Récupère les détails d'une mission
**Contrôle d'accès**:
- Utilisateur doit être créateur OU membre de la mission
**Retour**: Mission complète avec relations
### 4. `PUT /api/missions/[missionId]`
**Fichier**: `app/api/missions/[missionId]/route.ts`
**Fonctionnalité**: Met à jour une mission
**Contrôle d'accès**:
- Créateur OU gardien-temps/gardien-parole
**Body**: Même structure que POST (tous les champs optionnels)
### 5. `DELETE /api/missions/[missionId]`
**Fichier**: `app/api/missions/[missionId]/route.ts`
**Fonctionnalité**: Supprime une mission
**Contrôle d'accès**:
- Créateur OU admin uniquement
**Actions**:
- Suppression du logo dans Minio
- Suppression de la mission en base (cascade sur MissionUsers et Attachments)
- TODO: Rollback N8N (non implémenté)
### 6. `GET /api/missions/all`
**Fichier**: `app/api/missions/all/route.ts`
**Fonctionnalité**: Liste TOUTES les missions (pas de filtre utilisateur)
**Différences avec `/api/missions`**:
- Pas de filtre par utilisateur
- Retourne toutes les missions publiques
- Utilisé par `/mission-tab`
### 7. `GET /api/missions/image/[...path]`
**Fichier**: `app/api/missions/image/[...path]/route.ts`
**Fonctionnalité**: Sert les images (logos et attachments) depuis Minio
**Path**: `missions/{missionId}/logo.png` ou `missions/{missionId}/attachments/{filename}`
### 8. `POST /api/missions/upload`
**Fichier**: `app/api/missions/upload/route.ts`
**Fonctionnalité**: Upload de fichiers (logo ou attachments)
### 9. `GET /api/missions/[missionId]/attachments`
**Fichier**: `app/api/missions/[missionId]/attachments/route.ts`
**Fonctionnalité**: Liste les attachments d'une mission
### 10. `POST /api/missions/[missionId]/attachments`
**Fichier**: `app/api/missions/[missionId]/attachments/route.ts`
**Fonctionnalité**: Ajoute un attachment à une mission existante
### 11. `DELETE /api/missions/[missionId]/attachments/[attachmentId]`
**Fichier**: `app/api/missions/[missionId]/attachments/[attachmentId]/route.ts`
**Fonctionnalité**: Supprime un attachment
---
## 🗄️ Base de Données
### Modèle Mission (`prisma/schema.prisma`)
```prisma
model Mission {
id String @id @default(uuid())
name String
logo String? // Path dans Minio
oddScope String[] // Catégories ODD
niveau String // A/B/C/S
intention String // Description
missionType String // remote/onsite/hybrid
donneurDOrdre String // individual/group/organization
projection String // short/medium/long
services String[] // ["Gite", "ArtLab", "Calcul"]
participation String? // volontaire/cooptation
profils String[] // ["DataIntelligence", ...]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
creator User @relation(fields: [creatorId], references: [id])
creatorId String
attachments Attachment[]
missionUsers MissionUser[]
// Intégrations externes
leantimeProjectId String?
outlineCollectionId String?
rocketChatChannelId String?
giteaRepositoryUrl String?
penpotProjectId String?
@@index([creatorId])
}
```
### Modèle MissionUser
```prisma
model MissionUser {
id String @id @default(uuid())
role String // 'gardien-temps', 'gardien-parole', 'gardien-memoire', 'volontaire'
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
mission Mission @relation(fields: [missionId], references: [id])
missionId String
user User @relation(fields: [userId], references: [id])
userId String
@@unique([missionId, userId, role])
@@index([missionId])
@@index([userId])
}
```
### Modèle Attachment
```prisma
model Attachment {
id String @id @default(uuid())
filename String
filePath String // Path dans Minio: missions/{missionId}/attachments/{filename}
fileType String // MIME type
fileSize Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
mission Mission @relation(fields: [missionId], references: [id])
missionId String
uploader User @relation(fields: [uploaderId], references: [id])
uploaderId String
@@index([missionId])
@@index([uploaderId])
}
```
---
## 🔗 Intégrations Externes
### Service N8N (`lib/services/n8n-service.ts`)
**Webhook URL**: `https://brain.slm-lab.net/webhook/mission-created`
**Données envoyées**:
```typescript
{
name, oddScope, niveau, intention, missionType,
donneurDOrdre, projection, services, participation,
profils, guardians, volunteers, creatorId,
config: {
N8N_API_KEY,
MISSION_API_URL
}
}
```
**Workflow N8N déclenche**:
1. Création projet Leantime (si applicable)
2. Création collection Outline (si applicable)
3. Création canal RocketChat (si applicable)
4. Création repository Gitea (si applicable)
5. Création projet Penpot (si applicable)
**Retour**:
```typescript
{
success: boolean;
results?: {
leantimeProjectId?: string;
outlineCollectionId?: string;
rocketChatChannelId?: string;
giteaRepositoryUrl?: string;
penpotProjectId?: string;
failedServices?: {
gitRepo?: boolean;
leantimeProject?: boolean;
docCollection?: boolean;
rocketChatChannel?: boolean;
}
};
error?: string;
}
```
**Rollback** (non implémenté):
- Webhook: `https://brain.slm-lab.net/webhook/mission-rollback`
- Appelé lors de la suppression d'une mission
---
## 📦 Stockage de Fichiers
### Minio Configuration
**Endpoint**: `https://dome-api.slm-lab.net`
**Bucket**: `missions`
**Credentials**: Hardcodés dans `lib/mission-uploads.ts` (⚠️ à sécuriser)
### Structure des Chemins
**Logo**:
```
missions/{missionId}/logo{extension}
Exemple: missions/abc-123/logo.png
```
**Attachments**:
```
missions/{missionId}/attachments/{filename}
Exemple: missions/abc-123/attachments/document.pdf
```
### URLs Publiques
**Format**: `/api/missions/image/{path}`
**Exemples**:
- Logo: `/api/missions/image/missions/{missionId}/logo.png`
- Attachment: `/api/missions/image/missions/{missionId}/attachments/document.pdf`
### Fonctions Utilitaires (`lib/mission-uploads.ts`)
- `getMissionLogoPath()` - Génère le chemin du logo
- `getMissionAttachmentPath()` - Génère le chemin d'un attachment
- `uploadMissionLogo()` - Upload un logo vers Minio
- `uploadMissionAttachment()` - Upload un attachment vers Minio
- `deleteMissionLogo()` - Supprime un logo (TODO)
- `deleteMissionAttachment()` - Supprime un attachment
- `getMissionFileUrl()` - Construit l'URL publique
- `ensureMissionsPrefix()` - Normalise le chemin
---
## 🧩 Composants Réutilisables
### 1. `MissionsAdminPanel` (`components/missions/missions-admin-panel.tsx`)
**Fonctionnalités**:
- Formulaire multi-onglets
- Gestion des gardiens et volontaires
- Upload de fichiers
- Validation complète
- Soumission vers API
**Props**: Aucune (composant autonome)
**State**:
- `missionData` - Données de la mission
- `selectedServices` - Services sélectionnés
- `selectedProfils` - Profils sélectionnés
- `gardienDuTemps`, `gardienDeLaParole`, `gardienDeLaMemoire` - IDs des gardiens
- `volontaires` - Array d'IDs de volontaires
- `activeTab` - Onglet actif
- `isSubmitting` - État de soumission
### 2. `FileUpload` (`components/missions/file-upload.tsx`)
**Fonctionnalités**:
- Upload de logo ou attachment
- Conversion en base64
- Preview pour les images
**Props**:
- `type`: 'logo' | 'attachment'
- `isNewMission`: boolean
- `onFileSelect`: (fileData) => void
### 3. `AttachmentsList` (`components/missions/attachments-list.tsx`)
**Fonctionnalités**:
- Liste des attachments d'une mission
- Upload de nouveaux attachments
- Suppression d'attachments
**Props**:
- `missionId`: string
- `allowUpload`: boolean
- `allowDelete`: boolean
### 4. `MissionsFrame` (`components/missions/missions-frame.tsx`)
**Fonctionnalités**: Wrapper iframe (non utilisé actuellement)
---
## 🔐 Contrôles d'Accès
### Page Centrale (`/missions`)
- **Rôles requis**: `entrepreneurship` ou `admin`
- Vérifié dans `components/main-nav.tsx` via `hasRole()`
### API Routes
- **Authentification**: Session NextAuth requise
- **GET /api/missions**: Missions où user est créateur ou membre
- **GET /api/missions/all**: Toutes les missions (authentifié)
- **GET /api/missions/[id]**: Créateur ou membre
- **PUT /api/missions/[id]**: Créateur ou gardien-temps/gardien-parole
- **DELETE /api/missions/[id]**: Créateur ou admin uniquement
---
## 📊 Flux de Données Complet
### Création de Mission
```
[Frontend]
MissionsAdminPanel
↓ (soumission)
POST /api/missions
[Backend]
1. Validation
2. prisma.mission.create()
3. prisma.missionUser.createMany()
4. uploadMissionLogo() → Minio
5. uploadMissionAttachment() → Minio (pour chaque attachment)
6. prisma.attachment.create() (pour chaque attachment)
7. verifyFileExists() (vérification Minio)
8. n8nService.triggerMissionCreation()
[N8N Workflow]
- Création Leantime
- Création Outline
- Création RocketChat
- Création Gitea
- Création Penpot
[Backend]
9. Retour succès/erreur
[Frontend]
Redirection → /missions
```
### Consultation de Mission
```
[Frontend]
MissionsPage ou MissionDetailPage
fetch('/api/missions') ou fetch('/api/missions/[id]')
[Backend]
1. Vérification session
2. Query Prisma avec relations
3. Transformation des paths en URLs publiques
4. Retour JSON
[Frontend]
Affichage des données
```
### Affichage d'Image
```
[Frontend]
<img src="/api/missions/image/missions/{id}/logo.png" />
[Backend]
GET /api/missions/image/[...path]
Lecture depuis Minio
Stream vers client
```
---
## 🎨 Styles et UI
### Couleurs des Badges Niveau
- **A (Apprentissage)**: `bg-green-100 text-green-800`
- **B (Basique)**: `bg-blue-100 text-blue-800`
- **C (Complexe)**: `bg-purple-100 text-purple-800`
- **S (Spécial)**: `bg-amber-100 text-amber-800`
### Layout Sidebar CAP
- **Fond**: `bg-pink-50`
- **Bordure**: `border-pink-100`
- **Largeur**: `234px` fixe
### Grille de Missions
- **Mobile**: 1 colonne
- **Tablet**: 2 colonnes (`md:grid-cols-2`)
- **Desktop**: 3 colonnes (`lg:grid-cols-3`)
---
## 🐛 Points d'Attention
1. **Credentials Minio hardcodés** dans `lib/mission-uploads.ts` - À déplacer vers variables d'environnement
2. **Rollback N8N non implémenté** lors de la suppression
3. **Skills tab non fonctionnel** - Placeholders uniquement
4. **Presigned URLs non implémentées** - Upload direct uniquement
5. **Gestion d'erreurs N8N** - Partielle (continue même si certaines intégrations échouent)
---
## 📝 Notes Techniques
### Types TypeScript
**Mission Interface** (utilisée dans les pages):
```typescript
interface Mission {
id: string;
name: string;
logo?: string;
logoUrl?: string;
oddScope: string[];
niveau: string;
missionType: string;
projection: string;
participation?: string;
services?: string[];
profils?: string[];
intention?: string;
donneurDOrdre?: string;
createdAt: string;
creator: User;
missionUsers: MissionUser[];
attachments?: Attachment[];
}
```
### Validation
**Côté Frontend**: Validation dans `MissionsAdminPanel.validateMission()`
**Côté Backend**: Validation minimale (name et oddScope requis)
### Gestion d'Erreurs
- **Frontend**: Toast notifications via `useToast()`
- **Backend**: Retour JSON avec `error` et `details`
- **N8N**: Retour avec `success` et `failedServices` pour erreurs partielles
---
## 🔄 Évolutions Possibles
1. **Pagination** côté client pour les listes
2. **Filtres avancés** (par niveau, type, ODD, etc.)
3. **Recherche full-text** dans l'intention
4. **Export** des missions (PDF, CSV)
5. **Notifications** lors de l'assignation à une mission
6. **Statistiques** des missions
7. **Timeline** des activités d'une mission
8. **Commentaires** sur les missions
9. **États** des missions (brouillon, publiée, terminée, etc.)
10. **Permissions granulaires** par rôle de gardien
---
**Document généré le**: $(date)
**Version**: 1.0
**Auteur**: Analyse automatique du codebase