home / skills / phrazzld / claude-config / billing-security

billing-security skill

/skills/billing-security

This skill helps you secure Stripe and Clerk integrations by validating env vars, webhook URLs, and cross-deployment parity before production.

npx playbooks add skill phrazzld/claude-config --skill billing-security

Review the files below or copy the command above to add this skill to your agents.

Files (7)
SKILL.md
3.7 KB
---
name: billing-security
description: |
  Apply billing and security best practices for payment/auth integrations.
  Invoke when: setting up Stripe/Clerk/auth, debugging payment issues,
  configuring webhooks, before prod deployment, after billing incidents.
keywords:
  - stripe
  - payment
  - webhook
  - billing
  - checkout
  - subscription
  - customer_creation
  - webhook_secret
effort: max
---

# Billing & Security Integration Patterns

> "Configuration is not reality. Verification must be active, not passive."

This skill codifies lessons from 3 prod incidents (chrondle, bibliomnomnom, volume) where Stripe integrations failed despite passing code review.

## Core Principle

**Code reviews catch code bugs, not configuration bugs.** External service integrations require:
1. Format validation (API key patterns, URL formats)
2. Reachability verification (can we actually reach the webhook URL?)
3. Cross-deployment parity (Vercel and Convex must have same config)
4. Runtime reconciliation (compare external state vs database state)

---

## Critical Patterns

### 1. Environment Variable Hygiene

**Always trim env vars:**
```typescript
// WRONG - trailing whitespace causes "Invalid character in header"
const key = process.env.STRIPE_SECRET_KEY;

// RIGHT - always trim
const key = process.env.STRIPE_SECRET_KEY?.trim();
```

**Validate format before use:**
```typescript
const STRIPE_KEY_PATTERN = /^sk_(test|live)_[a-zA-Z0-9]+$/;
if (!STRIPE_KEY_PATTERN.test(key)) {
  throw new Error("Invalid STRIPE_SECRET_KEY format");
}
```

### 2. Webhook URL Validation

**Stripe does NOT follow redirects for POST requests.** If your webhook URL returns 3xx, webhooks silently fail.

```bash
# Check for redirects BEFORE configuring webhook
curl -s -o /dev/null -w "%{http_code}" -I -X POST "https://your-domain.com/api/webhooks/stripe"
# Must return 4xx or 5xx, NOT 3xx
```

**Use canonical domain:**
- If `example.com` redirects to `www.example.com`, configure webhook for `www.example.com`

### 3. Cross-Deployment Parity

When using Vercel + Convex (or similar split architectures):
- Env vars must be set on BOTH platforms
- Use `--prod` flag: `npx convex env set --prod KEY value`
- Verify parity: compare `vercel env ls` with `npx convex env list --prod`

### 4. Stripe Parameter Constraints

**Mode-dependent parameters:**
| Parameter | Valid Modes | Invalid Modes |
|-----------|-------------|---------------|
| `customer_creation` | payment, setup | subscription |
| `subscription_data` | subscription | payment, setup |

**Common trap:** Using `customer_creation: "always"` in subscription mode throws an error at checkout time, not at compile time.

---

## Pre-Deployment Checklist

Before deploying any billing integration:

- [ ] All env vars trimmed at read time
- [ ] API key formats validated
- [ ] Webhook URL returns non-3xx status
- [ ] Vercel and Convex have matching config
- [ ] Signature verification enabled
- [ ] Error handling returns 200 (prevent Stripe infinite retries)

---

## Debugging Workflow (OODA-V)

When billing integration fails:

1. **Observe** - Check if request reaches server (look for logs)
2. **Orient** - If no logs, it is network/redirect, not code
3. **Decide** - Run `curl -I` on webhook URL
4. **Act** - Fix configuration
5. **Verify** - Resend event, watch `pending_webhooks` decrease

---

## References

- [Stripe Constraints](references/stripe-constraints.md) - API parameter rules
- [Env Var Hygiene](references/env-var-hygiene.md) - Validation patterns
- [Incident Patterns](references/incident-patterns.md) - Real failures from 3 projects

## Scripts

- `scripts/verify-webhook-url.sh <url>` - Check for redirects
- `scripts/verify-env-parity.sh` - Compare Vercel/Convex config
- `scripts/audit-stripe-config.py` - Full Stripe diagnostic

Overview

This skill applies billing and security best practices for payment and auth integrations, focusing on Stripe, Clerk, and similar services. It codifies production-proven checks and workflows to catch configuration and runtime mismatches that code review alone misses. Use it to validate keys, webhooks, cross-deployment parity, and to run a repeatable debugging flow before and after incidents.

How this skill works

The skill runs automated validations and runtime inspections: format checks for API keys and env vars, HTTP checks for webhook reachability and redirects, parity comparisons across deployment platforms, and runtime reconciliation between external service state and the application database. It also guides a concise OODA-style debugging workflow and includes scripts for quick diagnostics.

When to use it

  • Setting up Stripe, Clerk, or third-party auth/payment providers
  • Configuring or updating webhook endpoints before production
  • Verifying environment variables across multiple deployment targets
  • Debugging payment or webhook delivery failures after an incident
  • Doing a pre-deployment checklist for billing-related releases

Best practices

  • Trim environment variables at read time and validate key patterns before use
  • Verify webhook URLs do not return 3xx redirects; Stripe ignores POST redirects
  • Enable signature verification and ensure error handling returns 200 to avoid infinite retries
  • Keep environment variables in sync across all deployment platforms (e.g., Vercel and Convex)
  • Validate mode-dependent API parameters (e.g., customer_creation vs subscription_data) at runtime and CI

Example use cases

  • Run a webhook URL check script that fails CI if the endpoint redirects
  • Automate env var parity check between Vercel and Convex during deploy
  • Validate Stripe secret keys format with a regex before starting the server
  • Follow OODA-V debugging steps to find why a webhook never reached the app
  • Audit Stripe configuration after a billing incident and reconcile with DB state

FAQ

Why trim env vars?

Trailing whitespace can corrupt headers or keys; trimming at read time prevents hard-to-detect errors.

How do I detect webhook redirect problems?

Run an HTTP POST or HEAD check (curl -I -X POST) and ensure the status is not 3xx; configure the webhook to the canonical domain.