Files
goodgo-platform/docs/audits/AUDIT_TECHNICAL_REFERENCE.md
Ho Ngoc Hai b93c28fa01 chore: organize docs — move 37 files from root into docs/ subfolders
Root now contains only essential files:
  README.md, CLAUDE.md, CHANGELOG.md, CONTRIBUTING.md

Reorganized into:
  docs/audits/       — all audit reports & checklists (71 files)
  docs/architecture/  — codebase overview, implementation plan
  docs/guides/        — auth guide, implementation checklist
  docs/load-testing/  — k6 load test guides & endpoints
  docs/security/      — payment & security reviews

Also removed 5 untracked debug/investigation files and
cleaned up playwright-report/ & test-results/ artifacts.

Co-Authored-By: Claude Opus 4 (1M context) <noreply@anthropic.com>
2026-04-13 12:09:14 +07:00

601 lines
16 KiB
Markdown

# GoodGo Platform AI - Technical Reference & Deep Dive
**For Developers & Architects**
---
## BACKEND MODULE HIERARCHY
### Core Module Dependencies
```
SharedModule (lowest level)
├── 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)
```
---
## DOMAIN MODELS - RELATIONSHIPS
### User Role Hierarchy
```
User (root entity)
├── Role: BUYER → Can browse, search, inquire, purchase
├── Role: SELLER → Can create listings, receive inquiries, sell
├── Role: AGENT → Extends Seller + lead management
└── Role: ADMIN → All permissions + moderation
```
### Listing Workflow
```
User (SELLER)
↓ creates
Property + PropertyMedia
↓ associated with
Listing (status: DRAFT → PUBLISHED → SOLD → ARCHIVED)
↓ receives
Inquiry (from BUYER/AGENT)
↓ converts to
Transaction (buyer-seller exchange)
↓ followed by
Review + UsageRecord (analytics)
```
### Payment Flow
```
User (Subscription Start)
Plan (monthly/yearly pricing)
Subscription (active/cancelled/expired)
Payment (processed via VNPay)
├── Idempotency Key (prevents duplicates)
└── Status Tracking
UsageRecord (track consumed resources)
```
---
## AUTHENTICATION FLOW
### JWT Token Lifecycle
```
1. User Login (email + password OR OAuth)
└→ Verify credentials (bcrypt hash)
2. Generate Tokens
├→ AccessToken (15 min, bearer auth)
└→ RefreshToken (7 days, stored in DB)
└→ Token Family (refresh rotation)
3. Return to Client
└→ Set Secure HTTP-Only Cookie (refresh token)
4. API Access
├→ Authorization: Bearer <accessToken>
├→ Guard validates JWT signature
└→ Inject user context into request
5. Token Refresh
├→ Client sends refresh token
├→ Verify token family (revocation check)
├→ Rotate token (issue new family)
└→ Return new access token
```
---
## DATABASE SCHEMA - KEY INDEXES
### Query Optimization Strategy
```
User Table:
├── idx_user_role (BUYER/SELLER/AGENT/ADMIN filtering)
├── idx_user_kyc_status (compliance checks)
├── idx_user_active (active user queries)
├── idx_user_deleted_at (soft delete filtering)
└── idx_role_active_created (complex queries: role + active + order by)
Listing Table:
├── idx_listing_status (published, archived, sold filtering)
├── idx_listing_user_created (user's listings ordered)
└── idx_listing_location_geo (PostGIS spatial queries)
Payment Table:
├── idx_payment_user_status (user's payment history)
├── idx_payment_idempotency (duplicate prevention)
└── idx_payment_external_ref (payment gateway reconciliation)
Search Optimization:
└── Typesense (full-text + geo-search, delegated from DB)
```
---
## SECURITY LAYERS - DETAILED
### Layer 1: Network Level
```
HTTP Request
Helmet (Express middleware)
├── Content-Security-Policy
│ └── Blocks inline scripts, restricts origins
├── X-Frame-Options: DENY
│ └── Prevents clickjacking
├── Strict-Transport-Security (HSTS)
│ └── Forces HTTPS for 31536000 seconds
├── X-Content-Type-Options: nosniff
│ └── Prevents MIME-sniffing
└── Referrer-Policy: strict-origin-when-cross-origin
└── Controls referrer leaks
```
### Layer 2: Application Level
```
Request Processing
1. CORS Validation
└── Whitelist check (process.env.CORS_ORIGINS)
2. CSRF Protection
├── Read (GET): Set __Host-X-CSRF-Token cookie
└── Write (POST/PUT/PATCH/DELETE):
├── Verify X-CSRF-Token header
└── Validate cookie matches header (double-submit)
3. Input Sanitization
├── Remove XSS vectors (sanitize-html)
├── Whitelist validation (class-validator)
└── Type coercion (class-transformer)
4. Rate Limiting
├── Global: 60 req/min per IP
├── Auth: 10 req/min per IP (login brute-force protection)
└── Payments: 20 req/min per IP (webhook replay protection)
```
### Layer 3: Data Level
```
Field Encryption (PII Protection)
├── FieldEncryptionService
│ ├── AES-256-GCM encryption
│ ├── Field-level (can query by hash)
│ └── Key derivation from master secret
├── Email: Encrypted + hashed (both in DB)
├── Phone: Encrypted + hashed (both in DB)
└── KYC Data: Encrypted JSON storage
Audit Trail
├── AdminAuditLog captures:
│ ├── User ID (who)
│ ├── Action (what)
│ ├── Target entity (where)
│ ├── Changes (before/after)
│ └── Timestamp (when)
└── Queryable for compliance
```
### Layer 4: Authorization
```
Route Handler
@UseGuards(JwtGuard, RoleGuard)
├── Extract JWT from Authorization header
├── Validate signature (HS256)
├── Check token expiration
├── Inject user context (request.user)
└── Verify role (BUYER/SELLER/AGENT/ADMIN)
└── Reject if insufficient permissions
```
---
## CQRS PATTERN IMPLEMENTATION
### Command Pattern (State Changes)
```
CreateListingCommand
├── Input: CreateListingDTO
├── Handler: CreateListingCommandHandler
│ ├── Validate inputs
│ ├── Check user permissions
│ ├── Create Property entity
│ ├── Create Listing entity
│ ├── Emit ListingCreatedEvent
│ └── Update search index
└── Output: CreatedListingDTO
Flow:
Controller → Command → CommandHandler → Domain → Event → Repository → Cache invalidate
```
### Query Pattern (Read-only)
```
GetListingQuery
├── Input: ListingId
├── Handler: GetListingQueryHandler
│ ├── Check cache (Redis)
│ ├── If hit: return cached
│ └── If miss:
│ ├── Query database
│ ├── Cache result (TTL-based)
│ └── Return to client
└── Output: ListingDTO
Flow:
Controller → Query → QueryHandler → Repository → Cache store → Response
```
---
## CACHING STRATEGY
### Multi-Level Caching
```
Level 1: Browser Cache
├── Static assets (CSS, JS)
├── Max-Age: 31536000 (1 year)
└── Immutable: true
Level 2: CDN Cache (if deployed)
├── JSON responses
├── Max-Age: 300 (5 min)
└── Surrogate-Key invalidation
Level 3: Application Cache (Redis)
├── User objects (TTL: 1 hour)
├── Listing details (TTL: 30 min)
├── Search results (TTL: 5 min)
└── Rate limit counters (TTL: per window)
Cache Invalidation Triggers:
├── Event-based: ListingUpdatedEvent → invalidate key
├── Time-based: TTL expiration
├── Manual: Cache.delete(key) on batch operations
└── Circuit breaker: If Redis down, bypass to DB
```
---
## ERROR HANDLING & OBSERVABILITY
### Exception Hierarchy
```
GlobalExceptionFilter (catches all)
├→ HttpException (known errors)
│ ├── BadRequestException (400)
│ ├── UnauthorizedException (401)
│ ├── ForbiddenException (403)
│ ├── NotFoundException (404)
│ ├── ConflictException (409)
│ └── InternalServerErrorException (500)
└→ Unknown Error
└→ Sentry.captureException(error)
├── Capture stack trace
├── Attach request context
├── Tag by module/operation
└── Alert ops team (if severity > WARN)
Structured Logging (Pino)
├── JSON format for log aggregation
├── Context injection (request ID, user ID)
├── Log levels: trace, debug, info, warn, error, fatal
└── Destination: stdout (collected by Loki/Promtail)
```
### Monitoring Points
```
Metrics (Prometheus)
├── HTTP request latency
├── Database query time
├── Cache hit/miss ratio
├── Error rate by endpoint
├── Queue depth (background jobs)
└── Payment processing success rate
Logs (Loki)
├── Searchable by timestamp, level, service, user
├── Retention: 30 days
└── Queries: error trends, user activity, audit trail
Traces (Sentry)
├── Request waterfall
├── Database call chains
└── Error context snapshot
```
---
## BACKGROUND JOBS & EVENTS
### Event System
```
Domain Event
├── ListingCreatedEvent
├── PaymentProcessedEvent
├── NotificationScheduledEvent
└── UserDeletedEvent
EventEmitter.emit()
Event Subscribers (consume in order)
├── ListingCreatedEventSubscriber
│ └→ Index in Typesense
├── PaymentProcessedEventSubscriber
│ └→ Send email receipt
├── NotificationScheduledEventSubscriber
│ └→ Queue FCM push
└── UserDeletedEventSubscriber
└→ Archive data + audit trail
Error Handling:
├── Retry policy (3 retries, exponential backoff)
├── Dead letter queue (failed events)
└── Monitoring alert (critical events failed)
```
---
## FRONTEND STATE MANAGEMENT
### Zustand Store Pattern
```
// 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 }),
}
}))
// Component Usage
const { user, setUser } = useAuthStore()
// Persistence (automatic)
├── localStorage (client-side)
├── Hydration on page load
└── Sync across tabs (storage event)
```
### React Query Integration
```
// Hook Pattern
const useListings = (filters) => {
return useQuery({
queryKey: ['listings', filters],
queryFn: () => listingsApi.search(filters),
staleTime: 5 * 60 * 1000, // 5 min
gcTime: 10 * 60 * 1000, // 10 min (old: cacheTime)
retry: 3,
retryDelay: exponentialBackoff,
})
}
// Features
├── Automatic caching by queryKey
├── Background refetching
├── Optimistic updates
├── Pagination support
└── Dependency tracking
```
---
## DEPLOYMENT ARCHITECTURE
### Local Development
```
docker-compose.yml
├── PostgreSQL (5432)
├── Redis (6379)
├── Typesense (8108)
├── MinIO (9000)
└── PgBouncer (6432 - optional)
API Server: http://localhost:3001/api/v1
Web Server: http://localhost:3000
Swagger Docs: http://localhost:3001/api/v1/docs
```
### Production Deployment
```
Kubernetes Cluster
├── API Pod (NestJS)
│ ├── Port: 3001
│ ├── Resources: 2 CPU, 2GB RAM
│ ├── Replicas: 3+ (autoscaling)
│ ├── Probes: liveness + readiness
│ └── Limits: enforce resource quotas
├── Web Pod (Next.js)
│ ├── Port: 3000
│ ├── Replicas: 2+
│ └── CDN: CloudFront/Cloudflare
├── PostgreSQL (managed RDS or Kubernetes StatefulSet)
├── Redis (managed ElastiCache or Kubernetes)
└── Typesense (managed or self-hosted cluster)
Ingress → Load Balancer → Service → Pods
```
---
## CI/CD PIPELINE
### Automated Stages
```
1. Code Push to master/PR
└→ GitHub Actions triggered
2. Lint Stage (2 min)
├── ESLint check
└── Prettier validation
3. Type Check Stage (3 min)
└── TypeScript compilation (no emit)
4. Unit Test Stage (5 min)
├── Backend: Vitest (pnpm test)
└── Frontend: Vitest + RTL
5. Integration Test Stage (8 min)
├── Test database setup
└── Vitest integration config
6. Build Stage (10 min)
├── NestJS build (tsc + webpack)
├── Next.js build (.next folder)
└── Artifact storage
7. E2E Test Stage (15 min) - if CI passes
├── Service startup (Postgres, Redis, Typesense)
├── Database migration
├── Seed data
├── Playwright tests (Chromium)
└── Report generation
8. Deploy Stage (5 min) - if all pass
├── Docker image build
├── Registry push
└── Kubernetes rollout
Total: ~50 min (sequential) or ~15 min (parallel)
```
---
## PERFORMANCE TUNING CHECKLIST
### Database
- [ ] Query analysis (EXPLAIN ANALYZE)
- [ ] Missing indexes (pg_stat_statements)
- [ ] Connection pooling tuned (PgBouncer)
- [ ] Replication lag monitored
- [ ] Backup tested (recovery time < 1 hour)
### Application
- [ ] Memory usage profiled (Node.js heap)
- [ ] CPU throttling identified
- [ ] Garbage collection tuned (heap snapshots)
- [ ] Logging overhead measured
- [ ] Dependency versions updated
### Frontend
- [ ] Bundle size analyzed (webpack analyzer)
- [ ] Code splitting implemented (routes)
- [ ] Images optimized (Next.js Image)
- [ ] Critical CSS inlined
- [ ] Web vitals tracked (LCP, FID, CLS)
### Infrastructure
- [ ] Load balancer health checks tuned
- [ ] Autoscaling policies tested
- [ ] Cache hit rates > 80%
- [ ] Network latency acceptable (< 100ms)
- [ ] Monitoring alert thresholds realistic
---
## TROUBLESHOOTING GUIDE
### "Database Connection Timeout"
```
Diagnosis:
1. Check if PostgreSQL container is running: docker-compose ps
2. Verify DATABASE_URL in .env
3. Check PgBouncer if production: psql -h localhost -p 6432 -U pgbouncer
4. Look for connection limit reached: SELECT count(*) FROM pg_stat_activity
Fix:
├── Restart: docker-compose restart postgres
├── Increase PgBouncer pool: PGBOUNCER_POOL_SIZE=30
└── Check slow queries: pg_stat_statements
```
### "Redis Connection Refused"
```
Diagnosis:
1. Check Redis container: docker-compose ps redis
2. Verify REDIS_URL in .env
3. Check port: redis-cli -p 6379 ping
4. Check memory: redis-cli INFO memory
Fix:
├── Restart: docker-compose restart redis
├── Flush if needed: redis-cli FLUSHALL (dev only!)
└── Monitor: redis-cli --stat
```
### "Typesense Index Not Found"
```
Diagnosis:
1. Check Typesense container: docker-compose ps typesense
2. Verify TYPESENSE_API_KEY in .env
3. List indexes: curl http://localhost:8108/collections -H "X-TYPESENSE-API-KEY: <key>"
4. Check sync job logs
Fix:
├── Re-seed: pnpm db:seed
├── Reindex: DELETE /listings index, then rebuild
└── Monitor: Typesense dashboard http://localhost:8108/dashboard
```
### "Tests Failing with 'Port Already in Use'"
```
Diagnosis:
1. Check running processes: lsof -i :3001 (macOS) or netstat -ano (Windows)
2. Docker containers: docker ps
Fix:
├── Kill process: kill -9 <PID>
├── Stop containers: docker-compose down
├── Update port in .env.test
└── Ensure cleanup in global-teardown.ts
```
---
## SECURITY CHECKLIST - PRE-DEPLOYMENT
- [ ] JWT secrets rotated and unique
- [ ] CORS_ORIGINS finalized (no localhost in prod)
- [ ] Database credentials strong (> 16 chars, random)
- [ ] MinIO/AWS S3 credentials secure (IAM policy restricted)
- [ ] OAuth client secrets masked
- [ ] SSL certificate installed (HTTPS)
- [ ] HSTS preload submitted
- [ ] Security headers tested (securityheaders.com)
- [ ] OWASP Top 10 reviewed
- [ ] Penetration test scheduled
- [ ] Rate limits tuned (no bypass possible)
- [ ] Audit logging verified
- [ ] Backup encryption enabled
- [ ] Incident response plan documented
- [ ] On-call rotation configured