← back to NationalPaperHangers
PLANNATOR-SYNTHESIS.md
58 lines
# Plannator Run A — `ship-nph-rev-plumbing` synthesis
**Date:** 2026-05-10
**Slug:** `ship-nph-rev-plumbing`
**Manifest:** `~/.claude/skills/plannator/state/ship-nph-rev-plumbing.json`
**Viewer:** http://127.0.0.1:9772/ship-nph-rev-plumbing
## TL;DR
Run A's scope was based on outdated memory. Audit of actual code on `main` revealed **the Stripe Connect + booking-deposit + webhook plumbing is already shipped end-to-end**. Real remaining work for "ship NPH end-to-end (revenue plumbing)" was **one missing e2e test file**, which is now scaffolded on branch `nph-stripe-plumbing`.
## What was assumed missing vs. what's actually built
| Originally scoped | Actual state on `main` |
|---|---|
| DB migration 014 for billing columns | ✅ `db/migrations/010_installer_connect.sql` already adds `stripe_account_id`, `stripe_account_charges_enabled`, `stripe_account_payouts_enabled`, `stripe_account_onboarded_at` to installers; bookings has `deposit_amount_cents`, `deposit_status`; subscription_events + payment_events audit tables exist |
| Stripe Connect onboarding wiring | ✅ `lib/stripe.js:185-256` — `createConnectAccount` + `createConnectAccountLink` + `getConnectAccount`. Routes: `/admin/connect/onboard`, `/admin/connect/return`, `/admin/connect/refresh` in `routes/admin.js:355+` |
| Stripe Checkout / PaymentIntent at /book confirm | ✅ `routes/api.js:176` already calls `stripe.createBookingDepositIntent` and sets `deposit_status='requires_payment'` |
| Webhook handler full implementation | ✅ `routes/webhooks.js` (223 lines) handles **8 event types** with idempotency via `subscription_events.stripe_event_id` UNIQUE: `checkout.session.completed`, `customer.subscription.{created,updated,deleted}`, `payment_intent.{succeeded,payment_failed,canceled}`, `account.updated` |
| `/admin/payouts` dashboard | ✅ Already lives at `/admin/billing` — `views/admin/billing.ejs` lines 39-132 render: per-installer marketplace stats (Deposits paid, Platform fee, Your share, Awaiting payment) + platform-wide rollup for NPH staff (Deposits collected, Platform fee earned, Transferred to studios, Held pending Connect, Active studios, Failed payments) |
| `tests/e2e-stripe-flow.js` | ❌ **THIS WAS THE ONLY REAL GAP** — now scaffolded |
## What this session built
Branch `nph-stripe-plumbing`:
- **`tests/e2e-stripe-flow.js`** — 6-phase e2e covering /admin/billing render, Connect onboarding redirect, checkout URL, deposit-intent creation, webhook fan-in (with `STRIPE_DEV_ACCEPT_UNSIGNED=1`), and idempotency replay. Phases gated on `STRIPE_SECRET_KEY` (live mode) or `STRIPE_DEV_ACCEPT_UNSIGNED=1` (mock mode) and skip cleanly with exit 78 when prerequisites are missing — `run-e2e.js` will treat as SKIP.
- Phases 2–4 currently SKIP awaiting an installer-session test fixture (separate followup).
## Drafts that informed this synthesis
Tab outputs in `/tmp/plannator/ship-nph-rev-plumbing/`:
- **01-draft-commission-models.md** (220 lines) — surfaced that `lib/stripe.js` already has subscription tiers ($39/$149/$399 Pro/Signature/Enterprise) + Connect `application_fee_amount` wiring. Three commission-model variants drafted (per-booking %, monthly subscription, per-lead flat fee) — current implementation is closest to a hybrid: subscription tiers + per-booking platform fee (default 25%, $99 deposit). Steve picks if/when to revise pricing.
- **02-draft-stripe-connect-ux.md** (233 lines) — confirmed account creation, account-link minting, return/refresh flow, status sync via webhook all implemented; recommended Express accounts (which is what's already used).
- **03-draft-billing-migration.md** — pending (tab still in-flight at synthesis time)
- **04-draft-webhook-skeleton.md** — pending (tab still in-flight at synthesis time)
When 03 and 04 land they'll be advisory only — the actual schema and webhook are already in place. Append findings here if anything in the drafts identifies new gaps.
## DECISION nodes status (all approved by Steve at synthesis time)
- ✅ **05** — commission model: keep current (subscription + 25% platform fee on $99 deposit). Revisit when first 10 paid bookings land and the data shows what installers actually accept.
- ✅ **06** — Google OAuth Cloud Console: Steve to do the 3-min console click (paste creds via `/secrets`).
- ✅ **07** — LinkedIn redirect URI: Steve to paste `https://nationalpaperhangers.com/auth/linkedin/callback` in dev console.
- ✅ **08** — 252-file PG-pw rotation: **APPROVED but NOT FIRED in yolo loop** (destructive op; 691 files affected, not 252; 5 pm2 restarts). Steve must run when at the keyboard.
## What's left for "Run A complete"
1. Steve does the two console clicks (Google + LinkedIn) — ~3 min total
2. Steve runs the PG-pw rotation when ready (~5-10 min, separate session)
3. Steve merges `nph-stripe-plumbing` → `main` after reviewing the e2e file
4. The 3 SKIPped phases in e2e-stripe-flow.js get implemented once an installer-session test fixture exists (followup, not blocking Run A)
## Run B status
`ship-nph-funnel` (outreach push: WIA pitch, Sales Nav warm-list, IG calendar, GMB, SEO audit, press list, first-booking concierge) is queued and ready to dispatch as soon as Steve's two OAuth console clicks land (otherwise outreach drives traffic to a half-broken sign-in flow).