feat(referrals): rework reward engine + email-verified landing
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
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>
This commit is contained in:
@@ -44,7 +44,14 @@ export { paginationSchema } from "./schemas/pagination.js";
|
||||
|
||||
// Constants
|
||||
export { VIN_REGEX, EMAIL_REGEX, OEM_CODE_REGEX } from "./constants/regex.js";
|
||||
export { PLANS, REFERRAL_REWARDS, CURRENCY, FULL_PLAN_BRAND_LIMIT } from "./constants/plans.js";
|
||||
export {
|
||||
PLANS,
|
||||
REFERRAL_REWARDS,
|
||||
CURRENCY,
|
||||
FULL_PLAN_BRAND_LIMIT,
|
||||
referralRewardForCount,
|
||||
referralTotalRewardDays,
|
||||
} from "./constants/plans.js";
|
||||
export { ERROR_CODES } from "./constants/error-codes.js";
|
||||
export type { ErrorCode } from "./constants/error-codes.js";
|
||||
|
||||
@@ -62,4 +69,5 @@ export {
|
||||
formatDateTime,
|
||||
slugify,
|
||||
generateReferralCode,
|
||||
normalizeEmail,
|
||||
} from "./utils/formatters.js";
|
||||
|
||||
Reference in New Issue
Block a user