- Add KordantSpamShieldExtension target to project.yml with proper app-extension type, bundle identifier, and deployment target - Create CallKit + App Group entitlements for SpamShield extension - Move SpamDirectoryService to Sources/Shared for cross-target access - Update app-review-checklist with 5 new technical items (total: 121) - Update rejection-risk-mitigation with extension build integration - Add SpamShield extension details to reviewer notes - Mark Task 24 (push deep links) and Task 28 as complete
8.3 KiB
Rejection Risk Mitigation
Kordant iOS App — Pre-submission risk analysis
Last updated: 2026-06-02
High-Risk Areas & Mitigation
Guideline 2.1 — App Completeness
Risk: Rejection for incomplete features or placeholder content
Mitigation:
- ✅ Removed "Map integration coming soon" from PropertyDetailView
- ✅ All buttons are functional (including "Upgrade Plan" → opens billing portal)
- ✅ No disabled UI elements
- ✅ All navigation paths tested and working
- ✅ Empty states provide meaningful feedback (not blank screens)
Residual risk: LOW — All features are complete and functional
Guideline 3.1.1 — Payment (Subscription Model)
Risk: Rejection for not using In-App Purchase for digital subscriptions
Mitigation:
- ✅ Subscriptions are for access to server-side monitoring services (dark web scanning, data broker removal)
- ✅ Services are not digital content consumed within the app
- ✅ Billing handled via Stripe Customer Portal (web billing)
- ✅ "Upgrade Plan" button opens the billing portal
- ✅ Free tier available with limited features
- ✅ No external links to purchase digital goods within the app
- ✅ Documented rationale: service-based subscription, not content subscription
Reference: Apple's guidance distinguishes between:
- Digital content (magazines, music, games) → must use IAP
- Service access (cloud storage, monitoring, real-world services) → web billing acceptable
Residual risk: LOW-MEDIUM — Service model is clearly distinct from digital content
Guideline 4.2 — Minimum Functionality
Risk: Rejection for being a "wrapper" around a website
Mitigation:
- ✅ Full native SwiftUI application — not a web wrapper
- ✅ 5+ distinct service modules with native UI
- ✅ CallKit integration for spam call filtering (native system feature)
- ✅ Home screen widgets with real-time data
- ✅ Siri shortcuts for common actions
- ✅ Push notification deep linking
- ✅ Offline data caching and sync
- ✅ Biometric authentication
- ✅ Native camera integration for document scanning
- ✅ Native microphone access for voice enrollment
Residual risk: VERY LOW — App is clearly a substantial native application
Guideline 5.1.1 — Data Collection and Storage
Risk: Rejection for inaccurate or missing privacy disclosures
Mitigation:
- ✅ Privacy manifest (
PrivacyInfo.xcprivacy) present in main app and widget extension - ✅ All data types accurately declared with correct linkage
- ✅
NSPrivacyTrackingset tofalse— no cross-app tracking - ✅ API access reasons declared (FileTimestamp, DiskSpace, UserDefaults)
- ✅ ATT prompt shown before any analytics
- ✅ Analytics respects user consent
- ✅ No third-party tracking domains
- ✅ All permission usage descriptions accurate and localized
Residual risk: LOW — Privacy disclosures are comprehensive and accurate
Guideline 5.6 — Developer Code of Conduct
Risk: Rejection for manipulating reviews or ratings
Mitigation:
- ✅ No review prompts in the app
- ✅ No SKStoreReviewController usage
- ✅ No manipulation of app store metadata
- ✅ No incentivized reviews
- ✅ No pre-filled review text
Residual risk: NONE — No review-related code in the app
Guideline 2.3.1 — Performance — Accurate Metadata
Risk: Rejection for screenshots not matching the app
Mitigation:
- ✅ Screenshots captured from actual app builds
- ✅ All supported device sizes (iPhone SE, 12, 14 Pro, 15 Pro Max)
- ✅ Screenshots reflect current app state (no outdated UI)
- ✅ App preview video shows real app functionality
- ✅ Description accurately reflects app capabilities
Residual risk: LOW — Ensure screenshots are refreshed before each submission
Guideline 2.1 — Crash on Launch
Risk: Rejection if app crashes during review
Mitigation:
- ✅ Deferred initialization — no blocking work on launch
- ✅ Graceful error handling for all async operations
- ✅ Network failure handling with retry
- ✅ Permission denial handling
- ✅ Keychain access with error recovery
- ✅ Security checks run on background thread
- ✅ Tested on multiple iOS versions (17.0+)
Residual risk: LOW — Comprehensive error handling throughout
Medium-Risk Areas
Jailbreak Detection
Risk: Reviewer's device triggers jailbreak detection (e.g., simulator, development device)
Mitigation:
- ✅ Graceful degradation — app remains functional in degraded mode
- ✅ Warning banner is informational, not blocking
- ✅ Degraded mode reduces features but doesn't prevent usage
- ✅ Security checks are non-blocking (run on detached tasks)
Note: Apple reviewers typically use clean devices. Simulator testing shows degraded mode works correctly.
Call Directory Extension
Risk: Extension not properly integrated in build
Mitigation:
- ✅ Extension target added to
project.ymlwith proper configuration - ✅ Entitlements created (CallKit + App Group) for shared data access
- ✅
SpamDirectoryServicemoved toSources/Sharedfor cross-target access - ✅ Extension is optional — app works without it
- ✅ Clear instructions in SpamShield settings
- ✅ Extension status checked via
CXCallDirectoryManager.getEnabledStatusForExtension - ✅ Graceful fallback when extension is not enabled
Siri Shortcuts
Risk: Siri intents not configured on reviewer's device
Mitigation:
- ✅ Shortcuts are optional — app works without Siri
- ✅ Intent donations happen automatically after onboarding
- ✅ Settings screen explains how to enable Siri shortcuts
Low-Risk Areas
Background Fetch
- App uses standard background fetch API
- No aggressive battery usage
- Fetch interval respects system scheduling
Push Notifications
- Standard UNUserNotificationCenter usage
- Deep links use standard userInfo payload
- No critical alert abuse
OAuth Sign-In
- Apple Sign-In uses native
AuthenticationServices - Google Sign-In uses official GoogleSignIn-iOS SDK
- Both flows are standard and well-documented
Rejection Response Plan
If the app is rejected, follow this process:
- Read the rejection email carefully — Identify the specific guideline
- Reproduce the issue — Test on a clean device/simulator
- Fix the issue — Implement the required change
- Update this document — Add the new risk and mitigation
- Resubmit with response — Use App Store Connect messaging to explain the fix
- Target response time: Within 24 hours of rejection
Common Rejection Scenarios & Quick Fixes
| Rejection Reason | Quick Fix |
|---|---|
| 2.1 — Incomplete app | Remove any remaining placeholder content |
| 2.1 — Crashes | Check crash logs, fix the specific crash |
| 3.1.1 — IAP required | Clarify service model in review notes |
| 4.3 — Spam | Ensure app is unique, not a clone |
| 5.1.1 — Privacy | Update privacy manifest, add missing declarations |
| 2.1 — Beta label | Remove any "beta", "test", or "preview" text |
| 2.1 — Dead links | Verify all external URLs work |
| 4.2 — Minimum functionality | Emphasize native features in review notes |
Pre-Submission Checklist
Before submitting to App Store Review:
- Build Release configuration
- Verify no
#if DEBUGcode paths contain visible content - Verify no
print()calls remain outside#Previewblocks - Verify no force unwraps in production code paths
- Test on physical device (not just simulator)
- Verify all deep links work
- Verify push notifications work
- Verify ATT flow works
- Verify sign-in flows work (email, Apple, Google)
- Verify subscription upgrade button opens billing portal
- Verify widgets appear on home screen
- Verify Siri shortcuts are available
- Verify no console warnings in release build
- Verify app icon and launch screen are correct
- Verify version number and build number are correct
- Verify privacy policy URL works
- Verify all screenshots match current app UI
- Verify app preview video is current
- Verify SpamShield extension target built
- Verify SpamShield extension entitlements correct
- Upload via Xcode Organizer or Transporter
- Fill in App Store Connect metadata
- Add review notes and demo account
- Submit for review