
# Actualizar la configuración de identidad

`PATCH /v1/identity-settings` · permiso `identity-settings:write`

Actualiza la configuración de nombre de usuario del entorno con un parche de fusión JSON (`application/merge-patch+json`, RFC 7396). `If-Match` es requerido: si falta se devuelve `428`, con una versión obsoleta `412`. Si la configuración nunca se escribió, la versión es `"0"` y la primera escritura crea la fila. Un parche que no cambia nada no escribe nada y mantiene la versión.

## Solicitud

| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
| `If-Match` | header | sí | El `ETag` de la configuración como se leyó por última vez (`"0"` si nunca se escribió). Falta: `428`; obsoleto: `412`. |
| `username_identifier` | string | no | `required`, `optional` u `off`. No puede ser `null`. |
| `username_min_length` | integer | no | 3 a 64, no mayor que `username_max_length`. No puede ser `null`. |
| `username_max_length` | integer | no | 3 a 64, no menor que `username_min_length`. No puede ser `null`. |
| `reserved_usernames` | string[] \| null | no | Como máximo 1000 nombres; reemplaza la lista completa (RFC 7396 no fusiona arreglos). `null` o `[]` la vacía. Cada entrada se normaliza, los duplicados se descartan y la lista se guarda ordenada. |
| `verification_policy` | string | no | `before_sign_in` (predeterminado) o `after_sign_in`. `after_sign_in` detiene la limpieza de cuentas no verificadas. No puede ser `null`. |
| `unverified_account_ttl_days` | integer | no | 1-30 (predeterminado 7): días que se conserva un registro no verificado en un entorno `before_sign_in` antes de eliminarlo. No puede ser `null`. |

La configuración de nombre de usuario solo se aplica a escrituras posteriores; nunca modifica a los usuarios existentes. La configuración de verificación también actúa sobre los registros existentes (ver abajo).

## Reglas de aplicación

- `off` (predeterminado): una solicitud que escribe un nombre de usuario (`POST /v1/users`, `PATCH /v1/users/{id}`) falla con `422` y el código `identifier_type_disabled` (puntero `/username`). Borrar un nombre de usuario existente sigue permitido, y un parche de usuario que no toca el nombre de usuario no se vuelve a comprobar. El inicio de sesión no resuelve cuentas por nombre de usuario.
- `optional`: se puede definir un nombre de usuario. `required`: crear un usuario con la API de administración sin nombre de usuario falla con `422` (`required`), y un parche de administración no puede borrarlo. Pedir el nombre de usuario en el formulario de registro corresponde al inicio de sesión alojado; la creación social y justo a tiempo (JIT) nunca lo pide.
- Longitud: un nombre de usuario más corto que `username_min_length` o más largo que `username_max_length` falla con `422` (`invalid`).
- Nombres reservados: un nombre de usuario cuya forma normalizada está en `reserved_usernames` falla con `422` y el código `username_reserved`. Una entrada de lista inválida falla con `422` y el puntero `/reserved_usernames/<i>`.
- Los usuarios existentes no se modifican cuando cambia la configuración; las reglas solo se aplican a escrituras posteriores.

## Limpieza de cuentas no verificadas

`verification_policy` y `unverified_account_ttl_days` controlan la limpieza automática de los registros que nunca se verificaron. La limpieza solo se ejecuta mientras la dirección de correo electrónico (o el número de teléfono) sea un identificador obligatorio, que es lo predeterminado para el correo electrónico.

- `before_sign_in` (predeterminado): un usuario creado mediante registro no puede recibir tokens antes de verificar el identificador obligatorio. Un usuario registrado que, `unverified_account_ttl_days` días (1-30, predeterminado 7) después del registro, sigue sin una dirección de correo electrónico o un número de teléfono verificado, nunca ha recibido un token y no tiene una identidad social o empresarial (SAML/OIDC) se elimina de forma permanente. La limpieza se ejecuta periódicamente (cada hora de forma predeterminada).
- `after_sign_in`: los usuarios reciben tokens antes de verificar (`email_verified: false`); la limpieza no se ejecuta y no se elimina ningún usuario.
- Nunca se eliminan: los usuarios creados mediante la API de administración, la importación, SCIM, una invitación o la federación just-in-time, los usuarios bloqueados y aquellos cuya eliminación ya comenzó. Solo son elegibles los registros creados después de que la limpieza comenzara en el entorno.
- La eliminación no se puede deshacer: el usuario se elimina de forma permanente, se conserva una lápida con el motivo `unverified_expired` y se publica el evento `user.deleted`.
- Un cambio de política o de plazo surte efecto en la siguiente ejecución. Reducir `unverified_account_ttl_days` hace elegibles de inmediato los registros no verificados más antiguos; volver de `after_sign_in` a `before_sign_in` elimina los registros no verificados vencidos en la siguiente ejecución.

## Respuesta

`200 OK` con la configuración actualizada y el nuevo `ETag`.

```json
{
  "username_identifier": "optional",
  "username_min_length": 3,
  "username_max_length": 32,
  "reserved_usernames": ["admin", "root", "support"],
  "verification_policy": "before_sign_in",
  "unverified_account_ttl_days": 7,
  "updated_at": "2026-10-05T09:30:00.123456Z"
}
```

## Errores

| HTTP | código | Cuándo |
|---|---|---|
| 400 | `unknown_field` | El parche contiene un campo desconocido o de solo lectura, o no es un objeto JSON (`malformed_request`). |
| 412 | `precondition_failed` | `If-Match` no coincide con la versión actual. |
| 415 | `unsupported_media_type` | El tipo de contenido no es `application/merge-patch+json`. |
| 422 | `validation_failed` | Un valor es inválido, `min` supera a `max`, o un campo que no puede ser `null` se estableció en `null` (`code: invalid`). |
| 428 | `precondition_required` | Falta el encabezado `If-Match`. |
| 401 | `unauthenticated` | La credencial falta, es inválida o ha sido revocada. |
| 403 | `insufficient_permissions` | La credencial carece del permiso requerido. |
| 429 | `rate_limited` | Se superó el límite de velocidad; reintente después del período `Retry-After`. |
| 503 | `service_unavailable` | Una dependencia no está disponible temporalmente; reintente después del período `Retry-After`. |

## Ejemplo

```bash
curl -X PATCH https://api.eu.keenauth.com/v1/identity-settings \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/merge-patch+json" \
  -H 'If-Match: "0"' \
  -d '{"username_identifier":"optional","username_max_length":32,"reserved_usernames":["admin","root","support"]}'
```
