
# SCIM プロビジョニングのシミュレーション

`POST /v1/directories/{directory_id}:simulate` · 権限 `directories:write` · 開発環境およびステージング環境のみ

ディレクトリの実際の SCIM エンドポイントに対して、SCIM シミュレーターのシナリオを 1 つ実行します。この実行のためだけに、KeenAuth は実際の SCIM トークンを発行して使用し、その後で取り消します。トークンの検証、レート制限、大量デプロビジョニングのサーキットブレーカー、プロビジョニングログは、ID プロバイダーの場合とまったく同様に動作します。ユーザーは固定されたフィクションのセットです。`example.test` の 5 つのグループに属する 25 名です。実在の個人データは含まれません。

シミュレーターは開発用ツールであり、ディレクトリを変更します。シミュレーターが書き込んだユーザーとグループは、ほかのプロビジョニング済みのレコードと同様にディレクトリに残ります。テスト用に作成したディレクトリを使用してください。

| シナリオ | 動作 |
|---|---|
| `seed` | 25 名のユーザーと 5 つのグループを、そのメンバーシップとともに作成します。すでにこれらが存在するディレクトリでは、最初のユーザーで SCIM の `409` が返され、実行は `failed` になります。 |
| `bulk_deactivate` | ユーザーの 60%（25 名中 15 名）に `active=false` を送信します。サーキットブレーカーは、ディレクトリの `mass_deprovision_guard.absolute_min` が 15 以下の場合にのみ作動します。既定値の 25 の場合は作動しません。 |
| `group_churn` | あるユーザーを、あるグループから別のグループへ移動します。 |
| `attribute_update` | すべてのユーザーの表示名と姓を変更します。 |
| `conflict_email` | 既存の `userName` を持つユーザーを作成し、SCIM の `409 uniqueness` を期待します。 |

ディレクトリが空の場合、`seed` 以外のすべてのシナリオは、まず `seed` を実行します。

シミュレーション用のトークンは一覧に表示されず、有効なトークン 2 件の数にも含まれません。これを使用しても、ID プロバイダーのトークンのローテーションは開始されません。ディレクトリごとに同時に実行できるのは 1 回だけです。この実行は `directory.simulation_started` と `directory.simulation_finished` として監査されます。

## リクエスト

| フィールド | 種類 | 必須 | 説明 |
|---|---|---|---|
| `directory_id` | パス | はい | SCIM ディレクトリ ID（`dir_…`）。 |
| `scenario` | ボディ、文字列 | はい | `seed`、`bulk_deactivate`、`group_churn`、`attribute_update`、`conflict_email` のいずれか。 |
| `Idempotency-Key` | ヘッダー | いいえ | 再試行されたリクエストに対して最初のレスポンスを再送します。シナリオは再実行されません。 |

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

## レスポンス

実行結果を含む `200 OK`。SCIM のエラー応答があっても、リクエストは失敗しません。その場合、実行は `failed` になり、`failure` が設定され、件数はエラーの前に成功した分のままになります。結果に含まれるのは件数と状態のみです。ユーザー、SCIM ID、トークンは含まれません。

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

| フィールド | 説明 |
|---|---|
| `status` | `completed`。エンドポイントが SCIM のエラーを返した、実行に時間がかかりすぎた、または応答がシナリオの期待と異なった場合は `failed`。 |
| `users_updated` | 無効化以外のユーザーに対する PATCH。 |
| `users_deactivated` | エンドポイントが受け付けた `active=false` の PATCH。保留されたものを含みます。 |
| `conflicts` | 期待どおりの `409 uniqueness` 応答（`conflict_email`）。 |
| `circuit_breaker_tripped` | 実行中に大量デプロビジョニングの保留が開かれた。 |
| `deprovision_hold` | 実行後のディレクトリの未決定の保留。ない場合は `null`。`deprovision-holds` エンドポイントで承認または却下できます。 |
| `failure` | `completed` の場合は `null`。それ以外の場合は `reason`（`scim_error`、`timeout`、`unexpected_response` のいずれか）。`scim_error` の場合は `scim_status`（HTTP ステータス）と `scim_type`（SCIM の `scimType`、または `null`）も含まれます。 |

## エラー

| HTTP | コード | 発生条件 |
|---|---|---|
| 400 | `unknown_field` | ボディに `scenario` 以外のフィールドが含まれている。 |
| 403 | `test_feature_not_in_production` | この環境は本番環境である。 |
| 404 | `not_found` | この環境にディレクトリが存在しない。 |
| 409 | `conflict` | このディレクトリで別の実行が進行中である、またはディレクトリが無効化されている、もしくは削除中である。 |
| 422 | `validation_failed` | `scenario` が指定されていない、または不明である（`/scenario`）。 |
| 422 | `idempotency_key_reuse` | `Idempotency-Key` が別のリクエストで使用された。 |
| 401 | `unauthenticated` | 認証情報がない、無効である、または取り消されている。 |
| 403 | `insufficient_permissions` | 認証情報に必要な権限がない。 |
| 429 | `rate_limited` | レート制限を超えた。`Retry-After` の期間を待ってから再試行してください。 |
| 503 | `service_unavailable` | ディレクトリ同期またはシミュレーターが一時的に利用できないか、このデプロイメントで未設定である。`Retry-After` の期間を待ってから再試行してください。 |

## 例

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