Hive
feat(slack): add Slack OAuth integration with events, interactivity, and message shortcuts
GitHub issue · Closed
Summary
Adds a first-class Slack integration to Hive. Operators register a single Slack app per Hive deployment and enable Public Distribution; any workspace can then install Hive via OAuth at /slack/install without the Slack App Directory review (which would take weeks). Each workspace persists as a Hive.Slack.Installation row with its own bot token, and inbound events and interactions route by team_id.
Motivation
hive.tuist.dev (and any self-hoster) needs to be reachable from Slack: replying in threads when the bot is mentioned, posting notifications, and letting workspace members turn a Slack message into a Hive idea with one click. Atlas (../atlas/lib/atlas/slack/) already had a working Slack integration that I used as the architectural reference, but Atlas threads a slack_app: :community | :company enum through every module to support its two-bot setup. That distinction is bespoke to Tuist’s operating model and doesn’t belong in a generic Hive deployment. The first cut of this plan was actually built around a single static bot token per deployment, but enabling Slack across multiple workspaces from one Hive deployment is the standard shape every real Slack app uses, and Public Distribution makes it reachable without the App Directory gate. The integration ended up with per-installation tenancy (installation_id FK on every Slack-owned table) rather than the static-token model, which is structurally similar to Atlas’s enum but anchored in a real DB row representing an installed workspace.
Capabilities
- Events API at
POST /api/slack/eventswith HMAC-SHA256 signature verification (handles theurl_verificationchallenge automatically). - Outbound Web API via a small
Hive.Slack.APIReq wrapper:chat.postMessage,chat.update,conversations.info,conversations.replies,users.info, pluspost_response/2for interactionresponse_urls. - App-mention thread replies driven by
Hive.Slack.Agents.ConversationAgent(Condukt) and an Oban worker on the:agentsqueue. Dormant when no LLM is configured. - Block Kit interactivity at
POST /api/slack/interactions(theblock_actionsbranch is a stub for future button/select handlers). - Message shortcut
capture_feature_request: right-click a Slack message → captures it as a Hive forage feature request by matching the Slack user to a Hive user via email. Confirmation posted ephemerally throughresponse_url; failures get a useful ephemeral error. - Settings UI at
/account/slackto connect / disconnect workspaces, with an inert empty state when env vars are missing. - Audit entries for every install, disconnect, app-mention, thread reply, and feature-request capture.
Configuration
When all three of HIVE_SLACK_CLIENT_ID, HIVE_SLACK_CLIENT_SECRET, and HIVE_SLACK_SIGNING_SECRET are set, Hive.Slack.enabled?/0 is true and /slack/install is reachable. With any of them missing, the integration stays dormant, mirroring Hive.Agents.enabled?/0 and Hive.GitHub.Webhooks.secret/0.
Approach
lib/hive/slack/mirrors../atlas/lib/atlas/slack/’s shape, but theslack_appenum + signing-secret loop + company-only gates are all gone. Per-workspace tenancy is theinstallation_idFK onslack_channels/slack_users/slack_messages, with composite unique indexes like[installation_id, slack_channel_id].- Signature verification is a single app-wide secret (one Slack app, many workspaces), not a loop over per-bot secrets like Atlas does.
HiveWeb.CacheBodyReaderstashes the raw body for any path under/api/slack/(the same one-lineifit already used for/webhooks/github).- All tests are
async: true; Mimic stubs (Hive.Slack.API,Hive.Slack.Installations,Hive.Slack.Signature,Hive.Slack,Req,Condukt.Operation) keep parallelism safe.
Verification
mix formatmix compile --warnings-as-errors(clean)mix credo --strict(no new issues; pre-existing ones unchanged)mix test— 419 tests, 0 failures (up from 368, so 51 new tests cover signature verification, OAuth code exchange, API wire format, event dispatch, interaction dispatch, the Oban worker, and both controllers)
Testing
mix formatmix compile --warnings-as-errorsmix credo --strictmix test- Manual Slack-side smoke test is documented in
docs/guide/self-hosting/slack.mdfor operators.
No GitHub comments yet.