Skip to content

Domain Type Design Decisions

This document analyzes the natural language requirements defined in the Business Requirements from a DDD perspective. The first step is to identify independent consistency boundaries (Aggregates) from the business areas, and the second step is to classify the rules within each boundary as invariants.

Identifying Aggregates from Business Areas

Section titled “Identifying Aggregates from Business Areas”

Before encoding business rules as types, we must first identify independent consistency boundaries from the business areas. Four Aggregates are derived from four business topics.

Business TopicAggregateDerivation Rationale
AI Model ManagementAIModelUnique model lifecycle, independent risk tier management
Deployment LifecycleModelDeployment6-state transition rules, independent per-deployment management
Compliance AssessmentComplianceAssessmentOwns assessment criteria, score calculation consistency boundary
Incident ManagementModelIncidentUnique incident state transitions, independent lifecycle
Cross-Domain RulesCross-Aggregate validation -> Domain Service

Model information changes (name, purpose, version) and deployment state transitions have different frequencies and concurrency requirements. One model can have multiple deployments, each following independent state transition rules. Model archiving should not block deployment transactions.

Why Is Assessment an Independent Aggregate?

Section titled “Why Is Assessment an Independent Aggregate?”

A compliance assessment owns multiple assessment criteria (AssessmentCriterion) and automatically calculates the score after all criteria are evaluated. This calculation logic must be independent of the deployment. Changes to deployment status should not affect an in-progress assessment.

AggregateSeparation ReasonCore Invariants
AIModelUnique model lifecycle, archive/restoreArchive guard, model name validity
ModelDeployment6-state transition, independent per-deployment managementState transitions, endpoint URL validity
ComplianceAssessmentOwns assessment criteria, score calculation consistencyAll criteria evaluated before completion, automatic score calculation
ModelIncidentUnique incident state transitions, auto-quarantine triggerState transitions, severity-based quarantine

Business terms are mapped to DDD tactical patterns.

EnglishDDD PatternRole
AIModelAggregate RootGovernance target, owns risk tier
ModelDeploymentAggregate RootDeployment status management, references Model ID
ComplianceAssessmentAggregate RootOwns assessment criteria, score calculation
AssessmentCriterionEntity (child)Individual criterion within assessment, subordinate to Assessment
ModelIncidentAggregate RootIncident status management
ModelNameValue ObjectString, 100 characters or fewer
ModelVersionValue ObjectSemVer format, regex validation
ModelPurposeValue ObjectString, 500 characters or fewer
RiskTierValue Object (Smart Enum)4 levels, domain properties embedded
DeploymentStatusValue Object (Smart Enum)6 states, transition rules embedded
DeploymentEnvironmentValue Object (Smart Enum)Staging, Production
EndpointUrlValue ObjectURL format validation
DriftThresholdValue Object0.0~1.0 range, comparable
AssessmentScoreValue Object0~100 range, passing threshold embedded
AssessmentStatusValue Object (Smart Enum)5 states, transition rules embedded
CriterionResultValue Object (Smart Enum)Pass, Fail, NotApplicable
IncidentSeverityValue Object (Smart Enum)4 levels, quarantine condition embedded
IncidentStatusValue Object (Smart Enum)4 states, transition rules embedded
IncidentDescriptionValue ObjectString, 2000 characters or fewer
ResolutionNoteValue ObjectString, 2000 characters or fewer
RiskClassificationServiceDomain ServiceKeyword-based risk tier classification
DeploymentEligibilityServiceDomain ServiceCross-Aggregate eligibility verification

Six invariant types were identified in this domain.

TypeScopeKey Question
Single ValueIndividual fieldIs this value always valid?
StructuralField combinationAre derived values consistent in parent-child relationships?
State TransitionChange over timeDo only allowed state changes occur?
LifecycleAggregate lifecycleAre actions blocked on deleted objects?
OwnershipChild entity boundaryDo children stay within the parent boundary?
Cross-AggregateAcross multiple AggregatesWhere are rules guaranteed that cannot be validated by a single Aggregate?

Constraints that individual fields must always hold valid values.

Business Rules:

  • “Model name must be 100 characters or fewer and must not be empty”
  • “Model version must be in SemVer format”
  • “Model purpose must be 500 characters or fewer and must not be empty”
  • “Endpoint URL must be a valid HTTP/HTTPS URL”
  • “Drift threshold must be in the range 0.0~1.0”
  • “Assessment score must be in the range 0~100”
  • “Incident description must be 2000 characters or fewer and must not be empty”

Design Decision: Validate at creation and guarantee immutability thereafter.

Naive FieldFunctorium TypeValidation Rules
string NameSimpleValueObject<string>NotNull, NotEmpty, Trim, MaxLength(100)
string VersionSimpleValueObject<string>NotNull, NotEmpty, SemVer regex
string PurposeSimpleValueObject<string>NotNull, NotEmpty, Trim, MaxLength(500)
string UrlSimpleValueObject<string>NotNull, NotEmpty, URI format validation
decimal DriftThresholdComparableSimpleValueObject<decimal>Between(0.0, 1.0)
int ScoreComparableSimpleValueObject<int>Between(0, 100)
string DescriptionSimpleValueObject<string>NotNull, NotEmpty, Trim, MaxLength(2000)

Constraints that enumerated values must only hold allowed values.

Business Rules:

  • “Risk tier allows only Minimal, Limited, High, Unacceptable”
  • “High or Unacceptable tiers require compliance assessments”
  • “Unacceptable tier prohibits deployment”
  • “Critical or High severity requires automatic deployment quarantine”

Design Decision: Embed domain properties in value objects using the Smart Enum pattern.

Smart EnumValue ListEmbedded Domain Properties
RiskTierMinimal, Limited, High, UnacceptableRequiresComplianceAssessment, IsProhibited
IncidentSeverityCritical, High, Medium, LowRequiresQuarantine
CriterionResultPass, Fail, NotApplicable
DeploymentEnvironmentStaging, Production

Constraints that states transition only according to defined rules. The Smart Enum + HashMap transition map pattern is applied.

Smart EnumTransition RulesTerminal States
DeploymentStatusDraft->PendingReview, PendingReview->Active/Rejected, Active->Quarantined/Decommissioned, Quarantined->Active/DecommissionedDecommissioned, Rejected
IncidentStatusReported->Investigating/Escalated, Investigating->Resolved/EscalatedResolved, Escalated
AssessmentStatusInitiated->InProgress, InProgress->Passed/Failed/RequiresRemediationPassed, Failed, RequiresRemediation

Business Rule: “Archived models cannot be modified”

Design Decision: ISoftDeletableWithUser + DeletedAt.IsSome guard pattern. ClassifyRisk, UpdateVersion, Update methods return AlreadyDeleted error when DeletedAt.IsSome.

Business Rule: “Assessment criteria are subordinate to the compliance assessment”

Design Decision: ComplianceAssessment manages child entities via a private List<AssessmentCriterion>, exposing only IReadOnlyList externally. Criterion creation, evaluation, and completion are all possible only through the parent Aggregate.

Business Rules:

  • “Deployment eligibility: prohibited tier check, compliance assessment check, unresolved incident check”
  • “Risk tier classification: automatic classification based on purpose keywords”

Design Decision: Implemented as Domain Services.

Domain ServiceCross-Domain TargetsVerification Content
RiskClassificationServiceAIModel (purpose)Keyword -> risk tier mapping
DeploymentEligibilityServiceAIModel, ComplianceAssessment, ModelIncidentProhibited tier, assessment passed, incident absence

All Smart Enums in this domain are single-dimensional (a single string value). RiskTier, DeploymentStatus, etc. do not have different field structures per value, so the SimpleValueObject<string> + HashMap pattern was chosen over UnionValueObject (discriminated union). Domain properties (RequiresComplianceAssessment, IsProhibited, etc.) are sufficiently expressed as Smart Enum instance methods/properties.

Design DecisionFunctorium TypeApplication ExampleGuaranteed Effect
Single value validation + immutability + normalizationSimpleValueObject<T> + Validate chainModelName, ModelVersion, EndpointUrlValidation at creation, Trim normalization, empty string blocking
Comparable single value + rangeComparableSimpleValueObject<T>DriftThreshold, AssessmentScoreRange validation, size comparison, domain property (IsPassing)
Smart Enum + domain propertiesSimpleValueObject<string> + HashMapRiskTier, IncidentSeverityOnly valid values allowed, domain properties embedded
Smart Enum + state transition rulesSimpleValueObject<string> + transition mapDeploymentStatus, IncidentStatus, AssessmentStatusOnly allowed transitions possible, terminal state guaranteed
Aggregate Root dual factoryAggregateRoot<TId> + Create/CreateFromValidatedAIModel, ModelDeployment, ComplianceAssessment, ModelIncidentSeparation of domain creation and ORM restoration
Child entity + collection managementEntity<TId> + private List + IReadOnlyListAssessmentCriterionCollection cannot be directly modified externally
Cross-Aggregate business rulesIDomainServiceDeploymentEligibilityService, RiskClassificationServiceCross-Aggregate verification
Queryable domain specificationsExpressionSpecification<T>ModelNameSpec, DeploymentActiveSpec, etc. (12 types)Expression Tree-based querying
Domain events + domain errorsNested sealed recordAIModel.RegisteredEvent, ModelDeployment.InvalidStatusTransitionEvents/errors cohesive within Aggregate
Soft Delete + guardISoftDeletableWithUser + DeletedAt.IsSomeAIModel.ClassifyRisk(), Update()Blocking changes on archived Aggregates

In the next step, these design decisions are mapped to C# code to proceed with Code Design.