Skills/production-resilience-obser.../SKILL.md

4.8 KiB

name description
production-resilience-observability Implement production resilience and observability: nested React Error Boundaries, graceful UI degradation, PII-safe telemetry, structured error logging, and retry mechanisms.

Production Resilience & Observability Architecture

Ce skill empêche l'écran blanc fatal (White Screen of Death). Il impose l'encapsulation modulaire des composants dans des Error Boundaries imbriquées, fournit des interfaces de dégradation gracieuse avec réessai sans rechargement de page, et configure la télémétrie conforme au RGPD (anonymisation stricte des données personnelles dans les logs).


🎯 Déclencheurs d'Activation

Activez ce skill dès que :

  1. Vous intégrez des composants tiers ou dépendants d'un service distant instable (graphiques, flux en direct, météo, intégrations bancaires).
  2. Vous structurez l'architecture racine d'une application ou les gabarits de mise en page (Layouts).
  3. Vous mettez en place la capture d'erreurs en production (Sentry, OpenTelemetry, Datadog).
  4. Vous configurez des flux de réessai utilisateur en cas d'échec de rendu.
  5. Vous auditez la protection contre les fuites de données personnelles dans les journaux système (PII Masking).

🛡️ 1. Error Boundaries Imbriquées (Isolation des Pannes)

Une erreur dans une bannière ou un graphique secondaire ne doit jamais casser la barre de navigation ou le tableau de bord principal.

'use client';

import React from 'react';
import { ErrorBoundary, FallbackProps } from 'react-error-boundary';

// Interface de repli modulaire avec bouton de réessai ciblé
export const ComponentErrorFallback: React.FC<FallbackProps> = ({ error, resetErrorBoundary }) => {
  return (
    <div 
      role="alert" 
      className="p-5 rounded-xl bg-rose-500/5 border border-rose-500/20 text-start flex flex-col gap-3"
    >
      <div className="flex items-center gap-2 text-rose-400 font-semibold text-sm">
        <span className="size-2 rounded-full bg-rose-400" />
        Une erreur temporaire est survenue
      </div>
      <p className="text-xs text-white/60">
        Ce widget n'a pas pu être chargé. Les autres services restent pleinement opérationnels.
      </p>
      <button
        type="button"
        onClick={resetErrorBoundary}
        className="self-start px-3 py-1.5 rounded-md text-xs font-medium text-white bg-white/10 hover:bg-white/15 
                   border border-white/10 transition-all focus-visible:ring-2 focus-visible:ring-rose-400"
      >
        Réessayer le chargement
      </button>
    </div>
  );
};

// Encapsulation déclarative
export const SafeWidgetWrapper = ({ children }: { children: React.ReactNode }) => {
  return (
    <ErrorBoundary
      FallbackComponent={ComponentErrorFallback}
      onReset={() => {
        // Nettoyage ou réinitialisation d'état local si besoin
      }}
      onError={(error, info) => {
        // Journalisation sécurisée
        logSafeError(error, info);
      }}
    >
      {children}
    </ErrorBoundary>
  );
};

🔒 2. Journalisation PII-Safe (Conformité RGPD)

Il est illégal et dangereux d'envoyer des mots de passe, tokens JWT ou adresses email privées dans des outils de tracking de bugs comme Sentry ou Datadog :

// Filtrage et assainissement des données avant expédition
export function logSafeError(error: Error, errorInfo?: any) {
  const sanitizedContext = {
    message: error.message,
    stack: error.stack,
    componentStack: errorInfo?.componentStack,
    url: window.location.pathname, // Pas de paramètres de requête sensibles (?token=...)
    timestamp: new Date().toISOString(),
  };

  // Masquage des motifs sensibles (regex token/mot de passe/email)
  const payloadString = JSON.stringify(sanitizedContext)
    .replace(/"(password|token|secret|apiKey)":\s*"[^"]+"/gi, '"$1": "[REDACTED]"')
    .replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g, '[EMAIL_REDACTED]');

  // Expédition sécurisée vers l'outil d'observabilité
  if (process.env.NODE_ENV === 'production') {
    // Sentry.captureException(...) ou fetch('/api/telemetry', { body: payloadString })
  } else {
    console.error('Safe Dev Error Log:', JSON.parse(payloadString));
  }
}

📋 Checklist de Conformité Résilience & Observabilité

  • Les widgets à risque ou asynchrones sont isolés par leur propre ErrorBoundary.
  • Le composant de repli (Fallback) offre un bouton d'action clair pour retenter sans recharger la page entière.
  • Aucune donnée personnelle (email, mot de passe, token en URL) n'est envoyée aux outils de télémétrie.
  • Le Layout racine possède une frontière d'erreur globale (global-error.tsx dans Next.js).
  • Les promesses non interceptées (unhandled rejections) sont écoutées et journalisées proprement.