Files
goodgo-platform/docs/audits/CQRS_HANDLER_AUDIT_REPORT.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

17 KiB

🔍 KIỂM TOÁN TOÀN DIỆN XỬ LÝ LỖI CQRS HANDLER

GoodGo Platform NestJS API

Ngày kiểm toán: Ngày 11 tháng 4 năm 2026
Tổng số Handler đã phân tích: 77
Có xử lý lỗi: 11 (14,3%)
Cần bổ sung xử lý lỗi: 66 (85,7%)


📊 TÓM TẮT ĐIỀU HÀNH

Kiểm toán này xác định các lỗ hổng nghiêm trọng trong xử lý lỗi trên toàn bộ tầng CQRS handler. Trong số 77 handler được phân tích:

  • 11 handler đã triển khai xử lý lỗi try-catch
  • 66 handler thiếu xử lý lỗi đúng cách
  • 🔴 NGHIÊM TRỌNG: Các module trọng tâm (admin, inquiries, leads, reviews) có lỗ hổng nghiêm trọng

Mẫu xử lý lỗi được tìm thấy

Mẫu được khuyến nghị xác định trong các handler hiện có:

async execute(command: XCommand): Promise<XResult> {
  try {
    // business logic
  } catch (error) {
    if (error instanceof DomainException) throw error;
    this.logger.error(
      `Failed: ${error.message}`,
      error instanceof Error ? error.stack : undefined,
      this.constructor.name
    );
    throw new InternalServerErrorException();
  }
}

📈 PHÂN TÍCH THEO MODULE

🔴 MODULE ADMIN (15 handler)

Trạng thái: NGHIÊM TRỌNG - Chỉ 1/15 handler có xử lý lỗi (6,7%)

Command CẦN XỬ LÝ LỖI (7/8):

  • adjust-subscription
  • approve-kyc
  • approve-listing
  • ban-user
  • reject-kyc
  • reject-listing
  • update-user-status

✓ Command ĐÃ có xử lý lỗi (1/8):

  • bulk-moderate-listings

Query CẦN XỬ LÝ LỖI (7/7):

  • get-audit-logs
  • get-dashboard-stats
  • get-kyc-queue
  • get-moderation-queue
  • get-revenue-stats
  • get-user-detail
  • get-users

🔴 MODULE AGENTS (3 handler)

Trạng thái: NGHIÊM TRỌNG - 0/3 handler có xử lý lỗi (0%)

Command CẦN XỬ LÝ LỖI (1/1):

  • recalculate-quality-score

Query CẦN XỬ LÝ LỖI (2/2):

  • get-agent-dashboard
  • get-agent-public-profile

🔴 MODULE ANALYTICS (8 handler)

Trạng thái: NGHIÊM TRỌNG - 0/8 handler có xử lý lỗi (0%)

Command CẦN XỬ LÝ LỖI (3/3):

  • generate-report
  • track-event
  • update-market-index

Query CẦN XỬ LÝ LỖI (5/5):

  • get-district-stats
  • get-heatmap
  • get-market-report
  • get-price-trend
  • get-valuation

🟡 MODULE AUTH (11 handler)

Trạng thái: TRUNG BÌNH - 5/11 handler có xử lý lỗi (45,5%)

✓ Command ĐÃ có xử lý lỗi (5/9):

  • export-user-data
  • force-delete-user
  • login-user ✓ (Được triển khai tốt)
  • process-scheduled-deletions
  • refresh-token

Command CẦN XỬ LÝ LỖI (4/9):

  • cancel-user-deletion
  • register-user
  • request-user-deletion
  • verify-kyc

Query CẦN XỬ LÝ LỖI (2/2):

  • get-agent-by-user-id
  • get-profile

🔴 MODULE INQUIRIES (4 handler)

Trạng thái: NGHIÊM TRỌNG - 0/4 handler có xử lý lỗi (0%)

Command CẦN XỬ LÝ LỖI (2/2):

  • create-inquiry
  • mark-inquiry-read

Query CẦN XỬ LÝ LỖI (2/2):

  • get-inquiries-by-agent
  • get-inquiries-by-listing

🔴 MODULE LEADS (5 handler)

Trạng thái: NGHIÊM TRỌNG - 0/5 handler có xử lý lỗi (0%)

Command CẦN XỬ LÝ LỖI (3/3):

  • create-lead
  • delete-lead
  • update-lead-status

Query CẦN XỬ LÝ LỖI (2/2):

  • get-lead-stats
  • get-leads-by-agent

🟡 MODULE LISTINGS (7 handler)

Trạng thái: TRUNG BÌNH - 2/7 handler có xử lý lỗi (28,6%)

✓ Command ĐÃ có xử lý lỗi (2/4):

  • create-listing ✓ (Được triển khai tốt với khả năng giảm cấp nhẹ nhàng)
  • upload-media

Command CẦN XỬ LÝ LỖI (2/4):

  • moderate-listing
  • update-listing-status

Query CẦN XỬ LÝ LỖI (3/3):

  • get-listing
  • get-pending-moderation
  • search-listings

🟢 MODULE NOTIFICATIONS (1 handler)

Trạng thái: TỐT - 1/1 handler có xử lý lỗi (100%)

✓ Command ĐÃ có xử lý lỗi (1/1):

  • send-notification

🟡 MODULE PAYMENTS (5 handler)

Trạng thái: TRUNG BÌNH - 1/5 handler có xử lý lỗi (20%)

✓ Command ĐÃ có xử lý lỗi (1/3):

  • create-payment

Command CẦN XỬ LÝ LỖI (2/3):

  • handle-callback
  • refund-payment

Query CẦN XỬ LÝ LỖI (2/2):

  • get-payment-status
  • list-transactions

🔴 MODULE REVIEWS (5 handler)

Trạng thái: NGHIÊM TRỌNG - 0/5 handler có xử lý lỗi (0%)

Command CẦN XỬ LÝ LỖI (2/2):

  • create-review
  • delete-review

Query CẦN XỬ LÝ LỖI (3/3):

  • get-average-rating
  • get-reviews-by-target
  • get-reviews-by-user

🟡 MODULE SEARCH (9 handler)

Trạng thái: TRUNG BÌNH - 1/9 handler có xử lý lỗi (11,1%)

✓ Command ĐÃ có xử lý lỗi (1/5):

  • create-saved-search

Command CẦN XỬ LÝ LỖI (4/5):

  • delete-saved-search
  • reindex-all
  • sync-listing
  • update-saved-search

Query CẦN XỬ LÝ LỖI (4/4):

  • geo-search
  • get-saved-search
  • get-saved-searches
  • search-properties

🔴 MODULE SUBSCRIPTIONS (7 handler)

Trạng thái: NGHIÊM TRỌNG - 0/7 handler có xử lý lỗi (0%)

Command CẦN XỬ LÝ LỖI (4/4):

  • cancel-subscription
  • create-subscription
  • meter-usage
  • upgrade-subscription

Query CẦN XỬ LÝ LỖI (3/3):

  • check-quota
  • get-billing-history
  • get-plan

🎯 CÁC HẠNG MỤC HÀNH ĐỘNG ƯU TIÊN

BẬC 1 - NGHIÊM TRỌNG (Các module trọng tâm + thao tác rủi ro cao)

Các module này ảnh hưởng trực tiếp đến trải nghiệm người dùng và tính toàn vẹn dữ liệu:

ADMIN (7 command, 7 query)

  • Tất cả handler duyệt/từ chối đều có thể gây mất nhất quán dữ liệu
  • Nhật ký kiểm toán là yếu tố then chốt cho tuân thủ
  • Cập nhật trạng thái người dùng phải được theo dõi lỗi

LEADS (3 command, 2 query)

  • Tạo/xóa lead là các thao tác nghiệp vụ cốt lõi
  • Cập nhật trạng thái ảnh hưởng đến quy trình bán hàng
  • Truy xuất lead của môi giới phải đáng tin cậy

INQUIRIES (2 command, 2 query)

  • create-inquiry là thao tác phía người dùng có tần suất cao
  • Thiếu xử lý lỗi có thể làm mất yêu cầu tư vấn
  • Lỗi query phá vỡ bảng điều khiển của môi giới

REVIEWS (2 command, 3 query)

  • Tạo/xóa đánh giá ảnh hưởng đến uy tín môi giới
  • Các query xếp hạng được sử dụng trong thứ hạng tìm kiếm
  • Lỗi không được xử lý có thể làm hỏng dữ liệu đánh giá

SUBSCRIPTIONS (4 command, 3 query)

  • Các thao tác liên quan đến thanh toán là nghiệp vụ cốt lõi
  • Kiểm tra hạn mức không được thất bại âm thầm
  • Lịch sử thanh toán phải truy vấn được một cách đáng tin cậy

BẬC 2 - CAO (Tác động đến doanh thu và tìm kiếm)

PAYMENTS (2 command, 2 query)

  • Callback thanh toán phải có xử lý lỗi
  • Hoàn tiền phải ghi lại lỗi để đối soát

SEARCH (4 command, 4 query)

  • Lỗi tìm kiếm làm giảm trải nghiệm người dùng
  • Các thao tác lập chỉ mục cần logic thử lại

BẬC 3 - TRUNG BÌNH (Vận hành)

LISTINGS (2 command, 3 query)

  • Các thao tác kiểm duyệt cần theo dõi lỗi
  • Các query listing nên có phương án dự phòng nhẹ nhàng

ANALYTICS (3 command, 5 query)

  • Tạo báo cáo nên ghi lại lỗi
  • Các query dữ liệu thị trường nên có phương án dự phòng

AGENTS (1 command, 2 query)

  • Tính toán điểm chất lượng cần xử lý lỗi
  • Query hồ sơ công khai không bao giờ được gây sự cố

🔧 HƯỚNG DẪN TRIỂN KHAI

Mẫu xử lý lỗi chuẩn cho Command

import { Logger } from '@nestjs/common';
import { CommandHandler, type ICommandHandler } from '@nestjs/cqrs';
import { DomainException, InternalServerErrorException } from '@modules/shared';

@CommandHandler(YourCommand)
export class YourHandler implements ICommandHandler<YourCommand> {
  private readonly logger = new Logger(this.constructor.name);

  async execute(command: YourCommand): Promise<YourResult> {
    try {
      // Bước 1: Xác thực đầu vào
      // Bước 2: Tải aggregate từ repo
      // Bước 3: Thực thi logic domain
      // Bước 4: Lưu trạng thái
      // Bước 5: Phát sự kiện
      // Bước 6: Trả về kết quả

      return result;
    } catch (error) {
      // Ném lại domain exception - đây là các lỗi mong đợi
      if (error instanceof DomainException) throw error;
      
      // Ghi lại lỗi không mong đợi với đầy đủ ngữ cảnh
      this.logger.error(
        `Command execution failed: ${error instanceof Error ? error.message : String(error)}`,
        error instanceof Error ? error.stack : undefined,
        this.constructor.name
      );
      
      // Ném một HTTP exception chung
      throw new InternalServerErrorException('Operation failed, please try again');
    }
  }
}

Mẫu xử lý lỗi chuẩn cho Query

@QueryHandler(YourQuery)
export class YourQueryHandler implements IQueryHandler<YourQuery> {
  private readonly logger = new Logger(this.constructor.name);

  async execute(query: YourQuery): Promise<YourResult> {
    try {
      // Logic query ở đây
      return result;
    } catch (error) {
      this.logger.error(
        `Query execution failed: ${error instanceof Error ? error.message : String(error)}`,
        error instanceof Error ? error.stack : undefined,
        this.constructor.name
      );
      
      throw new InternalServerErrorException('Unable to fetch data, please try again');
    }
  }
}

Những điều KHÔNG nên làm:

Im lặng nuốt lỗi
Trả về null/undefined mà không ghi log
Dùng các lần ném "Error" chung chung không có ngữ cảnh
Ghi log ra console thay vì dịch vụ logger

Những điều NÊN làm:

✓ Luôn ghi log lỗi với thông điệp + stack trace
✓ Ném lại domain exception nguyên vẹn
✓ Chuyển đổi lỗi khác thành HTTP exception phù hợp
✓ Sử dụng structured logging với ngữ cảnh (tên handler)
✓ Đảm bảo giao dịch cơ sở dữ liệu rollback khi có lỗi


📋 DANH SÁCH HANDLER CHI TIẾT

ĐÃ CÓ XỬ LÝ LỖI ✓ (11 handler)

  1. admin/commands/bulk-moderate-listings

    • Mẫu: Try-catch với thu thập lỗi chi tiết
    • Tính năng: Xử lý từng mục độc lập, thu thập lỗi
  2. auth/commands/export-user-data

    • Mẫu: Try-catch chuẩn với ghi log
  3. auth/commands/force-delete-user

    • Mẫu: Try-catch chuẩn với ghi log
  4. auth/commands/login-user

    • Mẫu: Try-catch với xử lý lỗi dịch vụ token
    • Được triển khai tốt: Thông điệp lỗi phù hợp cho người dùng
  5. auth/commands/process-scheduled-deletions

    • Mẫu: Try-catch chuẩn với ghi log
  6. auth/commands/refresh-token

    • Mẫu: Try-catch chuẩn với ghi log
  7. listings/commands/create-listing

    • Mẫu: Xử lý lỗi nâng cao với khả năng giảm cấp nhẹ nhàng
    • Tính năng: Phát hiện trùng lặp và xác thực giá được bao bọc trong try-catch
    • Thực hành tốt nhất: Tiếp tục hoạt động nếu dịch vụ phụ thất bại
  8. listings/commands/upload-media

    • Mẫu: Try-catch chuẩn với ghi log
  9. notifications/commands/send-notification

    • Mẫu: Try-catch chuẩn với ghi log
  10. payments/commands/create-payment

    • Mẫu: Try-catch chuẩn với ghi log
  11. search/commands/create-saved-search

    • Mẫu: Try-catch chuẩn với ghi log

CẦN XỬ LÝ LỖI ✗ (66 handler)

[Được tổ chức theo module chi tiết ở trên]


🚀 CHIẾN LƯỢC KHẮC PHỤC

Giai đoạn 1: Khẩn cấp (Tuần 1)

  1. Thêm xử lý lỗi cho tất cả handler command/query của admin
  2. Thêm xử lý lỗi cho tất cả handler command/query của leads
  3. Thêm xử lý lỗi cho tất cả handler command/query của inquiries
  4. Thêm xử lý lỗi cho tất cả handler command/query của reviews
  5. Thêm xử lý lỗi cho tất cả handler command/query của subscriptions

Công sức: ~30-40 handler, ~1-2 ngày làm việc của nhà phát triển

Giai đoạn 2: Ưu tiên cao (Tuần 2)

  1. Thêm xử lý lỗi cho các handler payments còn lại
  2. Thêm xử lý lỗi cho các handler search còn lại
  3. Thêm xử lý lỗi cho các handler kiểm duyệt của listings
  4. Thêm xử lý lỗi cho các handler của agents

Công sức: ~18 handler, ~1 ngày làm việc của nhà phát triển

Giai đoạn 3: Hoàn thiện (Tuần 3)

  1. Thêm xử lý lỗi cho các handler của analytics
  2. Xem xét và kiểm toán tất cả triển khai để đảm bảo nhất quán
  3. Thêm kiểm thử tích hợp xác nhận các tình huống lỗi

Công sức: ~8 handler + kiểm thử, ~1 ngày làm việc của nhà phát triển


📐 DANH SÁCH KIỂM TRA CODE REVIEW

Đối với mỗi handler, xác minh:

  • Phương thức Execute có khối try-catch
  • Các instance DomainException được ném lại
  • Lỗi được ghi log với thông điệp VÀ stack trace
  • Ngữ cảnh Logger bao gồm tên lớp handler
  • HTTP exception phù hợp được ném ra
  • Không có khối catch rỗng
  • Không có ẩn lỗi âm thầm
  • Giao dịch cơ sở dữ liệu được xử lý
  • Sự kiện chỉ được phát khi thành công

🎓 THỰC HÀNH TỐT NHẤT ĐƯỢC GHI NHẬN

Từ các handler có xử lý lỗi tốt:

  1. Login User Handler - Thông điệp lỗi xuất sắc phía người dùng

    throw new UnauthorizedException(
      'Không thể tạo phiên đăng nhập, vui lòng thử lại'
    );
    
  2. Create Listing Handler - Giảm cấp nhẹ nhàng cho các dịch vụ không quan trọng

    try {
      // duplicate detection
    } catch {
      this.logger.warn('Duplicate detection failed');
      // Continue without warnings
    }
    
  3. Bulk Moderate Handler - Thu thập lỗi theo từng mục

    for (const listingId of ids) {
      try {
        // process
      } catch (error) {
        failed.push({ listingId, reason });
      }
    }
    

⚠️ RỦI RO KHI THIẾU XỬ LÝ LỖI

  1. Tính nhất quán dữ liệu: Lỗi cơ sở dữ liệu không được xử lý để lại bản ghi không đầy đủ
  2. Lỗi âm thầm: Các thao tác có vẻ thành công nhưng thực ra thất bại
  3. Khó gỡ lỗi: Không có log đồng nghĩa không có khả năng quan sát
  4. Trải nghiệm người dùng: Lỗi timeout thay vì thông điệp lỗi rõ ràng
  5. Tuân thủ: Khoảng trống trong nhật ký kiểm toán ở các thao tác quan trọng
  6. Sự cố trên môi trường production: Các rejection không được xử lý gây sự cố tiến trình worker

📞 CÁC CÂU HỎI ĐƯỢC TRẢ LỜI BỞI KIỂM TOÁN NÀY

H: Các module nào cần sửa trước tiên?
Đ: admin, leads, inquiries, reviews, subscriptions

H: Mẫu xử lý lỗi có nhất quán không?
Đ: Không - chỉ có 11/77 handler triển khai nó. Mẫu cần được chuẩn hóa.

H: Phạm vi khắc phục là bao nhiêu?
Đ: ~66 handler cần xử lý lỗi (~1-2 giờ mỗi handler trung bình)

H: Có handler nào KHÔNG cần xử lý lỗi không?
Đ: Không - tất cả handler gọi I/O bất đồng bộ đều cần xử lý lỗi.


📝 METADATA KIỂM TOÁN

  • Tổng số Handler: 77
  • Tổng số dòng đã phân tích: ~15.000+
  • Số file đã xem xét: 77
  • Độ sâu kiểm toán: Xem xét đầy đủ nội dung của từng handler
  • Phát hiện xử lý lỗi: Khớp mẫu thủ công
  • Số mẫu được tìm thấy: ~8 cách tiếp cận xử lý lỗi khác nhau
  • Điểm nhất quán: Thấp (14,3% tuân thủ)
  • Hành động được khuyến nghị: Triển khai ưu tiên cao trên tất cả các module