SpawnForge Stripe webhook patterns — idempotent refunds, CTE atomic claims, neonSql transaction ordering, token billing. Auto-loads when editing billing code.
Instal·la
npx skillscat add tristan578/project-forge/claude-skills-stripe-webhooks Instal·la des del registre de SkillsCat.
SKILL.md
Stripe Webhook Patterns — SpawnForge
Critical patterns (from real bugs)
1. Atomic CTE claim for refunds (PF-7514)
Never read refundedCents in JS then update in a separate query. Use a single CTE:
WITH old AS (SELECT id, refunded_cents, tokens, amount_cents FROM token_purchases WHERE id = $1)
UPDATE token_purchases SET refunded_cents = $2 FROM old
WHERE token_purchases.id = $1 AND old.refunded_cents < $2
RETURNING old.tokens, old.amount_cents, ($2 - old.refunded_cents) AS increment_centsIf 0 rows returned → concurrent request already claimed. Return immediately.
2. neonSql transaction ordering
INSERT audit record BEFORE UPDATE user balance — PostgreSQL sees prior statements' effects within neonSql.transaction([...]).
3. Idempotent refundTokens
Check metadata->>'refundedUsageId' before crediting. Without this, server + client both refunding the same failed job doubles credits.
4. Never use db.transaction()
neon-http driver throws. Use getNeonSql() → neonSql.transaction([...statements]).
References
web/src/app/api/stripe/webhook/route.ts— the live webhook handler implementing the patterns aboveweb/src/lib/tokens/service.ts—refundTokens()idempotency + balance deduction- Stripe API version is pinned to
2026-08-26.dahliainweb/src/lib/billing/stripe-client.ts(must match the installed SDK)