fix(trust-safety): referral #891, notifications idempotency, support dedup, collaborator RBAC, legal + DPDP docs - #989
fix(trust-safety): referral #891, notifications idempotency, support dedup, collaborator RBAC, legal + DPDP docs#989teetangh wants to merge 2 commits into
Conversation
…ollaborator perms, legal constants, DPDP docstring Trust & safety sweep bundling seven correctness/compliance fixes: - Referral stash no longer wiped when landing without ?ref= (#891). - Novu triggers carry a deterministic transactionId (dedup) and fail loud via Sentry when unconfigured in prod; reminders pass a per-window key. - Payment-linked support tickets dedup against an open ticket; staff status transition is now a status-guarded CAS (updateMany). - Collaborator permission booleans are set at invite time; canSeeAttendees is enforced on the participant-roster endpoints. - Legal constants set name=Practitionist and drop the [ADDRESS] placeholder and its rendered blocks; contact emails kept as loud TODO placeholders. - DPDP header docstring corrected to describe the live fail-closed behavior. - Webinar/class XOR added to the check-constraints.sql sidecar. Closes #891 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 3 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (19)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces several updates, including removing company address details from public pages, adding granular collaborator permissions with restricted roster access, implementing status-guarded CAS and deduplication for support tickets, persisting referral codes during signup, and introducing deterministic transaction IDs for Novu notifications to prevent duplicate sends. Feedback on these changes highlights a security concern where internal staff notes are leaked to end-users during support ticket deduplication, which requires filtering the returned responses. Additionally, the use of relation filters inside Prisma's findUnique for participant roster queries will cause TypeScript compilation errors; these queries should be updated to use findFirst instead.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
✅ Deploy Preview for familiarise ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
…response, findFirst for relation filters Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|



Trust & safety sweep — seven scoped correctness/compliance fixes.
Fixes
app/auth/signup/page.tsx:92. Landing without?ref=no longer clears a previously stashed referral code; only an explicit different code overwrites it.clearPendingReferralimport dropped.lib/novu/service.ts. Every trigger now carries a deterministictransactionIdderived from workflow + recipient(s) + payload (or an explicitdedupeKey), so app-level retries can't double-notify. Unconfigured Novu in production emits a SentrycaptureMessageinstead of a silentconsole.warn.scripts/appointments/send-appointment-reminders.tspasses a per-windowdedupeKeyso the 1h reminder isn't swallowed as a duplicate of the 24h one.app/api/user/support-tickets/route.ts:172reuses an existing open (status NOT IN RESOLVED/CLOSED) ticket for the samepaymentId+user instead of creating a duplicate (runtime check, no schema unique).app/api/staff/support-tickets/[ticketId]/responses/route.ts:70OPEN→IN_PROGRESS is now a status-guardedupdateManyCAS so concurrent staff edits don't clobber.schemas/collaborators.ts,lib/collaborators/service.ts, bothapp/api/collaborations/{webinar,class}/[planId]/route.ts). Enforced:canSeeAttendeesat the participant-roster GETs (app/api/participants/{webinar,class}/[id]/route.ts) — an accepted collaborator sees the roster only if granted. Set-but-not-enforced (no surface yet, terse TODO):canApprovePayment,canViewAnalytics,canEditEvent. Added the webinar/class XOR toprisma/sql/check-constraints.sql(raw-SQL sidecar, mirrors app-levelassertCollaboratorPlanXor).app/(pages)/constants.tssetsname: "Practitionist", removes the[ADDRESS]placeholder and its rendered Registered-Address blocks (about/privacy/terms/contactus/refund; unusedMapPinimport dropped).email/supportEmailkept as placeholders with a loud// TODO: real contact email before launch.lib/compliance/dpdp.tsheader corrected:checkConsentis live fail-closed (not "returns true unconditionally") andrecordConsentwrites a real SHA-256 artifact.app/form/onboarding/page.tsxtrims toundefined;app/api/user/[id]/route.tsusesemptyToUndefined). The sharedPersonalInfoAndRoleSchemais unused. No change needed.Notes
prisma/sql/check-constraints.sqlneeds the central migration apply (npm run db:constraints) after the next push/reset — it does not self-apply.prisma/schema.prismachange; support dedup is a runtime check by design.Closes #891
🤖 Generated with Claude Code