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>
253 lines
16 KiB
Markdown
253 lines
16 KiB
Markdown
# 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`](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`](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-Crypto` in 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-card` via `get_filing_card` API
|
|
- [ ] 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_registry` creates 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 `.ca` address (`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_cents` from `state_filing_fees` DB table using `state` code
|
|
- [ ] 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_URL` env 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=30` and `--compress`, or use a staged approach (`tar | ssh`)
|
|
- [ ] On server: `docker compose build && docker compose up -d`
|
|
- [ ] Update ERPNext Docker image: rebuild `performancewest-erpnext:latest` with latest `frappe_ca_registry` + `performancewest_erpnext` changes
|
|
- [ ] 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_KEY`
|
|
- [ ] `FLOWROUTE_ACCESS_KEY` / `FLOWROUTE_SECRET_KEY`
|
|
- [ ] `HESTIA_HOST` / `HESTIA_USER` / `HESTIA_PASSWORD`
|
|
- [ ] `SHKEEPER_API_KEY`
|
|
- [ ] `ADYEN_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 from `service_bundles` table, 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):**
|
|
- [x] `docs/architecture.md` — Replaced Mautic with Listmonk. Added DocServer, workers, portal. Updated container count to 15.
|
|
- [x] `docs/go-live-todo.md` — Marked completed items. Added multi-province priority 11. Updated pricing.
|
|
- [x] `docs/formation-system.md` — Updated BC section with BITS/CCTS/GCKey/compliance. Updated DocServer.
|
|
- [x] `docs/crm.md` — Replaced Mautic Integration → Listmonk. Added CRTC campaign.
|
|
|
|
**High priority:**
|
|
- [x] `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.
|
|
- [x] `docs/billing.md` — Added renewal billing, compliance calendar billing, maintenance bundles, Canadian formation pricing.
|
|
- [x] `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.
|
|
- [x] `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 Request` DocType to `Registry Filing Request` (55 jurisdictions)
|
|
- [ ] Add `Registry Settings` DocType: 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 `BaseAdapter` interface with auto-discovery by jurisdiction code
|
|
- [ ] Build fee scraper framework:
|
|
- [ ] `base_scraper.py` — abstract scraper class with rate limiting, retry, user-agent rotation
|
|
- [ ] `pdf_scraper.py` — Tesseract OCR for scanned fee schedule PDFs, pdfplumber for text PDFs
|
|
- [ ] `fee_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_history` table 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.md` for 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.ts` Bank 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 |
|