L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Explorer les Skills
Développement · SKILL.md

audit-monetization-iap

audit-monetization-iap

Read-only audit of mobile IAP and subscriptions (StoreKit 2, Play Billing, RevenueCat): receipt validation, restore, lifecycle sync, grace periods, entitlements. Use when "audit our IAP" or "restore purchases broken". Web → audit-payment-system.

Independent GitHub snapshot · Automated classification · Original documentation governs

Documentation de la Skill

GitHub

name: audit-monetization-iap description: > Read-only audit of mobile IAP and subscriptions (StoreKit 2, Play Billing, RevenueCat): receipt validation, restore, lifecycle sync, grace periods, entitlements. Use when "audit our IAP" or "restore purchases broken". Web → audit-payment-system. license: MIT effort: high

audit-monetization-iap — Store billing & entitlements

Degree of freedom: MIXED — Phases 0–1 [HIGH freedom]; Phase 2 sandbox [LOW freedom — run exactly], sandbox only: a real purchase charges a real card and cannot be undone from here.

Read-only. Entitlements must match what users paid for: no unlock-without-pay, no paid-but-locked, no double-charge, no lost purchase on reinstall.

The two revenue killers are client-trusted entitlements (piracy) and broken restore (refunds + 1-star reviews).

Present findings. Do not patch store/server code until approved. Never test against real billing.

This skill vs neighbors

SkillOwns
audit-monetization-iap (this)App Store / Play IAP, restore, store notifications
audit-payment-systemWeb money-movement, Stripe, ledgers, PCI
plan-mobile-readinessSubmission paperwork (IAP via official billing is a checkbox)
plan-asoStore listing conversion, not receipt validation
plan-privacy-compliancePurchase-data in privacy labels

Do not fire for "Stripe webhook / double charge on the website" → audit-payment-system.

How to reason

  1. Observe — quote where "is Pro?" is decided and whether a receipt/token is verified server-side
  2. Interpret — can a client lie, or can a paid user lose access?
  3. Classify — client-trust / missing restore / lifecycle hole / correct
  4. Severity — client-trusted entitlement or broken restore = Critical

Worked example

Observe: isPro reads RevenueCat.getCustomerInfo() on-device only; no App Store Server Notification handler. Interpret: a patched client can unlock Pro; refunds never revoke. Classify: client-trust + missing lifecycle sync. Severity: Critical. Finding: entitlements | client-only | Critical | lib/pro.ts:18 | verify on server + ASN V2 / RTDN


Phase 0 — Detect the billing setup [HIGH freedom]

  • Layer: raw StoreKit 2 / Play Billing, or RevenueCat / Adapty / Glassfy
  • Entitlement check: client-only vs server-verified
  • Backend store of subscription state vs trust-the-SDK-at-runtime
  • Products: consumable, non-consumable, auto-renewing sub, trial / intro

Phase 1 — Correctness [HIGH freedom]

Receipt / token validation — Server-side (App Store Server API / Play Developer API). Client-trusted "purchase succeeded" is Critical. StoreKit 2 signed transactions still need verification, not just decode.

Source of truth — One place answers "does this user have Pro?" Backend must hear App Store Server Notifications V2 / Play RTDN for cancel, refund, billing failure — not only check at purchase time.

Restore — Discoverable Restore (Apple requires it). Recovers after reinstall / new device / re-login.

Lifecycle — trial, active, grace (billing retry), on hold, paused (Android), expired, refunded, up/downgrade. Missing grace locks paying users out. Missing revoke leaves refunded users in.

Trials — One trial per user/family; no farm. UI must not promise a trial the store will refuse.

Cross-platform — iOS + Android (+ web): one purchase unlocks via backend, or the user is charged twice.

Prices — From the store (localized), never hardcoded.

Edges — Interrupted purchase resumes; sandbox vs prod receipt mix-up; clock-gamed trials.


Phase 2 — Sandbox only [LOW freedom — never real billing]

Exercise: fresh purchase, restore on clean install, cancel → access ends at period end, sandbox refund → revoke, trial → convert, interrupted purchase. Confirm backend entitlement flips.


Definition of Done

  • Layer + products inventoried
  • Every entitlement traced to server verify, or client-trust flagged Critical
  • Store notifications wired or gap logged
  • Restore present and sandbox-verified
  • Lifecycle grid complete
  • Cross-platform double-charge checked
  • Prices from store
  • Nothing patched

Self-critique before reporting [LOW freedom — do not skip]

  1. Evidenced — file:line for the entitlement SoT, not "RevenueCat probably verifies"
  2. No real charges — sandbox only
  3. Severity justified — Critical = unlock-without-pay or paid-but-locked
  4. Right owner — web Stripe → audit-payment-system
  5. Restore probed — "button exists" is not restore-verified

Output format

  1. Setup — layer, products, entitlement SoT
  2. Findings — issue | severity | file:line | fix shape
  3. Lifecycle grid — state × handled?
  4. Sandbox log — scenario | expected | actual
  5. Fix plan — server verify + restore first

Related

  • audit-payment-system — web / Stripe / ledger
  • plan-mobile-readiness — store review gates
  • plan-aso — listing, not billing correctness
  • plan-privacy-compliance — purchase data disclosure
Skills enregistrées