chore: update project documentation, audit reports, and initialize IDE configuration files
Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 29s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 2m42s
Deploy / Build Web Image (push) Failing after 27s
Deploy / Build AI Services Image (push) Failing after 29s
E2E Tests / Playwright E2E (push) Failing after 43s
Deploy / Build API Image (push) Failing after 1m31s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 6s
Security Scanning / Trivy Scan — API Image (push) Failing after 5m35s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 3m45s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Security Scanning / Trivy Scan — Web Image (push) Failing after 13m51s
Security Scanning / Trivy Filesystem Scan (push) Failing after 14m46s
Security Scanning / Security Gate (push) Has been cancelled
Some checks failed
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 29s
CI / E2E Tests (push) Has been skipped
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 2m42s
Deploy / Build Web Image (push) Failing after 27s
Deploy / Build AI Services Image (push) Failing after 29s
E2E Tests / Playwright E2E (push) Failing after 43s
Deploy / Build API Image (push) Failing after 1m31s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 6s
Security Scanning / Trivy Scan — API Image (push) Failing after 5m35s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 3m45s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Deploy / Deploy to Production (push) Has been skipped
Deploy / Smoke Test Production (push) Has been skipped
Deploy / Rollback Staging (push) Has been skipped
Deploy / Rollback Production (push) Has been skipped
Security Scanning / Trivy Scan — Web Image (push) Failing after 13m51s
Security Scanning / Trivy Filesystem Scan (push) Failing after 14m46s
Security Scanning / Security Gate (push) Has been cancelled
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
# GoodGo Platform AI - Technical Reference & Deep Dive
|
||||
**For Developers & Architects**
|
||||
# GoodGo Platform AI - Tài Liệu Kỹ Thuật Tham Chiếu & Phân Tích Chuyên Sâu
|
||||
**Dành cho Nhà Phát Triển & Kiến Trúc Sư**
|
||||
|
||||
---
|
||||
|
||||
## BACKEND MODULE HIERARCHY
|
||||
## PHÂN CẤP MODULE BACKEND
|
||||
|
||||
### Core Module Dependencies
|
||||
### Phụ Thuộc Module Cốt Lõi
|
||||
```
|
||||
SharedModule (lowest level)
|
||||
SharedModule (cấp thấp nhất)
|
||||
├── Infrastructure Services
|
||||
├── Middleware & Guards
|
||||
├── Decorators & Utilities
|
||||
@@ -32,258 +32,258 @@ SharedModule (lowest level)
|
||||
|
||||
---
|
||||
|
||||
## DOMAIN MODELS - RELATIONSHIPS
|
||||
## MÔ HÌNH MIỀN - MỐI QUAN HỆ
|
||||
|
||||
### User Role Hierarchy
|
||||
### Phân Cấp Vai Trò Người Dùng
|
||||
```
|
||||
User (root entity)
|
||||
├── Role: BUYER → Can browse, search, inquire, purchase
|
||||
├── Role: SELLER → Can create listings, receive inquiries, sell
|
||||
├── Role: AGENT → Extends Seller + lead management
|
||||
└── Role: ADMIN → All permissions + moderation
|
||||
User (thực thể gốc)
|
||||
├── Role: BUYER → Có thể duyệt, tìm kiếm, hỏi thăm, mua
|
||||
├── Role: SELLER → Có thể tạo tin đăng, nhận hỏi thăm, bán
|
||||
├── Role: AGENT → Mở rộng từ Seller + quản lý khách hàng tiềm năng
|
||||
└── Role: ADMIN → Toàn bộ quyền hạn + kiểm duyệt
|
||||
```
|
||||
|
||||
### Listing Workflow
|
||||
### Luồng Xử Lý Tin Đăng
|
||||
```
|
||||
User (SELLER)
|
||||
↓ creates
|
||||
↓ tạo
|
||||
Property + PropertyMedia
|
||||
↓ associated with
|
||||
Listing (status: DRAFT → PUBLISHED → SOLD → ARCHIVED)
|
||||
↓ receives
|
||||
Inquiry (from BUYER/AGENT)
|
||||
↓ converts to
|
||||
Transaction (buyer-seller exchange)
|
||||
↓ followed by
|
||||
Review + UsageRecord (analytics)
|
||||
↓ liên kết với
|
||||
Listing (trạng thái: DRAFT → PUBLISHED → SOLD → ARCHIVED)
|
||||
↓ nhận
|
||||
Inquiry (từ BUYER/AGENT)
|
||||
↓ chuyển đổi thành
|
||||
Transaction (giao dịch người mua - người bán)
|
||||
↓ tiếp theo là
|
||||
Review + UsageRecord (phân tích)
|
||||
```
|
||||
|
||||
### Payment Flow
|
||||
### Luồng Thanh Toán
|
||||
```
|
||||
User (Subscription Start)
|
||||
User (Bắt đầu Đăng ký)
|
||||
↓
|
||||
Plan (monthly/yearly pricing)
|
||||
Plan (giá hàng tháng/hàng năm)
|
||||
↓
|
||||
Subscription (active/cancelled/expired)
|
||||
Subscription (đang hoạt động/đã hủy/đã hết hạn)
|
||||
↓
|
||||
Payment (processed via VNPay)
|
||||
├── Idempotency Key (prevents duplicates)
|
||||
Payment (xử lý qua VNPay)
|
||||
├── Idempotency Key (ngăn trùng lặp)
|
||||
└── Status Tracking
|
||||
↓
|
||||
UsageRecord (track consumed resources)
|
||||
UsageRecord (theo dõi tài nguyên đã dùng)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## AUTHENTICATION FLOW
|
||||
## LUỒNG XÁC THỰC
|
||||
|
||||
### JWT Token Lifecycle
|
||||
### Vòng Đời Token JWT
|
||||
```
|
||||
1. User Login (email + password OR OAuth)
|
||||
└→ Verify credentials (bcrypt hash)
|
||||
1. Đăng nhập Người dùng (email + mật khẩu HOẶC OAuth)
|
||||
└→ Xác minh thông tin đăng nhập (bcrypt hash)
|
||||
|
||||
2. Generate Tokens
|
||||
├→ AccessToken (15 min, bearer auth)
|
||||
└→ RefreshToken (7 days, stored in DB)
|
||||
└→ Token Family (refresh rotation)
|
||||
2. Tạo Token
|
||||
├→ AccessToken (15 phút, bearer auth)
|
||||
└→ RefreshToken (7 ngày, lưu trong DB)
|
||||
└→ Token Family (luân phiên refresh)
|
||||
|
||||
3. Return to Client
|
||||
└→ Set Secure HTTP-Only Cookie (refresh token)
|
||||
3. Trả về Client
|
||||
└→ Đặt Cookie HTTP-Only Bảo mật (refresh token)
|
||||
|
||||
4. API Access
|
||||
4. Truy cập API
|
||||
├→ Authorization: Bearer <accessToken>
|
||||
├→ Guard validates JWT signature
|
||||
└→ Inject user context into request
|
||||
├→ Guard xác thực chữ ký JWT
|
||||
└→ Đưa ngữ cảnh người dùng vào request
|
||||
|
||||
5. Token Refresh
|
||||
├→ Client sends refresh token
|
||||
├→ Verify token family (revocation check)
|
||||
├→ Rotate token (issue new family)
|
||||
└→ Return new access token
|
||||
5. Làm mới Token
|
||||
├→ Client gửi refresh token
|
||||
├→ Xác minh token family (kiểm tra thu hồi)
|
||||
├→ Luân phiên token (cấp family mới)
|
||||
└→ Trả về access token mới
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## DATABASE SCHEMA - KEY INDEXES
|
||||
## SCHEMA CƠ SỞ DỮ LIỆU - CHỈ MỤC QUAN TRỌNG
|
||||
|
||||
### Query Optimization Strategy
|
||||
### Chiến Lược Tối Ưu Hóa Truy Vấn
|
||||
```
|
||||
User Table:
|
||||
├── idx_user_role (BUYER/SELLER/AGENT/ADMIN filtering)
|
||||
├── idx_user_kyc_status (compliance checks)
|
||||
├── idx_user_active (active user queries)
|
||||
├── idx_user_deleted_at (soft delete filtering)
|
||||
└── idx_role_active_created (complex queries: role + active + order by)
|
||||
Bảng User:
|
||||
├── idx_user_role (lọc BUYER/SELLER/AGENT/ADMIN)
|
||||
├── idx_user_kyc_status (kiểm tra tuân thủ)
|
||||
├── idx_user_active (truy vấn người dùng hoạt động)
|
||||
├── idx_user_deleted_at (lọc xóa mềm)
|
||||
└── idx_role_active_created (truy vấn phức tạp: vai trò + hoạt động + sắp xếp theo)
|
||||
|
||||
Listing Table:
|
||||
├── idx_listing_status (published, archived, sold filtering)
|
||||
├── idx_listing_user_created (user's listings ordered)
|
||||
└── idx_listing_location_geo (PostGIS spatial queries)
|
||||
Bảng Listing:
|
||||
├── idx_listing_status (lọc đã đăng, đã lưu trữ, đã bán)
|
||||
├── idx_listing_user_created (tin đăng của người dùng theo thứ tự)
|
||||
└── idx_listing_location_geo (truy vấn không gian PostGIS)
|
||||
|
||||
Payment Table:
|
||||
├── idx_payment_user_status (user's payment history)
|
||||
├── idx_payment_idempotency (duplicate prevention)
|
||||
└── idx_payment_external_ref (payment gateway reconciliation)
|
||||
Bảng Payment:
|
||||
├── idx_payment_user_status (lịch sử thanh toán của người dùng)
|
||||
├── idx_payment_idempotency (ngăn trùng lặp)
|
||||
└── idx_payment_external_ref (đối soát cổng thanh toán)
|
||||
|
||||
Search Optimization:
|
||||
└── Typesense (full-text + geo-search, delegated from DB)
|
||||
Tối Ưu Hóa Tìm Kiếm:
|
||||
└── Typesense (tìm kiếm toàn văn bản + địa lý, ủy thác từ DB)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## SECURITY LAYERS - DETAILED
|
||||
## CÁC LỚP BẢO MẬT - CHI TIẾT
|
||||
|
||||
### Layer 1: Network Level
|
||||
### Lớp 1: Cấp Mạng
|
||||
```
|
||||
HTTP Request
|
||||
↓
|
||||
Helmet (Express middleware)
|
||||
├── Content-Security-Policy
|
||||
│ └── Blocks inline scripts, restricts origins
|
||||
│ └── Chặn script nội tuyến, hạn chế nguồn gốc
|
||||
├── X-Frame-Options: DENY
|
||||
│ └── Prevents clickjacking
|
||||
│ └── Ngăn chặn clickjacking
|
||||
├── Strict-Transport-Security (HSTS)
|
||||
│ └── Forces HTTPS for 31536000 seconds
|
||||
│ └── Bắt buộc HTTPS trong 31536000 giây
|
||||
├── X-Content-Type-Options: nosniff
|
||||
│ └── Prevents MIME-sniffing
|
||||
│ └── Ngăn chặn MIME-sniffing
|
||||
└── Referrer-Policy: strict-origin-when-cross-origin
|
||||
└── Controls referrer leaks
|
||||
└── Kiểm soát rò rỉ referrer
|
||||
```
|
||||
|
||||
### Layer 2: Application Level
|
||||
### Lớp 2: Cấp Ứng Dụng
|
||||
```
|
||||
Request Processing
|
||||
Xử Lý Request
|
||||
↓
|
||||
1. CORS Validation
|
||||
└── Whitelist check (process.env.CORS_ORIGINS)
|
||||
1. Xác Thực CORS
|
||||
└── Kiểm tra danh sách trắng (process.env.CORS_ORIGINS)
|
||||
|
||||
2. CSRF Protection
|
||||
├── Read (GET): Set __Host-X-CSRF-Token cookie
|
||||
└── Write (POST/PUT/PATCH/DELETE):
|
||||
├── Verify X-CSRF-Token header
|
||||
└── Validate cookie matches header (double-submit)
|
||||
2. Bảo Vệ CSRF
|
||||
├── Đọc (GET): Đặt cookie __Host-X-CSRF-Token
|
||||
└── Ghi (POST/PUT/PATCH/DELETE):
|
||||
├── Xác minh header X-CSRF-Token
|
||||
└── Xác nhận cookie khớp header (double-submit)
|
||||
|
||||
3. Input Sanitization
|
||||
├── Remove XSS vectors (sanitize-html)
|
||||
├── Whitelist validation (class-validator)
|
||||
└── Type coercion (class-transformer)
|
||||
3. Làm Sạch Đầu Vào
|
||||
├── Loại bỏ vector XSS (sanitize-html)
|
||||
├── Xác thực danh sách trắng (class-validator)
|
||||
└── Ép kiểu dữ liệu (class-transformer)
|
||||
|
||||
4. Rate Limiting
|
||||
├── Global: 60 req/min per IP
|
||||
├── Auth: 10 req/min per IP (login brute-force protection)
|
||||
└── Payments: 20 req/min per IP (webhook replay protection)
|
||||
4. Giới Hạn Tốc Độ
|
||||
├── Toàn cầu: 60 req/phút mỗi IP
|
||||
├── Xác thực: 10 req/phút mỗi IP (bảo vệ brute-force đăng nhập)
|
||||
└── Thanh toán: 20 req/phút mỗi IP (bảo vệ phát lại webhook)
|
||||
```
|
||||
|
||||
### Layer 3: Data Level
|
||||
### Lớp 3: Cấp Dữ Liệu
|
||||
```
|
||||
Field Encryption (PII Protection)
|
||||
Mã Hóa Trường (Bảo Vệ PII)
|
||||
├── FieldEncryptionService
|
||||
│ ├── AES-256-GCM encryption
|
||||
│ ├── Field-level (can query by hash)
|
||||
│ └── Key derivation from master secret
|
||||
├── Email: Encrypted + hashed (both in DB)
|
||||
├── Phone: Encrypted + hashed (both in DB)
|
||||
└── KYC Data: Encrypted JSON storage
|
||||
│ ├── Mã hóa AES-256-GCM
|
||||
│ ├── Cấp trường (có thể truy vấn bằng hash)
|
||||
│ └── Dẫn xuất khóa từ bí mật chính
|
||||
├── Email: Đã mã hóa + đã băm (cả hai trong DB)
|
||||
├── Điện thoại: Đã mã hóa + đã băm (cả hai trong DB)
|
||||
└── Dữ liệu KYC: Lưu trữ JSON đã mã hóa
|
||||
|
||||
Audit Trail
|
||||
├── AdminAuditLog captures:
|
||||
│ ├── User ID (who)
|
||||
│ ├── Action (what)
|
||||
│ ├── Target entity (where)
|
||||
│ ├── Changes (before/after)
|
||||
│ └── Timestamp (when)
|
||||
└── Queryable for compliance
|
||||
Nhật Ký Kiểm Toán
|
||||
├── AdminAuditLog ghi lại:
|
||||
│ ├── User ID (ai)
|
||||
│ ├── Action (gì)
|
||||
│ ├── Target entity (ở đâu)
|
||||
│ ├── Changes (trước/sau)
|
||||
│ └── Timestamp (khi nào)
|
||||
└── Có thể truy vấn để tuân thủ
|
||||
```
|
||||
|
||||
### Layer 4: Authorization
|
||||
### Lớp 4: Phân Quyền
|
||||
```
|
||||
Route Handler
|
||||
↓
|
||||
@UseGuards(JwtGuard, RoleGuard)
|
||||
├── Extract JWT from Authorization header
|
||||
├── Validate signature (HS256)
|
||||
├── Check token expiration
|
||||
├── Inject user context (request.user)
|
||||
└── Verify role (BUYER/SELLER/AGENT/ADMIN)
|
||||
└── Reject if insufficient permissions
|
||||
├── Trích xuất JWT từ header Authorization
|
||||
├── Xác thực chữ ký (HS256)
|
||||
├── Kiểm tra hạn sử dụng token
|
||||
├── Đưa ngữ cảnh người dùng vào (request.user)
|
||||
└── Xác minh vai trò (BUYER/SELLER/AGENT/ADMIN)
|
||||
└── Từ chối nếu không đủ quyền
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CQRS PATTERN IMPLEMENTATION
|
||||
## TRIỂN KHAI MẪU CQRS
|
||||
|
||||
### Command Pattern (State Changes)
|
||||
### Mẫu Lệnh (Thay Đổi Trạng Thái)
|
||||
```
|
||||
CreateListingCommand
|
||||
├── Input: CreateListingDTO
|
||||
├── Handler: CreateListingCommandHandler
|
||||
│ ├── Validate inputs
|
||||
│ ├── Check user permissions
|
||||
│ ├── Create Property entity
|
||||
│ ├── Create Listing entity
|
||||
│ ├── Emit ListingCreatedEvent
|
||||
│ └── Update search index
|
||||
│ ├── Xác thực đầu vào
|
||||
│ ├── Kiểm tra quyền người dùng
|
||||
│ ├── Tạo thực thể Property
|
||||
│ ├── Tạo thực thể Listing
|
||||
│ ├── Phát ListingCreatedEvent
|
||||
│ └── Cập nhật chỉ mục tìm kiếm
|
||||
└── Output: CreatedListingDTO
|
||||
|
||||
Flow:
|
||||
Luồng:
|
||||
Controller → Command → CommandHandler → Domain → Event → Repository → Cache invalidate
|
||||
```
|
||||
|
||||
### Query Pattern (Read-only)
|
||||
### Mẫu Truy Vấn (Chỉ Đọc)
|
||||
```
|
||||
GetListingQuery
|
||||
├── Input: ListingId
|
||||
├── Handler: GetListingQueryHandler
|
||||
│ ├── Check cache (Redis)
|
||||
│ ├── If hit: return cached
|
||||
│ └── If miss:
|
||||
│ ├── Query database
|
||||
│ ├── Cache result (TTL-based)
|
||||
│ └── Return to client
|
||||
│ ├── Kiểm tra cache (Redis)
|
||||
│ ├── Nếu trúng cache: trả về kết quả đã cache
|
||||
│ └── Nếu không trúng:
|
||||
│ ├── Truy vấn cơ sở dữ liệu
|
||||
│ ├── Cache kết quả (dựa trên TTL)
|
||||
│ └── Trả về cho client
|
||||
└── Output: ListingDTO
|
||||
|
||||
Flow:
|
||||
Luồng:
|
||||
Controller → Query → QueryHandler → Repository → Cache store → Response
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CACHING STRATEGY
|
||||
## CHIẾN LƯỢC CACHE
|
||||
|
||||
### Multi-Level Caching
|
||||
### Cache Nhiều Cấp
|
||||
```
|
||||
Level 1: Browser Cache
|
||||
├── Static assets (CSS, JS)
|
||||
├── Max-Age: 31536000 (1 year)
|
||||
Cấp 1: Cache Trình Duyệt
|
||||
├── Tài nguyên tĩnh (CSS, JS)
|
||||
├── Max-Age: 31536000 (1 năm)
|
||||
└── Immutable: true
|
||||
|
||||
Level 2: CDN Cache (if deployed)
|
||||
├── JSON responses
|
||||
├── Max-Age: 300 (5 min)
|
||||
└── Surrogate-Key invalidation
|
||||
Cấp 2: Cache CDN (nếu đã triển khai)
|
||||
├── Phản hồi JSON
|
||||
├── Max-Age: 300 (5 phút)
|
||||
└── Vô hiệu hóa Surrogate-Key
|
||||
|
||||
Level 3: Application Cache (Redis)
|
||||
├── User objects (TTL: 1 hour)
|
||||
├── Listing details (TTL: 30 min)
|
||||
├── Search results (TTL: 5 min)
|
||||
└── Rate limit counters (TTL: per window)
|
||||
Cấp 3: Cache Ứng Dụng (Redis)
|
||||
├── Đối tượng User (TTL: 1 giờ)
|
||||
├── Chi tiết Listing (TTL: 30 phút)
|
||||
├── Kết quả tìm kiếm (TTL: 5 phút)
|
||||
└── Bộ đếm giới hạn tốc độ (TTL: theo cửa sổ)
|
||||
|
||||
Cache Invalidation Triggers:
|
||||
├── Event-based: ListingUpdatedEvent → invalidate key
|
||||
├── Time-based: TTL expiration
|
||||
├── Manual: Cache.delete(key) on batch operations
|
||||
└── Circuit breaker: If Redis down, bypass to DB
|
||||
Kích Hoạt Vô Hiệu Hóa Cache:
|
||||
├── Dựa trên sự kiện: ListingUpdatedEvent → vô hiệu hóa key
|
||||
├── Dựa trên thời gian: hết hạn TTL
|
||||
├── Thủ công: Cache.delete(key) trên các thao tác theo lô
|
||||
└── Circuit breaker: Nếu Redis down, bỏ qua sang DB
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ERROR HANDLING & OBSERVABILITY
|
||||
## XỬ LÝ LỖI & QUAN SÁT HỆ THỐNG
|
||||
|
||||
### Exception Hierarchy
|
||||
### Phân Cấp Ngoại Lệ
|
||||
```
|
||||
GlobalExceptionFilter (catches all)
|
||||
GlobalExceptionFilter (bắt tất cả)
|
||||
│
|
||||
├→ HttpException (known errors)
|
||||
├→ HttpException (lỗi đã biết)
|
||||
│ ├── BadRequestException (400)
|
||||
│ ├── UnauthorizedException (401)
|
||||
│ ├── ForbiddenException (403)
|
||||
@@ -291,46 +291,46 @@ GlobalExceptionFilter (catches all)
|
||||
│ ├── ConflictException (409)
|
||||
│ └── InternalServerErrorException (500)
|
||||
│
|
||||
└→ Unknown Error
|
||||
└→ Lỗi Không Xác Định
|
||||
└→ Sentry.captureException(error)
|
||||
├── Capture stack trace
|
||||
├── Attach request context
|
||||
├── Tag by module/operation
|
||||
└── Alert ops team (if severity > WARN)
|
||||
├── Ghi lại stack trace
|
||||
├── Đính kèm ngữ cảnh request
|
||||
├── Gắn thẻ theo module/thao tác
|
||||
└── Cảnh báo đội vận hành (nếu mức độ nghiêm trọng > WARN)
|
||||
|
||||
Structured Logging (Pino)
|
||||
├── JSON format for log aggregation
|
||||
├── Context injection (request ID, user ID)
|
||||
├── Log levels: trace, debug, info, warn, error, fatal
|
||||
└── Destination: stdout (collected by Loki/Promtail)
|
||||
Ghi Log Có Cấu Trúc (Pino)
|
||||
├── Định dạng JSON để tổng hợp log
|
||||
├── Đưa ngữ cảnh vào (request ID, user ID)
|
||||
├── Cấp độ log: trace, debug, info, warn, error, fatal
|
||||
└── Đích: stdout (thu thập bởi Loki/Promtail)
|
||||
```
|
||||
|
||||
### Monitoring Points
|
||||
### Điểm Giám Sát
|
||||
```
|
||||
Metrics (Prometheus)
|
||||
├── HTTP request latency
|
||||
├── Database query time
|
||||
├── Cache hit/miss ratio
|
||||
├── Error rate by endpoint
|
||||
├── Queue depth (background jobs)
|
||||
└── Payment processing success rate
|
||||
Chỉ Số (Prometheus)
|
||||
├── Độ trễ HTTP request
|
||||
├── Thời gian truy vấn cơ sở dữ liệu
|
||||
├── Tỷ lệ trúng/trượt cache
|
||||
├── Tỷ lệ lỗi theo endpoint
|
||||
├── Độ sâu hàng đợi (công việc nền)
|
||||
└── Tỷ lệ thành công xử lý thanh toán
|
||||
|
||||
Logs (Loki)
|
||||
├── Searchable by timestamp, level, service, user
|
||||
├── Retention: 30 days
|
||||
└── Queries: error trends, user activity, audit trail
|
||||
Log (Loki)
|
||||
├── Có thể tìm kiếm theo timestamp, cấp độ, dịch vụ, người dùng
|
||||
├── Lưu trữ: 30 ngày
|
||||
└── Truy vấn: xu hướng lỗi, hoạt động người dùng, nhật ký kiểm toán
|
||||
|
||||
Traces (Sentry)
|
||||
├── Request waterfall
|
||||
├── Database call chains
|
||||
└── Error context snapshot
|
||||
Trace (Sentry)
|
||||
├── Luồng waterfall request
|
||||
├── Chuỗi gọi cơ sở dữ liệu
|
||||
└── Snapshot ngữ cảnh lỗi
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## BACKGROUND JOBS & EVENTS
|
||||
## CÔNG VIỆC NỀN & SỰ KIỆN
|
||||
|
||||
### Event System
|
||||
### Hệ Thống Sự Kiện
|
||||
```
|
||||
Domain Event
|
||||
├── ListingCreatedEvent
|
||||
@@ -340,27 +340,27 @@ Domain Event
|
||||
↓
|
||||
EventEmitter.emit()
|
||||
↓
|
||||
Event Subscribers (consume in order)
|
||||
Event Subscribers (xử lý theo thứ tự)
|
||||
├── ListingCreatedEventSubscriber
|
||||
│ └→ Index in Typesense
|
||||
│ └→ Lập chỉ mục trong Typesense
|
||||
├── PaymentProcessedEventSubscriber
|
||||
│ └→ Send email receipt
|
||||
│ └→ Gửi email biên lai
|
||||
├── NotificationScheduledEventSubscriber
|
||||
│ └→ Queue FCM push
|
||||
│ └→ Xếp hàng FCM push
|
||||
└── UserDeletedEventSubscriber
|
||||
└→ Archive data + audit trail
|
||||
└→ Lưu trữ dữ liệu + nhật ký kiểm toán
|
||||
|
||||
Error Handling:
|
||||
├── Retry policy (3 retries, exponential backoff)
|
||||
├── Dead letter queue (failed events)
|
||||
└── Monitoring alert (critical events failed)
|
||||
Xử Lý Lỗi:
|
||||
├── Chính sách thử lại (3 lần, exponential backoff)
|
||||
├── Dead letter queue (sự kiện thất bại)
|
||||
└── Cảnh báo giám sát (sự kiện quan trọng thất bại)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## FRONTEND STATE MANAGEMENT
|
||||
## QUẢN LÝ TRẠNG THÁI FRONTEND
|
||||
|
||||
### Zustand Store Pattern
|
||||
### Mẫu Zustand Store
|
||||
```
|
||||
// auth-store.ts
|
||||
const useAuthStore = create((set) => ({
|
||||
@@ -374,227 +374,226 @@ const useAuthStore = create((set) => ({
|
||||
}
|
||||
}))
|
||||
|
||||
// Component Usage
|
||||
// Cách Dùng Trong Component
|
||||
const { user, setUser } = useAuthStore()
|
||||
|
||||
// Persistence (automatic)
|
||||
├── localStorage (client-side)
|
||||
├── Hydration on page load
|
||||
└── Sync across tabs (storage event)
|
||||
// Lưu Trữ Bền Vững (tự động)
|
||||
├── localStorage (phía client)
|
||||
├── Hydration khi tải trang
|
||||
└── Đồng bộ giữa các tab (storage event)
|
||||
```
|
||||
|
||||
### React Query Integration
|
||||
### Tích Hợp React Query
|
||||
```
|
||||
// Hook Pattern
|
||||
// Mẫu Hook
|
||||
const useListings = (filters) => {
|
||||
return useQuery({
|
||||
queryKey: ['listings', filters],
|
||||
queryFn: () => listingsApi.search(filters),
|
||||
staleTime: 5 * 60 * 1000, // 5 min
|
||||
gcTime: 10 * 60 * 1000, // 10 min (old: cacheTime)
|
||||
staleTime: 5 * 60 * 1000, // 5 phút
|
||||
gcTime: 10 * 60 * 1000, // 10 phút (cũ: cacheTime)
|
||||
retry: 3,
|
||||
retryDelay: exponentialBackoff,
|
||||
})
|
||||
}
|
||||
|
||||
// Features
|
||||
├── Automatic caching by queryKey
|
||||
├── Background refetching
|
||||
├── Optimistic updates
|
||||
├── Pagination support
|
||||
└── Dependency tracking
|
||||
// Tính Năng
|
||||
├── Cache tự động theo queryKey
|
||||
├── Tải lại nền
|
||||
├── Cập nhật lạc quan
|
||||
├── Hỗ trợ phân trang
|
||||
└── Theo dõi phụ thuộc
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## DEPLOYMENT ARCHITECTURE
|
||||
## KIẾN TRÚC TRIỂN KHAI
|
||||
|
||||
### Local Development
|
||||
### Phát Triển Cục Bộ
|
||||
```
|
||||
docker-compose.yml
|
||||
├── PostgreSQL (5432)
|
||||
├── Redis (6379)
|
||||
├── Typesense (8108)
|
||||
├── MinIO (9000)
|
||||
└── PgBouncer (6432 - optional)
|
||||
└── PgBouncer (6432 - tùy chọn)
|
||||
|
||||
API Server: http://localhost:3001/api/v1
|
||||
Web Server: http://localhost:3000
|
||||
Swagger Docs: http://localhost:3001/api/v1/docs
|
||||
```
|
||||
|
||||
### Production Deployment
|
||||
### Triển Khai Sản Xuất
|
||||
```
|
||||
Kubernetes Cluster
|
||||
├── API Pod (NestJS)
|
||||
│ ├── Port: 3001
|
||||
│ ├── Resources: 2 CPU, 2GB RAM
|
||||
│ ├── Replicas: 3+ (autoscaling)
|
||||
│ ├── Tài nguyên: 2 CPU, 2GB RAM
|
||||
│ ├── Replicas: 3+ (tự động mở rộng)
|
||||
│ ├── Probes: liveness + readiness
|
||||
│ └── Limits: enforce resource quotas
|
||||
│ └── Limits: thực thi hạn mức tài nguyên
|
||||
├── Web Pod (Next.js)
|
||||
│ ├── Port: 3000
|
||||
│ ├── Replicas: 2+
|
||||
│ └── CDN: CloudFront/Cloudflare
|
||||
├── PostgreSQL (managed RDS or Kubernetes StatefulSet)
|
||||
├── Redis (managed ElastiCache or Kubernetes)
|
||||
└── Typesense (managed or self-hosted cluster)
|
||||
├── PostgreSQL (RDS được quản lý hoặc Kubernetes StatefulSet)
|
||||
├── Redis (ElastiCache được quản lý hoặc Kubernetes)
|
||||
└── Typesense (được quản lý hoặc cluster tự lưu trữ)
|
||||
|
||||
Ingress → Load Balancer → Service → Pods
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CI/CD PIPELINE
|
||||
## PIPELINE CI/CD
|
||||
|
||||
### Automated Stages
|
||||
### Các Giai Đoạn Tự Động
|
||||
```
|
||||
1. Code Push to master/PR
|
||||
└→ GitHub Actions triggered
|
||||
1. Đẩy Code lên master/PR
|
||||
└→ Kích hoạt GitHub Actions
|
||||
|
||||
2. Lint Stage (2 min)
|
||||
├── ESLint check
|
||||
└── Prettier validation
|
||||
2. Giai Đoạn Lint (2 phút)
|
||||
├── Kiểm tra ESLint
|
||||
└── Xác thực Prettier
|
||||
|
||||
3. Type Check Stage (3 min)
|
||||
└── TypeScript compilation (no emit)
|
||||
3. Giai Đoạn Kiểm Tra Kiểu (3 phút)
|
||||
└── Biên dịch TypeScript (không emit)
|
||||
|
||||
4. Unit Test Stage (5 min)
|
||||
4. Giai Đoạn Kiểm Thử Đơn Vị (5 phút)
|
||||
├── Backend: Vitest (pnpm test)
|
||||
└── Frontend: Vitest + RTL
|
||||
|
||||
5. Integration Test Stage (8 min)
|
||||
├── Test database setup
|
||||
└── Vitest integration config
|
||||
5. Giai Đoạn Kiểm Thử Tích Hợp (8 phút)
|
||||
├── Thiết lập cơ sở dữ liệu kiểm thử
|
||||
└── Cấu hình tích hợp Vitest
|
||||
|
||||
6. Build Stage (10 min)
|
||||
├── NestJS build (tsc + webpack)
|
||||
├── Next.js build (.next folder)
|
||||
└── Artifact storage
|
||||
6. Giai Đoạn Build (10 phút)
|
||||
├── Build NestJS (tsc + webpack)
|
||||
├── Build Next.js (thư mục .next)
|
||||
└── Lưu trữ artifact
|
||||
|
||||
7. E2E Test Stage (15 min) - if CI passes
|
||||
├── Service startup (Postgres, Redis, Typesense)
|
||||
├── Database migration
|
||||
├── Seed data
|
||||
├── Playwright tests (Chromium)
|
||||
└── Report generation
|
||||
7. Giai Đoạn Kiểm Thử E2E (15 phút) - nếu CI vượt qua
|
||||
├── Khởi động dịch vụ (Postgres, Redis, Typesense)
|
||||
├── Migration cơ sở dữ liệu
|
||||
├── Dữ liệu seed
|
||||
├── Kiểm thử Playwright (Chromium)
|
||||
└── Tạo báo cáo
|
||||
|
||||
8. Deploy Stage (5 min) - if all pass
|
||||
├── Docker image build
|
||||
├── Registry push
|
||||
└── Kubernetes rollout
|
||||
8. Giai Đoạn Triển Khai (5 phút) - nếu tất cả vượt qua
|
||||
├── Build Docker image
|
||||
├── Đẩy lên Registry
|
||||
└── Triển khai Kubernetes
|
||||
|
||||
Total: ~50 min (sequential) or ~15 min (parallel)
|
||||
Tổng cộng: ~50 phút (tuần tự) hoặc ~15 phút (song song)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## PERFORMANCE TUNING CHECKLIST
|
||||
## DANH SÁCH KIỂM TRA TINH CHỈNH HIỆU SUẤT
|
||||
|
||||
### Database
|
||||
- [ ] Query analysis (EXPLAIN ANALYZE)
|
||||
- [ ] Missing indexes (pg_stat_statements)
|
||||
- [ ] Connection pooling tuned (PgBouncer)
|
||||
- [ ] Replication lag monitored
|
||||
- [ ] Backup tested (recovery time < 1 hour)
|
||||
### Cơ Sở Dữ Liệu
|
||||
- [ ] Phân tích truy vấn (EXPLAIN ANALYZE)
|
||||
- [ ] Thiếu chỉ mục (pg_stat_statements)
|
||||
- [ ] Tinh chỉnh connection pooling (PgBouncer)
|
||||
- [ ] Giám sát độ trễ nhân rộng
|
||||
- [ ] Kiểm tra sao lưu (thời gian phục hồi < 1 giờ)
|
||||
|
||||
### Application
|
||||
- [ ] Memory usage profiled (Node.js heap)
|
||||
- [ ] CPU throttling identified
|
||||
- [ ] Garbage collection tuned (heap snapshots)
|
||||
- [ ] Logging overhead measured
|
||||
- [ ] Dependency versions updated
|
||||
### Ứng Dụng
|
||||
- [ ] Lập hồ sơ sử dụng bộ nhớ (Node.js heap)
|
||||
- [ ] Xác định giới hạn CPU
|
||||
- [ ] Tinh chỉnh garbage collection (heap snapshots)
|
||||
- [ ] Đo lường chi phí ghi log
|
||||
- [ ] Cập nhật phiên bản phụ thuộc
|
||||
|
||||
### Frontend
|
||||
- [ ] Bundle size analyzed (webpack analyzer)
|
||||
- [ ] Code splitting implemented (routes)
|
||||
- [ ] Images optimized (Next.js Image)
|
||||
- [ ] Critical CSS inlined
|
||||
- [ ] Web vitals tracked (LCP, FID, CLS)
|
||||
- [ ] Phân tích kích thước bundle (webpack analyzer)
|
||||
- [ ] Triển khai code splitting (routes)
|
||||
- [ ] Tối ưu hóa hình ảnh (Next.js Image)
|
||||
- [ ] Nội tuyến CSS quan trọng
|
||||
- [ ] Theo dõi web vitals (LCP, FID, CLS)
|
||||
|
||||
### Infrastructure
|
||||
- [ ] Load balancer health checks tuned
|
||||
- [ ] Autoscaling policies tested
|
||||
- [ ] Cache hit rates > 80%
|
||||
- [ ] Network latency acceptable (< 100ms)
|
||||
- [ ] Monitoring alert thresholds realistic
|
||||
### Hạ Tầng
|
||||
- [ ] Tinh chỉnh kiểm tra sức khỏe load balancer
|
||||
- [ ] Kiểm tra chính sách tự động mở rộng
|
||||
- [ ] Tỷ lệ trúng cache > 80%
|
||||
- [ ] Độ trễ mạng chấp nhận được (< 100ms)
|
||||
- [ ] Ngưỡng cảnh báo giám sát thực tế
|
||||
|
||||
---
|
||||
|
||||
## TROUBLESHOOTING GUIDE
|
||||
## HƯỚNG DẪN KHẮC PHỤC SỰ CỐ
|
||||
|
||||
### "Database Connection Timeout"
|
||||
```
|
||||
Diagnosis:
|
||||
1. Check if PostgreSQL container is running: docker-compose ps
|
||||
2. Verify DATABASE_URL in .env
|
||||
3. Check PgBouncer if production: psql -h localhost -p 6432 -U pgbouncer
|
||||
4. Look for connection limit reached: SELECT count(*) FROM pg_stat_activity
|
||||
Chẩn Đoán:
|
||||
1. Kiểm tra container PostgreSQL có đang chạy: docker-compose ps
|
||||
2. Xác minh DATABASE_URL trong .env
|
||||
3. Kiểm tra PgBouncer nếu production: psql -h localhost -p 6432 -U pgbouncer
|
||||
4. Tìm kiếm giới hạn kết nối đạt: SELECT count(*) FROM pg_stat_activity
|
||||
|
||||
Fix:
|
||||
├── Restart: docker-compose restart postgres
|
||||
├── Increase PgBouncer pool: PGBOUNCER_POOL_SIZE=30
|
||||
└── Check slow queries: pg_stat_statements
|
||||
Khắc Phục:
|
||||
├── Khởi động lại: docker-compose restart postgres
|
||||
├── Tăng pool PgBouncer: PGBOUNCER_POOL_SIZE=30
|
||||
└── Kiểm tra truy vấn chậm: pg_stat_statements
|
||||
```
|
||||
|
||||
### "Redis Connection Refused"
|
||||
```
|
||||
Diagnosis:
|
||||
1. Check Redis container: docker-compose ps redis
|
||||
2. Verify REDIS_URL in .env
|
||||
3. Check port: redis-cli -p 6379 ping
|
||||
4. Check memory: redis-cli INFO memory
|
||||
Chẩn Đoán:
|
||||
1. Kiểm tra container Redis: docker-compose ps redis
|
||||
2. Xác minh REDIS_URL trong .env
|
||||
3. Kiểm tra port: redis-cli -p 6379 ping
|
||||
4. Kiểm tra bộ nhớ: redis-cli INFO memory
|
||||
|
||||
Fix:
|
||||
├── Restart: docker-compose restart redis
|
||||
├── Flush if needed: redis-cli FLUSHALL (dev only!)
|
||||
└── Monitor: redis-cli --stat
|
||||
Khắc Phục:
|
||||
├── Khởi động lại: docker-compose restart redis
|
||||
├── Xóa nếu cần: redis-cli FLUSHALL (chỉ môi trường dev!)
|
||||
└── Giám sát: redis-cli --stat
|
||||
```
|
||||
|
||||
### "Typesense Index Not Found"
|
||||
```
|
||||
Diagnosis:
|
||||
1. Check Typesense container: docker-compose ps typesense
|
||||
2. Verify TYPESENSE_API_KEY in .env
|
||||
3. List indexes: curl http://localhost:8108/collections -H "X-TYPESENSE-API-KEY: <key>"
|
||||
4. Check sync job logs
|
||||
Chẩn Đoán:
|
||||
1. Kiểm tra container Typesense: docker-compose ps typesense
|
||||
2. Xác minh TYPESENSE_API_KEY trong .env
|
||||
3. Liệt kê chỉ mục: curl http://localhost:8108/collections -H "X-TYPESENSE-API-KEY: <key>"
|
||||
4. Kiểm tra log công việc đồng bộ
|
||||
|
||||
Fix:
|
||||
├── Re-seed: pnpm db:seed
|
||||
├── Reindex: DELETE /listings index, then rebuild
|
||||
└── Monitor: Typesense dashboard http://localhost:8108/dashboard
|
||||
Khắc Phục:
|
||||
├── Seed lại: pnpm db:seed
|
||||
├── Lập chỉ mục lại: XÓA chỉ mục /listings, sau đó xây dựng lại
|
||||
└── Giám sát: Typesense dashboard http://localhost:8108/dashboard
|
||||
```
|
||||
|
||||
### "Tests Failing with 'Port Already in Use'"
|
||||
```
|
||||
Diagnosis:
|
||||
1. Check running processes: lsof -i :3001 (macOS) or netstat -ano (Windows)
|
||||
2. Docker containers: docker ps
|
||||
Chẩn Đoán:
|
||||
1. Kiểm tra tiến trình đang chạy: lsof -i :3001 (macOS) hoặc netstat -ano (Windows)
|
||||
2. Container Docker: docker ps
|
||||
|
||||
Fix:
|
||||
├── Kill process: kill -9 <PID>
|
||||
├── Stop containers: docker-compose down
|
||||
├── Update port in .env.test
|
||||
└── Ensure cleanup in global-teardown.ts
|
||||
Khắc Phục:
|
||||
├── Hủy tiến trình: kill -9 <PID>
|
||||
├── Dừng container: docker-compose down
|
||||
├── Cập nhật port trong .env.test
|
||||
└── Đảm bảo dọn dẹp trong global-teardown.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## SECURITY CHECKLIST - PRE-DEPLOYMENT
|
||||
|
||||
- [ ] JWT secrets rotated and unique
|
||||
- [ ] CORS_ORIGINS finalized (no localhost in prod)
|
||||
- [ ] Database credentials strong (> 16 chars, random)
|
||||
- [ ] MinIO/AWS S3 credentials secure (IAM policy restricted)
|
||||
- [ ] OAuth client secrets masked
|
||||
- [ ] SSL certificate installed (HTTPS)
|
||||
- [ ] HSTS preload submitted
|
||||
- [ ] Security headers tested (securityheaders.com)
|
||||
- [ ] OWASP Top 10 reviewed
|
||||
- [ ] Penetration test scheduled
|
||||
- [ ] Rate limits tuned (no bypass possible)
|
||||
- [ ] Audit logging verified
|
||||
- [ ] Backup encryption enabled
|
||||
- [ ] Incident response plan documented
|
||||
- [ ] On-call rotation configured
|
||||
## DANH SÁCH KIỂM TRA BẢO MẬT - TRƯỚC KHI TRIỂN KHAI
|
||||
|
||||
- [ ] Bí mật JWT đã được xoay vòng và duy nhất
|
||||
- [ ] CORS_ORIGINS đã được hoàn thiện (không có localhost trong production)
|
||||
- [ ] Thông tin đăng nhập cơ sở dữ liệu mạnh (> 16 ký tự, ngẫu nhiên)
|
||||
- [ ] Thông tin đăng nhập MinIO/AWS S3 an toàn (chính sách IAM bị hạn chế)
|
||||
- [ ] Bí mật OAuth client đã được che giấu
|
||||
- [ ] Chứng chỉ SSL đã được cài đặt (HTTPS)
|
||||
- [ ] HSTS preload đã được gửi
|
||||
- [ ] Headers bảo mật đã được kiểm tra (securityheaders.com)
|
||||
- [ ] OWASP Top 10 đã được xem xét
|
||||
- [ ] Kiểm tra thâm nhập đã được lên lịch
|
||||
- [ ] Giới hạn tốc độ đã được tinh chỉnh (không thể bỏ qua)
|
||||
- [ ] Ghi log kiểm toán đã được xác minh
|
||||
- [ ] Mã hóa sao lưu đã được bật
|
||||
- [ ] Kế hoạch ứng phó sự cố đã được lập tài liệu
|
||||
- [ ] Lịch trực đã được cấu hình
|
||||
|
||||
Reference in New Issue
Block a user