{
  "contract_version": "gab_348_contract_v1",
  "gab_id": "GAB-348",
  "canonical_name": "SafetyFallbackLearningPrivacyDataWarning",
  "module_owner": "EdTechSafetyFallbackLearning",
  "renderer_key": "text_cta",
  "required_fields": [
    "gab_id",
    "privacy_warning_id",
    "document",
    "detection_notice",
    "primary_cta"
  ],
  "optional_fields": [
    "title",
    "state_badge",
    "secondary_cta",
    "mask_feedback",
    "keep_feedback",
    "use_when",
    "do_not_use_when",
    "child_safety"
  ],
  "field_types": {
    "document": "object{kind,original_text,masked_text}",
    "detection_notice": "string — message de détection des données personnelles (affiché en panneau warn)",
    "primary_cta": "object{label,action,masked_label,next_state}",
    "secondary_cta": "object{label,action,next_state}",
    "state_badge": "enum['risk_detected','private_mode','confirmation_needed']",
    "use_when": "array<string>",
    "do_not_use_when": "array<string>",
    "child_safety": "object{minimization:boolean,user_choice:boolean,no_clear_storage:boolean,minor_message}"
  },
  "constraints": [
    "Tout texte (detection_notice, feedbacks, masked_text) vient du JSON — aucune donnée perso ni message inventé.",
    "Minimisation par défaut : on rappelle que les données ne sont pas nécessaires pour apprendre.",
    "Choix laissé à l'élève : masquer OU garder, jamais imposé, jamais bloquant.",
    "Aucun stockage en clair : le masquage est purement d'affichage côté renderer."
  ],
  "blocked_conditions": [
    "document.original_text absent",
    "detection_notice absent",
    "primary_cta absent"
  ],
  "accessibility": [
    "keyboard_navigable",
    "focus_visible",
    "prefers_reduced_motion",
    "fallback_text"
  ],
  "qa_cases": [
    { "case": "instance conforme", "expected": "rendu complet, 0 erreur, badge risk_detected" },
    { "case": "champ requis manquant", "expected": "BLOCKED listant le champ" },
    { "case": "clic Masquer", "expected": "texte remplacé par masked_text, badge private_mode, panneau ok, bouton désactivé" },
    { "case": "clic Garder", "expected": "badge confirmation_needed, panneau warn rappelant la minimisation" },
    { "case": "instance externe injectée", "expected": "le rendu change sans modifier le HTML" },
    { "case": "responsive 375/768/1024", "expected": "aucun débordement horizontal" }
  ],
  "traceability": {
    "derived_from_core_gab": "GAB-348",
    "note": "Ce schema VALIDE l'instance. Le contrat pédagogique complet (input_contract/validation_logic/feedback_scoring_logic) vit dans le CORE-GAB officiel, pas ici (évite la duplication)."
  }
}
