Functional Story 27: State-Change Consistency — Broken Rules on Active Dependencies
1. Business Purpose
Administrative operations that change entity state (suspend, block, deactivate, delete) can leave orphaned active data if executed while dependencies are still active. Administrators need clear, actionable feedback explaining what must be resolved before a state change is allowed, rather than receiving a generic error or silent failure.
2. Actors
| Actor |
Responsibility |
| System Administrator |
Manages tenant and user lifecycle. |
| Security Administrator |
Manages role, template, and domain resource lifecycle. |
3. Business Preconditions
- The actor is authenticated in the UMS portal with the appropriate administrative role.
- The target entity exists and is in a state that allows the attempted operation.
4. Main Functional Flow
- The actor attempts a state-change operation (e.g., suspend tenant, block user).
- The system checks for active blocking dependencies before executing the change.
- If blocking dependencies exist, the system rejects the operation with HTTP 409 Conflict.
- The system returns a structured response with the error code, a human-readable message, the broken business rule, and the list of blocking dependencies with entity type, status, and count.
- The actor resolves each blocking dependency (e.g., deactivates users, removes profiles).
- The actor retries the operation — it succeeds once all dependencies are resolved.
5. Alternative Flows and Exceptions
A. No Blocking Dependencies
The state change proceeds normally and returns the expected success status (204 No Content).
B. Multiple Blocking Dependency Types
The response lists all blocking dependency groups, each with its own entityType, status, and count.
6. Business Rules
- A tenant cannot be suspended while it has active users, branches, or identity providers.
- A user cannot be blocked or deleted while they have active profiles.
- A role cannot be deactivated while it has active profiles or active child roles.
- A permission template cannot be deprecated while active profiles reference it.
- A domain resource cannot be removed while active permission template items reference it.
- A module cannot be removed while active menus are configured within it.
7. Acceptance Criteria
- Attempting a guarded state change with active dependencies returns HTTP 409.
- The 409 response body contains
errorCode, message, brokenRule, and blockingDependencies[].
- Each
blockingDependencies entry contains entityType, status, and count.
- After resolving all blocking dependencies, the same operation succeeds.
- Operations with no blocking dependencies are not affected by the guard.
8. Technical Requirements
- Guard logic resides in application command handlers (not in the domain aggregate or UI).
- Error encoding:
BlockedOperationError.Encode(errorCode, deps) with | separator.
- HTTP response: 409 Conflict with
BlockedOperationResponse payload.
- Error codes defined in
DomainErrors; messages mapped in BlockedOperationMessages.
9. Traceability
- Entities:
TENANT, USER_ACCOUNT, PROFILE, ROLE, PERMISSION_TEMPLATE, DOMAIN_RESOURCE, MODULE
- ADRs: ADR-0079