new-site/docs/multi-province-plan.md
justin f8cd37ac8c Initial commit — Performance West telecom compliance platform
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>
2026-04-27 06:54:22 -05:00

34 KiB

Multi-Province, Canadian Formation & Universal Compliance — Implementation Plan

Created: 2026-04-05 Status: Planning — dev-only implementation, not yet in production Triggers:

  • Ontario removed Canadian resident director requirement (Bill 213, July 2021)
  • Formation page frontend already supports 10 Canadian provinces (backend does not)
  • Compliance calendar system built for CRTC but not used by other order types

Goal

Three interconnected features:

  1. Multi-province CRTC — Extend the $3,899 CRTC Carrier Package from BC-only to multi-province. Ontario first; architecture supports any Canadian province.
  2. Standalone Canadian formation — Offer Canadian province incorporation (C$449
    • gov fees) on the existing formation page WITHOUT telecom registration. Separate flow from CRTC.
  3. Universal compliance calendar — Create compliance entries for ALL orders (US formations, Canadian formations, CRTC carriers). Formation maintenance bundle at $199/yr.

Service fee stays at $3,899 USD for CRTC regardless of province. US formation: $179 Basic / $399 Complete. Canadian formation: C$449 + gov fees (single tier). Government fees passed through at cost for all products.

Dev-only gate: Ontario and Canadian formation options visible only in dev (import.meta.env.DEV / NODE_ENV !== 'production'). Production continues unchanged until everything is tested end-to-end.


Research Findings

Ontario Director Residency — Confirmed Removed

Bill 213 (Better for People, Smarter for Business Act, 2020) removed OBCA s.118(3) requiring 25% of directors to be Canadian residents. Proclaimed in force July 5, 2021. Both BC and Ontario now have no Canadian residency requirement — the key enabler for our foreign (non-Canadian) clients.

Ontario vs BC Comparison

Factor BC Ontario
Director residency None required None required
Incorporation fee ~C$350 ~C$360
Annual return/report C$42.71/yr C$25/yr
Portal BC Corporate Online (anonymous) Ontario Business Registry (requires login)
Entity format "1234567 B.C. Ltd." "1234567 Ontario Inc."
Legal endings Ltd., Inc., Corp., Limited, etc. Inc., Corp., Ltd., Ltee (+ French)
Sales tax GST 5% + PST 7% = 12% HST 13% (combined)
Workers comp WorkSafeBC WSIB
DID area codes 604/778/236/250 416/647/437/905/289/365/519/613
AMB locations 4 (Vancouver) 30+ (Toronto, Mississauga, Ottawa, etc.)
AMB pricing ~C$13-20/mo from C$7.99/mo
Corporate tax (small biz) 11% combined 12.2% combined
Language English only English or French

Province-Agnostic Components (Zero Changes Needed)

These are federal or infrastructure-level and work identically for any province:

  • CRTC domestic carrier registration (letter to Secretary General)
  • BITS international registration (Form 503 + affidavit)
  • CCTS membership registration
  • GCKey provisioning (for CRTC filings)
  • .ca domain registration via Porkbun (CIRA CPR satisfied by any Canadian corp)
  • HestiaCP email/hosting provisioning
  • eSign portal flow
  • MinIO document storage
  • Corporate binder compilation (pikepdf + reportlab)
  • Payment processing (Stripe/PayPal/SHKeeper)

Key Difference: OBR Requires Login

BC Corporate Online is anonymous — no account needed. The Ontario Business Registry requires an Ontario Business Account (OBA) login. Plan: create a Performance West "house account" on the OBR and test whether it's suitable for filing multiple incorporations. If not, fall back to admin ToDo with manual incorporation.

Formation Page — Existing Canada Support

The formation order page (site/src/pages/order/formation.astro) already has:

  • Country selector (US / CA)
  • CA_PROVINCES array with all 10 provinces + fees + live FX conversion
  • Entity type swap: LLC->Ltd., Corporation->Inc., S-Corp->Corp.
  • Province dropdown with dual CAD/USD pricing
  • CRTC callout linking to the CRTC order page (separate flows)

What's missing: The backend (formations.ts route) only validates US entity types and the formation_orders table has entity_type CHECK (llc, corporation, s_corp). Canadian types (ltd, inc, corp) are rejected. No Canadian province adapter is dispatched.

Codebase Coupling (CRTC Pipeline)

~100+ hardcoded "BC" references across:

  • Order form (site/src/pages/order/canada-crtc.astro) — ~40 references
  • Pipeline (scripts/workers/services/canada_crtc.py) — ~50 references
  • API route (api/src/routes/canada-crtc.ts) — ~10 references
  • AMB scraper, Flowroute DID, compliance calendar

No province column in canada_crtc_orders table. Pipeline hardcodes BCPortal import.

Good abstraction points exist: StatePortal base class, amb_locations.province column, own_ca_province DB column, FormationOrder.state_code parameter.


Architecture

Product Matrix

Product Price Pipeline Compliance Entries Maintenance
US Formation Basic $179 + state fees US state adapter 1-3 (annual report, franchise tax) $179/yr bundle
US Formation Complete $399 + state fees US state adapter 2-4 (+ RA renewal) $179/yr bundle
CA Formation C$449 + gov fees + AMB CanadianIncorporationHandler 7-8 (annual return + tax + AMB) $179/yr bundle
CRTC Carrier Package $3,899 + gov fees CanadaCRTCHandler (composes CanadianIncorporationHandler) 15-17 (+ telecom obligations) $349/yr

Pipeline Decomposition

The CRTC pipeline is currently monolithic. We decompose it into shared incorporation steps and telecom-only steps.

Shared steps (used by BOTH formation-only AND CRTC):

Step Action Formation Basic Formation Complete CRTC
AMB mailbox setup Registered office No Yes Yes
Name reservation Registry filing If named If named If named
Incorporation COLIN / OBR Yes Yes Yes
Trade name registration Registry filing If requested If requested If requested
CRA Business Number BN from CRA Add-on ($49) Add-on ($49) No (not needed)
Organizational minutes Document gen No Yes Yes
Corporate binder PDF compilation Digital only Yes Yes
Delivery email Send docs Yes Yes Yes
Compliance calendar Create entries Yes (corporate) Yes (corporate + AMB) Yes (corporate + telecom)

CRTC-only steps (NOT in formation pipeline):

Step Action
DID provisioning Canadian phone number via Flowroute
.ca domain + HestiaCP Domain, email, 14 mailboxes, hosting
CRTC letter generation DOCX template -> MinIO -> DocServer PDF
eSign Client signs CRTC letter in portal
CRTC submission Mail letter to Secretary General
BITS registration GCKey provisioning + BITS filing
CCTS membership Registration + client obligations email
GCKey provisioning Government credential for CRTC filings
Telecom compliance entries CRTC, BITS, CCTS, ATS surveys, DID/domain/mailbox renewals

ProvinceConfig Protocol

class ProvinceConfig(TypedDict):
    # Identity
    code: str                      # "BC", "ON", "AB", "QC", ...
    name: str                      # "British Columbia", "Ontario"
    abbreviation: str              # "B.C.", "Ont."

    # Corporate law
    act_name: str                  # "BC Business Corporations Act", "OBCA"
    legal_endings: list[str]       # Province-specific corporate name suffixes
    numbered_entity_template: str  # "{number} B.C. Ltd.", "{number} Ontario Inc."

    # Portal
    portal_name: str               # "BC Corporate Online", "Ontario Business Registry"
    portal_url: str
    requires_login: bool           # False (BC), True (ON)
    selectors: dict                # Playwright CSS selectors for portal

    # Fees (CAD cents)
    incorporation_fee_cad: int     # 35000 (BC), 36000 (ON)
    annual_return_fee_cad: int     # 4271 (BC), 2500 (ON)
    annual_return_name: str        # "Annual Report" (BC), "Annual Return" (ON)
    name_reservation_fee_cad: int

    # Tax
    sales_tax: dict                # {type: "GST+PST", gst: 5, pst: 7} or {type: "HST", rate: 13}
    workers_comp_name: str         # "WorkSafeBC", "WSIB"

    # Infrastructure
    area_codes: list[str]          # DID area codes for Flowroute
    default_city: str              # "Vancouver", "Toronto"
    timezone: str                  # "America/Vancouver", "America/Toronto"
    amb_scrape_slug: str           # "british-columbia", "ontario"
    registered_office_addresses: list

    # Compliance
    corporate_obligations: list    # Province-specific tax/filing requirements
    supports_formation_only: bool  # Whether we offer standalone formation
    cra_bn_automatable: bool       # Whether BN registration can be automated

    # Templates
    articles_template: str         # Path to province-specific Articles template
    minutes_template: str          # Path to organizational minutes template

Universal Compliance Calendar

A shared module called by ALL pipelines:

# scripts/formation/compliance.py

def create_compliance_entries(
    order_type: str,        # "crtc" | "ca_formation" | "us_formation"
    jurisdiction: str,      # "BC", "ON", "WY", "DE", etc.
    country: str,           # "CA" | "US"
    order_reference: str,   # Sales Order or order number
    entity_name: str,
    incorporation_date: date,
    add_ons: dict,          # {ra: bool, amb: bool, domain: bool, did: bool, ein: bool}
) -> list[dict]:
    """Create compliance calendar entries based on order type and jurisdiction."""

The function reads obligations from province/state config and filters by order_type. The renewal_worker.py already handles the lifecycle regardless of origin.

File Structure

scripts/formation/
  province_config.py          # ProvinceConfig TypedDict + get_province(code)
  compliance.py               # NEW: Universal create_compliance_entries()
  canadian_incorporation.py   # NEW: CanadianIncorporationHandler (shared steps)
  base.py                     # StatePortal base class (existing)
  states/
    __init__.py               # State registry (add CA provinces)
    bc/config.py              # BC ProvinceConfig (refactored)
    bc/adapter.py             # BCPortal(StatePortal) (existing)
    on/__init__.py            # NEW
    on/config.py              # NEW: Ontario ProvinceConfig
    on/adapter.py             # NEW: ONPortal(StatePortal)
    wy/config.py              # WY config (add compliance obligations)
    ... (50 more US states)

scripts/workers/
  services/
    canada_crtc.py            # MODIFIED: Composes with CanadianIncorporationHandler
    cra_bn.py                 # NEW: CRA Business Number registration
    flowroute.py              # MODIFIED: provision_canadian_did(province)
  renewal_worker.py           # Unchanged (already handles any compliance entry)
  amb_location_scraper.py     # MODIFIED: Multi-province scraping

Pricing

CRTC Carrier Package (unchanged)

Item Price
CRTC Telecom Registration (one-time) $3,899 USD
Annual Maintenance & Compliance $349/yr
Consulting $75/hr
Government fees Passed through at cost (province-specific)

Canadian Formation (new)

Item Price Notes
Canadian Formation C$449 + gov fees Incorporation + org minutes + binder + compliance calendar. AMB mailbox billed separately (annual, ~C$96-240/yr depending on location).
Government fees BC ~C$350, ON ~C$360 Passed through (BoC rate + 10% buffer)
Add-on: CRA BN $49 Business Number registration with CRA
Add-on: Named company +gov fee Name reservation (BC: C$30, ON: varies)
Free DID Included With formation + RA renewal (stub — not yet active)

Maintenance Bundles (new)

Bundle Price Includes
US Formation Maintenance $179/yr Annual report filing ($99 value) + RA renewal ($99 value)
CA Formation Maintenance $179/yr Annual return filing ($99 value) + AMB/RA renewal ($99 value)
CRTC Maintenance (existing) $349/yr All of CA maintenance + CRTC + CCTS + domain/email + DID

ERPNext Items Needed

Item Code Name Rate (USD) Used By
CRTC-MAINT-ANNUAL CRTC Annual Maintenance $349/yr CRTC orders
FORMATION-MAINT-US US Formation Maintenance Bundle $179/yr US formation (Complete)
FORMATION-MAINT-CA CA Formation Maintenance Bundle $179/yr CA formation
RA-RENEWAL Registered Agent Renewal $99/yr ($49 WY) All formations (if RA)
FREE-DID Free DID (with formation + RA) $0 Stub — not yet active
ANNUAL-REPORT Annual Report/Return Filing $99/yr All formations
CRA-BN CRA Business Number Registration $49 CA formation add-on
MAILBOX-RENEWAL Mailbox Renewal (AMB) $199/yr CRTC + CA Complete
DOMAIN-RENEWAL-CA .ca Domain + Hosting Renewal $25/yr CRTC only

Phases

Phase 0: OBR + CRA Playwright Recon

Model: Opus 4.6 — Complex unknown-portal reconnaissance requiring judgment.

0a. Ontario Business Registry recon:

  1. Navigate to business.ontario.ca, map account creation flow
  2. Walk through incorporation wizard — record form fields, selectors, inputs
  3. Document: login method, MFA, CAPTCHA, bot detection
  4. Record: payment step (credit card selectors)
  5. Test if one house account can file multiple incorporations
  6. Record: name search flow (part of wizard or separate?)
  7. Output: selector map + screenshots saved to MinIO

0b. CRA Business Number recon:

  1. Navigate to CRA Business Registration Online
  2. Map the BN registration form fields
  3. Document: does it require an existing corp number? Identity verification?
  4. Can we register using our house account or does the client need to do it?
  5. Determine if automatable or admin ToDo

Files:

  • scripts/recon_obr.py — NEW: OBR Playwright recon script
  • scripts/recon_cra_bn.py — NEW: CRA BN recon script

Effort: 2-2.5 hours


Phase 1: ProvinceConfig + Compliance Module Design

Model: Opus 4.6 — Architecture with future-proofing for any province and all order types.

Files:

  • scripts/formation/province_config.py — NEW: ProvinceConfig TypedDict + get_province(code) registry
  • scripts/formation/compliance.py — NEW: create_compliance_entries() universal function
  • scripts/formation/states/bc/config.py — MODIFY: conform to ProvinceConfig
  • scripts/formation/states/__init__.py — MODIFY: register CA provinces, add compliance fields to US states

The compliance module design must handle:

  • CRTC orders: 15-17 entries (telecom + corporate + renewals)
  • CA formation: 6-8 entries (corporate obligations only)
  • US formation: 1-4 entries (annual report + RA + franchise tax)
  • Filtering by order type and purchased add-ons
  • Province/state-specific deadlines, fees, and filing names

Effort: 3-4 hours


Phase 2: Database Migrations

Model: Sonnet 4.6 — Mechanical SQL.

Files:

  • api/src/migrations/036_multi_province.sql — NEW
-- === CRTC table changes ===
ALTER TABLE canada_crtc_orders ADD COLUMN province TEXT NOT NULL DEFAULT 'BC';
ALTER TABLE canada_crtc_orders RENAME COLUMN bc_incorporation_number TO incorporation_number;
CREATE INDEX idx_crtc_orders_province ON canada_crtc_orders(province);

-- === Formation table changes ===
ALTER TABLE formation_orders ADD COLUMN country CHAR(2) NOT NULL DEFAULT 'US';
ALTER TABLE formation_orders DROP CONSTRAINT formation_orders_entity_type_check;
ALTER TABLE formation_orders ADD CONSTRAINT formation_orders_entity_type_check
  CHECK (entity_type IN ('llc', 'corporation', 's_corp', 'ltd', 'inc', 'corp'));
CREATE INDEX idx_formation_orders_country ON formation_orders(country);

Effort: 45 minutes


Phase 3: Ontario Adapter + Infrastructure + Shared Handlers

3a. Ontario configSonnet 4.6

scripts/formation/states/on/config.py — Full Ontario ProvinceConfig:

  • OBR URLs, fees (C$360 incorp, C$25 annual return)
  • Legal endings: Inc., Corp., Ltd., Ltee, Cie (+ French equivalents)
  • Area codes: 416/647/437/905/289/365/519/613/705
  • HST 13%, WSIB, Toronto default
  • Selectors from Phase 0 recon
  • Corporate obligations (Ontario Annual Return, T2, GST/HST, WSIB — no PST)

3b. Ontario adapterSonnet 4.6

scripts/formation/states/on/adapter.pyONPortal(StatePortal):

  • search_name(): OBR free search
  • file_incorporation(): initially admin ToDo, OBR automation stubbed
  • file_llc() / file_corporation(): route to file_incorporation() (Canadian entity types)

3c. AMB scraper extensionSonnet 4.6

scripts/workers/amb_location_scraper.py:

  • Parameterize province in scrape function
  • Add Ontario scraping (Toronto, Mississauga, Ottawa, Hamilton, etc.)
  • Run for both BC + ON in daily cron

3d. Flowroute DID generalizationSonnet 4.6

scripts/workers/services/flowroute.py:

  • Rename provision_bc_did() -> provision_canadian_did(province)
  • Area code mapping: BC=[604,778,236,250], ON=[416,647,437,905,289,365]

3e. CanadianIncorporationHandlerOpus 4.6

scripts/formation/canadian_incorporation.py — NEW:

  • Shared incorporation pipeline used by BOTH formation-only AND CRTC
  • Steps: AMB setup (if Complete), name reservation (if named), incorporation, trade name (if requested), CRA BN (if add-on), binder compilation, delivery email, compliance calendar creation
  • CanadaCRTCHandler composes with this (calls it for incorporation, then continues with telecom steps)
  • Formation-only orders dispatch here directly from the job server

3f. CRA BN registrationSonnet 4.6

scripts/workers/services/cra_bn.py — NEW:

  • Initially stubbed as admin ToDo
  • CRA Business Number registration automation added after Phase 0b recon

3g. Universal compliance creatorOpus 4.6

scripts/formation/compliance.py — NEW:

  • create_compliance_entries() function
  • Reads obligations from province/state config
  • Filters by order_type and purchased add-ons
  • Creates entries in ERPNext Compliance Calendar DocType
  • Called by: CanadianIncorporationHandler, CanadaCRTCHandler, US formation job handler

Effort: 7-8 hours total (3a-d: 3-4 hrs, 3e: 2-3 hrs, 3f: 30 min, 3g: 1-2 hrs)


Phase 4: Service Page Province Comparison Table + FAQ

Model: Sonnet 4.6 (table HTML) + Opus 4.6 (FAQ)

4a. Province comparison table (Sonnet) — Add to CRTC service page between the corporate tax table (line ~1205) and M&A section (line ~1262):

New table: "Choose your province: incorporation comparison"

Factor British Columbia Ontario Alberta* Federal (CBCA)*
Resident director No No No 25% Canadian
Incorporation fee ~C$350 ~C$360 ~C$300 ~C$200
Annual return/report C$42.71/yr C$25/yr C$20/yr C$12/yr
Portal Anonymous Requires account Requires account Requires account
Processing time 1-2 days Same day 1-2 days 1-5 days
Numbered format 1234567 B.C. Ltd. 1234567 Ontario Inc. 1234567 Alberta Ltd. 1234567 Canada Inc.
Sales tax GST+PST 12% HST 13% GST 5% Depends
Small biz tax rate 11% 12.2% 11% Depends
Language English English/French English English/French
Best for Pacific gateway Largest market Low cost Multi-province

*Alberta and Federal shown as "Coming soon".

4b. FAQ rewrite (Opus) — In canada-crtc.json:

  • Rewrite Q23: "Which province should I choose?" — BC vs ON pros/cons
  • New FAQ: "Can I switch provinces later?" — extra-provincial registration

Effort: 1-2 hours


Phase 5: Order Form Multi-Province

5a. CRTC order formOpus 4.6

Modify site/src/pages/order/canada-crtc.astro (2,550 lines):

  • Province selector at Step 1 (radio: BC | Ontario, dev-only gate)
  • PROVINCE_DATA JS object + setProvince(code) function
  • Swaps: entity format, legal endings, fees, AMB locations, DID area codes, act references
  • province hidden field in form submission

5b. Formation page backend wiringSonnet 4.6

The frontend already works for Canada. Backend changes only:

  • Ensure the CRTC callout remains (separate flows)
  • Verify entity type mapping sends correct values (ltd/inc/corp)
  • Verify province fee display works with API

Effort: 4-5 hours total (5a: 3-4 hrs, 5b: 1 hr)


Phase 6: API Routes + Pipeline Refactors

6a. CRTC API routeSonnet 4.6

api/src/routes/canada-crtc.ts:

  • Accept province parameter
  • Province-specific fee calculation via lookup
  • Dev gate: reject ON if NODE_ENV=production
  • Store province in canada_crtc_orders

6b. CRTC pipeline refactorOpus 4.6

scripts/workers/services/canada_crtc.py (2,179 lines):

  • Constructor accepts province from Sales Order
  • Composes with CanadianIncorporationHandler for incorporation steps
  • Dynamic province adapter: get_province(code) replaces hardcoded BCPortal
  • All messages use province_config["name"] instead of "BC"
  • Compliance entries dispatched to universal create_compliance_entries()

6c. Formation API routeSonnet 4.6

api/src/routes/formations.ts:

  • Accept country parameter ("US" default, "CA")
  • Validate Canadian entity types (ltd, inc, corp) when country=CA
  • Province-specific fee calculation (CAD->USD via FX)
  • Dev gate: reject country=CA if NODE_ENV=production
  • Dispatch to CanadianIncorporationHandler job for CA orders
  • ERPNext Formation Order: add Ltd./Inc./Corp. to entity_type Select

Effort: 5.5-6.5 hours total (6a: 1 hr, 6b: 3-4 hrs, 6c: 1.5-2 hrs)


Phase 7: Compliance Configs — All Jurisdictions

Model: Sonnet 4.6 — Data entry into established config structure.

7a. Canadian province compliance configs:

BC corporation (non-telecom):

Entry Fee Deadline Billable
BC Annual Report C$42.71 2 months after anniversary Yes ($99)
T2 Corporate Income Tax $0 (accountant) June 30 No
Corporate Tax Payment $0 (accountant) March 31 No
GST/HST Return $0 (accountant) March 31 (if registered) No
T4/T4A Slips $0 (accountant) February 28 (if employees) No
BC PST $0 (accountant) Volume-based (if applicable) No
WorkSafeBC $0 March 1 (if BC employees) No
AMB Renewal ~C$199/yr Anniversary Yes ($99)

Ontario corporation (non-telecom):

Entry Fee Deadline Billable
Ontario Annual Return C$25 6 months after anniversary Yes ($99)
T2 Corporate Income Tax $0 (accountant) June 30 No
Corporate Tax Payment $0 (accountant) March 31 No
HST Return $0 (accountant) March 31 (HST 13% combined) No
T4/T4A Slips $0 (accountant) February 28 (if employees) No
WSIB $0 Quarterly (if ON employees) No
AMB Renewal ~C$96/yr Anniversary Yes ($99)

Note: Ontario has fewer entries (no separate PST — HST is combined).

7b. US state compliance configs — all 51 jurisdictions:

Add compliance_obligations to each state config in scripts/formation/states/. Data sourced from docs/state-annual-fees-complete.md.

States with annual report fees ($7-$810):

State Code Annual Fee Deadline Filing Name
California CA $810 Apr 15 (1st year: 90 days) Statement of Information + Franchise Tax
Massachusetts MA $500 Anniversary Annual Report
Nevada NV $350 Anniversary Annual List + Business License
Delaware DE $300 Jun 1 Franchise Tax
Maryland MD $300 Apr 15 Annual Report + PPT Return
Tennessee TN $300 Anniversary (1st quarter) Annual Report
North Carolina NC $200 Apr 15 Annual Report
DC DC $150/yr Anniversary (biennial $300) Biennial Report
Arkansas AR $150 May 1 Franchise Tax Report
Florida FL $138.75 May 1 Annual Report
New Hampshire NH $100 Apr 1 Annual Report
Oregon OR $100 Anniversary Annual Report
Alaska AK $50/yr Jan 2 (biennial $100) Biennial Report
Maine ME $85 Jun 1 Annual Report
Connecticut CT $80 Anniversary Annual Report
Illinois IL $75 Anniversary month Annual Report
New Jersey NJ $75 Anniversary month Annual Report
Georgia GA $60 Apr 1 Annual Registration
Washington WA $60 Anniversary Annual Report
Wyoming WY $60 min Anniversary month Annual Report
South Dakota SD $55 Anniversary month Annual Report
Alabama AL $50 min Apr 15 Business Privilege Tax
Kansas KS $50 Apr 15 Annual Report
North Dakota ND $50 Nov 15 Annual Report
Rhode Island RI $50 Anniversary Annual Report
Virginia VA $50 Anniversary month (last day) Annual Registration
Vermont VT $45 Anniversary quarter Annual Report
Hawaii HI $35 Anniversary Annual Report + GET License
Louisiana LA $35 Anniversary Annual Report
Colorado CO $25 Anniversary month Periodic Report
Michigan MI $25 Feb 15 Annual Statement
Oklahoma OK $25 Anniversary Annual Certificate
West Virginia WV $25 Jul 1 Annual Report
Wisconsin WI $25 Anniversary quarter Annual Report
Montana MT $20 Apr 15 Annual Report
Utah UT $18 Anniversary Annual Renewal
Indiana IN $15/yr Anniversary month (biennial $30) Business Entity Report
Iowa IA $15/yr Apr 1 odd years (biennial $30) Biennial Report
Kentucky KY $15 Jun 30 Annual Report
Pennsylvania PA $7 Anniversary (new as of 2025) Annual Report
New York NY $4.50/yr Anniversary (biennial $9) Biennial Statement
Nebraska NE $6.50/yr Apr 1 odd years (biennial $13) Biennial Report

States with $0 annual fees (9 states):

State Code Notes
Arizona AZ No annual report required, no fee
Idaho ID Annual report required but $0 fee
Minnesota MN Annual renewal required but $0 fee
Mississippi MS No annual report ($0); privilege tax only for S-Corps
Missouri MO No annual report required, no fee
New Mexico NM No annual report required, no fee
Ohio OH No annual report; Commercial Activity Tax only if revenue >$150K
South Carolina SC No annual report unless LLC elects S-Corp treatment
Texas TX Public Information Report ($0); franchise tax only if revenue >$2.47M

Note: Even $0-fee states get a compliance calendar entry as a REMINDER — the client may still need to file a $0 report to maintain good standing (ID, MN, TX).

Franchise tax states (additional entry beyond annual report):

State Franchise Tax Threshold Deadline
California $800/yr minimum All LLCs Apr 15
Delaware $300/yr minimum All LLCs Jun 1
Texas 0.375%/0.75% of revenue >$2.47M revenue May 15
Tennessee $300/member min All LLCs Anniversary
Alabama $0.25 per $1K net worth Min $50, max $15K Apr 15

Effort: 3-4 hours total (7a: 1 hr, 7b: 2-3 hrs)


Phase 8: Dev Stack E2E Tests

Model: Debugger agent

8a. Multi-province CRTC test:

  1. Verify province selector shows BC + ON on dev
  2. Create Ontario CRTC order, verify fees adjust
  3. Verify DID search returns 416/647 numbers
  4. Verify mailbox picker shows Toronto locations
  5. Verify pipeline runs with ON adapter
  6. Verify compliance calendar: 15-17 ON entries (WSIB not WorkSafeBC, no PST, HST)
  7. Verify emails use "Ontario" language
  8. Regression: verify BC orders still work

8b. Canadian formation-only test:

  1. Select Canada + Ontario on formation page
  2. Verify entity types show Ltd./Inc./Corp.
  3. Verify fees show CAD + USD
  4. Submit formation-only order
  5. Verify CanadianIncorporationHandler dispatched (no telecom steps)
  6. Verify compliance calendar: 6-8 ON entries (corporate only, no telecom)
  7. Verify binder compilation works without CRTC letter

8c. US formation compliance test:

  1. Create a WY formation order
  2. Verify compliance calendar entry created: WY Annual Report ($60, anniversary month)
  3. Create a DE formation order (with RA)
  4. Verify entries: DE Franchise Tax ($300, Jun 1) + RA renewal ($99)
  5. Verify renewal_worker processes these entries correctly

Effort: 2-3 hours


Model Assignment Summary

Model Phases Why
Opus 4.6 0, 1, 3e, 3g, 4b, 5a, 6b Architecture, unknown portal recon, pipeline decomposition, complex refactoring, persuasive content
Sonnet 4.6 2, 3a-d, 3f, 4a, 5b, 6a, 6c, 7a, 7b Mechanical edits, known patterns, SQL, HTML tables, data entry, config population
Debugger 8 Build verification, regression testing, E2E validation

Effort Summary

Phase Effort Model
Phase 0: OBR + CRA Recon 2-2.5 hrs Opus
Phase 1: ProvinceConfig + compliance design 3-4 hrs Opus
Phase 2: DB Migrations 45 min Sonnet
Phase 3a-d: ON adapter + AMB + DID 3-4 hrs Sonnet
Phase 3e: CanadianIncorporationHandler 2-3 hrs Opus
Phase 3f: CRA BN stub 30 min Sonnet
Phase 3g: Universal compliance creator 1-2 hrs Opus
Phase 4: Service page table + FAQ 1-2 hrs Sonnet + Opus
Phase 5a: CRTC order form 3-4 hrs Opus
Phase 5b: Formation page wiring 1 hr Sonnet
Phase 6a: CRTC API route 1 hr Sonnet
Phase 6b: CRTC pipeline refactor 3-4 hrs Opus
Phase 6c: Formation API route 1.5-2 hrs Sonnet
Phase 7a: CA province compliance configs 1 hr Sonnet
Phase 7b: US state compliance (51 jurisdictions) 2-3 hrs Sonnet
Phase 8: Dev E2E tests 2-3 hrs Debugger
Total 28-36 hours 5-6 sessions

Parallelizable: Phases 0, 1, 2, 4, and 7b have no dependencies on each other. Phase 4 (service page table) can ship to production immediately — no backend needed.


Files Changed Summary

New Files (10)

File Phase Purpose
scripts/formation/province_config.py 1 ProvinceConfig TypedDict + registry
scripts/formation/compliance.py 3g Universal compliance entry creator
scripts/formation/canadian_incorporation.py 3e Shared Canadian incorporation handler
scripts/formation/states/on/__init__.py 3a Ontario package init
scripts/formation/states/on/config.py 3a Ontario ProvinceConfig
scripts/formation/states/on/adapter.py 3b ONPortal(StatePortal)
scripts/workers/services/cra_bn.py 3f CRA Business Number registration
scripts/recon_obr.py 0 OBR Playwright recon (disposable)
scripts/recon_cra_bn.py 0 CRA BN recon (disposable)
api/src/migrations/036_multi_province.sql 2 Province + country columns

Modified Files (16)

File Phase Change
site/src/pages/services/telecom/canada-crtc.astro 4a Province comparison table
site/src/pages/order/canada-crtc.astro 5a Province selector + dynamic content
site/src/content/services/canada-crtc.json 4b FAQ rewrite
api/src/routes/canada-crtc.ts 6a Accept province parameter
api/src/routes/formations.ts 6c Accept CA provinces + entity types
scripts/workers/services/canada_crtc.py 6b Compose with CanadianIncorporationHandler
scripts/workers/services/flowroute.py 3d provision_canadian_did(province)
scripts/workers/amb_location_scraper.py 3c Multi-province scraping
scripts/workers/job_server.py 3e Add CA formation job handlers
scripts/formation/states/bc/config.py 1 Conform to ProvinceConfig
scripts/formation/states/__init__.py 1 Register CA provinces
scripts/formation/states/*/config.py (51 files) 7b Add compliance_obligations to each US state
erpnext/doctypes/formation_order/formation_order.json 6c Add Canadian entity types
docs/go-live-todo.md Add multi-province + formation items
docs/product-facts.md Add CA formation product
docs/billing.md Add maintenance bundles

AMB Ontario Locations

From Anytime Mailbox Ontario page (30+ locations):

City Address Starting Price
Toronto - Dundas St 2967 Dundas St. W., Toronto, ON M6P 1Z2 C$7.99/mo
Toronto - Davenport Rd 1463 Davenport Rd, Toronto, ON M6H 2H6 C$13.99/mo
Mississauga 1065 Canadian Pl, Mississauga, ON L4W 0C2 C$8.99/mo
+ 25 more cities Acton, Ajax, Bolton, Brampton, Cambridge, Cornwall, Etobicoke, Georgetown, Hamilton, Markham, North York, Oakville, Ottawa, etc. Varies

Recommendation: Default to a downtown Toronto location for prestige.


Open Questions

Question Context Decision Needed
OBR house account viability? Phase 0 will answer. If one account can't file multiple corps, fall back to admin ToDo. After Phase 0
CRA BN automation viability? Phase 0b will answer. If not automatable, admin ToDo with instructions. After Phase 0
Alberta / Federal — when? Architecture supports from day one. Add when demand warrants. Post-launch
Ontario AMB default location? Toronto has 6+ locations. Downtown for prestige? Phase 3
ON numbered entity suffix? "Ontario Inc." or "Ontario Ltd."? Verify against OBR. Phase 0
French-language support? OBCA allows French endings (Ltee, Cie). Offer on form? Phase 5
US state compliance — all at once or incremental? 51 configs is a lot. Could do top 10 first. Decision: all 51 now. Phase 7b
Formation maintenance auto-enrollment? Auto-enroll in $179/yr bundle? Or opt-in? Phase 6c