Closes the loop on https://github.com/twentyhq/twenty/pull/22984#discussion_r3673946334, where the Slack app claimed a `team_id` on connect and never released it. The `onDisconnect` hook it waited on merged in #23538, and `twenty-sdk` 2.27.0 ships the `onDisconnectLogicFunction` manifest field, so this bumps the app to it. ## Disconnect `slack-team-release` releases the server-scoped `slack-team:{teamId}` claim, so another Twenty workspace can connect that Slack team afterwards. `kv.delete` on a SERVER key only clears a claim the calling workspace owns, and the result reports a team only when that delete actually removed something. The connection is already deleted when the hook runs, so `getConnection` cannot resolve the `team_id` anymore. `claimSlackTeam` records `teamId` under a workspace-scoped `slack-connected-account-team:{connectedAccountId}` key, written before the claim itself so a failure between the two cannot leave a claim nothing can resolve, and the release reads it back from there. That also retires the TODO the review comment pointed at. The release is skipped when a live connection still maps to the same team, excluding the disconnecting account explicitly. That covers a reconnect that re-claimed the team while the job was queued, and a second connection to the same Slack workspace, whose claim would otherwise have been dropped along with the first. The recorded team is cleared either way, so the disconnecting account leaves nothing behind. ## Uninstall Uninstalling the app drops its connections through the `connectionProvider` and `application` cascades, which never reach the disconnect hook, and the same operation deletes the app's logic functions so the hook could not run anyway. The app declares an `uninstallLogicFunction`: it runs before the app's metadata is deleted, lists the remaining Slack connections, and releases each claim through the same `releaseSlackTeamClaim` util. It deliberately skips the live-connection check, since at that point every connection is still listed. ## Known limits A disconnect immediately followed by a reconnect has a window where the queued release can clear a claim the reconnect just took. It self-heals, because the reconnect's own onConnect re-claims the same key moments later. Closing it properly needs a compare-and-set on the claim, which the key-value store does not expose. No unit tests are added for the release path. Earlier revisions of this branch had specs for the disconnect guard, the uninstall sweep and the no-op-release result; they were dropped, so those branches carry no regression coverage. The app's existing 34 tests still pass, along with lint, typecheck and `twenty dev:build`, the last being what used to fail with `Duplicate universal identifiers` on the older SDK.
The #1 Open-Source CRM
Website ·
Documentation ·
Roadmap ·
Discord ·
Figma
Why Twenty
Twenty gives technical teams the building blocks for a custom CRM that meets complex business needs and quickly adapts as the business evolves. Twenty is the CRM you build, ship, and version like the rest of your stack.
Learn more about why we built Twenty
Installation
Cloud
The fastest way to get started. Sign up at twenty.com and spin up a workspace in under a minute, with no infrastructure to manage and always up to date.
Build an app
Scaffold a new app with the Twenty CLI:
npx create-twenty-app my-app
Define objects, fields, and views as code:
import { defineObject, FieldType } from 'twenty-sdk/define';
export default defineObject({
nameSingular: 'deal',
namePlural: 'deals',
labelSingular: 'Deal',
labelPlural: 'Deals',
fields: [
{ name: 'name', label: 'Name', type: FieldType.TEXT },
{ name: 'amount', label: 'Amount', type: FieldType.CURRENCY },
{ name: 'closeDate', label: 'Close Date', type: FieldType.DATE_TIME },
],
});
Then ship it to your workspace:
npx twenty app:publish --private
See the app development guide for objects, views, agents, and logic functions.
Self-hosting
Run Twenty on your own infrastructure with Docker Compose, or contribute locally via the local setup guide.
Everything you need
Twenty gives you the building blocks of a modern CRM (objects, views, workflows, and agents) and lets you extend them as code. Here's a tour of what's in the box.
Want to go deeper? Read the User Guide for product walkthroughs, or the
Documentation for developer reference.
|
|
|
|
|
|
Stack
TypeScript
Nx
NestJS, with BullMQ,
PostgreSQL,
Redis
React, with Jotai, Linaria and Lingui
Thanks
Thanks to these amazing services that we use and recommend for code review (Greptile), catching bugs (Sentry) and translating (Crowdin).
Join the Community
Star the repo ·
Discord ·
Feature requests ·
Releases ·
X ·
LinkedIn ·
Crowdin ·
Contribute





