# Invited User Billing Upgrade 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:** Let invited temporary users start Stripe checkout for Solo, Team, or Founder plans and automatically convert them into full users once a paid subscription is synced.

**Architecture:** Keep the existing temporary-user read-only model for normal product actions, but carve out a narrow billing exception for Stripe checkout creation. Complete the upgrade on the server-side subscription sync path so promotion to a full account happens only after Stripe-backed paid state exists.

**Tech Stack:** Hono, Vitest, Supabase Postgres migrations/tests, React/Vitest

---

## Chunk 1: Billing Access Gate

### Task 1: Add failing API coverage for temporary-user billing checkout access

**Files:**
- Modify: `apps/api/src/__tests__/middlewares/middlewares.test.ts`
- Modify: `apps/api/src/middlewares/middleware.ts`

- [ ] **Step 1: Write the failing test**

Add coverage proving a temporary user is still rejected by `regularUserCheck`, while a new billing-specific check allows temporary users through.

- [ ] **Step 2: Run test to verify it fails**

Run: `pnpm --filter @xtablo/api test -- middlewares`
Expected: FAIL because no billing-safe middleware exists yet.

- [ ] **Step 3: Write minimal implementation**

Add a focused middleware/getter that authenticates the user and confirms the profile exists, but does not reject `is_temporary`.

- [ ] **Step 4: Run test to verify it passes**

Run: `pnpm --filter @xtablo/api test -- middlewares`
Expected: PASS

## Chunk 2: Stripe Checkout Route

### Task 2: Add failing route coverage for temporary invited checkout

**Files:**
- Modify: `apps/api/src/__tests__/routes/stripe.test.ts`
- Modify: `apps/api/src/routers/stripe.ts`

- [ ] **Step 1: Write the failing test**

Add route-level coverage that the checkout route uses the billing-safe middleware while portal/cancel/reactivate remain on the regular user path.

- [ ] **Step 2: Run test to verify it fails**

Run: `pnpm --filter @xtablo/api test -- stripe`
Expected: FAIL because checkout still uses `regularUserCheck`.

- [ ] **Step 3: Write minimal implementation**

Switch only `create-checkout-session` to the billing-safe middleware and preserve existing billing-owner enforcement inside the route.

- [ ] **Step 4: Run test to verify it passes**

Run: `pnpm --filter @xtablo/api test -- stripe`
Expected: PASS

## Chunk 3: Post-Payment Promotion

### Task 3: Add failing database coverage for paid subscription promotion

**Files:**
- Modify: `supabase/tests/database/05_triggers.test.sql`
- Create: `supabase/migrations/20260324120000_promote_paid_temporary_users.sql`

- [ ] **Step 1: Write the failing test**

Add a trigger test that creates a temporary profile plus Stripe customer/subscription records, fires `update_profile_subscription_status`, and expects `is_temporary = false` once the paid subscription is present.

- [ ] **Step 2: Run test to verify it fails**

Run: `pnpm test -- --filter` if a repo wrapper exists, otherwise run the project’s Supabase database test command used by the team.
Expected: FAIL because the trigger only updates `plan` today.

- [ ] **Step 3: Write minimal implementation**

Create a migration that updates `public.update_profile_subscription_status()` to clear `is_temporary` whenever a paid plan is inferred.

- [ ] **Step 4: Run test to verify it passes**

Run the same Supabase database trigger test command.
Expected: PASS

## Chunk 4: Frontend Safety Net

### Task 4: Verify no UI regression for pending signup checkout behavior

**Files:**
- Modify: `apps/main/src/components/PendingSignupCheckout.test.tsx` (only if needed)
- Modify: `apps/main/src/pages/settings.test.tsx` (only if needed)

- [ ] **Step 1: Add or adjust failing test only if the UI has an explicit temporary-user block**

If implementation reveals a frontend gate, add a focused failing test for it.

- [ ] **Step 2: Run targeted frontend test**

Run: `pnpm --filter @xtablo/main test -- PendingSignupCheckout`
Expected: FAIL only if a frontend gate exists.

- [ ] **Step 3: Implement the minimal UI change**

Only patch the exact gate if one is discovered; otherwise leave frontend logic unchanged.

- [ ] **Step 4: Re-run targeted frontend tests**

Run: `pnpm --filter @xtablo/main test -- PendingSignupCheckout`
Expected: PASS

## Chunk 5: Verification

### Task 5: Verify end-to-end relevant coverage

**Files:**
- Modify: none unless verification exposes a bug

- [ ] **Step 1: Run API targeted tests**

Run: `pnpm --filter @xtablo/api test -- middlewares stripe`
Expected: PASS

- [ ] **Step 2: Run frontend targeted tests**

Run: `pnpm --filter @xtablo/main test -- PendingSignupCheckout settings`
Expected: PASS

- [ ] **Step 3: Run the database trigger tests**

Run the project’s Supabase trigger test command for `supabase/tests/database/05_triggers.test.sql`.
Expected: PASS

- [ ] **Step 4: Review changed files and summarize remaining risk**

Confirm the only intentional behavior change is: temporary invited billing owners can start checkout, and paid checkout promotion clears read-only status.
