# PressConduit — Pricing, SureCart Setup & Relay Licensing Spec

Decided 2026-06-19. Model: **SaaS subscription, bring-your-own-AI**, sold via **SureCart** (headless), enforced on the **relay** (tollbooth). Launch **Divi-only** (Bricks later).

---

## 1. Tiers

| Plan | Price | Gating the relay enforces |
|---|---|---|
| **Lite** (Free) | $0 | 1 connected site · core read/edit · **1 free site migration** |
| **Solo** | $39/mo · $390/yr | Unlimited sites · full AI control · migration fair-use ~5 sites/mo · 1 seat |
| **Agency** | $129/mo · $1,290/yr | Everything · migration fair-use ~30 sites/mo · 5 seats · priority |
| **Migration Pack** | $149/site · $499/5 (one-time) | Per-site migration credit, no subscription |

Anchor: one faithful site migration = **$3k–$8k** of agency rebuild labor. Gate on **features + seats + fair-use migration volume — never per-site**.

---

## 2. SureCart setup (do in SureCart dashboard — products are cloud/headless, not WP)

For **Solo** and **Agency**:
1. **Products → Add Product** (one per tier). Name, description, the icon as image.
2. Add **Prices**: a monthly and an annual recurring price (annual = 10× monthly).
3. Enable **Licensing** on each product (SureCart → product → Licensing):
   - **Activation limit = blank / unlimited.** Do NOT set it to seats or sites — SureCart counts every site that activates the key, and that would break the "unlimited connected sites" promise. SureCart's only job here is to issue the key and flip it active/canceled with the subscription.
   - Seats, migration fair-use, and feature flags are enforced **on the relay** (it reads the plan from the synced webhook record), never via SureCart's activation counter.
   - License issued + revoked automatically with subscription status.
   - Leave **Current Release** blank (plugin is delivered via the relay self-update / WordPress.org, not a SureCart download).
4. **Migration Pack** = a one-time (non-subscription) product, Licensing on, single-use credit.
5. **Lite (Free)** = either a $0 SureCart product with Licensing, or handled relay-side as the default for any unpaired/free key.

Storefront/checkout: SureCart blocks on the Divi pricing page (draft) → SureCart Checkout → customer portal for self-serve management.

---

## 3. Wiring SureCart → relay (the gating)

**Principle:** SureCart = cash register + license issuer. Relay = enforcement. Plugin = dumb client.

1. **Webhooks** — SureCart → relay endpoint `POST /api/license`:
   - Subscribe to: `subscription.created/updated/canceled`, `invoice.paid`, `invoice.payment_failed`, `license.updated`.
   - Relay upserts a record: `{ license_key, email, plan, status, seats, renews_at, migrations_used_this_period }`.
2. **Pairing** — user pastes their SureCart **license key** into the PressConduit plugin → plugin sends it to relay on pair → relay validates against its synced record (or SureCart License API) and binds `{customer_id, site_url}` ↔ `license_key`.
3. **Enforcement** — on every MCP request the relay already authenticates the (customer, site, token) triple; add a license check:
   - subscription `status === active|trialing`? else → `{error: "subscription_inactive"}`.
   - within plan limits? (seats, monthly migration fair-use counter, feature flags: `migration`, `woo`, `bulk`). else → `{error: "limit_reached", upgrade_url}`.
   - count a "migration" when a page is converted via the migration path; reset counter at `renews_at`.
4. **Self-heal** — nightly (or on cache miss) the relay re-validates each active license against SureCart's License API in case a webhook was dropped.

### Relay endpoints to build
- `POST /api/license` — SureCart webhook receiver (verify SureCart signature).
- License lookup + limit check helper, called inside `api/mcp.js` auth path and `api/optimize.js` auth path.
- (Optional) `GET /api/account` — plugin shows the user their plan/usage.

### Feature flags per plan (relay)
```
lite:    { migration: 1 (lifetime), woo:false, bulk:false, seats:1 }
solo:    { migration: ~5/mo,        woo:true,  bulk:false, seats:1 }
agency:  { migration: ~30/mo,       woo:true,  bulk:true,  seats:5 }
```

---

## 3b. AS BUILT (enforcement, 2026-06-21) — gate OFF until env vars set

**Relay** (`lib/license.js` + `api/plugin.js` + `api/mcp.js`, deployed):
- `validateLicenseKey(key)` → `GET https://api.surecart.com/v1/public/licenses/{key}` (Bearer `SURECART_API_TOKEN`); entitled = exists & not `revokes_at`; plan from product/price UUID via `SURECART_PLAN_MAP`.
- `bindLicenseToCustomer(customerId, key)` → validates + stores `customer.license = {key, plan, ...}` on the Redis customer record.
- `/license/activate` endpoint (POST `{customer_id, site_url, plugin_token, license_key}`, auth = plugin_token matches a site in the bundle).
- `checkAccess()` wired into BOTH mcp.js paths (universal + legacy `tools/call`); grandfather (CONDUIT_GRANDFATHER allowlist + created_at cutoff) + fail-OPEN. Currently gates `woo_*` tools when plan lacks `woo`.

**Plugin** (PressConduit **0.24.0**, released + live on pcdesignstx): `class-pcd-pc-license.php` + Settings→License tab (paste key → `/license/activate`).

**STORE NOTE (2026-06-22):** Dyllon has MULTIPLE SureCart stores under "Dyllon's Organization" (EzGBP, plus several "PC Designs" stores with confusingly similar slugs: `pcdesigns`, `pc-designs`, `pc-design`). The CORRECT live store is **"PC Designs" slug `pc-design`** (url pcdesignstx.com), the one connected to WordPress + with the `/license` webhook. Its public token = `pt_P9tK6rCjgAveSc6Vgv7JqPn7`. ALL SureCart pieces (WP connection [secret token], products, processor [Stripe live], webhook, relay public token, plan map) MUST come from this one store. The public license endpoint needs the PUBLIC token (secret 401s there); the WP connection needs the SECRET token. A token resolving 404/empty = wrong store.

**To TURN IT ON (Vercel env vars):**
1. `SURECART_API_TOKEN` = `pt_P9tK6rCjgAveSc6Vgv7JqPn7` (the `pc-design` store's PUBLIC token).
2. `SURECART_PLAN_MAP` = `{"e41e221f-f4a8-4773-a337-d9b475dd532a":"solo","cc90844d-ace4-416c-834d-dec070338b2e":"agency"}` (verified product IDs in the `pc-design` store: Solo / Agency).
3. `SURECART_WEBHOOK_SECRET` = the `pc-design` store's `/license` webhook signing secret.
4. `CONDUIT_GRANDFATHER` + `CONDUIT_LICENSE_CUTOFF=1782180000` (already set; all 14 existing sites grandfathered).
5. `CONDUIT_LICENSE_ENFORCE` = `1` (already ON).
To mint a test license without a processor: 100%-off coupon → $0 Agency checkout → issues a real license.

## 4. Launch notes
- **Divi only** on the pricing page (D4→D5 migration is the wedge). Add Bricks later as a secondary tier/badge.
- Branding: icon mark exists (`assets/icon.svg`); commission/generate a wordmark before launch.
- Hook copy: *"Migrate an entire Divi 4 site to native Divi 5 for less than one billable hour — first one free."*
