Skip to main content

Listen to SSO Change Owner webhook

Jira: BIF-8751 · Epic: BIF-8695

Overview

When SSO sends a Change Owner webhook for an org, the system reassigns the owner role in Chat and CRM and updates the owner columns, so Chat and CRM stay in sync with SSO's source of truth. Modpanel's SSO-Owner protection (modpanel-block-sso-owner-edit) relies on this ownership truth.

Webhook contract: Webhook Data Update NotificationTODO: name the exact payload fields for CID, previous owner, new owner.

Scope Changes

  • Backend — consume the SSO Change Owner webhook; atomically update roles + owner columns in chat.organizations and crm.teams.

Role vocabulary (pinned)

  • Qontak One / unified path (unified_app = TRUE) → unified roles: Owner · Admin · Member
  • Non-unified path (unified_app = FALSE) → split roles: Chat Admin · CRM Owner · CRM Admin

Flow

flowchart TD
A([SSO Change Owner webhook received]) --> V{Payload valid?<br/>new owner is a member?}
V -->|No| ERR[Reject, no mutation<br/>surface actionable failure]
V -->|Yes| IDEM{New owner already<br/>the current owner?<br/>or duplicate delivery?}
IDEM -->|Yes| NOOP[Safe no-op<br/>return success]
IDEM -->|No| TX[[Begin atomic transaction]]
TX --> U{unified_app = TRUE?}
U -->|Yes| U1{Current owner's role = Owner?}
U1 -->|Yes| AC1[New owner --> Owner<br/>Previous owner --> Admin default]
U1 -->|No| AC2[New owner --> Owner<br/>Previous owner: keep role]
U -->|No| AC3[New owner --> Chat Admin + CRM Owner<br/>Previous owner: keep role]
AC1 --> DB
AC2 --> DB
AC3 --> DB
DB[Update owner column in chat.organizations and crm.teams] --> COMMIT{All writes OK?}
COMMIT -->|Yes| DONE([Commit, return success])
COMMIT -->|No| RB[Roll back all changes<br/>ownership never split]

8. User Stories + Acceptance Criteria

User StoryImportanceMockup / Technical NotesAcceptance Criteria
[CHOWN-S01] — Reassign owner on SSO webhook

As the system, when SSO sends a Change Owner webhook for an org, I reassign the owner role in Chat and CRM and update the owner columns, so that Chat and CRM stay in sync with SSO's source of truth.
Must HaveUpdates chat.organizations + crm.teams owner columns atomically. On the unified_app = FALSE path the previous owner's role is always kept — there is no branch on the current owner's role.— Happy Path —
• AC-1: Given unified_app = TRUE and the current owner's role is Owner, when the webhook is received, then set the new owner to Owner, set the previous owner to Admin (default), and update the owner column in chat.organizations and crm.teams.
• AC-2: Given unified_app = TRUE and the current owner's role is not Owner, when the webhook is received, then set the new owner to Owner, keep the previous owner's role unchanged, and update the owner columns.
• AC-3: Given unified_app = FALSE, when the webhook is received, then set the new owner to Chat Admin + CRM Owner, keep the previous owner's role unchanged, and update the owner column in chat.organizations and crm.teams.
— Idempotency —
• AC-4: Given the webhook names a new owner that is already the current owner, or the same webhook is delivered more than once, when it is processed, then it is a safe no-op (no role flip-flop, no duplicate writes) and returns success.
— Error / Unhappy Path —
• ERR-1: Given a malformed/missing-field payload or a new-owner email that is not a member of the org, when it is processed, then reject without mutating any role or table and surface an actionable failure; and the two role changes + two table updates must be atomic — on partial failure, roll back so ownership is never split across Chat and CRM.

Open questions

  1. Exact webhook fields for CID / previous owner / new owner?
  2. Behaviour when the org currently has no owner?
  3. Is an owner change audit-logged, and where?
  4. Is "Owner CRM" (original AC 3 title) the same as "CRM Owner" (body)?