plugins/stripe-billing-master/skills/stripe-refund-dispute-lifecycle/SKILL.md
Complete Stripe refund and dispute lifecycle handling. PROACTIVELY activate for: (1) charge.refunded handler design, (2) charge.dispute.created / charge.dispute.closed handlers, (3) Refund delta computation from event.data.previous_attributes.amount_refunded, (4) Dispute-hold past_due status management, (5) shouldRestoreStatus predicate with satisfies Record<Stripe.Dispute.Status, boolean>, (6) Credit-pack vs subscription refund differentiation, (7) Checkout Session lookup for refund proportion math, (8) Allowlist default-deny for external enums, (9) stripe.checkout.sessions.list({payment_intent}) pattern, (10) Dispute outcome branch logic (won / lost / warning_closed / prevented). Provides: full handler patterns for all three events, predicate examples, credit-pack vs subscription math, exhaustive switch patterns.
npx skillsauth add JosiahSiegel/claude-plugin-marketplace stripe-refund-dispute-lifecycleInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
| Event | Action | Key rule |
|--|--|--|
| charge.refunded | Revoke credits proportional to refund delta | G2 — previous_attributes.amount_refunded |
| charge.dispute.created | Set user past_due + store checkpoint | G1 + G9 |
| charge.dispute.closed | won / warning_closed / prevented -> restore; lost -> no-op (charge.refunded handles); else -> no-op | G5 + G7 |
| Refund source priority | When to use |
|--|--|
| event.data.previous_attributes.amount_refunded (G2) | Primary — always prefer |
| charge.refunds.data (sorted by created desc) | Fallback when previous_attributes absent |
| stripe.refunds.list({charge, limit:1}) | Last resort when embedded missing |
| charge.amount_refunded alone | NEVER (cumulative, not per-event) |
Use when implementing any handler that revokes credits or mutates a paid-status column in response to Stripe refund or dispute events.
Related skills:
getRefundDelta (the G2 delta helper): stripe-billing-master:stripe-list-pagination-previous-attributesstripe-billing-master:stripe-credit-audit-trailstripe-billing-master:stripe-webhook-idempotencyUse getRefundDelta() from stripe-billing-master:stripe-list-pagination-previous-attributes — that skill owns the delta-computation helper. Key guarantee: the helper returns null when no source is available, and the handler MUST skip revocation rather than guess.
shouldRestoreStatusconst shouldRestoreMap = {
won: true,
warning_closed: true,
prevented: true,
lost: false,
needs_response: false,
under_review: false,
warning_needs_response: false,
warning_under_review: false,
charge_refunded: false,
} satisfies Record<Stripe.Dispute.Status, boolean>;
export const shouldRestoreStatus = (s: Stripe.Dispute.Status): boolean => shouldRestoreMap[s];
When Stripe adds a new status in a future SDK version, this object is a compile error until you add the key — forcing a conscious G5 allowlist decision.
async function resolveCreditsToRevoke(charge: Stripe.Charge, refundAmount: number) {
const sessions = await stripe.checkout.sessions.list({
payment_intent: charge.payment_intent as string,
limit: 1,
expand: ["data.line_items"],
});
const session = sessions.data[0];
if (session?.mode !== "subscription") {
const pack = CREDIT_PACKS.find(p => session?.line_items?.data?.[0]?.price?.id === p.priceId);
if (pack && session.amount_total && session.amount_total > 0) {
// Proportional revocation: if they refunded 50% of the pack, revoke 50% of the credits
return Math.round(pack.credits * (refundAmount / session.amount_total));
}
}
// Subscription: 1 credit = 1 cent at cash-equivalent
return refundAmount;
}
Notes on the credit-pack math: proportional revocation matters because packs are bulk-priced (e.g., 1000 credits for $9 instead of $10) — a flat refundAmount -> credits conversion over-revokes. Always look up the originating Checkout Session to distinguish mode: "subscription" (cash-equivalent) from mode: "payment" with a known pack price ID (proportional).
development
Use for Clerk sessions, tokens, webhooks, orgs, and security. PROACTIVELY activate for session tokens, JWT templates, getToken(), custom claims, pending sessions, multi-session UX, organizations, roles, permissions, system vs custom permissions, features/plans, MFA/passkeys/password policy/bot protection, Clerk webhooks, Svix signatures, verifyWebhook(), user/org sync, retries/replays, environment variables, custom domains, secret rotation, logs, and auth security reviews. Provides token semantics, webhook idempotency, authorization defaults, and hardening checklist.
tools
Use for Clerk in Next.js. PROACTIVELY activate for @clerk/nextjs setup, App Router auth()/currentUser(), clerkMiddleware(), proxy.ts/middleware.ts, createRouteMatcher(), protected pages/layouts/Route Handlers/Server Actions/API routes/tRPC, auth.protect() role/permission/token checks, ClerkProvider placement, server-only clerkClient, Link prefetch, redirects, 401/404 auth failures, custom domains, __clerk proxy paths, and deployment gotchas. Provides file patterns, server/client boundary rules, matcher templates, and production checks.
development
Use for Clerk frontend auth flows. PROACTIVELY activate for React, JavaScript, Vue, Nuxt, Astro, Expo, React Router, TanStack React Start, or SPA setup; ClerkProvider and publishable-key wiring; SignIn/SignUp/UserButton/UserProfile/OrganizationSwitcher; custom useUser/useAuth/useClerk/useSignIn/useSignUp/useSession/useOrganization flows; multi-session UX; cross-origin getToken() fetches; loading states, redirects, routing, CORS/cookies, or hydration bugs. Provides SDK selection, UI patterns, token-fetch templates, and frontend gotchas.
development
Use for Clerk dev/prod readiness, deployment, and multi-language implementation planning. PROACTIVELY activate for environment variables, pk_test/sk_test vs pk_live/sk_live, local dev, preview/staging/prod instances, domains/DNS, redirects, OAuth credentials, custom domains/proxy, authorizedParties, CSP, CORS/cookies, webhooks/tunnels, Vercel/Netlify/Cloudflare/API gateways, monitoring/troubleshooting, and backends in Node/Express/Fastify, Python/FastAPI/Django/Flask, Go, Ruby/Rails, Java/Spring, .NET, PHP/Laravel. Provides checklists, rollout plans, and language-portable patterns.