diff --git a/CHANGELOG.md b/CHANGELOG.md index 4aae47bbc88..fc93bfea0b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ Docs: https://docs.openclaw.ai - Telegram/setup: require numeric `allowFrom` user IDs during setup instead of offering unsupported `@username` DM resolution, and point operators to `from.id`/`getUpdates` for discovery. (#69191) Thanks @obviyus. - GitHub Copilot/onboarding: default GitHub Copilot setup to `claude-opus-4.6` and keep the bundled default model list aligned, so new Copilot setups no longer start on the older `gpt-4o` default. (#69207) Thanks @obviyus. - Gateway/status: separate reachability, capability, and read-probe reporting so connect-only or scope-limited sessions no longer look fully healthy, and normalize SSH targets entered as `ssh user@host`. (#69215) Thanks @obviyus. +- Slack: fix outbound replies failing with "unresolved SecretRef" for accounts configured via `file` or `exec` secret sources; the send path now tolerates the runtime snapshot retaining an unresolved channel SecretRef when a boot-resolved token override is already available. (#68954) Thanks @openperf. ## 2026.4.19-beta.2 diff --git a/extensions/slack/src/accounts.ts b/extensions/slack/src/accounts.ts index 9f0fac47f10..948e547212e 100644 --- a/extensions/slack/src/accounts.ts +++ b/extensions/slack/src/accounts.ts @@ -96,13 +96,13 @@ export function resolveSlackAccount(params: { baseAllowEnv && !blockAppEnv ? resolveSlackAppToken(process.env.SLACK_APP_TOKEN) : undefined; const envUser = baseAllowEnv && !blockUserEnv ? resolveSlackUserToken(process.env.SLACK_USER_TOKEN) : undefined; - const configBot = params.tolerateUnresolvedSecrets + const configBot = tolerantMode ? normalizeSecretInputString(merged.botToken) : resolveSlackBotToken(merged.botToken, `channels.slack.accounts.${accountId}.botToken`); - const configApp = params.tolerateUnresolvedSecrets + const configApp = tolerantMode ? normalizeSecretInputString(merged.appToken) : resolveSlackAppToken(merged.appToken, `channels.slack.accounts.${accountId}.appToken`); - const configUser = params.tolerateUnresolvedSecrets + const configUser = tolerantMode ? normalizeSecretInputString(merged.userToken) : resolveSlackUserToken(merged.userToken, `channels.slack.accounts.${accountId}.userToken`); const botToken = configBot ?? envBot; diff --git a/extensions/slack/src/channel.ts b/extensions/slack/src/channel.ts index 81d4ba8bd40..3a1100b9208 100644 --- a/extensions/slack/src/channel.ts +++ b/extensions/slack/src/channel.ts @@ -170,6 +170,10 @@ async function resolveSlackSendContext(params: { const send = resolveOutboundSendDep(params.deps, "slack") ?? (await loadSlackSendRuntime()).sendMessageSlack; + // params.cfg is the scoped channel-dispatch config; channel credentials are + // expected to be resolved here (not a raw loadConfig() snapshot). Strict mode + // is intentional so boot-time misconfigurations surface loudly. See #68237 + // for the companion tolerant-mode path in sendMessageSlack itself. const account = resolveSlackAccount({ cfg: params.cfg, accountId: params.accountId }); const token = getTokenForOperation(account, "write"); const botToken = account.botToken?.trim();