Mobile Store Review Skill
Audits a mobile app's source and config — not the running app, not the store listing — and reports whether Apple App Review and Google Play review would pass it. Most first-submission rejections are compliance plumbing that's visible in code: a missing usage description, no in-app account-deletion path, a target SDK below the current floor, a privacy declaration that doesn't match what's actually linked. This skill finds those before a human reviewer does.
Discovery — Do This First
Locate the app and classify its stack before checking anything else.
1. Find the mobile app(s). In a monorepo, check turbo.json for app-shaped tasks (build, ios, android) and the workspace globs in pnpm-workspace.yaml / package.json#workspaces / turbo.json#packages. Within candidate packages, look for app.json, app.config.js/app.config.ts, an expo dependency, or committed ios/ + android/ directories. A monorepo can contain more than one mobile app — audit each separately.
2. Classify the workflow — this determines which file is the source of truth:
| Signal |
Workflow |
Source of truth |
app.config.*/app.json, no committed ios//android/ |
Expo managed (CNG) |
The resolved Expo config |
app.config.*/app.json and committed ios/+android/ |
Expo + prebuilt native dirs |
The native files — app.config.ts may be stale |
ios/+android/, no expo dependency |
Bare React Native |
The native files |
No RN/Expo — pure ios//android/ project |
Native |
The native files |
If both app.config.ts and committed native directories exist, the native directories win — a permission or usage description added only to app.config.ts never reaches the shipped binary unless expo prebuild regenerates the native dirs from it. Don't assume; check whether the native dirs are regenerated in CI or hand-maintained.
3. Resolve the real config. app.config.ts is JavaScript and can branch on environment — never audit the literal source text as if it were the final manifest. Read-only commands to resolve it:
npx expo config --type public # fully resolved manifest, including plugin effects
npx expo-doctor # flags known misconfigurations
npx eas config --platform ios # resolved build profile (which profile is production)
npx eas config --platform android
4. Record the target. Which storefronts (iOS App Store, Google Play, both)? Which eas.json build profile ships to production? That's the profile whose config the audit should follow — a development or preview profile's env vars are not relevant.
What This Skill Does NOT Do
Static analysis cannot see: server-side behavior, real crash rates, the actual App Store Connect / Play Console listing (screenshots, description, category), whether a review demo account currently works, or purely subjective calls (Guideline 4.2 Minimum Functionality, 4.3 Spam, "quality" bars). Findings in those areas are graded ⚪ Unverifiable from code, never 🟢 Pass — a report that silently skips its blind spots is worse than one that names them.
Severity Rubric
| Grade |
Meaning |
| 🔴 Blocker |
Hard, mechanical trigger — upload rejected or review rejection near-certain (missing usage description for a linked API, target SDK below the enforced floor, sign-up with no in-app deletion path) |
| 🟡 Risk |
Reviewer-discretion or a mismatch that's often but not always caught (Data safety vs. binary, permission scope, a login wall) |
| 🟢 Pass |
Checked against a concrete rule and clean |
| ⚪ Unverifiable from code |
Needs a human, a store console, or a live build to confirm |
Reference Files (read these on demand)
| Task |
Read |
| Running the audit end-to-end; the exact command sequence |
references/audit-workflow.md |
| Permissions, usage descriptions, ATT, privacy manifest, App Privacy / Data safety |
references/permissions-and-privacy.md |
| Citing an App Review Guideline; App Store Connect submission gates |
references/apple-review.md |
| Citing a Play policy; Play Console declarations and the target API level floor |
references/google-play-review.md |
| Where a rule lives in Expo config vs. bare RN vs. native files |
references/expo-and-rn.md |
| Finding the app in a monorepo; EAS build/submit, versioning, credentials |
references/monorepo-and-eas.md |
Copyable assets live in assets/:
assets/audit-report.md — the graded report template; fill this in as the deliverable
assets/PrivacyInfo.xcprivacy — starter Apple privacy manifest with required-reason API categories
assets/pre-submission-checklist.md — a copyable human checklist for a release runbook, covering the ⚪ items code can't verify
The Audit in Six Phases
See references/audit-workflow.md for the full procedure and exact commands.
- Discover & classify — locate the app(s), determine the workflow, resolve the config (above).
- Permissions & privacy — every linked capability has a usage description, a privacy manifest entry, and matches its store declaration (
references/permissions-and-privacy.md).
- Accounts, payments & content — account deletion, third-party login, IAP vs. external payment links, UGC moderation, age rating.
- Submission gates — SDK/Xcode floor, target API level, version/build-number monotonicity, bundle ID / applicationId consistency, signing.
- Metadata & assets — icons, splash, support/privacy-policy URL reachability, placeholder content, staging URLs baked into the production profile.
- Write the report — fill
assets/audit-report.md: Blockers, then Risks, then Unverifiable, then a Pass summary, each with file:line evidence and a fix.
Critical Gotchas
Read the resolved config, not the file. app.config.ts can branch on process.env; grepping the source misses env-conditional plugins entirely.
# ✅ correct
npx expo config --type public
# ❌ wrong — misses plugin effects and env branches
cat app.config.ts
Committed ios/+android/ dirs beat app.config.ts. If they exist and aren't regenerated in CI, they are what ships. A usage description or permission present only in app.config.ts is a false 🟢 if the native files are stale.
A transitive dependency can add a permission you never asked for. A workspace package can pull in an SDK that links an API requiring NSPhotoLibraryUsageDescription even though the app's own code never touches the photo library. Audit resolved native modules (npx expo-modules-autolinking / the merged Android manifest), not just direct package.json dependencies.
Sign-up implies account deletion — with different requirements per store. Apple's Guideline 5.1.1(v) ("Account Sign-In") is satisfied by an in-app deletion flow. Google Play additionally requires a public web URL for account deletion, declared in the Data safety form — a support email is not sufficient for either store.
Never run eas build, eas submit, or expo prebuild. prebuild mutates the repo (regenerates ios//android/); build/submit cost money and touch store APIs. This is a read-only audit — see references/audit-workflow.md for the full allowed-command list.
Declared privacy must match the binary — both stores now cross-reference this. An analytics or crash-reporting SDK that's linked but undeclared in App Privacy / Data safety is a removal risk, not a minor note.
Don't grade subjective guidelines 🟢. Guideline 4.2 (Minimum Functionality), 4.3 (Spam), and similar reviewer-judgment rules go in ⚪ Unverifiable, never Pass — code can't confirm them.
Facts here go stale. SDK floors, target API levels, and billing rules change on published deadlines. Before citing a specific date or version number in a report, verify it's still current — see references/apple-review.md and references/google-play-review.md for the values known at time of writing, each flagged with when to re-check.
1---2name: mobile-store-review3description: Audits a mobile app codebase — Expo/React Native (managed or bare) or native iOS/Android, standalone or inside a Turborepo/monorepo — and reports whether it would pass Apple App Review and Google Play review. Use this skill whenever the user: asks if their app will pass, fail, or get rejected by Apple or Google review; is preparing an App Store or Play Store submission; got a rejection email or resolution center message citing a guideline or policy; is filling out the App Privacy questionnaire or Play Data safety form; is auditing permissions, usage descriptions, a privacy manifest, or account-deletion flow; mentions App Review Guidelines, Play Developer Program Policies, TestFlight, `eas submit`, App Store Connect, or Play Console; or is doing a pre-submission or release-readiness check on a mobile app. Also use when the user says things like "will this get rejected?", "audit my app before I ship it", or "review my app for the stores" — even if they don't name a specific guideline.4---56# Mobile Store Review Skill78Audits a mobile app's source and config — not the running app, not the store listing — and reports whether Apple App Review and Google Play review would pass it. Most first-submission rejections are compliance plumbing that's visible in code: a missing usage description, no in-app account-deletion path, a target SDK below the current floor, a privacy declaration that doesn't match what's actually linked. This skill finds those before a human reviewer does.910## Discovery — Do This First1112Locate the app and classify its stack before checking anything else.1314**1. Find the mobile app(s).** In a monorepo, check `turbo.json` for app-shaped tasks (`build`, `ios`, `android`) and the workspace globs in `pnpm-workspace.yaml` / `package.json#workspaces` / `turbo.json#packages`. Within candidate packages, look for `app.json`, `app.config.js`/`app.config.ts`, an `expo` dependency, or committed `ios/` + `android/` directories. A monorepo can contain more than one mobile app — audit each separately.1516**2. Classify the workflow** — this determines which file is the *source of truth*:1718| Signal | Workflow | Source of truth |19|---|---|---|20| `app.config.*`/`app.json`, no committed `ios/`/`android/` | Expo managed (CNG) | The resolved Expo config |21| `app.config.*`/`app.json` **and** committed `ios/`+`android/` | Expo + prebuilt native dirs | The native files — `app.config.ts` may be stale |22| `ios/`+`android/`, no `expo` dependency | Bare React Native | The native files |23| No RN/Expo — pure `ios/`/`android/` project | Native | The native files |2425If both `app.config.ts` and committed native directories exist, **the native directories win** — a permission or usage description added only to `app.config.ts` never reaches the shipped binary unless `expo prebuild` regenerates the native dirs from it. Don't assume; check whether the native dirs are regenerated in CI or hand-maintained.2627**3. Resolve the real config.** `app.config.ts` is JavaScript and can branch on environment — never audit the literal source text as if it were the final manifest. Read-only commands to resolve it:2829```bash30npx expo config --type public # fully resolved manifest, including plugin effects31npx expo-doctor # flags known misconfigurations32npx eas config --platform ios # resolved build profile (which profile is production)33npx eas config --platform android34```3536**4. Record the target.** Which storefronts (iOS App Store, Google Play, both)? Which `eas.json` build profile ships to production? That's the profile whose config the audit should follow — a `development` or `preview` profile's env vars are not relevant.3738## What This Skill Does NOT Do3940Static analysis cannot see: server-side behavior, real crash rates, the actual App Store Connect / Play Console listing (screenshots, description, category), whether a review demo account currently works, or purely subjective calls (Guideline 4.2 Minimum Functionality, 4.3 Spam, "quality" bars). Findings in those areas are graded ⚪ **Unverifiable from code**, never 🟢 Pass — a report that silently skips its blind spots is worse than one that names them.4142## Severity Rubric4344| Grade | Meaning |45|---|---|46| 🔴 **Blocker** | Hard, mechanical trigger — upload rejected or review rejection near-certain (missing usage description for a linked API, target SDK below the enforced floor, sign-up with no in-app deletion path) |47| 🟡 **Risk** | Reviewer-discretion or a mismatch that's often but not always caught (Data safety vs. binary, permission scope, a login wall) |48| 🟢 **Pass** | Checked against a concrete rule and clean |49| ⚪ **Unverifiable from code** | Needs a human, a store console, or a live build to confirm |5051## Reference Files (read these on demand)5253| Task | Read |54|---|---|55| Running the audit end-to-end; the exact command sequence | `references/audit-workflow.md` |56| Permissions, usage descriptions, ATT, privacy manifest, App Privacy / Data safety | `references/permissions-and-privacy.md` |57| Citing an App Review Guideline; App Store Connect submission gates | `references/apple-review.md` |58| Citing a Play policy; Play Console declarations and the target API level floor | `references/google-play-review.md` |59| Where a rule lives in Expo config vs. bare RN vs. native files | `references/expo-and-rn.md` |60| Finding the app in a monorepo; EAS build/submit, versioning, credentials | `references/monorepo-and-eas.md` |6162Copyable assets live in `assets/`:63- `assets/audit-report.md` — the graded report template; fill this in as the deliverable64- `assets/PrivacyInfo.xcprivacy` — starter Apple privacy manifest with required-reason API categories65- `assets/pre-submission-checklist.md` — a copyable human checklist for a release runbook, covering the ⚪ items code can't verify6667## The Audit in Six Phases6869See `references/audit-workflow.md` for the full procedure and exact commands.70711. **Discover & classify** — locate the app(s), determine the workflow, resolve the config (above).722. **Permissions & privacy** — every linked capability has a usage description, a privacy manifest entry, and matches its store declaration (`references/permissions-and-privacy.md`).733. **Accounts, payments & content** — account deletion, third-party login, IAP vs. external payment links, UGC moderation, age rating.744. **Submission gates** — SDK/Xcode floor, target API level, version/build-number monotonicity, bundle ID / applicationId consistency, signing.755. **Metadata & assets** — icons, splash, support/privacy-policy URL reachability, placeholder content, staging URLs baked into the production profile.766. **Write the report** — fill `assets/audit-report.md`: Blockers, then Risks, then Unverifiable, then a Pass summary, each with `file:line` evidence and a fix.7778## Critical Gotchas79801. **Read the resolved config, not the file.** `app.config.ts` can branch on `process.env`; grepping the source misses env-conditional plugins entirely.81 ```bash82 # ✅ correct83 npx expo config --type public84 # ❌ wrong — misses plugin effects and env branches85 cat app.config.ts86 ```87882. **Committed `ios/`+`android/` dirs beat `app.config.ts`.** If they exist and aren't regenerated in CI, they are what ships. A usage description or permission present only in `app.config.ts` is a false 🟢 if the native files are stale.89903. **A transitive dependency can add a permission you never asked for.** A workspace package can pull in an SDK that links an API requiring `NSPhotoLibraryUsageDescription` even though the app's own code never touches the photo library. Audit resolved native modules (`npx expo-modules-autolinking` / the merged Android manifest), not just direct `package.json` dependencies.91924. **Sign-up implies account deletion — with different requirements per store.** Apple's Guideline 5.1.1(v) ("Account Sign-In") is satisfied by an in-app deletion flow. Google Play additionally requires a **public web URL** for account deletion, declared in the Data safety form — a support email is not sufficient for either store.93945. **Never run `eas build`, `eas submit`, or `expo prebuild`.** `prebuild` mutates the repo (regenerates `ios/`/`android/`); `build`/`submit` cost money and touch store APIs. This is a read-only audit — see `references/audit-workflow.md` for the full allowed-command list.95966. **Declared privacy must match the binary — both stores now cross-reference this.** An analytics or crash-reporting SDK that's linked but undeclared in App Privacy / Data safety is a removal risk, not a minor note.97987. **Don't grade subjective guidelines 🟢.** Guideline 4.2 (Minimum Functionality), 4.3 (Spam), and similar reviewer-judgment rules go in ⚪ Unverifiable, never Pass — code can't confirm them.991008. **Facts here go stale.** SDK floors, target API levels, and billing rules change on published deadlines. Before citing a specific date or version number in a report, verify it's still current — see `references/apple-review.md` and `references/google-play-review.md` for the values known at time of writing, each flagged with when to re-check.