Install
$ agentstack add skill-cruisediary-apple-app-review-skills-review-readiness-check ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Skill: Review Readiness Check
Purpose
Detects review-blocking configuration issues including sub-1.0 version numbers, beta/alpha in app name, staging endpoints, and missing demo credentials that prevent reviewers from evaluating the app, violating Guidelines 2.1 and 2.3.
Apple Guideline
- Primary: 2.1 — Performance: App Completeness
- Related: 2.3 — Performance: Accurate Metadata
- Reference:
references/guidelines/2-performance.md
Real-World Rejection Cases
- Case: App version showing "0.1" in App Store submission — reviewer treated as beta/incomplete
Source: mobiloud.com/blog/avoid-app-rejected-apple Root cause: Sub-1.0 version numbers signal incomplete app to reviewers — Apple's review team interprets 0.x versions as pre-release/beta software not ready for the App Store
- Case: App requiring login with no demo account provided — reviewer couldn't access any features — rejected
Source: Apple Developer Forums (Guideline 2.1 enforcement; reviewer requirement documented in App Review guidelines) Root cause: If app requires login, demo credentials must be in review notes — reviewers will not create real accounts and will reject if they cannot access core functionality
- Case: App used SMS-based OTP for login — App Store reviewer's test device could not receive SMS to the developer's phone number — reviewer was locked out and rejected the app
Source: Apple Developer Forums thread/125961 Root cause: Reviewers cannot receive SMS codes tied to the developer's phone. Apps with SMS OTP must provide a demo account that bypasses OTP, or document a working alternative in review notes
- Case: App referenced an IAP product still in "Waiting for Review" status in App Store Connect — reviewer saw "item not available" on purchase — rejected
Source: RevenueCat (revenuecat.com/blog/engineering/app-store-rejections-and-how-to-avoid-them) Root cause: All IAP products referenced by the app must be in "Ready to Submit" status before submission. Any unapproved IAP appears unavailable to reviewers
- Case: App displayed a mandatory update dialog immediately on launch blocking all app content — reviewer downloaded the submission binary and could not proceed past the update screen — rejected under 2.1
Source: Apple Developer Forums (multiple developer reports) Root cause: The App Store reviewer evaluates the exact binary submitted — a forced-update gate that requires downloading a newer version from the App Store means the submitted build is inaccessible. The submitted build must be fully functional as-is; forced update prompts must never block access to core functionality during review
Trigger
Invoke on any iOS/macOS project before App Store submission to check submission configuration readiness.
Inputs
| Name | Type | Default | Description | |------|------|---------|-------------| | project_root | path | cwd | iOS/macOS project root | | shared_context | object | nil | Pre-collected context from appstore-full-audit Phase 1 |
Actions
Phase 1: Context Collection
Skip this phase if shared_context is provided.
Glob**/*.pbxproj— locate the Xcode project file.Glob**/Info.plist— locate Info.plist.Glob**/*.swift— collect Swift source files for network configuration.GlobREVIEW_NOTES*|review_notes*|AppStoreReviewInfo*|ReviewNotes*— locate review notes documentation.
Phase 2: Checks
- Marketing version number
Read project.pbxproj — search for MARKETING_VERSION. If value starts with 0. → 🟠 HIGH. Version numbers starting with 0 signal beta status; use 1.0 or higher for initial App Store submissions.
- Beta/alpha/test in app display name
Read Info.plist — check CFBundleDisplayName value. If value contains "beta", "alpha", "debug", "test", "demo" (case-insensitive) → 🟠 HIGH. App names containing these words signal an incomplete build.
- Staging or localhost endpoints
Grep pattern "localhost"|"127\.0\.0\.1"|"staging\."|"\.dev\." in **/*.swift and configuration files. Any match in a base URL constant or API configuration → 🟠 HIGH. Submissions must use production endpoints.
- Demo credentials documented
Glob REVIEW_NOTES*|review_notes*|AppStoreReviewInfo*|ReviewNotes* — check if file exists. If absent: Grep "login"|"signIn"|"signUp"|"createAccount" in **/*.swift — if login is required, flag → 🟠 HIGH. Demo credentials must accompany any login-required submission.
- HTTP (non-HTTPS) API endpoints
Grep pattern "http://" in **/*.swift — filter for API base URL constants. Any non-HTTPS production endpoint → 🟠 HIGH. App Transport Security requires HTTPS by default.
- Forced update gate on launch
Grep pattern forceUpdate|force_update|ForceUpdate|minimumVersion|minVersion|min_version|mustUpdate in **/*.swift. For each match, Read surrounding context — if an update prompt is shown unconditionally at launch with no way to dismiss → 🔴 CRITICAL. The submitted binary must be fully functional as-is; blocking access pending an App Store update locks out the reviewer entirely.
Phase 3: Output
Collect all findings from Phase 2 and build the prioritised findings list below. Include file paths and line numbers. Omit tiers with no findings.
Output Format
## Review Readiness Check — Findings
### 🔴 CRITICAL — Guaranteed rejection
- [ ] TODO: Remove or make dismissible the forced-update gate — submitted binary must be fully accessible to reviewer without requiring an App Store update — `AppUpdateManager.swift:22` — Guideline 2.1
### 🟠 HIGH — Very likely rejection
- [ ] TODO: Change MARKETING_VERSION from 0.9 to 1.0 or higher before submission — sub-1.0 versions are treated as beta — `MyApp.xcodeproj/project.pbxproj` — Guideline 2.1
- [ ] TODO: Rename app display name — remove "Beta" from CFBundleDisplayName — `Info.plist` — Guideline 2.1
- [ ] TODO: Replace staging base URL with production URL — `NetworkConstants.swift:8` — Guideline 2.1
- [ ] TODO: Add REVIEW_NOTES.md with demo credentials — app requires login but no credentials are documented for reviewers — Guideline 2.1
- [ ] TODO: Change API base URL from http:// to https:// — `APIConfig.swift:4` — Guideline 2.1
### 🟡 MEDIUM — Possible rejection
- [ ] TODO: Verify all App Store Connect metadata URLs (support, marketing, privacy policy) return 200 before submission
### 🟢 LOW — Best practice
- [ ] TODO: Run a pre-submission checklist: version ≥ 1.0, all URLs live, demo credentials documented, no staging endpoints active in release scheme
Tools Used
Glob, Grep, Read
Constraints
- Read-only. No file edits.
- No network calls.
- Skip Phase 1 if
shared_contextis provided by orchestrating agent. - Works on Swift, Objective-C, React Native, Flutter projects.
Quick Commands
Run these in your project root to check manually:
# Check app version (should be 1.0+)
!grep -rn "MARKETING_VERSION" . --include="*.pbxproj" | head -3
# Check for beta/alpha in app name
!find . -name "Info.plist" -not -path "*/Pods/*" | head -1 | xargs plutil -convert json -o - | python3 -c "import sys,json; d=json.load(sys.stdin); print('Display Name:', d.get('CFBundleDisplayName', d.get('CFBundleName','?')))"
# Check for staging URLs in config
!grep -rn "localhost\|127\.0\.0\.1\|staging\.\|\.dev\." . --include="*.swift" --include="*.plist" | grep -iv "comment\|test\|localhost_not"
# Check build config for DEBUG defines
!grep -rn "DEBUG\|STAGING\|DEVELOPMENT" . --include="*.xcconfig" --include="*.plist"
Swift Anti-Pattern Reference
examples/swift/QualityPatterns.swift
Detection Steps
- Find target files
- Glob:
**/Info.plist,**/*.swift,**/fastlane/
- Search for rejection patterns
- Read
Info.plist→ checkCFBundleShortVersionStringforbeta,test,0.0,0.1 - Read
Info.plist→ checkCFBundleName/CFBundleDisplayNameforbeta,test,debug - Grep
localhost\|127\.0\.0\.1\|staging\.\|\.dev\.in Swift constants/configuration files - Check
fastlane/metadata/review_information/exists with demo credentials
- Determine verdict
betaortestin bundle version/name → 🟠 HIGH (Guideline 2.1)- Hardcoded staging/localhost URL in production code → 🟠 HIGH
- No demo account credentials in fastlane review notes → 🟡 MEDIUM (if login required)
- All checks pass → 🟢 pass
- Report
- Exact value of
CFBundleShortVersionStringandCFBundleName - File path + line of any hardcoded staging URL
- Fix: Set version to a release number (e.g.,
1.0.0); use build configuration to switch URLs
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: cruisediary
- Source: cruisediary/apple-app-review-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.