Skip to content

Changes : Added Pro paywall and AI usage gates#56

Merged
aryansoni-dev merged 2 commits into
mainfrom
dev
Jul 15, 2026
Merged

Changes : Added Pro paywall and AI usage gates#56
aryansoni-dev merged 2 commits into
mainfrom
dev

Conversation

@aryansoni-dev

@aryansoni-dev aryansoni-dev commented Jul 15, 2026

Copy link
Copy Markdown
Owner
- Added RevenueCat subscription provider, paywall screens, plan cards, and feature access hooks
- Gated AI chat, entry reflections, and insight reports behind free/Pro monthly limits
- Added Supabase subscription status and AI usage ledger migration plus Edge Function enforcement
- Added RevenueCat environment keys, billing permission, app version bump, and setup docs
- Added Maestro smoke flows, test IDs, and E2E selector documentation
- Improved App Lock controls and fixed preview logout crash during auth navigation

Summary by CodeRabbit

  • New Features
    • Added DearDiary Pro subscriptions with monthly and yearly plans, purchase restoration, and subscription management.
    • Added paywall prompts for premium insights, AI chat, reflections, and reports.
    • Added monthly AI usage limits with clearer upgrade and limit-reached messages.
  • Bug Fixes
    • Improved authentication redirects and subscription-aware access handling.
  • Accessibility
    • Improved labels and navigation support across onboarding, authentication, settings, journaling, and subscription screens.
  • Documentation
    • Updated privacy policy and terms with subscription, billing, renewal, and AI fair-use details.

    - Added RevenueCat subscription provider, paywall screens, plan cards, and feature access hooks
    - Gated AI chat, entry reflections, and insight reports behind free/Pro monthly limits
    - Added Supabase subscription status and AI usage ledger migration plus Edge Function enforcement
    - Added RevenueCat environment keys, billing permission, app version bump, and setup docs
    - Added Maestro smoke flows, test IDs, and E2E selector documentation
    - Improved App Lock controls and fixed preview logout crash during auth navigation
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@aryansoni-dev, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 48 seconds

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: fbf758dc-23a8-477b-977e-4a47f4f54c3d

📥 Commits

Reviewing files that changed from the base of the PR and between 5d2489c and beabcd0.

📒 Files selected for processing (22)
  • .maestro/00-launch.yaml
  • .maestro/00-smoke-launch.yaml
  • app/insights/report/[periodType].tsx
  • components/app-lock/AppLockScreen.tsx
  • components/app-lock/BiometricLockSwitch.tsx
  • components/auth/auth-screen.tsx
  • components/onboarding/onboarding-progress-header.tsx
  • components/paywall/PaywallScreen.tsx
  • components/paywall/PlanCard.tsx
  • components/paywall/PremiumFeatureList.tsx
  • components/profile/profile-screen.tsx
  • data/paywall.ts
  • hooks/useAppSignOut.ts
  • hooks/useReportAccessActions.ts
  • lib/ai/entryReflectionService.ts
  • lib/subscription/featureGates.ts
  • store/useAIUsageStore.ts
  • supabase/functions/_shared/subscriptionAccess.ts
  • supabase/functions/generate-insight-report/index.ts
  • supabase/functions/journal-ai-chat/index.ts
  • supabase/functions/reflect-on-entry/index.ts
  • supabase/migrations/20260715174319_add_ai_usage_reservation_release.sql
📝 Walkthrough

Walkthrough

This PR adds RevenueCat subscriptions, client and server-side AI feature gating, monthly usage tracking, a paywall, subscription documentation, and extensive E2E test identifiers and accessibility metadata across the app.

Changes

Subscription and AI access

Layer / File(s) Summary
RevenueCat foundation and subscription state
lib/subscription/*, providers/*, hooks/useSubscription.ts, store/useAIUsageStore.ts, lib/environment.ts
Adds RevenueCat configuration, subscription context/provider state, entitlement handling, public API-key environment wiring, and persisted monthly AI usage counters.
Paywall and client feature gates
app/paywall.tsx, components/paywall/*, app/insights/report/*, components/ai-chat/*, components/insights/*, components/journal-editor/*, components/profile/profile-screen.tsx
Adds paywall purchase/restore flows and gates AI chat, reflections, reports, advanced insights, and subscription management based on feature access.
Server quota enforcement
supabase/functions/_shared/subscriptionAccess.ts, supabase/functions/*, supabase/migrations/*
Adds subscription-status and AI-usage tables, an atomic quota RPC, RevenueCat entitlement fallback checks, and Edge Function gates before AI provider calls.
Error handling and subscription documentation
lib/ai/*, lib/insights/*, docs/subscription-*, content/legal/*, .env*
Maps quota and fair-use errors to user-facing messages and documents RevenueCat configuration, billing, privacy, fair-use rules, and test scenarios.

E2E selectors and accessibility

Layer / File(s) Summary
Reusable testability contracts
components/ui/*, components/auth/*, components/home/mood/*, components/tags/*, components/states/*, data/profile.ts
Extends shared component props and menu data to forward stable test identifiers and accessibility metadata.
Primary app surfaces
app/(onboarding)/*, components/auth/*, components/home/*, components/journal-*, components/insights/*, components/ai-chat/*
Adds selectors for authentication, onboarding, home, journal editing, history, calendar, AI chat, insights, reports, and navigation controls.
Settings and account surfaces
app/settings/*, components/app-lock/*, components/profile/*, app/sso.tsx
Adds selectors and accessibility metadata for app lock, privacy, profile, notifications, account deletion, and SSO loading states.
Launch flows and selector documentation
.maestro/*, docs/e2e-testid-*, .gitignore
Adds optional Maestro launch/smoke flows and documents stable and dynamic testID conventions.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding a Pro paywall and AI usage gating.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 15

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
components/profile/profile-screen.tsx (1)

189-216: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Extract shared sign-out logic to a custom hook.

The sign-out cleanup logic (clearing the active user ID, sync state, and Supabase token alongside Clerk's signOut) is duplicated here and in components/app-lock/AppLockScreen.tsx. To ensure state is cleared consistently across the app and to simplify future cleanup additions, extract this into a shared hook (e.g., useAppSignOut).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/profile/profile-screen.tsx` around lines 189 - 216, Extract the
Clerk sign-out and cleanup sequence from handleSignOut into a shared
useAppSignOut hook, including clearing the active user ID, per-user sync state,
and Supabase access-token provider. Update both ProfileScreen’s handleSignOut
and AppLockScreen to use the hook, while preserving their existing loading,
error-dialog, and failed-sign-out state behavior.
components/auth/auth-screen.tsx (1)

104-106: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Prevent concurrent authentication flows.

Currently, isAuthActionDisabled does not check socialStrategy, and isSocialActionDisabled does not check isSubmitting. This allows a user to trigger a social SSO flow and a password auth flow simultaneously, which could lead to race conditions or unexpected state overlapping.

Consider combining the busy states so that any active authentication request disables all authentication buttons on the screen.

💡 Proposed fix
-  const isAuthActionDisabled = !isClerkReady || isOffline || isSubmitting;
-  const isSocialActionDisabled =
-    !isClerkReady || isOffline || socialStrategy !== null;
+  const isBusy = isSubmitting || socialStrategy !== null;
+  const isAuthActionDisabled = !isClerkReady || isOffline || isBusy;
+  const isSocialActionDisabled = !isClerkReady || isOffline || isBusy;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/auth/auth-screen.tsx` around lines 104 - 106, Update the
isAuthActionDisabled and isSocialActionDisabled calculations in the auth screen
to share both active-request states, isSubmitting and socialStrategy, so any
ongoing password or social authentication flow disables every authentication
action while preserving the existing Clerk-readiness and offline checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.maestro/00-smoke-launch.yaml:
- Around line 6-36: Require at least one stable launch invariant: in
.maestro/00-smoke-launch.yaml lines 6-36, retain the optional branching checks
but make one final expected screen or stable launch element mandatory; in
.maestro/00-launch.yaml lines 6-28, make one expected app-shell assertion
mandatory instead of leaving every assertion optional.

In `@app/insights/report/`[periodType].tsx:
- Around line 173-202: Update the monthly access branch in the report component
to show the paywall only when reportAccess indicates subscription-required
access, excluding Pro_fair_use_exhausted. For exhausted fair use, preserve the
existing monthly report and display the established fair-use message instead of
the Pro upsell.
- Around line 75-141: The report screen currently contains report-access gating
and generation orchestration that should be reusable. Extract
canUseReportAccess, handleGenerate, handleRegenerate, handleConfirmedRegenerate,
including paywall navigation, dialogs, and usage bookkeeping, into a dedicated
report-access hook; expose the resulting actions/state and update the screen to
compose the hook and invoke them without retaining this business logic.
- Around line 177-182: Update the Text component containing “Monthly AI reports
are included with DearDiary Pro.” to use the required leading-6 typography
instead of leading-8, while preserving its other styling and content.

In `@components/app-lock/BiometricLockSwitch.tsx`:
- Around line 38-39: Update the animated value initialization in
BiometricLockSwitch by replacing the useRef(...).current patterns for progress
and thumbScale with lazy useState initialization. Preserve the existing initial
values based on value for progress and 1 for thumbScale, and continue using the
resulting state values with the existing animation logic.

In `@components/onboarding/onboarding-progress-header.tsx`:
- Around line 34-37: Update the View identified by testID
"onboarding-page-indicator" to set it as accessible so VoiceOver and TalkBack
announce its existing accessibilityLabel. Preserve the current label and layout
behavior.

In `@components/paywall/PaywallScreen.tsx`:
- Around line 177-193: Normalize all paywall text to leading-6: update the
affected text elements in components/paywall/PaywallScreen.tsx at lines 177-193
and 333-355, replacing leading-5, leading-10, and leading-7; also update the
text elements in components/paywall/PlanCard.tsx at lines 47-60, replacing
leading-5, leading-4, and leading-8. Preserve all other styling and content.

In `@components/paywall/PremiumFeatureList.tsx`:
- Around line 4-11: Move the hardcoded benefits collection out of
PremiumFeatureList into a typed export in the data module, then import and use
that export from the component. Preserve the existing benefit text and ordering,
and remove the local benefits declaration.

In `@components/profile/profile-screen.tsx`:
- Around line 483-490: Update the managementUrl handling in the profile screen
so Linking.openURL is wrapped in try/catch; only return after a successful open,
and allow both canOpenURL=false and openURL rejection to continue to the
existing fallback dialog.

In `@lib/ai/entryReflectionService.ts`:
- Around line 300-302: Update the response handling in the entry reflection
service to parse the HTTP 402 response body and distinguish QUOTA_EXHAUSTED from
PRO_FAIR_USE_EXHAUSTED, following the parsing approach used by the report/chat
services. Keep the free-quota upgrade message only for QUOTA_EXHAUSTED and
provide the appropriate Pro fair-use exhaustion message for
PRO_FAIR_USE_EXHAUSTED instead of relying solely on response.status.

In `@lib/subscription/featureGates.ts`:
- Around line 30-32: Update the Pro-only gating branch in the feature-gate
evaluation flow to deny users without Pro access before entering free-quota
checks, including cases where subscriptionAvailable is true. Return the
established Pro-specific denial reason for these features, while preserving free
quota handling for non-Pro-only features.

In `@store/useAIUsageStore.ts`:
- Around line 78-95: Update the onRehydrateStorage callback in useAIUsageStore
to replace direct mutations of state.hasHydrated and state.hydrationError with
useAIUsageStore.setState, preserving the existing values and error-reporting
behavior so subscribed consumers are notified.

In `@supabase/config.toml`:
- Around line 10-11: Update the generate-daily-reflection-prompts configuration
to keep verify_jwt enabled, or replace the current parseJwtClaims validation
with genuine JWT signature verification before accepting the sub claim. Ensure
forged token-like payloads cannot authorize the function.

In `@supabase/functions/_shared/subscriptionAccess.ts`:
- Around line 93-103: AI usage is consumed before downstream work succeeds, so
replace the immediate increment in subscription access with an atomic
reservation/finalization or compensating-release contract. Update
supabase/functions/_shared/subscriptionAccess.ts lines 93-103 to expose that
contract; finalize only after successful generation and persistence in
supabase/functions/generate-insight-report/index.ts lines 355-364, finalize
after a usable reflection in supabase/functions/reflect-on-entry/index.ts lines
304-312, and release reservations on every unsuccessful provider path in
supabase/functions/journal-ai-chat/index.ts lines 485-494 and 583-592.
- Around line 181-197: Update resolveServerSideProEntitlement so the RevenueCat
fallback is protected by a bounded timeout and a short-lived cache, including
for mirrored statuses other than true and missing rows. Reuse existing
timeout/cache utilities or symbols if available, cache the resolved fallback
entitlement per user, and preserve the current false result when RevenueCat
returns null.

---

Outside diff comments:
In `@components/auth/auth-screen.tsx`:
- Around line 104-106: Update the isAuthActionDisabled and
isSocialActionDisabled calculations in the auth screen to share both
active-request states, isSubmitting and socialStrategy, so any ongoing password
or social authentication flow disables every authentication action while
preserving the existing Clerk-readiness and offline checks.

In `@components/profile/profile-screen.tsx`:
- Around line 189-216: Extract the Clerk sign-out and cleanup sequence from
handleSignOut into a shared useAppSignOut hook, including clearing the active
user ID, per-user sync state, and Supabase access-token provider. Update both
ProfileScreen’s handleSignOut and AppLockScreen to use the hook, while
preserving their existing loading, error-dialog, and failed-sign-out state
behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d08ed944-b709-476f-a38a-31a41628751d

📥 Commits

Reviewing files that changed from the base of the PR and between b139662 and 5d2489c.

⛔ Files ignored due to path filters (2)
  • assets/images/landing-page.png is excluded by !**/*.png
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (81)
  • .env.example
  • .env.preview.example
  • .env.production.example
  • .gitignore
  • .maestro/00-launch.yaml
  • .maestro/00-smoke-launch.yaml
  • app.json
  • app/(onboarding)/onboarding-screen-1.tsx
  • app/(onboarding)/onboarding-screen-2.tsx
  • app/(onboarding)/onboarding-screen-3.tsx
  • app/(onboarding)/onboarding-screen-4.tsx
  • app/(onboarding)/onboarding-screen-5.tsx
  • app/(tabs)/_layout.tsx
  • app/_layout.tsx
  • app/insights/report/[periodType].tsx
  • app/paywall.tsx
  • app/settings/app-lock/setup.tsx
  • app/settings/privacy.tsx
  • app/sso.tsx
  • components/ai-chat/ai-chat-screen.tsx
  • components/app-lock/AppLockScreen.tsx
  • components/app-lock/AppLockSettingsComponents.tsx
  • components/app-lock/BiometricLockSwitch.tsx
  • components/app-lock/PinInput.tsx
  • components/auth/auth-screen.tsx
  • components/auth/auth-text-field.tsx
  • components/home/home-screen.tsx
  • components/home/mood/HomeMoodCheckInCard.tsx
  • components/home/mood/MoodCheckInAction.tsx
  • components/home/mood/MoodOption.tsx
  • components/home/mood/MoodSpectrumSelector.tsx
  • components/insights/insights-screen.tsx
  • components/insights/report/ReportScreenStates.tsx
  • components/journal-editor/entry-ai-reflection-card.tsx
  • components/journal-editor/journal-editor-screen.tsx
  • components/journal-history/journal-calendar-view.tsx
  • components/journal-history/journal-history-screen.tsx
  • components/navigation/bottom-tab-bar.tsx
  • components/onboarding/onboarding-progress-header.tsx
  • components/paywall/PaywallScreen.tsx
  • components/paywall/PlanCard.tsx
  • components/paywall/PremiumFeatureList.tsx
  • components/profile/notification-settings-screen.tsx
  • components/profile/profile-screen.tsx
  • components/states/ScreenEmptyState.tsx
  • components/tags/tag-input-modal.tsx
  • components/ui/animated-icon-button.tsx
  • constants/app-lock-theme.ts
  • content/legal/privacyPolicy.ts
  • content/legal/termsAndConditions.ts
  • data/profile.ts
  • docs/e2e-testid-audit.md
  • docs/e2e-testid-map.md
  • docs/environment-matrix.md
  • docs/privacy.md
  • docs/subscription-feature-gating-audit.md
  • docs/subscription-paywall-test.md
  • docs/subscription-setup.md
  • docs/subscription-store-setup.md
  • hooks/useAIInsightReport.ts
  • hooks/useEntryReflection.ts
  • hooks/useFeatureAccess.ts
  • hooks/useSubscription.ts
  • lib/ai/dailyReflectionPromptService.ts
  • lib/ai/entryReflectionService.ts
  • lib/ai/remoteJournalAssistant.ts
  • lib/environment.ts
  • lib/insights/aiInsightReportService.ts
  • lib/subscription/constants.ts
  • lib/subscription/featureGates.ts
  • lib/subscription/revenueCat.ts
  • package.json
  • providers/SubscriptionProvider.tsx
  • store/useAIUsageStore.ts
  • supabase/config.toml
  • supabase/functions/_shared/subscriptionAccess.ts
  • supabase/functions/generate-insight-report/index.ts
  • supabase/functions/journal-ai-chat/index.ts
  • supabase/functions/reflect-on-entry/index.ts
  • supabase/migrations/20260712080005_add_ai_usage_subscription_gates.sql
  • tests/environment.test.ts

Comment thread .maestro/00-smoke-launch.yaml Outdated
Comment thread app/insights/report/[periodType].tsx Outdated
Comment thread app/insights/report/[periodType].tsx Outdated
Comment thread app/insights/report/[periodType].tsx
Comment thread components/app-lock/BiometricLockSwitch.tsx Outdated
Comment thread lib/subscription/featureGates.ts Outdated
Comment thread store/useAIUsageStore.ts
Comment thread supabase/config.toml Outdated
Comment thread supabase/functions/_shared/subscriptionAccess.ts
Comment thread supabase/functions/_shared/subscriptionAccess.ts Outdated
@aryansoni-dev
aryansoni-dev merged commit f96e961 into main Jul 15, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant