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>
774 lines
34 KiB
Markdown
774 lines
34 KiB
Markdown
# 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
|
|
|
|
```python
|
|
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:
|
|
|
|
```python
|
|
# 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
|
|
|
|
```sql
|
|
-- === 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 config** — **Sonnet 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 adapter** — **Sonnet 4.6**
|
|
|
|
`scripts/formation/states/on/adapter.py` — `ONPortal(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 extension** — **Sonnet 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 generalization** — **Sonnet 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. CanadianIncorporationHandler** — **Opus 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 registration** — **Sonnet 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 creator** — **Opus 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 form** — **Opus 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 wiring** — **Sonnet 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 route** — **Sonnet 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 refactor** — **Opus 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 route** — **Sonnet 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 |
|