Commit 02cf74aa authored by Jordan Grossemy's avatar Jordan Grossemy
Browse files

Kits : 3 kits d'exercice non-cyber + variables de personnalisation

Ajoute 3 kits « clé en main » (inondation communale, black-out
électrique, canicule communale) d'après docs/spec-cythin-kits-non-cyber.md :
chronogrammes multi-canal (e-mail, chat, réseau social, presse, appel),
personnages joués + PNJ, documents (mise en situation, modèles, RETEX)
et injects de bruit pour l'immersion.

Branche les variables {{cours_deau}}, {{prefecture}} et
{{gestionnaire_reseau}} dans le moteur de personnalisation (shared, DTO,
buildVars avec valeurs par défaut §1) et le parcours de création (wizard).

Ignore docs-site/ (Docusaurus autonome) au lint racine.

Co-Authored-By: Claude (RCA)
parent 3ee535a5
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -32,6 +32,21 @@ export class PersonalizationDto {
  @MaxLength(160)
  media?: string;

  @IsOptional()
  @IsString()
  @MaxLength(160)
  cours_deau?: string;

  @IsOptional()
  @IsString()
  @MaxLength(160)
  prefecture?: string;

  @IsOptional()
  @IsString()
  @MaxLength(160)
  gestionnaire_reseau?: string;

  @IsOptional()
  @IsString()
  @MaxLength(40)
+33 −3
Original line number Diff line number Diff line
@@ -3,8 +3,9 @@
 * champs de mise en situation + moteur de variables {{...}} substituées dans le
 * contenu d'un kit à l'installation.
 *
 * Variables disponibles pour les (futurs) kits : {{organisation}}, {{ville}},
 * {{secteur}}, {{edr}}, {{partenaire}}, {{media}}.
 * Variables disponibles pour les kits : {{organisation}}, {{ville}}, {{secteur}},
 * {{edr}}, {{partenaire}}, {{media}} ; et pour les kits non-cyber {{cours_deau}},
 * {{prefecture}}, {{gestionnaire_reseau}} (valeurs par défaut si non renseignées).
 */

export interface Personalization {
@@ -16,6 +17,9 @@ export interface Personalization {
  edr?: string;
  partenaire?: string;
  media?: string;
  cours_deau?: string;
  prefecture?: string;
  gestionnaire_reseau?: string;
  startAt?: string;
}

@@ -25,10 +29,30 @@ export interface ExerciseContext {
  edr?: string;
  partenaire?: string;
  media?: string;
  cours_deau?: string;
  prefecture?: string;
  gestionnaire_reseau?: string;
  startAt?: string;
}

const CONTEXT_KEYS = ['organisation', 'ville', 'edr', 'partenaire', 'media', 'startAt'] as const;
const CONTEXT_KEYS = [
  'organisation',
  'ville',
  'edr',
  'partenaire',
  'media',
  'cours_deau',
  'prefecture',
  'gestionnaire_reseau',
  'startAt',
] as const;

/** Valeurs par défaut des variables non-cyber (spec kits §1) si non renseignées. */
const NON_CYBER_DEFAULTS = {
  cours_deau: 'la rivière',
  prefecture: 'la préfecture',
  gestionnaire_reseau: 'le gestionnaire du réseau',
} as const;

/** Contexte (mise en situation) nettoyé, ou undefined si aucun champ renseigné. */
export function buildContext(p: Personalization | undefined): ExerciseContext | undefined {
@@ -53,6 +77,12 @@ export function buildVars(
  if (ctx?.edr) vars.edr = ctx.edr;
  if (ctx?.partenaire) vars.partenaire = ctx.partenaire;
  if (ctx?.media) vars.media = ctx.media;
  // Variables non-cyber : toujours résolues (valeur saisie ou défaut) pour éviter
  // qu'un jeton {{...}} reste visible côté joueur dans les kits inondation/black-out/canicule.
  vars.cours_deau = ctx?.cours_deau?.trim() || NON_CYBER_DEFAULTS.cours_deau;
  vars.prefecture = ctx?.prefecture?.trim() || NON_CYBER_DEFAULTS.prefecture;
  vars.gestionnaire_reseau =
    ctx?.gestionnaire_reseau?.trim() || NON_CYBER_DEFAULTS.gestionnaire_reseau;
  return vars;
}

+9 −1
Original line number Diff line number Diff line
@@ -7,6 +7,9 @@ import rempar25Admin from './data/rempar25-administration.json';
import rempar25Cod from './data/rempar25-cod.json';
import rempar25Csirt from './data/rempar25-csirt.json';
import rempar25GlobalImmersif from './data/rempar25-global-immersif.json';
import inondationCommunale from './data/inondation-communale.json';
import blackoutElectrique from './data/blackout-electrique.json';
import caniculeCommunale from './data/canicule-communale.json';

/** Kits officiels REMPAR25 importés depuis les chronogrammes ANSSI (Licence Ouverte 2.0). */
const REMPAR25: Kit[] = [
@@ -20,4 +23,9 @@ const REMPAR25: Kit[] = [
  rempar25Csirt,
].map((k) => k as unknown as Kit);

export const CATALOGUE: Kit[] = [...REMPAR25];
/** Kits d'exercice non-cyber (crises communales / continuité d'activité — JNR). */
const NON_CYBER: Kit[] = [inondationCommunale, blackoutElectrique, caniculeCommunale].map(
  (k) => k as unknown as Kit,
);

export const CATALOGUE: Kit[] = [...REMPAR25, ...NON_CYBER];
+255 −0
Original line number Diff line number Diff line
{
  "id": "blackout-electrique",
  "name": "Black-out — coupure électrique prolongée",
  "sector": "Continuité d'activité (PME) / Collectivité",
  "source": "Cythin — kit d'exercice non-cyber (JNR). À valider par un référent gestion de crise avant diffusion.",
  "description": "Une panne électrique majeure (>12 h) frappe {{ville}}. {{organisation}} doit assurer la sécurité des personnes, la continuité des activités essentielles et la communication en mode dégradé.",
  "objectives": "Sécuriser les personnes ; activer les procédures dégradées et le PCA ; gérer l'autonomie énergétique ; communiquer sans les outils habituels.",
  "characters": [
    {
      "ref": "direction",
      "name": "Direction",
      "title": "Cellule de crise",
      "orgUnit": "Direction",
      "kind": "PLAYER",
      "avatarColor": "#d5382f"
    },
    {
      "ref": "continuite",
      "name": "Continuité d'activité",
      "title": "Cellule de crise",
      "orgUnit": "Continuité d'activité",
      "kind": "PLAYER",
      "avatarColor": "#1f9d57"
    },
    {
      "ref": "technique",
      "name": "Technique / systèmes dégradés",
      "title": "Cellule de crise",
      "orgUnit": "Technique / systèmes dégradés",
      "kind": "PLAYER",
      "avatarColor": "#4b6bfb"
    },
    {
      "ref": "communication",
      "name": "Communication",
      "title": "Cellule de crise",
      "orgUnit": "Communication",
      "kind": "PLAYER",
      "avatarColor": "#7d5fff"
    },
    {
      "ref": "rh-securite",
      "name": "RH & sécurité des personnes",
      "title": "Cellule de crise",
      "orgUnit": "RH & sécurité des personnes",
      "kind": "PLAYER",
      "avatarColor": "#c77b00"
    },
    {
      "ref": "logistique",
      "name": "Logistique",
      "title": "Cellule de crise",
      "orgUnit": "Logistique",
      "kind": "PLAYER",
      "avatarColor": "#0e8a9a"
    },
    {
      "ref": "gestionnaire-reseau",
      "name": "{{gestionnaire_reseau}}",
      "title": "Interlocuteur (simulé)",
      "kind": "NPC",
      "avatarColor": "#8695a6"
    },
    {
      "ref": "partenaire",
      "name": "{{partenaire}}",
      "title": "Interlocuteur (simulé)",
      "kind": "NPC",
      "avatarColor": "#8695a6"
    },
    {
      "ref": "salarie",
      "name": "Un salarié",
      "title": "Interlocuteur (simulé)",
      "kind": "NPC",
      "avatarColor": "#8695a6"
    }
  ],
  "channels": [
    {
      "ref": "cellule-crise",
      "name": "cellule-crise"
    },
    {
      "ref": "technique",
      "name": "technique"
    },
    {
      "ref": "rh",
      "name": "rh"
    }
  ],
  "documents": [
    {
      "ref": "dms",
      "folder": "Mise en situation",
      "name": "Dossier de mise en situation",
      "description": "Synopsis et contexte de l'exercice black-out",
      "body": "Exercice de gestion de crise — SIMULATION. Aucun message n'est réellement émis.\n\nContexte : une panne électrique majeure touche {{ville}} ; le rétablissement est estimé à plus de 12 heures. {{organisation}} doit assurer la sécurité des personnes, la continuité des activités essentielles et communiquer en mode dégradé (réseaux et outils habituels indisponibles).\n\nRôles joués : Direction, Continuité d'activité, Technique / systèmes dégradés, Communication, RH & sécurité des personnes, Logistique.\nInterlocuteurs simulés (animation) : {{gestionnaire_reseau}}, {{partenaire}}, clients, presse.\n\nConvention d'exercice : préfixer les échanges par [EXERCICE]. Durée de jeu ~60-75 min, puis RETEX."
    },
    {
      "ref": "pca",
      "folder": "Modèles",
      "name": "PCA / procédures dégradées",
      "description": "Plan de continuité d'activité — trame",
      "body": "Objectif : maintenir les activités essentielles en mode dégradé.\nActivités essentielles (à prioriser) : [lister].\nModes dégradés prévus : [téléphone, papier, site de repli, énergie de secours].\nSeuils de décision : [renvoyer le personnel, suspendre une activité, basculer sur groupe électrogène].\nCommunication de repli : [liste de diffusion SMS, permanence téléphonique, affichage]."
    },
    {
      "ref": "activites-essentielles",
      "folder": "Modèles",
      "name": "Liste des activités essentielles (RTO/RPO)",
      "description": "Tableau des activités critiques et de leurs objectifs de reprise",
      "body": "Activité | Criticité | RTO (délai max d'interruption) | RPO (perte de données tolérée) | Mode dégradé\n[activité 1] | ... | ... | ... | ...\n[activité 2] | ... | ... | ... | ..."
    },
    {
      "folder": "Ressources",
      "name": "Annuaire de crise",
      "description": "Contacts clés (gestionnaire réseau, secours, clients critiques, partenaires) — à compléter par l'animateur."
    },
    {
      "ref": "autonomie",
      "folder": "Fiches",
      "name": "Fiche « autonomie énergétique »",
      "description": "Groupe électrogène, onduleurs, carburant — points de vigilance",
      "body": "Groupe électrogène : capacité, autonomie carburant, équipements prioritaires à brancher.\nOnduleurs (UPS) : durée de tenue, systèmes protégés.\nChaîne du froid : température critique, délai avant perte.\nCarburant : stock, réapprovisionnement, priorités d'usage."
    },
    {
      "ref": "retex",
      "folder": "RETEX",
      "name": "RETEX — grille de débrief",
      "description": "Questions de retour d'expérience",
      "body": "La sécurité des personnes a-t-elle primé ?\nLes activités essentielles ont-elles été identifiées et priorisées ?\nL'autonomie énergétique était-elle suffisante / testée ?\nLa communication clients & salariés a-t-elle été assurée en mode dégradé ?"
    }
  ],
  "injects": [
    {
      "offsetMinutes": 0,
      "channel": "CHAT",
      "title": "DEBEX — coupure",
      "body": "Coupure générale sur le site. Le groupe électrogène ne démarre pas. On est dans le noir, on cherche l'origine.",
      "senderRef": "technique",
      "channelRef": "technique"
    },
    {
      "offsetMinutes": 5,
      "channel": "EMAIL",
      "title": "Incident majeur",
      "subject": "[Réseau] Incident majeur — rétablissement > 12 h",
      "body": "Un incident réseau étendu affecte {{ville}}. Le rétablissement est estimé à plus de 12 heures. Nous vous tiendrons informés de l'évolution.",
      "senderRef": "gestionnaire-reseau",
      "attachmentRefs": [
        "dms"
      ]
    },
    {
      "offsetMinutes": 10,
      "channel": "CALL",
      "title": "Personnes bloquées",
      "body": "Faire remonter à la cellule : des personnes sont bloquées dans un ascenseur sur site. Objectif : déclencher une mise en sécurité immédiate (priorité aux personnes).",
      "to": "Un agent, depuis le site (au téléphone)"
    },
    {
      "offsetMinutes": 15,
      "channel": "CHAT",
      "title": "Que dit-on aux salariés",
      "body": "Télétravail impossible (box HS), plus de réseau. Faut-il renvoyer le personnel ou le maintenir sur site ? On a besoin d'une consigne RH.",
      "senderRef": "rh-securite",
      "channelRef": "rh"
    },
    {
      "offsetMinutes": 20,
      "channel": "EMAIL",
      "title": "Chaîne du froid / onduleurs",
      "subject": "[Alerte] Onduleurs ~2 h, chaîne du froid menacée",
      "body": "Les onduleurs tiennent environ 2 heures ; au-delà, la chaîne du froid est menacée. Quelles sont vos priorités de sauvegarde ? Merci de trancher rapidement.",
      "senderRef": "partenaire"
    },
    {
      "offsetMinutes": 22,
      "channel": "SOCIAL",
      "title": "Bruit — Rumeur cyberattaque (désinformation)",
      "body": "La coupure à {{ville}} ce serait une CYBERATTAQUE, on nous cache que des données ont fuité 😱 Passez le mot #blackout",
      "network": "X",
      "authorName": "InfoLibre {{ville}}",
      "authorHandle": "infolibre.actu",
      "likes": 132
    },
    {
      "offsetMinutes": 25,
      "channel": "SOCIAL",
      "title": "Pression clients",
      "body": "{{organisation}} injoignable, ma commande est bloquée, service déplorable. Quelqu'un répond ?? #panne",
      "network": "X",
      "authorName": "Dominique",
      "authorHandle": "dom_client",
      "likes": 61
    },
    {
      "offsetMinutes": 30,
      "channel": "CALL",
      "title": "Logistique bloquée",
      "body": "Jouer un fournisseur : « Livraison impossible, les feux tricolores sont HS et la circulation est paralysée à {{ville}}. Qu'est-ce que je fais de la marchandise ? » Objectif : arbitrer la logistique en mode dégradé.",
      "to": "Un fournisseur (au téléphone)"
    },
    {
      "offsetMinutes": 35,
      "channel": "CALL",
      "title": "Bruit — Faux journaliste",
      "body": "Jouer un inconnu se présentant comme journaliste : « C'est off, entre nous — vous confirmez que la production est à l'arrêt et que vous perdez de l'argent chaque heure ? » Objectif : tester la discipline de communication et l'orientation vers le porte-parole.",
      "to": "Un inconnu se présentant comme journaliste (au téléphone)"
    },
    {
      "offsetMinutes": 40,
      "channel": "NEWS",
      "title": "Couverture presse",
      "subject": "Panne géante : {{ville}} plongée dans le noir",
      "body": "Une panne électrique de grande ampleur prive {{ville}} d'électricité depuis ce matin. Commerces fermés, feux hors service : les entreprises locales, dont {{organisation}}, sont à l'arrêt.",
      "outlet": "GENERIC",
      "newsSource": "{{media}}",
      "newsCategory": "Économie"
    },
    {
      "offsetMinutes": 45,
      "channel": "EMAIL",
      "title": "Bruit — Chaîne interne anxiogène",
      "subject": "On reste dans le noir ? les gens commencent à paniquer",
      "body": "Un salarié écrit à toute la liste interne : « Personne ne nous dit rien, on reste combien de temps ? certains parlent déjà de rentrer chez eux, ça part dans tous les sens… » Objectif : reprendre la main sur la communication interne.",
      "senderRef": "salarie"
    },
    {
      "offsetMinutes": 50,
      "channel": "CHAT",
      "title": "Groupe électrogène",
      "body": "Le groupe redémarre mais le carburant est limité (~6 h). Qu'est-ce qu'on branche en priorité ? On attend l'arbitrage.",
      "senderRef": "technique",
      "channelRef": "technique"
    },
    {
      "offsetMinutes": 60,
      "channel": "EMAIL",
      "title": "Rétablissement partiel",
      "subject": "[Réseau] Rétablissement partiel par quartiers",
      "body": "Le courant est rétabli partiellement, quartier par quartier. Merci de nous confirmer vos points critiques pour prioriser.",
      "senderRef": "gestionnaire-reseau"
    },
    {
      "offsetMinutes": 70,
      "channel": "EMAIL",
      "title": "FINEX — retour courant",
      "subject": "[FINEX] Courant rétabli — redémarrage ordonné",
      "body": "Le courant est rétabli. Procédez à un redémarrage ordonné des systèmes, vérifiez les données et l'intégrité des équipements, puis établissez le bilan et le RETEX. Fin de l'exercice.",
      "senderRef": "gestionnaire-reseau"
    }
  ]
}
+250 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading