Files
motovaultpro/docs/ARCHITECTURE-OVERVIEW.md
Eric Gullickson 8331bde4b0
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 34s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 51s
Deploy to Staging / Verify Staging (pull_request) Successful in 2m37s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 8s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped
docs: update 5-container refs to 9-container architecture (refs #101)
Update all documentation to reflect the current 9-container architecture
(6 application + 3 logging) after the logging stack upgrades. Add missing
OCR, Loki, Alloy, and Grafana services to context.json.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 20:11:31 -06:00

20 KiB

MotoVaultPro Architecture Overview

Architecture Summary

MotoVaultPro is a single-tenant vehicle management application built with a 9-container Docker-first architecture (6 application + 3 logging). All development and deployment occurs in production-configured containers with no local installation dependencies.

Application Containers (6)

  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) - includes platform feature module
  4. OCR - Python-based document text extraction
  5. PostgreSQL - Primary database (PostgreSQL 18)
  6. Redis - Caching layer (Redis 8)

Logging Containers (3)

  1. Loki - Centralized log storage (30-day retention)
  2. Alloy - Log collection and forwarding
  3. Grafana - Log querying and visualization

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
  • Access: External (requires Auth0 JWT validation)

Database Network

  • Purpose: Data layer isolation
  • Type: Bridge (internal)
  • Connected Services: Backend, 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: /api/platform/* → Backend (platform feature module)
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 <JWT>)
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:lts-alpine → nginx:alpine)
  • Port: 3000 (internal)
  • Networks: frontend
  • Dependencies: Backend (API calls)
  • Health Check: curl https://motovaultpro.com (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:lts-alpine
  • Port: 3001 (internal)
  • Networks: backend, database
  • Dependencies: PostgreSQL, Redis, Platform
  • Health Check: https://motovaultpro.com/api/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 queries
  • Secrets:
    • Reuses backend secrets (PostgreSQL, Auth0, etc.)
  • Purpose:
    • Vehicle hierarchical data (years, makes, models, trims, engines)
    • VIN decoding (Planned/Future - not yet implemented)
    • 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

// 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/
├── admin/             # Admin role management
├── auth/              # User authentication
├── backup/            # Database backup/restore
├── documents/         # Document storage
├── fuel-logs/         # Fuel tracking
├── maintenance/       # Service records and schedules
├── notifications/     # Email and toast notifications
├── onboarding/        # User onboarding flow
├── platform/          # Vehicle data + VIN decoding
├── stations/          # Gas station locations
├── terms-agreement/   # T&C acceptance audit
├── user-export/       # GDPR data export
├── user-preferences/  # User settings
├── user-profile/      # User profile management
└── vehicles/          # Vehicle management

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 (15)

Admin

  • Purpose: Admin role management and oversight
  • Tables: admin_users, admin_audit_logs
  • Endpoints: Admin CRUD, catalog management, station oversight

Auth

  • Purpose: User authentication and signup
  • Tables: None (uses Auth0)
  • Integration: Auth0 for identity management
  • Endpoints: Signup, verify email, resend verification

Backup

  • Purpose: Database and document backup/restore
  • Tables: backup_schedules, backup_history, backup_settings
  • Storage: /app/data/backups/
  • Endpoints: Admin backup CRUD, restore, schedules

Documents

  • Purpose: Document storage and retrieval
  • Tables: documents (user-scoped)
  • Storage: Filesystem (/app/data/documents/)
  • Endpoints: Upload + download + delete

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_logs, maintenance_schedules (user-scoped)
  • Integration: Vehicles feature, notifications
  • Endpoints: CRUD + schedules + reminders

Notifications

  • Purpose: Email and toast notifications
  • Tables: email_templates, notification_logs
  • Integration: Resend API for email delivery
  • Endpoints: User summary, admin template management

Onboarding

  • Purpose: User onboarding after signup
  • Tables: Uses user_profiles, user_preferences
  • Integration: User profile and preferences features
  • Endpoints: Preferences, complete, status

Platform

  • Purpose: Vehicle data and VIN decoding
  • Tables: engines, transmissions, vehicle_options
  • Integration: Backend dropdown cascade queries
  • Endpoints: Years, makes, models, trims, engines

Stations

  • Purpose: Gas station location and pricing
  • Tables: stations, community_stations
  • Integration: Google Maps API
  • Endpoints: Search + favorites + community reports

Terms Agreement

  • Purpose: Legal audit trail for T&C acceptance
  • Tables: terms_agreements
  • Integration: Created during signup flow
  • Endpoints: None (internal use)

User Export

  • Purpose: GDPR-compliant data export
  • Tables: None (reads from all user data)
  • Storage: Temporary TAR.GZ archives
  • Endpoints: Export download

User Preferences

  • Purpose: User preference management
  • Tables: user_preferences (user-scoped)
  • Endpoints: GET/PUT preferences

User Profile

  • Purpose: User profile management
  • Tables: user_profiles (user-scoped)
  • Endpoints: GET/PUT profile

Vehicles

  • Purpose: Vehicle inventory management
  • Tables: vehicles (user-scoped)
  • Integration: Platform service for make/model/trim data
  • Endpoints: CRUD + dropdown data + images

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 <JWT>)
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

// 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:

-- 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:

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)

make start          # Start all 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

# 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 https://motovaultpro.com/api/health

Database Access

# 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

# 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
  • 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