Includes: API (Express/TypeScript), Astro site, Python workers, document generators, FCC compliance tools, Canada CRTC formation, Ansible infrastructure, and deployment scripts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
16 KiB
Performance West — Build Plan
Last updated: 2026-04-05
Status: Pre-launch. CRTC pipeline ~95% built (14 steps, BITS/CCTS/compliance calendar implemented). DocServer provisioned. US formation plumbing exists but no state has been filed end-to-end. Payment flow is wired but gateways not yet configured in ERPNext UI.
See also:
docs/multi-province-plan.md— Plan to extend CRTC to multi-province + standalone Canadian formation + universal compliance calendar. 28-36 hours, 16 sub-phases. See also:docs/competitive-pricing.md— Competitor pricing analysis: US formation, Canadian formation, registered agents. Updated 2026-04-05.
How to Read This Plan
Tracks are independent workstreams. Within each track, items are ordered by dependency — complete them top-to-bottom. Across tracks, work in parallel where possible.
Labels:
[BLOCKER]— nothing ships until this is done[CRTC]— affects the $3,899 flagship product[FORMATION]— affects US LLC/Corp product[INFRA]— server/ops[PLUMBING]— backend wiring, no user-facing change
Track 1 — CRTC Pipeline (Flagship Revenue)
The Canada CRTC Carrier Package is the highest-value product. Get one real order through end-to-end before doing anything else.
1.1 ERPNext Payment Config [BLOCKER][CRTC]
ERPNext gateways exist as code but are not configured in the UI — no payment can complete.
- Configure Crypto Payment Settings: URL =
https://pay.performancewest.net, SHKeeper API key - Create Payment Gateway Account
Crypto-Cryptoin ERPNext - Configure Adyen Settings (5 instances: Card, ACH, Klarna, CashApp, AmazonPay) — pending Adyen account approval
- Create 5 Adyen Payment Gateway Accounts
- Configure ERPNext SMTP for outbound email (invoices, notifications)
- Test: place a $1 test order, confirm Payment Request is created, confirm redirect to checkout, confirm webhook fires back to Express API
1.2 COLIN Selector Verification [BLOCKER][CRTC]
The BC incorporation adapter (frappe_ca_registry/provinces/bc/adapter.py) has 13 steps mapped but selectors are unverified against the live portal. No real BC incorporation can complete until this is tested.
- Place a real test incorporation order against COLIN (corporateonline.gov.bc.ca)
- Verify/fix selectors for: Step 6 Director, Step 7 Office Addresses, Step 8 Share Structure, Step 9 Notification, Step 12 Payment
- Verify payment step: COLIN accepts Visa/MC — use
relay-filing-cardviaget_filing_cardAPI - Implement multiple-directors loop (currently only first director is inserted)
- Confirm that BC sends certificate email to
filings@performancewest.net - End-to-end smoke test:
frappe_ca_registrycreates Filing Request → COLIN automation completes → certificate arrives
1.3 CRTC Pipeline Remaining Stubs [CRTC]
- Anytime Mailbox automation hardening — provider has no API, but Playwright flow now exists. Validate selectors against live UI and stabilize OTP retrieval via Carbonio IMAP, then keep admin handoff as fallback.
- CCTS registration — Step 11 is a stub. Research CCTS online registration form, implement Playwright or keep as admin ToDo with instructions.
- eSign workflow for CRTC letter — Step 6 generates the DOCX letter but customer signature is not collected. Use ERPNext built-in eSign (drawing pad). Wire: generate letter → send for eSign → on signed → continue pipeline.
- CRTC letter email submission — After eSign, email the signed letter to CRTC from the customer's provisioned
.caaddress (regulatory@{domain}.ca). Requires IMAP send via HestiaCP provisioned mailbox. - BITS affidavit — BITS requires a notarized affidavit confirming the company is a US carrier (or Canadian equivalent). Provider: NotaryLive ($59/mo platform + $23/session). Implement: generate affidavit DOCX → send NotaryLive session invite → on completion → attach to binder.
- Order confirmation email — After payment, send customer a confirmation email with order summary, expected timeline, and next steps checklist. Currently nothing is sent at payment time.
- Branded HTML email templates — 15 ERPNext Email Notifications are plain text. Design and import HTML templates (header logo, PW brand colors, footer with unsubscribe).
1.4 Customer Portal Auth [CRTC]
Portal pages (/portal/domain-search, /portal/manage-services) exist but have no authentication. Any URL visitor can access any order.
- Implement portal authentication via ERPNext portal login (ERPNext has a built-in portal user system)
- Generate a signed JWT or ERPNext portal token and embed in the email links sent to customers
- Add auth middleware to all
/portal/*API routes — validate token, scope to customer's own orders only - Add session expiry (24h) and re-send link flow
1.5 End-to-End CRTC Test [CRTC]
- Place a real CRTC order (numbered company, test customer)
- Walk through all 12 pipeline steps
- Confirm: DID provisioned, COLIN automation runs, domain registered, CRTC letter generated + eSigned, binder compiled, MinIO upload, customer emails received
- Document any failures and fix before first real customer order
Track 2 — US Formation (Second Revenue Stream)
2.1 Wyoming End-to-End [FORMATION]
WY is the highest-priority state — selectors verified on name search, no CAPTCHA, cheapest filing fee.
- Implement WY filing automation: walk the WYO SOS filing wizard step-by-step with Playwright, map all form field selectors
- Wire payment step: WY SOS accepts credit card — use
relay-filing-card - Test: place a real WY LLC order, confirm name search works, confirm filing completes, confirm confirmation number saved to DB
- Wire formation worker to create ERPNext Formation Order + Sales Invoice on order receipt
- Wire formation worker to send order confirmation email after payment
2.2 Colorado End-to-End [FORMATION]
CO name search is already working (Socrata API). Need filing automation.
- Research CO SOS filing wizard (sos.state.co.us), map selectors
- Implement CO LLC filing automation
- Test end-to-end
2.3 Server-Side Fee Validation [FORMATION][PLUMBING]
Currently the API trusts client-submitted state_fee_cents. This is a billing vulnerability.
- Add server-side lookup: on order receipt, look up
state_fee_centsfromstate_filing_feesDB table usingstatecode - Reject any order where client-submitted fee does not match DB value
- Audit and fix the 12+ known fee discrepancies between the frontend hardcoded array and DB (identified last session)
2.4 Operating Agreement + EIN [FORMATION]
- Test operating agreement DOCX generation end-to-end (template → DocxBuilder → PDF → MinIO)
- Test EIN obtainment worker (IRS Playwright) on a real WY entity after filing
- Confirm both documents are attached to the ERPNext Formation Order and emailed to customer
2.5 DocServer (Windows VM) [FORMATION][INFRA]
LibreOffice fallback produces lower-quality PDFs. Office 2021 on Windows is required for production-quality DOCX→PDF conversion.
- Provision Windows Server 2022 VM in Proxmox (2 vCPU, 4 GB RAM, 40 GB SSD)
- Install Microsoft Office 2021
- Deploy DocServer Flask app on port 5050
- Configure
DOCSERVER_URLenv var to point workers at Windows VM - Verify: workers use DocServer when available, fall back to LibreOffice when not
2.6 Remaining State Adapters [FORMATION]
Priority order based on formation volume. Each requires: portal inspection, selector extraction, Playwright implementation, payment wiring.
- Delaware (DE) — CAPTCHA. Integrate 2captcha or AntiCaptcha solving service first.
- Florida (FL) — High demand. Playwright needed, no CAPTCHA expected.
- Texas (TX) — SOSDirect account needed for search. Get account first.
- Nevada (NV) — WAF. Use stealth Playwright (playwright-extra + puppeteer-stealth).
- Utah (UT) — Name search works without login. Filing needs UtahID OAuth.
- New Mexico, Ohio, Montana — Untested, research portals.
- Remaining 37 states — Batch: inspect portals, extract selectors, implement in priority order.
Track 3 — Infrastructure & Ops
3.1 Production Deployment [INFRA][BLOCKER]
The rsync to production timed out. Get the current codebase deployed.
- Fix rsync: run with
--timeout=30and--compress, or use a staged approach (tar | ssh) - On server:
docker compose build && docker compose up -d - Update ERPNext Docker image: rebuild
performancewest-erpnext:latestwith latestfrappe_ca_registry+performancewest_erpnextchanges - Run any pending DB migrations on production
3.2 Environment Variables [INFRA]
Several env vars are not yet set in production .env.
PORKBUN_API_KEY/PORKBUN_SECRET_KEYFLOWROUTE_ACCESS_KEY/FLOWROUTE_SECRET_KEYHESTIA_HOST/HESTIA_USER/HESTIA_PASSWORDSHKEEPER_API_KEYADYEN_API_KEY/ADYEN_MERCHANT_ACCOUNT/ADYEN_CLIENT_KEY(when account approved)DOCSERVER_URL(when Windows VM is provisioned)CUSTOMER_JWT_SECRET(for portal auth)
3.3 Monitoring & Alerts [INFRA]
- Set up UptimeRobot (free) to monitor: performancewest.net, api.performancewest.net, crm.performancewest.net, pay.performancewest.net
- Configure alert email to
ops@performancewest.net - Set up weekly automated DB backup to MinIO (pg_dump → minio/backups/)
- Verify ERPNext daily backup is configured and uploading to MinIO
Track 4 — Payment & Billing Completion
4.1 Bundle / Compliance Checkout [PLUMBING]
The Express API returns null for bundle and compliance service checkout. These are broken.
- Implement bundle checkout in
api/src/routes/checkout.ts: look up bundle fromservice_bundlestable, create Sales Order + Invoice with correct line items and 20% bundle discount - Implement compliance service checkout (CCPA audit, FLSA audit, etc.): create Sales Invoice with correct item and turnaround date
- Test both flows end-to-end through payment
4.2 Subscription / Renewal Billing [PLUMBING]
Annual renewals (RA $99/yr ($49 WY), Annual Report $99/yr, CRTC Maintenance $349/yr) exist as ERPNext Subscription Plans but the renewal worker is not wired to trigger them.
- Wire
renewal_handler.py: on subscription due date (from Compliance Calendar), create ERPNext Sales Invoice + Payment Request, send renewal email with payment link - Test: manually trigger a renewal for a test customer, confirm invoice created, confirm email sent, confirm payment marks subscription renewed
4.3 Refund Flow [PLUMBING]
- Verify ERPNext Credit Note flow works end-to-end
- Test: issue a partial refund on a test invoice, confirm Adyen processes the refund, confirm customer email is sent
- Document refund policy in customer-facing portal
Track 5 — Docs Update
All 15 docs have stale content. These need to be rewritten to match current state before bringing on any contractors or making architectural decisions.
Critical (do first):
docs/architecture.md— Replaced Mautic with Listmonk. Added DocServer, workers, portal. Updated container count to 15.docs/go-live-todo.md— Marked completed items. Added multi-province priority 11. Updated pricing.docs/formation-system.md— Updated BC section with BITS/CCTS/GCKey/compliance. Updated DocServer.docs/crm.md— Replaced Mautic Integration → Listmonk. Added CRTC campaign.
High priority:
docs/product-facts.md— Added Canada annual maintenance ($349), consulting ($75/hr), Canadian formation (C$449), maintenance bundles ($179/yr). Updated CRTC pipeline to 14 steps.docs/billing.md— Added renewal billing, compliance calendar billing, maintenance bundles, Canadian formation pricing.docs/infrastructure.md— Replaced Mautic/MySQL with Listmonk. Updated container count to 15. Added portal nginx config.
Medium priority:
docs/marketing.md— Add FCC RMD as primary lead gen channel. Add Listmonk drip campaign details. Add 3 campaign descriptions.docs/state-automation-status.md— Updated BC section with all new capabilities + GCKey automation table.docs/document-generation.md— Update DocServer section (MinIO transport, not HTTP). Add template list.
Track 6 — frappe_registry Migration (Future)
This is a significant refactor — ~24 hours of work. Do not start until CRTC pipeline is working end-to-end and at least WY formation is live.
- Rename
frappe_ca_registry→frappe_registry - Generalize
CA Filing RequestDocType toRegistry Filing Request(55 jurisdictions) - Add
Registry SettingsDocType: NWRA defaults, per-state RA override, CA mailbox config - Move 51 US state adapters from
scripts/formation/states/into Frappe app - Add extra-provincial registration support (10 Canadian provinces)
- Add foreign state qualification support (US foreign entity)
- Define
BaseAdapterinterface with auto-discovery by jurisdiction code - Build fee scraper framework:
base_scraper.py— abstract scraper class with rate limiting, retry, user-agent rotationpdf_scraper.py— Tesseract OCR for scanned fee schedule PDFs, pdfplumber for text PDFsfee_change_detector.py— compares scraped values against DB, generates diff report- Admin email alert when any fee changes (does NOT auto-update — human review required)
- Monthly cron job in workers container (
0 6 1 * *— 1st of each month, 6am) - Store scraped results in
state_fee_scrape_historytable with timestamp + source URL + old/new values
- Implement US state fee scrapers (51 jurisdictions):
- Tier 1 (top 10 by formation volume): WY, DE, FL, TX, NV, CA, CO, NY, GA, IL
- Tier 2 (remaining 41 states + DC)
- Handle: annual report fees, franchise taxes, business license fees, privilege taxes, personal property returns
- Reference:
docs/state-annual-fees-complete.mdfor current verified values + source URLs
- Implement Canadian province fee scrapers (10 provinces):
- BC, AB, ON, QC, MB, SK, NS, NB, PE, NL
- Scrape in CAD, convert to USD via
fx.tsBank of Canada rate + 10% buffer
- Fix fee data integrity: DB as single source of truth, frontend fetches from API, server-side validation (see 2.3)
Launch Readiness Checklist
Before accepting the first paying customer:
- ERPNext payment gateways configured (Track 1.1)
- CRTC end-to-end test passes (Track 1.5)
- Portal authentication implemented (Track 1.4)
- Order confirmation email sends after payment (Track 1.3)
- Production deployed with current codebase (Track 3.1)
- All env vars set in production (Track 3.2)
- UptimeRobot monitoring configured (Track 3.3)
Formation orders can follow ~2 weeks after CRTC is live (WY first).
Open Questions / Decisions Needed
| Question | Context | Deadline |
|---|---|---|
| Adyen account approval status? | Without Adyen, card/ACH payments are blocked. Only crypto works. | Before first customer |
| NotaryLive account — go or no-go? | $59/mo + $23/session for BITS affidavit notarization. Alternative: partner with a Canadian notary. | Before first CRTC delivery |
| Anytime Mailbox credential handoff policy? | Provider confirmed no API; Playwright signup uses shared inbox OTP. Decide whether to bootstrap with filings@performancewest.net then transfer to client, or require client email from the start. |
Before first customer |
| Portal auth strategy? | ERPNext portal login vs. signed JWT in email link. Signed JWT is simpler, no password needed. | Before first customer uses portal |
| Canadian accountant? | 3 hours free accounting support is promised in the CRTC package. Need to onboard a freelance Canadian accountant. | Before first delivery |