# Billing Setup Guide

This guide covers how to configure Stripe billing and local user sign-up in DocuElevate.

## Table of Contents

- [Local User Sign-up](#local-user-sign-up)
- [Stripe Billing Integration](#stripe-billing-integration)
  - [Prerequisites](#prerequisites)
  - [Configuration](#configuration)
  - [Stripe Setup Wizard (recommended)](#stripe-setup-wizard-recommended)
  - [Setting Up Plans Manually](#setting-up-plans-manually)
  - [Webhook Configuration](#webhook-configuration)
  - [Billing Flows](#billing-flows)
- [Compliance Notes](#compliance-notes)

---

## Local User Sign-up

By default, user accounts are created by an administrator. To allow users to self-register with an email address and password, set `ALLOW_LOCAL_SIGNUP=true`.

> **Note:** SMTP is **optional** for local sign-up. When SMTP is configured, new accounts require email verification before they can log in. Without SMTP, accounts are activated immediately upon registration — useful for self-hosted deployments without email infrastructure.

### Configuration

```bash
ALLOW_LOCAL_SIGNUP=true

# SMTP (optional — enables email verification and password reset)
EMAIL_HOST=smtp.example.com
EMAIL_PORT=587
EMAIL_USERNAME=noreply@example.com
EMAIL_PASSWORD=yourpassword
EMAIL_USE_TLS=true
EMAIL_SENDER=DocuElevate <noreply@example.com>
```

### Sign-up Flow

**With SMTP configured (recommended):**
1. User visits `/signup` and fills out the registration form.
2. DocuElevate sends a verification email with a 24-hour token link.
3. User clicks the link — their account is activated and they are signed in.
4. First-time users are redirected to the onboarding wizard.

**Without SMTP:**
1. User visits `/signup` and fills out the registration form.
2. Account is activated immediately — no email verification required.
3. User is redirected to the login page to sign in straight away.

### Admin-Created Accounts

Administrators can create local user accounts directly from the **Admin → User Management** page without requiring self-registration. Admin-created accounts are immediately active regardless of SMTP configuration.

### Password Reset Flow

1. User clicks "Forgot password?" on the login page.
2. User enters their email address.
3. DocuElevate sends a password reset email with a 24-hour token link.
4. User clicks the link, enters a new password, and is redirected to sign in.

### Security

- Passwords are hashed with bcrypt (12 rounds).
- Verification and reset tokens are 256-bit URL-safe random strings.
- All tokens expire after 24 hours.
- Sign-up and login endpoints return generic error messages to prevent user enumeration.

---

## Stripe Billing Integration

DocuElevate integrates with [Stripe](https://stripe.com) to handle subscription payments. Stripe acts as a data processor under a Data Processing Agreement (DPA) and is SOC 2 Type II certified.

### Prerequisites

- A Stripe account (sign up at [stripe.com](https://stripe.com))
- A publicly reachable webhook endpoint (or use [Stripe CLI](https://stripe.com/docs/stripe-cli) for local testing)

### Configuration

```bash
STRIPE_SECRET_KEY=sk_live_...         # Your Stripe secret key
STRIPE_PUBLISHABLE_KEY=pk_live_...    # Your Stripe publishable key (for frontend)
STRIPE_WEBHOOK_SECRET=whsec_...       # Webhook signing secret
STRIPE_SUCCESS_URL=https://app.example.com/api/billing/success  # Optional override
STRIPE_CANCEL_URL=https://app.example.com/pricing               # Optional override
```

> **Security:** Never commit your Stripe secret key. Store it in your environment or secrets manager.

### Stripe Setup Wizard (recommended)

DocuElevate includes a built-in **Stripe Setup Wizard** at `/admin/stripe-wizard` that guides you through the complete setup in three steps:

1. **Verify API Keys** — checks that your Stripe secret key is configured and the connection to Stripe is working.
2. **Sync Plans to Stripe** — automatically creates Stripe **Products** and **Prices** for every paid plan defined in DocuElevate, then stores the resulting `price_id` values back in the database. Free plans are skipped; plans that already have a price ID are left unchanged.
3. **Configure Webhook** — shows the exact webhook endpoint URL to register in the Stripe Dashboard and which events to subscribe to.

You can also reach the wizard from the **Admin → Plans** page via the **Stripe Setup** button.

#### Auto-sync API

The sync step is also available as an API endpoint for automation:

```bash
curl -X POST https://your-app.example.com/api/billing/stripe/sync-plans \
  -H "Cookie: <admin-session-cookie>"
```

Response:

```json
{
  "results": [
    {
      "plan_id": "starter",
      "name": "Starter",
      "status": "created",
      "stripe_price_id_monthly": "price_1OtAbc...",
      "stripe_price_id_yearly": "price_1OtDef..."
    },
    {
      "plan_id": "free",
      "name": "Free",
      "status": "skipped_free"
    }
  ]
}
```

Possible `status` values:

| Status | Meaning |
|--------|---------|
| `created` | Stripe product and price(s) were created and saved |
| `already_synced` | Plan already had a price ID — no changes made |
| `skipped_free` | Free plan (price is $0) — no Stripe price needed |
| `error` | Stripe API call failed — `detail` contains the error message |

#### Stripe connection status API

```bash
curl https://your-app.example.com/api/billing/stripe/status
```

Returns connection health, API mode (test/live), webhook secret status, and per-plan sync status.

### Setting Up Plans Manually

If you prefer to enter price IDs yourself rather than using the wizard:

1. Create **Products** and **Prices** in the [Stripe Dashboard](https://dashboard.stripe.com/products).
2. Go to **Admin → Plans** in DocuElevate and click the **Edit** (pencil) button for a paid plan.
3. Scroll to the **Stripe Integration** section in the plan editor.
4. Enter the **Stripe Price ID (monthly)** (e.g. `price_1OtAbc...`).
5. Optionally enter the **Stripe Price ID (yearly)** for annual billing.
6. Save the plan.

> **Stable link:** DocuElevate stores the Stripe `customer_id` in the `UserProfile.stripe_customer_id` column and matches it on every webhook event. This is the stable link between Stripe billing profiles and DocuElevate accounts. It is set automatically when a user completes their first checkout.

### Webhook Configuration

Stripe webhooks allow DocuElevate to sync subscription status in real time.

#### Stripe Dashboard setup

1. Go to **Developers → Webhooks** in the Stripe Dashboard.
2. Click **Add endpoint**.
3. Set the endpoint URL to: `https://your-app-domain.com/api/billing/webhook`
   (The Stripe Setup Wizard shows the exact URL for your deployment.)
4. Select the following events:
   - `checkout.session.completed`
   - `customer.subscription.updated`
   - `customer.subscription.deleted`
   - `invoice.payment_failed`
5. Copy the **Signing secret** and set `STRIPE_WEBHOOK_SECRET` in your environment.

#### Local testing with Stripe CLI

```bash
# Install Stripe CLI and log in
stripe login

# Forward webhooks to your local server
stripe listen --forward-to http://localhost:8000/api/billing/webhook

# Trigger test events
stripe trigger checkout.session.completed
stripe trigger customer.subscription.updated
stripe trigger customer.subscription.deleted
```

### Billing Flows

#### Subscribe to a plan

1. User visits `/pricing`.
2. User clicks the **CTA button** on a paid plan.
3. DocuElevate calls `POST /api/billing/create-checkout-session`.
4. User is redirected to Stripe Checkout.
5. After payment, Stripe fires `checkout.session.completed`.
6. DocuElevate webhook handler activates the subscription tier and stores the Stripe `customer_id`.
7. User is redirected to `/api/billing/success`.

#### Manage or cancel subscription

1. User visits their account settings.
2. DocuElevate calls `POST /api/billing/create-portal-session`.
3. User is redirected to the Stripe Customer Portal.
4. User can update payment method, upgrade, downgrade, or cancel.
5. Stripe fires `customer.subscription.updated` or `customer.subscription.deleted`.
6. DocuElevate webhook handler syncs the change.

#### Cancellation

When a subscription is cancelled, Stripe fires `customer.subscription.deleted` and DocuElevate automatically downgrades the user to the free tier.

---

## Compliance Notes

| Topic | Details |
|-------|---------|
| **GDPR** | Stripe acts as a data processor. A Data Processing Agreement (DPA) is available in the Stripe Dashboard. Stripe supports EU data residency. |
| **SOC 2** | Stripe is SOC 2 Type II certified. |
| **EU VAT** | Configure [Stripe Tax](https://stripe.com/tax) in the Stripe Dashboard for automatic VAT collection. |
| **PCI DSS** | Card data is handled entirely by Stripe. DocuElevate never sees or stores card details. |

---

## Environment Variable Reference

| Variable | Type | Default | Description |
|----------|------|---------|-------------|
| `ALLOW_LOCAL_SIGNUP` | bool | `false` | Allow users to self-register with email/password |
| `STRIPE_SECRET_KEY` | string | — | Stripe API secret key |
| `STRIPE_PUBLISHABLE_KEY` | string | — | Stripe API publishable key |
| `STRIPE_WEBHOOK_SECRET` | string | — | Webhook signing secret from Stripe Dashboard |
| `STRIPE_SUCCESS_URL` | string | — | Override redirect URL after successful checkout |
| `STRIPE_CANCEL_URL` | string | — | Override redirect URL when checkout is cancelled |

See [ConfigurationGuide.md](./ConfigurationGuide.md) for the full environment variable reference.
