# Command Sovereignty β Remodeling Sector Gap Plan
**Target companies:** Omnia, Renuity, Tundraland, Power Home Remodeling
**Revenue range:** $20Mβ$100M+ annually, PE-backed or scaling, multi-service line
---
## Current capabilities that directly serve this segment
| Capability | Why it matters to remodeling | Status |
|---|---|---|
| QuickBooks connector | Actuals ingestion for revenue/rexpense tracking | β
Built |
| Revenue Leak engine (21 detectors) | Catches abandoned deals, stale leads, overdue invoices | β
Built |
| Forecast automation (actuals + pipeline) | Know if you'll hit the number weeks early | β
Built |
| Cascading goals (org β dept β team β rep) | Targets flow down instead of staying on a whiteboard | β
Built |
| Scale optimization (ROAS / LTV:CAC by channel) | See which lead source is actually profitable | β
Built |
| Strategic Intelligence (FP&A waterfall) | Drill into variance instead of guessing | β
Built |
| Multi-tenant portals | Multiple operating companies/brands each get their own view | β
Built |
| Google Ads connector | Lead cost tracking for paid search | β
Built |
| Facebook Ads connector | Lead cost tracking for social ads | β
Built |
| HubSpot connector | CRM pipeline + deal tracking | β
Built |
| ServiceTitan connector | CRM/project management integration | β
Built |
| AngiLead model + API routes | Data model and CRUD API for Angi leads | β
Built (partial) |
| Twilio SMS/Call integration | Speed-to-lead tracking, automated follow-up | β
Built |
---
## Gaps to close
### 1. Angi Connector (webhook receiver + setup flow) β β
DONE
**What exists:** `AngiLead` model in models.py (line 926), API proxy routes for CRUD, SMS/call integration referencing AngiLead, **working webhook endpoint**, multi-tenant auth.
**What was built (2026-07-22):**
- Webhook endpoint `POST /api/connectors/webhooks/angi` with `x-api-key` multi-tenant authentication
- New AngiLead fields: `interview_qa` (Text/JSON), `tcpa_compliance` (Boolean), `match_type` (String)
- Real field mapping: `service_type`β`project_type`, `project_description`β`description`, `tcpa_consent`β`tcpa_compliance`
- `to_dict()` serialization of new fields
- AngiLead creation includes all new fields on webhook receipt
**What's missing:**
- Webhook receiver endpoint that accepts Angi's JSON POST (`POST /api/connectors/angi/webhook/<connector_id>`)
- Field mapping: Angi sends `name`, `firstName`, `lastName`, `address`, `city`, `stateProvince`, `postalCode`, `primaryPhone`, `email`, `srOid`, `leadOid`, `fee`, `taskName`, `comments`, `matchType`, `leadDescription`, `interview[]`, `automatedContactCompliant`
- Connector config UI: company enters their webhook URL (Command Sovereity's endpoint) + API key, emails it to `crmintegrations@angi.com` for Angi to configure
- Lead acceptance/rejection callbacks to Angi (if needed)
- Duplicate detection across companies sharing Angi leads (shared leads are a common Angi pattern)
**Auth model:** Angi uses `x-api-key` header (partner-provided key, max 160 chars). No OAuth β it's a webhook push from Angi β our endpoint.
**Implementation:**
- `POST /api/connectors/angi/webhook/<connector_id>` β receives lead, maps fields, creates `AngiLead`, triggers speed-to-lead alerts
- Connector settings page: shows webhook URL, API key generation, setup instructions for Angi
- Test mode: company emails test webhook URL to Angi, we validate payload
- Duplicate detection: check `angi_lead_id` + `company_id` unique constraint (already in model)
- Cost tracking: store `fee` from Angi payload as `cost_per_lead`
**Estimated effort:** 1 day
---
### 2. Change Order Revenue Leakage Detection
**Problem:** Remodeling companies lose 10-15% of project revenue in uncaptured change orders. A $500k kitchen remodel ends up with $650k in work but only $500k invoiced.
**Detector concept:** `change_order_capture_rate` β compare original estimate (from ServiceTitan/Jobber/HubSpot) to final invoice (from QuickBooks). Flag projects where actual scope exceeded estimate by >15% but invoice didn't reflect the increase.
**Data sources needed:**
- ServiceTitan: original estimate amount vs. final invoice amount (connector exists, needs estimate endpoint)
- Jobber: same pattern (connector doesn't exist yet β see gap #4)
- QuickBooks: final invoice amounts (connector exists)
**Implementation:**
- New leak detector: compares estimate β invoice delta per project
- Alert: "Project #12345 β estimated $12,000, invoiced $12,000. Customer approved $18,000 in scope changes. ~$6,000 in uncaptured change orders."
- Dashboard widget: change order capture rate by project manager/team
**Estimated effort:** 2-3 days (depends on ServiceTitan estimate data availability)
---
### 3. Estimate-to-Close Funnel Tracking
**Problem:** Lead β Estimate β Close is the core funnel in remodeling. We track deals in HubSpot but not estimates from estimating software. The drop-off point between estimate delivered and estimate accepted is the biggest revenue leak.
**What to build:**
- Funnel stage tracking: Lead received β Contacted β Estimate delivered β Estimate accepted β Won/Lost
- Time-in-stage metrics: average days from estimate to close
- Drop-off analysis: which project types have worst estimate acceptance rates
- Integration with ServiceTitan/Jobber estimate endpoints
**Data model additions:**
- `Estimate` model (or extend `AngiLead` with estimate tracking)
- Estimate stages with timestamps
- Funnel conversion rates by project type, rep, region
**Implementation:**
- Extend `AngiLead` lifecycle to include estimate stages: `estimate_delivered`, `estimate_accepted`, `estimate_rejected`
- ServiceTitan connector: pull estimate data when available
- Dashboard: funnel visualization with conversion rates and time-in-stage
**Estimated effort:** 3-4 days
---
### 4. Jobber Connector
**Problem:** Many remodeling companies use Jobber instead of ServiceTitan. Renuity and others in the mid-market segment have migrated to Jobber.
**API:** Jobber has a documented REST API with OAuth 2.0. Covers estimates, jobs, customers, invoices, tasks.
**What to build:**
- OAuth 2.0 flow: company clicks "Connect Jobber," authenticates, we store tokens
- Sync: estimates, jobs, customers, invoices
- Map Jobber data to our existing `AngiLead`/`Opportunity` models
- Reuse connector architecture from existing ServiceTitan/QuickBooks connectors
**Key endpoints:**
- `GET /v1/estimates` β estimate tracking
- `GET /v1/jobs` β project tracking
- `GET /v1/customers` β customer data
- `GET /v1/invoices` β revenue data
**Estimated effort:** 3-4 days
---
### 5. Project Slippage Detection
**Problem:** Design-build projects (Tundraland, Renuity) run over schedule. A 6-week bathroom remodel becomes 9 weeks. Each week of slippage eats margin (crew costs, equipment rentals, overhead).
**Detector concept:** `project_schedule_variance` β compare estimated completion date to actual/forecasted completion. Flag projects >10% behind schedule.
**Data sources needed:**
- ServiceTitan/Jobber: job start date, estimated end date, current status, milestones
- QuickBooks: time-based expenses that indicate ongoing work past deadline
**Implementation:**
- New leak detector: tracks schedule variance per active project
- Alert: "Project #67890 β estimated completion July 15, now forecasted July 29. 2-week slippage. Estimated margin impact: $2,400."
- Rollup: average slippage by project type, project manager, region
**Estimated effort:** 2-3 days (depends on job date data from connectors)
---
### 6. Backlog Burn-Down Tracking
**Problem:** Storm restoration companies (Omnia) and remodelers live by their backlog. They need to know: "At current conversion rate, how many weeks of backlog do we have? When do we need more leads?"
**What to build:**
- Backlog calculation: sum of all active/scheduled project values
- Burn rate: average weekly revenue from completed projects
- Weeks of coverage: backlog / burn_rate
- Alert when coverage drops below threshold (e.g., 4 weeks)
- Re-forecasting: update projection weekly as new deals close and projects complete
**Data sources:**
- ServiceTitan/Jobber: scheduled jobs, estimated values
- QuickBooks: completed project revenue
- HubSpot/Angi: pipeline value
**Estimated effort:** 2 days
---
### 7. Margin Per Job/Room Tracking
**Problem:** Kitchen, bath, deck, roof projects have wildly different margins. Companies need to know which project types are actually profitable after labor, materials, and overhead.
**What to build:**
- Project-level P&L: estimate cost vs. actual cost from QuickBooks expenses
- Margin by project type, by project manager, by region
- Alert when project margin drops below threshold
**Data sources:**
- ServiceTitan/Jobber: estimated materials + labor
- QuickBooks: actual expenses, payroll allocation
- Command Sovereignty: calculate margin delta
**Estimated effort:** 3-4 days
---
### 8. Multi-Location Rollup Analytics
**Problem:** Renuity operates in multiple markets. Leadership needs a rollup view: total revenue, conversion rates, leak detection across all locations, with the ability to drill into any single market.
**What to build:**
- Group companies by parent organization
- Rollup dashboard: aggregate KPIs across all locations
- Drill-down: click into any location for detailed view
- Comparative analysis: which location has best/worst metrics
**Current state:** Multi-tenant portals exist, but analytics are per-company not rollup.
**Estimated effort:** 4-5 days
---
## Implementation Priority
| Priority | Feature | Effort | Impact | Rationale |
|---|---|---|---|---|
| **P0** | Angi Connector (webhook) | 1 day | High | Quick win, immediate value, companies already use Angi |
| **P1** | Backlog Burn-Down | 2 days | High | Critical for storm restoration / remodeling ops |
| **P1** | Change Order Detection | 2-3 days | High | Directly catches revenue leakage |
| **P2** | Estimate-to-Close Funnel | 3-4 days | Medium | Closes the leadβclose visibility gap |
| **P2** | Jobber Connector | 3-4 days | Medium | Expands CRM coverage beyond ServiceTitan |
| **P3** | Project Slippage Detection | 2-3 days | Medium | Margin protection for design-build |
| **P3** | Margin Per Job Tracking | 3-4 days | Medium | Profitability visibility by project type |
| **P4** | Multi-Location Rollup | 4-5 days | Low-Medium | Needed for multi-market companies |
**Total estimated effort:** ~25-30 days (single developer)
---
## Angi Connector β Detailed Implementation Plan (P0)
### Angi webhook payload β our model mapping
| Angi field | Our field | Notes |
|---|---|---|
| `firstName`, `lastName` | `first_name`, `last_name` | Direct map |
| `email` | `email` | Direct map |
| `primaryPhone` | `phone` | Direct map |
| `address`, `city`, `stateProvince`, `postalCode` | `address`, `city`, `state`, `zip_code` | Rename stateProvince |
| `srOid` or `leadOid` | `angi_lead_id` | Use srOid as primary |
| `taskName` | `project_type` | Direct map |
| `comments` | `description` | Direct map |
| `fee` | `cost_per_lead` | Direct map |
| `leadSource` | `lead_source` | Direct map |
| `interview[]` | (new) `interview_qa` JSON field | Store as JSON array |
| `automatedContactCompliant` | (new) `tcpa_compliant` boolean | TCPA tracking |
| `matchType` | (new) `match_type` string | Track lead type |
### New fields to add to AngiLead model
```python
interview_qa = db.Column(db.Text, nullable=True) # JSON array
tcpa_compliant = db.Column(db.Boolean, default=True)
match_type = db.Column(db.String(50), default='')
```
### Files to create/modify
1. `app/routes/connectors/angi_webhook.py` β webhook receiver endpoint
2. `app/routes/connectors/angi_config.py` β connector settings (webhook URL display, API key gen)
3. `app/models.py` β add 3 new fields to AngiLead
4. `app/services/leak_detectors/` β add angi-specific detector: `angi_lead_cost_roi` (compare cost_per_lead to closed deal value)
5. `frontend/src/pages/Connectors/AngiSettings.tsx` β UI for connector setup
6. `tests/test_angi_webhook.py` β webhook payload handling tests
### Endpoint spec
```
POST /api/connectors/angi/webhook/<connector_id>
Headers: x-api-key: <partner_key>
Content-Type: application/json
Response: 200 { "status": "success", "leadId": "<our_lead_id>" }
Response: 401 { "status": "error", "message": "Invalid API key" }
Response: 200 { "status": "success", "duplicate": true } (for duplicate leads)
```