Files
motovaultpro/backend/src/features/vehicles
Eric Gullickson 9b4f94e1ee
All checks were successful
Deploy to Staging / Build Images (pull_request) Successful in 4m36s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 28s
Deploy to Staging / Verify Staging (pull_request) Successful in 7s
Deploy to Staging / Notify Staging Ready (pull_request) Successful in 6s
Deploy to Staging / Notify Staging Failure (pull_request) Has been skipped
docs: Update vehicles README with VIN decode endpoint (refs #9)
- Add VIN decode endpoint to API section
- Document request/response format with confidence levels
- Add error response examples (400, 403, 502)
- Update architecture diagram with external/ directory

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 13:56:32 -06:00
..
2026-01-01 10:05:56 -06:00
2025-12-15 21:39:51 -06:00

Vehicles Feature Capsule

Quick Summary (50 tokens)

Primary entity for vehicle management consuming MVP Platform Vehicles Service. Handles CRUD operations, hierarchical vehicle dropdowns, VIN decoding via platform service, user ownership validation, caching strategy (user lists: 5 minutes). Foundation for fuel-logs and maintenance features.

API Endpoints

Vehicle Management

  • POST /api/vehicles - Create new vehicle with platform VIN decoding
  • GET /api/vehicles - List all user's vehicles (cached 5 min)
  • GET /api/vehicles/:id - Get specific vehicle
  • PUT /api/vehicles/:id - Update vehicle details
  • DELETE /api/vehicles/:id - Soft delete vehicle

VIN Decoding (Pro/Enterprise Only)

  • POST /api/vehicles/decode-vin - Decode VIN using NHTSA vPIC API

Hierarchical Vehicle Dropdowns

Status: Vehicles service now proxies the platform vehicle catalog to provide fully dynamic dropdowns. Each selection step filters the next list, ensuring only valid combinations are shown.

Sequence:

  1. GET /api/vehicles/dropdown/years[number] (latest to oldest).
  2. GET /api/vehicles/dropdown/makes?year={year}{ id, name }[] (only makes produced in the selected year).
  3. GET /api/vehicles/dropdown/models?year={year}&make_id={id}{ id, name }[] (models offered for that year/make).
  4. GET /api/vehicles/dropdown/trims?year={year}&make_id={id}&model_id={id}{ id, name }[] (valid trims for the chosen combination).
  5. GET /api/vehicles/dropdown/engines?year={year}&make_id={id}&model_id={id}&trim_id={id}{ id, name }[] (engines tied to the trim).
  6. GET /api/vehicles/dropdown/transmissions?year={year}&make_id={id}&model_id={id}{ id, name }[] (static options: Automatic, Manual).

All dropdown endpoints call Platform VehicleDataService behind the scenes, reuse Redis caching, and return normalized { id, name } payloads ready for the frontend.

Authentication

  • All vehicles endpoints (including dropdowns) require a valid JWT (Auth0).

Request/Response Examples

Create Vehicle

POST /api/vehicles
{
  "vin": "1HGBH41JXMN109186",
  "nickname": "My Honda",
  "color": "Blue",
  "licensePlate": "ABC123",
  "odometerReading": 50000
}

Response (201):
{
  "id": "uuid-here",
  "userId": "user-id",
  "vin": "1HGBH41JXMN109186",
  "make": "Honda", // Auto-decoded via platform service
  "model": "Civic", // Auto-decoded via platform service
  "year": 2021, // Auto-decoded via platform service
  "nickname": "My Honda",
  "color": "Blue",
  "licensePlate": "ABC123",
  "odometerReading": 50000,
  "isActive": true,
  "createdAt": "2024-01-01T00:00:00Z",
  "updatedAt": "2024-01-01T00:00:00Z"
}

Get Makes for Year

GET /api/vehicles/dropdown/makes?year=2024

Response (200):
[
  {"id": 1, "name": "Honda"},
  {"id": 2, "name": "Toyota"},
  {"id": 3, "name": "Ford"}
]

Get Models for Make/Year

GET /api/vehicles/dropdown/models?year=2024&make_id=1

Response (200):
[
  {"id": 101, "name": "Civic"},
  {"id": 102, "name": "Accord"},
  {"id": 103, "name": "CR-V"}
]

Feature Architecture

Complete Self-Contained Structure

vehicles/
├── README.md              # This file
├── index.ts               # Public API exports
├── api/                   # HTTP layer
│   ├── vehicles.controller.ts
│   ├── vehicles.routes.ts
│   └── vehicles.validation.ts
├── domain/                # Business logic
│   ├── vehicles.service.ts
│   ├── vehicles.types.ts
│   └── name-normalizer.ts
├── data/                  # Database layer
│   └── vehicles.repository.ts
├── external/              # External service integrations
│   ├── CLAUDE.md          # Integration pattern docs
│   └── nhtsa/             # NHTSA vPIC API client
│       ├── nhtsa.client.ts
│       ├── nhtsa.types.ts
│       └── index.ts
├── migrations/            # Feature schema
│   └── 001_create_vehicles_tables.sql
├── tests/                 # All tests
│   ├── unit/
│   │   └── vehicles.service.test.ts
│   └── integration/
│       └── vehicles.integration.test.ts
└── (Platform integration: dropdown/VIN decode via shared platform module in features/platform/)

Key Features

🔍 VIN Decoding (NHTSA vPIC API)

  • Tier Gating: Pro and Enterprise users only (vehicle.vinDecode feature key)
  • NHTSA API: Calls official NHTSA vPIC API for authoritative vehicle data
  • Caching: Results cached in vin_cache table (1-year TTL, VIN data is static)
  • Validation: 17-character VIN format, excludes I/O/Q characters
  • Matching: Case-insensitive exact match against dropdown options
  • Confidence Levels: High (exact match), Medium (normalized match), None (hint only)
  • Timeout: 5-second timeout for NHTSA API calls

Decode VIN Request

POST /api/vehicles/decode-vin
Authorization: Bearer <jwt>
{
  "vin": "1HGBH41JXMN109186"
}

Response (200):
{
  "year": { "value": 2021, "nhtsaValue": "2021", "confidence": "high" },
  "make": { "value": "Honda", "nhtsaValue": "HONDA", "confidence": "high" },
  "model": { "value": "Civic", "nhtsaValue": "Civic", "confidence": "high" },
  "trimLevel": { "value": "EX", "nhtsaValue": "EX", "confidence": "high" },
  "engine": { "value": null, "nhtsaValue": "2.0L L4 DOHC 16V", "confidence": "none" },
  "transmission": { "value": null, "nhtsaValue": "CVT", "confidence": "none" },
  "bodyType": { "value": null, "nhtsaValue": "Sedan", "confidence": "none" },
  "driveType": { "value": null, "nhtsaValue": "FWD", "confidence": "none" },
  "fuelType": { "value": null, "nhtsaValue": "Gasoline", "confidence": "none" }
}

Error (400 - Invalid VIN):
{ "error": "INVALID_VIN", "message": "Invalid VIN format. VIN must be..." }

Error (403 - Tier Required):
{ "error": "TIER_REQUIRED", "requiredTier": "pro", "currentTier": "free", ... }

Error (502 - NHTSA Failure):
{ "error": "VIN_DECODE_FAILED", "message": "Unable to decode VIN from external service" }

📋 Hierarchical Vehicle Dropdowns

  • Platform Service: Consumes year-based hierarchical vehicle API
  • Performance: < 100ms response times via platform service caching
  • Parameters: Hierarchical filtering (year → make → model → trims/engines/transmissions)
  • Circuit Breaker: Graceful degradation with cached fallbacks

🏗️ Database Schema

  • Primary Table: vehicles with soft delete
  • Indexes: Optimized for user queries and VIN lookups
  • Constraints: Unique VIN per user, proper foreign keys
  • Platform Integration: No duplicate caching - relies on platform service

🚀 Performance Optimizations

  • Redis Caching: User vehicle lists cached for 5 minutes
  • Platform Service: Offloads heavy VIN decoding and vehicle data caching
  • Circuit Breaker: Prevents cascading failures with fallback responses
  • Indexes: Strategic database indexes for fast user queries
  • Soft Deletes: Maintains referential integrity

Business Rules

VIN Validation

  • Must be exactly 17 characters
  • Cannot contain letters I, O, or Q
  • Must pass basic checksum validation
  • Auto-populates make, model, year from MVP Platform Vehicles Service

User Ownership

  • Each user can have multiple vehicles
  • Same VIN cannot be registered twice by same user
  • All operations validate user ownership
  • Soft delete preserves data for audit trail

Dependencies

Internal Core Services

  • core/auth - JWT authentication middleware
  • core/config - Database pool, Redis cache
  • core/logging - Structured logging with Winston
  • shared-minimal/utils - Pure validation utilities

Platform Services

  • MVP Platform Vehicles Service - VIN decoding and hierarchical vehicle data
  • PostgreSQL - Primary data storage
  • Redis - Caching layer

Database Tables

  • vehicles - Primary vehicle data

Caching Strategy

Platform Service Caching

  • VIN Decoding: Handled entirely by MVP Platform Vehicles Service
  • Hierarchical Data: Year-based caching strategy managed by platform service
  • Performance: < 100ms responses via platform service optimization

User Vehicle List (5 minutes)

  • Key: vehicles:user:{userId}
  • TTL: 300 seconds (5 minutes)
  • Invalidation: On create, update, delete

Platform Service Integration

  • Circuit Breaker: Prevent cascading failures
  • Fallback Strategy: Cached responses when platform service unavailable
  • Timeout: 3 second timeout with automatic retry

Testing

Unit Tests

  • vehicles.service.test.ts - Business logic with mocked dependencies (VIN decode, caching, CRUD operations)

Integration Tests

  • vehicles.integration.test.ts - Complete API workflow with test database (create, read, update, delete vehicles)

Run Tests

# All vehicle tests
npm test -- features/vehicles

# Unit tests only
npm test -- features/vehicles/tests/unit

# Integration tests only  
npm test -- features/vehicles/tests/integration

# With coverage
npm test -- features/vehicles --coverage

Error Handling

Client Errors (4xx)

  • 400 - Invalid VIN format, validation errors
  • 401 - Missing or invalid JWT token
  • 403 - User not authorized for vehicle
  • 404 - Vehicle not found
  • 409 - Duplicate VIN for user

Server Errors (5xx)

  • 500 - Database connection, platform service failures
  • 503 - Platform service unavailable (circuit breaker open)
  • Graceful degradation when platform service unavailable

Future Considerations

Dependent Features

  • fuel-logs - Will reference vehicle_id
  • maintenance - Will reference vehicle_id
  • Both features depend on vehicles as primary entity

Potential Enhancements

  • Vehicle image uploads (filesystem storage integration)
  • Enhanced platform service integration for real-time updates
  • Vehicle value estimation via additional platform services
  • Maintenance scheduling based on vehicle age/mileage
  • Advanced dropdown features (trim-specific engines/transmissions)

Development Commands

# Run migrations
make migrate

# Start environment
make start

# View feature logs
make logs-backend | grep vehicles

# Open container shell
make shell-backend

# Inside container - run feature tests
npm test -- features/vehicles