safe_int now clamps values to PostgreSQL INTEGER max (2.1B) and
handles scientific notation. Mileage columns changed to BIGINT
on prod since carriers can have >2B annual miles.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Uses pypdf to fill the official MCS-150/150B/150C fillable PDFs.
Maps intake data to 289 form fields (text + checkboxes).
Supports form type detection (standard vs hazmat vs intermodal).
Produces ready-to-fax PDF from intake data.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PayPal capture was defaulting to canada_crtc_orders table for all
non-formation orders. Now properly routes compliance_batch orders
to compliance_orders table with batch_id lookup. Also infers
order type from ID prefix (CB-=batch, CO-=compliance, FO-=formation).
MCS-150 form generator: produces DOCX with fax cover sheet + filled
MCS-150 form for faxing to FMCSA at 202-366-3477.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bounces showed 0 in campaigns because the webhook didn't include
campaign_uuid. Now fetches UUID of running campaign via API and
includes it in bounce reports. Refreshes every 100 messages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Before checking the real address, sends a random 20-char address to
the domain. If the server accepts it (250), the domain is catch-all
and individual verification is meaningless. Result cached per domain.
Existing known catch-all list (gmail, outlook, etc.) still bypassed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Listmonk bulk import API returns 400. Switch to individual POST
/api/subscribers with 409 conflict handling (update existing subs
to add them to the new list). Progress logging every 200 records.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
FMCSA census carrier_operation is single-letter: A=Interstate,
B=Intrastate Hazmat, C=Intrastate Non-Hazmat. Previous code searched
for "interstate" in text which never matched. Now 22,089 interstate
carriers will be properly flagged for IRP/IFTA.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- boc3_playwright.py: 4-step form automation (company info, contact,
account, payment) using patchright/undetected Playwright
- Payment with PW company card ($25/filing), credentials from env
- CAPTCHA detection — falls back to admin todo if reCAPTCHA triggers
- boc3_filing.py: process() tries Playwright first, falls back to
manual admin todo on failure
- Env vars needed: PW_CARD_NUMBER, PW_CARD_CVC, PW_CARD_EXP_MONTH,
PW_CARD_EXP_YEAR, BOC3_ACCOUNT_PASSWORD
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ProcessAgent.com is subsidiary of Registered Agents Inc. $25/yr
blanket BOC-3, no API, will automate via Playwright. Updated
partner details, admin todo steps, removed dead API stub.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- For-hire carriers now flagged with issues (BOC-3/UCR/insurance needed)
- Zero trucks/drivers flagged as stale data
- For-hire + MCS-150 overdue = critical severity
- Actionable flags count excludes zero_fleet (informational only)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MCS-150 Biennial Update ($79):
- Admin-assisted filing (FMCSA Portal requires Login.gov MFA)
- Creates admin todo with intake data and filing steps
- Checks current MCS-150 status via FMCSA API
- Sends status email to client
BOC-3 Process Agent Filing ($149):
- Partners with blanket process agent (NWRA or similar)
- Collects carrier info, submits designation to partner
- Partner files electronically with FMCSA
- Stub for future process agent API integration
- Sends status/confirmation emails
Both follow the same handler pattern as FCC services (admin todo
with structured data when full automation isn't possible).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 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>
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>
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>
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>
- CRTC letter now auto-emailed to secretary.general@crtc.gc.ca after eSign
- BITS admin todo updated to reference electronic + physical submission
- COLIN selectors.py: documented verification status per step
- BC config: added CRTC Secretary General email address
- plan.md: marked completed items (eSign, portal auth, CRTC email)
- go-live-todo.md: marked Compliance Calendar DocType as imported
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
_convert_to_pdf() now calls pdf_converter.convert_to_pdf() which tries
the Windows Word VM via MinIO first (pixel-perfect), falling back to
LibreOffice headless automatically when the VM is unavailable.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- upload_file doesn't exist on MinioStorage — the method is upload()
- Return [] when pausing for eSign so job_server doesn't trigger instant delivery
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each handler now pauses for officer signature via the eSign portal
before filing/submitting. esign_completed callback re-dispatches
through standard pipeline with client_approved=true.
- CPNI: officer signs certification before ECFS submission (perjury)
- CALEA SSI: officer signs plan before delivery
- 499-A engagement: replaced custom JWT/email with request_esign()
- Discontinuance: officer signs deactivation letter before USAC email
- job_server: injects client_approved + order_number into order_data
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reusable signing flow: service handler generates document → inserts
esign_records row → emails JWT link → client reviews PDF + signs →
API stores signature + resumes pipeline. Works for RMD, CPNI, CALEA,
499-A engagement, discontinuance, CRTC, and any future doc types.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The checklist was a manual-process artifact that listed what info the
client needed to gather. Since all data is now collected through the
intake wizard and CDR upload, the checklist is unnecessary. Removed
from the 499-A handler's prep packet and deleted the 1,326-line
generator file.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
_styles.py: Centralized typography, spacing, and formatting for all
26 DOCX generators. Calibri 9.5pt body, 1.15 line spacing, navy
headings, consistent signature blocks, page numbers, PW footer.
All generators will be migrated to use this instead of defining
their own styles.
Campaign tools:
- campaign_template.html: Styled email template for Listmonk campaigns
- populate_deficiency_list.py: Populates Listmonk with FCC deficiency data
- send_test_campaigns.py: Sends test emails with real carrier data
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Critical #1 — CRTC: Fix undefined 'province' variable (canada_crtc.py:1322)
Crashes every order at Step 6 document generation. Replaced with
order_data.get("custom_incorporation_province", "BC").
Critical #2 — FCC Carrier Reg: Add State PUC state picker
The order page collected "1/few/nationwide" but API expected an array
of state codes. Added a multi-state checkbox grid that appears when
State PUC add-on is checked. Sends puc_states: ["CA","NY",...] in
service_wizard. Price updates per-state ($399 × count).
Critical #3 — Compliance: Add REQUIRED_FIELDS for fcc-499q and
fcc-499a-discontinuance. Without these, intake validation was
completely skipped — invalid data accepted silently.
High #4 — FCC Carrier Reg: Don't mark D.C. Agent complete
prematurely. Was calling _update_step() right after creating the
admin todo. Now waits for admin to confirm NW order is placed.
High #5 — Compliance: Add fcc-499q and fcc-499a-discontinuance to
REQUIRES_ENTITY_FRN set. Both require FRN for USAC filing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When any Playwright submission fails (selector not found, timeout, etc.):
1. Full-page screenshot captured and uploaded to MinIO
2. Telegram alert sent immediately with error details + screenshot link
3. Email alert to ops with same info
4. Admin todo includes screenshot MinIO path for debugging
5. Client order stays pending for manual completion
Proactive selector health check (daily 7am CT cron):
- Navigates to each portal (FCC RMD, USAC E-File, FCC CPNI/ECFS)
- Verifies all critical selectors are still present in the DOM
- If selectors are missing (UI changed): alerts via Telegram + email
BEFORE any real client order fails
- Reports which service slugs are affected
Integrated into:
- RMD filing handler (fccprod.servicenowservices.com)
- Form 499-A handler (forms.universalservice.org)
- Form 499-Q handler (already had error handling)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
job_server.py expects process() to return a list of file paths for
MinIO upload. The 499-Q and discontinuance handlers were returning
dicts like {'status':'admin_review'} which caused the job_server to
iterate dict keys as file paths -> 'File not found: status'.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When AUTO_FILING_ENABLED is explicitly set as an env var, skip the
ERPNext API call entirely. The ERPNext client hangs indefinitely
when the host is unreachable (dev workers can't reach prod ERPNext),
blocking all compliance handlers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
499-Q Handler:
- Auto-filing toggle integration (same as 499-A)
- Playwright USAC E-File submission for quarterly form
- Revenue field filling (4 categories)
- Confirmation number capture + PDF save
- Client receives "data received" email immediately, then
"filed successfully" email with confirmation number after submission
- Falls back to admin todo if Playwright/session unavailable
Discontinuance Handler:
- Auto-emails deactivation letter to USAC (Form499@usac.org)
with DOCX attachment + entity summary in body
- CC to admin email for records
- Dev mode: redirects USAC email to admin instead
- Client confirmation email with process timeline
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Formal letter addressed to USAC Contributor Operations requesting
deactivation of a 499 Filer ID. Covers:
- Entity identification (name, Filer ID, FRN, EIN)
- Reason for deactivation + termination date
- Final 499-A status (zero-revenue included OR filed separately)
- Successor entity info (if applicable)
- Outstanding balance acknowledgment
- Related filings confirmation (RMD, CPNI, BDC)
- Officer signature block
- Entity summary box
Handler updated to:
- Generate the letter via document_gen template
- Upload DOCX to MinIO (compliance/{order_number}/)
- Reference the letter in admin todo
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Both scrapers held a cursor/transaction open while doing slow HTTP
requests to FCC ServiceNow and company websites, causing
"idle in transaction" for 10+ minutes and triggering the
PostgresSlowQueries alert.
Fix: fetch all row IDs upfront, commit the read transaction
immediately, then process each row with its own short
UPDATE+COMMIT cycle. No long-lived transactions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When user selects "cancel registration" in the compliance checker:
- Option 1: "499-A Discontinuance (incl. zero-revenue filing)" $299
For carriers with no revenue — includes final zero-revenue 499-A
+ deactivation letter + CORES update
- Option 2: "499-A Filing + Discontinuance" $798 ($499+$299)
For carriers with actual revenue — full 499-A filed separately
+ deactivation process
Standalone discontinuance ($299) is for carriers already current
on filings who just want to close out.
Handler detects whether zero-revenue filing is included vs
handled by a separate full 499-A order.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Per 2026 FCC Form 499-A Instructions:
- Final 499-A CAN have actual revenue (not required to be zero)
— reports revenue for the period the company was in service
- Deactivation is a SEPARATE step: submit letter to USAC with
termination date and successor entity info, within 30 days
- Line 603: check TRS/LNP/NANPA exemption boxes, write
"Not in business as of [date]"
- USAC processing takes 60-90 days
- CORES must be updated to reflect inactive status
Handler now creates admin todo with 4-step process:
1. File final 499-A with actual/zero revenue
2. Submit USAC deactivation letter (Form499@usac.org)
3. Update CORES registration
4. Confirm CPNI/RMD/BDC discontinued
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>