ShopKit — Hardening Checklist

1. Functional correctness

  • Sign in with Apple works end-to-end on first install and after sign-out
  • Auth token survives app relaunch (Keychain)
  • 401 from API triggers a one-time refresh; second 401 signs out
  • Paywall shows accurate pricing in all supported locales
  • Free trial offer is shown only to eligible users
  • Restore Purchases works for users on a new device
  • Subscription state machine handles billing retry + grace period correctly
  • Refund of a transaction surfaces as .revoked and gates Pro content

2. Security

  • Auth token in Keychain with .userPresence access control
  • No tokens in UserDefaults or files
  • TLS pinning enforced for all API hosts
  • No third-party analytics or trackers (verify Package.resolved)
  • Info.plist ATS exceptions: zero
  • No print of token, headers, or response bodies
  • os_log uses %{private}@ for any user-attached values
  • No force-unwraps; SwiftLint enforces

3. StoreKit / billing

  • All Transaction values verified via .verified case before granting entitlement
  • Sandbox test for: purchase, cancel during trial, refund, upgrade/downgrade
  • Transaction.updates is consumed for the app’s lifetime (no missed updates)
  • manageSubscriptionsSheet opens correctly from Settings
  • Server-side validation path documented (App Store Server API) even if not implemented
  • Promo offer eligibility checked against Apple’s rules

4. Privacy

  • Privacy Nutrition Label: Identifier (User ID), Usage Data, Purchases (App Functionality, linked to user, NOT used for tracking)
  • PrivacyInfo.xcprivacy lists every accessed API category with required reasons
  • No tracking SDKs, no AdServices integration
  • Sign in with Apple email is the only user identifier; hashed before being stored on the server

5. Performance

  • Cold launch < 1.5 s
  • Paywall display < 500 ms after tap
  • API request average latency < 400 ms on LTE
  • No retain cycles (Instruments → Leaks)
  • Subscription state change reflected in UI < 2 s

6. CI/CD

  • PR build + test passes consistently (no flake)
  • Merge to main → TestFlight build appears within 30 min
  • Build numbers auto-incremented
  • Match-managed certificates working without manual intervention
  • Slack notification on successful deploy

7. App Store Review readiness

  • Demo Sign in with Apple sandbox account in Review notes
  • Sandbox StoreKit test account in Review notes
  • Subscription terms in paywall match Apple’s requirements (auto-renewal text, length, cancel-anytime)
  • Restore Purchases button visible (Apple Review will reject without)
  • Privacy policy and terms of use URLs live
  • Compelling screenshots showing the paywall, content, and a feature
  • No mention of Stripe, PayPal, or external purchases (would trigger rejection)

8. Documentation

  • GitHub README with green CI badge, screenshots, architecture diagram
  • CONTRIBUTING.md documenting how to run the backend locally
  • ADRs reflect shipped build
  • Interview talking points rehearsed
  • App Store URL on portfolio

Sign-off

Read interview-talking-points.md.