feat(invite): referral push notifications — accepted, inviter reward, invitee reward - #469
Merged
Merged
Conversation
… invitee reward The invite slice of ENG-531 (event notifications). Three pushes, all best-effort (they can never throw into the redeem or payout paths): - inviter: "Your invite was accepted" — fired from the redeem resolver after the ACCEPTED transition, named body when the redeemer has a username, no-name fallback otherwise - inviter: "Referral reward earned — US$X credited" — fired from award-referral-reward only when the inviter's leg is confirmed PAID - invitee: "Welcome reward received — US$X credited" — same, invitee leg Pending IBEX legs deliberately do NOT notify (money unconfirmed; ops reconciles first). Mirrors the bridge-KYC push module end to end: account -> user -> deviceTokens, localized phrases (notification.referral.* added to en + es), dead-token pruning, Payments notification category, typed data payload for client routing. Tests: 7 new module tests (phrase selection, amount formatting, dead-token pruning, never-throws x2) + wiring assertions in the award spec (paid legs push, failed legs never) and redeem spec (accepted push fires with the inviter's id). Touched suites 64/64. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C7z7o9J18BWbUnYJcemMtg
Review fix: the IBEX-pending cases now assert the push behavior — both- pending fires nothing, mixed paid+pending fires exactly the paid leg. Guards the rule most likely to be broken by a future "just notify on pending too" edit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C7z7o9J18BWbUnYJcemMtg
bobodread876
approved these changes
Aug 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The invite slice of ENG-531 (event notifications): three pushes across the referral flow, queued since the feature launch plan.
Design
paidlegs push.notification.referral.*added to en + es), dead-token pruning viaremoveDeviceTokens, Payments category, typeddatapayload (referral_accepted/referral_inviterReward/referral_inviteeReward) for client-side routing.Tests
7 new module tests (phrase selection, $ formatting, dead-token pruning, never-throws ×2) + wiring assertions: award spec (both legs push on paid; failed leg never), redeem spec (accepted push fires with the inviter's id). Full unit suite 1396 passed. (kyc.spec's logger stub gained
.child()— the new import chain reaches the push module's load-time child logger.)No schema changes, no migrations — deployable on the next train.
🤖 Generated with Claude Code