feat(bento): tag org invite accepted - #2967
Conversation
Stop Invite-to-org reminder workflows when a role binding is written with reason Accepted invitation. Co-authored-by: Cursor <cursoragent@cursor.com>
📝 WalkthroughWalkthroughThe role-binding trigger now tags accepted organization invitees in Bento. Tests cover successful tagging and skipped-tagging paths. Documentation defines the Invite-to-org reminder workflow and its ChangesInvite acceptance Bento synchronization
Estimated code review effort: 2 (Simple) | ~10 minutes Sequence Diagram(s)sequenceDiagram
participant on_user_org_access
participant SupabaseAdmin
participant Bento
on_user_org_access->>SupabaseAdmin: retrieve principal email
SupabaseAdmin-->>on_user_org_access: invitee email
on_user_org_access->>Bento: apply org:invite_accepted segment
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
Comment |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 82b3ad9. Configure here.
| const result = await syncBentoSubscriberTags(c, { | ||
| email, | ||
| segments: [BENTO_ORG_INVITE_ACCEPTED_TAG], | ||
| deleteSegments: [], |
There was a problem hiding this comment.
Global tag stops other invites
Medium Severity
Accepting one org invitation adds subscriber-wide org:invite_accepted, while Bento exits every invite-reminder workflow on that tag. Pending invitations to other orgs can stop getting reminders even though those invites were never accepted.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 82b3ad9. Configure here.
There was a problem hiding this comment.
Stale comment
Risk: medium. Left a non-blocking comment because Cursor Bugbot completed as skipped and reported unresolved findings that need human attention; also above the low-risk approval threshold. Assigned a reviewer for the Bento/org-access path.
Sent by Cursor Approval Agent: Pull Request Approver External
Merging this PR will not alter performance
Comparing Footnotes
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@supabase/functions/_backend/utils/bento_org_invite.ts`:
- Around line 83-111: Propagate Bento synchronization failures instead of
suppressing them: in supabase/functions/_backend/utils/bento_org_invite.ts lines
83-111, update the syncBentoOrgInviteAcceptedOnRoleBindingWrite flow to throw
after logging a false result and rethrow caught errors after structured logging.
In tests/bento-org-invite-accepted.unit.test.ts lines 119-124, expect the helper
to reject while continuing to verify closeClient() executes.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 8b3e4ae2-08e7-412c-843f-bf17e5a61858
📒 Files selected for processing (5)
docs/BENTO_EMAIL_PREFERENCES_SETUP.mdsupabase/functions/_backend/triggers/on_user_org_access.tssupabase/functions/_backend/utils/bento_org_invite.tstests/bento-first-org-route.unit.test.tstests/bento-org-invite-accepted.unit.test.ts
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Cap-go/capacitor-updater(manual)
Drop the dedicated helper; look up email and tag from the webhook payload. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Risk: medium. Left a non-blocking comment because Cursor Bugbot completed as skipped and this invite/Bento behavior change is above the low-risk approval threshold. A reviewer is already assigned for the org-access path; no additional reviewers assigned.
Sent by Cursor Approval Agent: Pull Request Approver External
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@supabase/functions/_backend/triggers/on_user_org_access.ts`:
- Around line 20-31: The invite-accepted trigger must propagate lookup and
tagging failures as retryable errors. In
supabase/functions/_backend/triggers/on_user_org_access.ts:20-31, check the
Supabase lookup error and throw it; capture syncBentoSubscriberTags’ result and
throw only when it is false, preserving undefined for unconfigured Bento. In
tests/bento-first-org-route.unit.test.ts:144-152, add coverage for both cases
and assert each produces a 5xx response.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 7a3374cb-3c32-4d9f-9568-b3b31522963d
📒 Files selected for processing (2)
supabase/functions/_backend/triggers/on_user_org_access.tstests/bento-first-org-route.unit.test.ts
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Cap-go/capacitor-updater(manual)
| if (record.reason === 'Accepted invitation' && record.principal_id) { | ||
| const { data: user } = await supabaseAdmin(c) | ||
| .from('users') | ||
| .select('email') | ||
| .eq('id', record.principal_id) | ||
| .maybeSingle() | ||
| if (user?.email) { | ||
| await syncBentoSubscriberTags(c, { | ||
| email: user.email.trim().toLowerCase(), | ||
| segments: ['org:invite_accepted'], | ||
| deleteSegments: [], | ||
| }) |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Return a retryable failure when invite-accepted tagging cannot complete.
maybeSingle() errors and syncBentoSubscriberTags() returning false currently produce a successful trigger response. The queue then completes without applying org:invite_accepted, so Bento can continue sending invite reminders.
- supabase/functions/_backend/triggers/on_user_org_access.ts#L20-L31: check the Supabase
error, and throw it. Capture the tag result, and throw only when it isfalseso an unconfigured Bento integration can still returnundefined. - tests/bento-first-org-route.unit.test.ts#L144-L152: add cases where the lookup returns an error and where
syncBentoSubscriberTagsMockresolvesfalse; both must return a 5xx response.
Proposed fix
- const { data: user } = await supabaseAdmin(c)
+ const { data: user, error } = await supabaseAdmin(c)
.from('users')
.select('email')
.eq('id', record.principal_id)
.maybeSingle()
+ if (error)
+ throw error
if (user?.email) {
- await syncBentoSubscriberTags(c, {
+ const synced = await syncBentoSubscriberTags(c, {
email: user.email.trim().toLowerCase(),
segments: ['org:invite_accepted'],
deleteSegments: [],
})
+ if (synced === false)
+ throw new Error('Could not sync Bento invite acceptance tag')
}As per coding guidelines, unfinished queue-backed work must be re-enqueued through sweepers or cron.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (record.reason === 'Accepted invitation' && record.principal_id) { | |
| const { data: user } = await supabaseAdmin(c) | |
| .from('users') | |
| .select('email') | |
| .eq('id', record.principal_id) | |
| .maybeSingle() | |
| if (user?.email) { | |
| await syncBentoSubscriberTags(c, { | |
| email: user.email.trim().toLowerCase(), | |
| segments: ['org:invite_accepted'], | |
| deleteSegments: [], | |
| }) | |
| if (record.reason === 'Accepted invitation' && record.principal_id) { | |
| const { data: user, error } = await supabaseAdmin(c) | |
| .from('users') | |
| .select('email') | |
| .eq('id', record.principal_id) | |
| .maybeSingle() | |
| if (error) | |
| throw error | |
| if (user?.email) { | |
| const synced = await syncBentoSubscriberTags(c, { | |
| email: user.email.trim().toLowerCase(), | |
| segments: ['org:invite_accepted'], | |
| deleteSegments: [], | |
| }) | |
| if (synced === false) | |
| throw new Error('Could not sync Bento invite acceptance tag') |
📍 Affects 2 files
supabase/functions/_backend/triggers/on_user_org_access.ts#L20-L31(this comment)tests/bento-first-org-route.unit.test.ts#L144-L152
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@supabase/functions/_backend/triggers/on_user_org_access.ts` around lines 20 -
31, The invite-accepted trigger must propagate lookup and tagging failures as
retryable errors. In
supabase/functions/_backend/triggers/on_user_org_access.ts:20-31, check the
Supabase lookup error and throw it; capture syncBentoSubscriberTags’ result and
throw only when it is false, preserving undefined for unconfigured Bento. In
tests/bento-first-org-route.unit.test.ts:144-152, add coverage for both cases
and assert each produces a 5xx response.
Source: Coding guidelines
|







Summary (AI generated)
org:invite_acceptedBento tag when a user-orgrole_bindingsrow is written with reasonAccepted invitationon_user_org_access(covers dashboard RPC + private accept-invitation API)Motivation (AI generated)
Invite-to-org reminder emails had no stop signal after accept. Bento could not know the invitee joined.
Business Impact (AI generated)
Stops invite reminder spam after acceptance. Improves invitee experience and keeps Bento workflows accurate.
Test Plan (AI generated)
Tag contains: org:invite_accepted→ End before reminder sendsorg:invite_acceptedGenerated with AI
Made with Cursor
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by CodeRabbit
New Features
org:invite_acceptedstatus to the invitee.Documentation
Tests