From e285f3d3c6684d41444e1ee1e6b6fec676e51ec4 Mon Sep 17 00:00:00 2001 From: Ho Ngoc Hai Date: Sat, 17 Jan 2026 17:58:21 +0700 Subject: [PATCH] docs: Add Mission Service architecture documentation in English and Vietnamese. --- .../docs/en/ARCHITECTURE.md | 477 ++++++++++++++++++ .../docs/vi/ARCHITECTURE.md | 477 ++++++++++++++++++ 2 files changed, 954 insertions(+) create mode 100644 services/mission-service-net/docs/en/ARCHITECTURE.md create mode 100644 services/mission-service-net/docs/vi/ARCHITECTURE.md diff --git a/services/mission-service-net/docs/en/ARCHITECTURE.md b/services/mission-service-net/docs/en/ARCHITECTURE.md new file mode 100644 index 00000000..703226db --- /dev/null +++ b/services/mission-service-net/docs/en/ARCHITECTURE.md @@ -0,0 +1,477 @@ +# Mission Service Architecture + +Technical architecture documentation for the Mission Service. + +## High-Level Architecture + +```mermaid +%%{init: {'theme':'dark'}}%% +graph TD + subgraph API["🌐 API Layer"] + Controllers[Controllers] + Commands[Commands] + Queries[Queries] + end + + subgraph Domain["⚙️ Domain Layer"] + Mission[Mission Aggregate] + Task[Task Aggregate] + CheckIn[CheckIn Aggregate] + end + + subgraph Infra["💾 Infrastructure Layer"] + EF[EF Core] + Redis[(Redis Cache)] + RabbitMQ[RabbitMQ] + end + + subgraph Data["🗄️ Data Storage"] + DB[(PostgreSQL)] + end + + API --> Domain + Domain --> Infra + EF --> DB + + style API fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:3px + style Domain fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px + style Infra fill:#34495E,color:#ECF0F1,stroke:#2C3E50,stroke-width:2px + style Data fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px +``` + +## Architecture Patterns + +### CQRS Pattern + +```mermaid +%%{init: {'theme':'dark'}}%% +flowchart LR + subgraph Write["📝 Commands"] + C1[StartTaskCommand] + C2[CompleteTaskCommand] + C3[ClaimRewardCommand] + C4[CheckInCommand] + C5[CreateMissionCommand] + end + + subgraph Read["📖 Queries"] + Q1[GetMissionsQuery] + Q2[GetUserTasksQuery] + Q3[GetCheckInStatusQuery] + Q4[GetAnalyticsQuery] + end + + style Write fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px + style Read fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:2px +``` + +## Domain Model + +### Mission Aggregate + +```mermaid +%%{init: {'theme':'dark'}}%% +classDiagram + class Mission { + +Guid Id + +string Code + +LocalizedString Title + +LocalizedString Description + +MissionType Type + +MissionCategory Category + +MissionReward Reward + +FrequencyType Frequency + +int MaxCompletions + +DateTime StartDate + +DateTime EndDate + +MissionStatus Status + +int Priority + +Activate() + +Pause() + +ValidateCompletion() + } + + class MissionRule { + +Guid Id + +string RuleType + +string Operator + +string Value + +string Metadata + } + + class MissionReward { + +decimal Points + +decimal MiningBoost + +int ExperiencePoints + +string BadgeId + } + + Mission "1" --> "*" MissionRule : has + Mission --> MissionReward : uses +``` + +### Task Aggregate + +```mermaid +%%{init: {'theme':'dark'}}%% +classDiagram + class UserTask { + +Guid Id + +Guid UserId + +Guid MissionId + +TaskStatus Status + +TaskProgress Progress + +TaskEvidence Evidence + +VerificationResult Verification + +bool RewardClaimed + +DateTime StartedAt + +DateTime CompletedAt + +Start() + +UpdateProgress() + +SubmitEvidence() + +Complete() + +ClaimReward() + } + + class TaskProgress { + +int CurrentValue + +int TargetValue + +decimal PercentComplete + +DateTime LastUpdated + } + + class TaskEvidence { + +string EvidenceType + +string Data + +string ScreenshotUrl + +DateTime CapturedAt + } + + class VerificationResult { + +bool IsValid + +string FailureReason + +VerificationMethod Method + +Guid VerifiedBy + +DateTime VerifiedAt + } + + UserTask --> TaskProgress : tracks + UserTask --> TaskEvidence : has + UserTask --> VerificationResult : verified by +``` + +### CheckIn Aggregate + +```mermaid +%%{init: {'theme':'dark'}}%% +classDiagram + class UserCheckIn { + +Guid Id + +Guid UserId + +int CurrentStreak + +int LongestStreak + +int TotalCheckIns + +DateOnly LastCheckInDate + +CheckIn() + +CanCheckInToday() + +GetStreakBonus() + +GetMonthlyReward() + } + + class CheckInDay { + +Guid Id + +DateOnly Date + +decimal PointsEarned + +bool IsMilestone + } + + class StreakBonus { + +int MinDays + +int MaxDays + +decimal BonusPercent + +decimal MilestoneBonus + } + + UserCheckIn "1" --> "*" CheckInDay : records + UserCheckIn --> StreakBonus : applies +``` + +## Database Schema + +### ER Diagram + +```mermaid +%%{init: {'theme':'dark'}}%% +erDiagram + Mission ||--o{ MissionRule : has + Mission ||--o{ UserTask : generates + UserTask }o--|| User : belongs + User ||--o| UserCheckIn : has + UserCheckIn ||--o{ CheckInDay : records + + Mission { + uuid Id PK + string Code UK + json Title + json Description + string Type + string Category + json Reward + string Frequency + int MaxCompletions + datetime StartDate + datetime EndDate + string Status + int Priority + datetime CreatedAt + } + + MissionRule { + uuid Id PK + uuid MissionId FK + string RuleType + string Operator + string Value + json Metadata + } + + UserTask { + uuid Id PK + uuid UserId FK + uuid MissionId FK + string Status + json Progress + json Evidence + json Verification + bool RewardClaimed + datetime StartedAt + datetime CompletedAt + } + + UserCheckIn { + uuid Id PK + uuid UserId FK + int CurrentStreak + int LongestStreak + int TotalCheckIns + date LastCheckInDate + } + + CheckInDay { + uuid Id PK + uuid UserCheckInId FK + date Date + decimal PointsEarned + bool IsMilestone + } +``` + +## Reward Flow with Wallet Service + +### Claim Reward Sequence + +```mermaid +%%{init: {'theme':'dark'}}%% +sequenceDiagram + participant Client as 📱 Client + participant API as 🌐 Mission API + participant Task as ⚙️ TaskAggregate + participant DB as 💾 PostgreSQL + participant MQ as 📨 RabbitMQ + participant Wallet as 💰 Wallet Service + + Client->>API: POST /api/v1/tasks/{id}/claim + API->>Task: ClaimRewardCommand + Task->>Task: ValidateTaskCompleted() + Task->>Task: ValidateNotAlreadyClaimed() + + alt Task Valid + Task->>Task: MarkRewardClaimed() + Task->>DB: SaveChanges() + Task->>MQ: Publish MissionCompletedEvent + MQ->>Wallet: Consume MissionCompletedEvent + Wallet->>Wallet: GrantPoints(userId, amount) + API-->>Client: 200 OK { points_earned } + else Already Claimed + API-->>Client: 400 Bad Request + end +``` + +### CheckIn Reward Flow + +```mermaid +%%{init: {'theme':'dark'}}%% +sequenceDiagram + participant Client as 📱 Client + participant API as 🌐 Mission API + participant CheckIn as 📅 CheckInAggregate + participant DB as 💾 PostgreSQL + participant MQ as 📨 RabbitMQ + participant Wallet as 💰 Wallet Service + + Client->>API: POST /api/v1/checkin + API->>CheckIn: CheckInCommand + CheckIn->>CheckIn: CanCheckInToday() + + alt Can Check In + CheckIn->>CheckIn: IncrementStreak() + CheckIn->>CheckIn: CalculateStreakBonus() + CheckIn->>CheckIn: CheckMilestone() + CheckIn->>DB: SaveCheckInDay() + CheckIn->>MQ: Publish CheckInCompletedEvent + MQ->>Wallet: Consume CheckInCompletedEvent + Wallet->>Wallet: GrantPoints(userId, dailyPoints + bonus) + API-->>Client: 200 OK { streak, points, milestone } + else Already Checked In + API-->>Client: 400 Already checked in today + end +``` + +## Integration Events + +### Events Published + +```mermaid +%%{init: {'theme':'dark'}}%% +flowchart LR + subgraph Mission["📋 Mission Service"] + M[Events Publisher] + end + + subgraph Events["📨 Integration Events"] + E1[MissionCompletedEvent] + E2[CheckInCompletedEvent] + E3[TaskStartedEvent] + E4[RewardClaimedEvent] + end + + subgraph Consumers["📥 Consumers"] + Wallet[Wallet Service] + Mining[Mining Service] + end + + M --> E1 --> Wallet + M --> E2 --> Wallet + M --> E3 + M --> E4 --> Wallet + E1 -.-> Mining + + style Events fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px + style Wallet fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px +``` + +### Event Payloads + +```csharp +public record MissionCompletedEvent( + Guid TaskId, + Guid UserId, + Guid MissionId, + string MissionType, + decimal PointsEarned, + DateTime CompletedAt +); + +public record CheckInCompletedEvent( + Guid UserId, + int StreakDays, + decimal BasePoints, + decimal StreakBonus, + decimal MilestoneBonus, + decimal TotalPoints, + DateTime CheckedInAt +); + +public record RewardClaimedEvent( + Guid TaskId, + Guid UserId, + decimal PointsAmount, + string RewardType, + DateTime ClaimedAt +); +``` + +## Service Dependencies + +```mermaid +%%{init: {'theme':'dark'}}%% +graph TD + subgraph External["🔐 Authentication"] + IAM[IAM Service] + end + + subgraph Core["📋 Mission Service"] + Mission[Mission Service] + end + + subgraph Integration["🔗 Integrations"] + Wallet[Wallet Service] + Mining[Mining Service] + Social[Social Service] + Storage[Storage Service] + end + + IAM -->|JWT Validation| Mission + Mission -->|Grant Points| Wallet + Mission <-->|Referral Sync| Mining + Mission <-->|Friend Data| Social + Mission <-->|Media Upload| Storage + + style External fill:#C0392B,color:#ECF0F1,stroke:#A93226,stroke-width:2px + style Core fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:3px + style Integration fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:2px +``` + +## Caching Strategy + +| Key Pattern | TTL | Purpose | +|-------------|-----|---------| +| `mission:{id}` | 1h | Cache mission details | +| `missions:active` | 5m | Active missions list | +| `user:{id}:tasks` | 10m | User's active tasks | +| `user:{id}:checkin` | 24h | Check-in status | +| `config:missions` | 30m | Mission configurations | + +## Security + +### Anti-Fraud Flow + +```mermaid +%%{init: {'theme':'dark'}}%% +flowchart TD + Request([🚀 Request]) --> RateLimit{⏱️ Rate Limit} + RateLimit -->|Exceeded| Block[❌ Block] + RateLimit -->|OK| Cooldown{⏳ Cooldown} + Cooldown -->|Too Fast| Wait[⏸️ Wait] + Cooldown -->|OK| Device{🔍 Device Check} + Device -->|New/Suspicious| Flag[⚠️ Flag for Review] + Device -->|OK| Evidence{📝 Evidence Valid?} + Evidence -->|No| Reject[❌ Reject] + Evidence -->|Yes| Approve[✅ Approve & Reward] + + style Block fill:#C0392B,color:#ECF0F1,stroke:#A93226,stroke-width:2px + style Reject fill:#E74C3C,color:#ECF0F1,stroke:#C0392B,stroke-width:2px + style Approve fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px +``` + +## Health Checks + +| Endpoint | Check | +|----------|-------| +| `/health/live` | ✅ Service running | +| `/health/ready` | ✅ DB + Redis + RabbitMQ connected | +| `/health` | ✅ Full status | + +## Observability + +### Metrics +- Tasks started per minute +- Tasks completed per minute +- Check-in rate +- Reward claims +- Verification success rate + +### Logging +- Structured JSON logs (Serilog) +- Correlation IDs for tracing +- Sensitive data masking diff --git a/services/mission-service-net/docs/vi/ARCHITECTURE.md b/services/mission-service-net/docs/vi/ARCHITECTURE.md new file mode 100644 index 00000000..82626e57 --- /dev/null +++ b/services/mission-service-net/docs/vi/ARCHITECTURE.md @@ -0,0 +1,477 @@ +# Kiến Trúc Mission Service + +Tài liệu kiến trúc kỹ thuật cho Mission Service. + +## Kiến Trúc Tổng Quan + +```mermaid +%%{init: {'theme':'dark'}}%% +graph TD + subgraph API["🌐 Tầng API"] + Controllers[Controllers] + Commands[Commands] + Queries[Queries] + end + + subgraph Domain["⚙️ Tầng Domain"] + Mission[Mission Aggregate] + Task[Task Aggregate] + CheckIn[CheckIn Aggregate] + end + + subgraph Infra["💾 Tầng Infrastructure"] + EF[EF Core] + Redis[(Redis Cache)] + RabbitMQ[RabbitMQ] + end + + subgraph Data["🗄️ Lưu Trữ Dữ Liệu"] + DB[(PostgreSQL)] + end + + API --> Domain + Domain --> Infra + EF --> DB + + style API fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:3px + style Domain fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:2px + style Infra fill:#34495E,color:#ECF0F1,stroke:#2C3E50,stroke-width:2px + style Data fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px +``` + +## Các Mẫu Kiến Trúc + +### CQRS Pattern + +```mermaid +%%{init: {'theme':'dark'}}%% +flowchart LR + subgraph Write["📝 Commands (Ghi)"] + C1[StartTaskCommand] + C2[CompleteTaskCommand] + C3[ClaimRewardCommand] + C4[CheckInCommand] + C5[CreateMissionCommand] + end + + subgraph Read["📖 Queries (Đọc)"] + Q1[GetMissionsQuery] + Q2[GetUserTasksQuery] + Q3[GetCheckInStatusQuery] + Q4[GetAnalyticsQuery] + end + + style Write fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px + style Read fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:2px +``` + +## Domain Model + +### Mission Aggregate + +```mermaid +%%{init: {'theme':'dark'}}%% +classDiagram + class Mission { + +Guid Id + +string Code + +LocalizedString Title + +LocalizedString Description + +MissionType Type + +MissionCategory Category + +MissionReward Reward + +FrequencyType Frequency + +int MaxCompletions + +DateTime StartDate + +DateTime EndDate + +MissionStatus Status + +int Priority + +Activate() + +Pause() + +ValidateCompletion() + } + + class MissionRule { + +Guid Id + +string RuleType + +string Operator + +string Value + +string Metadata + } + + class MissionReward { + +decimal Points + +decimal MiningBoost + +int ExperiencePoints + +string BadgeId + } + + Mission "1" --> "*" MissionRule : chứa + Mission --> MissionReward : sử dụng +``` + +### Task Aggregate + +```mermaid +%%{init: {'theme':'dark'}}%% +classDiagram + class UserTask { + +Guid Id + +Guid UserId + +Guid MissionId + +TaskStatus Status + +TaskProgress Progress + +TaskEvidence Evidence + +VerificationResult Verification + +bool RewardClaimed + +DateTime StartedAt + +DateTime CompletedAt + +Start() + +UpdateProgress() + +SubmitEvidence() + +Complete() + +ClaimReward() + } + + class TaskProgress { + +int CurrentValue + +int TargetValue + +decimal PercentComplete + +DateTime LastUpdated + } + + class TaskEvidence { + +string EvidenceType + +string Data + +string ScreenshotUrl + +DateTime CapturedAt + } + + class VerificationResult { + +bool IsValid + +string FailureReason + +VerificationMethod Method + +Guid VerifiedBy + +DateTime VerifiedAt + } + + UserTask --> TaskProgress : theo dõi + UserTask --> TaskEvidence : có + UserTask --> VerificationResult : xác thực bởi +``` + +### CheckIn Aggregate + +```mermaid +%%{init: {'theme':'dark'}}%% +classDiagram + class UserCheckIn { + +Guid Id + +Guid UserId + +int CurrentStreak + +int LongestStreak + +int TotalCheckIns + +DateOnly LastCheckInDate + +CheckIn() + +CanCheckInToday() + +GetStreakBonus() + +GetMonthlyReward() + } + + class CheckInDay { + +Guid Id + +DateOnly Date + +decimal PointsEarned + +bool IsMilestone + } + + class StreakBonus { + +int MinDays + +int MaxDays + +decimal BonusPercent + +decimal MilestoneBonus + } + + UserCheckIn "1" --> "*" CheckInDay : ghi nhận + UserCheckIn --> StreakBonus : áp dụng +``` + +## Database Schema + +### ER Diagram + +```mermaid +%%{init: {'theme':'dark'}}%% +erDiagram + Mission ||--o{ MissionRule : có + Mission ||--o{ UserTask : tạo ra + UserTask }o--|| User : thuộc về + User ||--o| UserCheckIn : có + UserCheckIn ||--o{ CheckInDay : ghi nhận + + Mission { + uuid Id PK + string Code UK + json Title + json Description + string Type + string Category + json Reward + string Frequency + int MaxCompletions + datetime StartDate + datetime EndDate + string Status + int Priority + datetime CreatedAt + } + + MissionRule { + uuid Id PK + uuid MissionId FK + string RuleType + string Operator + string Value + json Metadata + } + + UserTask { + uuid Id PK + uuid UserId FK + uuid MissionId FK + string Status + json Progress + json Evidence + json Verification + bool RewardClaimed + datetime StartedAt + datetime CompletedAt + } + + UserCheckIn { + uuid Id PK + uuid UserId FK + int CurrentStreak + int LongestStreak + int TotalCheckIns + date LastCheckInDate + } + + CheckInDay { + uuid Id PK + uuid UserCheckInId FK + date Date + decimal PointsEarned + bool IsMilestone + } +``` + +## Luồng Nhận Thưởng với Wallet Service + +### Luồng Nhận Thưởng Task + +```mermaid +%%{init: {'theme':'dark'}}%% +sequenceDiagram + participant Client as 📱 Client + participant API as 🌐 Mission API + participant Task as ⚙️ TaskAggregate + participant DB as 💾 PostgreSQL + participant MQ as 📨 RabbitMQ + participant Wallet as 💰 Wallet Service + + Client->>API: POST /api/v1/tasks/{id}/claim + API->>Task: ClaimRewardCommand + Task->>Task: ValidateTaskCompleted() + Task->>Task: ValidateNotAlreadyClaimed() + + alt Task Hợp Lệ + Task->>Task: MarkRewardClaimed() + Task->>DB: SaveChanges() + Task->>MQ: Publish MissionCompletedEvent + MQ->>Wallet: Consume MissionCompletedEvent + Wallet->>Wallet: GrantPoints(userId, amount) + API-->>Client: 200 OK { points_earned } + else Đã Nhận Thưởng + API-->>Client: 400 Bad Request + end +``` + +### Luồng Thưởng Check-in + +```mermaid +%%{init: {'theme':'dark'}}%% +sequenceDiagram + participant Client as 📱 Client + participant API as 🌐 Mission API + participant CheckIn as 📅 CheckInAggregate + participant DB as 💾 PostgreSQL + participant MQ as 📨 RabbitMQ + participant Wallet as 💰 Wallet Service + + Client->>API: POST /api/v1/checkin + API->>CheckIn: CheckInCommand + CheckIn->>CheckIn: CanCheckInToday() + + alt Có Thể Check-in + CheckIn->>CheckIn: IncrementStreak() + CheckIn->>CheckIn: CalculateStreakBonus() + CheckIn->>CheckIn: CheckMilestone() + CheckIn->>DB: SaveCheckInDay() + CheckIn->>MQ: Publish CheckInCompletedEvent + MQ->>Wallet: Consume CheckInCompletedEvent + Wallet->>Wallet: GrantPoints(userId, dailyPoints + bonus) + API-->>Client: 200 OK { streak, points, milestone } + else Đã Check-in Hôm Nay + API-->>Client: 400 Đã điểm danh hôm nay + end +``` + +## Integration Events + +### Các Event Được Xuất Bản + +```mermaid +%%{init: {'theme':'dark'}}%% +flowchart LR + subgraph Mission["📋 Mission Service"] + M[Events Publisher] + end + + subgraph Events["📨 Integration Events"] + E1[MissionCompletedEvent] + E2[CheckInCompletedEvent] + E3[TaskStartedEvent] + E4[RewardClaimedEvent] + end + + subgraph Consumers["📥 Người Tiêu Thụ"] + Wallet[Wallet Service] + Mining[Mining Service] + end + + M --> E1 --> Wallet + M --> E2 --> Wallet + M --> E3 + M --> E4 --> Wallet + E1 -.-> Mining + + style Events fill:#E67E22,color:#ECF0F1,stroke:#D35400,stroke-width:2px + style Wallet fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px +``` + +### Event Payloads + +```csharp +public record MissionCompletedEvent( + Guid TaskId, + Guid UserId, + Guid MissionId, + string MissionType, + decimal PointsEarned, // Điểm kiếm được + DateTime CompletedAt +); + +public record CheckInCompletedEvent( + Guid UserId, + int StreakDays, // Số ngày streak + decimal BasePoints, // Điểm cơ bản + decimal StreakBonus, // Thưởng streak + decimal MilestoneBonus, // Thưởng mốc + decimal TotalPoints, // Tổng điểm + DateTime CheckedInAt +); + +public record RewardClaimedEvent( + Guid TaskId, + Guid UserId, + decimal PointsAmount, + string RewardType, + DateTime ClaimedAt +); +``` + +## Phụ Thuộc Dịch Vụ + +```mermaid +%%{init: {'theme':'dark'}}%% +graph TD + subgraph External["🔐 Xác Thực"] + IAM[IAM Service] + end + + subgraph Core["📋 Mission Service"] + Mission[Mission Service] + end + + subgraph Integration["🔗 Tích Hợp"] + Wallet[Wallet Service] + Mining[Mining Service] + Social[Social Service] + Storage[Storage Service] + end + + IAM -->|Xác thực JWT| Mission + Mission -->|Cấp Điểm| Wallet + Mission <-->|Đồng bộ Referral| Mining + Mission <-->|Dữ liệu Bạn bè| Social + Mission <-->|Upload Media| Storage + + style External fill:#C0392B,color:#ECF0F1,stroke:#A93226,stroke-width:2px + style Core fill:#8E44AD,color:#ECF0F1,stroke:#7D3C98,stroke-width:3px + style Integration fill:#3498DB,color:#ECF0F1,stroke:#2980B9,stroke-width:2px +``` + +## Chiến Lược Cache + +| Key Pattern | TTL | Mục Đích | +|-------------|-----|----------| +| `mission:{id}` | 1h | Cache chi tiết mission | +| `missions:active` | 5m | Danh sách missions hoạt động | +| `user:{id}:tasks` | 10m | Tasks đang làm của user | +| `user:{id}:checkin` | 24h | Trạng thái check-in | +| `config:missions` | 30m | Cấu hình mission | + +## Bảo Mật + +### Luồng Chống Gian Lận + +```mermaid +%%{init: {'theme':'dark'}}%% +flowchart TD + Request([🚀 Yêu Cầu]) --> RateLimit{⏱️ Rate Limit} + RateLimit -->|Vượt Quá| Block[❌ Chặn] + RateLimit -->|OK| Cooldown{⏳ Cooldown} + Cooldown -->|Quá Nhanh| Wait[⏸️ Chờ] + Cooldown -->|OK| Device{🔍 Kiểm Tra Thiết Bị} + Device -->|Mới/Đáng Ngờ| Flag[⚠️ Đánh Dấu Xem Xét] + Device -->|OK| Evidence{📝 Bằng Chứng Hợp Lệ?} + Evidence -->|Không| Reject[❌ Từ Chối] + Evidence -->|Có| Approve[✅ Duyệt & Thưởng] + + style Block fill:#C0392B,color:#ECF0F1,stroke:#A93226,stroke-width:2px + style Reject fill:#E74C3C,color:#ECF0F1,stroke:#C0392B,stroke-width:2px + style Approve fill:#27AE60,color:#ECF0F1,stroke:#229954,stroke-width:2px +``` + +## Health Checks + +| Endpoint | Kiểm Tra | +|----------|----------| +| `/health/live` | ✅ Service đang chạy | +| `/health/ready` | ✅ DB + Redis + RabbitMQ đã kết nối | +| `/health` | ✅ Trạng thái đầy đủ | + +## Observability + +### Metrics +- Số tasks bắt đầu mỗi phút +- Số tasks hoàn thành mỗi phút +- Tỷ lệ check-in +- Số lần nhận thưởng +- Tỷ lệ xác thực thành công + +### Logging +- Logs JSON có cấu trúc (Serilog) +- Correlation IDs để tracing +- Ẩn dữ liệu nhạy cảm