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

239 lines
8.3 KiB
Markdown

# 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