Skip to content

feat(connect): add account-backed referral points - #8330

Open
shivamhwp wants to merge 26 commits into
pingdotgg:mainfrom
shivamhwp:feat/referral-points
Open

feat(connect): add account-backed referral points#8330
shivamhwp wants to merge 26 commits into
pingdotgg:mainfrom
shivamhwp:feat/referral-points

Conversation

@shivamhwp

@shivamhwp shivamhwp commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Referral points need to belong to a T3 account so the same balance appears on every machine and client.

This adds an append-only referral ledger to the hosted relay. A referred account can claim one code before linking an environment, and its first successful environment link awards the referrer 67 points exactly once. Web, desktop, iOS, and Android use the same account summary. Shared URLs now retain the claim through sign-in, remove the ref parameter from browser history, and automatically apply it after authentication.

Verification report with embedded web, iOS, and Android screenshots:
https://pverr9b7kfgi.postplan.dev

Verified:

  • three real claim-and-link awards in isolated environments, with one account progressing 67 → 134 → 201 points across web, iOS, and Android
  • hosted referral link capture, sign-in prompt, URL cleanup, pending-code retention, and automatic post-sign-in claim
  • exact canonical share URL and honest 67-point share copy in native iOS and Android share surfaces
  • responsive web UI at desktop and narrow widths
  • iOS Simulator and Android release-bundle claim, alert, share, and qualification flows
  • production web and desktop builds plus Electron smoke test
  • 56 focused tests across eight files; shared, web, mobile, desktop, and relay typechecks; targeted lint, format, and mobile native static checks
  • final PR automation: 17 passed, 10 intentionally skipped or neutral, 0 failed

Built with GPT-5.6 Sol in T3 Code using the Codex harness.


Note

Medium Risk
Changes relay persistence, environment-link side effects, and blocks cloud linking when a pending referral claim fails; points logic must stay idempotent under retries and races.

Overview
Adds a T3 account referral program backed by the hosted relay: each user gets a code, referred accounts claim once before their first environment link, and the referrer earns 67 points when that link succeeds. Balances are ledger-based and shared across web, desktop, and mobile.

Relay gains relay_referral_accounts / relay_referral_point_entries, a ReferralProgram service (claim, qualify, idempotent awards, pending recovery), client APIs for summary and claim, qualification after linkEnvironment, and bounded recovery before summary loads and in cron.

Clients wire relay summary/claim through client-runtime and managed-relay state. Web captures ?ref= into local storage, prompts sign-in when needed, auto-claims with retries (ReferralClaimCoordinator), shows referrals in the Clerk profile, and passes a pending code into primary environment linking (claim runs before link). Mobile adds Settings → Referrals (metrics, share/copy, apply code). Privacy policy and user docs describe referral data and retention.

Reviewed by Cursor Bugbot for commit 22ee34f. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add account-backed referral points to relay, client runtime, and apps

  • New ReferralProgram service in ReferralProgram.ts handles account creation, summary aggregation, claim validation with atomic guards, qualification awarding (67 points), and background recovery of missed awards.
  • Adds two authenticated client API endpoints: GET /v1/client/referrals and POST /v1/client/referrals/claim in Api.ts; linkEnvironment now triggers referral qualification as a best-effort side-effect.
  • Database migration in migration.sql creates relay_referral_accounts and relay_referral_point_entries tables with uniqueness constraints for idempotent awards.
  • Web and mobile apps get new referrals UI screens, a ReferralClaimCoordinator that captures referral codes from URLs, prompts sign-in, and claims with bounded retries, plus shared utilities for code normalization and link building.
  • Risk: loadReferralSummary in Api.ts runs recoverPendingAwards with a 500ms budget (REFERRAL_SUMMARY_RECOVERY_BUDGET_MS) before returning the summary; recovery failures and timeouts are logged and ignored. RelayCommonPersistenceError union now includes ReferralProgramPersistenceError.

Macroscope summarized 22ee34f.

@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8d4b7280-4640-4800-b4e3-6e952bd9b9af

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 26, 2026
Comment thread infra/relay/src/http/Api.ts Outdated
Comment thread infra/relay/src/http/Api.ts Outdated
Comment thread apps/web/src/components/cloud/ReferralClaimCoordinator.tsx Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

UI consistency review of the new web referrals surface. Two findings on apps/web/src/components/clerk/ReferralsUserProfilePage.tsx; the rest of the page (error banner, header/refresh action, ClerkUserProfilePage composition, Button/Input/Skeleton primitive usage, icon color indirection) matches the sibling Clerk profile pages.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/clerk/ReferralsUserProfilePage.tsx Outdated
Comment thread apps/web/src/components/clerk/ReferralsUserProfilePage.tsx Outdated
Comment thread apps/web/src/components/cloud/ReferralClaimCoordinator.tsx Outdated
Comment thread infra/relay/src/http/Api.ts Outdated
Comment thread infra/relay/src/referrals/ReferralProgram.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces an account-backed referral program across the relay, database, client runtime, web, and mobile apps. It adds new persistent state and authenticated workflows, and changes environment linking by gating it on referral-claim behavior, so the cross-cutting production impact warrants human review.

You can add or adjust custom eligibility rules. Learn more.

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One control-geometry inconsistency in the new Referrals profile page; everything else lines up with the shared Clerk profile primitives (ClerkUserProfilePage, Input, Button, Skeleton, useCopyToClipboard).

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/clerk/ReferralsUserProfilePage.tsx Outdated
Comment thread infra/relay/src/referrals/ReferralProgram.ts

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the new ReferralProgram Effect service and its call sites (infra/relay/src/http/Api.ts, worker.ts, client runtime/atom wiring). Module layout, inline Context.Service interface, make/layer exports, namespace imports, dependency acquisition via yield*, and the Schema.TaggedErrorClass shape all follow the conventions. One issue: the transaction boundaries re-wrap errors that are already ReferralProgramPersistenceError.

Posted via Macroscope — Effect Service Conventions

Comment thread infra/relay/src/referrals/ReferralProgram.ts
Comment thread infra/relay/src/referrals/ReferralProgram.ts
Comment thread infra/relay/src/referrals/ReferralProgram.ts Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the web referral UI against the shared component system and the sibling Clerk profile pages. The earlier findings (clipboard hook, role="status" on the loading block, input/button size pairing) are resolved. Two remaining consistency items in the newly restructured layout are noted inline.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/clerk/ReferralsUserProfilePage.tsx Outdated
Comment thread apps/web/src/components/clerk/ReferralsUserProfilePage.tsx Outdated
Comment thread apps/web/src/components/cloud/ReferralClaimCoordinator.tsx Outdated
@shivamhwp
shivamhwp force-pushed the feat/referral-points branch from 11a67e7 to cafeba2 Compare August 27, 2026 05:25
Comment thread apps/web/src/components/cloud/ReferralClaimCoordinator.tsx
@shivamhwp
shivamhwp force-pushed the feat/referral-points branch from f5fcf7c to 471bb4a Compare August 27, 2026 05:48

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the web referral UI against the shared primitives and interaction conventions. The earlier findings (icon slot duplication, useCopyToClipboard, role="status", Input/Button size pairing, row alignment) are resolved — Input size="sm" (30px + 1px borders) now matches Button size="sm" (h-8 sm:h-7), and the share row centers its action. One interaction-consistency issue remains in ReferralClaimCoordinator.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/cloud/ReferralClaimCoordinator.tsx
Comment thread infra/relay/src/http/Api.ts
Comment thread apps/web/src/components/clerk/ReferralsUserProfilePage.tsx Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

UI consistency review of the new web referral surfaces. Two findings, both in apps/web/src; the previously flagged items (shared icon slot, useCopyToClipboard, role="status", Input/Button size pairing, sign-in prompt scoped to URL-captured codes) all look addressed at this head.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/clerk/ReferralsUserProfilePage.tsx Outdated
Comment thread apps/web/src/components/cloud/ReferralClaimCoordinator.tsx Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One consistency finding in the new web referrals surface: the two Button size="sm" controls skip the 13px type scale that every other button on the Clerk profile surface pins, so their labels render a step larger than the Refresh button in the same panel.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/clerk/ReferralsUserProfilePage.tsx Outdated
Comment thread apps/web/src/components/clerk/ReferralsUserProfilePage.tsx Outdated
Comment thread infra/relay/src/http/Api.ts Outdated
@shivamhwp
shivamhwp force-pushed the feat/referral-points branch from 6841d4b to ad787ba Compare August 27, 2026 13:16
Comment thread apps/web/src/components/cloud/ReferralClaimCoordinator.tsx

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed the web UI changes for shared-primitive and Tailwind ownership consistency. Prior findings (type scale on size="sm" buttons, clipboard hook, role="status", shared icon slot, stackedThreadToast, text-entry hints, sign-in prompt scoping) are addressed. Three remaining consistency issues, all about how the new page relates to the shared primitives it touches.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/clerk/ClerkUserProfilePage.tsx Outdated
Comment thread apps/web/src/components/clerk/ClerkUserProfilePage.tsx Outdated
Comment thread apps/web/src/components/clerk/ReferralsUserProfilePage.tsx Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One new UI-consistency finding on the web referral surface; the three findings from the previous run (Card surface overrides, ClerkUserProfileRefreshButton variant flip, and the borderless ClerkUserProfileIcon treatment applied to existing rows) are still present and remain open.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/clerk/ReferralsUserProfilePage.tsx Outdated
Comment thread infra/relay/src/referrals/ReferralProgram.ts Outdated
@shivamhwp
shivamhwp force-pushed the feat/referral-points branch from eee2822 to e70d6c5 Compare August 27, 2026 13:48
Comment thread apps/web/src/components/cloud/ReferralClaimCoordinator.tsx Outdated
@shivamhwp
shivamhwp force-pushed the feat/referral-points branch from e70d6c5 to a5d23e1 Compare August 27, 2026 14:03
Comment thread infra/relay/src/http/Api.ts
Comment thread apps/web/src/routes/__root.tsx
Comment thread apps/web/src/components/cloud/ReferralClaimCoordinator.tsx

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding on the new Referrals profile page: the error banner hardcodes the light-mode error surface instead of using the semantic token / the treatment the sibling Clerk profile pages already use.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/clerk/ReferralsUserProfilePage.tsx Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One finding: the new referral error banner hardcodes a destructive tint that the theme owns per-mode, so it loses its surface in dark mode and in custom themes. Everything previously flagged on this PR (Card surface overrides, shared icon slot, refresh-button variant, button/input sizing and type scale, clipboard hook, loading role="status", stacked CTA toast, user-initiated sign-in) now looks addressed.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/clerk/ReferralsUserProfilePage.tsx Outdated
Comment thread apps/web/src/components/cloud/ReferralClaimCoordinator.tsx
Comment thread apps/mobile/src/features/settings/SettingsReferralsRouteScreen.tsx

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 8c7169f. Configure here.

Comment thread apps/web/src/cloud/useCloudLinkController.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant