Bounded Context: Authorization
Aggregate Root: SystemSuite
Module: Ums.Domain.Authorization.SystemSuite
Status: Production
The SystemSuite aggregate represents a tenant-owned application surface registered in UMS. It defines the functional topology used by downstream authorization models and stores suite-level operational settings. In the current implementation, it owns Module, menu topology, DomainResource (Aggregates, Entities, and DomainMethods), AppSetting, and Action children. The independent Role aggregate is maintained in the selected suite context and references it through SystemSuiteId. During bootstrap, UMS is the canonical base suite for the tenant-management surface.
Code, Name, Description, Status.PermissionTemplate and effective authorization flows.SystemStatus.SystemSuite is the aggregate root. Changes to suite identity, modules, domain resources, app settings, and suite status must go through the aggregate root.
TenantId, Code, Name, and Description are mandatory.Code must be unique within the owning tenant boundary.Module.Code must be unique inside the suite.ConfigurationKey for the same ConfigurationScope.| Entity / VO | Type | Ownership | Description |
|—|—|—|—|
| Module | Entity | Owned | Functional subsystem inside the suite |
| AppSetting | Entity | Owned | Suite-scoped configuration entry |
| Action | Entity | Owned / catalogued | Action tokens exposed for authorization targeting |
| Role | Aggregate Root | Related by SystemSuiteId | Responsibility catalog and hierarchy defined for the suite |
| TenantId | Value Object | - | Tenant ownership boundary |
| Code | Value Object | - | Technical identifier |
| Name | Value Object | - | Display label |
| Description | Value Object | - | Functional description |
| SystemStatus | Enumeration | - | Active, Inactive, Beta, etc. |
| Event | Trigger |
|—|—|
| SystemSuiteRegisteredEvent | New suite created |
| SystemSuiteStatusChangedEvent | Suite status changed |
| SystemSuiteModuleAddedEvent | Module added |
| SystemSuiteModuleRemovedEvent | Module removed |
| SystemSuiteModuleStatusChangedEvent | Module activated or deactivated |
SystemSuite (Aggregate Root)
├── Props: SystemSuiteProps
│ ├── Id: IdValueObject
│ ├── TenantId: TenantId
│ ├── Code: Code
│ ├── Name: Name
│ ├── Description: Description
│ ├── Status: SystemStatus
│ └── Audit: AuditValueObject
├── Children
│ ├── IReadOnlyCollection<Module>
│ └── IReadOnlyCollection<AppSetting>
└── Catalog Surface
└── IReadOnlyCollection<Action>
classDiagram
direction TB
class SystemSuite {
+Guid Id
+Guid TenantId
+Code Code
+Name Name
+Description Description
+SystemStatus Status
+List~Module~ Modules
+List~DomainResource~ DomainResources
+List~AppSetting~ AppSettings
+List~Action~ Actions
+Create(tenantId, code, name, description, actor)
+Update(name, description, actor)
+SetStatus(status, actor)
+AddModule(code, name, description, sortOrder, actor)
+UpdateModule(moduleId, name, description, sortOrder, actor)
+ActivateModule(moduleId, actor)
+DeactivateModule(moduleId, actor)
+RemoveModule(moduleId, actor)
+AddDomainResource(moduleId, parentResourceId, type, code, name, description, actor)
+UpdateDomainResource(resourceId, moduleId, type, code, name, description, actor)
+RemoveDomainResource(resourceId, actor)
+AddAppSetting(key, value, scope, actor)
}
class Module {
+Guid Id
+Guid SuiteId
+Code Code
+Name Name
+Description Description
+int SortOrder
+ModuleStatus Status
}
class DomainResource {
+Guid Id
+Guid? ModuleId
+Guid? ParentResourceId
+DomainResourceType Type
+Code Code
+Name Name
+Description Description
}
class AppSetting {
+Guid Id
+ConfigurationKey Key
+ConfigurationValue Value
+ConfigurationScope Scope
}
class Action {
+Guid Id
+ActionCode Code
}
SystemSuite "1" *-- "0..*" Module : contiene
SystemSuite "1" *-- "0..*" DomainResource : posee
SystemSuite "1" *-- "0..*" AppSetting : configura
SystemSuite "1" *-- "0..*" Action : expone
sequenceDiagram
participant C as Client
participant H as Handler
participant R as ISystemSuiteRepository
participant S as SystemSuite (AR)
C->>H: AddModuleCommand(systemSuiteId, code, name, description, sortOrder)
H->>R: GetById(systemSuiteId)
R-->>H: SystemSuite
H->>S: AddModule(code, name, description, sortOrder, actor)
S->>S: Validate module code uniqueness
S->>S: Raise SystemSuiteModuleAddedEvent
H->>R: Update(systemSuite)
R-->>H: ok
H-->>C: Success
erDiagram
TENANT ||--o{ SYSTEM_SUITE : "owns"
SYSTEM_SUITE ||--o{ MODULE : "contiene"
SYSTEM_SUITE ||--o{ DOMAIN_RESOURCE : "posee"
SYSTEM_SUITE ||--o{ APP_SETTING : "configura"
SYSTEM_SUITE ||--o{ ACTION : "expone"
SYSTEM_SUITE ||--o{ ROLE : "defines"
SYSTEM_SUITE {
uniqueidentifier Id PK
uniqueidentifier TenantId FK
nvarchar Code
nvarchar Name
nvarchar Description
int Status "Active(1) | Inactive(2)"
}
DOMAIN_RESOURCE {
uniqueidentifier ResourceId PK
uniqueidentifier SuiteId FK
uniqueidentifier ModuleId FK "Nullable"
int Type "Aggregate(1) | Entity(2) | DomainMethod(3)"
nvarchar Code "Unique within Suite"
nvarchar Name
nvarchar Description
}
MODULE {
nvarchar CreatedBy
datetime2 CreatedAtUtc
nvarchar UpdatedBy
datetime2 UpdatedAtUtc
nvarchar AuditTimeSpan
}
SystemSuite is tenant-owned in the current implementation.PermissionTemplate and effective authorization resolution.CreateSystemSuiteCommand -> Inputs: TenantId, Code, Name, Description -> Returns: GuidUpdateSystemSuiteCommand -> Inputs: SystemSuiteId, Name, Description -> Returns: voidSetSystemSuiteStatusCommand -> Inputs: SystemSuiteId, Status -> Returns: voidCreateRoleCommand, UpdateRoleCommand, and SetRoleStatusCommand operate on roles under the selected suite.rolesBySystemSuite(systemSuiteId) for the Roles detail tab.[ums_authorization].[Roles] references [ums_authorization].[SystemSuites] and supports a nullable parent-role FK.SystemSuite is tenant-owned in the current domain model, even if some older documentation described it as a global catalog.