All packsApp Store MachinerySolve
app store review rejection guideline 3.1.2 restore purchases
A missing restore-purchases button is a review rejection, not a build error
Guideline 3.1.2 requires a visible restore-purchases control on the paywall -- Xcode happily lets you submit without one, and Apple rejects it days later.
What goes wrong
App Review guidelines 3.1.2 (restore purchases must be visible and functional), 3.1.1 and 2.1 (subscription terms and pricing must be clear), and 5.1.2 (privacy commitments) are all things a StoreKit integration can compile, run, and pass every local test while still violating -- because none of them are things the compiler, the simulator, or a unit test checks. The rejection arrives from Apple's human review, typically 2-3 days after submission, for something that was avoidable and checkable well before then.
Why agents get it wrong
These guidelines live in App Review's documentation, not in any API's type signature or compiler warning -- a StoreKit integration that renders a working paywall and processes a purchase correctly gives every local signal of being done. Whether a restore button is visible enough, or terms-of-service links are wired to the right policy destination, is a review-time, human-judged UI-completeness question that no automated local check catches unless something is specifically built to check it.
What App Store Machinery pre-decides
Decision 10 pins the paywall to Apple's own SubscriptionStoreView with .subscriptionStorePolicyDestination(url:for:) wired for both Terms of Service and Privacy Policy, a visible restore button via .storeButton(.visible, for: .restorePurchases), and the offer-code redemption control -- Apple's own component renders price, duration, and localization correctly by construction. The review-rejection preflight then statically checks for the presence of exactly these elements (plus the privacy manifest and export-compliance flag) before the build ships, catching what's checkable before a review cycle does.
Source: ARCHITECTURE.md decision 10; LISTING.md 'The five traps this pack pre-solves'