feat(mobile): add Apple Kilo Pass purchases#3079
Open
iscekic wants to merge 162 commits into
Open
Conversation
…al-credit-purchases # Conflicts: # apps/web/src/routers/kiloclaw-billing-router.test.ts
Contributor
Author
|
Review-ready status as of head
The only remaining merge blocker is required non-author approval. |
Contributor
Author
|
Bot gone cray, sorry for the ping. |
…al-credit-purchases # Conflicts: # pnpm-workspace.yaml
jeanduplessis
approved these changes
May 12, 2026
Contributor
jeanduplessis
left a comment
There was a problem hiding this comment.
Left one optional suggestion on state.ts about the read-named getter performing a DB write — feel free to take or leave it.
Non-USD refunds (EUR, GBP, etc.) previously threw before writing processed_at, causing Apple to retry forever and leaving subscriptions active with no credit clawback. - getAppleTransactionPriceMicrodollars returns null for non-USD instead of throwing; the stored amount_microdollars on the credit_transactions row for the original purchase is used as the base reversal amount - When no stored amount is found for a non-USD refund, logs to Sentry and skips the base clawback rather than blocking the handler - reverseAppStoreRefundCredits call is wrapped in try/catch so that any remaining error logs to Sentry and processing continues; subscription is always marked ended and processed_at is always written
…ForUser App Store subscriptions have no stripeSubscriptionId, so the function was returning no_subscription instead of a distinct reason. Added a new store_managed_subscription reason variant (paymentProvider: 'apple') that fires when paymentProvider !== 'stripe', updated both admin router consumers and the bulk cancel UI to handle it.
…fications Wrap the REFUND/REVOKE and renewal-completion dispatch branches each in a single outer db.transaction so that credit reversals, subscription status updates, audit log entries, and the processed_at write are committed or rolled back as a unit. - markStoreSubscriptionEnded now accepts a DbOrTx first arg and is exported - reverseAppStoreRefundCredits drops its inner db.transaction; caller owns tx - completeStoreKiloPassPurchase accepts an optional dbOrTx; wraps internally when called without one (backward-compatible for all existing callers) - processAppStoreKiloPassNotification accepts an optional endStoreSubscription override (test-injection pattern matching decodeNotification etc.) - Adds TDD test: rolls back credit reversal and processed_at write when markStoreSubscriptionEnded throws inside the outer transaction
… DrizzleTransaction
Extract the lazy-cancel of store-managed subscriptions out of `getKiloPassStateForUser` (which was performing a DB UPDATE inside a read-named getter) and into a dedicated 15-minute cron at `/api/cron/kilo-pass-store-subscription-reconcile`. The getter still derives `canceled` status from the latest store-purchase `expires_at` so callers see the correct state immediately, but no longer mutates the row — read-only DB connections are now safe.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR replaces the original one-time Apple credit purchase experiment with App Store-managed Kilo Pass subscriptions across the data model, backend APIs, web management surfaces, and mobile purchase flow.
/device-authto show the signed-in account plus a sign-out path before approving a device.Verification
Visual Changes
Visual changes exist for the mobile Kilo Pass/profile purchase flow and web account-management surfaces, but screenshots are not attached in this description update.
Reviewer Notes
APPLE_IAP_ENVIRONMENT.