diff --git a/apps/sim/blocks/blocks/slack.ts b/apps/sim/blocks/blocks/slack.ts index 1792db96c52..0cdb2266280 100644 --- a/apps/sim/blocks/blocks/slack.ts +++ b/apps/sim/blocks/blocks/slack.ts @@ -7,6 +7,25 @@ import { normalizeFileInput } from '@/blocks/utils' import type { SlackResponse } from '@/tools/slack/types' import { getTrigger } from '@/triggers' +/** + * Scopes added for the native Sim Slack app trigger (`slack_oauth`): the shared + * app's `app_mention`, assistant-thread, and DM events don't deliver without + * them. Advertised by `slack_v2` and the trigger only — the legacy block has no + * feature that needs them, and listing them there would flag every existing + * Slack credential as missing scopes and prompt a reconnect. + * + * This only controls what each picker *advertises* and treats as missing. The + * authorization request itself is provider-wide + * (`getCanonicalScopesForProvider('slack')`), so any reconnect grants the full + * set regardless of which block started it. + */ +const SLACK_V2_ONLY_SCOPES = new Set(['app_mentions:read', 'assistant:write', 'im:history']) + +/** Slack scopes the legacy v1 block advertises — the set from before the trigger expansion. */ +const SLACK_V1_ADVERTISED_SCOPES = getScopesForService('slack').filter( + (scope) => !SLACK_V2_ONLY_SCOPES.has(scope) +) + export const SlackBlock: BlockConfig = { type: 'slack', name: 'Slack', @@ -107,7 +126,7 @@ export const SlackBlock: BlockConfig = { canonicalParamId: 'oauthCredential', mode: 'basic', serviceId: 'slack', - requiredScopes: getScopesForService('slack'), + requiredScopes: SLACK_V1_ADVERTISED_SCOPES, placeholder: 'Select Slack workspace', dependsOn: ['authMethod'], condition: { @@ -2642,6 +2661,9 @@ function adaptSubBlockForV2(sb: SubBlockConfig): SubBlockConfig { ...rest, credentialKind: 'any', placeholder: 'Select Slack account or bot', + // Full set, unlike v1: v2 hosts the native Sim app trigger, whose events + // need the mention/assistant/DM scopes. + requiredScopes: getScopesForService('slack'), credentialLabels: { oauthGroup: 'Sim app', oauthConnect: 'Connect the Sim app', diff --git a/apps/sim/lib/oauth/oauth.ts b/apps/sim/lib/oauth/oauth.ts index 99477a53525..1d74cac2b63 100644 --- a/apps/sim/lib/oauth/oauth.ts +++ b/apps/sim/lib/oauth/oauth.ts @@ -782,12 +782,9 @@ export const OAUTH_PROVIDERS: Record = { 'groups:write', 'chat:write', 'chat:write.public', - // TODO: Re-add once Slack app review approves these. Requesting a scope - // the app is not yet approved for makes Slack reject the entire - // authorization with "unapproved permissions requested", breaking connect. - // 'assistant:write', - // 'app_mentions:read', - // 'im:history', + 'assistant:write', + 'app_mentions:read', + 'im:history', 'im:write', 'im:read', 'users:read',