# Un centre hospitalier headless : anonymiser les champs patients

> Une API REST expose par défaut bien plus de champs qu'un front n'en affiche. Checklist des champs à exclure ou pseudonymiser avant qu'ils ne fuitent en public.

- Auteur : WordPress Développement
- Publié le : 2021-05-27
- Mis à jour le : 2021-05-27
- Catégorie : Headless &amp; API
- URL : https://www.wpmoderne.fr/headless/centre-hospitalier-headless-anonymiser-champs-patients/

## L’essentiel

- register_rest_field expose ce qu'on ajoute, pas ce qu'on retire
- Un champ jamais affiché par le front reste accessible via l'API brute
- La checklist doit être revue à chaque nouveau champ ACF ajouté

Une API REST expose systématiquement plus de données que ce qu'un front consomme réellement : c'est un fait structurel, pas une négligence isolée. Sur le site vitrine d'un centre hospitalier proposant la prise de rendez-vous en ligne via un WordPress headless, ce constat a pris une tournure sérieuse : plusieurs champs personnalisés liés aux fiches de rendez-vous, jamais affichés par le front, restaient accessibles en clair via l'endpoint `wp/v2/rendez_vous` pour quiconque connaissait l'URL.

Cette checklist recense les champs à exclure ou à pseudonymiser côté WordPress avant qu'une API REST publique ne les expose, sans entrer dans la question de l'hébergement des données de santé elles-mêmes, qui relève d'un cadre réglementaire distinct (HDS) et d'un choix d'infrastructure à part.

## Pourquoi l'exposition par défaut surprend souvent

Un champ ACF ajouté à un type de contenu personnalisé, dès lors que ce type est enregistré avec `show_in_rest => true`, apparaît automatiquement dans la réponse de l'API REST via le sous-objet `acf`, sans qu'aucune action explicite ne soit nécessaire pour l'exposer. Beaucoup d'équipes découvrent ce comportement après coup, en constatant qu'un champ jamais affiché par le front est pourtant lisible en clair dans la réponse JSON brute.

## La checklist avant mise en production

1. Lister l'intégralité des champs personnalisés (ACF ou meta natives) attachés au type de contenu exposé en REST, sans se fier uniquement à ce que le front affiche.
2. Identifier parmi eux les champs contenant une donnée directement identifiante (nom, numéro de sécurité sociale, date de naissance complète) ou une donnée médicale (motif de consultation, traitement en cours).
3. Pour chaque champ sensible identifié, décider explicitement : exclusion totale de l'API, ou pseudonymisation avant exposition.
4. Vérifier que les rôles disposant d'un accès authentifié à l'API (personnel administratif) ne voient exposés que les champs strictement nécessaires à leur usage, via un contrôle de capacité.
5. Retester après chaque ajout de champ ACF : cette checklist n'est pas un contrôle ponctuel, mais une vérification à répéter à chaque évolution du type de contenu.

> L'essentiel à retenir : register_rest_field expose ce qu'on ajoute, pas ce qu'on retire ; Un champ jamais affiché par le front reste accessible via l'API brute ; La checklist doit être revue à chaque nouveau champ ACF ajouté

## Exclure un champ de l'API REST

Le filtre `rest_prepare_{$post_type}` permet de retirer explicitement un champ de la réponse juste avant son envoi, quelle que soit la manière dont il a été ajouté initialement :

```
add_filter('rest_prepare_rendez_vous', function ($response, $post, $request) {
    $data = $response->get_data();

    unset($data['acf']['motif_consultation']);
    unset($data['acf']['numero_secu']);
    unset($data['acf']['notes_internes']);

    $response->set_data($data);
    return $response;
}, 10, 3);
```

Cette approche reste explicite et facile à auditer : chaque exclusion est visible en un coup d'œil dans une seule fonction, plutôt que dispersée dans la configuration de chaque champ ACF individuellement.

## Pseudonymiser plutôt qu'exclure

Certains champs restent utiles au front sous une forme partielle : afficher les initiales d'un patient dans un espace personnel authentifié, sans exposer son nom complet dans la réponse brute de l'API, par exemple. Le même filtre permet cette transformation :

```
add_filter('rest_prepare_rendez_vous', function ($response, $post, $request) {
    $data = $response->get_data();

    if (!empty($data['acf']['nom_patient'])) {
        $mots = explode(' ', $data['acf']['nom_patient']);
        $data['acf']['nom_patient'] = implode(' ', array_map(
            fn($mot) => mb_substr($mot, 0, 1) . '.',
            $mots
        ));
    }

    $response->set_data($data);
    return $response;
}, 10, 3);
```

## Ce que la checklist ne couvre pas

Cette checklist porte exclusivement sur la surface d'exposition de l'API REST, une fois le contenu déjà stocké dans WordPress. Elle ne traite ni du chiffrement au repos, ni de l'hébergement conforme aux exigences applicables aux données de santé, deux sujets qui relèvent du choix d'infrastructure et du prestataire d'hébergement, indépendamment de la configuration applicative décrite ici.

- Un champ exclu de l'API REST publique doit l'être aussi de tout endpoint personnalisé ajouté ultérieurement au même type de contenu.
- Un accès authentifié (personnel soignant) n'est pas une excuse pour exposer davantage de champs que nécessaire à cet usage précis.
- La revue de cette checklist doit être intégrée au processus de recette, pas laissée à la mémoire de l'équipe.

> Le champ le plus dangereux d'une API n'est presque jamais celui qu'on affiche par erreur : c'est celui qu'on a oublié d'exclure, parce que le front, lui, ne l'a jamais demandé.

## En résumé

Un WordPress headless expose, par défaut, tout ce qu'il sait sur un contenu, indépendamment de ce que le front en affiche réellement. Sur un projet manipulant des données sensibles, cette checklist doit devenir un réflexe systématique à chaque ajout de champ, et non une vérification a posteriori une fois le problème découvert en production.
