
# Mettre à jour la politique des clés de signature

`PATCH /v1/signing-keys/policy` · permission `signing-keys:write`

Met à jour la politique des clés de signature avec un JSON merge patch (`application/merge-patch+json`, RFC 7396). `If-Match` est obligatoire : absent, `428` ; version périmée, `412`. Si la politique n'a jamais été écrite, la version est `"0"`. Un patch qui ne change rien n'écrit rien et conserve la version.

Changer `algorithm` génère aussitôt une nouvelle clé `next` avec le nouvel algorithme ; elle peut devenir active au plus tôt 7 jours plus tard, afin que les vérificateurs qui mettent le JWKS en cache la voient d'abord (une rotation `immediate` plus précoce échoue avec `409 next_key_too_young`). La clé active continue de signer jusque-là. Changer `rotation_interval_days` déplace `next_rotation_at`. Une modification réussie écrit l'enregistrement d'audit de gestion `signing_key.policy_updated`.

## Requête

| Champ | Type | Obligatoire | Description |
|---|---|---|---|
| `If-Match` | header | oui | L'`ETag` de la politique tel que lu en dernier (`"0"` si jamais écrite). Absent : `428` ; périmé : `412`. |
| `algorithm` | string | non | `RS256`, `ES256`, `PS256` ou `EdDSA`. Ne peut pas être `null`. |
| `rotation_interval_days` | integer | non | 30 à 365. Ne peut pas être `null`. |
| `storage` | string | non | `wrapped` (la clé privée est stockée chiffrée sous la clé de l'environnement et utilisée uniquement dans le service de signature). `transit` (clé conservée dans le service de gestion des clés) n'est pas encore disponible et est rejeté avec `422`. Ne peut pas être `null`. |

## Réponse

`200 OK` avec la politique mise à jour et le nouvel `ETag`.

```json
{
  "algorithm": "ES256",
  "rotation_interval_days": 90,
  "storage": "wrapped",
  "next_rotation_at": "2026-12-04T09:30:00.123456Z",
  "updated_at": "2026-10-05T09:30:00.123456Z"
}
```

## Erreurs

| HTTP | code | Quand |
|---|---|---|
| 400 | `unknown_field` | Le patch contient un champ inconnu ou en lecture seule, ou n'est pas un objet JSON (`malformed_request`). |
| 412 | `precondition_failed` | `If-Match` ne correspond pas à la version actuelle. |
| 415 | `unsupported_media_type` | Le type de contenu n'est pas `application/merge-patch+json`. |
| 422 | `validation_failed` | Une valeur est invalide (`invalid_value`), hors limites (`out_of_range`), définie à `null` (`invalid`), ou `storage` vaut `transit`. |
| 428 | `precondition_required` | L'en-tête `If-Match` est manquant. |
| 401 | `unauthenticated` | L'authentification est manquante, invalide ou révoquée. |
| 403 | `insufficient_permissions` | L'authentification manque la permission requise. |
| 429 | `rate_limited` | La limite de débit a été dépassée ; réessayez après la période `Retry-After`. |
| 501 | `not_implemented` | L'opération n'est pas encore disponible dans ce déploiement ; réessayer ne change pas le résultat. |
| 503 | `service_unavailable` | Une dépendance est temporairement indisponible ; réessayez après la période `Retry-After`. |

## Exemple

```bash
curl -X PATCH https://api.eu.keenauth.com/v1/signing-keys/policy \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/merge-patch+json" \
  -H 'If-Match: "0"' \
  -d '{"algorithm":"ES256","rotation_interval_days":90}'
```
