# Architecture ## System Overview GoodGo Platform AI is a monorepo containing a NestJS backend, Next.js frontend, Python AI services, and MCP (Model Context Protocol) servers. The system is orchestrated with Turborepo and pnpm workspaces. ``` ┌──────────────────────────────────────────┐ │ Client (Browser) │ └──────────────────┬───────────────────────┘ │ ┌──────────────────▼───────────────────────┐ │ Next.js 14 (apps/web) │ │ ┌─────────┐ ┌──────────┐ ┌───────┐ │ │ │ Pages │ │Components│ │Zustand │ │ │ │(App │ │(UI + │ │(State) │ │ │ │ Router) │ │ Domain) │ │ │ │ │ └─────────┘ └──────────┘ └───────┘ │ └──────────────────┬───────────────────────┘ │ REST API ┌──────────────────▼───────────────────────┐ │ NestJS 11 (apps/api) │ │ │ │ ┌────────┐ ┌────────┐ ┌─────────────┐ │ │ │ Auth │ │Listings│ │ Payments │ │ │ ├────────┤ ├────────┤ ├─────────────┤ │ │ │ Search │ │ Admin │ │Subscriptions│ │ │ ├────────┤ ├────────┤ ├─────────────┤ │ │ │Analytics│ │ MCP │ │Notifications│ │ │ ├────────┤ ├────────┤ ├─────────────┤ │ │ │ Agents │ │Inquires│ │ Leads │ │ │ ├────────┤ ├────────┤ ├─────────────┤ │ │ │Reviews │ │ Health │ │ Metrics │ │ │ └────────┘ └────────┘ └─────────────┘ │ └───┬─────┬──────┬─────────┬──────────────┘ │ │ │ │ ┌────────────▼┐ ┌─▼────┐ ▼ ┌───▼──────────┐ │ PostgreSQL │ │Redis │ │ │ Typesense │ │ + PostGIS │ │ │ │ │ (Search) │ └─────────────┘ └──────┘ │ └──────────────┘ │ ┌───────────────▼──────────────────────┐ │ MCP Servers (libs/mcp-servers) │ │ ┌──────────┐┌──────────┐┌────────┐ │ │ │ Property ││ Market ││Valua- │ │ │ │ Search ││Analytics ││tion │ │ │ └──────────┘└──────────┘└───┬────┘ │ └──────────────────────────────┼───────┘ │ ┌──────────────────────────────▼───────┐ │ AI Services (libs/ai-services) │ │ FastAPI + XGBoost + Claude API │ │ ┌──────────┐ ┌────────────────┐ │ │ │ AVM │ │ Moderation │ │ │ │(Pricing) │ │ (Claude API) │ │ │ └──────────┘ └────────────────┘ │ └──────────────────────────────────────┘ ``` ## Module Architecture Each API module follows a layered Domain-Driven Design structure: ``` modules/{module-name}/ ├── presentation/ # HTTP layer │ ├── controllers/ # Route handlers │ └── dtos/ # Request/response DTOs (class-validator) ├── application/ # Business orchestration │ ├── commands/ # Write operations (CQRS) │ ├── queries/ # Read operations (CQRS) │ ├── handlers/ # Command/query handlers │ └── services/ # Application services ├── domain/ # Core business logic │ ├── entities/ # Domain entities & value objects │ ├── repositories/ # Repository interfaces (abstractions) │ └── events/ # Domain events ├── infrastructure/ # External integrations │ ├── repositories/ # Prisma repository implementations │ └── services/ # External service adapters └── {module-name}.module.ts # NestJS module definition ``` ### CQRS Pattern The platform uses NestJS CQRS (`@nestjs/cqrs`) for complex operations: - **Commands** — mutate state (create listing, process payment, register user) - **Queries** — read state (search properties, get analytics) - **Events** — cross-module communication (listing published → index in Typesense, payment completed → send notification) ### Shared Module The `shared/` module provides cross-cutting concerns: - **Prisma service** — database connection and client - **Redis service** — caching and session management - **Guards** — JWT auth guard, roles guard, throttle guard - **Pipes** — global validation pipe (whitelist mode) - **Filters** — exception filters for consistent error responses - **Decorators** — `@CurrentUser()`, `@Roles()`, `@Public()` ## Data Flow ### Property Listing Lifecycle ``` DRAFT → PENDING_REVIEW → ACTIVE → RESERVED → SOLD/RENTED │ │ ▼ │ REJECTED EXPIRED ``` 1. **Seller/Agent** creates listing (status: `DRAFT`) 2. **Seller** submits for review → `PENDING_REVIEW` 3. **Admin** moderates (AI moderation score assists) → `ACTIVE` or `REJECTED` 4. Active listings are indexed in Typesense for search 5. **Buyer** makes inquiry → `Inquiry` record created 6. Transaction workflow: `OFFER_MADE → DEPOSIT_PAID → CONTRACT_SIGNING → COMPLETED` ### Search Flow ``` User Query → NestJS Search Module → Typesense │ ├─ Full-text on title/description ├─ Faceted filters (price, type, bedrooms) └─ Geo-spatial (lat/long + radius) ``` ### Payment Flow ``` User → API (create payment) → Provider (VNPay/MoMo/ZaloPay) │ [User pays on provider page] │ Provider callback → API → Verify signature → Update Payment status │ SUCCESS / FAILED ``` ### AI Valuation Flow ``` API Request → MCP Valuation Server → AI Service (FastAPI) │ XGBoost Model │ ┌─────▼──────┐ │ Estimated │ │ Price + │ │ Confidence │ │ + Factors │ └─────────────┘ ``` ## Database Schema ### Core Models ``` User ──┬── Agent (1:1, for AGENT role users) ├── OAuthAccount (1:N, Google/Zalo) ├── RefreshToken (1:N, token families) ├── Subscription (1:N) ├── SavedSearch (1:N) └── UsageRecord (1:N) Property ──┬── PropertyMedia (1:N, images/videos) ├── Listing (1:N) └── Valuation (1:N) Listing ──┬── Inquiry (1:N) ├── Lead (1:N) ├── Transaction (1:N) └── Agent (N:1) Transaction ── Payment (1:N) Plan ── Subscription (1:N) MarketIndex (standalone — city/district/month aggregates) ``` ### Key Design Decisions - **PostGIS** for spatial queries — property locations stored as `Point` geometry - **JSON columns** for flexible data: amenities, nearby POIs, KYC data, subscription features - **Token family tracking** for secure refresh token rotation (detects reuse attacks) - **Soft statuses** over soft deletes — listings use status workflow, not `deletedAt` ## MCP Servers Three Model Context Protocol servers provide AI tool interfaces: | Server | Tools | Data Source | |--------|-------|-------------| | **Property Search** | `search_properties`, `compare_properties`, `get_property_details` | Typesense | | **Market Analytics** | `get_market_report`, `analyze_trends`, `get_price_indices` | PostgreSQL | | **Valuation** | `estimate_valuation`, `extract_features`, `compare_valuations` | AI Services (FastAPI) | MCP servers are registered via `McpModule` in NestJS, managed by `McpRegistryService`, and exposed through `McpTransportController` over HTTP. ## AI Services Python FastAPI microservice (`libs/ai-services/`) provides: | Endpoint | Model | Purpose | |----------|-------|---------| | `POST /avm/estimate` | XGBoost | Property price estimation with confidence score | | `POST /moderation/check` | Claude API | Content moderation for listing descriptions | | `GET /health` | — | Health check | - **Underthesea** handles Vietnamese text tokenization and NLP preprocessing - XGBoost model uses engineered features (area, location, property type, amenities) ## Security - **JWT + Refresh Token Rotation** — 15-minute access tokens, 7-day refresh tokens with family-based rotation - **OAuth** — Google and Zalo social login - **Rate Limiting** — 60 req/60s default, 10 req/60s for auth endpoints - **Helmet** — HTTP security headers - **CORS** — Configurable origins via `CORS_ORIGINS` - **Input Validation** — class-validator (backend), Zod (frontend) - **Content Sanitization** — sanitize-html for user-generated content - **KYC** — Agent verification workflow (NONE → PENDING → VERIFIED/REJECTED) ## Monitoring - **Prometheus** scrapes `/api/v1/metrics` endpoint every 15 seconds - **Grafana** dashboards auto-provisioned from `monitoring/grafana/dashboards/` - **Loki + Promtail** aggregate container logs; viewable in Grafana - **Pino** structured JSON logging with configurable log levels - Metrics include HTTP request duration, error rates, web vitals, and custom business metrics - Log retention: 15 days (configured in `monitoring/loki/loki-config.yml`) ## Event System The platform uses `@nestjs/event-emitter` for loose coupling between modules: - `listing.published` → Typesense indexer updates search index - `payment.completed` → Notification service sends confirmation - `inquiry.created` → Agent notification triggered - `user.registered` → Welcome email sent