Commit graph

182 commits

Author SHA1 Message Date
justin
9919947440 Fix: Flowroute (Intrado) -> Flowroute (BCM One)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-27 11:17:13 -05:00
justin
15cd006260 Vendor guide: Calibri font, US carrier note, cleanup
- Set Calibri as explicit font on all runs via _run() helper
- Added note that many large US carriers work with Canadian carriers
  and to ask about specific regulatory requirements
- BCM One ownership for Flowroute
- Cleaned up leftover manual font assignments

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-27 11:16:02 -05:00
justin
3bac30510e Update Flowroute ownership: now BCM One (acquired from Intrado)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-27 11:14:12 -05:00
justin
32c1e57c5c Add Canadian Wholesale Vendor Reference Guide to CRTC binder
New DOCX generator with 8 recommended upstream providers:
Fibernetics, Iristel, Flowroute, VoIP.ms, Telnyx, SkySwitch,
Distributel, Allstream. Each with services, website, and notes.

Wired into CRTC handler Step 6a (generates before eSign pause)
and added to binder compiler default sections.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-27 11:11:47 -05:00
justin
7aec5b23cb Add Fibernetics to recommended Canadian wholesale carrier references
Added alongside Iristel, Flowroute, and SkySwitch in the CRTC
service page case studies and wholesale provider mentions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-27 11:08:36 -05:00
justin
7139630fa8 Add Accessible Canada Act (ACA) compliance tracking for CRTC orders
- CRTC handler: new compliance calendar entry for ACA accessibility
  plan/progress report (June 1 annual deadline), with 2-month advance
  reminder. Covers new entrant feedback process and existing carrier
  plans/reports. Notes dual notification requirement (Commissioner + CRTC).
- Order page: amber advisory banner about June 1, 2026 ACA deadline
  with key obligations and penalty warning
- "What's included" list: added ACA accessibility compliance tracking

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-27 10:09:33 -05:00
justin
d4c4ae003e Fix 6 bugs from code review
Critical:
- Single-order discount used wrong column names (discount_pct/discount_flat_cents
  → discount_type/discount_value). Discounts were silently $0.
- Single-order discount skipped allowed_emails and expires_at checks
- Free orders now set paid_at = NOW()

High:
- Discount usage now tracked in discount_usage table + current_uses incremented
- Flat discount only replaces bundle when flat >= bundle (was always replacing)

Minor:
- Removed unused CDR profile fetch in EntityStep

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 02:16:38 -05:00
justin
4125b0f09f Auto-fill entity from FRN in order intake_data, not just URL param
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>
2026-05-22 01:53:44 -05:00
justin
03c72a2525 Pre-fill intake form from order data via ?order=CO-xxx
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>
2026-05-22 01:51:12 -05:00
justin
2316168072 Clarify email field is not shared with FCC
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 01:49:53 -05:00
justin
d62a858098 Clarify USAC Filer ID: 6 digits starting with 8, with example and link
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 01:48:47 -05:00
justin
0cb6e20021 Clarify intake form labels: name, email, carrier entity
- "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>
2026-05-22 01:47:52 -05:00
justin
bf0c6dc85e Hide payment methods when order total is $0
When discount brings total to zero, hide the payment method selector
and change button from "Continue to Secure Payment" to "Place Free Order".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 01:32:30 -05:00
justin
a8cdfc65f6 Fix: promo re-render trigger used wrong checkbox selector
Was looking for .svc-cb:checked but checkboxes use
input[data-slug]:checked. Discount display never updated after
promo info loaded.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 01:30:26 -05:00
justin
de50971fb3 Add intake form links to compliance order confirmation email
The confirmation email now includes a prominent blue box with
direct links to the intake form for each ordered service. Subject
changed to "Action Required" to prompt the customer to complete it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 01:26:33 -05:00
justin
5cb360acba Fix: add allowed_emails to DiscountCode TypeScript interface
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 01:19:12 -05:00
justin
6ed5105ae5 Send intake email for $0 free orders
Free orders bypass Stripe, so the Stripe webhook never fires and the
intake/confirmation email never gets sent. Now trigger
sendComplianceIntakeEmail directly in the $0 bypass flow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 01:18:19 -05:00
justin
844cc7e11f Add inline free-order success handler to success page
Static inline script that verifies $0 orders via API and shows
"Order Confirmed" state. Re-asserts success state on delays to
override the Astro hoisted JS which would otherwise show error
(since there's no Stripe session_id for free orders).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 01:11:26 -05:00
justin
b81e102d39 Validate allowed_emails on discount code lookup
The /api/v1/discount/:code endpoint now checks allowed_emails when
an email is provided. If the email isn't in the allowed list, returns
valid:false so the frontend doesn't show a fake discount. The promo
field is cleared and unlocked if validation fails.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 01:08:51 -05:00
justin
7bb08f3493 Handle already-paid orders gracefully in checkout
When create-session is called for an order that's already paid (e.g.
free order with page refresh, duplicate submit, or browser retry),
return a success redirect instead of 404. Prevents confusing
"Payment Not Confirmed" errors on the success page.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 01:07:27 -05:00
justin
316d4a4912 Fix success page for $0 free orders
When free=1 is in the URL, verify order status via API instead of
looking for a Stripe session. Checks payment_status=paid on the
server side — no security hole since the server already validated
the discount code before marking the order paid.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 01:01:02 -05:00
justin
ae5dc4745e Fix: fetch actual discount type/value from API instead of hardcoding 25%
The checkout page was hardcoding 25% for all promo codes. Now fetches
/api/v1/discount/:code to get real discount_type (percent vs flat) and
discount_value, then displays correct amount.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 00:56:44 -05:00
justin
fdbed5c097 Pre-fill email from URL on checkout and compliance checker
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>
2026-05-22 00:49:28 -05:00
justin
b91e76e44c Fix: FCC errors now fall through to local DB fallback
Was returning 502 early instead of throwing to trigger the catch block
where the local fcc_499_filers fallback lives.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 00:42:43 -05:00
justin
bbfa6393fa Fall back to local DB when FCC name search is blocked
FCC/Akamai is blocking our server IP (403). Name search now falls back
to querying the local fcc_499_filers table (20K+ records) when the
live FCC search fails.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 00:41:47 -05:00
justin
33684a9152 Better error message when FCC 499 search is down
FCC ColdFusion app returns 503 periodically. Show helpful message
suggesting FRN search instead of generic "Search failed".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 00:39:38 -05:00
justin
7909f130c6 Fix $0 checkout bypass: remove nonexistent status column
compliance_orders has payment_status, not status.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 00:36:15 -05:00
justin
6d441a5cc0 Add email-restricted discount codes and $0 order bypass
- discount_codes.allowed_emails: when set, code only valid for listed emails
- Flat discounts now replace bundle discount (don't stack)
- $0 orders skip all payment gateways, mark paid immediately, redirect to success
- FREEDOM249: $249 flat off restricted to 4+ deficiency carriers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 00:16:47 -05:00
justin
868b0eeca5 Pass promo code through compliance checker to order page
- 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>
2026-05-21 15:16:27 -05:00
justin
ba2f6eb667 UPL-proof document templates + reliable bounce sync
Templates (22 files):
- Replace "Reviewed By" with "Document prepared by" + consulting disclaimer
- Add "not a law firm / not legal advice" footer to all CPNI, CALEA, RMD docs
- Change "on behalf of" to "at the direction of" in discontinuance letter
- Reframe RMD penalty language as client acknowledgment

Bounce sync:
- New listmonk-bounce-sync.py replaces unreliable bash tail watcher
- Scans full mail.log, matches QIDs to campaign senders, inserts directly
  into Listmonk DB with proper subscriber_id foreign keys
- Idempotent, runs via cron every 5 minutes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-21 15:06:29 -05:00
justin
d39e10485f Add URL promo code pre-fill and fix discount stacking logic
- Checkout page reads ?code= or ?promo= from URL, pre-fills and locks the
  promo field, shows the promo discount in the summary instead of the 15%
  bundle discount
- API: when a promo code % >= bundle %, replace the bundle discount entirely
  instead of stacking (e.g. MEMORIAL25 at 25% replaces the 15% bundle)
- Also checks discount code expiration in the query

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-21 15:06:19 -05:00
justin
5a07335b2f Fix: remove escaped backticks that broke compliance checker JS
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>
2026-05-20 16:18:30 -05:00
justin
397e006321 Fix: remove remaining TypeScript assertions from inline script
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>
2026-05-20 16:06:33 -05:00
justin
b9f27e939a Fix: remove TypeScript annotation from inline script (broke compliance checker)
Record<string, string> type annotation leaked into compiled JS output,
causing SyntaxError that silently broke the entire script block.
runCheck() and all event handlers stopped working.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-20 16:02:42 -05:00
justin
45e2172417 Fix checkout page UX: card first, shorter legal, trust signals, help link
- Card payment now default (was ACH — lower trust barrier for new customers)
- Removed +3% surcharge labels (reduces friction)
- Shortened authorization text to one line (was intimidating paragraph)
- Added trust signals below button: 256-bit SSL, Powered by Stripe, PCI compliant
- Added "Questions?" help box with phone + email below checkout
- Button text: "Continue to Secure Payment" with green glow shadow

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-18 20:57:06 -05:00
justin
54bdb9d480 Add sticky CTA bar, penalty warnings, lead capture to compliance checker
- Sticky bar fixed to bottom: "N issues found — your filing needs to be
  corrected" with "See How to Fix This" + "Call Us" buttons
- Per-filing penalty warnings on red/yellow cards: RMD removal from network,
  CPNI $239K/violation, 499-A Red Light blocks all FCC apps, CALEA $10K/day,
  CORES can't legally operate
- CTA copy changed: "Your filing is inaccurate" urgency box + "Fix My Filing"
  button with "no commitment until you pay" reassurance
- Lead capture form: "Get your compliance report emailed" for people not
  ready to buy — creates ticket + tracks lead-capture event in Umami

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-13 12:29:47 -05:00
justin
71d466c922 Wire createCommission() into compliance batch checkout
Compliance batch orders now create commission ledger entries when
a discount code (agent referral) is used. Tracks total order amount,
discount applied, and links to the agent for payout processing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 11:00:38 -05:00
justin
fa80c6dab9 Add FCC penalty warnings below order total on checkout page
Shows specific penalty amounts for each filing type:
- RMD: $500K per violation, network disconnection
- CPNI: $239K per violation, $2.39M continuing
- 499-A: USAC Red Light blocks all FCC applications
- CALEA: $10K/day court-enforced
- Registration forfeiture for persistent non-compliance

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-09 11:11:26 -05:00
justin
0ef07e25b4 Remove prices from compliance checker service selection
Hide individual service prices and total/discount row from the
compliance checker results. Users see service names + checkboxes
only. Prices revealed on the order page after clicking Get Started.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-09 11:05:24 -05:00
justin
acf72da341 Remove prices from compliance checker — show only on order page
Prices removed from CTA buttons and banner cards on the checker.
Users see "Get Started" instead of dollar amounts, reducing sticker
shock before they understand the value. Prices shown on the order
page where they can see itemized services.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-09 10:50:59 -05:00
justin
b1750cfd20 Fix compliance check logging: use status (red/yellow/green) not severity
Check objects use status field (red/yellow/green), not severity
(critical/major/minor). Logging was always recording 0 issues.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-07 12:10:03 -05:00
justin
b5282f5e00 Fix compliance checker: include structured_checks + pdf_checks from audit
Was only reading pdf_checks, missing structured_checks. Also skip
minor-only issues — show major/critical that match email campaign data.
This fixes the "clean" result for carriers our audit flagged as deficient.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-07 10:59:59 -05:00
justin
9c1b1387cb Update docs + add 3 SVG flowcharts
New diagrams:
- business-flow.svg: acquisition → check → order → filing → delivery
- technical-architecture.svg: full Docker stack, data tier, external services
- order-flow.svg: detailed worker pipeline with eSign gate and handler map

Updated docs:
- infrastructure.md: DocServer, email servers, backup server sections
- architecture.md: linked to new SVGs, updated date

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-07 09:17:36 -05:00
justin
c127cdd908 Improve compliance checker UX + add search logging
- Loading message: shows estimated time (30-90 seconds) + rotating status
  updates (RMD, CPNI, USAC, BDC, STIR/SHAKEN, compiling report)
- Timeout increased to 90s (was 60s)
- Error messages: "try again in a few minutes" (not "moments" or "check internet")
- New compliance_check_log table: logs every FCC lookup with FRN, entity,
  IP, user agent, referrer, issue count, severity, response time
- Enables conversion funnel analysis and follow-up

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-06 22:37:29 -05:00
justin
0085e2b33e Add ERPNext Dockerfile + build script for automated security rebuilds
- erpnext/Dockerfile: builds from frappe/erpnext:v15 base with custom apps
- erpnext/build.sh: stages custom apps into build context before docker build
- Container update script now runs build.sh pre-build + extracts assets post-build
- ERPNext will auto-rebuild nightly when base image has security patches

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-06 22:10:49 -05:00
justin
941349ccd9 Update pricing page with full telecom service catalog
Added all 20 telecom services with current API prices:
- FCC Carrier Registration bundle $1,299 (save 35%)
- Annual filings: 499-A $499, Zero $179, +Q $599, Discontinuance $299
- CPNI $199, RMD $249+fee, BDC $199-$349
- Setup: CORES $149, 499 Initial $349, CALEA $799, DC Agent $149
- STIR/SHAKEN $499, OCN $2,650, State PUC $399/state
- Free compliance checker highlighted
Organized into sections with category headers on both desktop and mobile.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-05 19:37:29 -05:00
justin
bd5193e45f Add Umami custom event tracking across all key pages
- Created /js/pw-analytics.js with conversion funnel events
- Added to Base.astro layout (all Astro pages) + 6 static HTML pages
- Events tracked: compliance-check-start, compliance-check-complete,
  order-cta-click, checkout-page-view, checkout-start, esign-opened,
  esign-submitted, campaign-click (UTM attribution), contact-form-submit
- Server-side payment-complete event from checkout webhook via Umami API
- Auto-tracks any element with data-track="event-name" attribute

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-05 05:10:13 -05:00
justin
19eb8ff2e8 Add compliance order pipeline tracking + fix Closed status bug
- Added COMPLIANCE_PIPELINE with 7 stages (Received → Filing → Complete)
- Show service items as type label for compliance orders
- Fixed is_cancelled: only "Cancelled" counts, not "Closed" (ERPNext
  auto-sets Closed when fully billed, which is wrong for active orders)
- Changed delivered badge text from "binder delivered" to "documents delivered"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-04 21:09:58 -05:00
justin
42a81f2868 Fix portal invoice link to use PDF download instead of desk URL
/Sales Invoice/NAME goes to desk (permission error for portal users).
Changed to PDF download API which respects portal user permissions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-04 20:49:37 -05:00
justin
19be48231d Fix portal orders: remove nonexistent custom_contact_email field query
The custom_contact_email field doesn't exist on Sales Order DocType,
causing the email-based fallback query to crash. Simplified to use
Customer record lookup only (email_id match works).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-04 20:43:33 -05:00