# MotoVaultPro Architecture Overview ## Architecture Summary MotoVaultPro is a single-tenant vehicle management application built with a **6-container Docker-first architecture**. All development and deployment occurs in production-configured containers with no local installation dependencies. ### Core Containers 1. **Traefik** - Reverse proxy and service discovery 2. **Frontend** - React SPA with Vite (Node.js 20 + nginx) 3. **Backend** - Node.js API with Fastify (Node.js 20) 4. **PostgreSQL** - Primary database (PostgreSQL 15) 5. **Redis** - Caching layer (Redis 7) 6. **Platform** - Vehicle data service (Python FastAPI) ### Key Architectural Principles - **Production-Only**: All services use production builds and configuration - **Docker-First**: Zero local installations, all work happens in containers - **Single-Tenant**: Application serves a single user/tenant - **User-Scoped Data**: All application data isolated by `user_id` - **Feature Capsule Organization**: Self-contained feature modules in `backend/src/features/` ## Container Interaction Diagram ``` Internet/Users | v +----------------+------------------+ | Traefik | | (Reverse Proxy & TLS) | | Ports: 80, 443, 8080 | +----------------+------------------+ | +---------------------+---------------------+ | | v v +------------------+ +--------------------+ | Frontend | | Backend | | React + Vite | | Node.js + Fastify | | Port: 3000 | | Port: 3001 | +------------------+ +--------------------+ (frontend network) (backend network) | | +---------------------------------+ | | v v +---------------+ +-------------+ | PostgreSQL | | Redis | | Port: 5432 | | Port: 6379 | +---------------+ +-------------+ (database network - internal) ``` ## Network Topology ### Frontend Network - **Purpose**: Public traffic routing - **Type**: Bridge (non-internal) - **Connected Services**: Traefik, Frontend - **Access**: External (for Traefik public endpoints) ### Backend Network - **Purpose**: API service communication - **Type**: Bridge (non-internal) - **Connected Services**: Traefik, Backend, Platform - **Access**: External (requires Auth0 JWT validation) ### Database Network - **Purpose**: Data layer isolation - **Type**: Bridge (internal) - **Connected Services**: Backend, Platform, PostgreSQL, Redis - **Access**: Internal only, no external exposure ## Request Flow ### User Request Flow ``` 1. User → HTTPS Request 2. Traefik → TLS Termination + Route Selection - Domain: motovaultpro.com or www.motovaultpro.com - Path: / → Frontend (priority 10) - Path: /api → Backend (priority 20) - Path: /platform → Platform (priority 25) 3. Frontend/Backend → Process Request 4. Response → Traefik → User ``` ### Authentication Flow ``` 1. User → Frontend → Auth0 (Login) 2. Auth0 → JWT Token → Frontend 3. Frontend → Backend (with Authorization: Bearer ) 4. Backend → Validate JWT via Auth0 JWKS 5. Backend → Extract user_id from JWT (request.user.sub) 6. Backend → Execute user-scoped queries 7. Backend → Response → Frontend ``` ### Backend Platform Flow ``` 1. Backend Feature → Calls platform domain services (TypeScript in-process) 2. Platform module → Query PostgreSQL (vehicles schema) 3. Platform module → Check/Update Redis cache 4. Platform response → Returned to caller (vehicles, frontend proxies, etc.) ``` ### Data Access Flow ``` 1. Backend/Platform → PostgreSQL Query - Database: motovaultpro - Connection: Internal via database network 2. Backend/Platform → Redis Cache Check - Connection: Internal via database network 3. Response → Backend → Frontend ``` ## Service Details ### Traefik (Reverse Proxy) - **Image**: traefik:v3.0 - **Purpose**: Service discovery, TLS termination, load balancing - **Ports**: - 80 (HTTP) - 443 (HTTPS) - 8080 (Dashboard) - **Networks**: frontend, backend - **Health Check**: `traefik healthcheck` (30s interval) - **Configuration**: - `/etc/traefik/traefik.yml` - Main config - `/etc/traefik/middleware.yml` - Middleware rules - Dynamic routing via Docker labels ### Frontend (React SPA) - **Technology**: React 18 + Vite + TypeScript - **Build**: Multi-stage Dockerfile (node:20-alpine → nginx:alpine) - **Port**: 3000 (internal) - **Networks**: frontend - **Dependencies**: Backend (API calls) - **Health Check**: `curl http://localhost:3000` (30s interval) - **Environment Variables**: - `VITE_AUTH0_DOMAIN` - Auth0 tenant - `VITE_AUTH0_CLIENT_ID` - Auth0 application ID - `VITE_AUTH0_AUDIENCE` - API identifier - `VITE_API_BASE_URL` - Backend API path (/api) - **Routing**: Traefik routes non-/api paths to frontend ### Backend (Node.js API) - **Technology**: Node.js 20 + Fastify + TypeScript - **Build**: Production build in node:20-alpine - **Port**: 3001 (internal) - **Networks**: backend, database - **Dependencies**: PostgreSQL, Redis, Platform - **Health Check**: `http://localhost:3001/health` (30s interval) - **Configuration**: - `/app/config/production.yml` - Main config - `/app/config/shared.yml` - Shared config - `/run/secrets/*` - Secret files (K8s pattern) - **Secrets**: - `postgres-password` - Database password - `platform-vehicles-api-key` - Platform service auth - `auth0-client-secret` - Auth0 M2M secret - `google-maps-api-key` - Maps API key - **Storage**: `/app/data/documents` - Document uploads ### PostgreSQL (Primary Database) - **Image**: postgres:15-alpine - **Database**: motovaultpro - **Port**: 5432 (exposed for development) - **Networks**: database (internal) - **User**: postgres - **Password**: File-based secret (`/run/secrets/postgres-password`) - **Health Check**: `pg_isready -U postgres` (10s interval) - **Storage**: Named volume `mvp_postgres_data` - **Schemas**: - `public` - Application data (user-scoped) - `vehicles` - Platform vehicle data (shared) ### Redis (Cache Layer) - **Image**: redis:7-alpine - **Port**: 6379 (exposed for development) - **Networks**: database (internal) - **Persistence**: AOF enabled (`--appendonly yes`) - **Health Check**: `redis-cli ping` (10s interval) - **Storage**: Named volume `mvp_redis_data` - **Usage**: - Vehicle data caching (year-based hierarchy) - Session storage (future) - Rate limiting (future) ### Platform Module (Vehicle Data) - **Technology**: TypeScript feature capsule inside `backend/src/features/platform/` - **Runtime**: Shares the `mvp-backend` Fastify container - **Dependencies**: PostgreSQL, Redis (accessed via backend connection pool) - **Deployment**: Bundled with backend build; no separate container or port - **Health**: Covered by backend `/health` endpoint and feature-specific logs - **Configuration**: - `backend/src/features/platform/domain/*.ts` - Business logic - `backend/src/features/platform/data/*.ts` - Database + vPIC integration - **Secrets**: - Reuses backend secrets (PostgreSQL, Auth0, etc.) - **Purpose**: - Vehicle make/model/trim/engine data - VIN decoding (planned) - Standardized vehicle information ## Platform Module Integration ### Current Architecture Platform capabilities now run **in-process** within the backend as a feature capsule. This delivers: - **Shared Language & Tooling**: TypeScript across the stack - **Centralized Caching**: Reuses backend Redis helpers for year-based lookups - **Simplified Operations**: No extra container to build, scale, or monitor ### Shared Infrastructure - **Database**: Uses the backend connection pool against `mvp-postgres` - **Cache**: Shares the backend Redis client (`mvp-redis`) - **Runtime**: Packaged with the `mvp-backend` container and Fastify plugins - **Secrets**: Relies on the same secret files as the backend (PostgreSQL, Auth0, etc.) ### Communication Pattern ```typescript // Vehicles feature pulling platform data via domain services const platformService = new PlatformVehicleDataService({ db: postgresPool, cache: redisClient }); const makes = await platformService.getMakes({ year: 2024 }); ``` ### Ongoing Work - Continue migrating remaining FastAPI utilities into TypeScript where needed - Expand `/api/platform/*` endpoints as new lookup types are added - Monitor backend logs for `platform` namespace entries to verify health ## Feature Capsule Architecture ### Organization Pattern Features are **self-contained modules** within the backend service at `backend/src/features/[name]/`: ``` backend/src/features/ ├── vehicles/ # Vehicle management ├── fuel-logs/ # Fuel tracking ├── maintenance/ # Service records ├── stations/ # Gas station locations ├── documents/ # Document storage └── platform/ # Vehicle data + VIN decoding ``` ### Feature Structure Each feature follows a standardized structure: ``` feature-name/ ├── README.md # Feature documentation ├── api/ # Route handlers ├── domain/ # Business logic ├── data/ # Data access layer ├── migrations/ # Database migrations ├── tests/ # Unit and integration tests ├── events/ # Event handlers (optional) └── external/ # External service integrations (optional) ``` ### Current Features #### Vehicles - **Purpose**: Vehicle inventory management - **Tables**: `vehicles` (user-scoped) - **Integration**: Platform service for make/model/trim data - **Endpoints**: CRUD + dropdown data #### Fuel Logs - **Purpose**: Fuel purchase and efficiency tracking - **Tables**: `fuel_logs` (user-scoped) - **Integration**: Stations feature for location data - **Endpoints**: CRUD + analytics #### Maintenance - **Purpose**: Service and maintenance record tracking - **Tables**: `maintenance_records` (user-scoped) - **Integration**: Vehicles feature for vehicle data - **Endpoints**: CRUD + reminders #### Stations - **Purpose**: Gas station location and pricing - **Tables**: `stations` (user-scoped) - **Integration**: Google Maps API - **Endpoints**: Search + favorites #### Documents - **Purpose**: Document storage and retrieval - **Tables**: `documents` (user-scoped) - **Storage**: Filesystem (`/app/data/documents/`) - **Endpoints**: Upload + download + delete ## Data Flow ### Authentication via Auth0 JWT ``` 1. Frontend → Auth0 Login 2. Auth0 → JWT Token (contains user_id in 'sub' claim) 3. Frontend → Backend (Authorization: Bearer ) 4. Backend → Validate JWT: - Verify signature via Auth0 JWKS endpoint - Check issuer: https://{AUTH0_DOMAIN}/ - Check audience: {AUTH0_AUDIENCE} 5. Backend → Extract user_id from token.sub 6. Backend → Execute user-scoped queries ``` ### User ID Extraction ```typescript // From auth.plugin.ts await request.jwtVerify(); // Validates and populates request.user const userId = request.user.sub; // Auth0 user ID (e.g., "auth0|123456") ``` ### User-Scoped Data Access All application data is isolated by `user_id`: ```sql -- Example: Get user's vehicles SELECT * FROM vehicles WHERE user_id = $1; -- Example: Create fuel log (user_id inserted) INSERT INTO fuel_logs (user_id, vehicle_id, gallons, cost, ...) VALUES ($1, $2, $3, $4, ...); -- Example: Soft delete (preserves audit trail) UPDATE vehicles SET deleted_at = NOW() WHERE id = $1 AND user_id = $2; ``` ### Data Isolation Strategy - **Foreign Keys**: All user data tables have `user_id` foreign key - **Query Scoping**: All queries filtered by authenticated user's ID - **Soft Deletes**: `deleted_at` timestamp for audit trail - **No Cascade Deletes**: Prevents accidental data loss - **Index Strategy**: Composite indexes on (`user_id`, primary key) ### Cross-Feature Data Flow ``` 1. User creates vehicle (Vehicles feature) 2. User logs fuel purchase (Fuel Logs feature) - References vehicle_id - References station_id (Stations feature) 3. User adds maintenance record (Maintenance feature) - References vehicle_id - Can attach documents (Documents feature) ``` ## Configuration Management ### Kubernetes-Style Patterns The application uses Kubernetes-inspired configuration patterns: **ConfigMaps** (YAML files): - `/app/config/production.yml` - Service-specific config - `/app/config/shared.yml` - Cross-service config **Secrets** (File-based): - `/run/secrets/postgres-password` - Database credentials - `/run/secrets/auth0-client-secret` - OAuth credentials - `/run/secrets/google-maps-api-key` - External API keys ### Environment Variables Used for service references and runtime configuration: ```yaml NODE_ENV: production CONFIG_PATH: /app/config/production.yml SECRETS_DIR: /run/secrets DATABASE_HOST: mvp-postgres REDIS_HOST: mvp-redis ``` ## Development Workflow ### Container Commands (via Makefile) ```bash make start # Start all 5 containers make stop # Stop all containers make restart # Restart all containers make rebuild # Rebuild and restart containers make logs # View all container logs make logs-backend # View backend logs only make clean # Remove containers and volumes ``` ### Health Monitoring ```bash # Check container health docker ps # View specific service logs docker logs mvp-backend -f docker logs mvp-postgres -f # Test health endpoints (via Traefik) curl https://motovaultpro.com/api/health # Backend (includes platform module) # Or from within backend container docker compose exec mvp-backend curl http://localhost:3001/health ``` ### Database Access ```bash # PostgreSQL shell make db-shell-app # Execute SQL docker exec -it mvp-postgres psql -U postgres -d motovaultpro # View Redis data docker exec -it mvp-redis redis-cli ``` ## Security Architecture ### Authentication & Authorization - **Provider**: Auth0 (OAuth 2.0 / OpenID Connect) - **Token Type**: JWT (JSON Web Token) - **Validation**: JWKS-based signature verification - **Token Cache**: 1 hour TTL for Auth0 public keys - **Issuer Validation**: Prevents token spoofing - **Audience Validation**: API-specific tokens only ### Protected Resources All API endpoints require valid JWT except: - `/health` - Health check (priority routing) - `/api/health` - API health check (bypass auth) ### Data Security - **VIN Handling**: Check digit validation, no VIN in logs - **User Isolation**: Queries filtered by authenticated `user_id` - **Soft Deletes**: Audit trail preservation - **No Cascading Deletes**: Manual data cleanup only - **Encrypted Connections**: PostgreSQL SSL/TLS ### Infrastructure Security - **Non-root Containers**: All services run as non-root users - **Network Isolation**: Internal database network - **Secret Management**: File-based secrets (K8s pattern) - **No Hardcoded Credentials**: Environment and file injection only ## Deployment Strategy ### Production Environment - **Container Orchestration**: Docker Compose (current) → Kubernetes (future) - **Service Discovery**: Traefik with Docker provider - **TLS**: Automatic certificate management via Traefik - **Scaling**: Single instance per service (MVP phase) - **Monitoring**: Container health checks + log aggregation ### Zero-Downtime Deployment ```bash # Build new images make rebuild # Traefik handles traffic routing during restart # Health checks ensure services are ready before traffic ``` ## Observability ### Logging Strategy - **Format**: Structured JSON logging - **Levels**: ERROR, WARN, INFO, DEBUG - **Context**: Request ID, User ID (truncated), Service name - **Aggregation**: Docker logs → Future: ELK/Loki stack ### Health Checks Every service exposes health endpoints: - **Backend**: `GET /health` - Database + Redis connectivity - **Platform**: `GET /health` - Database + Redis connectivity - **Frontend**: Nginx status check - **PostgreSQL**: `pg_isready` - **Redis**: `redis-cli ping` ### Metrics (Future) - Request rate and latency - Database query performance - Cache hit rates - Error rates by endpoint ## Performance Considerations ### Caching Strategy - **Vehicle Data**: Year-based hierarchical caching in Redis - **JWT Keys**: 1-hour cache for Auth0 public keys - **Database Queries**: Indexed by (`user_id`, primary key) ### Database Optimization - **Connection Pooling**: Fastify PostgreSQL plugin - **Prepared Statements**: SQL injection prevention + performance - **Indexes**: Composite indexes on frequently queried columns - **Query Scoping**: All queries filtered by `user_id` for data locality ### Horizontal Scaling (Future) - **Stateless Services**: Backend and Platform can scale horizontally - **Shared State**: PostgreSQL and Redis as centralized state - **Load Balancing**: Traefik distributes traffic across instances ## Related Documentation - Feature Documentation: `backend/src/features/{feature}/README.md` - Platform Architecture: `docs/PLATFORM-SERVICES.md` - Security Details: `docs/SECURITY.md` - Database Schema: `docs/DATABASE-SCHEMA.md` - Testing Guide: `docs/TESTING.md` - Vehicles API: `docs/VEHICLES-API.md` - Development Commands: `Makefile`