Add /order/{irp-registration,ifta-application,ifta-quarterly,or-weight-mile-tax,
ny-hut-registration,ky-kyu-registration,nm-weight-distance,ct-highway-use-fee,
ca-mcp-carb,state-dot-registration,intrastate-authority,osow-permit,
state-trucking-bundle,hazmat-phmsa,state-emissions,usdot-reactivation}.
Each renders the slug-gated state-trucking intake wizard. Site builds 48 pages,
new routes verified to render correct intake sections.
Cross-references every DOT/state/hazmat slug across COMPLIANCE_SERVICES,
REQUIRED_FIELDS, SERVICE_META, INTAKE_MANIFEST, and SERVICE_HANDLERS, and
verifies every required field is collectible by its assigned intake steps.
Caught + fixed missing usdot-reactivation SERVICE_META entry. 24/24 pass.
Adds Tawk_API.onLoad mobile guard (max-width 768px -> hideWidget) in shared
footer snippet and current built pages so mobile browsers no longer get the
proactive text bubble covering content.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Gap: dot-registration (new USDOT=MCS-150) routed through intake but never asked
for photo ID; usdot-reactivation, emergency-temporary-authority, carrier-closeout
(final MCS-150 + authority revocation), entity-dissolution, and entity-upgrade-
bundle weren't wired to collect it at all.
- intake_manifest: route usdot-reactivation, ETA, carrier-closeout,
entity-dissolution through the dot-intake step
- DOTIntakeStep DOT_SECTIONS: add dot-sec-photo-id for dot-registration and all
the above (operations + photo ID)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Client-side: Laplacian variance blur detection in photo quality check
(very blurry / somewhat blurry / acceptable / good)
- Server-side: async Ollama vision model validates uploaded image is a
real government ID (minicpm-v:8b), flags non-ID uploads
- Corporate check: sole proprietors now get yellow 'form an LLC' upsell,
formal entities get annual report/RA reminder
Previous approach relied on the main is:inline script block which
could be blocked by FCC step crashes. New approach: tiny self-contained
script right next to the QR img element, runs immediately, fetches
upload token and generates QR. Falls back to page URL on failure.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
QR code hidden via CSS on screens < 640px (phones). On mobile,
file input gets capture=environment so tapping the button opens
the camera directly. Tablets still show QR code.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- API: POST /api/v1/id-upload/token generates upload token
- API: POST /api/v1/id-upload/:token receives base64 image, stores in MinIO
- API: GET /api/v1/id-upload/:token/status returns upload status + thumbnail
- Mobile page: sends image as base64 with upload_token
- Desktop intake: requests token, generates QR with upload URL, polls
every 3s for phone upload, auto-shows thumbnail when detected
- MinIO storage with presigned URLs for thumbnails
- Compliance order intake_data updated with photo_id_uploaded flag
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
QR code displayed inline below the upload button so truckers can
immediately scan with their phone to take a photo of their ID.
Clear instructions: 'Scan with your phone camera to take a photo'
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Yellow instruction box explains 3 methods in plain English
(phone photo, computer upload, scanner)
- One big orange "Add Photo of Your ID" button
- Webcam + QR code kept in code but simplified UI
- Accepted formats note
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Desktop users can now use their webcam to photograph their ID:
- Click "Use Camera" → browser requests webcam permission
- Live video preview with orange guide rectangle for ID placement
- Capture button takes high-res JPEG (1280x720)
- Cancel button stops webcam and returns to upload options
- Captured image goes through same quality check flow
- Works on Chrome, Firefox, Edge, Safari (desktop + mobile)
- No libraries needed — native WebRTC API
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Intake data now persists to DB after each step completion (non-blocking).
If browser crashes, data is recoverable from compliance_orders.intake_data.
Partial saves (_partial: true) only update intake_data without changing
payment_status or marking intake_data_validated. Final submit still
triggers the full validation + worker dispatch flow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shows uploaded image at larger size with automated quality checks:
- File size (too small = low quality warning)
- File type validation (JPEG, PNG, PDF, HEIC)
- Resolution check (minimum 400x250 for readable text)
- Aspect ratio check (should look like an ID card)
Green checkmark for passing checks, red X for issues.
Yellow warning box for quality problems with specific guidance.
Accept & Continue button to confirm, Retake to re-upload.
After accept, collapses to small preview with "Change ID" option.
Front of ID only (sufficient for FMCSA MCS-150 filing).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three upload methods:
- Upload File: standard file picker
- Camera / Scanner: uses capture attribute for camera on mobile
or TWAIN/WIA scanner devices on desktop
- QR Code: generates QR with current page URL so user can scan
with phone and take a photo of their ID on mobile
QR generated via api.qrserver.com (no library dependency).
Remove button restores all upload options.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
FCC step scripts crash on DOT pages due to missing elements. By
using is:inline, DOT intake script runs independently, not in the
hoisted bundle. Stripped TypeScript annotations for plain JS compat.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wraps entire script in element existence check to prevent running
on FCC pages where other step scripts crash from missing elements.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MCS150Step script compiled into hoisted JS for all order pages.
Non-null assertions on photo ID elements crashed on non-MCS150 pages,
preventing DOTIntakeStep's showRelevantSections from running.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Script crashed on 'Cannot read properties of null' because photo ID
elements are inside a hidden section. All element refs now use
optional chaining instead of non-null assertions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sections were visible by default in HTML. Now all hidden, then
showRelevantSections() runs immediately + on pw:step-shown.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Single DOTIntakeStep shows/hides sections based on services ordered:
- Company info + address + signer (always)
- Entity & operations (MCS-150, USDOT, MC Auth, bundles)
- Fleet info (MCS-150, UCR, bundles)
- UCR fleet bracket + base state (UCR)
- Cargo types (MCS-150, bundles)
- D&A program (CDL drivers, DER, consortium)
- BOC-3 docket info (BOC-3)
- Photo ID upload (MCS-150, MC Auth)
- Security/encryption notices
All DOT services now use ["dot-intake", "review"] instead of ["review"].
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Security notice: SSL encryption, encrypted at rest, no third-party sharing
- EIN field added (required for MCS-150 form field 19)
- Photo ID upload with camera capture on mobile
- ID auto-deleted after filing processed
- Preview with remove button
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Collects all fields needed for FMCSA Form MCS-150:
- Legal name, DBA, DOT#, MC#
- Principal business address
- Entity type, carrier operation, interstate/intrastate
- Fleet info (power units, drivers, annual miles)
- 29 cargo type checkboxes
- Authorized signer name and title
Filed via fax to FMCSA at 202-366-3477 (VitalPBX).
Previously was review-only with no data collection.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Footer subscribe modal: new "I'm interested in" dropdown with 3 options
- Hoisted JS: reads interest field, validates selection, passes to API
- Subscribe API: routes to different Listmonk lists by interest
(telecom→list 3, trucking→list 8, formation→list 9)
- Interest stored as subscriber attribute for campaign segmentation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
8 new Astro intake pages for DOT services:
mcs150-update, boc3-filing, ucr-registration, dot-registration,
mc-authority, dot-drug-alcohol, dot-audit-prep, dot-full-compliance.
All use entity + review wizard steps (admin-assisted services).
Added to INTAKE_MANIFEST and SERVICE_META with correct pricing.
Fixes 404 on /order/mcs150-update?order=CO-xxx from confirmation emails.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Nav dropdown: Trucking/DOT section with DOT Compliance Services,
MCS-150/BOC-3/UCR link, and DOT Compliance Check [FREE] badge.
Added to both desktop mega-dropdown and mobile menu.
Footer: DOT/Trucking in services list, DOT Compliance Check in
free tools list.
This updates all Astro-compiled pages site-wide (nav partial).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When intake loads from ?order=CO-xxx, the FRN is in the order's
intake_data, not the URL. Now checks state.intake_data.frn and
state.entity.frn as fallback sources for auto-fill.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When the intake page is loaded with ?order=CO-xxx (from the
confirmation email), fetch the order and pre-fill customer name,
email, and FRN from the order record. Previously only worked
with JWT token-based links.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- "Email address (yours)" → "Your email address" with helper text
- "Your name" → "Your first and last name" with placeholder
- "Carrier legal name" → "Carrier entity legal name" with examples
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Email passes through the full funnel: campaign email (?email=) →
compliance checker → order page. Reduces friction for campaign
recipients who would otherwise have to type their email manually.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Compliance checker reads ?code= from URL, stores it, passes it
through to the order page CTA link
- Allows email campaigns to link to checker with coupon pre-applied
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The lead capture template literal used \` (escaped backtick) which
passed through Astro's compiler literally, creating an invalid JS
token that prevented the entire script from executing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
as HTMLInputElement and as HTMLElement leaked into compiled JS,
causing SyntaxError in the lead capture handler block.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>