Skip to content

feat(bento): tag org invite accepted - #2967

Merged
riderx merged 2 commits into
mainfrom
feat/bento-org-invite-accepted-tag
Aug 9, 2026
Merged

feat(bento): tag org invite accepted#2967
riderx merged 2 commits into
mainfrom
feat/bento-org-invite-accepted-tag

Conversation

@riderx

@riderx riderx commented Aug 9, 2026

Copy link
Copy Markdown
Member

Summary (AI generated)

  • Add org:invite_accepted Bento tag when a user-org role_bindings row is written with reason Accepted invitation
  • Wire tagging into on_user_org_access (covers dashboard RPC + private accept-invitation API)
  • Document Match → End setup for Invite-to-org reminder workflow

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)

  • Unit tests for tag helper (accept path + skip cases)
  • Route unit tests assert invite helper is dispatched
  • In Bento workflow 13469: Match Tag contains: org:invite_accepted → End before reminder sends
  • Manual: accept an org invite → confirm subscriber has org:invite_accepted

Generated with AI

Made with Cursor


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Added an Invite-to-organization reminder workflow that automatically ends when an invitation is accepted.
    • Accepted invitations now apply an org:invite_accepted status to the invitee.
  • Documentation

    • Added setup guidance covering workflow triggers, exit conditions, and status behavior.
  • Tests

    • Added coverage for successful invitation acceptance and cases where status updates are correctly skipped.

Stop Invite-to-org reminder workflows when a role binding is written with reason Accepted invitation.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The 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 org:invite_accepted exit condition.

Changes

Invite acceptance Bento synchronization

Layer / File(s) Summary
Invite acceptance synchronization implementation
supabase/functions/_backend/triggers/on_user_org_access.ts
The trigger retrieves the principal email and applies the org:invite_accepted Bento segment for accepted invitations.
Trigger validation and reminder workflow
tests/bento-first-org-route.unit.test.ts, docs/BENTO_EMAIL_PREFERENCES_SETUP.md
Tests cover successful tagging, non-invitation events, and validation or authentication failures. Documentation defines the reminder workflow entry and exit conditions.

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
Loading

Possibly related PRs

  • Cap-go/capgo.app#2841: Adds the accepted-invitation handling and Bento tagging built on the same trigger and route tests.

Suggested labels: codex

Suggested reviewers: wcaleniewolny

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding an org:invite_accepted Bento tag.
Description check ✅ Passed The description explains the change, motivation, impact, and test plan; missing checklist details are non-critical for this backend change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added the codex label Aug 9, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ 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.

Comment thread supabase/functions/_backend/utils/bento_org_invite.ts Outdated
const result = await syncBentoSubscriberTags(c, {
email,
segments: [BENTO_ORG_INVITE_ACCEPTED_TAG],
deleteSegments: [],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 82b3ad9. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

@codspeed-hq

codspeed-hq Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing feat/bento-org-invite-accepted-tag (566dbff) with main (918f7dc)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@cursor
cursor Bot requested a review from WcaleNieWolny August 9, 2026 21:00

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 918f7dc and 82b3ad9.

📒 Files selected for processing (5)
  • docs/BENTO_EMAIL_PREFERENCES_SETUP.md
  • supabase/functions/_backend/triggers/on_user_org_access.ts
  • supabase/functions/_backend/utils/bento_org_invite.ts
  • tests/bento-first-org-route.unit.test.ts
  • tests/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)

Comment thread supabase/functions/_backend/utils/bento_org_invite.ts Outdated
Drop the dedicated helper; look up email and tag from the webhook payload.

Co-authored-by: Cursor <cursoragent@cursor.com>
@riderx
riderx merged commit f0a51a3 into main Aug 9, 2026
56 of 57 checks passed
@riderx
riderx deleted the feat/bento-org-invite-accepted-tag branch August 9, 2026 21:04

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Approver External

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 82b3ad9 and 566dbff.

📒 Files selected for processing (2)
  • supabase/functions/_backend/triggers/on_user_org_access.ts
  • tests/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)

Comment on lines +20 to +31
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: [],
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ 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 is false so an unconfigured Bento integration can still return undefined.
  • tests/bento-first-org-route.unit.test.ts#L144-L152: add cases where the lookup returns an error and where syncBentoSubscriberTagsMock resolves false; 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.

Suggested change
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

@sonarqubecloud

sonarqubecloud Bot commented Aug 9, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant