
# SCIM-Provisionierung simulieren

`POST /v1/directories/{directory_id}:simulate` · Berechtigung `directories:write` · nur Entwicklung und Staging

Führt ein SCIM-Simulator-Szenario gegen den echten SCIM-Endpunkt des Verzeichnisses aus. Nur für diesen Lauf erstellt KeenAuth ein echtes SCIM-Token, verwendet es und widerruft es anschließend. Token-Prüfungen, Ratenlimits, der Schutzschalter für Massen-Deprovisionierung und das Provisionierungsprotokoll laufen genauso ab wie bei Ihrem Identitätsanbieter. Die Benutzer sind ein festes, fiktives Set: 25 Personen unter `example.test` in 5 Gruppen. Sie enthalten keine echten personenbezogenen Daten.

Der Simulator ist ein Entwicklungswerkzeug und verändert das Verzeichnis. Die Benutzer und Gruppen, die er schreibt, bleiben wie alle anderen provisionierten Datensätze im Verzeichnis erhalten. Verwenden Sie ein Verzeichnis, das Sie für Tests angelegt haben.

| Szenario | Was es tut |
|---|---|
| `seed` | Legt die 25 Benutzer und die 5 Gruppen mit ihren Mitgliedschaften an. In einem Verzeichnis, das sie bereits enthält, erhält der erste Benutzer ein SCIM-`409`, und der Lauf ist `failed`. |
| `bulk_deactivate` | Sendet `active=false` für 60 % der Benutzer (15 von 25). Der Schutzschalter löst nur aus, wenn `mass_deprovision_guard.absolute_min` des Verzeichnisses 15 oder weniger beträgt. Mit dem Standardwert von 25 löst er nicht aus. |
| `group_churn` | Verschiebt einen Benutzer von einer Gruppe in eine andere. |
| `attribute_update` | Ändert den Anzeigenamen und den Nachnamen jedes Benutzers. |
| `conflict_email` | Legt einen Benutzer mit einem bereits vorhandenen `userName` an und erwartet ein SCIM-`409 uniqueness`. |

Wenn das Verzeichnis leer ist, führt jedes Szenario außer `seed` zuerst `seed` aus.

Das Simulations-Token wird nie aufgelistet und zählt nicht zu den 2 gültigen Token. Seine Verwendung startet nicht die Rotation des Tokens Ihres Identitätsanbieters. Pro Verzeichnis kann nur ein Lauf gleichzeitig laufen. Der Lauf wird als `directory.simulation_started` und `directory.simulation_finished` protokolliert.

## Anfrage

| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
| `directory_id` | Pfad | ja | SCIM-Verzeichnis-ID (`dir_…`). |
| `scenario` | Body, string | ja | `seed`, `bulk_deactivate`, `group_churn`, `attribute_update` oder `conflict_email`. |
| `Idempotency-Key` | Header | nein | Wiederholt die erste Antwort bei einer erneuten Anfrage; das Szenario wird nicht erneut ausgeführt. |

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

## Antwort

`200 OK` mit dem Ergebnis des Laufs. Eine SCIM-Fehlerantwort lässt die Anfrage nicht fehlschlagen. Sie setzt den Lauf auf `failed`, füllt `failure` aus und belässt die Zähler bei dem, was vor dem Fehler erfolgreich war. Das Ergebnis enthält nur Zähler und Zustände: keinen Benutzer, keine SCIM-ID und kein Token.

```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"
}
```

| Feld | Beschreibung |
|---|---|
| `status` | `completed`, oder `failed`, wenn der Endpunkt mit einem SCIM-Fehler antwortete, der Lauf zu lange dauerte oder eine Antwort nicht dem entsprach, was das Szenario erwartete. |
| `users_updated` | Benutzer-PATCHes außer Deaktivierungen. |
| `users_deactivated` | Vom Endpunkt akzeptierte `active=false`-PATCHes, einschließlich zurückgehaltener. |
| `conflicts` | Erwartete `409 uniqueness`-Antworten (`conflict_email`). |
| `circuit_breaker_tripped` | Während des Laufs wurde eine Sperre für Massen-Deprovisionierung geöffnet. |
| `deprovision_hold` | Die offene Sperre des Verzeichnisses nach dem Lauf, oder `null`. Genehmigen oder lehnen Sie sie über die Endpunkte `deprovision-holds` ab. |
| `failure` | `null` bei `completed`. Andernfalls `reason` (`scim_error`, `timeout` oder `unexpected_response`) und bei `scim_error` außerdem `scim_status` (HTTP-Status) und `scim_type` (SCIM-`scimType` oder `null`). |

## Fehler

| HTTP | Code | Wann |
|---|---|---|
| 400 | `unknown_field` | Der Body enthält ein anderes Feld als `scenario`. |
| 403 | `test_feature_not_in_production` | Die Umgebung ist eine Produktionsumgebung. |
| 404 | `not_found` | Das Verzeichnis existiert in dieser Umgebung nicht. |
| 409 | `conflict` | Ein anderer Lauf dieses Verzeichnisses ist in Arbeit, oder das Verzeichnis ist deaktiviert oder wird gelöscht. |
| 422 | `validation_failed` | `scenario` fehlt oder ist unbekannt (`/scenario`). |
| 422 | `idempotency_key_reuse` | Der `Idempotency-Key` wurde für eine andere Anfrage verwendet. |
| 401 | `unauthenticated` | Die Anmeldedaten fehlen, sind ungültig oder widerrufen. |
| 403 | `insufficient_permissions` | Die Anmeldedaten haben nicht die erforderliche Berechtigung. |
| 429 | `rate_limited` | Das Ratenlimit wurde überschritten; wiederholen Sie die Anfrage nach der Zeitspanne `Retry-After`. |
| 503 | `service_unavailable` | Verzeichnissynchronisierung oder Simulator sind vorübergehend nicht verfügbar oder in dieser Bereitstellung nicht konfiguriert; wiederholen Sie die Anfrage nach der Zeitspanne `Retry-After`. |

## Beispiel

```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
```
