Stripe Expert — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Stripe Expert (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Billing bugs are the most expensive class of bug: an unverified webhook is an open door to fake "payment succeeded" events, a non-idempotent handler double-provisions on Stripe's at-least-once delivery, and state inferred from a client redirect grants free access to anyone who can type a URL. This skill wires Stripe so money moves correctly and your database never disagrees with Stripe about who has paid.
Stripe is the source of truth for billing state. Your database is a mirror, updated only by verified webhooks. Never grant access from a client-side success callback or redirect - the redirect can be spoofed, dropped, or replayed; the webhook cannot.
stripe_customer_id column? One Stripe customer per user, created lazily on first purchase.past_due before access is cut? Default: 7 days with email notices.const session = await stripe.checkout.sessions.create({
mode: 'subscription',
line_items: [{ price: priceId, quantity: 1 }], // resolved server-side
success_url: `${base}/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${base}/pricing`,
customer: stripeCustomerId,
}, { idempotencyKey: `checkout:${userId}:${planId}` });Pass an Idempotency-Key on every create request (sessions, charges, customers) so a network retry cannot create two of anything.
Every item is mandatory; each one missing is a specific production incident.
stripe.webhooks.constructEvent(rawBody, sig, endpointSecret) - reject with 400 on failure. Skipping this lets anyone POST fake payment events.express.json()) mutates bytes and breaks the signature - exempt the webhook route.event.ids (unique-constrained table) and skip duplicates. Stripe delivers at-least-once; without this, a redelivery double-provisions.checkout.session.completed, customer.subscription.updated, customer.subscription.deleted, invoice.payment_failed.On each subscription event, upsert one row per user: stripe_customer_id, stripe_subscription_id, status, current_period_end, price_id. The access gate reads this row only. States to gate on: active and trialing get access; past_due gets the grace window from Step 1; canceled and unpaid do not.
invoice.payment_failed: start dunning - notify the user, keep access through the grace window, cut on expiry or subscription.deleted.StripeCardError and surface a friendly message. Retry only transient errors (network, 5xx, rate limit); never auto-retry a card decline - that is card-testing behavior and triggers fraud flags.requires_action by completing authentication client-side. Checkout handles this for you - one more reason to prefer it.proration_behavior) and communicate the resulting invoice line to the user before confirming.customer.subscription.trial_will_end (fires 3 days before) to warn the user before the first charge.Run stripe listen --forward-to localhost:PORT/webhook and use test-mode keys. Verify with stripe trigger: successful checkout, duplicate event delivery (handler must no-op the second), payment failure, and cancellation. A webhook path that has never seen a replayed event in test will double-provision in production.
Bad - grants access from the redirect:
// success page handler
app.get('/success', async (req, res) => {
await db.user.update({ where: { id: req.user.id }, data: { plan: 'pro' } }); // spoofable
res.render('success');
});Good - grants access from the verified, idempotent webhook:
app.post('/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
let event;
try {
event = stripe.webhooks.constructEvent(req.body, req.headers['stripe-signature'], endpointSecret);
} catch { return res.status(400).send('bad signature'); }
const inserted = await db.processedEvents.insertIgnoreDuplicate({ id: event.id });
if (!inserted) return res.sendStatus(200); // already handled
if (event.type === 'checkout.session.completed') {
await queue.enqueue('activate-subscription', event.data.object);
}
res.sendStatus(200);
});Produce a working integration containing: the server-side Checkout Session endpoint with idempotency keys; a webhook handler passing every item on the Step 3 checklist; the mirrored subscription table and the single access-gate read path; the dunning policy wired to invoice.payment_failed; and a test log showing duplicate-delivery and failure events handled correctly via the Stripe CLI.
stripe listen test log covers success, duplicate, failure, and cancellation.This skill covers integration mechanics, not pricing strategy - route tier and packaging questions to saas-pricing. Tax registration, revenue recognition, and regulated money-movement (marketplaces holding funds, Connect platform liability) warrant a payments-savvy accountant or lawyer, not just Stripe defaults.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.