- 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>
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>
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>
- "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>
STIRShakenStep intake:
- New "Terminate only" option for carriers that only receive pre-signed
calls and don't originate
- Contextual hints for each option explaining requirements
- Show/hide vendor and upstream fields based on selection
RMD letter generator:
- New terminate_only section explaining verification-only posture,
citing 47 CFR § 64.6301 (signing obligation on originating provider)
- Added to needs_exhibit_a list
RMD Exhibit A generator:
- New terminate_only STIR/SHAKEN paragraph with SBC verification language
- Fixed scope paragraph: wholesale/facilities carriers no longer get
"small provider without Class 4 switch" boilerplate
- Fixed OCN paragraph: wholesale carriers get neutral wording instead
of "no OCN required for small retail provider"
RMD filing handler:
- Maps stir_shaken_status to rmd_option for Exhibit A generation
- Passes entity metadata (ocn, wholesale, gateway, contact) to generator
- Maps terminate_only → partial_implementation for FCC RMD form radio
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Yellow banner on each step: "We've pre-filled this from your FCC records.
Please review carefully and correct any information that is inaccurate."
- Only shows when accessed via token/FRN (post-payment intake)
- CORES address: filter by company name suffix (LLC/Inc/Corp) instead of
requiring a number — addresses like "PO Box 123" now work
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CategoryStep script runs on ALL pages using the Wizard component.
It tried to find #pw-wizard (its inner quiz div) and called
querySelectorAll on it — null on CPNI/RMD/etc pages, crashing the
entire script bundle. This prevented FRN auto-fill, officer
suggestions, and all other intake functionality.
Guard: if #pw-wizard doesn't exist, skip all CategoryStep logic.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entity cache has no RA/officer data yet. Instead, fetch the FCC lookup
(quick mode) and offer RMD contact name + address and CORES principal
address as clickable suggestions to auto-fill Officer 1.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Removed "How many officers" dropdown — all 3 always visible
- Officers 2 and 3 marked as (optional) in legend
- Only Officer 1 validated (name, title, street, city required)
- Blank optional officers skipped in saved data
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- OfficerStep searches entity_cache for matching corporations when loaded
- Shows clickable suggestions with RA name and address to auto-fill Officer 1
- Pre-fills contact_name/email/phone from entity data (helps data-only filers)
- Corp search endpoint: state param now optional (searches all states)
- Corp search returns registered_agent and principal_address fields
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CPNI: requires either clean compliance checkbox OR issues section opened
- STIR/SHAKEN: requires selecting implementation status before advancing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Entity structure (LLC/Corp/etc) is now required
- EIN must be provided and match XX-XXXXXXX format
- Full address (street, city, state, ZIP) required
- Email validation format checked
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>