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
600 lines
18 KiB
Markdown
600 lines
18 KiB
Markdown
# 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
|