ums

ApprovalRequest — Aggregate Architecture

Bounded Context: Approvals
Aggregate Root: ApprovalRequest
Module: Ums.Domain.Approvals.ApprovalRequest
Status: Production


1. Aggregate Overview

Purpose

The ApprovalRequest aggregate represents a concrete runtime execution of an approval process. When a user requests a high-privilege administrative action (like a profile promotion or security configuration modification), UMS instantiates an ApprovalRequest linked to a specific ApprovalWorkflow to track the state, approvals, rejections, and audit details of that operational decision.

Business Responsibility

Aggregate Root

ApprovalRequest is the aggregate root. All state transitions (Approving, Rejecting) must flow through it to ensure constraints.

Invariants and Consistency Rules

  1. A request is born in the Pending status.
  2. The status can only transition from Pending to Approved or Rejected. Once a request has been finalized (Approved or Rejected), its status is permanently locked and cannot be edited.
  3. Must contain valid references to WorkflowId and TargetUserId.
  4. A user cannot approve their own promotion request (enforced at the application/domain command barrier to prevent collusion).

| Entity / VO | Type | Ownership | |—|—|—| | ApprovalRequestId | Value Object | Guid-based aggregate root identifier | | ApprovalStatus | Enum | PENDING · APPROVED · REJECTED | | AuditValueObject | Value Object | Tracks creation and modification metadata |

Domain Events

| Event | Trigger | |—|—| | ApprovalRequestCreatedEvent | A new approval request is registered and set to Pending | | ApprovalRequestApprovedEvent | The request is marked as Approved, triggering downstream activations | | ApprovalRequestRejectedEvent | The request is marked as Rejected, aborting downstream activations |

Commands / Use Cases

| Command | Description | |—|—| | CreateApprovalRequestCommand | Instantiate an approval request instance for a user action | | ApproveRequestCommand | Approve a pending request with the authorized actor ID | | RejectRequestCommand | Reject a pending request and cancel the target elevation |

Repository / Service Boundaries


2. Domain Model

Classes / Entities / Value Objects

ApprovalRequest (Aggregate Root)
└── Props: ApprovalRequestProps
    ├── Id: ApprovalRequestId
    ├── WorkflowId: ApprovalWorkflowId
    ├── TargetUserId: UserId
    ├── TargetProfileId?: ProfileId
    ├── Status: ApprovalStatus
    └── Audit: AuditValueObject

3. Object Model Diagrams

classDiagram
    direction LR
    class ApprovalRequest {
        +Guid Id
        +Guid WorkflowId
        +Guid TargetUserId
        +Guid? TargetProfileId
        +ApprovalStatus Status
        +Create()
        +Approve()
        +Reject()
    }
    class ApprovalStatus {
        <<enumeration>>
        PENDING
        APPROVED
        REJECTED
    }
    ApprovalRequest "1" *-- "1" ApprovalStatus

4. Sequence Diagrams

Complete Approval Request Lifecycle

sequenceDiagram
    participant U as Requester
    participant H as RequestHandler
    participant R as IApprovalRequestRepository
    participant A as ApprovalRequest (AR)
    participant E as EventPublisher

    U->>H: CreateApprovalRequestCommand(workflowId, targetUserId, targetProfileId)
    H->>A: ApprovalRequest.Create(workflowId, targetUserId, targetProfileId, actorId)
    A->>A: Set Status = Pending
    A->>A: Raise ApprovalRequestCreatedEvent
    H->>R: Save(request)
    R-->>H: ok
    H-->>U: RequestId

    Note over U,A: Administrative Review
    Admin->>H: ApproveRequestCommand(requestId)
    H->>R: GetById(requestId)
    R-->>H: ApprovalRequest (AR)
    H->>A: Approve(adminActorId)
    A->>A: Transition Status -> Approved
    A->>A: Raise ApprovalRequestApprovedEvent
    H->>R: Save(request)
    R-->>H: ok
    H->>E: Publish ApprovalRequestApprovedEvent

5. ER Model

erDiagram
    APPROVAL_WORKFLOW ||--o{ APPROVAL_REQUEST : "routes"
    USER_ACCOUNT ||--o{ APPROVAL_REQUEST : "targets"
    PROFILE ||--o{ APPROVAL_REQUEST : "elevates-to"

    APPROVAL_REQUEST {
        uniqueidentifier RequestId PK
        uniqueidentifier WorkflowId FK
        uniqueidentifier TargetUserId FK
        uniqueidentifier TargetProfileId FK "Nullable"
        nvarchar Status "PENDING-APPROVED-REJECTED"
        datetime2 UpdatedAt
        uniqueidentifier UpdatedBy
    }

Tenant Isolation Rules


6. Bounded Context Integration


7. Application Layer


8. Infrastructure/Persistence


9. Security & Compliance


10. Technical Decisions


Back to Approvals Index