# 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 ├→ 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: " 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 ├── 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