Files
goodgo-platform/docs/audits/AUDIT_TECHNICAL_REFERENCE.md
Ho Ngoc Hai 11f2bf26e6
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
chore: update project documentation, audit reports, and initialize IDE configuration files
2026-04-19 03:12:54 +07:00

18 KiB

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