feat(referrals): rework reward engine + email-verified landing #48

Merged
root merged 1 commits from dev into main 2026-05-25 14:13:35 +03:00
Owner

Reward engine:

  • Recurring milestones (every 3 → +7d, every 5 → +14d) instead of one-time
    tiers capped at 5; idempotent + transactional grants serialised per
    referrer so concurrent qualifications can't double-count.
  • Rewards now gated on the referred user's email verification
    (afterEmailVerification hook); already-verified referees (OAuth) qualify
    at apply time.
  • Reward days banked as users.referral_credit_days when the referrer has no
    live subscription, consumed on next trial start / activation (no more
    silently lost rewards).
  • Accurate cumulative rewardDays in stats; getMyReferrals returns referee
    name/masked email/status.

Hardening / cleanup:

  • onConflictDoNothing makes apply idempotent (no unhandled unique violation).
  • Anti-fraud: normalizeEmail blocks self-referral via gmail dot/+tag aliases.
  • Collision-safe referral code generation at signup.
  • Single apply path (welcome onboarding modal); removed duplicate calls in
    register + subscription pages. Input validation on the apply code.

Email verification UX:

  • Verification link now lands on a dedicated /email-verified confirmation
    page instead of the deep-linked VIN/search page.

Schema: referrals.status + qualified_at, users.referral_credit_days (0009).

Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com

Reward engine: - Recurring milestones (every 3 → +7d, every 5 → +14d) instead of one-time tiers capped at 5; idempotent + transactional grants serialised per referrer so concurrent qualifications can't double-count. - Rewards now gated on the referred user's email verification (afterEmailVerification hook); already-verified referees (OAuth) qualify at apply time. - Reward days banked as users.referral_credit_days when the referrer has no live subscription, consumed on next trial start / activation (no more silently lost rewards). - Accurate cumulative rewardDays in stats; getMyReferrals returns referee name/masked email/status. Hardening / cleanup: - onConflictDoNothing makes apply idempotent (no unhandled unique violation). - Anti-fraud: normalizeEmail blocks self-referral via gmail dot/+tag aliases. - Collision-safe referral code generation at signup. - Single apply path (welcome onboarding modal); removed duplicate calls in register + subscription pages. Input validation on the apply code. Email verification UX: - Verification link now lands on a dedicated /email-verified confirmation page instead of the deep-linked VIN/search page. Schema: referrals.status + qualified_at, users.referral_credit_days (0009). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
root added 1 commit 2026-05-25 14:13:25 +03:00
feat(referrals): rework reward engine + email-verified landing
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
3926e276fd
Reward engine:
- Recurring milestones (every 3 → +7d, every 5 → +14d) instead of one-time
  tiers capped at 5; idempotent + transactional grants serialised per
  referrer so concurrent qualifications can't double-count.
- Rewards now gated on the referred user's email verification
  (afterEmailVerification hook); already-verified referees (OAuth) qualify
  at apply time.
- Reward days banked as users.referral_credit_days when the referrer has no
  live subscription, consumed on next trial start / activation (no more
  silently lost rewards).
- Accurate cumulative rewardDays in stats; getMyReferrals returns referee
  name/masked email/status.

Hardening / cleanup:
- onConflictDoNothing makes apply idempotent (no unhandled unique violation).
- Anti-fraud: normalizeEmail blocks self-referral via gmail dot/+tag aliases.
- Collision-safe referral code generation at signup.
- Single apply path (welcome onboarding modal); removed duplicate calls in
  register + subscription pages. Input validation on the apply code.

Email verification UX:
- Verification link now lands on a dedicated /email-verified confirmation
  page instead of the deep-linked VIN/search page.

Schema: referrals.status + qualified_at, users.referral_credit_days (0009).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
root merged commit d459995292 into main 2026-05-25 14:13:35 +03:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: root/sase.tr#48