SpeakTrue

iOS Subscription Reintroduction Plan

Reader and action

This document is for a future engineer or agent planning to reintroduce user subscriptions in the iOS app after the free-app cleanup. After reading it, they should be able to draft an implementation checkpoint with the right dependencies, sequencing, verification gates, and rollback plan.

This is a planning document, not an implementation runbook. Do not treat any section as permission to enable paid access without a new checkpoint, product decision, legal review, backend contract review, and App Store release plan.

Current baseline

The current iOS app is free-only.

The prior iOS subscription surface was deliberately removed rather than hidden. The app no longer ships a StoreKit billing service, local StoreKit configuration, subscription Settings route, restore-purchases UI, Pro/Premium plan state, local isPro gating, paid-tier BYOK response handling, or paid-plan copy in active iOS user-facing flows.

Active legal copy also describes the current iOS build as free, with no paid feature paywalls. Reintroducing subscriptions therefore changes more than UI. It changes product behavior, account lifecycle handling, App Review metadata, legal copy, privacy disclosure assumptions, backend entitlement semantics, and cross-platform parity expectations.

Decision gate before implementation

Before writing code, make these decisions explicitly and record them in planning artifacts:

  1. Subscription purpose — What does a paid subscription unlock?
    • Higher TTS/STT quotas?
    • Voice clone creation/deletion?
    • Soundboard category limits?
    • BYOK cloud storage/resolution?
    • Priority processing or future-only features?
  2. Free tier contract — What remains available without payment?
  3. Entitlement source of truth — Which backend table/function determines whether a user is active paid, expired, trialing, admin, or legacy?
  4. Billing authority — Is Apple StoreKit the only iOS purchase authority, or can web/Stripe entitlements also unlock iOS features?
  5. Restore behavior — What should Restore Purchases do when Apple reports no active transaction but backend has a legacy entitlement?
  6. Account deletion behavior — Should paid/legacy users be blocked, warned, routed to support, or allowed to delete with entitlement cleanup?
  7. Cross-surface parity — Should Android/web gain the same subscription behavior at the same time, or is iOS intentionally first?
  8. Rollback model — If App Review or production billing fails, can the app return to free-only without data loss or stuck entitlements?

If any answer is unknown, plan a discovery slice before implementation.

Non-goals for an iOS-only reintroduction

Do not do these accidentally while restoring iOS subscriptions:

Required architecture

1. StoreKit purchase and restore layer

A restored iOS subscription implementation needs a StoreKit 2 boundary that owns:

The client may observe Apple transactions, but backend authorization should still be confirmed through an authenticated server boundary. The iOS app should not decide permanently that a user is Pro solely because a local transaction appears valid.

2. Backend entitlement sync

The backend must expose authenticated server-side endpoints for Apple subscription sync. The endpoint contract should define:

The iOS app should consume a normalized entitlement response rather than raw provider or database details.

3. Auth state and entitlement state

Do not overload signed-in state with billing behavior unless the distinction is intentional and tested. Prefer a separate entitlement model with states such as:

The UI can derive display copy from that model, but backend-gated actions should still use server enforcement.

4. Feature gates

Each paid feature needs an explicit gate contract:

Feature family Required decision Backend enforcement required? Local UI behavior
TTS quota Daily/period limit per tier Yes Explain limit and reset/upgrade path
STT quota Byte/minute limit per tier Yes Explain limit and reset/upgrade path
Voice clone Whether creation/deletion is paid-only Yes Block before upload when entitlement is known insufficient
Soundboard Whether category/clip limits return Yes for durable limits Show limit before create/reorder where possible
BYOK Whether paid tier changes cloud BYOK behavior Yes if server storage is used Keep local-key fallback separate from paid cloud behavior

Do not restore a local UI gate unless the backend has an equivalent enforcement point or the gate is explicitly cosmetic.

Suggested checkpoint decomposition

Slice 1 — Product and contract brief

Produce the paid-tier contract before code changes.

Deliverables:

Verification:

Slice 2 — Backend entitlement and Apple sync contract

Implement or verify the authenticated backend contract that iOS will call after StoreKit purchases and restores.

Deliverables:

Verification:

Slice 3 — iOS StoreKit runtime restoration

Restore the iOS StoreKit service boundary without exposing subscription UI everywhere yet.

Deliverables:

Verification:

Slice 4 — iOS Settings/paywall UI

Restore user-facing subscription surfaces only after runtime and backend contracts are testable.

Deliverables:

Verification:

Slice 5 — Feature gates

Restore feature-specific paid behavior one gate family at a time.

Recommended order:

  1. Read-only status display and entitlement refresh
  2. TTS/STT quota copy and local preflight hints
  3. Voice clone local blocked reason and disabled button
  4. Soundboard limit copy and create/category guard
  5. BYOK cloud behavior, only if explicitly included in the paid tier contract

Verification:

Update user-facing legal and release surfaces after the paid product contract is stable.

Deliverables:

Verification:

Slice 7 — Rollout and rollback

Ship behind a deliberate rollout boundary.

Deliverables:

Verification:

iOS implementation details to plan explicitly

StoreKit service behavior

The service should not block app launch forever. Product loading should have a timeout or independent loading state. Startup can show paid status as unknown while the rest of the app remains usable.

Purchase flow should distinguish:

Each case needs fixed public copy and redacted diagnostics.

Restore purchases behavior

Restore must be idempotent and safe to retry. A successful Apple restore should still sync with backend before backend-gated features unlock. If no transactions are restored, the UI should explain that no active Apple subscription was found and point to support if the user believes that is wrong.

Account deletion behavior

Do not silently hide recovery guidance. Decide whether active paid users can delete directly. If deletion is blocked for legacy or paid state, iOS should show fixed public copy and support guidance, not raw backend messages.

Entitlement refresh behavior

The app needs an explicit refresh action or automatic refresh points after:

Unknown entitlement state should not accidentally grant paid access.

Offline behavior

Decide what paid features do offline. Reasonable default:

Diagnostics and observability

Use bounded labels and state transitions. Do not log:

Useful diagnostic labels include:

Verification matrix

Area Minimum verification
Build iOS app builds on a concrete simulator destination
StoreKit Local StoreKit tests cover purchase, cancellation, pending, restore, and failure
Backend sync Backend tests cover transaction verification, idempotency, expiry, revoke, malformed input, and stable errors
Settings UI Tests prove subscription route is visible only when intentionally enabled
Voice clone Tests cover free blocked, paid allowed, unknown blocked, validation preserved, preflight preserved
TTS/STT Tests cover quota copy and backend quota rejection mapping
Soundboard Tests cover paid/free limit copy and backend category-cap behavior if included
Account deletion Tests cover active paid, expired, legacy, and failed backend responses with fixed copy
Legal copy Static scan ensures active legal copy matches paid behavior
Privacy App Store privacy labels and policy mention purchase/entitlement data if collected
Rollback Tests or static checks prove paid UI/gates can be disabled without deleting entitlement history

Use concrete simulator destinations for XCTest. Generic iOS simulator destinations cannot run unit tests for this project.

Rollback plan

A safe rollback should be planned before release.

Rollback should be able to:

  1. Hide iOS subscription UI.
  2. Stop local paid-feature gates from blocking free users.
  3. Keep backend entitlement history intact for audit/support.
  4. Disable or ignore quota/paid-tier enforcement through backend configuration.
  5. Preserve account deletion and support guidance.
  6. Restore free-app legal copy only if the public paid offer is fully withdrawn.

Do not roll back by deleting customer transaction history or entitlement records.

Documentation updates required when implementing

When actual implementation begins, update:

The docs should state the current state only. Historical planning notes can remain, but active policy copy must not contradict the released app.

Ready-to-plan checklist

Do not start implementation until these are true: