Seamless Logout — cross-product session-invalidation fanout
Jira: BIF-8612 · Epic: TBD (currently parented under BIF-7949, a 26Q2 production-support bucket — not this Epic; a dedicated 26Q3 Epic is still to be minted, see the bucket README's "Jira alignment" note)
Overview
The unified logout flow can call the CRM v1 sign-out URL and destroy its session, but the browser
is then redirected to SSO login and may leave a visible new tab or popup. CRM v1/v2, Hub, and Hub
Chat sessions must stay consistent when a user logs out from Qontak One, Hub, or Hub Chat — the
implementation must not depend on the user permitting popups/redirects. Originating production bug:
BIF-8570 — "Logout process on Qontak One account can
trigger 'Open new tab' pop-up," still In Progress and repeatedly escalated as an off-plan item in
sprint reconciliation (see ../../delivery/sprints/2026-07-06-sprint-01.md).
Scope Changes
- Backend — session-invalidation fanout:
Auth::GlobalLogoutService+GlobalLogoutFanoutWorker(CRM),Oauths::Revoke→revoke-all-by-resource-owner+ Redis cleanup (Chat Panel), Warden session-validity enforcement,users.sessions_invalidated_at+sso_idindex (CRM), Hub-Chat wiring to theglobal_logouttrigger (flag-gated). - Frontend — Pusher force-logout listener +
sso_single_logoutflag (CRM web layout), MQTT/FCM force-logout publish (Chat Panel), mobile v2.8 routed throughGlobalLogoutService.
8. User Stories + Acceptance Criteria
| User Story | Importance | Mockup / Technical Notes | Acceptance Criteria |
|---|---|---|---|
| [LOGOUT-S01] — One logout, every session As a Qontak One user, I want one logout action to terminate my related Hub, Hub Chat, Qontak/CRM, and SSO sessions without leaving an unwanted tab or popup, so that my session state is consistent and secure across products and devices. | Must Have | Coordinates Hub, Hub Chat, qontak.com (CRM), hub-service, and hub-core. Ships behind a feature flag (sso_single_logout / the Hub-Chat global_logout trigger flag) with a reversible fallback; adds observability for propagation failures/retries. See Issue: Seamless Logout Experience (architecture, scenario matrix, rollout). | AC-1: Logging out from Hub or Hub Chat invalidates the Qontak/CRM session without a visible/persistent popup or new tab. AC-2: Logging out from Qontak/CRM causes Hub and Hub Chat to reject/clear related sessions on the next request or a supported real-time signal. AC-3: Logging out on one device invalidates the user's applicable sessions on other devices; a subsequent legitimate login remains active. AC-4: A popup blocker, unavailable real-time channel, or transient downstream failure does not block the initiating app's local logout — durable validation/retry handles propagation. AC-5: Blank/NULL SSO identity values are a no-op and cannot invalidate unrelated users. AC-6: Remember-me cookies and stored sync tokens cannot recreate a session after global logout. AC-7: Repeated/concurrent logout requests are safe and produce the same final logged-out state. AC-8: Covered by a happy-path/edge-case scenario matrix; disable-able via the rollout flag without a data rollback. |
Implementation status (as of 2026-07-14)
All items below are Tasks split from the Jira Story via "Work item split" links.
| Task | Repo | Summary | Status |
|---|---|---|---|
| BIF-8620 | CRM | DB migration: users.sessions_invalidated_at + sso_id index (DO FIRST) | Done |
| BIF-8621 | CRM | Warden session-validity enforcement | Done |
| BIF-8622 | CRM | Auth::GlobalLogoutService + GlobalLogoutFanoutWorker | Done |
| BIF-8623 | CRM | Route web/sso_sessions#destroy + mobile v2.8 through GlobalLogoutService | Done |
| BIF-8624 | CRM | New internal POST /api/v3.1/auth/global_logout + contract spec | Done |
| BIF-8625 | CRM | Pusher force-logout listener + sso_single_logout flag + observability | Done |
| BIF-8626 | Chat Panel | Extend Oauths::Revoke → revoke-all-by-resource-owner + Redis cleanup | Done |
| BIF-8627 | Chat Panel | Internal /api/internal/v1/global_logout endpoint + outbound call | Done |
| BIF-8628 | Chat Panel | Publish force-logout via MQTT/FCM | Done |
| BIF-8836 | Hub-Chat | Verify logout clears SSO resurrection keys (global_sso_*, is_sync_auth) | To Do |
| BIF-8837 | Hub-Chat | Wire logout to qontak global_logout trigger (flag-gated) | To Do |
| BIF-8838 | Hub-Chat | (Optional) MQTT force-logout subscription | To Do |
| BIF-8570 | Qontak One / CRM | [Bug] the originating production-support bug | In Progress |
9 of 13 Done — CRM and Chat Panel backend/frontend halves are shipped; only the three Hub-Chat tasks and the originating bug remain open.
Relationship to Centralized SSO Token
Distinct but related to centralized-sso-token — both
touch the logout path, different halves. Centralized SSO Token (Epic BIF-7802) adopts the shared
Mekari Session SDK and redirects each product's logout to the SSO sign-out endpoint; it explicitly
does not change logout UI. Seamless Logout (this item) fixes the cross-product session
invalidation fanout itself. Same engineer (Syafrizal M.) touches both, but they are separate
bodies of work.
Open questions
- Who is the per-repo engineering DRI/owner set? ("One engineering DRI and per-repository owners remain to be assigned during Sprint 7 planning" — per the source Story.)
- Mint a dedicated Epic for this item (currently parented under BIF-7949), or leave it there?