
# Yapılandırma planını uygula

`POST /v1/config-plans/{plan_id}:apply` · izin `config:write`, planın okuma izinleri ve değiştirdiği her tür için yazma izni

Ortamda kayıtlı bir [planı](create.md) uygular. Her değişiklik tek bir işlemde yazılır: biri başarısız olursa hiçbiri kaydedilmez. Bir plan yalnızca bir kez uygulanabilir.

## İstek

| Parametre | Açıklama |
|---|---|
| `plan_id` | Plan kimliği, `cfgp_…`. |

İstek gövdesi isteğe bağlıdır.

| Alan | Açıklama |
|---|---|
| `resolved_secrets` | `requires_secret: true` ile her değişiklik için `secret_ref` adı → değeri nesnesi (örneğin `KEENAUTH_CONNECTION_GITHUB_CLIENT_SECRET`). Değerler en fazla 8 KiB olabilir. Plan tarafından hiçbir zaman saklanmaz, günlüğe yazılmaz ve döndürülmez. |
| `confirm_deletions` | Onayladığınız `<kind>/<key>` silmelerinin listesi, örneğin `connection/legacy`. Planın `deletion_requires_confirmation` uyarıları bunu gerektiren silmeleri listeler. |
| `sp_host` | Ortamın hizmet sağlayıcı ana makinesi, örneğin `login.example.com`. Yalnızca plan kurumsal bağlantının OIDC materyalini oluşturduğunda gerekir (geri çağırma `https://<sp_host>/sso/<connection id>/callback` bundan sabitlenir); bunu gerektirmeyen bir istekte gönderilmemelidir. |

- Yazma izinleri şunlardır: `environment-settings:write`, `identity-settings:write`, `attack-protection:write`, `branding:write` (`branding` ve `application_branding` için), `connections:write`, `apis:write`, `roles:write` ve `applications:write`. Bunlar yalnızca `no_op` dışında bir değişikliği olan türler için gerekir.
- Yazmadan önce hedef yeniden okunur. Planlanan kaynakların herhangi birinin sürümü veya planın türlerinin içeriği plan oluşturulduktan sonra değiştiyse hiçbir şey yazılmaz, plan `conflicted` olur ve istek `409 config_conflict` hatasıyla başarısız olur. Yeni bir plan oluşturun. `prune` ile planlanan kaynaklara başvuran türler de karşılaştırılır ve kaynaklar arasındaki başvurular yeniden denetlenir; bozuk bir başvuru da planı `conflicted` yapar.
- Bir bağlantının silinmesi veya son 30 günde belirteç almış bir uygulamanın silinmesi `confirm_deletions` içinde yinelenmelidir. Aksi halde istek `409 deletion_not_confirmed` hatasıyla başarısız olur ve plan `planned` kalır.
- Kurumsal bağlantının OIDC materyali (`spec.oidc`) ve istemci gizli anahtarı, bağlantı kaydından sonra federasyon hizmetine yazılır. Bu ikinci yazma reddedilirse plan `planned` kalır, bağlantı kaydı zaten var olabilir ve yeni bir plan yalnızca eksik materyali yazar. Bir `spec.oidc` `null` materyali değiştirmez. Sosyal bağlantının istemci gizli anahtarı henüz yazılamaz: böyle bir `requires_secret` değişikliği içeren plan, gizli anahtarlar denetlendikten sonra `501 not_implemented` döndürür. Hiçbir şey yazılmaz.
- `Idempotency-Key` desteklenir. Mümkün olduğunda gövdeyi gizli anahtar içermeden gönderin: anahtarın kaydı gövdenin bir özetini tutar.

## Yanıt

`200 OK` ile `Cache-Control: no-store`: [Yapılandırma planını al](get.md) biçiminde plan, `status: applied` ve `applied_at` ile birlikte.

Değişiklikten önce etkilenen kaynakların yapılandırması bir revizyon olarak saklanır (ortam başına en yeni 50, en fazla 90 gün). Uygulama, ortamın yönetim günlüğüne oluşturulan, güncellenen, silinen ve değişmeyen kaynak sayılarıyla birlikte tek bir `config.applied` girdisi yazar; değişen her kaynak da kendi girdisini yazar.

## Hatalar

| HTTP | kod | Ne zaman |
|---|---|---|
| 400 | `malformed_request`, `unknown_field` | Gövde JSON değil veya `resolved_secrets`, `confirm_deletions` ve `sp_host` dışında bir alan içeriyor. |
| 401 | `unauthenticated` | Kimlik bilgisi eksik, geçersiz veya iptal edilmiş. |
| 403 | `insufficient_permissions` | Kimlik bilgisi gerekli bir izne sahip değil; `required_permissions` hepsini listeler. |
| 404 | `not_found` | Plan yok, başka bir ortama ait veya silinmiş. |
| 409 | `config_conflict` | Plan oluşturulduktan sonra hedef değişti; plan artık `conflicted`. |
| 409 | `config_plan_not_applicable` | Plan zaten uygulanmış veya `conflicted`, ya da başka bir istek şu anda uyguluyor (`plan_status: applying`); durumu için `plan_status` bakın. |
| 409 | `deletion_not_confirmed` | Korumalı bir silme `confirm_deletions` içinde eksik; `unconfirmed_deletions` bunları listeler. |
| 409 | `conflict` | Başka bir kaynak bir değişikliğin benzersiz bir değerini zaten kullanıyor (`errors[].pointer` `/changes/<i>/spec/<field>`, kod `duplicate`); plan `planned` kalır. |
| 409 | `connection_in_use` | Silinecek bağlantı hâlâ kullanımda; plan `planned` kalır. |
| 409 | `connection_test_required` | Bir değişiklik `enterprise` bağlantı `active` oluşturuyor veya başarılı bir test girişi olmadan birini etkinleştiriyor (`errors[].pointer` `/changes/<i>/spec`, kod `test_required`); plan `planned` kalır. |
| 410 | `config_plan_expired` | Planın süresi doldu; yeni bir plan oluşturun. |
| 413 | `config_document_too_large` | Değişiklikler veya bunlar için saklanan revizyon (en fazla 10 MiB) tek istekte uygulanamayacak kadar büyük; daha az tür planlayın. |
| 422 | `validation_failed` | Aşağıya bakın. |
| 422 | `policy_conflict` | Değişiklik bir ortam ilkesiyle çelişiyor; plan `planned` kalır. |
| 429 | `rate_limited` | `config_plan` hız sınırı (plan oluşturmayla paylaşılır) aşıldı veya bu ortam için aynı anda çok fazla plan hesaplanıyor ya da uygulanıyor; plan `planned` kalır; `Retry-After` süresinden sonra yeniden deneyin. |
| 501 | `not_implemented` | Plan, şu anda yazılamayan bir sosyal bağlantının istemci gizli anahtarını gerektiriyor. |
| 503 | `service_unavailable` | Bir bağımlılık (dizin veya kurumsal OIDC materyali için federasyon hizmeti) geçici olarak kullanılamıyor ya da plan kapasitesi geçici olarak dolu; hiçbir şey yazılmadı veya federasyon hizmeti için yalnızca bağlantı kaydı yazıldı. `Retry-After` süresinden sonra yeniden deneyin. |

| `errors[].pointer` | `errors[].code` | Anlamı |
|---|---|---|
| `/resolved_secrets/<NAME>` | `secret_missing` | Plan bu gizli anahtarı gerektiriyor. |
| `/resolved_secrets/<NAME>` | `secret_unused` | Plan bu gizli anahtarı gerektirmiyor. |
| `/resolved_secrets/<NAME>` | `secret_invalid` | Değer boş, 8 KiB'den uzun veya metin değil. |
| `/resolved_secrets/<NAME>` | `invalid` | Ad, `KEENAUTH_…` biçiminde değil (`A-Z`, `0-9`, `_`). |
| `/sp_host` | `sp_host_required`, `sp_host_unused`, `invalid` | Plan OIDC materyali oluşturuyor ama ana makine verilmedi, ana makine gerekmiyor veya ana makine küçük harfli bir DNS adı değil. |
| `/changes/<i>/spec/oidc/...` | bağlantı OIDC API'sindeki gibi | Federasyon hizmeti materyali planın `changes` içindeki bu konumda reddetti. |
| `/confirm_deletions/<i>` | `duplicate`, `not_a_deletion` | Öğe tekrarlanıyor veya planda bir silme değil. |
| `/confirm_deletions/<i>` | `invalid` | Öğe `<kind>/<key>` biçiminde değil. |
| `/resolved_secrets`, `/confirm_deletions` | `too_many` | 5.000'den fazla girdi. |
| `/changes/<i>/spec/...` | kaynağın kendi API'sindeki gibi | Ortam değişikliği, planın `changes` içindeki bu konumda reddetti. |

## Örnek

```bash
curl -X POST "https://api.eu.keenauth.com/v1/config-plans/cfgp_01m4qpqtywfs7930tb6kqn5rc5:apply" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"confirm_deletions": ["connection/legacy"]}'

keenauth config apply cfgp_01m4qpqtywfs7930tb6kqn5rc5 --confirm-deletion connection/legacy
```

`keenauth config apply --secrets-from-env` planın ihtiyaç duyduğu her gizli anahtarı, aynı adlı ortam değişkeninden okur ve hiçbir zaman yazdırmaz.
