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