Estado: Aceptado
Fecha: 2026-06-03
Responsable: Arquitectura
Relacionados:
Varias operaciones de cambio de estado en UMS son inseguras cuando existen dependencias activas. Por ejemplo, suspender un tenant mientras usuarios activos siguen autenticados, o bloquear un usuario mientras sus perfiles se usan activamente en decisiones de autorización.
Sin una capa de guardia, estas operaciones dejarían silenciosamente datos activos huérfanos o requerirían flujos de trabajo complejos con verificaciones manuales. Se necesita un contrato consistente y descubrible que:
Las guardias de dependencias viven en los handlers de comandos de aplicación, no en el agregado de dominio ni en la UI. El handler consulta los repositorios relevantes antes de despachar el comando de cambio de estado y rechaza la operación si se encuentran dependencias bloqueantes.
Esto permite:
BlockedOperationError con separador |Los errores de bloqueo se codifican como cadena usando BlockedOperationError.Encode(errorCode, deps) donde múltiples entradas de dependencia se separan con |. El decodificador BlockedOperationError.TryDecode(error, out errorCode, out deps) reconstruye la lista en la capa de presentación.
BlockedOperationResponseCuando una guardia se activa, el endpoint devuelve HTTP 409 Conflict con el siguiente cuerpo JSON:
{
"errorCode": "TENANT_HAS_ACTIVE_USERS",
"message": "Mensaje legible en el idioma configurado",
"brokenRule": "A tenant cannot be suspended while active users exist.",
"blockingDependencies": [
{ "entityType": "UserAccount", "status": "Active", "count": 3 }
]
}
Los valores de errorCode están definidos en DomainErrors y mapeados a mensajes/reglas en BlockedOperationMessages.
| Operación | Código de error | Dependencia bloqueante |
|---|---|---|
| Suspender Tenant | TENANT_HAS_ACTIVE_USERS |
Registros UserAccount activos |
| Suspender Tenant | TENANT_HAS_ACTIVE_BRANCHES |
Registros Branch activos |
| Suspender Tenant | TENANT_HAS_ACTIVE_IDP_CONFIG |
Registros IdpConfiguration activos |
| Bloquear / Eliminar Usuario | USER_HAS_ACTIVE_PROFILES |
Registros Profile activos |
| Desactivar Rol | ROLE_HAS_ACTIVE_PROFILES |
Registros Profile activos |
| Desactivar Rol | ROLE_HAS_ACTIVE_CHILD_ROLES |
Registros de Role hijo activos |
| Deprecar Template | TEMPLATE_HAS_ACTIVE_PROFILES |
Registros Profile activos |
| Eliminar DomainResource | DOMAIN_RESOURCE_HAS_TEMPLATE_ITEMS |
Registros PermissionTemplateItem activos |
| Eliminar Módulo | MODULE_HAS_ACTIVE_MENUS |
Registros Menu activos |
DomainErrors, una nueva entrada en BlockedOperationMessages, y una nueva verificación en el handler de comando correspondiente.