myodo — User Flows (MVP Beta)
Last Updated: 2026-04-25
Purpose: Engineering handoff document. Each flow shows what the user does, what happens behind the scenes, and what data is created or changed.
Scope: Everything in this document is MVP beta unless explicitly marked “Post-MVP.”
- System Overview
- Driver Journeys
- 2.1 Driver Onboarding (Beta — Shop Invite)
- 2.2 Add Vehicle (Claim)
- 2.3 Pair OBD-II Device
- 2.4 View Service History & Health
- 2.5 Receive Notifications & Schedule Service
- 2.6 Manage Shop Connections
- 2.7 Relinquish / Transfer Vehicle
- 2.8 Dispute a Record
- Shop Journeys
- 3.1 Shop Onboarding (Beta — Invite Only)
- 3.2 Internal Admin Dashboard (Beta)
- 3.3 Upload Repair Orders
- 3.4 Receive & Handle Service Requests
- 3.5 Messaging & Appointments
- Entity Lifecycle Diagrams
- Data Entities Reference
- Third-Party Integrations
- Record Visibility Rules
- Driver App (Glovebox) Views
- 8.1 App Shell & Navigation
- 8.2 Vehicles (Home Screen)
- 8.3 Vehicle Detail Page
- 8.4 Driver Upload RO
- Scope Boundary
1. System Overview
Two products, two user types, one shared data layer.
End-to-End Lifecycle
The full loop — how a driver and shop interact through myodo from first contact to recurring service.
The Core Loop
This is the business engine — the cycle that generates recurring revenue for shops and keeps drivers’ vehicles maintained. Everything else in the product exists to support this loop.
2. Driver Journeys
2.1 Driver Onboarding (Beta — Shop Invite)
During beta, driver onboarding is controlled through shop invites. The driver does not create their own account — the system provisions one from a parsed repair order, and the driver claims it.
At scale, drivers will also be able to sign up independently via the website. That flow is out of scope for beta.
Step 1: Shop uploads repair order
What gets parsed from the repair order:
- VIN → NHTSA vPIC decode → year, make, model, engine, trim
- Customer name, phone number, email address
- Service data: date, mileage, services performed, parts, labor, costs, DTCs, findings
Data created:
| Step | Entity | Operation | Fields |
|---|---|---|---|
| Store file | source_documents | INSERT | file_url, shop_id, status=pending |
| Parse result | service_events | INSERT | vehicle_id, shop_id, date, mileage, services, costs |
| Vehicle | vehicles | UPSERT on VIN | vin, year, make, model, engine, trim |
| Provisioned account | users | INSERT | name, email, phone, type=driver, status=provisioned |
| Group records | service_events | Link to provisioned user via VIN + identity match | |
| Shop relationship | shop_driver_relationships | INSERT | shop_id, driver_id, is_preferred=true |
Step 2: Shop sends invite
The invite email is sent from the shop’s own email address, not from myodo. This requires the shop to configure their email in their profile settings. The system uses an email relay mechanism (engineer decides implementation — sender verification, SMTP relay, etc.) so the driver sees an email from a business they trust, not from an unknown platform.
Step 3: Driver claims account
Data created/modified during claim:
| Step | Entity | Operation | Fields |
|---|---|---|---|
| Identity confirmed | users | UPDATE | email_verified=true, phone_verified=true |
| Each consent step | consent_events | INSERT | user_id, type (tos/privacy/data_processing/comms), method, timestamp |
| Comms preferences | notification_preferences | INSERT | user_id, service_reminders (bool), promotional (bool) |
| Auth setup | users | UPDATE | auth_provider (google/email), status=active |
| Account activated | users | UPDATE | status=active, claimed_at=now() |
Data modified on rejection:
| Step | Entity | Operation | Fields |
|---|---|---|---|
| Reject invite | users | UPDATE | status=rejected |
| Scrub PII | users | UPDATE | name=NULL, email=NULL, phone=NULL |
| Retain records | service_events | No change — records stay, anonymized (no PII link) |
Unclaimed accounts
If a provisioned account is never claimed, PII is automatically deleted after a configurable retention period (engineers decide timeline). Anonymized service records are retained on the VIN — the vehicle’s service history has value regardless of whether a specific owner claims it.
Error states:
- RO parsing fails to extract VIN → flag for manual review
- Parsed email/phone missing → shop notified to fill in gaps before invite can be sent
- Driver tries to claim but email/phone don’t match → identity verification fails, retry or contact support
- Consent declined during claim → account remains provisioned, not activated
- Shop email not configured → shop prompted to set up email in profile before sending invites
2.2 Add Vehicle (Claim)
Two paths to the same result: driver provides a VIN, system decodes and creates a pending vehicle record.
| Step | Entity | Operation | Fields |
|---|---|---|---|
| Plate decode | (external API call) | — | plate, state → VIN |
| NHTSA decode | (external API call) | — | VIN → year, make, model, engine, trim |
| New vehicle | vehicles | INSERT (UPSERT on VIN) | vin, year, make, model, engine, trim, ownership_status=pending |
| Ownership link | ownership_periods | INSERT | vehicle_id, customer_id, started_at=now(), ended_at=NULL |
pending until a service record uploads that matches BOTH the VIN AND the driver’s identity info (name, email, or phone). Then it flips to verified.
2.3 Pair OBD-II Device
| Step | Entity | Operation | Fields |
|---|---|---|---|
| Pair device | devices | INSERT/UPDATE | imei, vehicle_id, owner_id, status=active, nickname |
| Baseline mileage | mileage_readings | INSERT | vehicle_id, reading, source=app, timestamp |
| Audit trail | vehicle_events | INSERT | vehicle_id, event_type=device_coupled, device_id |
Telemetry feeds after pairing:
- Mileage readings (odometer snapshots at regular intervals)
- DTC detection (check engine light + fault codes)
- Trip data (ignition on/off with odometer deltas)
- Device status (online/offline/battery)
- GPS coordinates streamed to app in real-time but never persisted (privacy)
2.4 View Service History & Health
This is the core Glovebox experience. The data assembly rules are critical for engineers.
See Section 7: Record Visibility Rules for the full decision matrix.
2.5 Receive Notifications & Schedule Service
MVP notifications are mileage-based and require an OBD-II device.
| Step | Entity | Operation | Fields |
|---|---|---|---|
| Detect need | service_needs | INSERT | vehicle_id, type (oil/tire/cel), detected_at, current_mileage, last_service_mileage |
| Send notification | notifications | INSERT | user_id, service_need_id, channel (email/sms/in_app), status=sent, sent_at |
| Driver reads | notifications | UPDATE | status=read, read_at |
| Submit request | service_requests | INSERT | driver_id, shop_id, vehicle_id, description (free text), status=pending |
Post-MVP: The free-text description becomes a natural language interface that parses into structured line items (like a cart).
2.6 Manage Shop Connections
| Step | Entity | Operation | Fields |
|---|---|---|---|
| Change preferred | shop_driver_relationships | UPDATE | is_preferred=false on old, is_preferred=true on new |
| Toggle permission | shop_driver_relationships | UPDATE | cross_shop_history_visible (bool), promotional_messages (bool) |
2.7 Relinquish / Transfer Vehicle
Owner relinquishes (selling/giving away vehicle)
- You will lose live health record, telemetry, and notifications for this vehicle
- Your historical service records from your ownership period become read-only in “Archived Vehicles”
- Any paired OBD-II device is uncoupled (device stays on your account)
New owner claims transferred vehicle
What new owner sees for pre-ownership records: Anonymized — date, mileage, shop name, services performed, findings. NO pricing, NO previous owner identity. Living Health Record transfers fully (follows VIN).
2.8 Dispute a Record
| Step | Entity | Operation |
|---|---|---|
| Submit dispute | record_disputes | INSERT: record_id, user_id, description, status=open |
| Resolve | record_disputes | UPDATE: status=resolved, resolution_notes |
| Correct record | service_events | UPDATE: corrected fields |
3. Shop Journeys
3.1 Shop Onboarding (Beta — Invite Only)
During beta, shops join by invite only. There are two paths into the system — both converge at the same onboarding flow.
How shops get invited
Pre-vetted shops (Path A) have already been screened — no review step after they accept. Request-access shops (Path B) go through the interview before receiving an invite.
Onboarding flow
Onboarding must be completed in a single session — no partial saves. If a shop doesn’t want to lose progress, they need to finish. If onboarding is not completed within 48 hours of clicking the invite link, the myodo team is notified so they can follow up manually.
Hours of operation input
The hours input avoids duplicate effort for days with the same schedule:
The stored format should be structured (per-day open/close ranges) so it can be displayed consistently across the platform.
Shop user roles
Shops have multiple user accounts with different privilege levels. The person who completes onboarding gets the admin role.
| Role | Upload ROs | Send customer invites | Message customers | Edit business info / hours / email | Add/remove shop users | Transfer admin |
|---|---|---|---|---|---|---|
| Admin | Yes | Yes | Yes | Yes | Yes | Can receive |
| Service Advisor | Yes | Yes | Yes | No | No | Can give away |
Adding service advisors:
Admin transfer: If a service advisor signed up first and the shop owner/manager wants to take over, the advisor can transfer admin privileges to the owner. The owner receives and confirms the transfer.
Upload attribution: Every upload is tied to the specific shop user who uploaded it, not just the shop. This provides accountability and audit trail.
Shop statuses (state machine)
Beta request statuses (separate from shop statuses):
Data created
| Step | Entity | Operation | Key Fields |
|---|---|---|---|
| Request access (Path B) | shop_beta_requests | INSERT | name, email, phone, status=pending, requested_at |
| Interview outcome | shop_beta_requests | UPDATE | status (approved/waitlisted/declined), reviewed_by, reviewed_at |
| Send invite | shops | INSERT | name (from request or manual), status=invited, invite_token, invited_at |
| Profile setup | shops | UPDATE | contact_name, name, phone, email, address, hours (JSON), website, status=invited |
| Legal agreements | shop_agreements | INSERT | shop_id, signer_name, signer_title, signed_at, ip_address, agreement_version |
| Email config | shops | UPDATE | email_relay_config (engineer decides structure) |
| Auth setup | shop_users | INSERT | shop_id, user_id, role=admin |
| First RO upload | source_documents | INSERT | file_url, shop_id, uploaded_by (shop_user_id), status=pending |
| Onboarding complete | shops | UPDATE | status=active, activated_at |
| Team notification | (internal email) | — | Shop name, contact info, link to admin dashboard |
| Stale alert (48hrs) | (internal email) | — | Shop name, contact info, invite sent timestamp |
3.2 Internal Admin Dashboard (Beta)
An internal-facing tool for the myodo team to manage shops and monitor platform health during beta.
Core views (MVP)
| View | Contents |
|---|---|
| Active Shops | Shop name, contact name, email, phone, website, activated_at |
| Waitlisted Shops | Name, email, phone, waitlisted_at, notes from interview |
| Deletion Requests | User name (if available), request date, status (pending/completed), associated records |
Extra credit (engineer discretion)
| View | Contents |
|---|---|
| Requested Shops | Name, email, phone, requested_at, status |
| Per-Shop Metrics | ROs uploaded (count), customers invited (count), invites accepted vs. rejected |
Deletion request tracking: When a driver rejects an invite and requests data deletion (see Section 2.1 Step 3), or when an unclaimed account expires, the deletion must be logged. The admin dashboard shows these so the team can verify PII was scrubbed and anonymized records were retained correctly.
3.3 Upload Repair Orders
Uploading a repair order is the primary action in the system. It triggers record parsing, vehicle creation, account provisioning, and health updates.
What gets extracted from a repair order:
- VIN → NHTSA decode → year, make, model, engine, trim
- Customer name, email, phone (for identity matching + account provisioning)
- Event date, mileage
- Services performed: category, operation, finding, parts, labor, cost per line
- Diagnostic trouble codes (DTCs)
- Findings / technician notes
- Total cost
| Step | Entity | Operation |
|---|---|---|
| Store file | source_documents | INSERT: file_url, shop_id, status=pending |
| OCR complete | source_documents | UPDATE: ocr_text, status=parsed |
| Vehicle | vehicles | UPSERT on VIN: vin, year, make, model, engine, trim |
| Parse result | service_events | INSERT: vehicle_id, shop_id, date, mileage, services (JSON), costs, dtcs, findings |
| Account (if new customer) | users | INSERT: name, email, phone, type=driver, status=provisioned |
| Account (if existing) | service_events | Link to existing user |
| Shop relationship | shop_driver_relationships | INSERT (if new): shop_id, driver_id, is_preferred=true |
| Health update | living_health_docs | UPSERT: vehicle_id, per-item status updates |
| Notifications | service_needs | INSERT (if triggered, only for active accounts) |
3.4 Receive & Handle Service Requests
3.5 Messaging & Appointments
| Action | Entity | Operation |
|---|---|---|
| Send message | messages | INSERT: thread_id, sender_id, sender_type, content, sent_at |
| New thread | message_threads | INSERT: shop_id, driver_id, subject |
| Create appointment | appointments | INSERT: shop_id, driver_id, vehicle_id, scheduled_at, service_type, notes, status=scheduled |
| Send reminder | notifications | INSERT: type=appointment_reminder |
4. Entity Lifecycle Diagrams
Driver Account
Vehicle Ownership
Source Document (Repair Order)
Service Request
Shop Account
5. Data Entities Reference
This is not a schema — the engineer owns the data model. These are the entities the flows above require, with the relationships and key fields that must exist.
Entity Relationship Diagram
Users & Auth
| Entity | Key Fields | Notes |
|---|---|---|
users | id, name, email, phone, type (driver/shop_admin), status (provisioned/active/rejected/expired), auth_provider, claimed_at | Drivers can be provisioned (from RO parse) or active (claimed). See 2.1 for lifecycle. |
consent_events | user_id, type, method, timestamp | Immutable log — every consent action recorded |
notification_preferences | user_id, service_reminders, promotional | Per-user delivery preferences |
Vehicles & Ownership
| Entity | Key Fields | Notes |
|---|---|---|
vehicles | vin (UNIQUE), year, make, model, engine, trim, customer_id, ownership_status | VIN is the universal key |
ownership_periods | vehicle_id, customer_id, started_at, ended_at | Tracks who owned when — drives record visibility |
vehicle_authorized_users | vehicle_id, user_id, relationship | Spouse, family, etc. — requires verification |
Service Records & Health
| Entity | Key Fields | Notes |
|---|---|---|
source_documents | id, file_url, shop_id, uploaded_by (shop_user_id), ocr_text, status, uploaded_at | The raw uploaded file + OCR output. Attributed to specific shop user. |
service_events | id, vehicle_id, shop_id, source_document_id, event_date, mileage, services (JSON), total_cost, dtcs, findings | The parsed, structured record |
living_health_docs | vehicle_id, items (JSON: per-item status) | Running health status per vehicle — follows VIN, not owner |
health_observations | id, vehicle_id, service_event_id, item_id, status, measurement, notes | Individual inspection findings |
record_disputes | id, service_event_id, user_id, description, status, resolution | Driver-submitted accuracy disputes |
Shops, Users & Relationships
| Entity | Key Fields | Notes |
|---|---|---|
shops | id, name, contact_name, email, phone, address, hours (JSON), website, status, invited_at, activated_at | Status drives what the shop can do. Hours stored as structured per-day ranges. |
shop_users | id, shop_id, user_id, role (admin/advisor), status (invited/active/disabled), invited_at, accepted_at | Multi-user shops. First onboarder gets admin. Uploads attributed via this. |
shop_beta_requests | id, name, email, phone, status (pending/interviewing/waitlisted/approved/declined), requested_at | Request-to-join form submissions. Separate from shop records. |
shop_agreements | shop_id, signer_name, signer_title, signed_at, ip_address, agreement_version | Immutable audit record |
shop_assets | shop_id, qr_code_url, invite_link | Generated on activation |
shop_driver_relationships | shop_id, driver_id, is_preferred, cross_shop_history_visible, promotional_messages | Per-shop permissions controlled by driver |
deletion_requests | id, user_id, source (invite_rejection/account_expiry/user_request), status (pending/completed), requested_at, completed_at | Tracks all PII deletion events for compliance |
Devices & Telemetry
| Entity | Key Fields | Notes |
|---|---|---|
devices | imei, vehicle_id, owner_id, status, nickname, last_seen | OBD-II hardware units |
mileage_readings | vehicle_id, reading, source (device/app/repair_order), timestamp | Odometer snapshots from multiple sources |
trips | vehicle_id, device_id, started_at, ended_at, distance | Ignition on → off events |
vehicle_events | vehicle_id, event_type, device_id, timestamp | Audit trail: couple/uncouple/disable |
Notifications & Requests
| Entity | Key Fields | Notes |
|---|---|---|
service_needs | vehicle_id, type (oil/tire/cel), detected_at, current_mileage, last_service_mileage | Detected maintenance needs |
notifications | user_id, service_need_id, channel, status (sent/read/acted_on), sent_at | Delivery tracking |
service_requests | driver_id, shop_id, vehicle_id, description, status | Free-text requests (MVP) |
appointments | shop_id, driver_id, vehicle_id, scheduled_at, service_type, notes, status | Scheduled service visits |
Messaging
| Entity | Key Fields | Notes |
|---|---|---|
message_threads | id, shop_id, driver_id, subject, created_at | One thread per shop-driver pair per topic |
messages | id, thread_id, sender_id, sender_type, content, sent_at | Individual messages in a thread |
6. Third-Party Integrations
| Integration | Used In | Purpose | MVP? |
|---|---|---|---|
| Plate-to-VIN API | Vehicle claiming (2.2) | Decode license plate → VIN | Yes |
| NHTSA vPIC | Vehicle claiming (2.2) | Decode VIN → year, make, model, engine, trim | Yes |
| Google Document AI | Record upload (3.3) | OCR — extract text from PDF/image | Yes |
| OpenAI GPT-4o | Record upload (3.3) | Parse OCR text into structured service data | Yes |
| Email service | Notifications (2.5), onboarding | Transactional email delivery | Yes |
| SMS service | Notifications (2.5) | SMS delivery for opted-in users | Yes |
| Cloudflare Workers | Telemetry (2.3) | OBD-II data ingestion — firm infrastructure decision | Yes |
7. Record Visibility Rules
This is the core privacy model. Every record access must evaluate these rules.
What each view includes
| View | Shows | Hides |
|---|---|---|
| FULL | Date, mileage, shop, services, parts, labor, pricing, customer name, findings, DTCs | Nothing |
| ANONYMIZED (driver) | Date, mileage, shop name, services performed, findings | Pricing, parts cost, labor cost, customer identity |
| ANONYMIZED (cross-shop) | Date, mileage, services performed, findings | Pricing, labor times, other shop’s name, other shop’s contact info |
| NO ACCESS | Nothing | Everything |
Key invariants
- A shop always sees records they uploaded — this cannot be revoked
- Cross-shop records shown to shops are anonymized to protect competitive data (no pricing, no shop names)
- After vehicle transfer, the new owner sees pre-ownership records as anonymized
- The Living Health Record (inspection statuses) is vehicle-scoped — always shows full history regardless of ownership
- OBD-II telemetry (location, trips) is never transferred to a new owner — purged on relinquish
8. Driver App (Glovebox) Views
Sections 1–7 describe what happens behind the scenes. This section describes what the driver actually sees and interacts with.
8.1 App Shell & Navigation
Entry: Driver receives a business card with a QR code linking to the myodo website, or navigates to the URL manually. QR code / URL → login screen → home.
Layout: Main content area with a persistent side navigation bar.
Side nav items:
| Nav Item | Destination |
|---|---|
| Vehicles | Home screen — vehicle card grid (default) |
| Devices | OBD-II device management |
| Request Service | Service request form (to preferred shop) |
| Upload RO | Driver-uploaded repair orders |
| Settings | Account, privacy, shop connections, notification preferences |
On mobile, side nav collapses to a hamburger menu.
8.2 Vehicles (Home Screen)
The home screen is a grid of vehicle cards — one card per vehicle in the driver’s garage.
Vehicle card contents
┌─────────────────────────────────────────┐
│ 2019 Honda Accord EX-L │
│ │
│ Next oil change due at 67,500 mi │
│ Due in 1,230 mi (device) │
│ │
└─────────────────────────────────────────┘
| Element | Source | Notes |
|---|---|---|
| Year, make, model | vehicles (from VIN decode) | Always shown |
| Next oil change due at X mi | Calculated: last oil change mileage + 5,000 | Shown if oil change record exists |
| Due in X mi | Calculated: due mileage − current device odometer | Only for vehicles with active OBD-II device |
If no oil change record exists for a vehicle, the card shows a prompt instead of the oil change status (see 8.3).
Click a card → navigate to vehicle detail page (8.3).
8.3 Vehicle Detail Page
Two-column layout. On mobile, the right column stacks on top — upcoming services and actionable items are prioritized above service history.
Header
| Element | With device | Without device |
|---|---|---|
| Year, make, model | Always | Always |
| Odometer | Current reading from device (live) | Mileage from last service record, labeled “Last service: X mi” |
Service records list
Each record appears as a row. Records are ordered by date, most recent first.
Owned record row (identity matched, within ownership period):
| Field | Source |
|---|---|
| Date | service_events.event_date |
| Mileage | service_events.mileage |
| Price | service_events.total_cost |
| AI summary | service_events.summary (generated at parse time, stored) |
Anonymized record row (no identity match, or outside ownership period):
| Field | Source | Notes |
|---|---|---|
| Date | service_events.event_date | Shown |
| Mileage | service_events.mileage | Shown |
| Price | — | Hidden |
| AI summary | service_events.summary | Shown (summary describes services, not pricing) |
| Shop name | — | Hidden |
| Visual indicator | — | Badge or icon indicating “anonymized record” |
No “View Original” link on anonymized records. Only the record owner can access the source PDF/image. Exposing the source document would defeat the purpose of anonymization.
Record drill-down (accordion)
Three levels of detail, each expanding on click:
Parts detail fields (as much as parsed):
| Field | Example | Notes |
|---|---|---|
| Part description | “Mobil 1 5W-30 Full Synthetic” | Always shown if parsed |
| Part number | #15400-PLM-A02 | Shown if parsed |
| Brand | Mobil 1 | Shown if parsed |
| Quantity | 5 qt | Shown if parsed |
| Price | $42.99 | Only on owned records |
Labor detail fields:
| Field | Example | Notes |
|---|---|---|
| Description | “Oil & filter change” | Always shown |
| Time | 0.5 hr | Only on owned records |
| Rate/price | $35.00 | Only on owned records |
View Original Document: Button or link at the bottom of the expanded record. Opens the source PDF/image in a new tab. Only visible on owned records.
Upcoming services panel (right column)
For beta, this panel shows one thing: the next oil change.
Oil change detection: The parsing pipeline must identify oil changes in service records. When detected, the system stores the mileage and calculates the next due point.
| Scenario | Display |
|---|---|
| Oil change on record, device installed | “Next oil change due at 67,500 mi” + “Due in 1,230 mi” + [Schedule Service] |
| Oil change on record, no device | “Next oil change due at 67,500 mi” + [Schedule Service] |
| No oil change record | “No oil change on record” + prompt to upload or request |
The “Schedule Service” button links to the Request Service flow with the preferred shop pre-selected and “oil change” pre-filled.
8.4 Driver Upload RO
Drivers can add their own repair records from any shop — even shops that aren’t on the myodo platform.
Use cases:
- Paper records the driver wants to digitize (camera capture)
- PDF repair orders from email (download and upload)
- Email forwarding (see below)
Upload methods
Email forwarding: Each driver gets a unique ingest email address (e.g., records+{token}@myodo.co or similar — engineer decides format). The driver forwards an email from their shop that contains a PDF attachment. The system extracts the attachment and runs it through the standard parsing pipeline. The record is attributed to the driver.
Key differences from shop uploads:
- No shop_id on the source document (or shop is identified from the parsed record content)
- Record is attributed to the driver who uploaded it
- The driver automatically has full access to the record (they uploaded it)
- Identity matching still runs — if the parsed VIN matches a vehicle in the driver’s garage, the record links automatically
| Step | Entity | Operation | Key Fields |
|---|---|---|---|
| Upload file | source_documents | INSERT | file_url, driver_id, shop_id=NULL (unless parseable), status=pending |
| Parse | service_events | INSERT | vehicle_id (matched by VIN), summary, services, costs |
| Vehicle link | service_events | Link to vehicle in driver’s garage via VIN match |
9. Scope Boundary
What’s NOT in MVP Beta
Listed here so engineers can design with awareness but not build them yet.
| Feature | Why Deferred | Design Consideration |
|---|---|---|
| Living Health Record UI | Next major feature after launch | Data model and extraction logic should be designed now — the 40-item taxonomy across 8 categories. Just don’t build the driver-facing UI yet. |
| Manufacturer service intervals (Motor) | Requires Motor API integration | MVP uses simple mileage deltas for oil/tire. Data model should accommodate OEM-specific schedules later. |
| Fleet management | Separate user category | Driver data model should support multi-vehicle from day one. Fleet-specific reporting/bulk management is deferred. |
| NLP service request interface | Complex NL parsing | MVP uses free-text description. Structured line-item parsing is post-MVP. |
| CCPA/CPRA self-service | Needs legal review | Build the consent logging and data export infrastructure. Self-service UI is post-MVP but the data to support it should exist. |
| Forensic audit log | Scope too large for beta | Design immutable event logging from the start — retrofitting is painful. |
What IS in MVP Beta (Checklist)
- Driver onboarding via shop invite: RO parse → account provisioning → invite → claim + consent
- Invite rejection + PII deletion flow with anonymized record retention
- Unclaimed account PII auto-expiry (configurable retention period)
- Deletion request tracking and admin visibility
- Shop onboarding: invite-only, single-session, 5-step flow with mandatory first RO upload
- Shop beta request form (name, email, phone) with notification to myodo team
- Shop email configuration for sending customer invites from shop’s address
- Shop multi-user support: admin + service advisor roles with upload attribution
- Service advisor invite flow (admin adds → email invite → advisor accepts)
- Admin privilege transfer (advisor → owner/manager)
- Structured hours of operation input (batch-set by day groups)
- Stale onboarding detection: 48hr notification if shop doesn’t complete sign-up
- Internal admin dashboard: active shops, waitlisted shops, deletion requests
- Vehicle creation from parsed VIN (with NHTSA decode)
- OBD-II device pairing and telemetry ingestion
- Service history timeline with identity-matched vs. anonymized records
- Repair order upload, OCR, AI parsing, identity matching
- AI-generated record summary (one-liner) stored at parse time
- Preferred shop designation and shop connection management
- Mileage-based notifications: oil change, tire rotation, CEL
- Service requests (free-text to preferred shop)
- Driver app: vehicle card home screen with oil change status
- Driver app: vehicle detail with two-column layout (mobile-responsive, actions on top)
- Driver app: service record accordion drill-down (record → jobs → parts/labor)
- Driver app: upcoming services panel with oil change reminder (5,000 mi default)
- Driver app: “View original document” for owned records only
- Driver app: Upload RO (file upload, camera capture)
- Driver app: email forwarding ingest (unique address per driver, auto-parse PDF attachments)
- Shop Dashboard: upload ROs, receive requests, customer list
- Thread-based messaging between shops and drivers
- Appointment creation and reminders
- Vehicle relinquish and transfer request flow
- Record dispute submission and human review pipeline
- Record visibility rules enforced everywhere