Prompt vehicle selection on login after auto-downgrade to free tier #60
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
When a user's subscription is auto-downgraded to free tier (via grace period expiration) and they have more than 2 vehicles, they should be prompted to select which 2 vehicles to keep active on their next login.
Related
Current Behavior
The
VehicleSelectionDialogexists and works during manual downgrade flows (when user initiates downgrade), but there is no automatic prompt on login after a grace period auto-downgrade.Expected Behavior
On app load (after authentication), check if:
tier_vehicle_selections)If all conditions are met, show the VehicleSelectionDialog forcing user to select 2 vehicles
Until selection is made, user should not be able to navigate elsewhere in the app
Implementation Notes
Backend:
GET /api/subscriptions/needs-vehicle-selection{ needsSelection: boolean, vehicleCount: number, maxAllowed: number }Frontend:
App.tsxor AuthGate to check on authenticated loadVehicleSelectionDialogas a modal that cannot be dismissedAcceptance Criteria
needsSelectionstatusPlan: Prompt Vehicle Selection on Login After Auto-Downgrade
Phase: Planning | Agent: Planner | Status: AWAITING_REVIEW
Executive Summary
When a user's subscription is auto-downgraded to free tier via grace period expiration and they have more than 2 vehicles, they need to be prompted to select which vehicles to keep active. This requires:
Codebase Analysis Findings
Architecture Assessment:
VehicleSelectionDialogcomponent is reusable with modificationsCallbackPage.tsxfollows sequential auth check pattern - ideal integration pointApp.tsxprovides blocking mechanism after authenticationKey Files Affected:
subscriptions.service.tssubscriptions.controller.tssubscriptions.routes.tssubscription.api.tsuseSubscription.tsVehicleSelectionDialog.tsxCallbackPage.tsxCallbackMobileScreen.tsxMilestones
Milestone 1: Backend - Check Needs Vehicle Selection
Agent: Feature Agent | Estimated Files: 3
Objective: Create endpoint
GET /api/subscriptions/needs-vehicle-selectionImplementation:
Add
checkNeedsVehicleSelection(userId)method toSubscriptionsService:{ needsSelection: boolean, vehicleCount: number, maxAllowed: number }Add route handler in
SubscriptionsController:Register route in
subscriptions.routes.ts:Acceptance Criteria:
needsSelection: falsefor users who already made selectionsneedsSelection: falsefor pro/enterprise tiersMilestone 2: Frontend - API and Hook
Agent: Frontend Agent | Estimated Files: 2
Objective: Create hook to check if vehicle selection is needed
Implementation:
Add API method in
subscription.api.ts:Add hook in
useSubscription.ts:Acceptance Criteria:
Milestone 3: Frontend - Blocking Vehicle Selection Dialog
Agent: Frontend Agent | Estimated Files: 1-2
Objective: Modify VehicleSelectionDialog to support blocking mode
Implementation:
Add optional
blockingprop toVehicleSelectionDialog:When
blocking={true}:onClose={(_, reason) => reason !== 'backdropClick' && onClose()}disableEscapeKeyDown={blocking}Update dialog title and message for blocking mode context
Acceptance Criteria:
Milestone 4: Frontend - Callback Integration
Agent: Frontend Agent | Estimated Files: 3
Objective: Check vehicle selection requirement after authentication
Implementation:
Option A (Recommended): State-based blocking in App.tsx
useNeedsVehicleSelectionneedsSelection: true, render blocking VehicleSelectionDialogImplement
handleVehicleSelection:POST /api/subscriptions/downgradewith selected vehiclesneeds-vehicle-selectionqueryApply same logic to mobile rendering path in App.tsx
Acceptance Criteria:
Test Plan
Risk Assessment
Dependencies
Out of Scope
Verdict: AWAITING_REVIEW | Next: QR plan-completeness review
QR Review: Plan Completeness
Phase: Plan-Review | Agent: Quality Reviewer | Status: PASS
Review Criteria
Decision Log Check
blockingpropPolicy Defaults Applied
VERDICT: PASS
Findings
None - plan structure is complete.
Considered But Not Flagged
Verdict: PASS | Next: TW plan-scrub
TW Review: Plan Scrub
Phase: Plan-Review | Agent: Technical Writer | Status: PASS
Documentation Quality Check
Clarity Review
Technical Accuracy
GET /api/subscriptions/needs-vehicle-selectionuseNeedsVehicleSelectiondisableEscapeKeyDown, backdrop handlingImprovements Applied
None required - documentation is production-ready.
VERDICT: PASS
Findings
None - documentation meets quality standards.
Observations
Verdict: PASS | Next: QR plan-code
QR Review: Plan Code
Phase: Plan-Review | Agent: Quality Reviewer | Status: PASS
RULE 0: Production Reliability
Open Questions Verified:
Q: "What happens if needs-vehicle-selection API fails?"
A: Plan includes error handling with retry/support contact in risk assessment
Q: "What happens if vehicles query is empty?"
A: Plan checks
vehicleSelectionStatus?.needsSelection && vehiclesbefore renderingRULE 1: Project Conformance
subscriptions/featureSubscriptionsRepositorymethodsneedsVehicleSelection,checkNeedsVehicleSelection)RULE 2: Structural Quality
Code Alignment Check
checkNeedsVehicleSelection()getSubscription()useNeedsVehicleSelection()useSubscription()hookVERDICT: PASS
Findings
None - proposed code follows established patterns.
Considered But Not Flagged
&& vehiclescheckVerdict: PASS | Next: QR plan-docs
QR Review: Plan Docs
Phase: Plan-Review | Agent: Quality Reviewer | Status: PASS
Documentation Impact Assessment
Temporal Contamination Check
Comment Quality Standards
Post-Implementation Documentation Tasks
The following documentation updates should be included in milestone completion:
Milestone 1: Update
backend/src/features/subscriptions/README.mdMilestone 4: No external doc updates needed
VERDICT: PASS
Findings
None - documentation requirements are clear.
Documentation Checklist for Implementation
GET /api/subscriptions/needs-vehicle-selectionto subscriptions READMENeedsVehicleSelectionResponsetypeVerdict: PASS | Next: Plan Approved - Ready for Execution
Plan Status: APPROVED
Phase: Planning | Status: APPROVED
Review Cycle Complete
Ready for Execution
Branch:
issue-60-vehicle-selection-promptMilestones:
Estimated Files: 8
Plan approved and ready for execution.
Milestone: Execution Complete
Phase: Execution | Agent: Developer | Status: PASS
Milestones Completed
Implementation Summary
Backend (Milestone 1):
checkNeedsVehicleSelection(userId)method toSubscriptionsServiceGET /api/subscriptions/needs-vehicle-selection{ needsSelection, vehicleCount, maxAllowed }based on tier, vehicle count, and existing selectionsFrontend (Milestones 2-4):
NeedsVehicleSelectionResponsetypeneedsVehicleSelection()API method with proper data extractionuseNeedsVehicleSelection()hook withstaleTime: 0for fresh checksVehicleSelectionDialogwithblockingprop:App.tsxafter auth gate ready:needsVehicleSelectionstatusCommits
feat: add needs-vehicle-selection endpoint (refs #60)feat: add needsVehicleSelection frontend hook (refs #60)feat: add blocking mode to VehicleSelectionDialog (refs #60)feat: integrate vehicle selection dialog on login (refs #60)Quality Checks
npm run type-checkPASSnpm run lintPASS (warnings only, no errors)npm run type-checkPASSnpm run lintPASS (warnings only, no errors)Verdict: PASS | Next: Open PR and Quality Agent review
QR Review: Final Quality Review
Phase: Review | Agent: Quality Agent
Validation Results
Automated Checks
Code Changes Review
Files modified in PR #62:
backend/src/features/subscriptions/api/subscriptions.controller.tsbackend/src/features/subscriptions/api/subscriptions.routes.tsbackend/src/features/subscriptions/domain/subscriptions.service.tsbackend/src/features/subscriptions/domain/subscriptions.types.tsfrontend/src/App.tsxfrontend/src/features/subscription/api/subscription.api.tsfrontend/src/features/subscription/components/VehicleSelectionDialog.tsxfrontend/src/features/subscription/hooks/useSubscription.tsfrontend/src/features/subscription/types/subscription.types.tsRULE 0 (CRITICAL) - Production Reliability
STATUS: PASS
Findings:
Notes:
RULE 1 (HIGH) - Project Standards
STATUS: PASS
Findings:
Naming Conventions
Mobile + Desktop Requirement
Code Organization
Test Coverage
RULE 2 (SHOULD_FIX) - Structural Quality
STATUS: PASS (Minor observations)
Observations:
No God Objects Introduced:
No Code Duplication:
blockingpropNo Dead Code:
Mobile + Desktop Validation
Desktop: Code present in App.tsx routes (lines 1071-1102)
Mobile: Blocking dialog integrated (lines 645-665)
Manual Testing Status: NOT YET COMPLETED (per PR test plan checklist)
RECOMMENDATION: Complete manual mobile/desktop testing before merge.
Acceptance Criteria Review
From issue #60:
needsSelectionstatusFinal Verdict
CONDITIONAL PASS
All automated checks pass. Code quality meets RULE 0/1/2 standards.
Condition: Complete manual mobile + desktop testing (per PR test plan) before merging to ensure blocking dialog UX works correctly on both platforms.
Recommendation: Mark this PR as approved from a code quality perspective, pending manual QA testing.
Reviewed by: Quality Agent
Timestamp: 2026-01-24
Bug Fix: Vehicle Selection Not Hiding Unselected Vehicles
Phase: Execution | Agent: Developer | Status: COMPLETE
Problem
After user selected 2 vehicles during downgrade to free tier, all vehicles (including unselected ones) continued to appear in:
Root Cause
GET /api/vehiclesendpoint invehicles.controller.ts:31calledgetUserVehicles()which returns ALL vehicles, instead ofgetUserVehiclesWithTierStatus()which properly checkstier_vehicle_selectionstable and marks vehicles asactiveorlocked.Fix Applied
File:
backend/src/features/vehicles/api/vehicles.controller.tsgetUserVehiclesendpoint (list): Now usesgetUserVehiclesWithTierStatus()and filters out vehicles withtierStatus='locked', returning only active vehicles.getVehicleendpoint (detail): Added tier status check that returns403 TIER_REQUIREDif user tries to access a locked vehicle directly.Verification
Commit
6894848- fix: filter locked vehicles after tier downgrade selection (refs #60)Verdict: COMPLETE | Next: Manual testing on mobile and desktop