Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 33 additions & 11 deletions apps/mobile/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,39 @@ Changes require a new iOS build; an over-the-air update cannot change the native
4. `pnpm start`
5. open installed app on your phone

## App Store Kilo Pass Subscriptions

App Store Kilo Pass subscriptions require an EAS development build or TestFlight
build with the in-app purchase capability enabled. Expo Go is not supported for
this feature.

Configured auto-renewable subscription product IDs:

- `kilopass.tier19.monthly.v1`
- `kilopass.tier49.monthly.v1`
- `kilopass.tier199.monthly.v1`
## Kilo Pass status and legacy purchase recovery

Version 1.0.15 removes native Kilo Pass subscription sales and upgrades on both
platforms. Profile opens a read-only status screen for store and web subscriptions,
with streak, bonus credits, and paid-period end where the current backend state
provides it. The screen contains no web checkout or billing-management links.
The organization hub also shows read-only Kilo Pass state without checkout or
web subscription-management actions.
Active legacy subscriptions retain access to their platform's store-management sheet.
An owned active SDK receipt also keeps store management reachable when web state
is primary or recovery is incomplete. SDK evidence does not grant benefits.
Native one-off credit packs, localized prices, legal links, and recovery remain enabled.

The forced-upgrade build itself completes already-paid, unfinished subscriptions:
`StorePurchaseRecoveryMount` reconnects and submits verified receipts on launch and
foreground regain, without opening a sales screen. Explicit Restore Purchases is
also available on the status screen. Account epochs fence submission and feedback;
pending payments wait for approval; the store transaction finishes only after
backend completion succeeds. Historical subscription identifiers are retained
independently of current sale availability or store product lookup.

Store recovery requires an EAS development or release build with billing enabled;
Expo Go cannot verify it. Legacy identifiers retained for reconciliation:

- Apple: `kilopass.tier19.monthly.v1`, `kilopass.tier49.monthly.v1`,
`kilopass.tier199.monthly.v1`
- Play: `kilopass_tier19`, `kilopass_tier49`, `kilopass_tier199`

Release notes for 1.0.15: remove subscription sales while preserving paid benefits,
legacy receipt recovery, and one-off credit purchases. `CHANGELOG.md` remains
release-generated: `scripts/kilo-app-release-notes.mjs` adds this merged PR after an
actual store submission supplies its build identity. This change does not submit
a release, raise minimum versions, or retire store renewals.

Use App Store Connect sandbox tester accounts for local and TestFlight sandbox
verification. Configure App Store Server Notifications V2 to post to
Expand Down
5 changes: 1 addition & 4 deletions apps/mobile/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,7 @@ const config: ExpoConfig = {
name: 'Kilo',
owner: 'kilocode',
slug: 'kilo-app',
// Keep in lockstep with AGENT_CHANNEL_SPLIT_APP_VERSION in
// @kilocode/notifications: this is the first build that creates the split
// agent channels, so older tokens stay on the legacy `agent` channel.
version: '1.0.13',
version: '1.0.15',
// Rotation is supported on iOS and Android: `default` resolves to portrait +
// both landscapes in UISupportedInterfaceOrientations on iOS and all
// orientations in the Android manifest, satisfying WCAG 1.3.4 (Orientation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,8 @@ type InFlightOwnedRecovery = { epoch: number; promise: Promise<boolean> };
* The single `useIAP` call site for the credits route.
*
* expo-iap registers its purchase listeners at module scope, so the app must
* never mount two owners at once. The Kilo Pass route is popped before the
* credits route can be pushed, so `KiloPassNativeIapOwner` and this owner never
* coexist; a future route that mounts both would double-handle every purchase.
* never mount two owners at once. Subscription restoration uses value-returning
* store calls, leaving this as the app's only purchase-listener owner.
*/
export function CreditNativeIapOwner({ children }: { children: ReactNode }) {
const trpc = useTRPC();
Expand Down
Loading
Loading