fix: aligne le référentiel d'émotions sur le sujet et complète le dossier
Référentiel d'émotions (conformité au sujet) : - 6 émotions de base (suppression d'« Amour ») et 36 sous-émotions - libellés exacts du sujet (Surprise dédupliquée : Étonnement listé 2x) - propagation du décompte 6+36 (CLAUDE.md, plan oral, slides, dossier, mobile) Corrections dossier (grille d'évaluation Bloc INFCDAAL1) : - ajout d'un sommaire - contraintes budget 75 000 EUR et délai 12 mois (chiffres du sujet) - table des parties prenantes et de leur communication (§4.1) - mockup du module Informations (les 3 modules ont désormais une maquette) - cardinalités du MCD agrandies et lisibles - chiffrement reformulé honnêtement (bcrypt aujourd'hui, AES-256 prévu en prod HDS) - dossier maintenu à 20 pages (limite respectée) Vérifs : backend 15 tests, mobile tsc 0, seeder 6+36. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
@@ -48,8 +48,8 @@ Cesizen/
|
|||||||
| Configurer les émotions (2 niveaux) | Admin | ✅ | N/A |
|
| Configurer les émotions (2 niveaux) | Admin | ✅ | N/A |
|
||||||
|
|
||||||
### Hiérarchie des émotions (seed)
|
### Hiérarchie des émotions (seed)
|
||||||
7 émotions de base (niveau 1) avec 33 sous-émotions (niveau 2) :
|
6 émotions de base (niveau 1) avec 36 sous-émotions (niveau 2), conformes au référentiel du sujet :
|
||||||
Joie, Tristesse, Colère, Peur, Dégoût, Surprise, Amour.
|
Joie, Colère, Peur, Tristesse, Surprise, Dégoût.
|
||||||
|
|
||||||
## Grille de priorisation des besoins
|
## Grille de priorisation des besoins
|
||||||
Critères utilisés : Complexité (0-3), Valeur ajoutée Ministère (0-3), Valeur ajoutée Utilisateur (0-3), Nécessité (0-2), Interdépendance (0-2). Total sur 15.
|
Critères utilisés : Complexité (0-3), Valeur ajoutée Ministère (0-3), Valeur ajoutée Utilisateur (0-3), Nécessité (0-2), Interdépendance (0-2). Total sur 15.
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
| **0:00 – 2:00** (2′) | 1 — 2 | **Introduction** | Se présenter. Annoncer le commanditaire (Ministère) et l'objet : une plateforme grand public de santé mentale. Donner le fil rouge : « je vais dérouler le recueil du besoin, la priorisation, la réponse fonctionnelle, puis la modélisation technique et la conformité RGPD. » Présenter le sommaire (slide 2). |
|
| **0:00 – 2:00** (2′) | 1 — 2 | **Introduction** | Se présenter. Annoncer le commanditaire (Ministère) et l'objet : une plateforme grand public de santé mentale. Donner le fil rouge : « je vais dérouler le recueil du besoin, la priorisation, la réponse fonctionnelle, puis la modélisation technique et la conformité RGPD. » Présenter le sommaire (slide 2). |
|
||||||
| **2:00 – 5:00** (3′) | 3 — 4 | **Contexte, enjeux, parties prenantes** | Rappeler l'enjeu sociétal (22 % des Français, SPF 2023) et la stigmatisation. Énoncer les 4 objectifs stratégiques. Présenter les parties prenantes et les 3 acteurs (Visiteur, Utilisateur, Administrateur). Insister : « le besoin a été **reformulé**, pas recopié. » |
|
| **2:00 – 5:00** (3′) | 3 — 4 | **Contexte, enjeux, parties prenantes** | Rappeler l'enjeu sociétal (22 % des Français, SPF 2023) et la stigmatisation. Énoncer les 4 objectifs stratégiques. Présenter les parties prenantes et les 3 acteurs (Visiteur, Utilisateur, Administrateur). Insister : « le besoin a été **reformulé**, pas recopié. » |
|
||||||
| **5:00 – 7:00** (2′) | 5 — 6 | **Besoins & priorisation** | Périmètre : 2 modules obligatoires + Tracker au choix ; modules écartés assumés. Présenter la grille pondérée /15 (5 critères). Conclusion argumentée : « le Tracker cumule 4 fonctionnalités à 9-10/15, c'est le module au choix le plus rentable. » |
|
| **5:00 – 7:00** (2′) | 5 — 6 | **Besoins & priorisation** | Périmètre : 2 modules obligatoires + Tracker au choix ; modules écartés assumés. Présenter la grille pondérée /15 (5 critères). Conclusion argumentée : « le Tracker cumule 4 fonctionnalités à 9-10/15, c'est le module au choix le plus rentable. » |
|
||||||
| **7:00 – 12:00** (5′) | 7 — 8 — 9 | **Réponse fonctionnelle** | Module Comptes : JWT, RGPD, admin (slide 7 + maquette). Module Informations : feeds, modération, slug auto (slide 8). Module Tracker : wizard 3 étapes, journal, rapports 4 périodes, 7+33 émotions (slide 9 + maquettes). Montrer que chaque écran répond à un besoin précis. |
|
| **7:00 – 12:00** (5′) | 7 — 8 — 9 | **Réponse fonctionnelle** | Module Comptes : JWT, RGPD, admin (slide 7 + maquette). Module Informations : feeds, modération, slug auto (slide 8). Module Tracker : wizard 3 étapes, journal, rapports 4 périodes, 6+36 émotions (slide 9 + maquettes). Montrer que chaque écran répond à un besoin précis. |
|
||||||
| **12:00 – 16:00** (4′) | 10 — 11 — 12 | **Modélisation** | Cas d'usage UML (slide 10) : couverture par acteur. MCD Merise (slide 11) : 8 entités, cardinalités, hiérarchie d'émotions auto-référencée. Architecture MVC découplée (slide 12) : 1 API REST Laravel → 2 clients ; justifier le pattern (testabilité, évolutivité, non-duplication). |
|
| **12:00 – 16:00** (4′) | 10 — 11 — 12 | **Modélisation** | Cas d'usage UML (slide 10) : couverture par acteur. MCD Merise (slide 11) : 8 entités, cardinalités, hiérarchie d'émotions auto-référencée. Architecture MVC découplée (slide 12) : 1 API REST Laravel → 2 clients ; justifier le pattern (testabilité, évolutivité, non-duplication). |
|
||||||
| **16:00 – 17:30** (1′30) | 13 | **RGPD & données sensibles** | Données de santé = sensibles (art. 9). Consentement, droits CNIL (export/anonymisation), soft delete. Sécurité : chiffrement AES-256/TLS, JWT, HDS, table audits. |
|
| **16:00 – 17:30** (1′30) | 13 | **RGPD & données sensibles** | Données de santé = sensibles (art. 9). Consentement, droits CNIL (export/anonymisation), soft delete. Sécurité : chiffrement AES-256/TLS, JWT, HDS, table audits. |
|
||||||
| **17:30 – 19:00** (1′30) | 14 | **Prototype & perspectives** | Prototype fonctionnel (Laravel + Next.js + Expo + Docker). Ouverture : activer les modules écartés sans réécrire le modèle, Open Data, Mon Espace Santé (FHIR), i18n. |
|
| **17:30 – 19:00** (1′30) | 14 | **Prototype & perspectives** | Prototype fonctionnel (Laravel + Next.js + Expo + Docker). Ouverture : activer les modules écartés sans réécrire le modèle, Open Data, Mon Espace Santé (FHIR), i18n. |
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
> Le besoin est un journal personnel unique ; le tracker est créé automatiquement à l'inscription. Le modèle reste extensible (passer en 1-N) si un jour on veut plusieurs journaux thématiques.
|
> Le besoin est un journal personnel unique ; le tracker est créé automatiquement à l'inscription. Le modèle reste extensible (passer en 1-N) si un jour on veut plusieurs journaux thématiques.
|
||||||
|
|
||||||
**Q7. Comment gérez-vous la hiérarchie d'émotions à 2 niveaux ?**
|
**Q7. Comment gérez-vous la hiérarchie d'émotions à 2 niveaux ?**
|
||||||
> Une seule table `emotions` avec auto-référence `parent_id` : niveau 1 = parent_id NULL, niveau 2 = parent_id renseigné. 7 émotions de base + 33 sous-émotions. L'admin la configure via le CRUD émotions.
|
> Une seule table `emotions` avec auto-référence `parent_id` : niveau 1 = parent_id NULL, niveau 2 = parent_id renseigné. 6 émotions de base + 36 sous-émotions (référentiel du sujet). L'admin la configure via le CRUD émotions.
|
||||||
|
|
||||||
### Données & sécurité (RGPD)
|
### Données & sécurité (RGPD)
|
||||||
**Q8. Les données émotionnelles sont sensibles — comment êtes-vous conforme ?**
|
**Q8. Les données émotionnelles sont sensibles — comment êtes-vous conforme ?**
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 142 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 79 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 45 KiB |
@@ -12,30 +12,22 @@ class EmotionSeeder extends Seeder
|
|||||||
*/
|
*/
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
|
// Référentiel d'émotions conforme au sujet détaillé CESIZen (§7) :
|
||||||
|
// 6 émotions de base (niveau 1) et leurs sous-émotions (niveau 2).
|
||||||
|
// La colonne « Surprise » du sujet liste « Étonnement » en double (coquille) :
|
||||||
|
// l'occurrence est dédupliquée ici. Total : 36 sous-émotions.
|
||||||
$emotions = [
|
$emotions = [
|
||||||
[
|
[
|
||||||
'nom' => 'Joie',
|
'nom' => 'Joie',
|
||||||
'couleur' => '#FFD700',
|
'couleur' => '#FFD700',
|
||||||
'icone' => '😊',
|
'icone' => '😊',
|
||||||
'sous_emotions' => [
|
'sous_emotions' => [
|
||||||
['nom' => 'Bonheur', 'couleur' => '#FFE44D'],
|
['nom' => 'Fierté', 'couleur' => '#FFE44D'],
|
||||||
['nom' => 'Gratitude', 'couleur' => '#FFEB70'],
|
['nom' => 'Contentement', 'couleur' => '#FFEB70'],
|
||||||
['nom' => 'Sérénité', 'couleur' => '#FFF0A0'],
|
['nom' => 'Enchantement', 'couleur' => '#FFF0A0'],
|
||||||
['nom' => 'Enthousiasme', 'couleur' => '#FFE333'],
|
['nom' => 'Excitation', 'couleur' => '#FFE333'],
|
||||||
['nom' => 'Fierté', 'couleur' => '#FFED80'],
|
['nom' => 'Émerveillement', 'couleur' => '#FFED80'],
|
||||||
['nom' => 'Espoir', 'couleur' => '#FFF4B3'],
|
['nom' => 'Gratitude', 'couleur' => '#FFF4B3'],
|
||||||
],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'nom' => 'Tristesse',
|
|
||||||
'couleur' => '#4169E1',
|
|
||||||
'icone' => '😢',
|
|
||||||
'sous_emotions' => [
|
|
||||||
['nom' => 'Mélancolie', 'couleur' => '#6A8BE9'],
|
|
||||||
['nom' => 'Solitude', 'couleur' => '#7D9BED'],
|
|
||||||
['nom' => 'Déception', 'couleur' => '#90ABF1'],
|
|
||||||
['nom' => 'Nostalgie', 'couleur' => '#A3BBF5'],
|
|
||||||
['nom' => 'Chagrin', 'couleur' => '#5A7DE5'],
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
@@ -45,9 +37,10 @@ class EmotionSeeder extends Seeder
|
|||||||
'sous_emotions' => [
|
'sous_emotions' => [
|
||||||
['nom' => 'Frustration', 'couleur' => '#E34363'],
|
['nom' => 'Frustration', 'couleur' => '#E34363'],
|
||||||
['nom' => 'Irritation', 'couleur' => '#E9637F'],
|
['nom' => 'Irritation', 'couleur' => '#E9637F'],
|
||||||
['nom' => 'Agacement', 'couleur' => '#EF839B'],
|
['nom' => 'Rage', 'couleur' => '#EF839B'],
|
||||||
['nom' => 'Rage', 'couleur' => '#E23355'],
|
['nom' => 'Ressentiment', 'couleur' => '#E23355'],
|
||||||
['nom' => 'Indignation', 'couleur' => '#E85373'],
|
['nom' => 'Agacement', 'couleur' => '#E85373'],
|
||||||
|
['nom' => 'Hostilité', 'couleur' => '#EE93A7'],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
@@ -55,22 +48,25 @@ class EmotionSeeder extends Seeder
|
|||||||
'couleur' => '#9932CC',
|
'couleur' => '#9932CC',
|
||||||
'icone' => '😰',
|
'icone' => '😰',
|
||||||
'sous_emotions' => [
|
'sous_emotions' => [
|
||||||
['nom' => 'Anxiété', 'couleur' => '#AD5BD6'],
|
['nom' => 'Inquiétude', 'couleur' => '#AD5BD6'],
|
||||||
['nom' => 'Inquiétude', 'couleur' => '#B96FDC'],
|
['nom' => 'Anxiété', 'couleur' => '#B96FDC'],
|
||||||
['nom' => 'Panique', 'couleur' => '#C583E2'],
|
['nom' => 'Terreur', 'couleur' => '#C583E2'],
|
||||||
['nom' => 'Stress', 'couleur' => '#D197E8'],
|
['nom' => 'Appréhension', 'couleur' => '#D197E8'],
|
||||||
['nom' => 'Appréhension', 'couleur' => '#DDABEE'],
|
['nom' => 'Panique', 'couleur' => '#DDABEE'],
|
||||||
|
['nom' => 'Crainte', 'couleur' => '#C97FE0'],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'nom' => 'Dégoût',
|
'nom' => 'Tristesse',
|
||||||
'couleur' => '#228B22',
|
'couleur' => '#4169E1',
|
||||||
'icone' => '🤢',
|
'icone' => '😢',
|
||||||
'sous_emotions' => [
|
'sous_emotions' => [
|
||||||
['nom' => 'Aversion', 'couleur' => '#4DA64D'],
|
['nom' => 'Chagrin', 'couleur' => '#6A8BE9'],
|
||||||
['nom' => 'Répulsion', 'couleur' => '#66B366'],
|
['nom' => 'Mélancolie', 'couleur' => '#7D9BED'],
|
||||||
['nom' => 'Mépris', 'couleur' => '#80C080'],
|
['nom' => 'Abattement', 'couleur' => '#90ABF1'],
|
||||||
['nom' => 'Écœurement', 'couleur' => '#3D9C3D'],
|
['nom' => 'Désespoir', 'couleur' => '#A3BBF5'],
|
||||||
|
['nom' => 'Solitude', 'couleur' => '#5A7DE5'],
|
||||||
|
['nom' => 'Dépression', 'couleur' => '#87A1EF'],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
@@ -80,19 +76,23 @@ class EmotionSeeder extends Seeder
|
|||||||
'sous_emotions' => [
|
'sous_emotions' => [
|
||||||
['nom' => 'Étonnement', 'couleur' => '#FFA333'],
|
['nom' => 'Étonnement', 'couleur' => '#FFA333'],
|
||||||
['nom' => 'Stupéfaction', 'couleur' => '#FFB666'],
|
['nom' => 'Stupéfaction', 'couleur' => '#FFB666'],
|
||||||
['nom' => 'Émerveillement', 'couleur' => '#FFC999'],
|
['nom' => 'Sidération', 'couleur' => '#FFC999'],
|
||||||
['nom' => 'Choc', 'couleur' => '#FF9A1A'],
|
['nom' => 'Incrédule', 'couleur' => '#FF9A1A'],
|
||||||
|
['nom' => 'Émerveillement', 'couleur' => '#FFAD4D'],
|
||||||
|
['nom' => 'Confusion', 'couleur' => '#FFC080'],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'nom' => 'Amour',
|
'nom' => 'Dégoût',
|
||||||
'couleur' => '#FF69B4',
|
'couleur' => '#228B22',
|
||||||
'icone' => '💕',
|
'icone' => '🤢',
|
||||||
'sous_emotions' => [
|
'sous_emotions' => [
|
||||||
['nom' => 'Tendresse', 'couleur' => '#FF87C3'],
|
['nom' => 'Répulsion', 'couleur' => '#4DA64D'],
|
||||||
['nom' => 'Affection', 'couleur' => '#FFA5D2'],
|
['nom' => 'Déplaisir', 'couleur' => '#66B366'],
|
||||||
['nom' => 'Compassion', 'couleur' => '#FFC3E1'],
|
['nom' => 'Nausée', 'couleur' => '#80C080'],
|
||||||
['nom' => 'Admiration', 'couleur' => '#FF96CA'],
|
['nom' => 'Dédain', 'couleur' => '#3D9C3D'],
|
||||||
|
['nom' => 'Horreur', 'couleur' => '#5CAC5C'],
|
||||||
|
['nom' => 'Dégoût profond', 'couleur' => '#73BA73'],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
+78
-14
@@ -35,6 +35,10 @@ _UNICODE_FIX = {
|
|||||||
'≤': '<=',
|
'≤': '<=',
|
||||||
'≥': '>=',
|
'≥': '>=',
|
||||||
'°': 'deg',
|
'°': 'deg',
|
||||||
|
'œ': 'oe',
|
||||||
|
'Œ': 'OE',
|
||||||
|
'æ': 'ae',
|
||||||
|
'Æ': 'AE',
|
||||||
}
|
}
|
||||||
|
|
||||||
def _safe(s):
|
def _safe(s):
|
||||||
@@ -265,8 +269,38 @@ for lib, val in metadata:
|
|||||||
pdf.set_font('Helvetica', '', 10)
|
pdf.set_font('Helvetica', '', 10)
|
||||||
pdf.cell(0, 7, val, new_x="LMARGIN", new_y="NEXT")
|
pdf.cell(0, 7, val, new_x="LMARGIN", new_y="NEXT")
|
||||||
|
|
||||||
# ─────────────── 1. Glossaire ───────────────
|
# ─────────────── Sommaire ───────────────
|
||||||
pdf.add_page()
|
pdf.add_page()
|
||||||
|
pdf.set_font('Helvetica', 'B', 16)
|
||||||
|
pdf.set_text_color(*COULEUR_BLEU)
|
||||||
|
pdf.set_fill_color(*COULEUR_BLEU_CLAIR)
|
||||||
|
pdf.cell(0, 11, ' Sommaire', fill=True, new_x="LMARGIN", new_y="NEXT")
|
||||||
|
pdf.ln(6)
|
||||||
|
sommaire = [
|
||||||
|
('1', 'Glossaire'),
|
||||||
|
('2', 'Recueil du besoin'),
|
||||||
|
('3', 'Critères de priorisation et pondération'),
|
||||||
|
('4', 'Cahier des charges - Analyse'),
|
||||||
|
('5', 'Réponse fonctionnelle - Spécifications par module'),
|
||||||
|
('6', "Schématisation UML - Cas d'usage"),
|
||||||
|
('7', 'Modèle Conceptuel de Données (MCD)'),
|
||||||
|
('8', 'Conception technique - Architecture MVC'),
|
||||||
|
('9', 'Diagrammes UML - Séquences clés'),
|
||||||
|
('10', 'Gestion des données personnelles et sensibles (RGPD)'),
|
||||||
|
('11', 'Analyse des risques et mitigation'),
|
||||||
|
('12', 'Exigences non-fonctionnelles'),
|
||||||
|
('13', 'Conclusion'),
|
||||||
|
]
|
||||||
|
for num, titre in sommaire:
|
||||||
|
pdf.set_font('Helvetica', 'B', 11)
|
||||||
|
pdf.set_text_color(*COULEUR_SECONDAIRE)
|
||||||
|
pdf.cell(12, 8.5, num)
|
||||||
|
pdf.set_font('Helvetica', '', 11)
|
||||||
|
pdf.set_text_color(40, 40, 40)
|
||||||
|
pdf.cell(0, 8.5, titre, new_x="LMARGIN", new_y="NEXT")
|
||||||
|
pdf.ln(6)
|
||||||
|
|
||||||
|
# ─────────────── 1. Glossaire (même page que le sommaire) ───────────────
|
||||||
pdf.h1(1, 'Glossaire')
|
pdf.h1(1, 'Glossaire')
|
||||||
glossaire = [
|
glossaire = [
|
||||||
('MVC', "Modèle-Vue-Contrôleur. Patron d'architecture séparant données, présentation et logique applicative."),
|
('MVC', "Modèle-Vue-Contrôleur. Patron d'architecture séparant données, présentation et logique applicative."),
|
||||||
@@ -330,7 +364,9 @@ pdf.table(
|
|||||||
['Organisationnelle', 'Réalisation individuelle, 3 mois calendaires', 'CRITIQUE'],
|
['Organisationnelle', 'Réalisation individuelle, 3 mois calendaires', 'CRITIQUE'],
|
||||||
['Organisationnelle', "Pas de budget dédié à la création de contenu", 'MOYENNE'],
|
['Organisationnelle', "Pas de budget dédié à la création de contenu", 'MOYENNE'],
|
||||||
['Fonctionnelle', '2 modules obligatoires + 1 au choix (Tracker retenu)', 'CRITIQUE'],
|
['Fonctionnelle', '2 modules obligatoires + 1 au choix (Tracker retenu)', 'CRITIQUE'],
|
||||||
|
['Budgétaire', "Budget global du projet plafonné à 75 000 EUR (sujet)", 'CRITIQUE'],
|
||||||
['Budgétaire', 'Stack open-source uniquement (pas de licence payante)', 'MOYENNE'],
|
['Budgétaire', 'Stack open-source uniquement (pas de licence payante)', 'MOYENNE'],
|
||||||
|
['Temporelle', "Livraison de la version testée sous 12 mois (sujet)", 'FORTE'],
|
||||||
],
|
],
|
||||||
col_widths=[35, 130, 25],
|
col_widths=[35, 130, 25],
|
||||||
)
|
)
|
||||||
@@ -455,7 +491,33 @@ pdf.bullet(
|
|||||||
# ─────────────── 4. Cahier des charges — Analyse ───────────────
|
# ─────────────── 4. Cahier des charges — Analyse ───────────────
|
||||||
pdf.add_page()
|
pdf.add_page()
|
||||||
pdf.h1(4, 'Cahier des charges — Analyse')
|
pdf.h1(4, 'Cahier des charges — Analyse')
|
||||||
pdf.h2('4.1 Acteurs identifiés')
|
pdf.h2('4.1 Parties prenantes et communication')
|
||||||
|
pdf.paragraph(
|
||||||
|
"Au-delà des acteurs du système, le projet mobilise plusieurs parties prenantes dont les attentes et "
|
||||||
|
"les canaux d'échange structurent la conduite du projet. Le commanditaire valide les livrables en comité "
|
||||||
|
"de pilotage ; l'apprenant (maîtrise d'œuvre) restitue son avancement via le dossier et la soutenance ; "
|
||||||
|
"les contenus sont produits par des professionnels de santé et hébergés chez un prestataire HDS sous "
|
||||||
|
"le contrôle de la CNIL."
|
||||||
|
)
|
||||||
|
pdf.table(
|
||||||
|
headers=['Partie prenante', 'Rôle / intérêt', 'Attentes', 'Canal de communication'],
|
||||||
|
rows=[
|
||||||
|
['Ministère (commanditaire)', "Finance et valide le projet",
|
||||||
|
"Conformité santé publique, RGPD, image institutionnelle", "Comités de pilotage, validation des livrables"],
|
||||||
|
["Apprenant (maîtrise d'œuvre)", "Conçoit et développe la solution",
|
||||||
|
"Cadrage clair, périmètre stable", "Dossier, revues d'avancement, soutenance"],
|
||||||
|
['Utilisateurs finaux', "Usage quotidien de la plateforme",
|
||||||
|
"Simplicité, confidentialité, accessibilité", "Retours in-app, enquêtes de satisfaction"],
|
||||||
|
['Professionnels de santé', "Rédigent et modèrent les contenus",
|
||||||
|
"Outils d'administration fiables", "Back-office, charte éditoriale"],
|
||||||
|
['Hébergeur HDS', "Héberge les données de santé",
|
||||||
|
"Conformité technique, disponibilité (SLA)", "Contrat de service, supervision"],
|
||||||
|
['CNIL / DPO', "Contrôlent la conformité RGPD",
|
||||||
|
"Registre des traitements, sécurité", "Registre, analyses d'impact (AIPD)"],
|
||||||
|
],
|
||||||
|
col_widths=[42, 40, 58, 50],
|
||||||
|
)
|
||||||
|
pdf.h2('4.2 Acteurs identifiés')
|
||||||
pdf.table(
|
pdf.table(
|
||||||
headers=['Acteur', 'Description', 'Périmètre fonctionnel'],
|
headers=['Acteur', 'Description', 'Périmètre fonctionnel'],
|
||||||
rows=[
|
rows=[
|
||||||
@@ -472,7 +534,7 @@ pdf.table(
|
|||||||
col_widths=[35, 60, 90],
|
col_widths=[35, 60, 90],
|
||||||
)
|
)
|
||||||
|
|
||||||
pdf.h2('4.2 Personas')
|
pdf.h2('4.3 Personas')
|
||||||
personas = [
|
personas = [
|
||||||
("Claire — Utilisatrice (Visiteur → Membre)",
|
("Claire — Utilisatrice (Visiteur → Membre)",
|
||||||
"35 ans, responsable marketing à Lille. Mère célibataire de 2 enfants. Stressée par le travail, "
|
"35 ans, responsable marketing à Lille. Mère célibataire de 2 enfants. Stressée par le travail, "
|
||||||
@@ -493,7 +555,7 @@ for nom, desc in personas:
|
|||||||
pdf.multi_cell(0, 5, ' ' + desc)
|
pdf.multi_cell(0, 5, ' ' + desc)
|
||||||
pdf.ln(1)
|
pdf.ln(1)
|
||||||
|
|
||||||
pdf.h2('4.3 Opportunités et pérennité')
|
pdf.h2('4.4 Opportunités et pérennité')
|
||||||
pdf.bullet(
|
pdf.bullet(
|
||||||
"Évolutivité : architecture découplée (API REST + 2 clients web/mobile) permettant l'ajout futur "
|
"Évolutivité : architecture découplée (API REST + 2 clients web/mobile) permettant l'ajout futur "
|
||||||
"des modules Diagnostic, Respiration, Activités sans réécriture."
|
"des modules Diagnostic, Respiration, Activités sans réécriture."
|
||||||
@@ -557,8 +619,7 @@ pdf.ln(2)
|
|||||||
pdf.figure(_os.path.join(ASSETS, 'mockup_inscription.png'), 62,
|
pdf.figure(_os.path.join(ASSETS, 'mockup_inscription.png'), 62,
|
||||||
caption="Maquette - écran d'inscription (consentement RGPD obligatoire)")
|
caption="Maquette - écran d'inscription (consentement RGPD obligatoire)")
|
||||||
|
|
||||||
# ─── Module 2 — Informations
|
# ─── Module 2 — Informations (enchaîne après le module Comptes)
|
||||||
pdf.add_page()
|
|
||||||
pdf.h2("5.2 Module 'Informations' (obligatoire)")
|
pdf.h2("5.2 Module 'Informations' (obligatoire)")
|
||||||
pdf.h3("Écrans principaux")
|
pdf.h3("Écrans principaux")
|
||||||
pdf.bullet("Page publique liste : grille de cartes (titre, extrait 120 caractères, image, date).")
|
pdf.bullet("Page publique liste : grille de cartes (titre, extrait 120 caractères, image, date).")
|
||||||
@@ -579,24 +640,27 @@ pdf.table(
|
|||||||
],
|
],
|
||||||
col_widths=[20, 170],
|
col_widths=[20, 170],
|
||||||
)
|
)
|
||||||
|
pdf.figure(_os.path.join(ASSETS, 'mockup_informations.png'), 88,
|
||||||
|
caption="Maquette - liste publique des pages d'information + back-office admin")
|
||||||
|
|
||||||
# ─── Module 3 — Tracker
|
# ─── Module 3 — Tracker
|
||||||
pdf.h2("5.3 Module 'Tracker d'émotions' (au choix)")
|
pdf.h2("5.3 Module 'Tracker d'émotions' (au choix)")
|
||||||
pdf.paragraph(
|
pdf.paragraph(
|
||||||
"Le module Tracker permet à l'utilisateur d'enregistrer son état émotionnel via un wizard en 3 étapes, "
|
"Le module Tracker permet à l'utilisateur d'enregistrer son état émotionnel via un wizard en 3 étapes, "
|
||||||
"de consulter son journal, et de visualiser des rapports analytiques sur 4 périodes (semaine, mois, trimestre, année). "
|
"de consulter son journal, et de visualiser des rapports analytiques sur 4 périodes (semaine, mois, trimestre, année). "
|
||||||
"Les émotions sont structurées en 2 niveaux (7 émotions de base + 33 sous-émotions précises)."
|
"Les émotions sont structurées en 2 niveaux (6 émotions de base + 36 sous-émotions précises), "
|
||||||
|
"conformément au référentiel défini dans le sujet."
|
||||||
)
|
)
|
||||||
pdf.h3("Wizard d'ajout de saisie (3 étapes)")
|
pdf.h3("Wizard d'ajout de saisie (3 étapes)")
|
||||||
pdf.block_callout(
|
pdf.block_callout(
|
||||||
"Étape 1 — Sélection de l'émotion de base (niveau 1)",
|
"Étape 1 — Sélection de l'émotion de base (niveau 1)",
|
||||||
"L'utilisateur choisit parmi 7 émotions fondamentales : Joie, Tristesse, Colère, Peur, Dégoût, Surprise, Amour. "
|
"L'utilisateur choisit parmi 6 émotions fondamentales : Joie, Colère, Peur, Tristesse, Surprise, Dégoût. "
|
||||||
"Chaque émotion est représentée par une couleur et un icône distinctifs.",
|
"Chaque émotion est représentée par une couleur et un icône distinctifs.",
|
||||||
color=COULEUR_SECONDAIRE
|
color=COULEUR_SECONDAIRE
|
||||||
)
|
)
|
||||||
pdf.block_callout(
|
pdf.block_callout(
|
||||||
"Étape 2 — Sous-émotion (niveau 2) + intensité 1-10",
|
"Étape 2 — Sous-émotion (niveau 2) + intensité 1-10",
|
||||||
"Selon l'émotion choisie, 4 à 6 sous-émotions plus précises sont proposées (ex: Joie → Sérénité, Enthousiasme, Fierté, Gratitude). "
|
"Selon l'émotion choisie, 6 sous-émotions plus précises sont proposées (ex: Joie -> Fierté, Contentement, Enchantement, Excitation, Émerveillement, Gratitude). "
|
||||||
"L'intensité est ajustée via un slider de 1 (très faible) à 10 (très forte).",
|
"L'intensité est ajustée via un slider de 1 (très faible) à 10 (très forte).",
|
||||||
color=COULEUR_BLEU
|
color=COULEUR_BLEU
|
||||||
)
|
)
|
||||||
@@ -644,7 +708,7 @@ pdf.paragraph(
|
|||||||
"Le MCD utilise le formalisme Merise (entités, associations, cardinalités). 8 entités principales sont "
|
"Le MCD utilise le formalisme Merise (entités, associations, cardinalités). 8 entités principales sont "
|
||||||
"modélisées : Utilisateur, Rôle, Tracker, Émotion, SaisieTracker, Feed, ContactUrgence, Audit."
|
"modélisées : Utilisateur, Rôle, Tracker, Émotion, SaisieTracker, Feed, ContactUrgence, Audit."
|
||||||
)
|
)
|
||||||
pdf.figure(_os.path.join(ASSETS, 'mcd.png'), 150,
|
pdf.figure(_os.path.join(ASSETS, 'mcd.png'), 165,
|
||||||
caption="Modèle Conceptuel de Données (Merise) - cardinalités et hiérarchie d'émotions")
|
caption="Modèle Conceptuel de Données (Merise) - cardinalités et hiérarchie d'émotions")
|
||||||
|
|
||||||
pdf.h2("7.1 Cardinalités principales")
|
pdf.h2("7.1 Cardinalités principales")
|
||||||
@@ -781,7 +845,8 @@ pdf.table(
|
|||||||
)
|
)
|
||||||
pdf.h2('10.3 Mesures de sécurité techniques')
|
pdf.h2('10.3 Mesures de sécurité techniques')
|
||||||
pdf.bullet("Chiffrement en transit : HTTPS strict (HSTS), TLS 1.3 minimum.")
|
pdf.bullet("Chiffrement en transit : HTTPS strict (HSTS), TLS 1.3 minimum.")
|
||||||
pdf.bullet("Chiffrement au repos : AES-256 sur le volume PostgreSQL, secrets dans .env hors-versioning.")
|
pdf.bullet("Chiffrement au repos : chiffrement du volume PostgreSQL (AES-256) prévu en production HDS. "
|
||||||
|
"À ce stade, les mots de passe sont hachés (bcrypt) et les secrets sont stockés hors-versioning (.env).")
|
||||||
pdf.bullet("Hash mot de passe : bcrypt 12 rounds (configurable selon serveur).")
|
pdf.bullet("Hash mot de passe : bcrypt 12 rounds (configurable selon serveur).")
|
||||||
pdf.bullet("Authentification : JWT signé (HS256), expiration 60min, refresh 14j, throttle login 5/min.")
|
pdf.bullet("Authentification : JWT signé (HS256), expiration 60min, refresh 14j, throttle login 5/min.")
|
||||||
pdf.bullet("Autorisation : middleware role-based (jwt.auth + role:administrateur), rate limit admin 60/min.")
|
pdf.bullet("Autorisation : middleware role-based (jwt.auth + role:administrateur), rate limit admin 60/min.")
|
||||||
@@ -796,7 +861,7 @@ pdf.table(
|
|||||||
headers=['Risque', 'Impact', 'Probabilité', 'Mitigation'],
|
headers=['Risque', 'Impact', 'Probabilité', 'Mitigation'],
|
||||||
rows=[
|
rows=[
|
||||||
['Fuite données de santé', 'CRITIQUE', 'Faible',
|
['Fuite données de santé', 'CRITIQUE', 'Faible',
|
||||||
"Chiffrement AES-256, HDS, audits trimestriels, minimisation données."],
|
"Hachage bcrypt, chiffrement volume AES-256 prévu en prod HDS, audits trimestriels, minimisation données."],
|
||||||
['Dérive contenus (conseil médical dangereux)', 'FORT', 'Moyen',
|
['Dérive contenus (conseil médical dangereux)', 'FORT', 'Moyen',
|
||||||
"Modération admin obligatoire avant publication. Avertissement légal en pied de page."],
|
"Modération admin obligatoire avant publication. Avertissement légal en pied de page."],
|
||||||
['Perte de données utilisateur', 'FORT', 'Faible',
|
['Perte de données utilisateur', 'FORT', 'Faible',
|
||||||
@@ -827,7 +892,6 @@ pdf.table(
|
|||||||
['Sécurité', 'Audit pénétration', 'Annuel (tiers indépendant)'],
|
['Sécurité', 'Audit pénétration', 'Annuel (tiers indépendant)'],
|
||||||
['Accessibilité', 'RGAA niveau', 'AA'],
|
['Accessibilité', 'RGAA niveau', 'AA'],
|
||||||
['Ergonomie', 'Dark Mode', "Natif iOS / Android / Web"],
|
['Ergonomie', 'Dark Mode', "Natif iOS / Android / Web"],
|
||||||
['Internationalisation', 'Langues supportées', 'FR (v1), EN (v2)'],
|
|
||||||
],
|
],
|
||||||
col_widths=[30, 80, 80],
|
col_widths=[30, 80, 80],
|
||||||
)
|
)
|
||||||
@@ -850,7 +914,7 @@ pdf.paragraph(
|
|||||||
"et démontre la faisabilité technique des choix présentés."
|
"et démontre la faisabilité technique des choix présentés."
|
||||||
)
|
)
|
||||||
|
|
||||||
pdf.ln(6)
|
pdf.ln(1)
|
||||||
pdf.set_font('Helvetica', 'I', 9)
|
pdf.set_font('Helvetica', 'I', 9)
|
||||||
pdf.set_text_color(*COULEUR_GRIS_MOYEN)
|
pdf.set_text_color(*COULEUR_GRIS_MOYEN)
|
||||||
pdf.cell(0, 6, 'Sources : consignes CESI INFCDAAL1, Santé Publique France 2023, CNIL — Guide RGPD santé.',
|
pdf.cell(0, 6, 'Sources : consignes CESI INFCDAAL1, Santé Publique France 2023, CNIL — Guide RGPD santé.',
|
||||||
|
|||||||
+49
-6
@@ -212,9 +212,9 @@ def diagram_mcd():
|
|||||||
ca = (p0[0] + (p1[0] - p0[0]) * 0.16, p0[1] + (p1[1] - p0[1]) * 0.16)
|
ca = (p0[0] + (p1[0] - p0[0]) * 0.16, p0[1] + (p1[1] - p0[1]) * 0.16)
|
||||||
cb = (p0[0] + (p1[0] - p0[0]) * 0.84, p0[1] + (p1[1] - p0[1]) * 0.84)
|
cb = (p0[0] + (p1[0] - p0[0]) * 0.84, p0[1] + (p1[1] - p0[1]) * 0.84)
|
||||||
for (cx, cy), card in ((ca, card_a), (cb, card_b)):
|
for (cx, cy), card in ((ca, card_a), (cb, card_b)):
|
||||||
w = c.text_w(card, 10, bold=True) + 8
|
w = c.text_w(card, 13, bold=True) + 12
|
||||||
c.box(cx - w / 2, cy - 9, w, 18, fill=WHITE, outline=GREEN_D, width=1, radius=5)
|
c.box(cx - w / 2, cy - 12, w, 24, fill=WHITE, outline=GREEN_D, width=2, radius=6)
|
||||||
c.text(cx, cy, card, 10, GREEN_D, bold=True, anchor='mm')
|
c.text(cx, cy, card, 13, GREEN_D, bold=True, anchor='mm')
|
||||||
c.pill(mx, my, verb, 11, GREEN)
|
c.pill(mx, my, verb, 11, GREEN)
|
||||||
|
|
||||||
# liens (cardinalités Merise : (min,max) côté de chaque entité)
|
# liens (cardinalités Merise : (min,max) côté de chaque entité)
|
||||||
@@ -233,8 +233,8 @@ def diagram_mcd():
|
|||||||
c.line(ex + ew + 45, ey - 5, ex + ew / 2, ey - 5, GREEN_D, 2)
|
c.line(ex + ew + 45, ey - 5, ex + ew / 2, ey - 5, GREEN_D, 2)
|
||||||
c.line(ex + ew / 2, ey - 5, ex + ew / 2, ey, GREEN_D, 2)
|
c.line(ex + ew / 2, ey - 5, ex + ew / 2, ey, GREEN_D, 2)
|
||||||
c.pill(ex + ew + 45, ey + 18, 'hiérarchie', 10, GREEN)
|
c.pill(ex + ew + 45, ey + 18, 'hiérarchie', 10, GREEN)
|
||||||
c.text(ex + ew + 50, ey + 40, '0,n', 9, GREEN_D, bold=True, anchor='lm')
|
c.text(ex + ew + 52, ey + 40, '0,n', 12, GREEN_D, bold=True, anchor='lm')
|
||||||
c.text(ex + ew / 2 + 8, ey - 12, '0,1', 9, GREEN_D, bold=True, anchor='lm')
|
c.text(ex + ew / 2 + 10, ey - 13, '0,1', 12, GREEN_D, bold=True, anchor='lm')
|
||||||
|
|
||||||
# dessin des entités (au-dessus des liens)
|
# dessin des entités (au-dessus des liens)
|
||||||
for name, (x, y, w, attrs) in entities.items():
|
for name, (x, y, w, attrs) in entities.items():
|
||||||
@@ -538,7 +538,7 @@ def mockup_wizard():
|
|||||||
c.ellipse(ix + 28, y + 170, 13, 13, fill=(255, 215, 0), outline=(225, 185, 0), width=2)
|
c.ellipse(ix + 28, y + 170, 13, 13, fill=(255, 215, 0), outline=(225, 185, 0), width=2)
|
||||||
c.text(ix + 52, y + 170, "Joie", 14, GREY_D, bold=True, anchor='lm')
|
c.text(ix + 52, y + 170, "Joie", 14, GREY_D, bold=True, anchor='lm')
|
||||||
# sous-émotions
|
# sous-émotions
|
||||||
subs = ['Sérénité', 'Gratitude', 'Fierté', 'Espoir', 'Bonheur', 'Enthousiasme']
|
subs = ['Fierté', 'Contentement', 'Enchantement', 'Excitation', 'Émerveillement', 'Gratitude']
|
||||||
for i, s in enumerate(subs):
|
for i, s in enumerate(subs):
|
||||||
sx = ix + (i % 2) * 140
|
sx = ix + (i % 2) * 140
|
||||||
sy = y + 215 + (i // 2) * 50
|
sy = y + 215 + (i // 2) * 50
|
||||||
@@ -598,6 +598,48 @@ def mockup_rapports():
|
|||||||
c.save('mockup_rapports.png')
|
c.save('mockup_rapports.png')
|
||||||
|
|
||||||
|
|
||||||
|
def mockup_informations():
|
||||||
|
c = Canvas(620, 760)
|
||||||
|
title_bar(c, 14, 14, 592, "Maquette - Informations (pages de contenu)", fill=GREEN_D)
|
||||||
|
x, y, w, h = 40, 80, 540, 650
|
||||||
|
# fenêtre navigateur
|
||||||
|
c.box(x, y, w, h, fill=WHITE, outline=GREY_D, width=3, radius=14)
|
||||||
|
c.box(x, y, w, 40, fill=GREY_L, outline=GREY_L, radius=14)
|
||||||
|
c.rect(x, y + 22, w, 18, fill=GREY_L)
|
||||||
|
for i, col in enumerate([(255, 95, 86), (255, 189, 46), (39, 201, 63)]):
|
||||||
|
c.ellipse(x + 22 + i * 22, y + 20, 7, 7, fill=col, outline=col)
|
||||||
|
c.text(x + w / 2, y + 20, "cesizen.fr / informations", 10, GREY_D, anchor='mm')
|
||||||
|
ix = x + 28
|
||||||
|
c.text(ix, y + 68, "Santé mentale - Ressources", 16, BLUE, bold=True, anchor='lm')
|
||||||
|
c.text(ix, y + 92, "Articles et conseils validés par nos professionnels", 10, GREY, anchor='lm')
|
||||||
|
# cartes articles (liste publique)
|
||||||
|
articles = [
|
||||||
|
("Comprendre le stress", ["Mécanismes du stress et signaux", "d'alerte à reconnaître au quotidien."]),
|
||||||
|
("5 exercices anti-anxiété", ["Respiration et ancrage pour apaiser", "une montée d'anxiété."]),
|
||||||
|
("Bien dormir, mieux vivre", ["L'impact du sommeil sur la santé", "mentale et routines de repos."]),
|
||||||
|
("Quand consulter ?", ["Repères pour identifier le moment", "d'aller voir un professionnel."]),
|
||||||
|
]
|
||||||
|
cy0 = y + 118
|
||||||
|
for i, (titre, lignes) in enumerate(articles):
|
||||||
|
cardx = ix + (i % 2) * 258
|
||||||
|
cardy = cy0 + (i // 2) * 152
|
||||||
|
c.box(cardx, cardy, 240, 132, fill=GREY_LL, outline=GREY_L, width=1, radius=12)
|
||||||
|
c.box(cardx, cardy, 240, 40, fill=BLUE_L, outline=BLUE_L, radius=12)
|
||||||
|
c.rect(cardx, cardy + 22, 240, 18, fill=BLUE_L)
|
||||||
|
c.text(cardx + 14, cardy + 20, titre, 11, BLUE, bold=True, anchor='lm')
|
||||||
|
for j, ln in enumerate(lignes):
|
||||||
|
c.text(cardx + 14, cardy + 62 + j * 19, ln, 9, INK, anchor='lm')
|
||||||
|
c.text(cardx + 14, cardy + 112, "12 mai 2026 · Lire ->", 8, GREEN_D, bold=True, anchor='lm')
|
||||||
|
# bandeau back-office admin
|
||||||
|
ay = cy0 + 320
|
||||||
|
c.box(ix, ay, w - 56, 40, fill=(255, 248, 200), outline=YELLOW, width=2, radius=10)
|
||||||
|
c.text(ix + 14, ay + 20, "Back-office admin : créer / modifier / publier · slug auto · "
|
||||||
|
"modération avant mise en ligne", 9, GREY_D, anchor='lm')
|
||||||
|
c.text(x + w / 2, y + h - 14, "RG-INF-01 slug auto · RG-INF-02 brouillon/publié · RG-INF-06 modération",
|
||||||
|
8, GREY, anchor='mm')
|
||||||
|
c.save('mockup_informations.png')
|
||||||
|
|
||||||
|
|
||||||
# ════════════════════════════════════════════════════════════════════
|
# ════════════════════════════════════════════════════════════════════
|
||||||
def main():
|
def main():
|
||||||
print("Génération des schémas CESIZen ->", OUT_DIR)
|
print("Génération des schémas CESIZen ->", OUT_DIR)
|
||||||
@@ -608,6 +650,7 @@ def main():
|
|||||||
diagram_mvc()
|
diagram_mvc()
|
||||||
mockup_inscription()
|
mockup_inscription()
|
||||||
mockup_wizard()
|
mockup_wizard()
|
||||||
|
mockup_informations()
|
||||||
mockup_rapports()
|
mockup_rapports()
|
||||||
print("Terminé.")
|
print("Terminé.")
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -229,7 +229,7 @@ cols = [
|
|||||||
]),
|
]),
|
||||||
("1 module AU CHOIX (retenu)", BLUE, [
|
("1 module AU CHOIX (retenu)", BLUE, [
|
||||||
"Tracker d'émotions : journal, saisies, rapports périodiques.",
|
"Tracker d'émotions : journal, saisies, rapports périodiques.",
|
||||||
"Hiérarchie : 7 émotions de base + 33 sous-émotions.",
|
"Hiérarchie : 6 émotions de base + 36 sous-émotions (référentiel du sujet).",
|
||||||
]),
|
]),
|
||||||
("Modules ÉCARTÉS", GREY, [
|
("Modules ÉCARTÉS", GREY, [
|
||||||
"Diagnostic de stress.",
|
"Diagnostic de stress.",
|
||||||
@@ -326,7 +326,7 @@ bullets(s, [
|
|||||||
"Journal de bord : consultation, modification, suppression des saisies.",
|
"Journal de bord : consultation, modification, suppression des saisies.",
|
||||||
"Rapports analytiques sur 4 périodes : semaine, mois, trimestre, année.",
|
"Rapports analytiques sur 4 périodes : semaine, mois, trimestre, année.",
|
||||||
"Statistiques : intensité moyenne, émotion dominante, répartition, évolution.",
|
"Statistiques : intensité moyenne, émotion dominante, répartition, évolution.",
|
||||||
"Hiérarchie configurable par l'admin : 7 émotions + 33 sous-émotions.",
|
"Hiérarchie configurable par l'admin : 6 émotions + 36 sous-émotions.",
|
||||||
"Web (graphiques Recharts) et mobile (Expo) synchronisés via l'API.",
|
"Web (graphiques Recharts) et mobile (Expo) synchronisés via l'API.",
|
||||||
], Inches(0.7), Inches(1.45), Inches(7.0), Inches(5.3), size=16, gap=10)
|
], Inches(0.7), Inches(1.45), Inches(7.0), Inches(5.3), size=16, gap=10)
|
||||||
image_fit(s, "mockup_wizard.png", Inches(7.9), Inches(1.35), Inches(2.5), Inches(5.3))
|
image_fit(s, "mockup_wizard.png", Inches(7.9), Inches(1.35), Inches(2.5), Inches(5.3))
|
||||||
@@ -383,7 +383,7 @@ rect(s, Inches(0.8), Inches(4.1), Inches(3.6), Inches(0.55), GREEN_D)
|
|||||||
tb, tf = textbox(s, Inches(0.95), Inches(4.13), Inches(3.4), Inches(0.5), MSO_ANCHOR.MIDDLE)
|
tb, tf = textbox(s, Inches(0.95), Inches(4.13), Inches(3.4), Inches(0.5), MSO_ANCHOR.MIDDLE)
|
||||||
set_par(tf.paragraphs[0], "Mesures de sécurité", 15, WHITE, bold=True, space_after=0)
|
set_par(tf.paragraphs[0], "Mesures de sécurité", 15, WHITE, bold=True, space_after=0)
|
||||||
bullets(s, [
|
bullets(s, [
|
||||||
"Chiffrement en transit (HTTPS/TLS 1.3) et au repos (AES-256).",
|
"Chiffrement en transit (HTTPS/TLS 1.3) ; bcrypt sur les mots de passe, AES-256 au repos prévu en prod HDS.",
|
||||||
"Authentification JWT signée, expiration 60 min, throttle login.",
|
"Authentification JWT signée, expiration 60 min, throttle login.",
|
||||||
"Hébergement certifié HDS (Scaleway / OVH Healthcare).",
|
"Hébergement certifié HDS (Scaleway / OVH Healthcare).",
|
||||||
"Journalisation : table audits trace toute action admin sensible.",
|
"Journalisation : table audits trace toute action admin sensible.",
|
||||||
|
|||||||
@@ -19,11 +19,10 @@ export const Colors = {
|
|||||||
},
|
},
|
||||||
emotions: {
|
emotions: {
|
||||||
joie: '#FFD700',
|
joie: '#FFD700',
|
||||||
tristesse: '#4169E1',
|
|
||||||
colere: '#DC143C',
|
colere: '#DC143C',
|
||||||
peur: '#9932CC',
|
peur: '#9932CC',
|
||||||
degout: '#228B22',
|
tristesse: '#4169E1',
|
||||||
surprise: '#FF8C00',
|
surprise: '#FF8C00',
|
||||||
amour: '#FF69B4',
|
degout: '#228B22',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user