Critical fix: Purchases was never told the Firebase uid, so RevenueCat assigned its
own anonymous app_user_id. The revenueCatWebhook Cloud Function writes premium status
to users/{app_user_id}/entitlements/premium using that id — meaning a real purchase
would silently never unlock premium for the signed-in account, and CouplePremiumChecker's
partner-side read (same path, different uid) was broken by the same root cause.
RevenueCatBillingRepository now collects AuthRepository.authState and calls
Purchases.awaitLogIn(uid) on sign-in / awaitLogOut() on sign-out, guarded against
redundant calls and wrapped best-effort so a failed sync retries on the next auth event
instead of crashing the singleton.
Also:
- Bump com.revenuecat.purchases 8.20.0 -> 10.12.0 (verified: real published version,
stable API surface across 8->10 per RevenueCat's own migration notes for the calls
this app uses; confirmed resolved + full Hilt/KSP graph compiles clean).
- Purchase cancellation (user backs out of the Play billing sheet) is now distinguished
from a real failure via PurchasesTransactionException.userCancelled, using a shared
PURCHASE_CANCELLED_SENTINEL (same marker-constant idiom PaywallViewModel already uses
for offering-load failures) so PaywallViewModel resets silently instead of surfacing
the SDK's internal error text.
- PaywallScreen: genuine purchase errors (billing unavailable, network, etc.) now show
a snackbar. Previously there was zero user-facing feedback on a real purchase failure
beyond the loading spinner disappearing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>