Added detailed logging to diagnose import merge issues:
- Log vehicle count at merge start
- Log each vehicle being processed with VIN/make/model/year
- Log when existing vehicles are found (by VIN or license plate)
- Log successful vehicle creation with new vehicle ID
- Log errors with full context (userId, VIN, make, model, error message)
- Log merge completion with summary statistics
This will help diagnose why vehicles show as "successfully imported" but don't appear in the UI.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Desktop changes:
- Replace ImportButton component with MUI Button matching Export style
- Use hidden file input with validation
- Dark red/maroon button with consistent styling
Mobile changes:
- Update both Import and Export buttons to use primary-500 style
- Consistent dark primary button appearance
- Maintains 44px touch target requirement
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement archive service to extract and validate user data import archives. Validates manifest structure, data files, and ensures archive format compatibility with export feature.
- user-import.types.ts: Type definitions for import feature
- user-import-archive.service.ts: Archive extraction and validation
- Validates manifest version (1.0.0) and required fields
- Validates all data files exist and contain valid JSON
- Temp directory pattern mirrors export (/tmp/user-import-work)
- Cleanup method for archive directories
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add batchInsert methods to vehicles, fuel-logs, maintenance, and documents repositories. Multi-value INSERT syntax provides 10-100x performance improvement over individual operations for bulk data import.
- vehicles.repository: batchInsert for vehicles
- fuel-logs.repository: batchInsert for fuel logs
- maintenance.repository: batchInsertRecords and batchInsertSchedules
- documents.repository: batchInsert for documents
- All methods support empty array (immediate return) and optional transaction client
- Fix lint error: replace require() with ES6 import in test mock
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
PostgreSQL error 0A000 (feature_not_supported) occurs when using
FOR UPDATE with aggregate functions like COUNT(*). Row-level locking
requires actual rows to lock.
Changes:
- Select id column instead of COUNT(*) aggregate
- Count rows in application using .length
- Maintains transaction isolation and race condition prevention
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Backend: Enhanced matchField function with prefix and contains matching
so NHTSA values like "Sierra" match dropdown options like "Sierra 1500".
Matching hierarchy:
1. Exact match (case-insensitive) -> high confidence
2. Normalized match (remove special chars) -> medium confidence
3. Prefix match (option starts with value) -> medium confidence (NEW)
4. Contains match (option contains value) -> medium confidence (NEW)
Frontend: Fixed VIN decode form population by loading dropdown options
before setting form values, preventing cascade useEffects from clearing
decoded values.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
VIN decode was setting year/make/model/trim values, but the cascading
dropdown useEffects would immediately clear dependent fields because
they detected a value change. Added isVinDecoding ref flag (mirroring
the existing isInitializing pattern for edit mode) to skip cascade
clearing during VIN decode and properly load dropdown options.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add VIN decode endpoint to API section
- Document request/response format with confidence levels
- Add error response examples (400, 403, 502)
- Update architecture diagram with external/ directory
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add NHTSA client for VIN decoding with caching and validation
- Add POST /api/vehicles/decode-vin endpoint with tier gating
- Add dropdown matching service with confidence levels
- Add decode button to VehicleForm with tier check
- Responsive layout: stacks on mobile, inline on desktop
- Only populate empty fields (preserve user input)
Backend:
- NHTSAClient with 5s timeout, VIN validation, vin_cache table
- Tier gating with 'vehicle.vinDecode' feature key (Pro+)
- Tiered matching: high (exact), medium (normalized), none
Frontend:
- Decode button with loading state and error handling
- UpgradeRequiredDialog for free tier users
- Mobile-first responsive layout
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add userEmail field to AuditLogEntry type in backend and frontend
- Update audit-log repository to LEFT JOIN with user_profiles table
- Update AdminLogsPage to show email with fallback to truncated userId
- Update AdminLogsMobileScreen with same display logic
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Backend:
- Add login event logging to getUserStatus() controller method
- Create POST /auth/track-logout endpoint for logout tracking
Frontend:
- Create useLogout hook that wraps Auth0 logout with audit tracking
- Update all logout locations to use the new hook (SettingsPage,
Layout, MobileSettingsScreen, useDeletion)
Login events are logged when the frontend calls /auth/user-status after
Auth0 callback. Logout events are logged via fire-and-forget call to
/auth/track-logout before Auth0 logout.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The audit_logs table migration was not being executed because the
audit-log feature was missing from MIGRATION_ORDER in run-all.ts,
causing 500 errors when accessing the audit logs API.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The routes and screen components for AdminLogsPage were implemented but
the navigation links to access them were missing from both desktop and
mobile Settings pages.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The old /api/admin/audit-logs route in admin.routes.ts conflicted with the
new centralized audit-log feature. Removed the old route since we're now
using the unified audit logging system.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add audit_logs table with categories, severities, and indexes
- Create AuditLogService and AuditLogRepository
- Add REST API endpoints for viewing and exporting logs
- Wire audit logging into auth, vehicles, admin, and backup features
- Add desktop AdminLogsPage with filters and CSV export
- Add mobile AdminLogsMobileScreen with card layout
- Implement 90-day retention cleanup job
- Remove old AuditLogPanel from AdminCatalogPage
Security fixes:
- Escape LIKE special characters to prevent pattern injection
- Limit CSV export to 5000 records to prevent memory exhaustion
- Add truncation warning headers for large exports
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace per-schedule count-based retention with unified tiered classification.
Backups are now classified by timestamp into categories (hourly/daily/weekly/monthly)
and are only deleted when they exceed ALL applicable category quotas.
Changes:
- Add backup-classification.service.ts for timestamp-based classification
- Rewrite backup-retention.service.ts with tiered logic
- Add categories and expires_at columns to backup_history
- Add Expires column to desktop and mobile backup UI
- Add unit tests for classification logic (22 tests)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
File inputs are replaced elements that ignore CSS centering properties.
The only reliable solution is to wrap the input in a flex container
with items-center.
Changes:
- Added wrapper div with `flex items-center h-11`
- Moved border/background/focus styles to the wrapper
- Input now uses flex-1 to fill available space
- Used focus-within for focus ring on wrapper
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use leading-[44px] to match the h-11 height, which should vertically
center the file input content. Removed padding that was conflicting.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The "Choose File" button and "No file chosen" text were not vertically
centered within the file input box.
Fixed by:
- Using py-2.5 for input padding (10px top/bottom)
- Adding file:my-auto to center the button vertically
- Adjusting file:py-1.5 for button internal padding
Note: flex/items-center don't work on <input> elements as they are
replaced elements. Using padding and margin-auto instead.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The "Choose File" button and "No file chosen" text were not vertically
centered within the file input. This was caused by:
1. Browser default `align-items: baseline` for file inputs
2. Conflicting `py-2` padding on the input container
Fixed by:
- Removing `py-2` (conflicting vertical padding)
- Adding `flex items-center` (explicit vertical centering)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add GET /api/admin/stats endpoint for Total Vehicles widget
- Add GET /api/admin/users/:auth0Sub/vehicles endpoint for user vehicle list
- Update AdminUsersPage with Total Vehicles stat and expandable vehicle rows
- Add My Vehicles section to SettingsPage (desktop) and MobileSettingsScreen
- Update AdminUsersMobileScreen with stats header and vehicle expansion
- Add defense-in-depth admin checks and error handling
- Update admin README documentation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The mobile FAB 'Maintenance' option was navigating to the Vehicles screen
instead of the Maintenance screen. Updated handleQuickAction to navigate
to 'Maintenance' which displays MaintenanceMobileScreen.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>