Replace NHTSAClient with OcrClient in vehicles controller. Move cache
logic into VehiclesService with format-aware reads (Gemini vs legacy
NHTSA entries). Rename nhtsaValue to sourceValue in MatchedField.
Remove vpic config from Zod schema and YAML config files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users with both auth0_sub and UUID rows in user_preferences get the same
user_profile_id after backfill, causing unique constraint violation on
rename. Keep the newest row per user_profile_id.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
user_preferences had rows where user_id already contained user_profiles.id
(UUID) instead of auth0_sub. Added second backfill pass matching UUID-format
values directly, and cleanup for 2 orphaned rows with no matching profile.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend test fixtures:
- Replace auth0|xxx format with UUID in all test userId values
- Update admin tests for new id/userProfileId schema
- Add missing deletionRequestedAt/deletionScheduledFor to auth test mocks
- Fix admin integration test supertest usage (app.server)
Frontend:
- AdminUser type: auth0Sub -> id + userProfileId
- admin.api.ts: all user management methods use userId (UUID) params
- useUsers/useAdmins hooks: auth0Sub -> userId/id in mutations
- AdminUsersPage + AdminUsersMobileScreen: user.auth0Sub -> user.id
- Remove encodeURIComponent (UUIDs don't need encoding)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Updated user-profile.repository.ts to use UUID instead of auth0_sub:
- Added getById(id) method for UUID-based lookups
- Changed all methods (except getByAuth0Sub, getOrCreate) to accept userId (UUID) instead of auth0Sub
- Updated SQL WHERE clauses from auth0_sub to id for UUID-based queries
- Fixed cross-table joins in listAllUsers and getUserWithAdminStatus to use user_profile_id
- Updated hardDeleteUser to use UUID for all DELETE statements
- Updated auth.plugin.ts to call updateEmail and updateEmailVerified with userId (UUID)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Auth plugin now uses profile.id (UUID) as userContext.userId instead
of raw JWT sub. Admin guard queries admin_users by user_profile_id.
Auth0 Management API calls continue using auth0Sub from JWT.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Multi-phase SQL migration converting all user_id columns from
VARCHAR(255) auth0_sub to UUID referencing user_profiles.id.
Restructures admin_users with UUID PK and user_profile_id FK.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add receipt_document_id FK on maintenance_records, update types/repo/service
to support receipt linking on create and return document metadata on GET.
Add OCR proxy endpoint POST /api/ocr/extract/maintenance-receipt with
tier gating (maintenance.receiptScan) through full chain: routes -> controller
-> service -> client.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Create reusable preHandler middleware for subscription tier gating.
Composable with requireAuth in route preHandler arrays. Returns 403
TIER_REQUIRED with upgrade prompt for insufficient tier, 500 for
unknown feature keys. Includes 9 unit tests covering all acceptance
criteria.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add/update documentation across backend, Python OCR service, and frontend
for receipt scanning, manual extraction, and Gemini integration. Create
new CLAUDE.md files for engines/, fuel-logs/, documents/, and maintenance/
features.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace Winston with Pino using API-compatible wrapper
- Add LOG_LEVEL env var support with validation and fallback
- Add correlation ID middleware (X-Request-Id from Traefik or UUID)
- Configure PostgreSQL logging env vars (POSTGRES_LOG_STATEMENT, POSTGRES_LOG_MIN_DURATION)
- Configure Redis loglevel via command args
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
API Endpoints (all authenticated):
- GET /api/subscriptions - current subscription status
- POST /api/subscriptions/checkout - create Stripe subscription
- POST /api/subscriptions/cancel - schedule cancellation at period end
- POST /api/subscriptions/reactivate - cancel pending cancellation
- PUT /api/subscriptions/payment-method - update payment method
- GET /api/subscriptions/invoices - billing history
Grace Period Job:
- Daily cron at 2:30 AM to check expired grace periods
- Downgrades to free tier when 30-day grace period expires
- Syncs tier to user_profiles.subscription_tier
Email Templates:
- payment_failed_immediate (first failure)
- payment_failed_7day (7 days before grace ends)
- payment_failed_1day (1 day before grace ends)
🤖 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 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>