# App Store release runbook

This runbook covers dashboard work that cannot be committed to the repository. Do it in order: later systems depend on identifiers and keys from earlier ones.

> **Note:** this runbook targets the **production** app. Per the plan in
> [environments.md](environments.md), the production app will be recreated
> under the H14H, LLC org developer account before public launch — the current
> personal-account ASC app (Apple ID 6790872998) is pre-launch scaffolding, and
> this runbook is re-run under the LLC account at that point. The sandbox app
> ("Glide Beta") has its own, much shorter setup in environments.md.

## What is already in the repository

- App identity: `Glide`, bundle ID `com.h14h.glide`, version `1.0.0`.
- EAS production profile with remote build numbers and automatic incrementing.
- StoreKit purchase and restore flow through RevenueCat.
- Server-side RevenueCat verification before Convex allows sync.
- 15-day read-only grace period and scheduled cloud-data wipe.
- In-app account deletion and batched Convex data deletion.
- Subscription disclosures and Privacy Policy / Terms links.
- App privacy manifest declarations.
- App Store metadata draft in `store.config.json`.
- Public Privacy Policy: https://glide.expo.app/privacy
- Public support page: https://glide.expo.app/support

A production build intentionally fails if its Clerk, Convex, or RevenueCat client configuration is missing or uses test credentials.

## 1. App Store Connect

1. Open **Agreements, Tax, and Banking**.
2. Accept the Paid Apps Agreement and complete banking and tax forms.
3. In **Certificates, Identifiers & Profiles**, confirm these identifiers/capabilities:
   - `com.h14h.glide`
   - `com.h14h.glide.widgets`
   - App Group `group.com.h14h.glide`
4. In **My Apps**, create Glide if it does not exist:
   - Platform: iOS
   - Name: Glide
   - Primary language: English (U.S.)
   - Bundle ID: `com.h14h.glide`
   - SKU: an internal stable value such as `glide-ios`
5. Record the app's numeric **Apple ID**; this becomes `ascAppId` for EAS submission.

## 2. App Store subscriptions

1. In Glide's App Store Connect record, create one subscription group named **Glide Sync**.
2. Add two auto-renewable subscriptions:
   - `glide_sync_monthly` — one month — target price USD $2
   - `glide_sync_yearly` — one year — target price USD $20
3. Add an English display name and description for each product.
4. Add availability and pricing for intended storefronts.
5. Add the required subscription review screenshot. It should show Glide's plan selection/confirmation UI and the displayed price.
6. Keep both products ready to submit; they are attached to the first app version later.
7. Create/download an **In-App Purchase key** for RevenueCat and record its key ID and issuer ID. The `.p8` file is downloadable only once.

## 3. Production Clerk

1. Create or promote a production Clerk instance.
2. Enable the authentication methods Glide supports (email/password and email verification).
3. Enable first/last-name editing if desired.
4. **Enable users deleting their own accounts.** Glide disables its deletion button when Clerk reports that this is off.
5. Create a JWT template named `convex` with audience `convex`.
6. Record:
   - Production publishable key (`pk_live_…`)
   - JWT issuer domain used by the template
7. Complete any Clerk production-domain/DNS requirements.

## 4. RevenueCat production app

1. In the existing RevenueCat project, add an **App Store** app with bundle ID `com.h14h.glide`.
2. Upload/configure the App Store Connect In-App Purchase key from step 2.
3. Import `glide_sync_monthly` and `glide_sync_yearly`.
4. Confirm the project-level entitlement is exactly `sync`.
5. Attach the products to the current offering:
   - Monthly product → `$rc_monthly`
   - Annual product → `$rc_annual`
6. Make that offering current.
7. Copy the public Apple SDK key (`appl_…`) for EAS.
8. Create/copy a **secret REST API v1 key** for Convex. Never put this key in an `EXPO_PUBLIC_` variable or the app bundle.
9. Configure App Store Server Notifications V2 using the RevenueCat-provided URL for both sandbox and production.
10. Review RevenueCat's restore/transfer behavior. Glide identifies customers by Clerk user ID and expects restoration with the same Glide account.

## 5. Production Convex

1. Open the production Convex deployment's **Settings → Environment Variables**.
2. Add:
   - `CLERK_JWT_ISSUER_DOMAIN` = the production Clerk issuer domain
   - `REVENUECAT_SECRET_API_KEY` = the RevenueCat secret REST API key
3. Deploy the current backend:

   ```bash
   npx convex deploy
   ```

4. Record the production deployment URLs:
   - `https://….convex.cloud`
   - `https://….convex.site`
5. Confirm the deployment contains `account`, `entitlements`, `revenuecat`, and `sync` functions and an `entitlements` table.

## 6. EAS production environment

In Expo/EAS project **Environment Variables**, create these variables for the **production** environment. They are client-visible by design and can use Plain text visibility:

- `EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY` = `pk_live_…`
- `EXPO_PUBLIC_CONVEX_URL` = production `convex.cloud` URL
- `EXPO_PUBLIC_CONVEX_SITE_URL` = production `convex.site` URL
- `EXPO_PUBLIC_REVENUECAT_KEY` = RevenueCat `appl_…` key

For preview/Test Store testing, also add `EXPO_PUBLIC_REVENUECAT_KEY=test_…` to the EAS **preview** environment and configure the matching RevenueCat secret key on the preview Convex deployment. The `testflight` build profile uses this preview environment but produces an App Store-distribution binary suitable for internal TestFlight; it deliberately does not use the live-production credential guard.

Do not set `EXPO_PUBLIC_ENABLE_PURCHASE_STUB` in EAS. The stub is development-only, but leaving it unset avoids confusion.

## 7. Submission credentials

1. In App Store Connect **Users and Access → Integrations**, create an App Store Connect API key with App Manager access for EAS submission.
2. Configure it with `eas credentials -p ios`, or supply it when EAS prompts during the first submission.
3. Optionally add `appleId`, `appleTeamId`, and `ascAppId` under `submit.production.ios` in `eas.json` after confirming their exact values.

Never commit `.p8`, `.mobileprovision`, password, or secret API key files.

## 8. Build and TestFlight

Before paid-production setup is complete, create and submit an internal TestFlight build backed by preview services:

```bash
eas build --platform ios --profile testflight
eas submit --platform ios --profile testflight --latest
```

This can exercise local features, auth, sync, account deletion, and—after the preview RevenueCat keys are configured—the RevenueCat Test Store. It does not validate Apple's real product catalog, receipts, or server notifications.

After the live Clerk/Convex/RevenueCat configuration is complete, replace it with the true production build:

```bash
eas build --platform ios --profile production
eas submit --platform ios --profile production --latest
```

Then test on at least one physical iPhone:
   - Fresh install and local-only task use
   - Planning, task completion, streaks, dark mode
   - Widget and quick actions
   - Monthly purchase and annual purchase in sandbox
   - Cancelled purchase
   - Restore after reinstall using the same Glide account
   - Signed-in sync across two devices
   - Offline edits and later reconciliation
   - Billing/grace UI with RevenueCat sandbox/Test Store controls
   - Account deletion, including confirmation that cloud rows and Clerk identity disappear while local tasks remain
Finally, put the tested live-production build through external TestFlight beta review if possible.

## 9. App Store listing

1. Review `store.config.json`, especially copyright ownership and marketing copy.
2. After the first binary exists in App Store Connect, push the draft metadata:

   ```bash
   eas metadata:push --profile production
   ```

3. In App Store Connect, supply anything not handled by metadata:
   - iPhone screenshots
   - App icon/build selection
   - Subscription review screenshots
   - Pricing and availability
   - Age rating answers
   - App Review contact information
   - Review notes and a demo Glide account
4. Use these URLs:
   - Privacy Policy: https://glide.expo.app/privacy
   - Support: https://glide.expo.app/support
   - Marketing: https://glide.expo.app
   - Terms: https://www.apple.com/legal/internet-services/itunes/dev/stdeula/
5. Complete App Privacy answers consistently with `app.json` and the policy. Expected categories include name, email address, user ID, device ID, task content, and purchase history, all for app functionality and not tracking. Verify Clerk, Convex, and RevenueCat disclosures before answering.
6. Add review notes explaining:
   - Core tasks work without an account.
   - Glide Sync is the subscription feature.
   - The reviewer reaches it through **You → Enable Sync**.
   - Account deletion is under **You → Account**.
   - Restore is on the Sync plan screen.
7. Attach both subscriptions to version 1.0 and submit the subscriptions with the app's first review.
8. Select manual release for the first version, then submit for review.
