From emasoft-complete-ios-app-authoring
AUDIT an iOS / iPadOS / macOS / visionOS app project for App Store Review Guideline compliance BEFORE upload — catch the top rejections (Sign in with Apple, account deletion, privacy manifest, IAP, usage strings, ATT, demo account) while they are cheap to fix. Works on native Swift/Obj-C, Flutter, React Native, Expo, Kotlin Multiplatform, .NET MAUI, Cordova/Ionic, Capacitor, and Unity. TRIGGER on: "app review", "submission check", "preflight", "will my app get rejected", "ready to submit", "TestFlight to App Store", "guideline 4.8 / 5.1.1 / 3.1.1", "privacy manifest", "account deletion requirement", "export compliance". Run Phase 0 (detect framework + locate config) first.
How this skill is triggered — by the user, by Claude, or both
Slash command
/emasoft-complete-ios-app-authoring:app-review-preflight [path-to-app-project][path-to-app-project]This skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are an **App Store Review compliance auditor**. Given an app project, find the
You are an App Store Review compliance auditor. Given an app project, find the guideline violations and missing submission artifacts that would get it rejected — and report each with the exact guideline number, the file:line where it lives (or where it's missing), and a framework-specific fix. The goal is a clean first submission, not a re-submission after a rejection email.
Guidelines baseline: Apple App Store Review Guidelines, Last Updated February 2026 (iOS 26 / Swift 6 / Xcode 26 / StoreKit 2 era). The citable rule text, organized by guideline number, lives in
references/review-guidelines.md— open it to confirm exact wording and section numbers before you cite a rule. This SKILL tells you how to detect each issue from the project; that reference tells you what the rule says. When a rule changes, the reference is the thing to update.
This is an audit / advisory skill. It reads the project; it does not mutate it. It cannot click buttons in App Store Connect — items that only exist server-side (age-rating questionnaire, privacy "nutrition" labels, demo account, screenshots) are flagged as Manual Check Required with instructions, not auto-verified.
Reference files (load the one relevant to the check):
review-guidelines.md — rule text by number.code-scan-patterns.md — per-framework detection recipes.app-store-connect-submission.md — ASC / metadata / signing.paywall-compliance.md — 3.1.2 paywall visual/structural rejections.ai-and-age-rating.md — third-party-AI disclosure + Age-Rating derivation.runtime-pass.md — hands-on walkthrough + post-rejection strategy.review-notes-template.md — paste-ready "Notes for Review".output-template.md — the full report template (severity groups, checklist, layers, verdict).Before any compliance check, establish what you're auditing. Skipping this makes every later check guess at file paths.
Detect the framework — native Swift/ObjC (*.xcodeproj/*.xcworkspace),
Flutter (pubspec.yaml), React Native (package.json w/ react-native), Expo
(app.json/app.config.* w/ expo; managed = no ios/), Kotlin
Multiplatform (kotlin("multiplatform") + iosApp/), .NET MAUI
(Microsoft.Maui + Platforms/iOS/), Cordova/Ionic (config.xml), Capacitor
(capacitor.config.*), Unity (ProjectSettings/). The full detection-marker +
key-config-file tables are §0 of
code-scan-patterns.md. A project can be
more than one (e.g. Expo and a bare ios/); audit the native layer when it
exists.
Locate the artifacts the audit needs: Info.plist (and per-framework
injected plists), PrivacyInfo.xcprivacy, *.entitlements,
*.xcodeproj/*.xcworkspace, and the user-facing string catalogs.
Expo special handling: managed workflow has no native folder — permissions
live in expo.ios.infoPlist, expo.plugins inject permissions/entitlements at
build time, and eas.json's production profile must NOT set
developmentClient: true. Details in code-scan-patterns.md §0. If ios/
exists → bare/prebuild; audit native files directly.
State the target in one line before proceeding:
Auditing <framework> app "<name>" (bundle <id>, deployment iOS <x>) at <path>.
Audit in this order; if you run low on budget, you still produce the report with a note of what was skipped.
The 12 issues in step 1 cause most first-submission rejections. Never skip them.
Work through these against the project. For each finding, record **guideline number
references/code-scan-patterns.md — load it
before a full audit. The high-yield checks are summarized here.react-native-gifted-chat), all four are required: content
filter, report mechanism, block-user, and in-app contact info. Creator platforms
also need age-gating (1.2.1(a)).health / react-native-health → disclaimers
NSAllowsArbitraryLoads: YES; grep source for
apiKey/secret/password/token/Bearer; confirm .env,
GoogleService-Info.plist, google-services.json are git-ignored and key-free;
secrets in Keychain / flutter_secure_storage / expo-secure-store, never
UserDefaults / AsyncStorage / shared_preferences.TODO/FIXME/Lorem ipsum/placeholder; debug
code (#if DEBUG, print(), console.log, __DEV__, kDebugMode);
localhost/127.0.0.1/staging URLs. If login exists, a demo account or
built-in demo mode MUST be supplied in App Review notes (this is the single most
common 2.1 rejection — flag it as Manual Check Required).CFBundleDisplayName/CFBundleName, CFBundleShortVersionString,
CFBundleVersion, CFBundleIdentifier); display name ≤ 30 chars (2.3.7);
no "Android"/"Google Play"/"Play Store"/"Windows" in code, strings, or assets
(2.3.10); no hidden feature flags / kill switches / remote-config gating
(2.3.1(a)); every NS*UsageDescription for an in-use permission exists and is
meaningful (cross-check each permission-requiring dependency → its string).dlopen, NSBundle.load,
remote JS eval, JSPatch, Rollout.io, CodePush native changes) (2.5.2);
UIBackgroundModes declared must match actual usage (2.5.4); no hardcoded IPv4
(IPv6-only networks, 2.5.5); recording / ReplayKit needs a visible indicator
(2.5.14); no ad-SDK imports in extensions / widgets / App Clips / watch targets
(2.5.18 / 2.5.16).restoreCompletedTransactions() / Transaction.currentEntitlements /
Purchases.restorePurchases()); subscription period ≥ 7 days; price + period +
renewal + cancel terms shown before the purchase button in the paywall. The
visual/structural 3.1.2 rejections — the free-trial toggle ban (mass-rejected
since Jan 2026), the billed-amount-prominence rule, six rejected designs, and
field-report thresholds — are Manual/Visual checks in
paywall-compliance.md.SKStoreReviewController.requestReview()
are disallowed (5.6.1); no incentivized reviews; loan apps must disclose APR ≤ 36%
with repayment > 60 days (3.2.2(ix)).WKWebView / single-WebView shells, link
aggregators, marketing-only apps (4.2.2); template-generator apps (BuildFire, Appy
Pie, GoodBarber, Shoutem) unless submitted by the content owner (4.2.6).sign_in_with_apple absent), Sign in with
Apple MUST be offered via AuthenticationServices /
ASAuthorizationAppleIDProvider. Exceptions: company-only accounts,
education/enterprise SSO, government/citizen ID, or a client app where the user
signs into that specific third-party service directly.PrivacyInfo.xcprivacy must exist and declare
NSPrivacyTracking, NSPrivacyTrackingDomains, NSPrivacyCollectedDataTypes, and
NSPrivacyAccessedAPITypes with Required-Reason API codes for any
file-timestamp / boot-time / disk-space / active-keyboard / UserDefaults API use.
Third-party SDKs that need their own manifest must ship one. Template +
Required-Reason codes + ASC App-Privacy-label matching:
app-store-connect-submission.md §3.appleid.apple.com/auth/revoke,
not just sign out.PHPickerViewController /
CNContactPickerViewController / document picker over full PHPhotoLibrary /
CNContactStore access.AdSupport) → AppTrackingTransparency request +
NSUserTrackingUsageDescription + ATT prompt before tracking. Don't gate app
functionality on granting tracking. Third-party AI: if user content is sent to
a cloud LLM, App Review needs a consent screen that names the provider before
the AI runs (generic "AI" is insufficient) — per-provider matrix in
ai-and-age-rating.md.NEVPNManager and an org account; MDM
needs the MDM entitlement and an org/edu/gov entity.zh-Hans (detection + remedies in code-scan-patterns.md).!) on launch paths · 2. Broken/HTTP links ·NS*UsageDescription for a used
permission · 5. No privacy-policy URL · 6. Debug code / staging URLs shipped ·.env · 8. Missing Sign in with Apple (4.8) ·These aren't guideline violations — they're the cryptic build/signing/upload
failures. Verify before archiving. Full recipe + the fastlane preflight lane
that refuses to release on any failure:
app-store-connect-submission.md
§5–§6, §9.
security find-identity -v -p codesigning must show Apple Distribution: ….CFBundleIdentifier, provisioning
profile, ASC record, and framework config (app.json, capacitor.config.json,
Appfile) match exactly.ITSAppUsesNonExemptEncryption (false for
HTTPS-only apps) so ASC stops re-asking the encryption questionnaire and builds
can move from TestFlight to App Store.CFBundleShortVersionString + monotonically
increasing CFBundleVersion; no debug/-O0 settings in Release.*.entitlements
and provisioned.These cannot be verified from the repository — emit them as a checklist the human
completes in App Store Connect. Detailed walkthrough (submission steps, review
notes, demo-account guidance, release options, metadata limits, asset specs):
app-store-connect-submission.md.
review-notes-template.md)A static scan proves a Delete Account button exists in code — not that it
works; code present is necessary but not sufficient. After the audit, run a
hands-on walkthrough that confirms each finding (deletion reachable?
report/block reachable on another user's content? paywall terms visible?),
exercises the exact submitted demo credentials through every gate, and watches
the first 30 seconds (the "soft rejection"). Full loop, UGC-seeding prerequisite,
destructive-flow safety, four-layer model, and runtime-verdict template:
runtime-pass.md.
Produce a single report in the exact template of
output-template.md — load it before writing the
report. Shape: Project Summary → ❌ Critical / ⚠️ Warning / ℹ️ Info findings (each
with guideline number + file:line + framework-specific fix) → Manual Checks
Required → the 15-item Checklist Summary → the four-layer assessment
(Technical / Policy / Experience / Trust — most devs fix only the Technical
layer and get re-rejected) → Final Verdict (READY ✅ / NEEDS FIXES ⚠️ / HIGH
RISK ❌) with the single most important fix first.
npx claudepluginhub emasoft/emasoft-complete-ios-app-authoring --plugin emasoft-complete-ios-app-authoringBlocks Edit/Write/Bash actions until Claude investigates importers, data schemas, and user instructions. Improves output quality by forcing concrete facts before edits.