proration-guard
Skill0 starsChanged 4 months agoMITView on GitHub
Reviews a subscription plan-change code path (upgrade, downgrade, cancel, reactivate) for billing-correctness bugs that look like normal operation — proration math that contradicts the plan's own documented cancellation/change policy, a credit/coupon/voucher redemption that silently triggers a plan change or a duplicate invoice, and a second plan-change request racing or stacking with one still in flight or already scheduled. Use when asked "does our proration math add up", "why did this customer get double-charged on upgrade", "what happens if they downgrade twice before the first change takes effect", "does canceling actually stop billing them", when adding or reviewing an upgrade/downgrade/cancel/reactivate handler, or after a support ticket about a wrong subscription charge.
In this repository46 other files it gives its agents.
- atomic-ioSkill
- backfill-pilotSkill
- backpressure-guardSkill
- blast-guardSkill
- changelogSkill
- cipher-guardSkill
- clipboard-guardSkill
- clock-sweepSkill
- codebase-tourSkill
- consent-guardSkill
- devlogSkill
- dormancy-guardSkill
- env-detectiveSkill
- erasure-guardSkill
- export-guardSkill
- failover-guardSkill
- git-rescueSkill
- import-guardSkill
- job-wardenSkill
- migration-guardSkill
- overwrite-guardSkill
- pagination-guardSkill
- portability-auditSkill
- pref-guardSkill
- push-guardSkill
- quote-guardSkill
- reaccept-guardSkill
- readme-forgeSkill
- recall-guardSkill
- residency-guardSkill
- restore-guardSkill
- resync-guardSkill
- rollout-guardSkill
- rotation-guardSkill
- seat-guardSkill
- secret-spillSkill
- security-sweepSkill
- selectall-guardSkill
- ship-itSkill
- skew-checkSkill
- stale-guardSkill
- storm-guardSkill
- sunset-guardSkill
- throttle-guardSkill
- tombstoneSkill
- trail-guardSkill
The file
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 2 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 37
Not an FX/currency-conversion review — rate-lock timing and multi-currency snapshot freezing are a different, already-covered failure class.
- Distinctive: line 38
Not a payment-webhook reliability review — signature verification, delivery retries, and event-ordering are a separate concern from whether …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
proration-guard
Proration code is easy to unit-test wrong in a way that still looks right: feed it a plan, a date, and a price, and it returns a number. What that testing style misses is whether the number matches what the business promised, and whether the plan-change machinery around it stays correct once a second event — a coupon, a race, a scheduled change — lands on top of the first. Two real, independently verified bugs show both failure modes. Kill Bill's END_OF_TERM cancellation policy is documented to cancel "in such a way that we do not generate credit for the account (no proration)" — but the account-level CANCELLATION state actually cancels immediately and generates prorated credit anyway (Kill Bill issue #698): the proration math itself may be arithmetically fine, it's just running on a path the docs promised it wouldn't. Separately, anthropics/claude-code issue #51168 reports a Pro Annual subscriber redeeming a promotional credit voucher and getting a silent plan downgrade (Pro Annual → Max monthly) plus a cascade of unauthorized duplicate invoices for gift-subscription products — not a proration-formula bug at all, but a credit-redemption path that reached into plan-change state it had no business touching. Both bugs shipped, both passed whatever tests existed, and both are invisible from inside the proration function itself.
Step 1: map every path that can change a subscription's plan or billing period
Start broader than the upgrade/downgrade buttons in the UI. List every code path that can mutate a subscription's plan, price, or period boundary: the customer-facing upgrade/downgrade flow, cancel and reactivate, an admin override or manual comp, a scheduled/deferred change that applies later (a downgrade queued for period end), a coupon or credit redemption that changes plan as a side effect, trial-to-paid conversion, and any webhook handler that reacts to a payment-provider event by writing plan state locally. Treat each one as a separate finding target — a proration bug in the main upgrade handler and a separate, unrelated one in the admin-comp path are two bugs, not one.
Step 2: check the proration math against the plan's own documented policy, not just against arithmetic correctness
A largest-remainder or day-fraction calculation can be internally consistent and still be the wrong calculation for what this specific plan promises. For every path found in Step 1, confirm:
- Does the actual behavior match the documented cancellation/change policy? If pricing/terms say a downgrade takes effect at period end with no credit, does the code path actually wait — or does some other code path (an admin action, a different entry point into the same subscription) prorate and refund immediately, contradicting it? This is the exact Kill Bill shape: the bug isn't in the math, it's in which policy the math thinks it's running under.
- Is the credit computed against the correct period boundary? A credit for "unused time" needs the current paid period's start and end, not "now" relative to signup date or a hardcoded 30 days — a plan on a non-monthly billing cycle (annual, custom trial extension) will silently miscompute against the wrong window.
- Do overlapping periods get double-counted or dropped? A plan change mid-cycle should account for exactly one period once — check that the old plan's remaining time and the new plan's starting time don't both get billed for the same days, and that a change applied twice (see Step 4) doesn't compound the credit or the charge.
Step 3: check what happens when a credit, coupon, or voucher redemption crosses paths with a plan change
This is the claude-code #51168 shape, and it's easy to miss because the redemption code and the plan-change code are usually written by different people at different times, each reasonably assuming the other doesn't touch their state. Trace what a credit/coupon/voucher-application handler actually does to the subscription record: does it only add a balance or apply a discount, or can it also write to the plan/tier field, trigger a webhook that a different handler interprets as a plan change, or create a second invoice alongside (rather than instead of) the one already scheduled? A voucher meant to apply a discount to the current plan has no business ever writing a different plan ID — if it can, trace exactly how, because that's the bug, not a hypothetical.
Step 4: check what happens when a second plan-change request arrives before the first is finished or takes effect
Plan changes are rarely instantaneous in the customer's mental model — a downgrade scheduled for period end is a promise about the future, not a completed action. Check what the code actually does when: a second upgrade or downgrade request arrives while an earlier one is still scheduled (does it replace the scheduled change, stack with it, or silently no-op?); the same request is double-submitted (a slow network retry, a double click) — is it idempotent, or does it create two scheduled changes or two proration credits for the same transition; and a plan change and a cancellation are requested in quick succession — does canceling actually void a still-pending scheduled change, or can the change apply after the account is supposed to be cancelled because the two are tracked independently.
Report
Lead with any case where the documented policy and the actual behavior diverge (Step 2's first bullet) — that's the highest-trust-cost bug, since it means the terms a customer or a support agent relies on are wrong about what the code does. BLOCK for: proration/credit behavior that contradicts the documented cancellation or change policy; a credit/coupon/voucher path that can write plan state or create an extra invoice; or a double-submit/race on a plan-change request that isn't idempotent. CAUTION for a period-boundary computation that's correct today but fragile (hardcoded interval assumptions that break the moment a non-standard billing cycle is added) or a scheduled-change/cancel interaction that's untested rather than confirmed wrong. Cite the exact function and the exact period/date values used, since "proration looks about right" is not a finding — either the boundary and policy match what's documented, or they don't.
Boundaries
- Not
financial-integrity-style decimal/rounding review — this skill assumes the arithmetic primitives (cents,Decimal, largest-remainder allocation) are already sound and looks at which policy and which period boundaries that arithmetic is fed, not whether floating point is used. If the codebase is doing money math in floats at all, that's a more fundamental problem than this skill's scope. - Not an FX/currency-conversion review — rate-lock timing and multi-currency snapshot freezing are a different, already-covered failure class; this skill's period/credit logic applies whether the plan is single- or multi-currency.
- Not a payment-webhook reliability review — signature verification, delivery retries, and event-ordering are a separate concern from whether the plan-change logic those webhooks eventually trigger is correct once it runs.
- Doesn't validate a specific provider's API contract (Stripe's
proration_behaviorvalues, an alternate billing platform's scheduling semantics) — it reviews what the codebase's own handlers do with whatever the provider gives them, and says so when a provider-specific detail would need to be confirmed against that provider's current docs rather than assumed. - Can't confirm live billing correctness from source alone — a handler that reads correctly may still be wired to a stale webhook secret or a misconfigured price ID in production; flag what the code does, and say plainly when confirming actual charged amounts needs a live/staging trace rather than a code read.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

