
# Simuler le provisioning SCIM

`POST /v1/directories/{directory_id}:simulate` · autorisation `directories:write` · développement et préproduction uniquement

Exécute un scénario du simulateur SCIM sur le point de terminaison SCIM réel de l'annuaire. Uniquement pour la durée de l'exécution, KeenAuth génère un véritable jeton SCIM, l'utilise, puis le révoque. Les vérifications des jetons, les limites de débit, le disjoncteur de désprovisionnement en masse et le journal de provisioning s'appliquent exactement comme pour votre fournisseur d'identité. Les utilisateurs forment un ensemble fictif fixe : 25 personnes sur `example.test` réparties en 5 groupes. Ils ne contiennent aucune donnée personnelle réelle.

Le simulateur est un outil de développement et il modifie l'annuaire. Les utilisateurs et les groupes qu'il crée restent dans l'annuaire comme tout autre enregistrement provisionné. Utilisez un annuaire que vous avez créé pour les tests.

| Scénario | Ce qu'il fait |
|---|---|
| `seed` | Crée les 25 utilisateurs et les 5 groupes avec leurs appartenances. Dans un annuaire qui les contient déjà, le premier utilisateur reçoit un SCIM `409` et l'exécution passe à `failed`. |
| `bulk_deactivate` | Envoie `active=false` pour 60 % des utilisateurs (15 sur 25). Le disjoncteur ne se déclenche que si `mass_deprovision_guard.absolute_min` de l'annuaire est égal ou inférieur à 15. Avec la valeur par défaut de 25, il ne se déclenche pas. |
| `group_churn` | Déplace un utilisateur d'un groupe à un autre. |
| `attribute_update` | Modifie le nom d'affichage et le nom de famille de chaque utilisateur. |
| `conflict_email` | Crée un utilisateur avec un `userName` existant et attend un SCIM `409 uniqueness`. |

Lorsque l'annuaire est vide, tous les scénarios sauf `seed` exécutent d'abord `seed`.

Le jeton de simulation n'est jamais listé et ne compte pas parmi les 2 jetons valides. Son utilisation ne démarre pas la rotation du jeton de votre fournisseur d'identité. Une seule exécution peut être en cours par annuaire à la fois. L'exécution est consignée dans l'audit sous les événements `directory.simulation_started` et `directory.simulation_finished`.

## Requête

| Champ | Type | Obligatoire | Description |
|---|---|---|---|
| `directory_id` | chemin | oui | ID de l'annuaire SCIM (`dir_…`). |
| `scenario` | corps, chaîne | oui | `seed`, `bulk_deactivate`, `group_churn`, `attribute_update` ou `conflict_email`. |
| `Idempotency-Key` | en-tête | non | Rejoue la première réponse pour une requête relancée ; le scénario ne s'exécute pas à nouveau. |

```json
{"scenario": "bulk_deactivate"}
```

## Réponse

`200 OK` avec le résultat de l'exécution. Une réponse d'erreur SCIM ne fait pas échouer la requête. Elle fait passer l'exécution à `failed`, renseigne `failure` et laisse les compteurs à ce qui a réussi avant l'erreur. Le résultat ne contient que des compteurs et des états : aucun utilisateur, aucun ID SCIM et aucun jeton.

```json
{
  "directory_id": "dir_01j9xm2n4p6q8r0s2t4v6w8y0z",
  "scenario": "bulk_deactivate",
  "status": "completed",
  "users_created": 0,
  "groups_created": 0,
  "users_updated": 0,
  "groups_updated": 0,
  "users_deactivated": 15,
  "conflicts": 0,
  "circuit_breaker_tripped": true,
  "deprovision_hold": {"id": "0191e9b2-6f3a-7c4d-8e5f-0a1b2c3d4e5f", "pending_count": 6},
  "failure": null,
  "started_at": "2026-10-28T09:31:00.123456Z",
  "completed_at": "2026-10-28T09:31:01.654321Z"
}
```

| Champ | Description |
|---|---|
| `status` | `completed`, ou `failed` lorsque le point de terminaison a répondu par une erreur SCIM, que l'exécution a duré trop longtemps ou qu'une réponse ne correspondait pas à ce que le scénario attendait. |
| `users_updated` | Modifications PATCH d'utilisateurs autres que les désactivations. |
| `users_deactivated` | Requêtes PATCH `active=false` acceptées par le point de terminaison, y compris celles mises en suspens. |
| `conflicts` | Réponses `409 uniqueness` attendues (`conflict_email`). |
| `circuit_breaker_tripped` | Une suspension de désprovisionnement en masse a été ouverte pendant l'exécution. |
| `deprovision_hold` | La suspension ouverte de l'annuaire après l'exécution, ou `null`. Approuvez-la ou rejetez-la avec les points de terminaison `deprovision-holds`. |
| `failure` | `null` lorsque `completed`. Sinon `reason` (`scim_error`, `timeout` ou `unexpected_response`), et pour `scim_error` également `scim_status` (statut HTTP) et `scim_type` (`scimType` SCIM, ou `null`). |

## Erreurs

| HTTP | code | Quand |
|---|---|---|
| 400 | `unknown_field` | Le corps contient un champ autre que `scenario`. |
| 403 | `test_feature_not_in_production` | L'environnement est un environnement de production. |
| 404 | `not_found` | L'annuaire n'existe pas dans cet environnement. |
| 409 | `conflict` | Une autre exécution de cet annuaire est en cours, ou l'annuaire est désactivé ou en cours de suppression. |
| 422 | `validation_failed` | `scenario` est absent ou inconnu (`/scenario`). |
| 422 | `idempotency_key_reuse` | La `Idempotency-Key` a été utilisée pour une autre requête. |
| 401 | `unauthenticated` | L'identifiant est absent, invalide ou révoqué. |
| 403 | `insufficient_permissions` | L'identifiant ne dispose pas de l'autorisation requise. |
| 429 | `rate_limited` | La limite de débit a été dépassée ; réessayez après la durée indiquée par `Retry-After`. |
| 503 | `service_unavailable` | La synchronisation de l'annuaire ou le simulateur est temporairement indisponible ou non configuré dans ce déploiement ; réessayez après la durée indiquée par `Retry-After`. |

## Exemple

```bash
curl -X POST "https://api.eu.keenauth.com/v1/directories/dir_01j9xm2n4p6q8r0s2t4v6w8y0z:simulate" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"scenario": "seed"}'
```

```bash
keenauth directories simulate dir_01j9xm2n4p6q8r0s2t4v6w8y0z --scenario bulk_deactivate
```
