# Pricing Signup Three-Plan Happy-Path Verification Implementation Plan

> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Ensure signup immediately starts Stripe Checkout for `solo` (monthly), `team` (monthly), and `founder` (yearly), then verify all three happy paths pass in Stripe test mode with evidence.

**Architecture:** Unify signup billing intent to a 3-plan contract (`solo|team|founder`), centralize pending-checkout logic in billing helpers, and make post-signup checkout bootstrap plan-agnostic in auth flow. Keep `create-checkout-session` API as-is (already supports 3 plans), add focused frontend tests for intent submission and pending checkout recovery, then run live manual verification and document outcomes.

**Tech Stack:** TypeScript, React 19, React Query, Vitest, Testing Library, Stripe test mode, Stripe CLI webhook forwarding

---

## Spec Reference

- `/Users/arthur.belleville/Documents/perso/projects/xtablo-source/docs/superpowers/specs/2026-03-15-pricing-signup-three-plan-happy-path-verification-design.md`

## Execution Skills

- `@test-driven-development`
- `@systematic-debugging`
- `@verification-before-completion`

## Scope Guardrails (YAGNI)

- Do not add failure-path handling beyond current behavior (declines/cancellations/webhook outages remain out-of-scope for this cycle).
- Do not redesign billing pages or pricing UI beyond replacing `trial` with explicit `solo`/`team` plans.
- Do not add browser automation (Playwright/Cypress) in this cycle.

## File Structure (lock boundaries before coding)

### Billing contract + shared helpers

- Modify: `apps/main/src/lib/billing.ts`
  - Responsibility: canonical signup billing intent types (`solo|team|founder`), localStorage key helpers, and plan satisfaction helper used by auth/bootstrap flows.
- Create: `apps/main/src/lib/billing.test.ts`
  - Responsibility: unit tests for plan parsing/defaults/satisfaction behavior.

### Signup UI + intent submission

- Modify: `apps/main/src/pages/signup.tsx`
  - Responsibility: expose 3 plan choices and submit selected billing intent.
- Modify: `apps/main/src/pages/signup-v2.tsx`
  - Responsibility: keep v2 signup behavior aligned with primary signup flow.
- Modify: `apps/main/src/pages/signup.test.tsx`
  - Responsibility: validate default plan + intent payload mapping.
- Create: `apps/main/src/pages/signup-v2.test.tsx`
  - Responsibility: parity checks for v2 plan intent submission.

### Checkout bootstrap and retry-on-login component

- Modify: `apps/main/src/hooks/auth.ts`
  - Responsibility: create checkout immediately after signup for any selected plan.
- Move/Modify: `apps/main/src/components/PendingFounderCheckout.tsx` -> `apps/main/src/components/PendingSignupCheckout.tsx`
  - Responsibility: recover pending checkout for any of the 3 plans once user is authenticated.
- Modify: `apps/main/src/App.tsx`
  - Responsibility: mount renamed generalized pending-checkout component.
- Create: `apps/main/src/components/PendingSignupCheckout.test.tsx`
  - Responsibility: behavior tests for pending plan recovery (`solo`, `team`, `founder`).

### Verification evidence

- Create: `docs/superpowers/reports/2026-03-15-pricing-signup-three-plan-happy-path-verification.md`
  - Responsibility: record pass/fail evidence matrix for all three live flows.

---

## Chunk 1: Contract + Signup Intent Wiring (TDD)

### Task 1.1: Replace legacy signup intent contract (`trial|founder`) with explicit 3-plan contract

**Files:**
- Modify: `apps/main/src/lib/billing.ts`
- Create: `apps/main/src/lib/billing.test.ts`
- Test: `apps/main/src/lib/billing.test.ts`

- [ ] **Step 1: Write failing unit tests for billing intent helpers**

```ts
import { describe, expect, it } from "vitest";
import {
  DEFAULT_SIGNUP_BILLING_INTENT,
  isSignupBillingIntent,
  satisfiesPendingCheckoutPlan,
} from "./billing";

describe("billing helpers", () => {
  it("defaults signup intent to solo", () => {
    expect(DEFAULT_SIGNUP_BILLING_INTENT).toBe("solo");
  });

  it("recognizes only solo/team/founder", () => {
    expect(isSignupBillingIntent("solo")).toBe(true);
    expect(isSignupBillingIntent("team")).toBe(true);
    expect(isSignupBillingIntent("founder")).toBe(true);
    expect(isSignupBillingIntent("trial")).toBe(false);
  });

  it("treats founder as satisfied only by annual", () => {
    expect(satisfiesPendingCheckoutPlan("founder", "annual")).toBe(true);
    expect(satisfiesPendingCheckoutPlan("founder", "team")).toBe(false);
  });
});
```

- [ ] **Step 2: Run test to verify failure**

Run: `pnpm --filter @xtablo/main test -- src/lib/billing.test.ts`  
Expected: FAIL because constants/helpers do not exist yet.

- [ ] **Step 3: Implement minimal helpers in `billing.ts`**

```ts
export type SignupBillingIntent = "solo" | "team" | "founder";
export const DEFAULT_SIGNUP_BILLING_INTENT: SignupBillingIntent = "solo";

export function isSignupBillingIntent(value: string | null): value is SignupBillingIntent {
  return value === "solo" || value === "team" || value === "founder";
}

export function satisfiesPendingCheckoutPlan(
  pending: SignupBillingIntent,
  active: "solo" | "team" | "annual" | null
): boolean {
  // founder => annual only
  // team => team or annual
  // solo => solo/team/annual
}
```

- [ ] **Step 4: Re-run unit tests**

Run: `pnpm --filter @xtablo/main test -- src/lib/billing.test.ts`  
Expected: PASS.

- [ ] **Step 5: Commit**

```bash
git add apps/main/src/lib/billing.ts apps/main/src/lib/billing.test.ts
git commit -m "feat(main): add 3-plan signup billing helpers"
```

### Task 1.2: Update signup forms to submit `solo|team|founder` intents

**Files:**
- Modify: `apps/main/src/pages/signup.tsx`
- Modify: `apps/main/src/pages/signup-v2.tsx`
- Modify: `apps/main/src/pages/signup.test.tsx`
- Create: `apps/main/src/pages/signup-v2.test.tsx`
- Test: `apps/main/src/pages/signup.test.tsx`, `apps/main/src/pages/signup-v2.test.tsx`

- [ ] **Step 1: Update existing signup test to encode new contract first**

Test updates in `signup.test.tsx`:
- default submit sends `billing_intent: "solo"` (instead of `trial`)
- selecting Team sends `billing_intent: "team"`
- selecting Founder sends `billing_intent: "founder"`

- [ ] **Step 2: Add v2 parity test with same assertions**

Create `signup-v2.test.tsx` with one default and two selection cases (`team`, `founder`).

- [ ] **Step 3: Run tests to verify failure before UI changes**

Run: `pnpm --filter @xtablo/main test -- src/pages/signup.test.tsx src/pages/signup-v2.test.tsx`  
Expected: FAIL because forms still default to `trial` and do not expose explicit Team option.

- [ ] **Step 4: Implement minimal signup UI changes**

Implementation checklist:
- Default state is `solo` in both signup pages.
- Plan cards/buttons become exactly `Solo`, `Team`, `Founder`.
- Copy reflects cadence (`Solo` + `Team` monthly, `Founder` yearly).
- Submit passes selected plan unchanged as `billing_intent`.

- [ ] **Step 5: Re-run targeted signup tests**

Run: `pnpm --filter @xtablo/main test -- src/pages/signup.test.tsx src/pages/signup-v2.test.tsx`  
Expected: PASS.

- [ ] **Step 6: Commit**

```bash
git add apps/main/src/pages/signup.tsx apps/main/src/pages/signup-v2.tsx apps/main/src/pages/signup.test.tsx apps/main/src/pages/signup-v2.test.tsx
git commit -m "feat(main): submit solo team founder intents from signup"
```

---

## Chunk 2: Immediate Checkout Bootstrap + Pending Recovery (TDD)

### Task 2.1: Generalize pending checkout component to all plans

**Files:**
- Move/Modify: `apps/main/src/components/PendingFounderCheckout.tsx` -> `apps/main/src/components/PendingSignupCheckout.tsx`
- Modify: `apps/main/src/App.tsx`
- Create: `apps/main/src/components/PendingSignupCheckout.test.tsx`
- Test: `apps/main/src/components/PendingSignupCheckout.test.tsx`

- [ ] **Step 1: Write failing component tests for plan-aware pending checkout**

Cases to cover:
- pending `solo` triggers `createCheckout({ plan: "solo" })`
- pending `team` triggers `createCheckout({ plan: "team" })`
- pending `founder` + active annual clears localStorage and does not trigger checkout
- invalid pending value clears localStorage and does not trigger checkout

- [ ] **Step 2: Run test to confirm failure**

Run: `pnpm --filter @xtablo/main test -- src/components/PendingSignupCheckout.test.tsx`  
Expected: FAIL because component/file does not exist yet.

- [ ] **Step 3: Implement generalized component**

Implementation checklist:
- Parse pending plan via `isSignupBillingIntent`.
- Use `satisfiesPendingCheckoutPlan` against `organizationData.active_subscription_plan`.
- Trigger `useCreateCheckoutSession` with the pending plan when needed.
- Preserve retry behavior on mutation error.
- Update `App.tsx` import/render to `PendingSignupCheckout`.

- [ ] **Step 4: Re-run component test**

Run: `pnpm --filter @xtablo/main test -- src/components/PendingSignupCheckout.test.tsx`  
Expected: PASS.

- [ ] **Step 5: Commit**

```bash
git add apps/main/src/components/PendingSignupCheckout.tsx apps/main/src/components/PendingSignupCheckout.test.tsx apps/main/src/App.tsx
git rm apps/main/src/components/PendingFounderCheckout.tsx
git commit -m "refactor(main): generalize pending signup checkout to all plans"
```

### Task 2.2: Make `useSignUp` bootstrap checkout for any selected plan

**Files:**
- Modify: `apps/main/src/hooks/auth.ts`
- Create: `apps/main/src/hooks/auth.signup.test.tsx`
- Test: `apps/main/src/hooks/auth.signup.test.tsx`, `apps/main/src/pages/signup.test.tsx`, `apps/main/src/components/PendingSignupCheckout.test.tsx`

- [ ] **Step 1: Write failing auth hook test for Team checkout bootstrap**

In `auth.signup.test.tsx`, add a test that:
- mocks a confirmed signup response with `session.access_token`
- calls `useSignUp(...).mutate` with `billing_intent: "team"`
- asserts `/api/v1/stripe/create-checkout-session` is called with `{ plan: "team" }`
- asserts `localStorage` pending key behavior is preserved for retry if redirect bootstrap fails

- [ ] **Step 2: Run focused tests to confirm failure**

Run: `pnpm --filter @xtablo/main test -- src/hooks/auth.signup.test.tsx`  
Expected: FAIL because `auth.ts` currently founder-special-cases checkout bootstrap.

- [ ] **Step 3: Implement minimal auth flow changes**

Implementation checklist in `auth.ts`:
- treat `variables.billing_intent` as selected checkout plan (`solo|team|founder`)
- set `SIGNUP_BILLING_INTENT_KEY` + `PENDING_BILLING_CHECKOUT_PLAN_KEY` for all plans
- after confirmed signup, call `/api/v1/stripe/create-checkout-session` with `{ plan: selectedPlan }`
- keep pending key for retry path if immediate redirect fails
- remove founder-only branching

- [ ] **Step 4: Re-run focused tests**

Run: `pnpm --filter @xtablo/main test -- src/hooks/auth.signup.test.tsx src/pages/signup.test.tsx src/components/PendingSignupCheckout.test.tsx`  
Expected: PASS.

- [ ] **Step 5: Run broader safety checks**

Run: `pnpm --filter @xtablo/main test -- src/hooks/auth.signup.test.tsx src/pages/signup.test.tsx src/pages/signup-v2.test.tsx src/components/PendingSignupCheckout.test.tsx`  
Expected: PASS.

- [ ] **Step 6: Commit**

```bash
git add apps/main/src/hooks/auth.ts apps/main/src/hooks/auth.signup.test.tsx apps/main/src/pages/signup.test.tsx
git commit -m "feat(main): bootstrap signup checkout for solo team founder"
```

---

## Chunk 3: Verification and Evidence Capture (Live Stripe Test Mode)

### Task 3.1: Preflight checks before live runs

**Files:**
- Create: `docs/superpowers/reports/2026-03-15-pricing-signup-three-plan-happy-path-verification.md`

- [ ] **Step 1: Confirm plan price IDs exist in API env**

Run: `rg -n "STRIPE_SOLO_PRICE_ID|STRIPE_TEAM_MONTHLY_PRICE_ID|STRIPE_FOUNDER_PRICE_ID" apps/api/src/routers/stripe.ts`  
Expected: all three env-backed plan mappings present.

- [ ] **Step 2: Start webhook forwarding in Stripe test mode**

Run: `stripe listen --forward-to http://localhost:3000/api/v1/stripe-webhook`  
Expected: CLI prints `Ready!` and webhook signing secret line.

- [ ] **Step 3: Start local apps (if not already running)**

Run in separate terminals:
- `pnpm dev:api`
- `pnpm dev:main`

Expected: API and frontend boot with no fatal startup errors.

- [ ] **Step 4: Commit code before live manual verification starts**

```bash
git status --short
# Expected: empty output (or only known, intentional files for this plan)
```

### Task 3.2: Execute happy-path run for `solo` (monthly)

**Files:**
- Modify: `docs/superpowers/reports/2026-03-15-pricing-signup-three-plan-happy-path-verification.md`

- [ ] **Step 1: Run signup with unique Solo email and select Solo plan**
- [ ] **Step 2: Verify immediate redirect to Stripe Checkout**
- [ ] **Step 3: Complete payment with `4242 4242 4242 4242`**
- [ ] **Step 4: Verify return to success URL and in-app paid status**
- [ ] **Step 5: Record observed billing interval as `month` in report**

### Task 3.3: Execute happy-path run for `team` (monthly)

**Files:**
- Modify: `docs/superpowers/reports/2026-03-15-pricing-signup-three-plan-happy-path-verification.md`

- [ ] **Step 1: Run signup with unique Team email and select Team plan**
- [ ] **Step 2: Verify immediate redirect to Stripe Checkout**
- [ ] **Step 3: Complete payment with `4242 4242 4242 4242`**
- [ ] **Step 4: Verify return to success URL and in-app paid status**
- [ ] **Step 5: Record observed billing interval as `month` in report**

### Task 3.4: Execute happy-path run for `founder` (yearly)

**Files:**
- Modify: `docs/superpowers/reports/2026-03-15-pricing-signup-three-plan-happy-path-verification.md`

- [ ] **Step 1: Run signup with unique Founder email and select Founder plan**
- [ ] **Step 2: Verify immediate redirect to Stripe Checkout**
- [ ] **Step 3: Complete payment with `4242 4242 4242 4242`**
- [ ] **Step 4: Verify return to success URL and in-app paid status**
- [ ] **Step 5: Record observed billing interval as `year` in report**

### Task 3.5: Final verification + completion gates

**Files:**
- Modify: `docs/superpowers/reports/2026-03-15-pricing-signup-three-plan-happy-path-verification.md`

- [ ] **Step 1: Run regression checks for touched frontend files**

Run: `pnpm --filter @xtablo/main test -- src/lib/billing.test.ts src/pages/signup.test.tsx src/pages/signup-v2.test.tsx src/components/PendingSignupCheckout.test.tsx`  
Expected: PASS.

- [ ] **Step 2: Run typecheck**

Run: `pnpm --filter @xtablo/main typecheck`  
Expected: PASS (or only documented unrelated pre-existing failures).

- [ ] **Step 3: Fill final pass/fail matrix in report**

Required columns:
- `plan`
- `checkout reached`
- `payment completed`
- `success redirect`
- `interval expected`
- `interval observed`
- `result`
- `evidence`

- [ ] **Step 4: Commit verification report and remaining changes**

```bash
git add apps/main/src/lib/billing.ts apps/main/src/lib/billing.test.ts apps/main/src/pages/signup.tsx apps/main/src/pages/signup-v2.tsx apps/main/src/pages/signup.test.tsx apps/main/src/pages/signup-v2.test.tsx apps/main/src/hooks/auth.ts apps/main/src/components/PendingSignupCheckout.tsx apps/main/src/components/PendingSignupCheckout.test.tsx apps/main/src/App.tsx docs/superpowers/reports/2026-03-15-pricing-signup-three-plan-happy-path-verification.md
git commit -m "feat(main): verify solo team founder signup checkout happy paths"
```

---

## Plan Review Checklist (for reviewer subagent)

- [ ] No TODO/TBD placeholders remain.
- [ ] Every task includes explicit files, commands, and expected outcomes.
- [ ] Plan aligns exactly with approved spec scope (happy paths only).
- [ ] New/modified files keep single responsibilities and manageable size.
- [ ] All execution steps use checkbox syntax.
