# Tài Liệu Kiến Trúc Chat Service

> Kiến trúc chi tiết cho Chat Service với E2EE, SignalR, scalability patterns, và AI integration.

## Tổng Quan Kiến Trúc

```mermaid
graph TB
    subgraph "Clients"
        WEB[Web App]
        MOB[Mobile App]
        BOT[Bot Client]
    end
    
    subgraph "Load Balancer"
        LB[NGINX/Traefik]
        SS[Sticky Sessions]
    end
    
    subgraph "Chat Service Instances"
        CS1[Instance 1<br/>SignalR Hub]
        CS2[Instance 2<br/>SignalR Hub]
        CS3[Instance 3<br/>SignalR Hub]
    end
    
    subgraph "Backplane"
        RD[(Redis<br/>Pub/Sub)]
    end
    
    subgraph "Storage"
        PG[(PostgreSQL<br/>Messages)]
        RC[(Redis<br/>Cache)]
    end
    
    subgraph "AI Service"
        AI[OpenAI<br/>GPT-4]
    end
    
    WEB & MOB & BOT --> LB
    LB --> SS --> CS1 & CS2 & CS3
    CS1 & CS2 & CS3 <--> RD
    CS1 & CS2 & CS3 --> PG
    CS1 & CS2 & CS3 --> RC
    CS1 & CS2 & CS3 --> AI
    
    style LB fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:3px
    style RD fill:#C0392B,color:#ECF0F1,stroke:#A93226,stroke-width:2px
    style PG fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px
    style AI fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
```

## Mã Hóa Đầu-cuối (E2EE)

### Giao Thức Trao Đổi Khóa X3DH

Service triển khai giao thức Extended Triple Diffie-Hellman (X3DH) để thiết lập phiên mã hóa:

```mermaid
sequenceDiagram
    participant Alice as Alice (Người gửi)
    participant Server as Chat Server
    participant Bob as Bob (Người nhận)
    
    Note over Bob,Server: Bob đăng ký keys
    Bob->>Server: Đăng ký Key Bundle<br/>(Identity, SignedPreKey, OneTimePreKeys)
    Server->>Server: Lưu chỉ public keys
    
    Note over Alice,Server: Alice khởi tạo session
    Alice->>Server: Yêu cầu Key Bundle của Bob
    Server->>Alice: {IdentityKey, SignedPreKey, OneTimePreKey}
    Alice->>Alice: X3DH → Session Key
    Alice->>Alice: AES-256-GCM mã hóa tin nhắn
    Alice->>Server: Gửi tin nhắn đã mã hóa
    Server->>Bob: Chuyển tin nhắn đã mã hóa
    Bob->>Bob: X3DH → Session Key
    Bob->>Bob: AES-256-GCM giải mã tin nhắn
    
    style Server fill:#2C3E50,color:#ECF0F1,stroke:#34495E,stroke-width:3px
```

### Các Thành Phần Khóa

| Thành phần | Mô tả | Lưu trữ |
|------------|-------|---------|
| **Identity Key** | Cặp khóa Curve25519 dài hạn | Private: Chỉ client |
| **Signed Pre-Key** | Xoay vòng mỗi 30 ngày | Public: Server |
| **One-Time Pre-Keys** | Tiêu thụ mỗi session | Public: Server (xóa sau khi dùng) |
| **Session Key** | Derive qua X3DH | Không lưu trữ |

### Tính Năng Bảo Mật

- ✅ **Forward Secrecy**: Khóa bị lộ không tiết lộ tin nhắn cũ
- ✅ **Zero-Knowledge Server**: Server không thể giải mã tin nhắn
- ✅ **Deniability**: Không có bằng chứng mật mã về tác giả

## Domain Model

### Aggregate Roots

```mermaid
erDiagram
    Conversation ||--o{ Message : contains
    Conversation ||--o{ ConversationParticipant : has
    ChatUser ||--o{ Conversation : participates
    ChatUser ||--|| UserKeyBundle : has
    ChatUser ||--o{ OneTimePreKey : owns
    
    Conversation {
        uuid Id PK
        string Name
        string AvatarUrl
        enum Type "Direct|Group"
        uuid CreatorId
        datetime CreatedAt
        datetime LastActivityAt
    }
    
    Message {
        uuid Id PK
        uuid ConversationId FK
        uuid SenderId FK
        string EncryptedContent
        string Nonce
        string AuthTag
        enum Type "Text|Image|File|System"
        enum Status "Sent|Delivered|Read|Failed"
        datetime CreatedAt
    }
    
    ConversationParticipant {
        uuid Id PK
        uuid ConversationId FK
        uuid ChatUserId FK
        enum Role "Owner|Admin|Member"
        datetime JoinedAt
        datetime LastReadAt
    }
    
    ChatUser {
        uuid Id PK
        string IdentityUserId
        string DisplayName
        string AvatarUrl
        enum Status "Online|Away|Offline"
        datetime LastSeenAt
    }
    
    UserKeyBundle {
        string IdentityPublicKey
        string SignedPreKey
        string SignedPreKeySignature
        datetime SignedPreKeyTimestamp
    }
    
    OneTimePreKey {
        uuid Id PK
        int KeyId
        string PublicKey
        bool IsUsed
        datetime CreatedAt
    }
```

### Domain Events

| Event | Trigger | Handler |
|-------|---------|---------|
| `ConversationCreatedDomainEvent` | Hội thoại mới được tạo | Thông báo participants |
| `MessageSentDomainEvent` | Tin nhắn được gửi | Cập nhật last_activity, broadcast |
| `MessageDeliveredDomainEvent` | Tin nhắn đã gửi đến | Thông báo sender |
| `MessageReadDomainEvent` | Tin nhắn đã đọc | Thông báo sender |
| `UserJoinedRoomDomainEvent` | User tham gia room | Thông báo members |
| `UserLeftRoomDomainEvent` | User rời room | Thông báo members |
| `TypingDomainEvent` | User đang gõ | Broadcast to room |
| `ChatUserCreatedDomainEvent` | Chat user mới | Khởi tạo presence |
| `UserKeyBundleUpdatedDomainEvent` | Keys được cập nhật | Invalidate cached keys |

## SignalR Hub Architecture

### Connection Lifecycle

```mermaid
sequenceDiagram
    participant Client
    participant Hub as ChatHub
    participant Groups
    participant DB as Database
    participant Redis
    
    Client->>Hub: Connect (JWT Token)
    Hub->>Hub: OnConnectedAsync()
    Hub->>DB: Load danh sách hội thoại
    Hub->>Groups: AddToGroupAsync(conversationId)
    Hub->>Redis: Publish(UserOnline)
    Hub-->>Client: Connected
    
    Note over Client,Hub: User hiện đang online
    
    Client->>Hub: SendMessage(conversationId, encryptedContent)
    Hub->>DB: Lưu tin nhắn đã mã hóa
    Hub->>Redis: Publish(NewMessage)
    Redis-->>Hub: Broadcast đến tất cả instances
    Hub->>Groups: Clients.Group(conversationId)
    Hub-->>Client: ReceiveMessage
    
    style Hub fill:#2C3E50,color:#ECF0F1,stroke:#34495E,stroke-width:3px
    style Redis fill:#C0392B,color:#ECF0F1,stroke:#A93226,stroke-width:2px
    style DB fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px
```

### Hub Methods

```csharp
public class ChatHub : Hub<IChatHubClient>
{
    // Quản lý kết nối
    public override Task OnConnectedAsync();
    public override Task OnDisconnectedAsync(Exception? exception);
    
    // Quản lý phòng
    public Task JoinRoom(Guid conversationId);
    public Task LeaveRoom(Guid conversationId);
    
    // Nhắn tin
    public Task SendMessage(Guid conversationId, string encryptedContent, 
                           string nonce, string? authTag);
    public Task SendTypingIndicator(Guid conversationId, bool isTyping);
    public Task MarkMessageRead(Guid conversationId, Guid messageId);
    
    // Tích hợp AI
    public IAsyncEnumerable<string> StreamAIResponse(Guid conversationId, 
                                                      string prompt);
}
```

## Scalability Architecture

### Redis Backplane

```mermaid
graph LR
    subgraph "Instance 1"
        C1[Client A] --> H1[Hub 1]
    end
    
    subgraph "Instance 2"
        C2[Client B] --> H2[Hub 2]
    end
    
    subgraph "Redis"
        CH[Channel: chat.messages]
    end
    
    H1 -->|Publish| CH
    CH -->|Subscribe| H2
    H2 -->|Deliver| C2
    
    style CH fill:#C0392B,color:#ECF0F1,stroke:#A93226,stroke-width:2px
    style H1 fill:#2C3E50,color:#ECF0F1,stroke:#34495E,stroke-width:2px
    style H2 fill:#2C3E50,color:#ECF0F1,stroke:#34495E,stroke-width:2px
```

### Cấu Hình Scaling

| Option | Ưu điểm | Nhược điểm |
|--------|---------|------------|
| **Redis Backplane** | Đơn giản, on-premise | Cần quản lý Redis cluster |
| **Azure SignalR** | Serverless, không sticky sessions | Vendor lock-in, chi phí |
| **Sticky Sessions** | Đơn giản nhất | Không hoàn hảo cho failover |

## AI Integration Flow

```mermaid
sequenceDiagram
    participant User
    participant Hub as ChatHub
    participant AI as AIService
    participant OpenAI
    participant DB as Database
    
    User->>Hub: "@gpt Giải thích DDD"
    Hub->>DB: Load lịch sử (20 tin nhắn)
    Hub->>AI: StreamAsync(prompt, history)
    AI->>OpenAI: ChatCompletion (stream: true)
    
    loop Streaming
        OpenAI-->>AI: Token chunk
        AI-->>Hub: yield chunk
        Hub-->>User: ReceiveAIChunk
    end
    
    Hub->>DB: Lưu AI response
    Hub-->>User: AIResponseComplete
    
    style Hub fill:#2C3E50,color:#ECF0F1,stroke:#34495E,stroke-width:3px
    style AI fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px
    style OpenAI fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px
```

## Resiliency Patterns

### Automatic Reconnect

```mermaid
stateDiagram-v2
    [*] --> Connected
    Connected --> Disconnected: Mất kết nối
    Disconnected --> Reconnecting: Tự động retry
    Reconnecting --> Connected: Thành công
    Reconnecting --> Reconnecting: Retry với backoff
    Reconnecting --> Disconnected: Vượt quá max retries
    Disconnected --> [*]: User logout
```

### Stateful Reconnect (.NET 8+)

```csharp
// Server configuration
builder.Services.AddSignalR(options =>
{
    options.StatefulReconnectBufferSize = 32 * 1024; // 32KB
});

// Với UseStatefulReconnect
app.MapHub<ChatHub>("/chatHub", options =>
{
    options.AllowStatefulReconnects = true;
});
```

## Deployment Architecture

### Kubernetes với Sticky Sessions

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: chatservice
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: chatservice
        image: chatservice:latest
        ports:
        - containerPort: 8080
        env:
        - name: REDIS_URL
          valueFrom:
            secretKeyRef:
              name: chat-secrets
              key: redis-url
---
apiVersion: v1
kind: Service
metadata:
  name: chatservice
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-sticky-sessions: "true"
spec:
  type: LoadBalancer
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 3600
  ports:
  - port: 80
    targetPort: 8080
```

## Health Checks

```csharp
builder.Services.AddHealthChecks()
    .AddNpgSql(connectionString, name: "postgresql")
    .AddRedis(redisConnectionString, name: "redis")
    .AddSignalRHub<ChatHub>(name: "signalr-hub");
```

## Tài Liệu Tham Khảo

- [ASP.NET Core SignalR](https://docs.microsoft.com/en-us/aspnet/core/signalr/)
- [SignalR Scale-out with Redis](https://docs.microsoft.com/en-us/aspnet/core/signalr/redis-backplane)
- [X3DH Protocol Specification](https://signal.org/docs/specifications/x3dh/)
- [Azure SignalR Service](https://docs.microsoft.com/en-us/azure/azure-signalr/)
