Specify a webhook-driven task for OpenClaw
Describe event inputs, validation, deduplication, and intended actions before integration work.
5,179,176 AI resources indexedWorking toward the world’s largest AI resource index.
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.
---
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
---
# 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
---
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
---
# 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
Imported from the listed AgentSkill.sh category. Complete supplied package files and notices are retained. Includes source scripts; review them before use. Required external tools and credentials are not installed. No bundled code was executed during import. Individual agent task behavior has not been tested.