# 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ư**

---

## PHÂN CẤP MODULE BACKEND

### Phụ Thuộc Module Cốt Lõi
```
SharedModule (cấp thấp nhất)
    ├── Infrastructure Services
    ├── Middleware & Guards
    ├── Decorators & Utilities
    └── Domain Enums & Types
        ↓
    ├→ AuthModule
    ├→ HealthModule
    └→ All Feature Modules
        ├→ AdminModule (audit, user management)
        ├→ AgentsModule (agent profiles, specialized deals)
        ├→ AnalyticsModule (market reports, valuation history)
        ├→ InquiriesModule (property inquiries)
        ├→ LeadsModule (agent leads management)
        ├→ ListingsModule (property listings)
        ├→ NotificationsModule (FCM push, email)
        ├→ PaymentsModule (VNPay integration)
        ├→ ReviewsModule (property reviews)
        ├→ SearchModule (Typesense full-text search)
        ├→ SubscriptionsModule (billing, usage metering)
        └→ MetricsModule (Prometheus metrics)
```

---

## MÔ HÌNH MIỀN - MỐI QUAN HỆ

### Phân Cấp Vai Trò Người Dùng
```
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
```

### Luồng Xử Lý Tin Đăng
```
User (SELLER)
    ↓ tạo
Property + PropertyMedia
    ↓ 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)
```

### Luồng Thanh Toán
```
User (Bắt đầu Đăng ký)
    ↓
Plan (giá hàng tháng/hàng năm)
    ↓
Subscription (đang hoạt động/đã hủy/đã hết hạn)
    ↓
Payment (xử lý qua VNPay)
    ├── Idempotency Key (ngăn trùng lặp)
    └── Status Tracking
            ↓
        UsageRecord (theo dõi tài nguyên đã dùng)
```

---

## LUỒNG XÁC THỰC

### Vòng Đời Token JWT
```
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. 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. Trả về Client
   └→ Đặt Cookie HTTP-Only Bảo mật (refresh token)
   
4. Truy cập API
   ├→ Authorization: Bearer <accessToken>
   ├→ Guard xác thực chữ ký JWT
   └→ Đưa ngữ cảnh người dùng vào request
   
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
```

---

## SCHEMA CƠ SỞ DỮ LIỆU - CHỈ MỤC QUAN TRỌNG

### Chiến Lược Tối Ưu Hóa Truy Vấn
```
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)

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)

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)

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)
```

---

## CÁC LỚP BẢO MẬT - CHI TIẾT

### Lớp 1: Cấp Mạng
```
HTTP Request
    ↓
Helmet (Express middleware)
├── Content-Security-Policy
│   └── Chặn script nội tuyến, hạn chế nguồn gốc
├── X-Frame-Options: DENY
│   └── Ngăn chặn clickjacking
├── Strict-Transport-Security (HSTS)
│   └── Bắt buộc HTTPS trong 31536000 giây
├── X-Content-Type-Options: nosniff
│   └── Ngăn chặn MIME-sniffing
└── Referrer-Policy: strict-origin-when-cross-origin
    └── Kiểm soát rò rỉ referrer
```

### Lớp 2: Cấp Ứng Dụng
```
Xử Lý Request
    ↓
1. Xác Thực CORS
   └── Kiểm tra danh sách trắng (process.env.CORS_ORIGINS)
   
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. 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. 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)
```

### Lớp 3: Cấp Dữ Liệu
```
Mã Hóa Trường (Bảo Vệ PII)
├── FieldEncryptionService
│   ├── 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

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ủ
```

### Lớp 4: Phân Quyền
```
Route Handler
    ↓
@UseGuards(JwtGuard, RoleGuard)
    ├── 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
```

---

## TRIỂN KHAI MẪU CQRS

### Mẫu Lệnh (Thay Đổi Trạng Thái)
```
CreateListingCommand
├── Input: CreateListingDTO
├── Handler: CreateListingCommandHandler
│   ├── 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

Luồng:
Controller → Command → CommandHandler → Domain → Event → Repository → Cache invalidate
```

### Mẫu Truy Vấn (Chỉ Đọc)
```
GetListingQuery
├── Input: ListingId
├── Handler: GetListingQueryHandler
│   ├── 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

Luồng:
Controller → Query → QueryHandler → Repository → Cache store → Response
```

---

## CHIẾN LƯỢC CACHE

### Cache Nhiều Cấp
```
Cấp 1: Cache Trình Duyệt
├── Tài nguyên tĩnh (CSS, JS)
├── Max-Age: 31536000 (1 năm)
└── Immutable: true

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

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ổ)

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
```

---

## XỬ LÝ LỖI & QUAN SÁT HỆ THỐNG

### Phân Cấp Ngoại Lệ
```
GlobalExceptionFilter (bắt tất cả)
│
├→ HttpException (lỗi đã biết)
│  ├── BadRequestException (400)
│  ├── UnauthorizedException (401)
│  ├── ForbiddenException (403)
│  ├── NotFoundException (404)
│  ├── ConflictException (409)
│  └── InternalServerErrorException (500)
│
└→ Lỗi Không Xác Định
   └→ Sentry.captureException(error)
      ├── 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)

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)
```

### Điểm Giám Sát
```
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

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

Trace (Sentry)
├── Luồng waterfall request
├── Chuỗi gọi cơ sở dữ liệu
└── Snapshot ngữ cảnh lỗi
```

---

## CÔNG VIỆC NỀN & SỰ KIỆN

### Hệ Thống Sự Kiện
```
Domain Event
├── ListingCreatedEvent
├── PaymentProcessedEvent
├── NotificationScheduledEvent
└── UserDeletedEvent
    ↓
EventEmitter.emit()
    ↓
Event Subscribers (xử lý theo thứ tự)
├── ListingCreatedEventSubscriber
│   └→ Lập chỉ mục trong Typesense
├── PaymentProcessedEventSubscriber
│   └→ Gửi email biên lai
├── NotificationScheduledEventSubscriber
│   └→ Xếp hàng FCM push
└── UserDeletedEventSubscriber
    └→ Lưu trữ dữ liệu + nhật ký kiểm toán

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)
```

---

## QUẢN LÝ TRẠNG THÁI FRONTEND

### Mẫu Zustand Store
```
// auth-store.ts
const useAuthStore = create((set) => ({
  user: null,
  tokens: { accessToken: null, refreshToken: null },
  
  actions: {
    setUser: (user) => set({ user }),
    setTokens: (tokens) => set({ tokens }),
    logout: () => set({ user: null, tokens: null }),
  }
}))

// Cách Dùng Trong Component
const { user, setUser } = useAuthStore()

// 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)
```

### Tích Hợp React Query
```
// Mẫu Hook
const useListings = (filters) => {
  return useQuery({
    queryKey: ['listings', filters],
    queryFn: () => listingsApi.search(filters),
    staleTime: 5 * 60 * 1000, // 5 phút
    gcTime: 10 * 60 * 1000, // 10 phút (cũ: cacheTime)
    retry: 3,
    retryDelay: exponentialBackoff,
  })
}

// 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
```

---

## KIẾN TRÚC TRIỂN KHAI

### Phát Triển Cục Bộ
```
docker-compose.yml
├── PostgreSQL (5432)
├── Redis (6379)
├── Typesense (8108)
├── MinIO (9000)
└── 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
```

### Triển Khai Sản Xuất
```
Kubernetes Cluster
├── API Pod (NestJS)
│   ├── Port: 3001
│   ├── Tài nguyên: 2 CPU, 2GB RAM
│   ├── Replicas: 3+ (tự động mở rộng)
│   ├── Probes: liveness + readiness
│   └── Limits: thực thi hạn mức tài nguyên
├── Web Pod (Next.js)
│   ├── Port: 3000
│   ├── Replicas: 2+
│   └── CDN: CloudFront/Cloudflare
├── 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
```

---

## PIPELINE CI/CD

### Các Giai Đoạn Tự Động
```
1. Đẩy Code lên master/PR
   └→ Kích hoạt GitHub Actions
   
2. Giai Đoạn Lint (2 phút)
   ├── Kiểm tra ESLint
   └── Xác thực Prettier
   
3. Giai Đoạn Kiểm Tra Kiểu (3 phút)
   └── Biên dịch TypeScript (không emit)
   
4. Giai Đoạn Kiểm Thử Đơn Vị (5 phút)
   ├── Backend: Vitest (pnpm test)
   └── Frontend: Vitest + RTL
   
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. Giai Đoạn Build (10 phút)
   ├── Build NestJS (tsc + webpack)
   ├── Build Next.js (thư mục .next)
   └── Lưu trữ artifact
   
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. 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
   
Tổng cộng: ~50 phút (tuần tự) hoặc ~15 phút (song song)
```

---

## DANH SÁCH KIỂM TRA TINH CHỈNH HIỆU SUẤT

### 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ờ)

### Ứ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
- [ ] 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)

### 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ế

---

## HƯỚNG DẪN KHẮC PHỤC SỰ CỐ

### "Database Connection Timeout"
```
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

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"
```
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

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"
```
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ộ

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'"
```
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

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
```

---

## 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
