ums

DocumentType — Aggregate Architecture

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


1. Aggregate Overview

Purpose

The DocumentType aggregate governs the classifications, rules, and policy schemas for user-uploaded documents (e.g. Passports, Certification documents). It declares critical thresholds (Criticity), binds recurring notification intervals (NotificationRule entities), and configures proactive security enforcement actions (EnforcementPolicy entity) to run automatically when a mandatory document expires or is deleted. NotificationRule specifies how many days before expiration a user must be alerted, and which communication channels are authorized.

Business Responsibility

Aggregate Root

DocumentType is the aggregate root. Defining enforcement actions or configuring notification alerts (NotificationRule) must go through it to enforce invariants. NotificationRule is an owned entity and cannot exist or undergo state transitions outside the lifecycle constraints of DocumentType.

Invariants and Consistency Rules

  1. Every DocumentType must possess a unique Code within its TenantId namespace.
  2. DaysBefore Uniqueness (INV-DT2): The alert thresholds (DaysBefore) in the owned NotificationRules must be unique across the rules list.
  3. Critical Mandates (INV-DT1): If a DocumentType is set to Critical, it must have exactly one active EnforcementPolicy defined to secure system compliance.
  4. Single Policy (INV-DT3): Only one active EnforcementPolicy is permitted per DocumentType.
  5. Criticity Matching (INV-DT4): Non-critical/high document types cannot apply BlockUser or RestrictProfile enforcement actions.
  6. NotificationRule.DaysBefore must be a positive integer strictly greater than zero.
  7. The NotificationRule.Channels collection must contain at least one valid notification channel (Email, SMS, WebPortal) and cannot be null or empty.
  8. Life cycle of NotificationRule is fully controlled by the parent DocumentType.

| Entity / VO | Type | Ownership | |—|—|—| | DocumentTypeId | Value Object | Guid-based aggregate root identifier | | DocumentCriticity | Enum | LOW · MEDIUM · HIGH · CRITICAL | | NotificationRule | Entity | Owned | | NotificationRuleId | Value Object | Entity unique identifier | | NotificationChannel | Enum | EMAIL · SMS · IN_APP · WEB_PUSH | | EnforcementPolicy | Entity | Owned child detailing grace periods and blocks | | AuditValueObject | Value Object | Tracks creation and modification metadata | | Code | Value Object | Alpha-numeric camelCase notification type identifier |

Domain Events

| Event | Trigger | |—|—| | DocumentTypeRegisteredEvent | A new document category is successfully registered | | NotificationRuleConfiguredEvent | An expiration pre-alert rule is configured | | NotificationRuleRemovedEvent | A pre-alert rule is removed | | EnforcementPolicyDefinedEvent | An enforcement block is defined | | EnforcementPolicyUpdatedEvent | The enforcement parameters are updated |

Commands / Use Cases

| Command | Description | |—|—| | CreateDocumentTypeCommand | Register a new document type with default parameters | | ConfigureNotificationRuleCommand | Configure a new alert threshold and channels | | RemoveNotificationRuleCommand | Remove an existing notification pre-alert rule | | DefineEnforcementPolicyCommand | Add a blocking or profile downgrade enforcement policy | | UpdateEnforcementPolicyCommand | Modify the actions or grace periods of a policy |

Repository / Service Boundaries


2. Domain Model

Classes / Entities / Value Objects

DocumentType (Aggregate Root)
├── Props: DocumentTypeProps
│   ├── Id: DocumentTypeId
│   ├── TenantId: TenantId
│   ├── Code: Code
│   ├── Name: Name
│   ├── Description: Description
│   ├── Criticity: DocumentCriticity
│   └── Audit: AuditValueObject
├── Children
│   └── IReadOnlyCollection<NotificationRule>
│       └── Props: NotificationRuleProps
│           ├── Id: NotificationRuleId
│           ├── DaysBefore: int
│           ├── Channels: NotificationChannel[]
│           ├── Code: Code
│           └── Description: Description
└── Child (Nullable)
    └── EnforcementPolicy

3. Object Model Diagrams

classDiagram
    direction LR
    class DocumentType {
        +Guid Id
        +Guid TenantId
        +Code Code
        +Name Name
        +Description Description
        +DocumentCriticity Criticity
        +List~NotificationRule~ NotificationRules
        +EnforcementPolicy EnforcementPolicy
        +Create()
        +ConfigureNotificationRule()
        +RemoveNotificationRule()
        +DefineEnforcementPolicy()
    }
    class DocumentCriticity {
        <<enumeration>>
        LOW
        MEDIUM
        HIGH
        CRITICAL
    }
    class NotificationRule {
        +Guid Id
        +int DaysBefore
        +NotificationChannel[] Channels
        +Code Code
        +Description Description
        +Create()
    }
    class NotificationChannel {
        <<enumeration>>
        EMAIL
        SMS
        IN_APP
        WEB_PUSH
    }
    class EnforcementPolicy {
        +Guid Id
        +AccessEnforcementAction ActionOnExpiration
        +int? GracePeriodDays
    }
    DocumentType "1" *-- "1" DocumentCriticity
    DocumentType "1" *-- "0..*" NotificationRule
    NotificationRule "1" *-- "1..*" NotificationChannel
    DocumentType "1" *-- "0..1" EnforcementPolicy

4. Sequence Diagrams

Define Enforcement Policy Flow

sequenceDiagram
    participant C as TenantAdmin
    participant H as DefinePolicyHandler
    participant R as IDocumentTypeRepository
    participant D as DocumentType (AR)

    C->>H: DefineEnforcementPolicyCommand(docTypeId, action, graceDays)
    H->>R: GetById(docTypeId)
    R-->>H: DocumentType (AR)
    H->>D: DefineEnforcementPolicy(action, graceDays, actorId)
    D->>D: Guard INV-DT4 (non-critical restrictions)
    D->>D: Guard INV-DT3 (single policy limit)
    D->>D: Raise EnforcementPolicyDefinedEvent
    H->>R: Save(docType)
    R-->>H: ok
    H-->>C: ok

5. ER Model

erDiagram
    TENANT ||--o{ DOCUMENT_TYPE : "configures"
    DOCUMENT_TYPE ||--o{ NOTIFICATION_RULE : "defines"
    DOCUMENT_TYPE ||--o| ENFORCEMENT_POLICY : "restricts"

    DOCUMENT_TYPE {
        uniqueidentifier DocumentTypeId PK
        uniqueidentifier TenantId FK
        nvarchar Code "Unique per TenantId"
        nvarchar Name
        nvarchar Description
        nvarchar Criticity "LOW-MEDIUM-HIGH-CRITICAL"
        datetime2 UpdatedAt
        uniqueidentifier UpdatedBy
    }
    NOTIFICATION_RULE {
        uniqueidentifier RuleId PK
        uniqueidentifier DocumentTypeId FK
        int DaysBefore "Unique per DocumentTypeId"
        nvarchar ChannelsJson "Serialized channels array"
        nvarchar Code
        nvarchar Description
    }
    ENFORCEMENT_POLICY {
        uniqueidentifier PolicyId PK
        uniqueidentifier DocumentTypeId FK
        nvarchar ActionOnExpiration "BlockUser-RestrictProfile-Notify"
        int GracePeriodDays "Nullable"
    }

Tenant Isolation Rules


6. Bounded Context Integration


7. Application Layer


8. Infrastructure/Persistence


9. Security & Compliance


10. Technical Decisions


Back to Approvals Index