Skip to content

feat(chat-app): implement Slack adapter#7

Open
scion-gteam[bot] wants to merge 2 commits into
mainfrom
scion/slack-chat-app
Open

feat(chat-app): implement Slack adapter#7
scion-gteam[bot] wants to merge 2 commits into
mainfrom
scion/slack-chat-app

Conversation

@scion-gteam
Copy link
Copy Markdown

@scion-gteam scion-gteam Bot commented May 4, 2026

Summary

  • New Slack platform adapter (internal/slack/) implementing the chatapp.Messenger interface as the second platform provider after Google Chat
  • Block Kit rendering for all widget types (text, key-value, buttons, dividers, images, inputs, checkboxes) and card actions with styled buttons
  • Modal rendering converting chatapp.Dialog to Slack ModalViewRequest with text, textarea, select, and checkbox field types
  • Event normalization for slash commands, app_mention, DM messages, member join/leave, interactions, and view submissions
  • Socket Mode and HTTP mode support with Slack signature verification (HMAC)
  • App Home tab showing user profile, linked groves, subscriptions, and quick actions
  • Per-agent identity via chat:write.customize with RoboHash avatars through an IconProvider abstraction
  • User profile caching with 15-minute TTL to avoid Slack API rate limits
  • Multi-platform messenger dispatch in CommandRouter and NotificationRelay — both now route messages to the correct platform adapter via a messengers map
  • Platform-aware @mention formatting (<@UID> for Slack, <users/UID> for Google Chat) in notifications.go
  • Async response pattern — Slack events are acknowledged within 3 seconds, then processed asynchronously via goroutines
  • Ephemeral command responses for help, info, register, unregister commands

Files changed

File Change
internal/slack/adapter.go New — main adapter (609 lines)
internal/slack/blocks.go New — Block Kit rendering (145 lines)
internal/slack/modals.go New — Modal rendering (150 lines)
internal/slack/events.go New — event normalization (136 lines)
internal/slack/apphome.go New — App Home tab (222 lines)
internal/slack/verify.go New — request signature verification (35 lines)
internal/slack/adapter_test.go New — 39 unit tests (871 lines)
internal/chatapp/commands.go Multi-platform messenger dispatch, GetUser fallback for email-less platforms
internal/chatapp/notifications.go Multi-platform dispatch, platform-aware mentions
internal/chatapp/notifications_test.go Added TestFormatMention
internal/chatapp/config.go Expanded SlackConfig (signing_secret, listen_address, socket_mode)
cmd/scion-chat-app/main.go Slack adapter initialization, graceful shutdown
go.mod / go.sum Added github.com/slack-go/slack v0.23.0

Test plan

  • All 39 new unit tests pass (go test ./internal/slack/...)
  • Existing chatapp tests pass (go test ./internal/chatapp/...)
  • Manual: Configure a Slack app with bot token, signing secret, and app token
  • Manual: Verify slash commands (/scion help, /scion link, /scion subscribe)
  • Manual: Verify agent notification cards render correctly in Slack channels
  • Manual: Verify user-targeted messages deliver with @mentions
  • Manual: Verify App Home tab displays profile, groves, and subscriptions
  • Manual: Verify Socket Mode connectivity (if app token configured)
  • Manual: Verify HTTP mode with signature verification
  • Manual: Verify ephemeral responses for help/info/register commands
  • Manual: Verify modal dialogs open and submit correctly
  • Manual: Confirm Google Chat adapter still works correctly (no regressions)

@scion-gteam scion-gteam Bot force-pushed the scion/slack-chat-app branch from 7971bbb to 94b2280 Compare May 4, 2026 15:40
@scion-gteam scion-gteam Bot force-pushed the scion/slack-chat-app branch from 94b2280 to 67b115b Compare May 4, 2026 16:08
@ptone
Copy link
Copy Markdown
Owner

ptone commented May 4, 2026

/gemini review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request implements a Slack adapter for the scion-chat-app, enabling multi-platform support alongside Google Chat. The changes include the Slack adapter implementation with support for Webhooks and Socket Mode, Block Kit rendering for cards, and App Home tab publishing. The core chatapp logic was refactored to manage multiple messengers and handle platform-specific user lookups and mentions. Feedback focuses on potential performance issues from synchronous network calls in the command flow and the lack of timeouts or cancellation mechanisms in background goroutines handling Slack events and interactions.

PlatformID: el.event.UserID,
}, nil
}
user, err := el.messenger.GetUser(ctx, el.event.UserID)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The messenger.GetUser() call is performed synchronously within the command handling flow. Given that this can involve network I/O, consider if this should be cached or if the latency is acceptable for the command execution path.

w.WriteHeader(http.StatusOK)

// Process asynchronously.
go a.processEventsAPIEvent(context.Background(), &eventsAPIEvent)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Using context.Background() in an asynchronous goroutine can lead to premature cancellation if the parent request context is used. However, it also means the operation lacks a timeout or cancellation mechanism. Consider passing a context with a timeout or using a dedicated background context with a timeout.

})

// Process asynchronously.
go a.processSlashCommand(context.Background(), cmd)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Similar to the event handler, this asynchronous processing lacks a timeout mechanism. Consider passing a context with a timeout to ensure long-running operations do not leak goroutines.

w.WriteHeader(http.StatusOK)

// Process asynchronously.
go a.processInteraction(context.Background(), callback)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Asynchronous processing of interactions without a bounded context or timeout could lead to resource exhaustion under high load. Consider using a worker pool or a context with a timeout.

… handlers

Cache GetUser results per-event in eventUserLookup to avoid redundant
API calls during event processing. Replace unbounded context.Background()
with 30-second timeout contexts in all async goroutines (HTTP and Socket
Mode handlers) to prevent resource leaks from hung operations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant