Files
Kordant/iOS/docs/rejection-risk-mitigation.md
Michael Freno 6b729a1334 feat: integrate KordantSpamShieldExtension target and complete App Review compliance (Task 28)
- 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
2026-06-02 15:04:50 -04:00

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
  • NSPrivacyTracking set to false — 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.yml with proper configuration
  • Entitlements created (CallKit + App Group) for shared data access
  • SpamDirectoryService moved to Sources/Shared for 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:

  1. Read the rejection email carefully — Identify the specific guideline
  2. Reproduce the issue — Test on a clean device/simulator
  3. Fix the issue — Implement the required change
  4. Update this document — Add the new risk and mitigation
  5. Resubmit with response — Use App Store Connect messaging to explain the fix
  6. 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 DEBUG code paths contain visible content
  • Verify no print() calls remain outside #Preview blocks
  • 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