From 2cc9cc5f9f65d98dbd0ccf8216dfd03616ce47ad Mon Sep 17 00:00:00 2001
From: Eric Gullickson <16152721+ericgullickson@users.noreply.github.com>
Date: Mon, 3 Nov 2025 14:18:25 -0600
Subject: [PATCH] Gas Station Prep
---
docs/GAS-STATION-AGENTS.md | 1118 ++++++++++++++++++++++
docs/GAS-STATIONS.md | 648 +++++++++++++
docs/PLATFORM-INTEGRATION-AGENTS.md | 1189 ------------------------
docs/PLATFORM-INTEGRATION-MIGRATION.md | 252 -----
docs/PLATFORM-INTEGRATION-TESTING.md | 335 -------
5 files changed, 1766 insertions(+), 1776 deletions(-)
create mode 100644 docs/GAS-STATION-AGENTS.md
create mode 100644 docs/GAS-STATIONS.md
delete mode 100644 docs/PLATFORM-INTEGRATION-AGENTS.md
delete mode 100644 docs/PLATFORM-INTEGRATION-MIGRATION.md
delete mode 100644 docs/PLATFORM-INTEGRATION-TESTING.md
diff --git a/docs/GAS-STATION-AGENTS.md b/docs/GAS-STATION-AGENTS.md
new file mode 100644
index 0000000..45a1b56
--- /dev/null
+++ b/docs/GAS-STATION-AGENTS.md
@@ -0,0 +1,1118 @@
+# Gas Stations Feature - Parallel Agent Execution Plan
+
+## Overview
+
+This document contains agent definition prompts for implementing the Gas Stations feature using parallel execution. The backend API is complete; this plan focuses on frontend implementation, backend improvements, and integration.
+
+### Key Context
+- Backend API: Fully implemented at `backend/src/features/stations/`
+- Frontend: Completely missing (needs full implementation)
+- Database: Schema ready, needs migration execution
+- Secrets: Google Maps API key exists in `secrets/app/google-maps-api-key.txt`
+- Pattern: Follow K8s-aligned runtime secrets (not build-time env vars)
+- Reference: Use `frontend/src/features/vehicles/` as implementation pattern
+
+### Investigation Summary
+- Backend has 4 complete API endpoints (search, save, get saved, delete)
+- Database migration ready: `001_create_stations_tables.sql`
+- External integration: Google Maps Places API client implemented
+- No frontend code exists yet (placeholder route only)
+- No tests exist (empty directories)
+- No circuit breaker or cache cleanup implemented
+
+## Execution Phases
+
+```
+Phase 1 (Parallel - Infrastructure):
+├─ Agent 1: Frontend-Secrets-Agent
+└─ Agent 2: Backend-Reliability-Agent
+
+Phase 2 (Foundation):
+└─ Agent 3: Frontend-Foundation-Agent (depends on Agent 1)
+
+Phase 3 (Parallel - Components):
+├─ Agent 4: Components-Agent (depends on Agent 3)
+└─ Agent 5: Map-Visualization-Agent (depends on Agent 3)
+
+Phase 4 (Parallel - Pages):
+├─ Agent 6: Desktop-Mobile-Agent (depends on Agents 4, 5)
+└─ Agent 7: Integration-Agent (depends on Agents 4, 5)
+
+Phase 5 (Testing):
+└─ Agent 8: Testing-Documentation-Agent (depends on all previous)
+```
+
+---
+
+## Agent 1: Frontend-Secrets-Agent
+
+### Scope
+Implement K8s-aligned runtime secrets pattern for frontend to load Google Maps API key from `/run/secrets/` at container startup.
+
+### Prerequisites
+- None (can start immediately)
+
+### Responsibilities
+
+1. **Create Frontend Config Loader Script**
+ - File: `frontend/scripts/load-config.sh`
+ - Reads `/run/secrets/google-maps-api-key`
+ - Generates `/usr/share/nginx/html/config.js` with: `window.CONFIG = { googleMapsApiKey: 'KEY_VALUE' }`
+ - Fallback to empty string if secret not found
+ - Logs success/failure for debugging
+
+2. **Update Frontend Dockerfile**
+ - File: `frontend/Dockerfile`
+ - Copy `scripts/load-config.sh` into image
+ - Make script executable
+ - Add `SECRETS_DIR` environment variable (default: `/run/secrets`)
+ - Update CMD to: `["sh", "-c", "/app/load-config.sh && nginx -g 'daemon off;'"]`
+
+3. **Update index.html**
+ - File: `frontend/index.html`
+ - Add `` before app bundle script tag
+ - Ensure config loads synchronously before React initializes
+
+4. **Create Frontend Config Types**
+ - File: `frontend/src/core/config/config.types.ts`
+ - Interface: `RuntimeConfig { googleMapsApiKey: string }`
+ - Extend Window interface: `declare global { interface Window { CONFIG: RuntimeConfig } }`
+ - Export typed accessor: `export function getConfig(): RuntimeConfig`
+ - Runtime validation: throw if required values missing
+
+5. **Update docker-compose.yml**
+ - File: `docker-compose.yml`
+ - Add to `mvp-frontend` service volumes:
+ ```yaml
+ - ./secrets/app/google-maps-api-key.txt:/run/secrets/google-maps-api-key:ro
+ ```
+ - Add environment variable: `SECRETS_DIR: /run/secrets`
+
+6. **Create Documentation**
+ - File: `frontend/docs/RUNTIME-CONFIG.md`
+ - Explain runtime config pattern vs build-time
+ - How to add new runtime secrets
+ - K8s deployment notes
+ - Local development setup
+
+### Success Criteria
+- Frontend container starts successfully
+- `/usr/share/nginx/html/config.js` exists and contains API key
+- `getConfig()` returns typed RuntimeConfig object
+- No TypeScript errors
+- Linters pass
+
+### Handoff Notes
+Provides `getConfig().googleMapsApiKey` for Agent 5 (Map-Visualization-Agent) to use when loading Google Maps JavaScript API.
+
+---
+
+## Agent 2: Backend-Reliability-Agent
+
+### Scope
+Enhance backend reliability with circuit breaker, comprehensive tests, and cache cleanup job.
+
+### Prerequisites
+- None (can start immediately)
+
+### Responsibilities
+
+1. **Add Circuit Breaker Pattern**
+ - Install package: Add `"opossum": "^8.1.4"` to `backend/package.json`
+ - File: `backend/src/features/stations/external/google-maps/google-maps.circuit-breaker.ts`
+ - Create circuit breaker factory function
+ - Configuration: 10s timeout, 50% error threshold, 30s reset timeout
+ - Update: `backend/src/features/stations/external/google-maps/google-maps.client.ts`
+ - Wrap `searchNearby()` method with circuit breaker
+ - Follow pattern from `backend/src/features/platform/` (reference implementation)
+ - Add circuit breaker events logging (open, close, halfOpen)
+
+2. **Backend Unit Tests**
+ - File: `backend/src/features/stations/tests/unit/stations.service.test.ts`
+ - Test searchStations() with valid coordinates
+ - Test saveStation() with user_id isolation
+ - Test getSavedStations() returns only user's stations
+ - Test deleteSavedStation() removes correct station
+ - File: `backend/src/features/stations/tests/unit/stations.repository.test.ts`
+ - Test database queries with mock connection
+ - Test SQL injection protection
+ - Test constraint violations (duplicate saves)
+ - File: `backend/src/features/stations/tests/unit/google-maps.client.test.ts`
+ - Mock Google Maps API responses
+ - Test distance calculation (Haversine formula)
+ - Test photo URL generation
+ - Test error handling
+
+3. **Backend Integration Tests**
+ - File: `backend/src/features/stations/tests/integration/stations.api.test.ts`
+ - Test all 4 endpoints with real database
+ - Test JWT authentication requirement
+ - Test request validation (Zod schemas)
+ - Test error responses (400, 401, 500)
+ - File: `backend/src/features/stations/tests/integration/saved-stations.flow.test.ts`
+ - Test complete workflow: search → save → retrieve → delete
+ - Test duplicate save handling
+ - Test user isolation (user A can't see user B's stations)
+
+4. **Test Fixtures**
+ - File: `backend/src/features/stations/tests/fixtures/mock-stations.ts`
+ - Export sample Station objects (5-10 examples)
+ - Include various ratings, distances, prices
+ - File: `backend/src/features/stations/tests/fixtures/mock-google-response.ts`
+ - Mock Google Places API responses
+ - Include success and error cases
+ - File: `backend/src/features/stations/tests/fixtures/test-coordinates.ts`
+ - Sample coordinates for major cities
+ - Edge cases (equator, poles, date line)
+
+5. **Cache Cleanup Job**
+ - File: `backend/src/features/stations/jobs/cache-cleanup.job.ts`
+ - Scheduled job using cron (daily at 2 AM)
+ - Delete `station_cache` entries older than 24 hours
+ - Log metrics: rows deleted, execution time
+ - Error handling and retry logic
+ - Update: `backend/src/app.ts`
+ - Import and register cache cleanup job
+ - Add to scheduler (if exists) or create simple interval
+
+6. **Run Tests**
+ - Execute: `cd backend && npm test -- features/stations`
+ - Verify 100% pass rate
+ - Check coverage (aim for >80%)
+
+### Success Criteria
+- Circuit breaker implemented and tested
+- All unit tests pass
+- All integration tests pass
+- Test coverage >80%
+- Cache cleanup job registered
+- Linters pass
+- No TypeScript errors
+
+### Handoff Notes
+Backend is now production-ready with reliability patterns. Tests provide safety net for future changes.
+
+---
+
+## Agent 3: Frontend-Foundation-Agent
+
+### Scope
+Create frontend foundation: types, API client, and React Query hooks for stations feature.
+
+### Prerequisites
+- **Depends on Agent 1** (needs `getConfig()` function)
+
+### Responsibilities
+
+1. **Type Definitions**
+ - File: `frontend/src/features/stations/types/stations.types.ts`
+ - Interface `Station`:
+ - placeId: string
+ - name: string
+ - address: string
+ - location: { latitude: number; longitude: number }
+ - rating?: number
+ - distance: number (meters)
+ - photoUrl?: string
+ - prices?: { fuel_type: string; price: number }[]
+ - Interface `SavedStation` extends Station:
+ - userId: string
+ - nickname?: string
+ - notes?: string
+ - isFavorite: boolean
+ - savedAt: string
+ - Interface `SearchRequest`:
+ - latitude: number
+ - longitude: number
+ - radius?: number (meters, default 5000)
+ - fuelType?: string
+ - Interface `SearchResponse`:
+ - stations: Station[]
+ - searchLocation: { latitude: number; longitude: number }
+ - Interface `SaveStationData`:
+ - placeId: string
+ - nickname?: string
+ - notes?: string
+ - isFavorite?: boolean
+
+2. **API Client**
+ - File: `frontend/src/features/stations/api/stations.api.ts`
+ - Function `searchStations(request: SearchRequest): Promise`
+ - POST /api/stations/search
+ - Include JWT in Authorization header
+ - Return stations array
+ - Function `saveStation(data: SaveStationData): Promise`
+ - POST /api/stations/save
+ - Include JWT in Authorization header
+ - Return saved station with full details
+ - Function `getSavedStations(): Promise`
+ - GET /api/stations/saved
+ - Include JWT in Authorization header
+ - Return array of user's saved stations
+ - Function `deleteSavedStation(placeId: string): Promise`
+ - DELETE /api/stations/saved/:placeId
+ - Include JWT in Authorization header
+ - Return nothing (204 No Content)
+ - Use axios instance from `frontend/src/core/api/client.ts`
+ - Proper error handling with try-catch
+ - Add request/response logging for debugging
+
+3. **React Query Hooks**
+ - File: `frontend/src/features/stations/hooks/useStationsSearch.ts`
+ - Export `useStationsSearch()` mutation hook
+ - Accepts SearchRequest, returns Station[]
+ - Don't cache by default (location-specific queries)
+ - Loading/error states
+ - File: `frontend/src/features/stations/hooks/useSavedStations.ts`
+ - Export `useSavedStations()` query hook
+ - Query key: `['stations', 'saved']`
+ - Auto-refetch on window focus
+ - Stale time: 5 minutes
+ - Loading/error states
+ - File: `frontend/src/features/stations/hooks/useSaveStation.ts`
+ - Export `useSaveStation()` mutation hook
+ - Accepts SaveStationData
+ - Optimistic update: add to saved list immediately
+ - On success: invalidate `['stations', 'saved']` query
+ - On error: rollback optimistic update
+ - File: `frontend/src/features/stations/hooks/useDeleteStation.ts`
+ - Export `useDeleteStation()` mutation hook
+ - Accepts placeId string
+ - Optimistic update: remove from saved list
+ - On success: invalidate `['stations', 'saved']` query
+ - On error: rollback optimistic update
+ - File: `frontend/src/features/stations/hooks/useGeolocation.ts`
+ - Export `useGeolocation()` hook
+ - Uses browser Geolocation API
+ - Returns: `{ position, loading, error, requestLocation }`
+ - Handle permission states: prompt, granted, denied
+ - Error handling: timeout, unavailable, permission denied
+ - Options: enableHighAccuracy, timeout, maximumAge
+
+4. **Utilities**
+ - File: `frontend/src/features/stations/utils/distance.ts`
+ - Export `formatDistance(meters: number): string`
+ - Convert meters to miles with proper formatting
+ - Examples: "0.3 mi", "1.2 mi", "5.7 mi"
+ - File: `frontend/src/features/stations/utils/location.ts`
+ - Export `getCurrentPosition(): Promise`
+ - Wrapper around navigator.geolocation.getCurrentPosition
+ - Promisified API
+ - Error handling helpers
+
+### Success Criteria
+- All type interfaces defined with proper TypeScript types
+- API client functions work (test with curl against backend)
+- All React Query hooks created with proper caching
+- Geolocation hook handles all permission states
+- No TypeScript errors
+- Linters pass
+- Utilities properly format data
+
+### Handoff Notes
+Foundation is complete. Agent 4 and Agent 5 can now build components and map visualization using these types, API client, and hooks.
+
+---
+
+## Agent 4: Components-Agent
+
+### Scope
+Build all React components for stations feature (cards, lists, forms).
+
+### Prerequisites
+- **Depends on Agent 3** (needs types, hooks, API client)
+
+### Responsibilities
+
+1. **StationCard Component**
+ - File: `frontend/src/features/stations/components/StationCard.tsx`
+ - Props:
+ - station: Station
+ - isSaved?: boolean
+ - onSave?: (placeId: string) => void
+ - onDelete?: (placeId: string) => void
+ - onSelect?: (station: Station) => void
+ - UI Elements:
+ - Material-UI Card component
+ - Station name (Typography variant="h6")
+ - Address (Typography variant="body2", color="text.secondary")
+ - Distance chip (Chip with LocationOnIcon)
+ - Rating stars (Rating component, if rating exists)
+ - Price display (Typography, if prices available)
+ - Photo thumbnail (CardMedia, if photoUrl exists)
+ - Save/Unsave IconButton (BookmarkIcon / BookmarkBorderIcon)
+ - Directions link (Button with OpenInNewIcon, opens Google Maps)
+ - Styling:
+ - Responsive: full width on mobile, fixed width on desktop
+ - Min height 44px for touch targets
+ - Hover effects on desktop
+ - Loading state while saving/deleting
+ - Follow pattern: `frontend/src/features/vehicles/components/VehicleCard.tsx`
+
+2. **StationsList Component**
+ - File: `frontend/src/features/stations/components/StationsList.tsx`
+ - Props:
+ - stations: Station[]
+ - loading?: boolean
+ - error?: Error | null
+ - onSaveStation?: (placeId: string) => void
+ - savedStationIds?: Set
+ - UI Elements:
+ - Grid container (responsive)
+ - Layout: 1 col mobile, 2 cols tablet, 3 cols desktop
+ - Loading state: Skeleton components (3-6 skeletons)
+ - Empty state: "No stations found. Try adjusting your search."
+ - Error state: Alert with retry option
+ - Map stations to StationCard components
+ - Styling:
+ - Gap between cards: 16px
+ - Smooth loading transitions
+ - Follow pattern: `frontend/src/features/vehicles/components/VehiclesList.tsx`
+
+3. **SavedStationsList Component**
+ - File: `frontend/src/features/stations/components/SavedStationsList.tsx`
+ - Props:
+ - savedStations: SavedStation[]
+ - loading?: boolean
+ - error?: Error | null
+ - onDelete: (placeId: string) => void
+ - onSelect?: (station: SavedStation) => void
+ - currentLocation?: { latitude: number; longitude: number }
+ - UI Elements:
+ - List container (vertical)
+ - Each item shows: nickname || name, address, distance from current location
+ - Notes preview (truncated to 50 chars)
+ - Favorite icon if isFavorite
+ - Delete IconButton with confirmation dialog
+ - Loading state: Linear progress bar
+ - Empty state: "No saved stations yet. Save stations from search results."
+ - Error state: Alert with error message
+ - Styling:
+ - List item min height: 64px
+ - Dividers between items
+ - Delete button always visible (not just on hover for mobile)
+ - Follow pattern: Material-UI List component examples
+
+4. **StationsSearchForm Component**
+ - File: `frontend/src/features/stations/components/StationsSearchForm.tsx`
+ - Props:
+ - onSearch: (request: SearchRequest) => void
+ - loading?: boolean
+ - UI Elements:
+ - Form container (Card or Paper)
+ - "Use Current Location" Button (uses useGeolocation hook)
+ - OR divider
+ - Manual lat/lng inputs (TextField type="number")
+ - Radius slider (Slider: 1-25 miles, default 5, step 1)
+ - Fuel type select (optional, Select component)
+ - Search LoadingButton (shows loading state during search)
+ - Geolocation status indicator (permission state)
+ - Error display for geolocation failures
+ - Validation:
+ - Require either current location OR manual lat/lng
+ - Validate latitude: -90 to 90
+ - Validate longitude: -180 to 180
+ - Behavior:
+ - Click "Use Current Location" → request permission → populate hidden lat/lng
+ - Manual input disables current location
+ - Convert miles to meters for API (1 mile = 1609.34 meters)
+ - Styling:
+ - Compact form layout
+ - Responsive: stack vertically on mobile
+ - Clear visual feedback for loading states
+ - Follow pattern: `frontend/src/features/fuel-logs/components/FuelLogForm.tsx`
+
+5. **Create Feature Index**
+ - File: `frontend/src/features/stations/components/index.ts`
+ - Export all components for easy importing
+
+### Success Criteria
+- All 4 components render without errors
+- Components follow Material-UI design patterns
+- Mobile responsive (test at 375px width)
+- Touch targets minimum 44px
+- Loading and error states work
+- TypeScript types are correct
+- Linters pass
+- Components match vehicles feature pattern
+
+### Handoff Notes
+Core components are ready. Agent 6 can now build pages using these components. Agent 7 can integrate with map visualization.
+
+---
+
+## Agent 5: Map-Visualization-Agent
+
+### Scope
+Implement Google Maps integration and StationMap component for visualizing stations on a map.
+
+### Prerequisites
+- **Depends on Agent 1** (needs `getConfig().googleMapsApiKey`)
+- **Depends on Agent 3** (needs Station types)
+
+### Responsibilities
+
+1. **Google Maps API Loader**
+ - File: `frontend/src/features/stations/utils/maps-loader.ts`
+ - Function: `loadGoogleMapsAPI(): Promise`
+ - Load Google Maps JavaScript API dynamically
+ - Use runtime config: `getConfig().googleMapsApiKey`
+ - Include libraries: `libraries=places,geometry`
+ - Singleton pattern: only load once, return cached promise
+ - Error handling: throw if API key missing or script fails
+ - TypeScript: Use `@types/google.maps` for types
+
+2. **Map Utilities**
+ - File: `frontend/src/features/stations/utils/map-utils.ts`
+ - Function: `createStationMarker(station: Station, map: google.maps.Map, isSaved: boolean): google.maps.Marker`
+ - Create marker at station location
+ - Icon: blue pin for normal, gold star for saved
+ - Title: station name
+ - Clickable: true
+ - Function: `createInfoWindow(station: Station, isSaved: boolean, onSave: () => void, onDirections: () => void): google.maps.InfoWindow`
+ - Create info window with station details
+ - Content: name, address, rating, distance
+ - Action buttons: Save/Saved, Directions
+ - HTML string with proper escaping
+ - Function: `fitBoundsToMarkers(map: google.maps.Map, markers: google.maps.Marker[]): void`
+ - Calculate bounds containing all markers
+ - Fit map to bounds with padding
+ - Handle single marker case (zoom to 14)
+ - Function: `calculateCenter(stations: Station[]): google.maps.LatLng`
+ - Calculate geometric center of stations
+ - Return LatLng object
+
+3. **StationMap Component**
+ - File: `frontend/src/features/stations/components/StationMap.tsx`
+ - Props:
+ - stations: Station[]
+ - savedStationIds?: Set
+ - center?: { latitude: number; longitude: number }
+ - zoom?: number
+ - currentLocation?: { latitude: number; longitude: number }
+ - onStationClick?: (station: Station) => void
+ - onSaveStation?: (placeId: string) => void
+ - State:
+ - map: google.maps.Map | null
+ - markers: google.maps.Marker[]
+ - infoWindow: google.maps.InfoWindow | null
+ - Behavior:
+ - Load Google Maps API on mount (useEffect)
+ - Initialize map in div container
+ - Create markers for all stations
+ - Current location marker (red pin, if provided)
+ - Click marker → open info window
+ - Click save button → call onSaveStation
+ - Click directions → open Google Maps in new tab
+ - Auto-fit bounds to show all markers
+ - Clean up markers on unmount
+ - Styling:
+ - Container: width 100%, height configurable (default 500px)
+ - Responsive: 300px height on mobile, 500px on desktop
+ - Map controls: zoom, pan, fullscreen
+ - Custom map styles (optional: subtle styling)
+ - Map Options:
+ - mapTypeControl: false
+ - streetViewControl: false
+ - fullscreenControl: true
+ - zoomControl: true
+ - Error Handling:
+ - Show error message if API fails to load
+ - Fallback: display stations in list if map unavailable
+
+4. **TypeScript Types**
+ - Ensure `@types/google.maps` is in `frontend/package.json`
+ - Add if missing: `"@types/google.maps": "^3.54.0"`
+
+5. **Testing**
+ - Test map loads with valid API key
+ - Test markers render for each station
+ - Test info windows open on marker click
+ - Test current location marker (red pin)
+ - Test directions link opens correct URL
+ - Test error handling (invalid API key)
+
+### Success Criteria
+- Google Maps API loads successfully from runtime config
+- StationMap component renders map
+- Markers appear for all stations
+- Color coding works (blue vs gold for saved)
+- Info windows display correct station details
+- Directions links work
+- Current location marker shows if provided
+- Responsive sizing works
+- No TypeScript errors
+- Linters pass
+
+### Handoff Notes
+Map visualization is complete. Agent 6 can integrate StationMap into desktop and mobile pages.
+
+---
+
+## Agent 6: Desktop-Mobile-Agent
+
+### Scope
+Build desktop StationsPage and mobile StationsMobileScreen, update routing.
+
+### Prerequisites
+- **Depends on Agent 4** (needs all components)
+- **Depends on Agent 5** (needs StationMap)
+
+### Responsibilities
+
+1. **Desktop StationsPage**
+ - File: `frontend/src/features/stations/pages/StationsPage.tsx`
+ - Layout:
+ - Container: Full width, Grid layout
+ - Left column (60%): StationMap (full height 600px)
+ - Right column (40%):
+ - StationsSearchForm at top
+ - Tabs component: "Search Results" | "Saved Stations"
+ - Tab 1 content: StationsList (scrollable)
+ - Tab 2 content: SavedStationsList (scrollable)
+ - State:
+ - searchResults: Station[] (from useStationsSearch)
+ - selectedStation: Station | null (for map focus)
+ - currentLocation: Position | null (from useGeolocation)
+ - activeTab: 0 | 1
+ - Hooks:
+ - useStationsSearch() for searching
+ - useSavedStations() for saved list
+ - useSaveStation() for saving
+ - useDeleteStation() for deleting
+ - useGeolocation() for current location
+ - Behavior:
+ - On search submit → call searchStations mutation
+ - On search success → update map with results
+ - On save station → add to saved list (optimistic)
+ - On delete station → remove from saved list (optimistic)
+ - Click station card → highlight on map (zoom to marker)
+ - Map marker click → highlight card and scroll into view
+ - Responsive:
+ - Breakpoint <960px: Stack vertically (map on top)
+ - Mobile view: Map 300px height, full width
+ - Loading States:
+ - Show loading spinner during search
+ - Skeleton loaders for saved stations
+ - Error Handling:
+ - Display error alerts for API failures
+ - Retry buttons where appropriate
+ - Follow pattern: `frontend/src/features/vehicles/pages/VehiclesPage.tsx`
+
+2. **Mobile StationsScreen**
+ - File: `frontend/src/features/stations/pages/StationsMobileScreen.tsx`
+ - Layout:
+ - BottomNavigation with 3 tabs: "Search", "Saved", "Map"
+ - Tab content area (full screen minus bottom nav)
+ - Tab 0 (Search):
+ - StationsSearchForm (compact mode, vertical layout)
+ - StationsList (vertical scroll, full width)
+ - Pull-to-refresh support (optional)
+ - Tab 1 (Saved):
+ - SavedStationsList (full screen)
+ - Swipe-to-delete gestures (optional enhancement)
+ - Empty state with illustration
+ - Tab 2 (Map):
+ - StationMap (full screen, 100vh minus nav)
+ - Floating action button (FAB) to return to search tab
+ - Current location button (FAB)
+ - State:
+ - activeTab: 0 | 1 | 2
+ - Same data state as desktop page
+ - Hooks:
+ - Same as desktop page
+ - Behavior:
+ - Tab switching persists scroll position
+ - Search → auto-switch to results view
+ - Save station → show snackbar confirmation
+ - Map marker click → open bottom sheet with station details
+ - Bottom Sheet:
+ - SwipeableDrawer component
+ - Shows station details
+ - Save/Delete buttons
+ - Directions link
+ - Touch Targets:
+ - All buttons minimum 44px
+ - Adequate spacing between interactive elements
+ - Safe Areas:
+ - Handle notched devices (safe-area-inset)
+ - Bottom navigation respects safe area
+ - Follow pattern: `frontend/src/features/vehicles/pages/VehiclesMobileScreen.tsx`
+
+3. **Update Desktop Routing**
+ - File: `frontend/src/App.tsx` (around line 556)
+ - Remove: `Stations (TODO)} />`
+ - Add: `} />`
+ - Import: `import { StationsPage } from './features/stations/pages/StationsPage'`
+ - Verify route is inside ProtectedRoute wrapper (requires auth)
+
+4. **Update Mobile Routing**
+ - File: `frontend/src/App.tsx` (mobile routes section)
+ - Add: `} />`
+ - Import: `import { StationsMobileScreen } from './features/stations/pages/StationsMobileScreen'`
+ - Update mobile navigation items:
+ - Add stations icon and route to bottom nav
+ - Icon: PlaceRoundedIcon (already used in Layout.tsx)
+ - Ensure onClick navigates to `/m/stations`
+
+5. **Feature Index**
+ - File: `frontend/src/features/stations/index.ts`
+ - Export StationsPage and StationsMobileScreen
+ - Export all components for external use
+
+6. **Manual Testing**
+ - Desktop: Navigate to /stations, test all functionality
+ - Mobile: Navigate to /m/stations, test all tabs
+ - Test on real mobile device or Chrome DevTools mobile emulation
+ - Verify responsive breakpoints work
+ - Verify touch targets are adequate (44px minimum)
+
+### Success Criteria
+- Desktop page renders and functions completely
+- Mobile screen renders with all 3 tabs
+- Routing works for both desktop and mobile
+- All components integrate properly
+- Search, save, delete operations work
+- Map updates when data changes
+- Mobile touch targets meet 44px requirement
+- Responsive design works at all breakpoints
+- No TypeScript errors
+- Linters pass
+
+### Handoff Notes
+Desktop and mobile UIs are complete and fully functional. Users can now search, save, and view stations on both platforms.
+
+---
+
+## Agent 7: Integration-Agent
+
+### Scope
+Integrate stations feature with fuel logs using a station picker component.
+
+### Prerequisites
+- **Depends on Agent 4** (needs StationCard and search functionality)
+- **Depends on Agent 5** (needs map utilities)
+
+### Responsibilities
+
+1. **StationPicker Component**
+ - File: `frontend/src/features/fuel-logs/components/StationPicker.tsx`
+ - Props:
+ - value: string (station name)
+ - onChange: (stationName: string) => void
+ - userLocation?: { latitude: number; longitude: number }
+ - label?: string
+ - error?: boolean
+ - helperText?: string
+ - UI Elements:
+ - Autocomplete component (Material-UI)
+ - TextField with LocationOnIcon adornment
+ - Dropdown shows: saved stations (group 1) + nearby stations (group 2)
+ - Option rendering:
+ - Primary text: station name
+ - Secondary text: distance + address
+ - Bookmark icon if saved
+ - FreeSolo mode: allow manual text entry
+ - Loading indicator while fetching stations
+ - Behavior:
+ - On focus → fetch saved stations immediately
+ - If userLocation provided → fetch nearby stations (5 mile radius)
+ - Show saved stations first (grouped, labeled "Saved Stations")
+ - Show nearby stations second (grouped, labeled "Nearby Stations")
+ - On select → call onChange with station name
+ - On manual input → call onChange with entered text
+ - Debounce: 300ms delay for search queries
+ - Data:
+ - Use useSavedStations() hook
+ - Use useStationsSearch() hook with userLocation
+ - Combine results: saved + nearby
+ - De-duplicate by placeId
+ - Error Handling:
+ - If geolocation fails → only show saved stations
+ - If API fails → fallback to manual text input
+ - Display error message in helper text
+ - Follow pattern: Material-UI Autocomplete with grouping
+
+2. **Update FuelLogForm**
+ - File: `frontend/src/features/fuel-logs/components/FuelLogForm.tsx`
+ - Find: Current location input field (likely TextField or LocationInput component)
+ - Replace with: StationPicker component
+ - Props to pass:
+ - value: formData.stationName (or equivalent)
+ - onChange: (name) => setFormData({ ...formData, stationName: name })
+ - userLocation: from useGeolocation hook
+ - label: "Gas Station"
+ - error: Boolean(errors.stationName)
+ - helperText: errors.stationName
+ - Integration:
+ - Add useGeolocation hook to FuelLogForm
+ - Pass current position to StationPicker
+ - Maintain existing form validation
+ - Ensure backward compatibility (text input still works)
+
+3. **Enhance Fuel Log Display (Optional)**
+ - File: `frontend/src/features/fuel-logs/components/FuelLogCard.tsx`
+ - If stationName is present → make it clickable
+ - On click → navigate to /stations with search for that name
+ - OR: Show station details in dialog
+ - Add LocationOnIcon next to station name
+ - Follow existing card styling
+
+4. **Add Geolocation to Fuel Logs**
+ - Update FuelLogForm to request location permission on mount
+ - Store current location in component state
+ - Pass to StationPicker for nearby stations
+ - Show permission request UI if needed
+ - Handle permission denied gracefully (picker still works with saved stations)
+
+5. **Testing**
+ - Test StationPicker in isolation (render component)
+ - Test selecting saved station
+ - Test selecting nearby station
+ - Test manual text entry (freeSolo)
+ - Test integration in FuelLogForm
+ - Test submitting fuel log with station
+ - Test geolocation permission flow
+
+### Success Criteria
+- StationPicker component renders and functions
+- Saved stations appear in dropdown
+- Nearby stations appear in dropdown (if location available)
+- Manual text entry works (fallback)
+- FuelLogForm integrates StationPicker successfully
+- Submitting fuel log with station works
+- Backward compatible (existing fuel logs still display)
+- Geolocation permission handled gracefully
+- No TypeScript errors
+- Linters pass
+
+### Handoff Notes
+Fuel logs now integrate with stations feature. Users can select stations from saved or nearby lists when logging fuel, improving data consistency and user experience.
+
+---
+
+## Agent 8: Testing-Documentation-Agent
+
+### Scope
+Create comprehensive tests for all new code and complete documentation.
+
+### Prerequisites
+- **Depends on all previous agents** (needs complete implementation)
+
+### Responsibilities
+
+1. **Backend Tests Verification**
+ - Run: `cd backend && npm test -- features/stations`
+ - Verify all tests pass (from Agent 2)
+ - If failures: debug and fix
+ - Check coverage: `npm test -- --coverage features/stations`
+ - Ensure coverage >80%
+
+2. **Frontend Component Tests**
+ - File: `frontend/src/features/stations/__tests__/components/StationCard.test.tsx`
+ - Test rendering with all props
+ - Test save button click
+ - Test delete button click
+ - Test directions link
+ - File: `frontend/src/features/stations/__tests__/components/StationsList.test.tsx`
+ - Test rendering with stations array
+ - Test loading state (skeletons)
+ - Test empty state
+ - Test error state
+ - File: `frontend/src/features/stations/__tests__/components/SavedStationsList.test.tsx`
+ - Test rendering saved stations
+ - Test delete action
+ - Test empty state
+ - File: `frontend/src/features/stations/__tests__/components/StationsSearchForm.test.tsx`
+ - Test form submission
+ - Test validation (lat/lng ranges)
+ - Test current location button
+ - Test manual input
+ - File: `frontend/src/features/stations/__tests__/components/StationMap.test.tsx`
+ - Mock Google Maps API
+ - Test map initialization
+ - Test marker rendering
+ - Test info window
+ - Use React Testing Library
+ - Mock hooks with jest.mock()
+
+3. **Frontend API Tests**
+ - File: `frontend/src/features/stations/api/__tests__/stations.api.test.ts`
+ - Test searchStations() - mock axios
+ - Test saveStation() - mock axios
+ - Test getSavedStations() - mock axios
+ - Test deleteSavedStation() - mock axios
+ - Test error handling (network errors, 401, 500)
+ - Verify request payloads
+ - Verify response parsing
+
+4. **Frontend Hook Tests**
+ - File: `frontend/src/features/stations/hooks/__tests__/useStationsSearch.test.ts`
+ - Test mutation flow
+ - Test loading state
+ - Test success state
+ - Test error state
+ - File: `frontend/src/features/stations/hooks/__tests__/useSavedStations.test.ts`
+ - Test query flow
+ - Test cache behavior
+ - Test refetch logic
+ - File: `frontend/src/features/stations/hooks/__tests__/useSaveStation.test.ts`
+ - Test mutation with optimistic update
+ - Test cache invalidation
+ - Test rollback on error
+ - File: `frontend/src/features/stations/hooks/__tests__/useDeleteStation.test.ts`
+ - Test mutation with optimistic update
+ - Test cache invalidation
+ - Test rollback on error
+ - Use @testing-library/react-hooks
+ - Mock React Query client
+
+5. **Frontend Page Tests**
+ - File: `frontend/src/features/stations/__tests__/pages/StationsPage.test.tsx`
+ - Test page renders
+ - Test search workflow
+ - Test save station workflow
+ - Test tab switching
+ - Test map interaction
+ - File: `frontend/src/features/stations/__tests__/pages/StationsMobileScreen.test.tsx`
+ - Test all 3 tabs render
+ - Test tab navigation
+ - Test search on mobile
+ - Test saved list on mobile
+
+6. **Integration Component Tests**
+ - File: `frontend/src/features/fuel-logs/__tests__/components/StationPicker.test.tsx`
+ - Test rendering
+ - Test saved stations load
+ - Test nearby stations load (with geolocation)
+ - Test manual text entry
+ - Test selection callback
+ - Mock useStationsSearch and useSavedStations
+
+7. **E2E Tests (Optional but Recommended)**
+ - File: `frontend/cypress/e2e/stations.cy.ts` (or similar framework)
+ - Test flows:
+ - Login → Navigate to Stations
+ - Search for nearby stations
+ - Save a station
+ - View saved stations
+ - Delete a station
+ - Navigate to Fuel Logs
+ - Select station from picker
+ - Submit fuel log
+ - Verify station name appears in log
+ - Use real backend in test environment
+ - Seed test data if needed
+
+8. **Run All Tests**
+ - Backend: `cd backend && npm test`
+ - Frontend: `cd frontend && npm test`
+ - Verify 100% pass rate
+ - Fix any failures
+
+9. **Backend Documentation**
+ - File: `backend/src/features/stations/docs/ARCHITECTURE.md`
+ - System design overview
+ - Data flow diagrams (text-based)
+ - External dependencies (Google Maps Places API)
+ - Caching strategy (Redis + PostgreSQL)
+ - Database schema with relationships
+ - Circuit breaker pattern explanation
+ - File: `backend/src/features/stations/docs/API.md`
+ - All endpoint documentation
+ - Request/response examples with curl commands
+ - Authentication requirements (JWT)
+ - Rate limits and quotas
+ - Error response formats
+ - File: `backend/src/features/stations/docs/TESTING.md`
+ - How to run tests
+ - Test database setup
+ - Writing new tests
+ - Coverage goals (>80%)
+ - CI/CD integration
+ - File: `backend/src/features/stations/docs/GOOGLE-MAPS-SETUP.md`
+ - Google Cloud Console setup
+ - Create project and enable Places API
+ - API key creation and restrictions
+ - Quota management and monitoring
+ - Cost estimation ($10-50/month typical)
+ - Security best practices (restrict by IP, referrer)
+
+10. **Frontend Documentation**
+ - File: `frontend/src/features/stations/README.md`
+ - Feature overview
+ - Component hierarchy diagram (text-based)
+ - Hook usage examples
+ - Adding new functionality guide
+ - Runtime config pattern explanation
+ - Testing guide
+ - Integration with other features
+ - Update: `frontend/docs/RUNTIME-CONFIG.md` (created by Agent 1)
+ - Ensure complete and accurate
+
+11. **Update Main Documentation**
+ - File: `docs/README.md`
+ - Add "Gas Stations" to features list
+ - Brief description: "Search and save gas stations using Google Maps"
+ - Link to backend docs: `backend/src/features/stations/docs/`
+ - Link to frontend docs: `frontend/src/features/stations/README.md`
+ - File: `backend/src/features/stations/README.md`
+ - Update with complete feature overview
+ - Configuration requirements
+ - API endpoints summary
+ - Testing instructions
+ - Deployment notes
+
+12. **Create User Guide (Optional)**
+ - File: `docs/USER-GUIDE-STATIONS.md`
+ - How to search for stations
+ - How to save favorites
+ - How to use in fuel logs
+ - Screenshots (if possible)
+ - Troubleshooting common issues
+
+### Success Criteria
+- All backend tests pass (100%)
+- All frontend tests pass (100%)
+- Test coverage >80% for new code
+- All documentation files created
+- Documentation is clear and accurate
+- Code examples in docs work
+- Main README updated
+- No TypeScript errors
+- Linters pass
+
+### Handoff Notes
+Testing and documentation complete. Feature is production-ready. All code is tested, documented, and follows project standards.
+
+---
+
+## Final Validation Checklist
+
+After all agents complete, run final validation:
+
+### Build & Deploy
+```bash
+make rebuild # Rebuild all containers
+make logs # Watch for errors
+make migrate # Run database migrations
+make test # Run all tests
+```
+
+### Linting
+```bash
+cd backend && npm run lint && npm run type-check
+cd frontend && npm run lint && npm run type-check
+```
+
+### Manual Testing
+- [ ] Desktop: Search stations at https://motovaultpro.com/stations
+- [ ] Desktop: Save a station
+- [ ] Desktop: View saved stations
+- [ ] Desktop: Delete a station
+- [ ] Desktop: Map visualization works
+- [ ] Mobile: Navigate to stations (/m/stations)
+- [ ] Mobile: All 3 tabs work
+- [ ] Mobile: Touch targets are 44px minimum
+- [ ] Fuel Logs: Station picker works
+- [ ] Fuel Logs: Submit log with station
+- [ ] Cross-browser: Chrome, Safari, Firefox
+
+### Performance
+- [ ] Map loads in <2 seconds
+- [ ] API responses <500ms
+- [ ] Redis caching works (check logs)
+- [ ] No memory leaks (React DevTools)
+
+### Security
+- [ ] All endpoints require JWT auth
+- [ ] User data isolation works (can't see other users' saved stations)
+- [ ] SQL injection protected (prepared statements)
+- [ ] API key not exposed to client (runtime config)
+
+### Documentation
+- [ ] All docs created and accurate
+- [ ] Code examples work
+- [ ] Main README updated
+- [ ] Google Maps setup guide complete
+
+### Standards (per CLAUDE.md)
+- [ ] All linters pass with zero issues
+- [ ] All tests pass
+- [ ] Feature works end-to-end on desktop
+- [ ] Feature works end-to-end on mobile
+- [ ] Old code deleted (no placeholder routes)
+- [ ] No emojis in code or docs
+- [ ] Meaningful variable names used
+
+---
+
+## Execution Commands
+
+To execute agents in parallel using Claude Code:
+
+### Phase 1 (Parallel)
+```bash
+# Terminal 1
+claude-code "Execute Agent 1: Frontend-Secrets-Agent as defined in GAS-STATION-AGENTS.md"
+
+# Terminal 2
+claude-code "Execute Agent 2: Backend-Reliability-Agent as defined in GAS-STATION-AGENTS.md"
+```
+
+### Phase 2
+```bash
+# Wait for Phase 1 to complete
+claude-code "Execute Agent 3: Frontend-Foundation-Agent as defined in GAS-STATION-AGENTS.md"
+```
+
+### Phase 3 (Parallel)
+```bash
+# Terminal 1
+claude-code "Execute Agent 4: Components-Agent as defined in GAS-STATION-AGENTS.md"
+
+# Terminal 2
+claude-code "Execute Agent 5: Map-Visualization-Agent as defined in GAS-STATION-AGENTS.md"
+```
+
+### Phase 4 (Parallel)
+```bash
+# Terminal 1
+claude-code "Execute Agent 6: Desktop-Mobile-Agent as defined in GAS-STATION-AGENTS.md"
+
+# Terminal 2
+claude-code "Execute Agent 7: Integration-Agent as defined in GAS-STATION-AGENTS.md"
+```
+
+### Phase 5
+```bash
+# Wait for Phase 4 to complete
+claude-code "Execute Agent 8: Testing-Documentation-Agent as defined in GAS-STATION-AGENTS.md"
+```
+
+---
+
+## Notes
+
+- Each agent is designed to be autonomous and complete its scope independently
+- Agents include clear prerequisites and dependencies
+- Follow CLAUDE.md standards: no emojis, meaningful names, delete old code
+- All implementations follow K8s-aligned patterns (runtime secrets, not build-time)
+- Reference implementation: vehicles feature
+- Testing is mandatory (per CLAUDE.md: must be 100% green)
+- Mobile + Desktop requirement: all features work on both platforms
+
+---
+
+## Estimated Total Time
+
+- Phase 1: 8 hours (parallel: 8 hours)
+- Phase 2: 4 hours
+- Phase 3: 8 hours (parallel: 8 hours)
+- Phase 4: 8 hours (parallel: 8 hours)
+- Phase 5: 12 hours
+
+**Total: 40 hours elapsed (with parallelization)**
+**Total: 48 hours of work (across all agents)**
+
+**Savings from parallelization: 8 hours (17% faster)**
diff --git a/docs/GAS-STATIONS.md b/docs/GAS-STATIONS.md
new file mode 100644
index 0000000..869c2c5
--- /dev/null
+++ b/docs/GAS-STATIONS.md
@@ -0,0 +1,648 @@
+Gas Stations Feature - Complete Implementation Plan (K8s-Aligned Secrets)
+
+ Overview
+
+ Implement complete Gas Stations feature with full integration, map visualization, backend improvements, and comprehensive testing. Uses K8s-aligned runtime
+ secrets pattern for frontend Google Maps API key.
+
+ Phase 1: Frontend Secrets Infrastructure (K8s-Aligned)
+
+ 1.1 Create Frontend Config Loader
+
+ Create frontend/scripts/load-config.sh:
+ - Bash script that runs as container entrypoint
+ - Reads /run/secrets/google-maps-api-key
+ - Generates /usr/share/nginx/html/config.js with: window.CONFIG = { googleMapsApiKey: '...' }
+ - Falls back to empty string if secret not found
+ - Logs success/failure for debugging
+
+ 1.2 Update Frontend Dockerfile
+
+ Modify frontend/Dockerfile:
+ - Copy load-config.sh into image
+ - Make script executable
+ - Add SECRETS_DIR environment variable (default: /run/secrets)
+ - Update CMD to run script before nginx: ["sh", "-c", "/app/load-config.sh && nginx -g 'daemon off;'"]
+
+ 1.3 Update Frontend index.html
+
+ Modify frontend/index.html:
+ - Add before app bundle
+ - Config loads before React app initializes
+ - Add TypeScript types for window.CONFIG
+
+ 1.4 Create Frontend Config Types
+
+ Create frontend/src/core/config/config.types.ts:
+ - Interface for window.CONFIG
+ - Export typed accessor: getConfig()
+ - Runtime validation (throw if required values missing)
+
+ 1.5 Update docker-compose.yml
+
+ Add to mvp-frontend service:
+ volumes:
+ - ./secrets/app/google-maps-api-key.txt:/run/secrets/google-maps-api-key:ro
+ environment:
+ SECRETS_DIR: /run/secrets
+
+ 1.6 Document Pattern
+
+ Create frontend/docs/RUNTIME-CONFIG.md:
+ - Explain runtime config pattern
+ - How to add new runtime secrets
+ - K8s deployment notes
+ - Local development setup
+
+ Phase 2: Backend Improvements
+
+ 2.1 Add Circuit Breaker Pattern
+
+ - Install opossum package: backend/package.json
+ - Create backend/src/features/stations/external/google-maps/google-maps.circuit-breaker.ts
+ - Update google-maps.client.ts to wrap API calls
+ - Follow platform feature pattern (reference: backend/src/features/platform/)
+ - Config: 10s timeout, 50% threshold, 30s reset
+
+ 2.2 Backend Unit Tests
+
+ Create backend/src/features/stations/tests/unit/:
+ - stations.service.test.ts - Business logic, user isolation
+ - stations.repository.test.ts - Database operations, SQL queries
+ - google-maps.client.test.ts - API mocking, distance calculation
+ - Use test fixtures for sample data
+
+ 2.3 Backend Integration Tests
+
+ Create backend/src/features/stations/tests/integration/:
+ - stations.api.test.ts - Full endpoint testing with real database
+ - saved-stations.flow.test.ts - Save, retrieve, delete workflow
+ - Use test database (configured in test setup)
+
+ 2.4 Test Fixtures
+
+ Create backend/src/features/stations/tests/fixtures/:
+ - mock-stations.ts - Sample station objects
+ - mock-google-response.ts - Mock Google Places API responses
+ - test-coordinates.ts - Test location data
+
+ 2.5 Cache Cleanup Job
+
+ Create backend/src/features/stations/jobs/cache-cleanup.job.ts:
+ - Scheduled job (daily at 2 AM)
+ - Delete station_cache entries older than 24 hours
+ - Log cleanup metrics (rows deleted)
+ - Register in main app scheduler
+
+ Phase 3: Frontend Foundation
+
+ 3.1 Type Definitions
+
+ Create frontend/src/features/stations/types/stations.types.ts:
+ - Station interface (id, name, address, location, rating, distance, photoUrl, prices)
+ - SavedStation interface (extends Station, adds nickname, notes, isFavorite)
+ - SearchRequest interface (latitude, longitude, radius?, fuelType?)
+ - SearchResponse interface
+ - MapMarker interface for map pins
+
+ 3.2 API Client
+
+ Create frontend/src/features/stations/api/stations.api.ts:
+ - searchStations(request: SearchRequest): Promise
+ - saveStation(placeId: string, data: SaveStationData): Promise
+ - getSavedStations(): Promise
+ - deleteSavedStation(placeId: string): Promise
+ - Use axios with proper error handling
+ - Add request/response logging
+
+ 3.3 React Query Hooks
+
+ Create frontend/src/features/stations/hooks/:
+
+ useStationsSearch.ts:
+ - Mutation hook for search (not cached by default)
+ - Accepts SearchRequest
+ - Returns Station array
+ - Integrates with useGeolocation
+
+ useSavedStations.ts:
+ - Query hook with React Query caching
+ - Auto-refetch on window focus
+ - Invalidate on save/delete mutations
+
+ useSaveStation.ts:
+ - Mutation hook
+ - Optimistic updates to saved list
+ - Invalidates saved stations cache on success
+
+ useDeleteStation.ts:
+ - Mutation hook
+ - Optimistic removal from list
+ - Invalidates cache on success
+
+ useGeolocation.ts:
+ - Browser Geolocation API wrapper
+ - Permission handling
+ - Error states (permission denied, unavailable, timeout)
+ - Returns current position
+
+ 3.4 Google Maps Integration
+
+ Create frontend/src/features/stations/utils/maps-loader.ts:
+ - Load Google Maps JavaScript API dynamically
+ - Use runtime config: getConfig().googleMapsApiKey
+ - Promise-based API
+ - Singleton pattern (load once)
+ - TypeScript types for Google Maps objects
+
+ Phase 4: Frontend Components
+
+ 4.1 Core Components
+
+ Create frontend/src/features/stations/components/:
+
+ StationCard.tsx:
+ - Material-UI Card component
+ - Props: station, onSave, onDelete, isSaved
+ - Display: name (Typography h6), address (Typography body2), distance (Chip)
+ - Rating stars (Rating component)
+ - Price display (if available)
+ - Photo thumbnail (if available)
+ - Save/Unsave IconButton (BookmarkIcon / BookmarkBorderIcon)
+ - Directions link (opens Google Maps)
+ - Mobile: 44px min height, touch targets
+ - Desktop: hover effects
+
+ StationsList.tsx:
+ - Container for search results
+ - Props: stations[], loading, error, onSaveStation
+ - Grid layout (responsive: 1 col mobile, 2 cols tablet, 3 cols desktop)
+ - Loading skeleton (Skeleton components)
+ - Empty state: "No stations found. Try adjusting your search."
+ - Error state with retry button
+
+ SavedStationsList.tsx:
+ - User's favorites display
+ - Props: savedStations[], onDelete, onSelect
+ - List layout (vertical)
+ - Show nickname if set, otherwise station name
+ - Notes preview (truncated)
+ - Distance from current location (optional)
+ - Delete IconButton
+ - Empty state: "No saved stations yet. Save stations from search results."
+
+ StationsSearchForm.tsx:
+ - Form with search parameters
+ - Current Location button (uses useGeolocation)
+ - Manual lat/lng inputs (number fields)
+ - Radius slider (FormControl, Slider: 1-25 miles, default 5)
+ - Fuel type select (optional filter)
+ - Search button (LoadingButton)
+ - Loading states on button
+ - Validation: require location (current OR manual)
+ - Error display for geolocation failures
+
+ StationMap.tsx:
+ - Google Maps embed component
+ - Props: stations[], center, zoom, onMarkerClick
+ - Load map using maps-loader utility
+ - Station markers (color-coded: blue=normal, gold=saved)
+ - Current location marker (red pin)
+ - Info windows on marker click (station details + save button)
+ - Directions button in info window
+ - Zoom controls, pan controls
+ - Responsive height (300px mobile, 500px desktop)
+
+ 4.2 UI Utilities
+
+ Create frontend/src/features/stations/utils/:
+
+ distance.ts:
+ - formatDistance(meters: number): string - "1.2 mi" or "0.3 mi"
+ - calculateDistance(lat1, lng1, lat2, lng2): number - Haversine formula
+
+ location.ts:
+ - getCurrentPosition(): Promise
+ - requestLocationPermission(): Promise
+ - Error handling helpers
+
+ map-utils.ts:
+ - createStationMarker(station, map, isSaved): google.maps.Marker
+ - createInfoWindow(station): google.maps.InfoWindow
+ - fitBoundsToMarkers(map, markers): void
+
+ Phase 5: Desktop Implementation
+
+ 5.1 Desktop Page
+
+ Create frontend/src/features/stations/pages/StationsPage.tsx:
+ - Layout: Grid container
+ - Left column (60%): StationMap (full height)
+ - Right column (40%):
+ - StationsSearchForm at top
+ - Tabs: "Search Results" | "Saved Stations"
+ - Tab 1: StationsList
+ - Tab 2: SavedStationsList
+ - State management:
+ - searchResults (from search mutation)
+ - savedStations (from query)
+ - selectedStation (for map focus)
+ - Effects:
+ - Load saved stations on mount
+ - Update map when search results change
+ - Mobile breakpoint: Stack vertically (map on top)
+
+ 5.2 Desktop Routing
+
+ Update frontend/src/App.tsx (line 556):
+ - Remove: Stations (TODO)} />
+ - Add: } />
+ - Import: import { StationsPage } from './features/stations/pages/StationsPage'
+ - Ensure route is inside ProtectedRoute wrapper
+
+ Phase 6: Mobile Implementation
+
+ 6.1 Mobile Screen
+
+ Create frontend/src/features/stations/pages/StationsMobileScreen.tsx:
+ - BottomNavigation with 3 tabs: Search, Saved, Map
+ - Tab 0 (Search):
+ - StationsSearchForm (compact mode)
+ - StationsList (vertical scroll)
+ - Pull-to-refresh support
+ - Tab 1 (Saved):
+ - SavedStationsList (full screen)
+ - Swipe to delete gestures
+ - Tab 2 (Map):
+ - StationMap (full screen, 100vh)
+ - Floating search button (FAB) to go back to search tab
+ - Bottom sheet for station details (SwipeableDrawer)
+ - Touch targets: 44px minimum
+ - Safe area insets for notched devices
+
+ 6.2 Mobile Routing
+
+ Update frontend/src/App.tsx:
+ - Add mobile route: } />
+ - Update mobile navigation items (add stations)
+ - Ensure icon is interactive (onClick navigation)
+
+ Phase 7: Fuel Logs Integration
+
+ 7.1 Station Picker Component
+
+ Create frontend/src/features/fuel-logs/components/StationPicker.tsx:
+ - Autocomplete component (Material-UI)
+ - Props: value, onChange, userLocation?
+ - Options:
+ - Saved stations (shown first, grouped)
+ - Nearby stations (if location available)
+ - Manual text input (freeSolo mode)
+ - Option rendering:
+ - Station name (primary)
+ - Distance + address (secondary)
+ - Bookmark icon if saved
+ - Debounced search (300ms)
+ - Loading indicator while searching
+ - Fallback to text input if API fails
+
+ 7.2 Update Fuel Log Form
+
+ Modify frontend/src/features/fuel-logs/components/FuelLogForm.tsx:
+ - Replace LocationInput with StationPicker
+ - Props: pass user location from geolocation
+ - Value binding to stationName field
+ - Maintain backward compatibility (accepts text string)
+ - Show nearby stations on field focus
+ - Optional: "Save this station" checkbox when new station entered
+
+ 7.3 Integration Features
+
+ Optional enhancements:
+ - In FuelLogCard, link station name to station details
+ - In StationsPage, show "Recent fuel logs at this station"
+ - Suggest saving station after logging fuel at new location
+
+ Phase 8: Testing
+
+ 8.1 Backend Tests Execution
+
+ cd backend
+ npm test -- features/stations
+ - Verify all unit tests pass
+ - Verify all integration tests pass
+ - Check coverage report (aim for >80%)
+ - Fix any failing tests
+
+ 8.2 Frontend Component Tests
+
+ Create frontend/src/features/stations/__tests__/components/:
+ - StationCard.test.tsx - Rendering, save/delete actions
+ - StationsList.test.tsx - List rendering, empty/error states
+ - SavedStationsList.test.tsx - Saved list, delete action
+ - StationsSearchForm.test.tsx - Form validation, submission
+ - StationMap.test.tsx - Map initialization (with mocks)
+ - Use React Testing Library
+ - Mock API calls with MSW (Mock Service Worker)
+
+ 8.3 Frontend Page Tests
+
+ Create frontend/src/features/stations/__tests__/pages/:
+ - StationsPage.test.tsx - Desktop page integration
+ - StationsMobileScreen.test.tsx - Mobile navigation, tabs
+ - Test user workflows: search, save, delete
+ - Test error handling and loading states
+
+ 8.4 API Client Tests
+
+ Create frontend/src/features/stations/api/__tests__/:
+ - stations.api.test.ts - Test all API methods
+ - Mock axios responses
+ - Test error handling (network, 401, 500)
+ - Verify request payloads
+
+ 8.5 React Query Hook Tests
+
+ Create frontend/src/features/stations/hooks/__tests__/:
+ - Test each hook in isolation
+ - Mock React Query
+ - Test loading, success, error states
+ - Test cache invalidation logic
+ - Test optimistic updates
+
+ 8.6 E2E Tests
+
+ Create frontend/cypress/e2e/stations.cy.ts (or similar E2E framework):
+ - Test: Search for nearby stations
+ - Test: Save a station to favorites
+ - Test: View saved stations list
+ - Test: Delete a saved station
+ - Test: Use station in fuel log entry
+ - Test: Mobile navigation flow
+ - Test: Map marker click and info window
+ - Use real backend API in test environment
+
+ Phase 9: Documentation
+
+ 9.1 Backend Feature Docs
+
+ Create backend/src/features/stations/docs/:
+
+ ARCHITECTURE.md:
+ - System design overview
+ - Data flow diagrams
+ - External dependencies (Google Maps API)
+ - Caching strategy
+ - Database schema
+ - Circuit breaker pattern
+
+ API.md:
+ - All endpoint documentation
+ - Request/response examples (curl commands)
+ - Authentication requirements
+ - Rate limits and quotas
+ - Error responses
+
+ TESTING.md:
+ - How to run tests
+ - Test database setup
+ - Writing new tests
+ - Coverage goals
+
+ GOOGLE-MAPS-SETUP.md:
+ - API key creation in Google Cloud Console
+ - Required APIs to enable
+ - Quota management
+ - Cost estimation
+ - Security best practices
+
+ 9.2 Frontend Feature Docs
+
+ Create frontend/src/features/stations/README.md:
+ - Feature overview
+ - Component hierarchy
+ - Hook usage examples
+ - Adding new functionality
+ - Runtime config pattern
+ - Testing guide
+
+ 9.3 Runtime Config Documentation
+
+ Already created in Phase 1.6: frontend/docs/RUNTIME-CONFIG.md
+
+ 9.4 Update Main Documentation
+
+ Update docs/README.md:
+ - Add "Gas Stations" to features list
+ - Link to backend and frontend docs
+ - Mention Google Maps integration
+
+ Update backend/src/features/stations/README.md:
+ - Complete feature overview
+ - Configuration requirements
+ - API endpoints summary
+ - Testing instructions
+ - Deployment notes
+
+ Phase 10: Validation & Polish
+
+ 10.1 Docker Build & Test
+
+ make rebuild # Rebuild all containers
+ make logs # Watch for errors
+ make migrate # Run database migrations
+ make test # Run all tests
+
+ Verify:
+ - Frontend config.js is generated at startup
+ - Backend loads Google Maps API key from secret
+ - All containers start without errors
+ - Database migrations create tables
+ - Tests pass in container environment
+
+ 10.2 Linting & Formatting
+
+ # Backend
+ cd backend && npm run lint && npm run type-check
+
+ # Frontend
+ cd frontend && npm run lint && npm run type-check
+
+ Fix all issues (MUST be 100% green per CLAUDE.md):
+ - Zero TypeScript errors
+ - Zero ESLint warnings
+ - Zero Prettier formatting issues
+
+ 10.3 Manual Testing - Desktop
+
+ - Open https://motovaultpro.com/stations in browser
+ - Test geolocation permission flow
+ - Search for stations near current location
+ - Verify map loads with markers
+ - Click marker, verify info window
+ - Save a station
+ - View saved stations list
+ - Delete a saved station
+ - Test manual lat/lng search
+ - Test with no results (remote location)
+ - Test error handling (API failure)
+
+ 10.4 Manual Testing - Mobile
+
+ - Open mobile nav, navigate to Stations
+ - Test all 3 tabs (Search, Saved, Map)
+ - Verify 44px touch targets
+ - Test swipe gestures
+ - Test bottom sheet interactions
+ - Verify responsive layout
+ - Test on actual mobile device (if possible)
+
+ 10.5 Fuel Logs Integration Testing
+
+ - Navigate to Fuel Logs
+ - Create new fuel log entry
+ - Test StationPicker autocomplete
+ - Select a saved station
+ - Enter new station name
+ - Submit fuel log
+ - Verify station name is saved
+
+ 10.6 Cross-Browser Testing
+
+ Test on:
+ - Chrome (latest)
+ - Safari (latest)
+ - Firefox (latest)
+ - Mobile Safari (iOS)
+ - Mobile Chrome (Android)
+
+ 10.7 Performance Validation
+
+ - Check map load time (<2s)
+ - Verify API response times (<500ms)
+ - Check Redis cache hits (backend logs)
+ - Monitor Google Maps API quota usage
+ - Verify no memory leaks (React DevTools Profiler)
+
+ Phase 11: Deployment Preparation
+
+ 11.1 Configuration Checklist
+
+ Backend:
+ - Secret file exists: ./secrets/app/google-maps-api-key.txt
+ - Docker compose mounts secret to /run/secrets/google-maps-api-key
+ - Backend config loader reads from SECRETS_DIR
+
+ Frontend:
+ - Secret file mounted: /run/secrets/google-maps-api-key
+ - Entrypoint script generates /usr/share/nginx/html/config.js
+ - index.html loads config.js before app
+ - App accesses via getConfig().googleMapsApiKey
+
+ 11.2 Database Migration
+
+ make migrate
+ Verify:
+ - Migration 001_create_stations_tables.sql runs successfully
+ - Tables created: station_cache, saved_stations
+ - Indexes created on both tables
+ - Test queries work
+
+ 11.3 Secrets Verification
+
+ # Verify backend can read secret
+ docker compose exec mvp-backend cat /run/secrets/google-maps-api-key
+
+ # Verify frontend generates config
+ docker compose exec mvp-frontend cat /usr/share/nginx/html/config.js
+ # Should show: window.CONFIG = { googleMapsApiKey: "..." }
+
+ 11.4 Health Checks
+
+ - Verify /health endpoint includes stations feature
+ - Test stations API endpoints with curl:
+ # Get JWT token first
+ TOKEN="your-jwt-token"
+
+ # Search stations
+ curl -X POST http://localhost:3001/api/stations/search \
+ -H "Authorization: Bearer $TOKEN" \
+ -H "Content-Type: application/json" \
+ -d '{"latitude": 37.7749, "longitude": -122.4194}'
+
+ # Get saved stations
+ curl http://localhost:3001/api/stations/saved \
+ -H "Authorization: Bearer $TOKEN"
+
+ 11.5 Production Readiness
+
+ Update config/app/production.yml.example:
+ - Document Google Maps API key requirement
+ - Add example configuration
+
+ Create deployment checklist:
+ - Google Maps API key in secrets
+ - Frontend container mounts secret
+ - Backend container mounts secret
+ - Database migrations run
+ - All tests pass
+ - Linters pass
+ - Manual testing complete
+ - Performance acceptable
+ - Documentation complete
+
+ Success Criteria (per CLAUDE.md)
+
+ - All linters pass with zero issues
+ - All tests pass (backend + frontend)
+ - Feature works end-to-end on desktop
+ - Feature works end-to-end on mobile
+ - Fuel logs integration functional
+ - Map visualization working
+ - Google Maps API integration live via runtime secrets
+ - K8s-aligned secrets pattern implemented
+ - Documentation complete
+ - Old code deleted (no orphaned files)
+
+ K8s Secrets Pattern Summary
+
+ Backend (already implemented):
+ - Secret mounted: /run/secrets/google-maps-api-key
+ - Read at runtime by config-loader.ts
+ - Never in environment variables or code
+
+ Frontend (new implementation):
+ - Secret mounted: /run/secrets/google-maps-api-key
+ - Read at container startup by entrypoint script
+ - Injected into config.js served with static files
+ - App loads config at runtime via window.CONFIG
+ - Can be updated by restarting container (no rebuild)
+
+ This mirrors K8s deployment where:
+ - Secrets are mounted as volumes
+ - Applications read them at runtime
+ - Secrets can be rotated without rebuilding images
+
+ Estimated Timeline
+
+ - Phase 1 (Frontend Secrets): 1 day
+ - Phase 2 (Backend): 1 day
+ - Phase 3 (Foundation): 0.5 day
+ - Phase 4 (Components): 1 day
+ - Phase 5 (Desktop): 0.5 day
+ - Phase 6 (Mobile): 0.5 day
+ - Phase 7 (Integration): 0.5 day
+ - Phase 8 (Testing): 1.5 days
+ - Phase 9 (Docs): 0.5 day
+ - Phase 10 (Validation): 0.5 day
+ - Phase 11 (Deployment): 0.5 day
+
+ Total: 8 days (full implementation with K8s-aligned secrets)
+
+ Reference Implementations
+
+ - Secrets pattern: Backend config-loader.ts and docker-compose.yml
+ - Feature structure: frontend/src/features/vehicles/
+ - Component patterns: Vehicles components
+ - Testing: Vehicles test suite
+ - Mobile + Desktop: Vehicles pages
\ No newline at end of file
diff --git a/docs/PLATFORM-INTEGRATION-AGENTS.md b/docs/PLATFORM-INTEGRATION-AGENTS.md
deleted file mode 100644
index e4e0c11..0000000
--- a/docs/PLATFORM-INTEGRATION-AGENTS.md
+++ /dev/null
@@ -1,1189 +0,0 @@
-# Platform Service Integration - Agent Execution Manifest
-
-## Overview
-
-Integration of mvp-platform vehicles service into backend as a feature module. This document defines specialized agents for parallel execution.
-
-**Goal**: Convert 6-container architecture to 5-container by absorbing platform service into backend.
-
-**Strategy**: Single-phase cutover with parallel agent execution.
-
-**Estimated Duration**: 6-8 hours with 7 agents running in parallel.
-
----
-
-## Execution Waves
-
-### Wave 1: Parallel Foundation (4 agents)
-Can execute simultaneously, no dependencies.
-
-- **Agent 1**: Backend Feature Creator
-- **Agent 2**: VIN Removal - Backend
-- **Agent 3**: VIN Removal - Frontend
-- **Agent 4**: Configuration Cleanup
-
-### Wave 2: Integration & Testing (2 agents)
-Depends on Wave 1 completion.
-
-- **Agent 5**: Integration & Testing
-- **Agent 6**: Documentation Updates
-
-### Wave 3: Final Cleanup (1 agent)
-Depends on Wave 2 completion.
-
-- **Agent 7**: Container Removal & Deployment
-
----
-
-## Agent Definitions
-
-## AGENT 1: Backend Feature Creator
-
-**Role**: Create new vehicle-data feature module in TypeScript
-
-**Subagent Type**: `feature-agent`
-
-**Dependencies**: None (can start immediately)
-
-**Deliverables**:
-- Complete feature structure in `backend/src/features/vehicle-data/`
-- TypeScript repository with all SQL queries converted from Python
-- Caching service using Redis
-- API routes and controllers
-- Request/response DTOs
-- Feature README
-
-**Prompt**:
-```
-Create a new feature module at backend/src/features/vehicle-data/ that replaces the Python FastAPI platform service.
-
-CONTEXT:
-- Source: /Users/egullickson/Documents/Technology/coding/motovaultpro/mvp-platform-services/vehicles/
-- Python FastAPI service with vehicle hierarchical data (makes/models/trims/engines)
-- Uses vehicles schema in PostgreSQL (vehicles.make, vehicles.model, etc.)
-- Redis caching with 6-hour TTL
-- Authentication via JWT (extract user_id)
-
-REQUIREMENTS:
-
-1. CREATE FEATURE STRUCTURE:
-backend/src/features/vehicle-data/
-├── api/
-│ ├── vehicle-data.routes.ts # Fastify routes
-│ └── vehicle-data.controller.ts # Controllers
-├── domain/
-│ ├── vehicle-data.service.ts # Business logic
-│ └── vehicle-data.cache.ts # Redis caching
-├── data/
-│ └── vehicle-data.repository.ts # PostgreSQL queries
-├── models/
-│ ├── requests.ts # DTOs
-│ └── responses.ts # DTOs
-├── tests/
-│ ├── unit/
-│ └── integration/
-└── README.md
-
-2. CONVERT PYTHON TO TYPESCRIPT:
-
-Source files:
-- Python repo: mvp-platform-services/vehicles/api/repositories/vehicles_repository.py
-- Python service: mvp-platform-services/vehicles/api/services/vehicles_service.py
-- Python cache: mvp-platform-services/vehicles/api/services/cache_service.py
-
-Convert these methods:
-- get_years() → SELECT DISTINCT year FROM vehicles.model_year ORDER BY year DESC
-- get_makes(year) → Join vehicles.make through model_year
-- get_models(year, make_id) → Join vehicles.model through model_year
-- get_trims(year, model_id) → Get trims for model/year
-- get_engines(year, model_id, trim_id) → Get engines via trim_engine
-
-3. IMPLEMENT CACHING:
-- Use Redis from backend core (already connected)
-- Cache keys: vehicle-data:makes:{year}, vehicle-data:models:{year}:{makeId}, etc.
-- TTL: 6 hours (21600 seconds)
-- Graceful fallback if Redis unavailable
-
-4. CREATE API ROUTES:
-All routes require JWT authentication:
-- GET /api/vehicle-data/years
-- GET /api/vehicle-data/makes?year={year}
-- GET /api/vehicle-data/models?year={year}&make_id={id}
-- GET /api/vehicle-data/trims?year={year}&model_id={id}
-- GET /api/vehicle-data/engines?year={year}&trim_id={id}
-
-5. RESPONSE FORMATS (match Python service):
-{
- "years": [2024, 2023, 2022, ...],
- "makes": [{ id: 1, name: "Honda" }, ...],
- "models": [{ id: 1, name: "Civic" }, ...],
- "trims": [{ id: 1, name: "LX" }, ...],
- "engines": [{ id: 1, name: "2.0L I4" }, ...]
-}
-
-6. ERROR HANDLING:
-- Validate query parameters (year 1950-2100, IDs positive integers)
-- Return 400 for invalid input
-- Return 404 if no data found
-- Log errors but don't expose internal details
-
-7. REGISTER ROUTES:
-Update backend/src/app.ts to register feature:
-import { vehicleDataRoutes } from './features/vehicle-data/api/vehicle-data.routes';
-app.register(vehicleDataRoutes, { prefix: '/api/vehicle-data' });
-
-CONSTRAINTS:
-- Use existing PostgreSQL pool from core
-- Use existing Redis client from core
-- Follow feature capsule pattern (see backend/src/features/vehicles/ as example)
-- NO VIN decoding (that's being removed)
-- Production-ready code (error handling, logging, validation)
-
-VERIFICATION:
-- All TypeScript compiles without errors
-- Routes registered in app.ts
-- Repository queries match Python SQL logic
-- Caching implementation complete
-- Feature README documents all endpoints
-
-Return confirmation when complete with file paths created.
-```
-
-**Success Criteria**:
-- ✅ Feature structure created
-- ✅ All Python logic converted to TypeScript
-- ✅ Caching implemented
-- ✅ Routes registered
-- ✅ TypeScript compiles
-- ✅ README complete
-
-**Estimated Time**: 3-4 hours
-
----
-
-## AGENT 2: VIN Removal - Backend
-
-**Role**: Remove all VIN decoding logic from backend
-
-**Subagent Type**: `general-purpose`
-
-**Dependencies**: None (can start immediately)
-
-**Deliverables**:
-- Removed VIN decode methods from platform client
-- Removed vPIC fallback client
-- Updated vehicles service (no auto-populate from VIN)
-- Updated vehicle creation to require make/model/year
-- Removed VIN cache methods
-- Removed circuit breaker for VIN decode
-
-**Prompt**:
-```
-Remove all VIN decoding functionality from the backend codebase.
-
-CONTEXT:
-VIN decoding is being removed as a feature. Users will manually select make/model/year instead of auto-populating from VIN.
-
-TASKS:
-
-1. DELETE ENTIRE DIRECTORY:
-backend/src/features/vehicles/external/platform-vehicles/
-- This contains the platform client with VIN decode
-- The entire external integration is being replaced
-
-2. DELETE FILE:
-backend/src/features/vehicles/domain/platform-integration.service.ts
-- This service wraps platform calls and vPIC fallback
-- No longer needed
-
-3. UPDATE VEHICLES SERVICE:
-File: backend/src/features/vehicles/domain/vehicles.service.ts
-
-Remove:
-- Import of PlatformIntegrationService
-- Constructor dependency on platformIntegration
-- Any calls to platformIntegration.decodeVIN()
-- Auto-population of make/model/year from VIN
-
-Keep VIN as optional string field (for user reference only).
-
-4. UPDATE VEHICLES REPOSITORY:
-File: backend/src/features/vehicles/data/vehicles.repository.ts
-
-Remove:
-- cacheVINDecode() method
-- Any VIN cache queries
-- VIN decode cache table references
-
-5. UPDATE VEHICLE CREATION:
-File: backend/src/features/vehicles/api/vehicles.controller.ts
-
-Update createVehicle endpoint:
-- Remove VIN decode step
-- Require make, model, year in request body (not optional)
-- VIN field optional (string for reference only)
-
-6. UPDATE VALIDATION:
-File: backend/src/features/vehicles/models/requests.ts
-
-Update CreateVehicleRequest:
-- make: REQUIRED string
-- model: REQUIRED string
-- year: REQUIRED number (1950-2100)
-- vin: OPTIONAL string (17 chars if provided)
-
-7. REMOVE CIRCUIT BREAKER:
-Check package.json for opossum dependency:
-- If ONLY used for platform service, remove from package.json
-- If used elsewhere, keep but remove platform-specific circuit breaker config
-
-8. REMOVE VPIC CLIENT:
-Search for vPIC/NHTSA API client:
-- Remove any vPIC fallback client files
-- Remove VPIC_API_URL environment variable references
-
-9. UPDATE TESTS:
-backend/src/features/vehicles/tests/
-- Delete: unit/platform-vehicles.client.test.ts
-- Update: integration/vehicles.integration.test.ts
- - Remove VIN decode test scenarios
- - Update create vehicle tests (now requires make/model/year)
-
-VERIFICATION:
-- No references to "platform-vehicles" in backend code
-- No references to "vindecode" or "decodeVIN"
-- No references to "vPIC" or "NHTSA"
-- Vehicle creation requires make/model/year
-- All tests updated and passing
-- TypeScript compiles without errors
-
-Return list of files deleted and modified with confirmation.
-```
-
-**Success Criteria**:
-- ✅ Platform integration deleted
-- ✅ VIN decode logic removed
-- ✅ Vehicle creation updated
-- ✅ Tests updated
-- ✅ No VIN references remain
-
-**Estimated Time**: 2-3 hours
-
----
-
-## AGENT 3: VIN Removal - Frontend
-
-**Role**: Remove VIN decoding from frontend UI
-
-**Subagent Type**: `first-frontend-agent`
-
-**Dependencies**: None (can start immediately)
-
-**Deliverables**:
-- Removed VIN decode button/functionality
-- Updated vehicle form to require make/model/year dropdowns
-- Updated form validation
-- Updated user experience (manual selection)
-
-**Prompt**:
-```
-Remove VIN decoding functionality from the frontend and update vehicle creation form to require manual make/model/year selection.
-
-CONTEXT:
-VIN decoding is being removed. Users will now manually select vehicle details from dropdowns instead of auto-populating from VIN.
-
-TASKS:
-
-1. FIND VEHICLE CREATION FORM:
-Search for vehicle creation/edit components:
-- Likely in: frontend/src/features/vehicles/ or frontend/src/components/vehicles/
-- Look for: CreateVehicle, VehicleForm, AddVehicle components
-
-2. REMOVE VIN DECODE UI:
-Remove:
-- "Decode VIN" button
-- VIN input auto-complete/lookup functionality
-- Any loading states for VIN decode
-- Success/error messages for VIN decode
-
-3. UPDATE FORM FIELDS:
-Make these fields REQUIRED with dropdowns:
-- Make: Dropdown populated from /api/vehicle-data/makes?year={year}
-- Model: Dropdown populated from /api/vehicle-data/models?year={year}&make_id={makeId}
-- Year: Dropdown populated from /api/vehicle-data/years
-- Trim: Optional dropdown from /api/vehicle-data/trims
-- Engine: Optional dropdown from /api/vehicle-data/engines
-
-Make VIN field OPTIONAL (text input for reference only).
-
-4. IMPLEMENT CASCADING DROPDOWNS:
-- Year selection → loads Makes
-- Make selection → loads Models
-- Model selection → loads Trims
-- Trim selection → loads Engines
-
-5. UPDATE API CALLS:
-Change from:
-- /api/vehicles/dropdown/* (old platform proxy)
-
-To:
-- /api/vehicle-data/years
-- /api/vehicle-data/makes?year={year}
-- /api/vehicle-data/models?year={year}&make_id={id}
-
-6. UPDATE FORM VALIDATION:
-- Require year, make, model
-- VIN optional (17 chars if provided)
-- Show clear error messages for required fields
-
-7. UPDATE USER EXPERIENCE:
-- Add help text: "Select your vehicle from the dropdowns below"
-- Clear dependent dropdowns when parent changes (e.g., clear Models when Make changes)
-- Show loading states while fetching dropdown data
-
-8. TEST ON MOBILE + DESKTOP:
-- Dropdowns work on mobile
-- Touch-friendly dropdown selection
-- Responsive layout
-- No horizontal scrolling
-
-9. REMOVE VIN DECODE UTILITIES:
-Search for and remove:
-- VIN validation functions (if only used for decode)
-- VIN formatting utilities
-- API client methods for VIN decode
-
-VERIFICATION:
-- No "Decode VIN" button in UI
-- Vehicle form has year/make/model dropdowns (required)
-- Cascading dropdowns work correctly
-- VIN field is optional
-- Form validation updated
-- Works on mobile and desktop
-- API calls updated to /api/vehicle-data/*
-- npm run build succeeds
-- npm run lint passes
-
-Return confirmation with screenshots of updated form (mobile + desktop).
-```
-
-**Success Criteria**:
-- ✅ VIN decode UI removed
-- ✅ Dropdowns implemented
-- ✅ Cascading logic works
-- ✅ Mobile + desktop tested
-- ✅ Validation updated
-
-**Estimated Time**: 2-3 hours
-
----
-
-## AGENT 4: Configuration Cleanup
-
-**Role**: Remove platform service from docker-compose and configuration
-
-**Subagent Type**: `general-purpose`
-
-**Dependencies**: None (can start immediately)
-
-**Deliverables**:
-- Updated docker-compose.yml (remove mvp-platform)
-- Removed environment variables
-- Removed secrets
-- Updated Traefik configuration
-
-**Prompt**:
-```
-Remove the mvp-platform service from docker-compose and clean up all related configuration.
-
-CONTEXT:
-The platform service is being absorbed into the backend. The mvp-platform container will be removed, reducing from 6 to 5 containers.
-
-TASKS:
-
-1. UPDATE DOCKER-COMPOSE.YML:
-File: /Users/egullickson/Documents/Technology/coding/motovaultpro/docker-compose.yml
-
-Remove lines 184-227 (entire mvp-platform service definition).
-
-This includes:
-- Service: mvp-platform
-- Build context: ./mvp-platform-services/vehicles
-- Container name: mvp-platform
-- All environment variables
-- All volume mounts
-- Network connections
-- Health check
-- Traefik labels
-
-2. UPDATE BACKEND ENVIRONMENT:
-File: docker-compose.yml (mvp-backend service)
-
-Remove environment variable:
-- PLATFORM_VEHICLES_API_URL: http://mvp-platform:8000
-
-3. REMOVE FROM ENV FILES:
-File: .env.development
-
-Remove:
-- PLATFORM_VEHICLES_API_URL=http://mvp-platform:8000
-
-4. UPDATE BACKEND CONFIG:
-File: config/app/production.yml
-
-Remove any platform service references:
-- platform_vehicles_api_url
-- platform_api_key
-
-5. DELETE SECRETS:
-File: secrets/app/platform-vehicles-api-key.txt
-
-Delete this file (no longer needed).
-
-Update docker-compose.yml backend volumes:
-Remove secret mount:
-- ./secrets/app/platform-vehicles-api-key.txt:/run/secrets/platform-vehicles-api-key:ro
-
-6. UPDATE TRAEFIK CONFIG:
-File: config/traefik/middleware.yml or traefik.yml
-
-Remove:
-- Any router rules for /platform prefix
-- Any platform service backends
-- Platform health checks
-
-7. UPDATE MAKEFILE:
-File: Makefile
-
-Remove or update:
-- Any platform-specific commands
-- Update logs command if it references mvp-platform
-- Update rebuild if it specifically references platform
-
-8. VERIFY NETWORK CONFIGURATION:
-Check docker-compose.yml networks section:
-- Ensure frontend, backend, database networks still defined
-- Remove platform-specific networks if any
-
-9. VERIFY VOLUME CONFIGURATION:
-Check docker-compose.yml volumes section:
-- Ensure mvp_postgres_data, mvp_redis_data still defined
-- Remove platform-specific volumes if any
-
-VERIFICATION:
-- docker-compose.yml valid YAML (use yamllint or docker compose config)
-- Only 5 services defined: mvp-traefik, mvp-frontend, mvp-backend, mvp-postgres, mvp-redis
-- No references to "mvp-platform" in config files
-- No references to "platform-vehicles-api"
-- Secrets file removed
-- docker compose config runs without errors
-
-Return confirmation with list of modified files and line numbers.
-```
-
-**Success Criteria**:
-- ✅ docker-compose.yml updated (5 services)
-- ✅ Environment variables removed
-- ✅ Secrets deleted
-- ✅ Traefik config updated
-- ✅ Valid YAML
-
-**Estimated Time**: 1 hour
-
----
-
-## AGENT 5: Integration & Testing
-
-**Role**: Integrate new vehicle-data feature with vehicles feature and create comprehensive tests
-
-**Subagent Type**: `general-purpose`
-
-**Dependencies**: Agents 1, 2 complete
-
-**Deliverables**:
-- Vehicles feature updated to use vehicle-data feature
-- Unit tests for vehicle-data feature
-- Integration tests for full workflow
-- All tests passing
-
-**Prompt**:
-```
-Integrate the new vehicle-data feature with the vehicles feature and create comprehensive tests.
-
-CONTEXT:
-- Agent 1 created: backend/src/features/vehicle-data/
-- Agent 2 removed: VIN decode and platform integration
-- Now need to connect vehicles feature to vehicle-data feature
-
-TASKS:
-
-1. UPDATE VEHICLES SERVICE:
-File: backend/src/features/vehicles/domain/vehicles.service.ts
-
-Add dependency:
-import { VehicleDataService } from '../../vehicle-data/domain/vehicle-data.service';
-
-Constructor:
-constructor(
- private repository: VehiclesRepository,
- private vehicleData: VehicleDataService // NEW
-) {}
-
-Update dropdown methods to use vehicleData:
-- Replace platformIntegration.getMakes() → vehicleData.getMakes()
-- Replace platformIntegration.getModels() → vehicleData.getModels()
-- etc.
-
-2. UPDATE VEHICLES CONTROLLER:
-File: backend/src/features/vehicles/api/vehicles.controller.ts
-
-Update dropdown route handlers to call vehicleData service.
-
-3. UPDATE VEHICLES ROUTES:
-File: backend/src/features/vehicles/api/vehicles.routes.ts
-
-Ensure dropdown routes call updated controller methods.
-
-4. CREATE UNIT TESTS - VEHICLE DATA:
-File: backend/src/features/vehicle-data/tests/unit/vehicle-data.service.test.ts
-
-Test:
-- getYears() returns descending array
-- getMakes(year) returns makes for year
-- getModels(year, makeId) returns models
-- Cache hits work correctly
-- Cache misses query database
-- Invalid parameters throw errors
-
-Mock:
-- Repository calls
-- Redis calls
-
-5. CREATE UNIT TESTS - REPOSITORY:
-File: backend/src/features/vehicle-data/tests/unit/vehicle-data.repository.test.ts
-
-Test:
-- Each SQL query method
-- Parameter binding
-- Error handling
-- Empty result sets
-
-Mock:
-- PostgreSQL pool
-
-6. CREATE INTEGRATION TESTS:
-File: backend/src/features/vehicle-data/tests/integration/vehicle-data.integration.test.ts
-
-Test full workflow:
-1. GET /api/vehicle-data/years → [2024, 2023, ...]
-2. GET /api/vehicle-data/makes?year=2024 → [{id: 1, name: "Honda"}, ...]
-3. GET /api/vehicle-data/models?year=2024&make_id=1 → [{id: 1, name: "Civic"}, ...]
-4. GET /api/vehicle-data/trims?year=2024&model_id=1 → [{id: 1, name: "LX"}, ...]
-5. GET /api/vehicle-data/engines?year=2024&trim_id=1 → [{id: 1, name: "2.0L I4"}, ...]
-
-Test:
-- Authentication required (401 without JWT)
-- Invalid parameters return 400
-- Caching works (second call faster)
-- CORS headers present
-
-7. UPDATE VEHICLES INTEGRATION TESTS:
-File: backend/src/features/vehicles/tests/integration/vehicles.integration.test.ts
-
-Update:
-- Remove VIN decode scenarios
-- Update create vehicle to include make/model/year
-- Verify validation requires make/model/year
-- Test dropdown endpoints still work
-
-8. RUN ALL TESTS:
-Execute:
-- npm run test (all unit tests)
-- npm run test:integration (all integration tests)
-
-Fix any failures.
-
-9. VERIFY TYPE SAFETY:
-Execute:
-- npm run type-check or npx tsc --noEmit
-
-Fix any TypeScript errors.
-
-10. RUN LINTER:
-Execute:
-- npm run lint
-
-Fix any linting issues.
-
-VERIFICATION:
-- All unit tests passing
-- All integration tests passing
-- TypeScript compiles without errors
-- Linter passes
-- Vehicles feature successfully uses vehicle-data feature
-- Dropdown APIs work end-to-end
-- Test coverage >80% for new feature
-
-Return test results summary and any issues found.
-```
-
-**Success Criteria**:
-- ✅ Features integrated
-- ✅ Unit tests complete
-- ✅ Integration tests complete
-- ✅ All tests passing
-- ✅ Type-check passes
-- ✅ Linter passes
-
-**Estimated Time**: 2-3 hours
-
----
-
-## AGENT 6: Documentation Updates
-
-**Role**: Update all documentation to reflect 5-container architecture
-
-**Subagent Type**: `general-purpose`
-
-**Dependencies**: Agents 1, 2, 3, 4 complete
-
-**Deliverables**:
-- Updated architecture documentation
-- Updated API documentation
-- Updated feature documentation
-- Migration notes created
-
-**Prompt**:
-```
-Update all documentation to reflect the new 5-container architecture and removal of platform service.
-
-CONTEXT:
-- Platform service absorbed into backend as vehicle-data feature
-- VIN decoding removed
-- Architecture now 5 containers (was 6)
-
-TASKS:
-
-1. UPDATE ARCHITECTURE OVERVIEW:
-File: docs/ARCHITECTURE-OVERVIEW.md
-
-Changes:
-- Update container count: 6 → 5
-- Remove mvp-platform container from list
-- Add vehicle-data as backend feature module
-- Update architecture diagram (remove platform container)
-- Add note: "VIN decoding removed - users manually select vehicle details"
-
-2. UPDATE VEHICLES API DOCS:
-File: docs/VEHICLES-API.md
-
-Changes:
-- Remove all platform service references
-- Update API endpoints from /platform/* to /api/vehicle-data/*
-- Remove VIN decode endpoint documentation
-- Update dropdown endpoint documentation
-- Remove platform reset instructions
-- Update troubleshooting section
-
-3. UPDATE DATABASE SCHEMA DOCS:
-File: docs/DATABASE-SCHEMA.md
-
-Changes:
-- Clarify vehicles schema accessed by vehicle-data feature (backend module)
-- Remove VIN decode function references (f_decode_vin)
-- Add note: "vehicles schema managed by vehicle-data feature"
-
-4. UPDATE ROOT README:
-File: README.md
-
-Changes:
-- Line 1-3: Change "6 containers" to "5 containers"
-- Remove mvp-platform from container list
-- Update quick start section (5 containers expected)
-
-5. UPDATE CLAUDE.MD:
-File: CLAUDE.md
-
-Changes:
-- Line 94-95: Update architecture description to "5 containers: Traefik, Frontend, Backend, PostgreSQL, Redis"
-- Update "Integrated Platform service" to "vehicle-data feature module"
-- Remove references to separate platform service
-
-6. UPDATE AI-INDEX.MD:
-File: AI-INDEX.md
-
-Changes:
-- Update container count to 5
-- Update service list
-- Update any platform service references
-
-7. CREATE VEHICLE-DATA FEATURE README:
-File: backend/src/features/vehicle-data/README.md
-
-Content:
-```markdown
-# Vehicle Data Feature
-
-Provides hierarchical vehicle data (makes, models, trims, engines) for the vehicles feature.
-
-## Purpose
-Replaced the separate mvp-platform Python service. Now integrated as a backend feature module.
-
-## Architecture
-- Database: vehicles schema (separate from public schema)
-- Caching: Redis with 6-hour TTL
-- Authentication: JWT required on all endpoints
-
-## API Endpoints
-- GET /api/vehicle-data/years
-- GET /api/vehicle-data/makes?year={year}
-- GET /api/vehicle-data/models?year={year}&make_id={id}
-- GET /api/vehicle-data/trims?year={year}&model_id={id}
-- GET /api/vehicle-data/engines?year={year}&trim_id={id}
-
-## Database Tables
-vehicles.make, vehicles.model, vehicles.model_year, vehicles.trim, vehicles.engine, vehicles.trim_engine
-
-## Caching Strategy
-Redis keys: vehicle-data:makes:{year}, etc.
-TTL: 6 hours
-Graceful fallback if Redis unavailable
-
-## Notes
-- VIN decoding was removed (not part of this feature)
-- Users manually select vehicle details from dropdowns
-```
-
-8. UPDATE VEHICLES FEATURE README:
-File: backend/src/features/vehicles/README.md
-
-Changes:
-- Remove VIN decode documentation
-- Remove platform integration references
-- Update vehicle creation workflow: "Users manually select make/model/year from dropdowns provided by vehicle-data feature"
-- Update dependencies: Add vehicle-data feature
-
-9. CREATE MIGRATION NOTES:
-File: docs/PLATFORM-INTEGRATION-MIGRATION.md
-
-Content:
-```markdown
-# Platform Service Integration - Migration Notes
-
-## Date
-[Insert completion date]
-
-## Summary
-Integrated the separate mvp-platform Python service into the backend as a TypeScript feature module.
-
-## Changes
-
-### Architecture
-- Before: 6 containers (Traefik, Frontend, Backend, PostgreSQL, Redis, Platform)
-- After: 5 containers (Traefik, Frontend, Backend, PostgreSQL, Redis)
-
-### Features Removed
-- VIN decoding via NHTSA API
-- VIN auto-population of vehicle details
-- Separate platform container
-
-### Features Added
-- vehicle-data feature module in backend
-- Manual vehicle selection workflow (dropdowns)
-
-### Breaking Changes
-- VIN decode API endpoint removed
-- Vehicle creation now requires make/model/year in request
-- Frontend updated to use dropdowns instead of VIN decode
-
-### Technical Details
-- Python FastAPI code converted to TypeScript/Fastify
-- vehicles schema remains unchanged
-- Redis caching maintained (6-hour TTL)
-- API endpoints moved from /platform/* to /api/vehicle-data/*
-
-## Rationale
-Simplify architecture by reducing container count and unifying on Node.js/TypeScript stack.
-
-## Migration Path
-Single-phase cutover completed [date].
-```
-
-10. UPDATE DOCS README:
-File: docs/README.md
-
-Changes:
-- Update feature list to include vehicle-data
-- Update architecture summary (5 containers)
-
-VERIFICATION:
-- All references to "6 containers" changed to "5 containers"
-- No references to mvp-platform container
-- No references to VIN decode API
-- vehicle-data feature documented
-- Migration notes complete
-- All markdown files valid (no broken links)
-
-Return list of files updated with line numbers changed.
-```
-
-**Success Criteria**:
-- ✅ All architecture docs updated
-- ✅ API docs updated
-- ✅ Feature READMEs updated
-- ✅ Migration notes created
-- ✅ No references to 6 containers
-
-**Estimated Time**: 1-2 hours
-
----
-
-## AGENT 7: Container Removal & Deployment
-
-**Role**: Final cleanup, container removal, and deployment verification
-
-**Subagent Type**: `general-purpose`
-
-**Dependencies**: All other agents complete
-
-**Deliverables**:
-- Platform service directory archived
-- Docker images cleaned
-- Deployment verified
-- 5 containers running
-
-**Prompt**:
-```
-Perform final cleanup, remove platform service, and verify deployment.
-
-CONTEXT:
-All code changes complete. Ready for final cleanup and deployment.
-
-TASKS:
-
-1. ARCHIVE PLATFORM SERVICE:
-Move platform service to archive (don't delete from git history):
-mkdir -p /Users/egullickson/Documents/Technology/coding/motovaultpro/archive/platform-services/
-mv /Users/egullickson/Documents/Technology/coding/motovaultpro/mvp-platform-services/vehicles/ /Users/egullickson/Documents/Technology/coding/motovaultpro/archive/platform-services/
-
-Create archive README:
-File: archive/platform-services/README.md
-Content:
-```markdown
-# Archived Platform Services
-
-## vehicles/
-**Archived**: [date]
-**Reason**: Integrated into backend as vehicle-data feature module
-
-This Python FastAPI service was replaced by the TypeScript vehicle-data feature in backend/src/features/vehicle-data/.
-
-For migration details, see: docs/PLATFORM-INTEGRATION-MIGRATION.md
-```
-
-2. VERIFY DOCKER COMPOSE:
-Execute:
-docker compose config
-
-Verify:
-- Valid YAML (no errors)
-- Exactly 5 services defined
-- No references to mvp-platform
-
-3. STOP ALL CONTAINERS:
-Execute:
-docker compose down
-
-Verify all containers stopped:
-docker ps -a
-
-4. CLEAN UP DOCKER IMAGES:
-Remove old platform image:
-docker image rm motovaultpro-mvp-platform 2>/dev/null || true
-
-5. REBUILD BACKEND:
-Execute:
-docker compose build mvp-backend
-
-Verify build succeeds without errors.
-
-6. START ALL CONTAINERS:
-Execute:
-docker compose up -d
-
-Verify 5 containers start:
-docker ps
-
-Expected:
-- mvp-traefik
-- mvp-frontend
-- mvp-backend
-- mvp-postgres
-- mvp-redis
-
-7. VERIFY HEALTH CHECKS:
-Wait 60 seconds for startup.
-
-Check health:
-docker compose ps
-
-All containers should show "healthy" or "running".
-
-8. VERIFY DATABASE MIGRATIONS:
-Check vehicles schema exists:
-docker compose exec mvp-postgres psql -U postgres -d motovaultpro -c "\dn"
-
-Should see "vehicles" schema.
-
-Check tables exist:
-docker compose exec mvp-postgres psql -U postgres -d motovaultpro -c "\dt vehicles.*"
-
-Should see: make, model, model_year, trim, engine, trim_engine
-
-9. TEST VEHICLE-DATA ENDPOINTS:
-Execute (requires JWT token):
-curl http://localhost/api/vehicle-data/years
-
-Expected: [2024, 2023, ...]
-
-Execute:
-curl http://localhost/api/vehicle-data/makes?year=2024
-
-Expected: {"makes": [{id: 1, name: "Honda"}, ...]}
-
-10. TEST FRONTEND:
-Open: http://localhost
-
-Navigate to vehicles page.
-Verify:
-- Dropdowns load (years, makes, models)
-- Can create vehicle by selecting from dropdowns
-- No VIN decode button visible
-- Vehicle creation works
-
-11. MONITOR LOGS:
-Execute:
-docker compose logs -f mvp-backend
-
-Watch for:
-- No errors on startup
-- Vehicle-data endpoints responding
-- No calls to mvp-platform (should be gone)
-
-12. VERIFY REDIS CACHING:
-Execute:
-docker compose exec mvp-redis redis-cli
-
-Run:
-KEYS vehicle-data:*
-
-After making API calls, should see cached keys.
-
-Run:
-GET vehicle-data:makes:2024
-
-Should see JSON data.
-
-13. PERFORMANCE CHECK:
-Test response times:
-time curl http://localhost/api/vehicle-data/years
-
-Should be <500ms after cache warm-up.
-
-14. FINAL VERIFICATION CHECKLIST:
-- [ ] 5 containers running (not 6)
-- [ ] All health checks passing
-- [ ] Vehicle-data API endpoints responding
-- [ ] Redis caching working
-- [ ] Frontend loads without errors
-- [ ] Vehicle creation works
-- [ ] No platform service references in logs
-- [ ] No errors in docker logs
-
-VERIFICATION:
-Return:
-- Output of: docker ps (should show 5 containers)
-- Output of: curl http://localhost/api/vehicle-data/years
-- Confirmation that frontend works
-- Any errors encountered
-- Performance metrics (response times)
-
-If any issues found, provide rollback instructions.
-```
-
-**Success Criteria**:
-- ✅ Platform service archived
-- ✅ 5 containers running
-- ✅ Health checks passing
-- ✅ APIs responding
-- ✅ Frontend working
-- ✅ No errors in logs
-
-**Estimated Time**: 1-2 hours
-
----
-
-## Dependency Graph
-
-```
-Wave 1 (Parallel):
-┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
-│ Agent 1 │ │ Agent 2 │ │ Agent 3 │ │ Agent 4 │
-│ Backend │ │ VIN Rem │ │ VIN Rem │ │Configuration │
-│ Feature │ │ Backend │ │ Frontend │ │ Cleanup │
-└──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘
- │ │ │ │
- └─────────┬───────┴─────────────────┴─────────────────┘
- │
-Wave 2 (Parallel): │
- ┌────────▼────────┐ ┌─────────────────┐
- │ Agent 5 │ │ Agent 6 │
- │ Integration │ │ Documentation │
- │ & Testing │ │ Updates │
- └────────┬────────┘ └────────┬────────┘
- │ │
-Wave 3: └──────────┬─────────┘
- │
- ┌──────────▼────────┐
- │ Agent 7 │
- │ Container │
- │ Removal & │
- │ Deployment │
- └───────────────────┘
-```
-
----
-
-## Execution Instructions
-
-### Start Wave 1 (4 agents in parallel):
-```bash
-# Spawn all 4 agents simultaneously
-/task agent1_prompt
-/task agent2_prompt
-/task agent3_prompt
-/task agent4_prompt
-```
-
-### Wait for Wave 1 Completion
-Monitor all 4 agents. When all report completion:
-- Review deliverables
-- Verify no conflicts
-- Commit changes from Wave 1
-
-### Start Wave 2 (2 agents in parallel):
-```bash
-# Spawn 2 agents simultaneously
-/task agent5_prompt
-/task agent6_prompt
-```
-
-### Wait for Wave 2 Completion
-When both agents complete:
-- Run all tests
-- Review documentation
-- Commit changes from Wave 2
-
-### Start Wave 3 (1 agent):
-```bash
-# Spawn final agent
-/task agent7_prompt
-```
-
-### Final Verification
-When Agent 7 completes:
-- Verify 5 containers running
-- Test all functionality
-- Create git tag: `v1.0-platform-integrated`
-
----
-
-## Rollback Plan
-
-If critical issues during deployment:
-
-1. **Restore docker-compose.yml**:
- ```bash
- git restore docker-compose.yml
- ```
-
-2. **Restore platform service**:
- ```bash
- mv archive/platform-services/vehicles/ mvp-platform-services/
- ```
-
-3. **Rebuild containers**:
- ```bash
- docker compose down
- docker compose up -d
- ```
-
-4. **Revert backend changes**:
- ```bash
- git revert HEAD~[n] # Revert last n commits
- ```
-
-5. **Rebuild backend**:
- ```bash
- docker compose build mvp-backend
- docker compose restart mvp-backend
- ```
-
----
-
-## Success Metrics
-
-- ✅ 5 containers running (down from 6)
-- ✅ All automated tests passing
-- ✅ Vehicle dropdown APIs <500ms response time
-- ✅ Redis cache hit rate >80% after warm-up
-- ✅ Zero errors in logs after 1 hour
-- ✅ Frontend vehicle creation works on mobile + desktop
-- ✅ All documentation updated
-- ✅ TypeScript compiles without warnings
-- ✅ Linter passes
-
----
-
-## Estimated Timeline
-
-**Total**: 6-8 hours with parallel execution
-
-| Wave | Duration | Agents |
-|------|----------|--------|
-| Wave 1 | 3-4 hours | 4 parallel |
-| Wave 2 | 2-3 hours | 2 parallel |
-| Wave 3 | 1-2 hours | 1 sequential |
-
-**Sequential Execution**: 12-16 hours
-**Parallel Execution**: 6-8 hours
-**Time Saved**: 50%
-
----
-
-## Notes
-
-- Each agent is independent in Wave 1 (no conflicts expected)
-- Wave 2 depends on Wave 1 code changes
-- Wave 3 is deployment only (must be last)
-- Use feature branches for each wave if needed
-- Test after each wave before proceeding
-- Commit after each wave for easy rollback
-
----
-
-## Agent Communication Protocol
-
-Agents should report:
-1. **Start**: "Agent [N] starting [task]"
-2. **Progress**: Regular updates every 30 minutes
-3. **Blockers**: Immediate report if stuck
-4. **Completion**: "Agent [N] complete - [deliverables]"
-5. **Handoff**: Files created/modified for next wave
-
-Coordinator (you) should:
-- Monitor all agents in parallel
-- Resolve conflicts between agents
-- Gate Wave 2 until Wave 1 100% complete
-- Gate Wave 3 until Wave 2 100% complete
-- Make final deployment decision
\ No newline at end of file
diff --git a/docs/PLATFORM-INTEGRATION-MIGRATION.md b/docs/PLATFORM-INTEGRATION-MIGRATION.md
deleted file mode 100644
index 6bd681a..0000000
--- a/docs/PLATFORM-INTEGRATION-MIGRATION.md
+++ /dev/null
@@ -1,252 +0,0 @@
-# Platform Service Integration - Migration Notes
-
-## Date
-2025-11-03
-
-## Summary
-Integrated the separate mvp-platform Python service into the backend as a TypeScript feature module.
-
-## Changes
-
-### Architecture
-- **Before**: 6 containers (Traefik, Frontend, Backend, PostgreSQL, Redis, Platform)
-- **After**: 5 containers (Traefik, Frontend, Backend, PostgreSQL, Redis)
-
-### Features MIGRATED (Not Removed)
-- VIN decoding via vPIC API (migrated to platform feature)
-- Vehicle hierarchical data lookups (makes/models/trims/engines)
-- PostgreSQL VIN decode function integration
-- Redis caching with 6-hour TTL (vehicle data) and 7-day TTL (VIN decode)
-
-### Features Removed
-- Separate mvp-platform container (Python FastAPI service)
-- External HTTP calls to platform service (http://mvp-platform:8000)
-- Platform service API key and secrets
-
-### Features Added
-- Platform feature module in backend (`backend/src/features/platform/`)
-- Unified API endpoints under `/api/platform/*`
-- Circuit breaker for vPIC API resilience (opossum library)
-- Dual user workflow (VIN decode OR manual dropdown selection)
-- PostgreSQL-first VIN decode strategy with vPIC fallback
-
-### Breaking Changes
-- API endpoints moved from old locations to `/api/platform/*`
-- VIN decode endpoint changed from POST to GET request
-- Frontend updated to use new unified endpoints
-- External platform service URL removed from environment variables
-
-### Technical Details
-- **Python FastAPI → TypeScript/Fastify**: Complete code conversion
-- **vehicles schema**: Remains unchanged, accessed by platform feature
-- **Redis caching**: Maintained with same TTL strategy
-- **VIN decode strategy**: PostgreSQL function → vPIC API (circuit breaker protected)
-- **Authentication**: JWT required on all platform endpoints
-
-## Rationale
-Simplify architecture by:
-- Reducing container count (6 → 5)
-- Unifying on Node.js/TypeScript stack
-- Eliminating inter-service HTTP calls
-- Improving development experience
-- Reducing deployment complexity
-
-## Migration Path
-Single-phase cutover completed 2025-11-03 with parallel agent execution:
-
-### Wave 1 (Parallel - 4 agents):
-1. **Platform Feature Creator**: Created `backend/src/features/platform/`
-2. **VIN Migration - Backend**: Migrated VIN logic from vehicles to platform
-3. **VIN Migration - Frontend**: Updated to `/api/platform/*` endpoints
-4. **Configuration Cleanup**: Removed platform container from docker-compose
-
-### Wave 2 (Parallel - 2 agents):
-5. **Integration & Testing**: Verified integration and tests
-6. **Documentation Updates**: Updated all documentation
-
-### Wave 3 (Sequential - 1 agent):
-7. **Container Removal & Deployment**: Archive and final verification
-
-## Agents Used
-
-### Agent 1: Platform Feature Creator
-- Created complete feature structure
-- Converted Python to TypeScript
-- Implemented VIN decode with circuit breaker
-- Created unit and integration tests
-
-### Agent 2: VIN Migration - Backend
-- Migrated VIN decode from vehicles feature
-- Updated vehicles service to use platform
-- Removed external platform client
-
-### Agent 3: VIN Migration - Frontend
-- Updated API calls to `/api/platform/*`
-- Kept VIN decode functionality
-- Enhanced mobile responsiveness
-
-### Agent 4: Configuration Cleanup
-- Removed mvp-platform from docker-compose
-- Cleaned environment variables
-- Updated Makefile
-
-## Verification
-
-### Integration Points
-- Vehicles service calls `getVINDecodeService()` from platform feature (vehicles.service.ts:46, 229)
-- Platform routes registered in app.ts (app.ts:22, 110)
-- Frontend uses `/api/platform/vehicle?vin=X` for VIN decode
-- Frontend uses `/api/platform/years`, `/api/platform/makes`, etc. for dropdowns
-
-### Testing
-- Platform feature: Unit tests for VIN decode and vehicle data services
-- Platform feature: Integration tests for all API endpoints
-- Vehicles feature: Updated tests to mock platform service
-
-### Performance
-- VIN decode: < 500ms with cache
-- Dropdown APIs: < 100ms with cache
-- Redis cache hit rate: Target >80% after warm-up
-
-## API Endpoint Changes
-
-### Old Endpoints (Deprecated)
-```
-POST /api/vehicles/decode-vin
-GET /api/vehicles/dropdown/years
-GET /api/vehicles/dropdown/makes?year={year}
-GET /api/vehicles/dropdown/models?year={year}&make_id={id}
-```
-
-### New Endpoints (Active)
-```
-GET /api/platform/vehicle?vin={vin}
-GET /api/platform/years
-GET /api/platform/makes?year={year}
-GET /api/platform/models?year={year}&make_id={id}
-GET /api/platform/trims?year={year}&model_id={id}
-GET /api/platform/engines?year={year}&trim_id={id}
-```
-
-## User Experience Changes
-
-### Before Migration
-- VIN decode: Required separate platform service
-- Manual selection: Dropdowns via vehicles API
-- Limited mobile optimization
-
-### After Migration
-- VIN decode: Integrated platform feature with circuit breaker resilience
-- Manual selection: Unified `/api/platform/*` endpoints
-- Dual workflow: Users can VIN decode OR manually select
-- Enhanced mobile: 44px touch targets, 16px fonts (no iOS zoom)
-
-## Rollback Plan
-
-If critical issues discovered:
-
-1. Restore docker-compose.yml:
-```bash
-git restore docker-compose.yml
-```
-
-2. Restore platform service directory:
-```bash
-git restore mvp-platform-services/
-```
-
-3. Rebuild containers:
-```bash
-docker compose down
-docker compose up -d
-```
-
-4. Revert code changes:
-```bash
-git revert HEAD~[n]
-```
-
-## Success Metrics
-
-- Container count: 5 (down from 6)
-- All automated tests: Passing
-- VIN decode response time: <500ms
-- Redis cache hit rate: >80% (after warm-up)
-- Zero errors in logs: After 1 hour runtime
-- Mobile + desktop: Both workflows functional
-- TypeScript compilation: Zero errors
-- Linter: Zero issues
-
-## Files Created
-
-### Backend
-- `backend/src/features/platform/` (14 files total)
- - API layer: routes, controller
- - Domain layer: VIN decode, vehicle data, cache services
- - Data layer: repository, vPIC client
- - Models: requests, responses
- - Tests: unit and integration
- - Documentation: README.md
-
-### Documentation
-- `docs/PLATFORM-INTEGRATION-MIGRATION.md` (this file)
-
-## Files Modified
-
-### Configuration
-- `docker-compose.yml` - Removed mvp-platform service
-- `.env` - Removed platform URL
-- `config/app/production.yml` - Removed platform config
-- `Makefile` - Updated to 5-container architecture
-
-### Backend
-- `backend/src/app.ts` - Registered platform routes
-- `backend/src/features/vehicles/domain/vehicles.service.ts` - Uses platform VIN decode
-- `backend/src/features/vehicles/tests/unit/vehicles.service.test.ts` - Updated mocks
-
-### Frontend
-- `frontend/src/features/vehicles/api/vehicles.api.ts` - Updated endpoints
-- `frontend/src/features/vehicles/components/VehicleForm.tsx` - Mobile enhancements
-
-### Documentation
-- `README.md` - Updated to 5 containers
-- `CLAUDE.md` - Updated architecture description
-- `docs/README.md` - Updated container count and feature list
-
-## Files Deleted
-
-### Backend
-- `backend/src/features/vehicles/external/platform-vehicles/` (entire directory)
-- `backend/src/features/vehicles/domain/platform-integration.service.ts`
-- `backend/src/features/vehicles/external/vpic/` (moved to platform)
-- `backend/src/features/vehicles/tests/unit/vpic.client.test.ts`
-
-## Future Considerations
-
-### Potential Enhancements
-- Batch VIN decode endpoint
-- Alternative VIN decode APIs (CarMD, Edmunds)
-- Part number lookups
-- Service bulletin integration
-- Recall information integration
-- Admin cache invalidation endpoints
-
-### Monitoring
-- Track cache hit rates
-- Monitor circuit breaker state transitions
-- Log slow queries (>200ms)
-- Alert on high error rates
-- Dashboard for vPIC API health
-
-## Related Documentation
-
-- Platform Feature README: `backend/src/features/platform/README.md`
-- Architecture Overview: `docs/PLATFORM-SERVICES.md`
-- Vehicles Feature: `backend/src/features/vehicles/README.md`
-- API Documentation: Platform README contains complete API reference
-
----
-
-**Migration Status**: COMPLETE
-
-The platform service has been successfully integrated into the backend as a feature module. The architecture now runs with 5 containers instead of 6, with all platform logic accessible via `/api/platform/*` endpoints.
diff --git a/docs/PLATFORM-INTEGRATION-TESTING.md b/docs/PLATFORM-INTEGRATION-TESTING.md
deleted file mode 100644
index ae58df9..0000000
--- a/docs/PLATFORM-INTEGRATION-TESTING.md
+++ /dev/null
@@ -1,335 +0,0 @@
-# Platform Integration Testing Guide
-
-## Prerequisites
-
-Docker must be running:
-```bash
-# Check Docker status
-docker compose ps
-
-# If not running, start containers
-make rebuild # Rebuilds with all changes
-make start # Starts all services
-```
-
-## Testing Sequence
-
-### 1. TypeScript Compilation Verification
-
-```bash
-# In backend container
-docker compose exec mvp-backend npm run type-check
-
-# Expected: No TypeScript errors
-```
-
-### 2. Linter Verification
-
-```bash
-# In backend container
-docker compose exec mvp-backend npm run lint
-
-# Expected: Zero linting issues
-```
-
-### 3. Platform Feature Unit Tests
-
-```bash
-# Run all platform unit tests
-docker compose exec mvp-backend npm test -- features/platform/tests/unit
-
-# Expected tests:
-# - vin-decode.service.test.ts (VIN validation, circuit breaker, caching)
-# - vehicle-data.service.test.ts (dropdown data, caching)
-```
-
-### 4. Platform Feature Integration Tests
-
-```bash
-# Run platform integration tests
-docker compose exec mvp-backend npm test -- features/platform/tests/integration
-
-# Expected tests:
-# - GET /api/platform/years
-# - GET /api/platform/makes?year=2024
-# - GET /api/platform/models?year=2024&make_id=1
-# - GET /api/platform/trims?year=2024&model_id=1
-# - GET /api/platform/engines?year=2024&trim_id=1
-# - GET /api/platform/vehicle?vin=1HGCM82633A123456
-# - Authentication (401 without JWT)
-# - Validation (400 for invalid params)
-```
-
-### 5. Vehicles Feature Integration Tests
-
-```bash
-# Run vehicles integration tests
-docker compose exec mvp-backend npm test -- features/vehicles/tests/integration
-
-# Expected: VIN decode now uses platform feature
-```
-
-### 6. End-to-End Workflow Tests
-
-#### VIN Decode Workflow
-```bash
-# 1. Start containers
-make start
-
-# 2. Get auth token (via frontend or Auth0 test token)
-
-# 3. Test VIN decode endpoint
-curl -H "Authorization: Bearer YOUR_TOKEN" \
- http://localhost:3001/api/platform/vehicle?vin=1HGCM82633A123456
-
-# Expected:
-# {
-# "vin": "1HGCM82633A123456",
-# "success": true,
-# "result": {
-# "make": "Honda",
-# "model": "Accord",
-# "year": 2003,
-# ...
-# }
-# }
-```
-
-#### Dropdown Cascade Workflow
-```bash
-# 1. Get years
-curl -H "Authorization: Bearer YOUR_TOKEN" \
- http://localhost:3001/api/platform/years
-
-# Expected: [2024, 2023, 2022, ...]
-
-# 2. Get makes for 2024
-curl -H "Authorization: Bearer YOUR_TOKEN" \
- http://localhost:3001/api/platform/makes?year=2024
-
-# Expected: {"makes": [{"id": 1, "name": "Honda"}, ...]}
-
-# 3. Get models for Honda 2024
-curl -H "Authorization: Bearer YOUR_TOKEN" \
- http://localhost:3001/api/platform/models?year=2024&make_id=1
-
-# Expected: {"models": [{"id": 101, "name": "Civic"}, ...]}
-```
-
-### 7. Frontend Testing
-
-#### Desktop Testing
-```bash
-# 1. Open browser
-open https://motovaultpro.com
-
-# 2. Navigate to Vehicles → Add Vehicle
-
-# 3. Test VIN decode:
-# - Enter VIN: 1HGCM82633A123456
-# - Click "Decode VIN"
-# - Verify auto-population of make/model/year
-
-# 4. Test manual selection:
-# - Select Year: 2024
-# - Select Make: Honda
-# - Select Model: Civic
-# - Verify cascading dropdowns work
-```
-
-#### Mobile Testing
-```bash
-# Use Chrome DevTools responsive mode
-
-# Test at widths:
-# - 320px (iPhone SE)
-# - 375px (iPhone 12)
-# - 768px (iPad)
-# - 1920px (Desktop)
-
-# Verify:
-# - 44px minimum touch targets
-# - No iOS zoom on input focus (16px font)
-# - Dropdowns work on touch devices
-# - VIN decode button accessible
-# - Both workflows functional
-```
-
-### 8. Performance Testing
-
-```bash
-# Monitor response times
-time curl -H "Authorization: Bearer YOUR_TOKEN" \
- http://localhost:3001/api/platform/years
-
-# Expected: < 500ms (first call, cache miss)
-# Expected: < 100ms (second call, cache hit)
-```
-
-### 9. Cache Verification
-
-```bash
-# Connect to Redis
-docker compose exec mvp-redis redis-cli
-
-# Check cache keys
-KEYS mvp:platform:*
-
-# Expected keys:
-# - mvp:platform:years
-# - mvp:platform:vehicle-data:makes:2024
-# - mvp:platform:vin-decode:1HGCM82633A123456
-
-# Check TTL
-TTL mvp:platform:vehicle-data:makes:2024
-# Expected: ~21600 seconds (6 hours)
-
-TTL mvp:platform:vin-decode:1HGCM82633A123456
-# Expected: ~604800 seconds (7 days)
-
-# Get cached value
-GET mvp:platform:years
-# Expected: JSON array of years
-```
-
-### 10. Error Handling Tests
-
-```bash
-# Test invalid VIN (wrong length)
-curl -H "Authorization: Bearer YOUR_TOKEN" \
- http://localhost:3001/api/platform/vehicle?vin=INVALID
-
-# Expected: 400 Bad Request
-
-# Test missing auth
-curl http://localhost:3001/api/platform/years
-
-# Expected: 401 Unauthorized
-
-# Test invalid year
-curl -H "Authorization: Bearer YOUR_TOKEN" \
- http://localhost:3001/api/platform/makes?year=3000
-
-# Expected: 400 Bad Request or empty array
-```
-
-### 11. Circuit Breaker Testing
-
-```bash
-# Monitor backend logs
-make logs-backend | grep "circuit breaker"
-
-# Should see:
-# - State transitions (open/half-open/close)
-# - Timeout events
-# - Fallback executions
-
-# Test with invalid VIN that requires vPIC API
-curl -H "Authorization: Bearer YOUR_TOKEN" \
- http://localhost:3001/api/platform/vehicle?vin=UNKNOWNVIN1234567
-
-# Check logs for circuit breaker activity
-```
-
-### 12. Container Health Check
-
-```bash
-# Verify 5 containers running
-docker compose ps
-
-# Expected output:
-# mvp-traefik - running
-# mvp-frontend - running
-# mvp-backend - running
-# mvp-postgres - running
-# mvp-redis - running
-
-# No mvp-platform container should exist
-
-# Check backend health
-curl http://localhost:3001/health
-
-# Expected:
-# {
-# "status": "healthy",
-# "features": ["vehicles", "documents", "fuel-logs", "stations", "maintenance", "platform"]
-# }
-```
-
-## Success Criteria
-
-- TypeScript compilation: Zero errors
-- Linter: Zero issues
-- Unit tests: All passing
-- Integration tests: All passing
-- VIN decode workflow: Functional
-- Dropdown cascade workflow: Functional
-- Mobile + desktop: Both responsive and functional
-- Cache hit rate: >80% after warm-up
-- Response times: <500ms VIN decode, <100ms dropdowns
-- 5 containers: Running healthy
-- Zero errors: In logs after 1 hour
-
-## Troubleshooting
-
-### TypeScript Errors
-```bash
-# Check compilation
-docker compose exec mvp-backend npm run type-check
-
-# If errors, review files modified by agents
-```
-
-### Test Failures
-```bash
-# Run specific test
-docker compose exec mvp-backend npm test -- path/to/test.ts
-
-# Check test logs for details
-```
-
-### VIN Decode Not Working
-```bash
-# Check backend logs
-make logs-backend | grep -E "vin|platform"
-
-# Verify vPIC API accessible
-curl https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVin/1HGCM82633A123456?format=json
-
-# Check circuit breaker state in logs
-```
-
-### Dropdowns Empty
-```bash
-# Check PostgreSQL vehicles schema
-docker compose exec mvp-postgres psql -U postgres -d motovaultpro -c "\\dt vehicles.*"
-
-# Query makes table
-docker compose exec mvp-postgres psql -U postgres -d motovaultpro -c "SELECT COUNT(*) FROM vehicles.make;"
-
-# Should have data
-```
-
-### Frontend Not Loading
-```bash
-# Check frontend logs
-make logs-frontend
-
-# Rebuild frontend
-docker compose build mvp-frontend
-docker compose restart mvp-frontend
-```
-
-## Next Steps After Testing
-
-If all tests pass:
-1. Create git tag: `v1.0-platform-integrated`
-2. Document any issues in GitHub
-3. Monitor production logs for 24 hours
-4. Archive Python platform service directory
-
-If tests fail:
-1. Review failure logs
-2. Fix issues
-3. Re-run tests
-4. Consider rollback if critical failures