Skip to content

fix(slack): prevent Zod default groupPolicy from breaking multi-account config#17579

Merged
gumadeiras merged 3 commits intoopenclaw:mainfrom
ZetiMente:fix/slack-multi-account-group-policy
Feb 23, 2026
Merged

fix(slack): prevent Zod default groupPolicy from breaking multi-account config#17579
gumadeiras merged 3 commits intoopenclaw:mainfrom
ZetiMente:fix/slack-multi-account-group-policy

Conversation

@ZetiMente
Copy link
Contributor

@ZetiMente ZetiMente commented Feb 15, 2026

Summary

  • Moves .default("allowlist") from SlackAccountSchema to SlackConfigSchema so Zod only injects the default at the top-level config, not into individual account entries.
  • Fixes multi-account Slack configs silently dropping all channel messages (DMs still worked, @mentions in channels did not).

Root Cause

SlackAccountSchema has groupPolicy: GroupPolicySchema.optional().default("allowlist"). When Zod parses an account entry like { botToken: "...", appToken: "..." }, it injects groupPolicy: "allowlist" into the output — even though the user never specified it.

mergeSlackAccountConfig then does { ...base, ...account }, so the account's phantom "allowlist" overrides the user's top-level groupPolicy: "open". With "allowlist" active and no channels explicitly listed, isSlackChannelAllowedByPolicy returns false for every channel message.

This affects any config that uses the channels.slack.accounts object, even with a single account.

The developer's intent was probably "default to secure" — which is reasonable. The mistake was putting that default on the account schema instead of the top-level schema. The right place for "default to secure if nobody says anything" is SlackConfigSchema, because that's the one that represents the user's actual top-level config. Individual account entries are meant to inherit from that, and Zod defaults break the inheritance by filling in keys that should have stayed undefined.

The Fix

- // SlackAccountSchema
- groupPolicy: GroupPolicySchema.optional().default("allowlist"),
+ // SlackAccountSchema — no default, so accounts don't poison the merge
+ groupPolicy: GroupPolicySchema.optional(),

  // SlackConfigSchema.safeExtend — default lives here now
+ groupPolicy: GroupPolicySchema.optional().default("allowlist"),

Test Plan

  • All 149 existing Slack tests pass (pnpm test -- --grep slack)
  • Live-tested on Raspberry Pi running OpenClaw v2026.2.14 with two Slack bot accounts in socket mode
  • Confirmed DMs work for both accounts
  • Confirmed @mentions in channels work for both accounts
  • Confirmed non-mentioned messages in channels are correctly skipped
  • Single-account top-level config (no accounts object) continues to work as before

Fixes #17507
Related: #5626, #16522

cc @thewilloftheshadow (Slack subsystem) @gumadeiras (multi-agent)


🤖 AI-assisted: This bug was diagnosed and fixed by Claude Opus 4.6 (Anthropic) in a live demo session with @ZetiMente. Fully tested on a live instance.

Greptile Summary

Fixes a bug where Zod's .default("allowlist") on SlackAccountSchema.groupPolicy caused a phantom default to be injected into every parsed account entry, overriding the user's top-level groupPolicy during the shallow merge ({ ...base, ...account }) in mergeSlackAccountConfig. This silently broke channel message delivery for multi-account Slack configs.

  • Removed .default("allowlist") from SlackAccountSchema so account entries no longer get a phantom groupPolicy injected
  • Added .default("allowlist") to SlackConfigSchema via safeExtend so the secure default still applies at the top-level config
  • The same bug pattern exists in other providers (Discord, Telegram, Signal, IRC, iMessage, BlueBubbles) — all have .default("allowlist") on their account schemas and use the same shallow merge, but were not addressed in this PR

Confidence Score: 4/5

  • The Slack fix is correct and safe to merge, though the same bug exists in other providers.
  • The change is minimal, well-reasoned, and correctly fixes the Slack-specific issue. The author reports all 149 existing tests pass and the fix was live-tested. Deducting a point because the same Zod default-on-account-schema bug is present in 6 other providers (Discord, Telegram, Signal, IRC, iMessage, BlueBubbles) that use the identical merge pattern, and this PR does not address them.
  • Other account schemas in src/config/zod-schema.providers-core.ts (DiscordAccountSchema line 275, TelegramAccountSchemaBase line 108, SignalAccountSchemaBase line 657, IrcAccountSchemaBase line 745, IMessageAccountSchemaBase line 805, BlueBubblesAccountSchemaBase line 897) have the same latent bug.

Last reviewed commit: fc243e3

(1/5) You can manually trigger the agent by mentioning @greptileai in a comment!

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 file reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 17, 2026

Additional Comments (1)

src/config/zod-schema.providers-core.ts
Same bug exists in other providers. DiscordAccountSchema still has groupPolicy: GroupPolicySchema.optional().default("allowlist") (line 275), and DiscordConfigSchema inherits it via .extend() without overriding. The merge in mergeDiscordAccountConfig ({ ...base, ...account }) will exhibit the same phantom-default override behavior described in this PR for Slack.

The same pattern also appears in TelegramAccountSchemaBase (line 108), SignalAccountSchemaBase (line 657), IrcAccountSchemaBase (line 745), IMessageAccountSchemaBase (line 805), and BlueBubblesAccountSchemaBase (line 897) — all have .default("allowlist") on the account schema, and all use the same { ...base, ...account } shallow merge. Consider applying the same fix (move the default to the *ConfigSchema only) to these providers as well.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/config/zod-schema.providers-core.ts
Line: 275:275

Comment:
**Same bug exists in other providers.** `DiscordAccountSchema` still has `groupPolicy: GroupPolicySchema.optional().default("allowlist")` (line 275), and `DiscordConfigSchema` inherits it via `.extend()` without overriding. The merge in `mergeDiscordAccountConfig` (`{ ...base, ...account }`) will exhibit the same phantom-default override behavior described in this PR for Slack.

The same pattern also appears in `TelegramAccountSchemaBase` (line 108), `SignalAccountSchemaBase` (line 657), `IrcAccountSchemaBase` (line 745), `IMessageAccountSchemaBase` (line 805), and `BlueBubblesAccountSchemaBase` (line 897) — all have `.default("allowlist")` on the account schema, and all use the same `{ ...base, ...account }` shallow merge. Consider applying the same fix (move the default to the `*ConfigSchema` only) to these providers as well.

How can I resolve this? If you propose a fix, please make it concise.

@openclaw-barnacle
Copy link

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle bot added stale Marked as stale due to inactivity and removed stale Marked as stale due to inactivity labels Feb 22, 2026
@gumadeiras gumadeiras self-assigned this Feb 23, 2026
@ZetiMente
Copy link
Contributor Author

Fixed all the CI issues.

gumadeiras added a commit to ZetiMente/openclaw that referenced this pull request Feb 23, 2026
@gumadeiras gumadeiras force-pushed the fix/slack-multi-account-group-policy branch from 06d3436 to f89f6da Compare February 23, 2026 17:31
theword and others added 3 commits February 23, 2026 12:31
…nt config

When `SlackAccountSchema` has `groupPolicy: GroupPolicySchema.optional().default("allowlist")`,
Zod injects `groupPolicy: "allowlist"` into every parsed account entry — even when the user
never specified it. `mergeSlackAccountConfig` then does `{ ...base, ...account }`, so the
account's phantom "allowlist" silently overrides the user's top-level "open". With
`groupPolicy: "allowlist"` active and no channels explicitly listed, ALL channel messages
are dropped by `isSlackChannelAllowedByPolicy`.

The fix moves `.default("allowlist")` from `SlackAccountSchema` to `SlackConfigSchema`,
so the default only applies to the top-level config — not to individual account entries
that get shallow-merged on top of it.

Fixes openclaw#17507
Related: openclaw#5626, openclaw#16522

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gumadeiras gumadeiras force-pushed the fix/slack-multi-account-group-policy branch from f89f6da to 7d2da57 Compare February 23, 2026 17:32
@gumadeiras gumadeiras merged commit ce1f12f into openclaw:main Feb 23, 2026
13 checks passed
@gumadeiras
Copy link
Member

Merged via squash.

Thanks @ZetiMente!

carlosrivera pushed a commit to myascendai/meshiclaw that referenced this pull request Feb 23, 2026
…nt config (openclaw#17579)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7d2da57
Co-authored-by: ZetiMente <76985631+ZetiMente@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
mreedr pushed a commit to mreedr/openclaw-custom that referenced this pull request Feb 24, 2026
…nt config (openclaw#17579)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7d2da57
Co-authored-by: ZetiMente <76985631+ZetiMente@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
plgs2005 pushed a commit to plgs2005/openclaw that referenced this pull request Feb 24, 2026
…nt config (openclaw#17579)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7d2da57
Co-authored-by: ZetiMente <76985631+ZetiMente@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
margulans pushed a commit to margulans/Neiron-AI-assistant that referenced this pull request Feb 25, 2026
…nt config (openclaw#17579)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7d2da57
Co-authored-by: ZetiMente <76985631+ZetiMente@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
brianleach pushed a commit to brianleach/openclaw that referenced this pull request Feb 26, 2026
…nt config (openclaw#17579)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7d2da57
Co-authored-by: ZetiMente <76985631+ZetiMente@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
mylukin pushed a commit to mylukin/openclaw that referenced this pull request Feb 26, 2026
…nt config (openclaw#17579)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7d2da57
Co-authored-by: ZetiMente <76985631+ZetiMente@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
mylukin pushed a commit to mylukin/openclaw that referenced this pull request Feb 26, 2026
…nt config (openclaw#17579)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7d2da57
Co-authored-by: ZetiMente <76985631+ZetiMente@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
r4jiv007 pushed a commit to r4jiv007/openclaw that referenced this pull request Feb 28, 2026
…nt config (openclaw#17579)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7d2da57
Co-authored-by: ZetiMente <76985631+ZetiMente@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
…nt config (openclaw#17579)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7d2da57
Co-authored-by: ZetiMente <76985631+ZetiMente@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Slack socket mode: events not received when using accounts object

4 participants