Commit graph

241 commits

Author SHA1 Message Date
justin
29ad0908ee trucking: pass-through fee disclosure + state fulfillment status machine
Item 2 of the trucking state-authorization plan.

- compliance-orders.ts: populate gov_fee_label for every state-trucking
  service so the variable, billed-at-cost government charges (apportioned
  IRP, IFTA decals, NY HUT, CT HUF, weight-distance, CA MCP+CARB, OS/OW
  permits, bundle) are disclosed at checkout. price_cents stays the flat
  service fee; gov fees pass through at cost.
- migration 086: compliance_orders.fulfillment_status state machine
  (authorization_required -> authorization_signed -> awaiting_customer_
  delegation -> awaiting_secure_credentials -> awaiting_government_fee_
  approval -> awaiting_insurance_filing -> ready_to_file ->
  filed_waiting_state -> completed) + fulfillment_status_at
- state_trucking.py: FULFILLMENT_* constants + _set_fulfillment_status();
  gate sets authorization_required on pause, authorization_signed on
  resume, ready_to_file once the filing todo is queued
- TruckingValueNotice.astro: 'What's included & what's billed at cost'
  disclosure with the authorization/delegation explanation
2026-06-02 16:49:31 -05:00
justin
53857574d3 Add referral/discount code to FCC carrier page + REF-JAYK05 agent
Frontend (order/fcc-carrier-registration):
- Add a referral/discount code box on the review step that validates
  against /api/v1/discount/:code and shows the discount line + adjusted
  total. Discount applies to service fee + add-ons, never state filing fees.
- Prefill + auto-apply from ?code= / ?ref= query param (referral links).

Backend (fcc-carrier-registration route):
- Accept discount_code, validate it, store discount_code/discount_cents,
  and subtract from the total. Checkout already reads discount_cents to
  apply the Stripe coupon.
- Create a pending commission when the code belongs to an active sales agent.

Commission fix (agents.createCommission):
- Percent-type agents now earn commission_pct on ALL order types. Previously
  canada_crtc/formation/bundle used flat defaults and ignored percent agents.

Agent: created sales agent Jay Kordic (The Horizon Group) with custom code
REF-JAYK05 -> client gets 5% off discountable services, agent earns 15%.
Idempotent setup script in scripts/create_agent_jaykordic.cjs.
2026-06-02 14:31:22 -05:00
justin
1584a6692b Pivot CRTC offering on FCC carrier page for A-Z wholesale carriers
The international (Q6) CRTC block was framed as a generic upsell (Expand
2026-06-02 13:26:39 -05:00
justin
c9d76545b3 intake: guard hoisted ResellerCertStep script 2026-06-02 13:21:27 -05:00
justin
539fad1396 intake: guard hoisted history/revenue step scripts 2026-06-02 13:19:48 -05:00
justin
bb3604c97b intake: guard category/officer/jurisdiction step scripts when hoisted 2026-06-02 13:16:48 -05:00
justin
4e916821c6 intake: guard hoisted EntityStep script on non-entity pages 2026-06-02 13:14:45 -05:00
justin
0fe8ce53ac intake: guard hoisted step scripts against absent DOM
Astro hoists multiple step scripts from Wizard even when the step is not
rendered on the current order page. Several steps bound DOM elements at load
time with no presence check, causing null addEventListener errors on unrelated
order pages.

Add step-presence guards to the obvious offenders used by the shared wizard:
IccImportStep, Block6CertStep, WirelessStep, BundledServiceStep, CPNIStep,
and LNPARegionStep.
2026-06-02 13:12:40 -05:00
justin
219507ce74 intake: fix hoisted payment-step null error and success nav cleanup
- Guard PaymentStep DOM bindings so its hoisted script no longer throws on
  pages without a payment step.
- Remove the correct wizard nav element on successful intake submit
  (pw-wizard-nav, not the nonexistent pw-wizard-footer).
2026-06-02 13:08:47 -05:00
justin
d0d39ebcbc intake: validate cold ?dot= orders before checkout (fix 422)
The cold-visitor Finish flow created the order then called Stripe Checkout
directly, which is gated on intake_data_validated=true and returned 422
INTAKE_NOT_VALIDATED. Now call POST /compliance-orders/:n/validate between
create and checkout (matching the token-order flow), and surface any missing
required fields to the user instead of a raw HTTP error.
2026-06-02 13:03:14 -05:00
justin
5c2f32c6f2 order: reframe state trucking fees as money recovered + deductible
Add TruckingValueNotice on the 14 state trucking order pages. Each page now
shows, near the price:
  - 'You already owe this' reframe: the tax/fee is a liability the moment the
    carrier operates in the state; we do not create it.
  - Per-program 'how you protect and recover money' bullets (IFTA fuel-tax
    credits/refunds, IRP apportionment vs trip permits, avoided penalties,
    citations, out-of-service, and protected operating revenue).
  - 'Is this a tax write-off?' section: BOTH our service fee AND the state
    tax/fee paid are deductible business expenses (IRC 162), with the exact
    return line per entity type (Schedule C / 1120 / 1120-S / 1065), mirroring
    the telecom TaxDeductibilityNotice pattern. Fuel taxes noted as part of
    fuel cost.
Not tax advice; disclaimer included.
2026-06-02 13:00:44 -05:00
justin
53ae3ef870 intake: cold ?dot= visitors can finish + correct per-state CTA links
- Wizard Finish button: for visitors with no token/order (e.g. arriving via a
  campaign ?dot= link), create the compliance order from collected intake data
  and redirect to Stripe Checkout, instead of silently doing nothing.
- StateTrucking: Operating States no longer required; single-state/intrastate
  carriers can finish (relabeled 'Other Operating States (if any)').
- build_trucking_campaigns: per-state programs (weight_tax/emissions) now derive
  the CTA landing page from the deficiency flag's state suffix (e.g.
  state_weight_tax_OR -> OR), not the carrier base state, so a GA-based carrier
  flagged for OR weight-mile tax links to the OR page (not a mismatched one).
2026-06-02 12:56:03 -05:00
justin
d420c49818 intake: prefill order form from ?dot= campaign CTA links
Campaign CTA buttons link to /order/<slug>?dot=1234567. Add a fast local-only
GET /api/v1/dot/census endpoint (vs the heavy 12s live /dot/lookup) and a ?dot=
branch in the Wizard that seeds intake_data from the carrier's cached FMCSA
census record (name, email, base state, city/street/zip, power units). The
existing StateTrucking step already prefills its inputs from intake_data, so the
form now shows up pre-populated. Best-effort: only fills empty fields, never
blocks the form, never overwrites visitor input.
2026-06-02 12:46:33 -05:00
justin
4010103531 Lower trucking compliance pricing across product + marketing surfaces
Permanent price cuts:
- MCS-150 Biennial Update: $69 -> $39
- UCR Annual Registration: $69 -> $39 (+ gov fee unchanged)
- MC Operating Authority: $349 -> $199 (+ $300 FMCSA fee unchanged)
- State compliance programs (IRP, IFTA, weight-distance/HUT/HUF/KYU,
  intrastate, OSOW, state DOT, state emissions): -> $109
- California MCP + CARB: $349 -> $229

Updated source of truth (compliance-orders.ts, intake_manifest SERVICE_META),
stale dot-lookup recommendation prices, all static trucking landing/marketing
pages (services/trucking/*, order/dot-compliance, pricing), and the email
campaign scripts (setup_trucking_campaigns, create_state_campaigns).
FE/BE price cross-check: all 16 changed slugs consistent. tsc clean,
fulfillment consistency 24/24, site build OK.
2026-06-02 10:45:07 -05:00
justin
9466ce24f1 Add IRP/IFTA, drug & alcohol, hazmat, and new-carrier trucking landing pages
Fills the 7 missing /services/trucking/* pages referenced by
setup_trucking_campaigns.py (kentucky, new-mexico, connecticut done earlier;
these 4 complete the set). Each follows the Oregon page template with
service-specific requirements + CTAs routing to the correct /order/ page.
2026-06-02 10:31:42 -05:00
justin
1a1e93bc04 Add Connecticut trucking compliance landing page 2026-06-02 10:23:57 -05:00
justin
439cd9d525 Add New Mexico trucking compliance landing page 2026-06-02 10:20:08 -05:00
justin
9721042669 Add Kentucky trucking compliance landing page 2026-06-02 04:10:59 -05:00
justin
b85be726b7 feat(fulfillment): bundle/exclusion enforcement + REQUIRED_FIELDS + intake wiring (Phases 1/1.5/2)
- compliance-orders: hazmat-phmsa/state-emissions products, full REQUIRED_FIELDS
  table for all DOT/state/hazmat slugs, BUNDLE_COMPONENTS dedup + MUTUALLY_EXCLUSIVE
  enforcement on /batch (single source of truth, exported)
- checkout: empty ADMIN_ASSISTED_SLUGS (state/hazmat now get intake links)
- services/__init__: register HazmatPHMSAHandler + state-emissions handler
- state_trucking: _summarize_intake admin-todo enrichment
- Wizard: wire StateTruckingIntakeStep + step labels
2026-06-02 03:51:25 -05:00
justin
3322003da0 feat(order-pages): landing pages for all state/hazmat/emissions slugs
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.
2026-06-02 03:33:23 -05:00
justin
cadff79bd6 test(fulfillment): consistency + intake-completeness checker
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.
2026-06-02 03:29:53 -05:00
justin
9c6b8d95e0 feat(fulfillment): state-trucking intake form + hazmat/emissions products
- Add StateTruckingIntakeStep.astro with slug-gated sections (IRP/IFTA,
  emissions, intrastate authority, OSOW, hazmat/PHMSA); wired into Wizard
- Register hazmat-phmsa + state-emissions products & SERVICE_INFO
- Add server-side bundle/mutual-exclusion enforcement + REQUIRED_FIELDS
- State-trucking slugs now collect real intake data (were review-only)
- Surface slug-specific intake fields in admin todo (_summarize_intake)
- Remove state slugs from email ADMIN_ASSISTED set (now get intake links)
2026-06-02 03:27:51 -05:00
justin
3d611e97a4 tawk mobile UX: hide widget on small screens to stop text overlay popups
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>
2026-06-01 12:31:01 -05:00
justin
02112facf5 capture client signature before filing signed DOT forms
Forms that legally require the client's signature were not being captured
correctly:

- MCS-150 handler created a perjury e-sign record but then submitted to FMCSA
  anyway, before the client signed. Now it gates submission: request the
  signature, hold, and only file when handle_esign_completed re-dispatches with
  client_approved=True.
- MCS-150 e-sign links were signed with JWT_SECRET/ADMIN_JWT_SECRET, but the
  portal verifies with CUSTOMER_JWT_SECRET, so every link returned "Invalid
  portal link." New shared dot_esign helper signs with CUSTOMER_JWT_SECRET.
- carrier-closeout (final MCS-150 Out of Business) and entity-dissolution
  (Articles of Dissolution + no-lawsuits/liens/judgments attestation) captured
  no signature at all. Both now request a signed attestation before the
  workflow proceeds.
- mc-authority / emergency-temporary-authority now get a correctly labeled
  OP-1 applicant certification instead of an "MCS-150" record.

Also fixes a latent dispatcher bug: order["service_slug"] was never set, so
handlers sharing a class fell back to their default SERVICE_SLUG. This made
entity-dissolution run the carrier-closeout branch and mc-authority/etc. look
like mcs150-update. Now the resolved slug is injected into order_data.

Portal e-sign page now renders the document-specific certification text from
metadata.perjury_text (so the dissolution no-liabilities attestation and OP-1
cert are actually shown to the signer), not just a generic perjury line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 20:30:09 -05:00
justin
6def0f6186 collect photo ID for all FMCSA filings that legally require the signer's ID
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>
2026-05-31 18:00:59 -05:00
justin
17b16087a4 checker sell-trucks: add Company name field prefilled from the carrier record
Separate from the contact's first/last name; defaults to data.legal_name.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 17:53:16 -05:00
justin
ae52c63983 add tawk.to live chat to 8 order/tool pages that were missing it
dot-compliance, trucking-new-carrier, neca-ocn, fcc-carrier-registration,
corporation-check, identity-complete, state-puc, fcc-499q.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 17:46:49 -05:00
justin
07e2f34608 dot-compliance: mutually-exclusive service conflicts + hero copy/layout
- Auto-uncheck conflicting services: closing-down (carrier-closeout, entity-
  dissolution) vs any operational filing; new USDOT vs reactivation; new USDOT
  vs MCS-150 update.
- Hero: removed 'this is all we do' (we also do telecom); 4-col grid.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 17:40:48 -05:00
justin
d3bf5b3520 preview test send: keep {{ UnsubscribeURL }} (real link); hero 4-col to save vertical space
- send_test no longer overwrites {{ UnsubscribeURL }} with a dead static URL;
  Listmonk renders it into a working per-subscriber unsubscribe link.
- dot-compliance hero grid: 4 columns (minmax 150px, max-width 920px) instead
  of 3 to reduce vertical space.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 17:38:57 -05:00
justin
b66b5a4cdc dot-compliance: expand hero with PW specialty, speed, and customer service
4-card dark hero: specialized in trucking compliance, fast turnaround (1-2 days),
attention to detail (verified against current FMCSA reqs), real people/support.
Trust bar updated: No Login.gov required + Klarna added.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 17:17:17 -05:00
justin
659f257167 dot-compliance order: add Emergency Temporary Authority ($499) + USDOT Reactivation ($149) cards
These were missing — the ETA button in email 188 linked to the order page
with services=emergency-temporary-authority but no matching checkbox existed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 17:12:20 -05:00
justin
54a46062a5 review fixes: wrap-up checkout dead-end, confident entity flag, textarea style
- order/dot-compliance: add carrier-closeout ($199) + entity-dissolution ($49)
  cards so the checker's wrap-up CTA actually resolves (was a dead-end: no
  matching data-slug checkbox to pre-select)
- new-carrier flag: drop the 'not tax advice / we'll confirm' hedge, reframe
  confidently as a fee/cost point (not taxes); only show the Wyoming-LLC caveat
  when Wyoming is actually selected
- checker: fix malformed inline style on the sell-truck textarea (missing ;)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 02:02:20 -05:00
justin
d85fdd36d9 new-carrier wizard: flag corp-favorable states (CA/TN/NY) in the entity step
When forming or operating in CA (gross-receipts fee >$250k), TN ($300 vs $20
report), or NY (LLC publication + filing fee), show an advisory with the reason
and a one-click 'Use a corporation'. Keyed off wiz.entityState/baseState.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 01:47:42 -05:00
justin
ffe6f34bc8 wrap-up: reframe as done-for-you (we file everything; client only cancels insurance etc.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 01:25:58 -05:00
justin
374db59ba7 checker: add 'not selling' sell-trucks option; remove em dashes from trucking pages
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 01:21:23 -05:00
justin
c98f48848c entity dissolution: $49 add-on to wrap-up + state fees (was $199)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 01:13:19 -05:00
justin
b25d1f5fd3 trucking wrap-up: close-out becomes a paid order + workflow
- Checker closing mode now pitches a done-for-you 'Trucking Wrap-Up' ($199)
  with a buy button to /order/dot-compliance?services=carrier-closeout, instead
  of a lead form. DIY checklist replaced by what's-included list.
- Entity dissolution offered as a paid add-on with the lawsuits/liens/judgments
  warning before dissolving.
- New catalog services: carrier-closeout ($199), entity-dissolution ($199).
- CarrierCloseoutHandler orchestrates the sequential shutdown workflow
  (final MCS-150 out-of-business, MC revoke, UCR cancel, IFTA/IRP + state
  closures; dissolution branch for the add-on) as admin-tracked tasks.
- Sell-your-trucks: single shared form with quick-cash / marketplace / both;
  name field is now a real first+last name (no corp-name prefill).
- tickets categories: add truck_sale_both, drop business_closeout (now an order).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 01:01:02 -05:00
justin
5f3a9dc54f web: remove CB 10-codes and ByeTruck name from checker + new-carrier page
- 10-code jokes are email-only now; revert checker/new-carrier CTAs to plain
- Sell-trucks quick-cash flow no longer names ByeTruck or links out; lead still
  routes via the truck_sale_quickcash ticket (internal routing stays generic)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 00:48:12 -05:00
justin
0835358cd4 add resized 536px JPEG banner for trucking emails (lighter, fits display 1:1)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 00:43:58 -05:00
justin
d9ffda27a4 trucking CTAs: CB 10-codes in buttons + compliance-check button on new-carrier page
- DOT checker: '10-4' on Fix My DOT Filings / Get These Handled; '10-7'
  (out of service) on the business close-out CTA
- New-carrier (LLC) page: add a free Compliance Check button in the hero

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 00:07:55 -05:00
justin
c0021c3cd6 DOT checker: add business close-out mode + sell-your-trucks routing
- Intent toggle: 'staying in business' (compliance) vs 'closing my business'
- Closing mode shows a green, personalized wind-down checklist from FMCSA data
  (final MCS-150/USDOT deactivation, MC revoke, UCR, IFTA/IRP, state permits,
  insurance, entity dissolution) + 'let us handle the shutdown' lead capture
- Sell-your-trucks box: quick cash -> ByeTruck referral lead + handoff;
  marketplace -> email capture for follow-up guide
- Deep link via ?intent=closing for the email CTAs

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 23:57:44 -05:00
justin
df48ef786d add CB radio accessories banner image for trucking email campaigns
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 23:43:36 -05:00
justin
e1ece093cd show order timeline with step names + estimated dates on success page
Visual timeline with dots, connecting lines, step names, descriptions,
and business-day estimated completion dates. Fetches from /api/v1/order-timeline.
2026-05-30 22:49:35 -05:00
justin
d6704e850e rebuild new carrier page as 4-step wizard: fleet profile → entity strategy → services → checkout
Step 0: fleet size, vehicle type, cargo (hazmat), interstate/intl, base state, operating states, for-hire/private
Step 1: existing entity or new, home state vs Wyoming optimization, name check (SOS + FMCSA parallel)
Step 2: auto-populated services from matrix, bundle detection, non-discountable items marked
Step 3: checkout with Klarna 4 payments, discount codes, batch order flow
2026-05-30 22:24:07 -05:00
justin
21b94c9ea9 add New Carrier Setup link to nav across all static pages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 22:12:23 -05:00
justin
479f3dfc45 add entity upgrade bundle service + deploy completion/IMAP crons
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 22:12:11 -05:00
justin
ad3d189b2b post-completion flow: survey, referral program, review ask
- Migration 081: referral_codes, referral_uses, exit_surveys tables
- API: POST /api/v1/survey, POST /api/v1/referral/check, GET /api/v1/referral/:email
- Worker: completion_emails.py — sends completion + 24h follow-up (survey + referral)
- Survey page: /survey/?order=X&rating=N — star rating, feedback, Google review ask
- Referral: REF-FIRSTNAME codes, $25 credit per referred order, no limit
- Low ratings (1-3 stars) trigger Telegram alert for admin follow-up
- Cron: every 15 minutes
2026-05-30 21:22:14 -05:00
justin
4cde6bbb4a add financing/factoring interest checkbox on success page + campaign topics 16-17
- Checkbox on post-order success page: 'Interested in freight factoring?'
- Stores lead via /api/v1/insurance-leads with source=financing_interest
- Added factoring + fuel card campaign topics to docs
2026-05-30 21:15:25 -05:00
justin
340a364d8c add insurance + state compliance upsells to success page for trucking orders
- Insurance lead capture: pre-filled name/email from order, submits to /api/v1/insurance-leads
- State compliance CTA: shown for new carrier orders, links to DOT compliance page
- Only shown for trucking/DOT order slugs
2026-05-30 20:57:30 -05:00
justin
29ff57694e add new carrier order page with Klarna 4-payments option
/order/trucking-new-carrier/ — for new trucking businesses without a DOT:
- New Carrier Starter Bundle 99 (LLC + USDOT + MC Auth + BOC-3 + MCS-150 + D&A)
- Individual service cards with bundle auto-toggle
- Klarna 4 payments, Card, PayPal, ACH
- No DOT pre-fill (new carriers)
2026-05-30 20:54:35 -05:00