Skip to content

fix(slack): override wrong channel_type for D-prefix DM channels#25479

Merged
steipete merged 3 commits intoopenclaw:mainfrom
mcaxtr:fix/slack-dm-channel-type-validation
Feb 24, 2026
Merged

fix(slack): override wrong channel_type for D-prefix DM channels#25479
steipete merged 3 commits intoopenclaw:mainfrom
mcaxtr:fix/slack-dm-channel-type-validation

Conversation

@mcaxtr
Copy link
Contributor

@mcaxtr mcaxtr commented Feb 24, 2026

Summary

  • Problem: Slack DMs (D-prefix channel IDs) are misclassified when Slack sends contradicting channel_type metadata
  • Why it matters: Breaks dmScope: "main" routing, fragments DM conversations across separate sessions, bypasses DM policies
  • What changed: Added cross-validation in normalizeSlackChannelType() to override wrong channel_type when channel ID is D-prefix
  • What did NOT change: No changes to G-prefix (ambiguous) or C-prefix channels; only D-prefix DMs are cross-validated

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

Before:

  • D-prefix DMs with wrong channel_type: "channel" → classified as channels
  • DMs routed to agent:main:slack:channel:d0abc123 (bypasses dmScope)
  • Outbound replies don't auto-deliver (wrong session)

After:

  • D-prefix DMs always classified as "im" regardless of channel_type
  • DMs correctly route to agent:main:main when dmScope: "main"
  • Outbound replies auto-deliver to DM channel

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)

Repro + Verification

Environment

  • OS: All (macOS, Linux, Windows)
  • Runtime/container: Any
  • Model/provider: N/A
  • Integration/channel (if any): Slack
  • Relevant config (redacted):
    session:
      dmScope: main
    channels:
      slack:
        enabled: true
        dm:
          policy: open

Steps

  1. Configure session.dmScope: "main" and channels.slack.dm.policy: "open"
  2. Send a direct message to the bot from Slack
  3. Check session key via openclaw sessions list
  4. Before fix: agent:main:slack:channel:d0abc123
  5. After fix: agent:main:main

Expected

  • DMs with D-prefix IDs are always classified as "im" type
  • DMs route to main session when dmScope: "main"
  • Conversation history is unified in main session

Actual

  • Before: DMs misclassified as channels when Slack sends wrong metadata
  • After: D-prefix always overrides to "im" (cross-validation)

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Test coverage:

Unit tests (monitor.test.ts - 3 new):

  • Overrides wrong channel_type ("channel", "group", "mpim") for D-prefix → returns "im"
  • Preserves correct channel_type ("im") for D-prefix
  • Does not override G-prefix channels (ambiguous prefix, trust provided type)

Integration tests (prepare.test.ts - 2 new):

  • D-prefix + wrong channel_type: "channel"isDirectMessage: true, routes to agent:main:main, ChatType: "direct"
  • D-prefix + missing channel_type → correctly inferred as DM

All 5 new tests pass. All existing tests pass.

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios:

    • All 5 new tests pass (unit + integration)
    • All existing Slack tests pass (no regressions)
    • pnpm build succeeds
    • pnpm check passes (oxlint + typecheck)
  • Edge cases checked:

    • D-prefix with correct channel_type: "im" (preserved)
    • D-prefix with wrong channel_type: "channel" (overridden to "im")
    • D-prefix with wrong channel_type: "group" (overridden to "im")
    • D-prefix with wrong channel_type: "mpim" (overridden to "im")
    • D-prefix with missing channel_type (inferred as "im")
    • G-prefix channels not affected (ambiguous, trust provided type)
    • C-prefix channels not affected (already correct)
  • What I did NOT verify:

    • Full end-to-end test with live Slack workspace
    • Actual Slack API sending contradicting channel_type
    • macOS app behavior (npm install only)

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)

This is a pure bug fix to normalization logic. No config changes or migrations required.

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: Revert the commit
  • Files/config to restore: src/slack/monitor/context.ts
  • Known bad symptoms reviewers should watch for:
    • D-prefix DMs incorrectly classified as channels again
    • Session routing breaks for DMs
    • Test failures in Slack monitor tests

Risks and Mitigations

  • Risk: Over-aggressive override might affect non-DM D-prefix channels (if Slack ever creates them)

    • Mitigation: Per Slack's documented ID schema, D-prefix is definitively and exclusively for DMs; this is a stable API contract
  • Risk: Changes might affect G-prefix channels

    • Mitigation: G-prefix channels explicitly NOT overridden (they remain ambiguous between private channel and group DM)
  • Risk: Existing sessions with wrong classification might not auto-migrate

    • Mitigation: This is expected - fix applies to new messages only; users can manually reset affected sessions if needed

Greptile Summary

Adds cross-validation logic to override incorrect channel_type metadata for Slack DM channels (D-prefix IDs). When Slack sends contradicting metadata (e.g., D-prefix channel with channel_type: "channel"), the fix correctly overrides to "im" based on the definitive D-prefix identifier.

Key changes:

  • Modified normalizeSlackChannelType() in src/slack/monitor/context.ts:48-51 to check if inferred type is "im" and override when normalized type doesn't match
  • Added 3 unit tests covering D-prefix override scenarios (wrong types: "channel", "group", "mpim"), preserved correct type, and G-prefix ambiguity handling
  • Added 2 integration tests validating end-to-end behavior: D-prefix with wrong channel_type routes correctly to main session, and missing channel_type is correctly inferred

The fix is surgical and limited to D-prefix channels only. G-prefix and C-prefix channels remain unaffected. Test coverage comprehensively validates the fix matches the described behavior.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The fix is well-scoped, logically sound, and thoroughly tested. The change adds a single conditional check that only affects D-prefix channels when metadata contradicts the channel ID prefix. The implementation correctly preserves existing behavior for all other cases (G-prefix ambiguity, C-prefix channels, and correct D-prefix metadata). Comprehensive test coverage includes 5 new tests (3 unit + 2 integration) validating all edge cases. The fix aligns with Slack's documented ID schema where D-prefix definitively indicates DMs.
  • No files require special attention

Last reviewed commit: 07d77c4

@steipete steipete force-pushed the fix/slack-dm-channel-type-validation branch from 07d77c4 to aacddc6 Compare February 24, 2026 14:25
@steipete steipete merged commit 5e6fe9c into openclaw:main Feb 24, 2026
7 checks passed
@steipete
Copy link
Contributor

Landed via temp rebase onto main.

  • Targeted tests: pnpm test src/slack/monitor/message-handler/prepare.test.ts src/slack/monitor/monitor.test.ts
  • Land commit: aacddc6
  • Merge commit: 5e6fe9c

Thanks @mcaxtr!

obviyus pushed a commit to Glucksberg/OpenClaw that referenced this pull request Feb 24, 2026
margulans pushed a commit to margulans/Neiron-AI-assistant that referenced this pull request Feb 25, 2026
Jackson3195 pushed a commit to Jackson3195/openclaw-with-a-personal-touch that referenced this pull request Feb 25, 2026
brianleach pushed a commit to brianleach/openclaw that referenced this pull request Feb 26, 2026
execute008 pushed a commit to execute008/openclaw that referenced this pull request Feb 27, 2026
r4jiv007 pushed a commit to r4jiv007/openclaw that referenced this pull request Feb 28, 2026
hughdidit pushed a commit to hughdidit/DAISy-Agency that referenced this pull request Mar 1, 2026
…thanks @mcaxtr)

(cherry picked from commit 5e6fe9c)

# Conflicts:
#	CHANGELOG.md
Maple778 added a commit to Maple778/openclaw that referenced this pull request Mar 2, 2026
…correct external data

Pattern from PR openclaw#25479

The bug is located in the `resolveModalSessionRouting` function, which orchestrates modal session routing by relying on `metadata.channelType`. The root cause is that this metadata originates from an untrusted external source (Slack modal submission payload) and may contradict the structural reality of the `channelId` (e.g., a 'C' prefix ID marked as 'im'). If passed downstream to `ctx.resolveSlackSystemEventSessionKey` or stored as the source of truth for the channel type, this causes data corruption. The fix implements the 'ground truth' strategy mentioned in PR openclaw#25479: deterministically inferring the type from the `channelId` prefix (D/G/C) and overriding the metadata if a contradiction is detected for DMs. This ensures the system relies on data structure rather than user input.
hughdidit pushed a commit to hughdidit/DAISy-Agency that referenced this pull request Mar 3, 2026
…thanks @mcaxtr)

(cherry picked from commit 5e6fe9c)

# Conflicts:
#	CHANGELOG.md
joelnishanth pushed a commit to joelnishanth/openclaw that referenced this pull request Mar 3, 2026
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: slack Channel integration: slack size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Slack DMs misclassified as channels when channel_type contradicts D-prefix ID

2 participants