Domain Layer — Entities, Aggregates & Value Objects
«aggregate root»
ChatSession
id: ChatSessionId
clientId: ClientId
persona: Persona
messages: List<Message>
language: Language
status: SessionStatus
sendMessage(content, tools): Message
executeAction(actionId): ActionResult
provideFeedback(msgId, fb): void
switchPersona(persona): void
close(): void
«entity»
Message
id: MessageId
role: Role (USER|MIA)
content: String
toolCalls: List<ToolCall>
citations: List<Citation>
confidence: ConfidenceScore
timestamp: Instant
attachCitation(c): void
markAsDelivered(): void
«entity»
ActionExecution
id: ActionId
type: ActionType
parameters: Map
status: ExecStatus
result: ActionResult?
execute(): ActionResult
compensate(): void
requiresConfirmation(): bool
«entity»
Feedback
messageId: MessageId
rating: Rating
comment: String?
category: FeedbackType
isActionable(): boolean
«value object»
Persona
type: WEALTH | MARKETS
name: String
tone: Tone
systemPrompt: String
«value object»
Language
code: String
name: String
isSupported(): bool
«value object»
ConfidenceScore
value: double [0.0-1.0]
isHighConfidence(): bool
requiresDisclaimer(): bool
«value object»
Citation
source: String
url: URI?
excerpt: String
retrievedAt: Instant
«value object»
Money
paise: long
currency: Currency
add(m: Money): Money
multiply(n): Money
toString(): "₹12,45,678.90"
«value object»
ToolCall
toolName: String
arguments: JsonNode
result: JsonNode?
isFinancialAction(): bool
Application Layer — Use Cases & Ports
«use case»
SendMessageUseCase
sessionRepo: ChatSessionRepository
llmPort: LlmPort
vectorStore: VectorStorePort
execute(cmd: SendMessageCommand): MessageResponse
«use case»
ExecuteActionUseCase
sessionRepo: ChatSessionRepository
orderExecPort: OrderExecPort
auditPort: AuditPort
execute(cmd: ExecuteActionCmd): ActionResult
«use case»
ProvideFeedbackUseCase
sessionRepo: ChatSessionRepository
analyticsPort: AnalyticsPort
execute(cmd: FeedbackCommand): void
«port»
LlmPort
chat(prompt, tools): LlmResponse
stream(prompt): Flux<Token>
«port»
VectorStorePort
search(query, k): List<Doc>
upsert(docs): void
«port»
OrderExecPort
placeOrder(cmd): OrderId
getStatus(id): OrderStatus
«port»
AuditPort
logInteraction(event): void
logAction(event): void
getAuditTrail(clientId): List
«port»
ChatSessionRepository
findById(id): ChatSession?
save(session): void
findByClient(cId): List
Infrastructure Layer — Adapters & External Integrations
«adapter»
ClaudeApiAdapter
apiKey: String
model: String
webClient: WebClient
chat(prompt, tools): LlmResponse
stream(prompt): Flux<Token>
«adapter»
PineconeAdapter
index: PineconeIndex
embeddingModel: String
search(query, k): List<Doc>
upsert(docs): void
«adapter»
MFUCentralAdapter
baseUrl: String
credentials: MfuCredentials
placeOrder(cmd): OrderId
getStatus(id): OrderStatus
«adapter»
KafkaAuditAdapter
kafkaTemplate: KafkaTemplate
topic: String
logInteraction(event): void
logAction(event): void
«decorator»
CachingLlmDecorator
delegate: LlmPort
cache: RedisTemplate
chat(prompt): LlmResponse
«adapter»
RedisSessionRepository
redisTemplate: RedisTemplate
ttl: Duration
findById(id): ChatSession?
save(session): void
«adapter»
JpaSessionRepository
entityManager: EntityManager
findById(id): ChatSession?
save(session): void
API Layer — Controllers & DTOs
«rest controller»
MiaChatController
POST /api/v1/mia/chat
POST /api/v1/mia/action
POST /api/v1/mia/feedback
GET /api/v1/mia/sessions
«websocket»
MiaStreamHandler
ws://mia/stream
handleTextMessage()
handleBinaryMessage()
«dto»
SendMessageRequest
sessionId: String
content: String
persona: String?
language: String?
«dto»
MessageResponse
messageId: String
content: String
actions: List<ActionDTO>
citations: List<CitationDTO>
Message --> ActionExecution --> Feedback --> DOMAIN: dashed + solid arrow --> ChatSession --> PORT: dashed + solid arrow --> LlmPort --> VectorStorePort --> OrderExecPort --> AuditPort --> USE CASE: dashed + solid arrow --> SendMessageUseCase --> ExecuteActionUseCase --> ProvideFeedbackUseCase -->
Dependency Rule enforced
Domain package (com.byld.mia.domain) has zero imports from Spring, JPA, Kafka, or any framework.

All dependencies point inward. Infrastructure depends on Application depends on Domain. Never the reverse.
Dependency
Implements
Composition
Domain Application Infrastructure API