App Store Server API-independent launch mode
This mode keeps subscription verification and enforcement operational without making outbound App Store Server API requests. It is the #335 workaround while Apple's API rejects the production credential set.
Trusted sources
- The iOS client obtains StoreKit 2 signed transactions for purchases, restorations, and current entitlements.
record_purchase_callverifies the Apple JWS on the server, enforces the bundle ID and product allowlist, rejects Family Sharing, and binds the original transaction to one Cookery Trove UID.- App Store Server Notifications V2 supplies signed renewal, billing, expiry, refund, and revocation events while the app is not running.
- Firestore and Storage authorize paid writes only while the trusted
expiresDateMs(or another explicitly bounded entitlement) is in the future.
No client Boolean, sandbox transaction, device clock, or cached purchase value is authoritative.
Runtime switch
APPLE_SERVER_API_ENABLED defaults to false. Only the exact value true
allows refresh_subscription_entitlement or
reconcile_apple_subscriptions to call the App Store Server API. With the
default value:
- the callable returns the current canonical state and tells compatible clients to restore purchases;
- the scheduled function records that reconciliation was skipped and performs no outbound Apple request; and
- no verification-outage extension is granted merely because the optional API is disabled.
Keep the switch false until a separately approved canary proves the App Store Server API credential path works.
Production cutover (separate approval required)
Repository merge does not authorize these production operations.
- Capture current revisions, Scheduler state, parameter values, monitoring, and rollback commands.
- Deploy the reviewed compatibility callable and guarded scheduler from the frozen commit with their isolated codebases and exact selectors.
- Confirm
APPLE_SERVER_API_ENABLED=falsewithout reading or changing private credential values. - Pause the six-hour
reconcile_apple_subscriptionsScheduler job. Do not delete it during the first change window. - Leave App Store Server Notifications V2 enabled and verify its production and sandbox URLs in App Store Connect.
- Run the test matrix below. Resume the scheduler or enable the API only after later approval and a successful credential-path canary.
Rollback redeploys the captured revisions and restores the captured Scheduler state. It does not alter transaction ownership, customer data, Apple keys, or notification history.
Required release evidence
- new monthly and annual purchase;
- Restore Purchases after reinstall;
- same Cookery Trove UID on a second device;
- different Cookery Trove UID under the same Apple subscription is denied;
- sandbox evidence cannot grant production access;
- renewal notification extends the trusted expiration;
- cancellation does not end prepaid access early;
- billing retry and grace-period notification behavior;
- expiration removes paid writes while preserving recovery access and data;
- refund/revocation removes paid writes;
- notification replay is idempotent;
- missed-notification simulation fails closed at the recorded expiration; and
- a later StoreKit restore repairs canonical state without an outbound Server API call.
Any invalid JWS, bundle/product mismatch, ownership mismatch, environment confusion, notification verification failure, unexpected entitlement extension, or outbound Server API request is a release stop condition.