Skip to content

Host @dsgt Slack bot on Firebase App Hosting - #356

Open
aamoghS wants to merge 4 commits into
mainfrom
cursor/dsgt-slack-firebase-24bd
Open

Host @dsgt Slack bot on Firebase App Hosting#356
aamoghS wants to merge 4 commits into
mainfrom
cursor/dsgt-slack-firebase-24bd

Conversation

@aamoghS

@aamoghS aamoghS commented Aug 17, 2026

Copy link
Copy Markdown
Member

Restores the @dsgt Slack bot and serves Slack over HTTP on the existing Firebase App Hosting backend. There is no second Cloud Run service and no Socket Mode in production.

Slack manifest (Create from manifest)

Slack rejects Event Subscriptions, Interactivity, and /dsgt when Socket Mode is off and no Request URL is set (invalid_manifest). apps/dsgt-slack/manifest.yaml now creates the @dsgt bot user and scopes only. After {AUTH_URL}/api/webhooks/slack is live, add those HTTP features in the Slack app settings.

Grok Bot vs this PR

This PR is a small FAQ webhook (help, ping, join). It is not Grok Bot.

Google Slides, Forms, Drive, Gmail, and other MCP tools belong on your Grok Bot teammate, the same way @Yodo works in Campus Leads Slack. Install that teammate into the DS@GT club workspace, connect Slack + Google there, and name the Slack bot user dsgt. Do not put those connectors in Firebase. Do not run this FAQ app and Grok Bot on the same bot tokens.

The Cursor Slack connector always posts as Cursor. Posting as @dsgt requires this Slack app installed in that workspace.

Why this shape (FAQ fallback)

sites/mainweb already has an HTTP webhook at /api/webhooks/stripe. proxy.ts already excludes /api/webhooks/*. App Hosting deploys that Next.js app to Cloud Run.

Request URL if you install this FAQ app (Event Subscriptions, Slash Commands /dsgt, Interactivity):

{AUTH_URL}/api/webhooks/slack

AUTH_URL / NEXTAUTH_URL in apphosting.yaml is the App Hosting origin (club host datasciencegt.org). Slack must hit that Cloud Run surface, not the static Firebase Hosting site dsgt-website (sites/mainweb/out/).

What the FAQ bot does

  • Replies to @dsgt mentions (app_mention)
  • Replies to DMs (message.im)
  • Slash command /dsgt (help, ping, join)
  • Join FAQ: first event August 26 (8/26); further details announced there; points to datasciencegt.org

Copy stays in apps/dsgt-slack (replies.ts). No LLM backend in this package.

stripBotMention no longer uses /<@[^>]+>/ (CodeQL js/polynomial-redos on PR alert #810). Mentions are removed with a linear indexOf scan.

Before merging — Secret Manager (FAQ app only)

apphosting.yaml now references SLACK_BOT_TOKEN and SLACK_SIGNING_SECRET. Create those secrets and grant the App Hosting backend access before this lands, or the next App Hosting deploy cannot start. Skip this if you are only using Grok Bot in Slack and will not deploy this webhook. Steps: apps/dsgt-slack/README.md.

Tests

pnpm --filter @query/dsgt-slack test — join FAQ, slash routing, mention stripping, HTTP signature / challenge / mention / DM / /dsgt join.

web lint and typecheck still fail on pre-existing files this PR does not touch.

Open in Web Open in Cursor 

Restore apps/dsgt-slack and serve Slack Events API, slash commands, and
interactivity at /api/webhooks/slack on sites/mainweb. Production uses
HTTP (not Socket Mode) with SLACK_BOT_TOKEN and SLACK_SIGNING_SECRET
from Secret Manager.
@github-actions github-actions Bot added the dependencies Pull requests that update a dependency file label Aug 17, 2026
@aamoghS
aamoghS marked this pull request as ready for review August 17, 2026 16:52
@github-actions

github-actions Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Dependency Review

The following issues were found:

  • ✅ 0 vulnerable package(s)
  • ✅ 0 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ⚠️ 5 package(s) with unknown licenses.
  • ⚠️ 18 packages with OpenSSF Scorecard issues.

View full job summary

@github-actions

Copy link
Copy Markdown
Contributor

Visit the preview URL for this PR (updated for commit bdb0052):

https://hacklytics2027--pr-356-2g1stjc2.web.app

(expires Mon, 24 Aug 2026 16:53:05 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: c48ba34db61581e25fe2978355160b5eefe0e83f

@github-actions

github-actions Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Visit the preview URL for this PR (updated for commit ef0d6df):

https://hacklytics2027--pr-356-2g1stjc2.web.app

(expires Mon, 24 Aug 2026 17:01:51 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: c48ba34db61581e25fe2978355160b5eefe0e83f

Comment thread apps/dsgt-slack/src/replies.ts Fixed

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit bdb0052. Configure here.

if (event) {
await handleEvent(event, client);
}
return Response.json({ ok: true });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Events ACK waits on reply

Medium Severity

event_callback handling awaits chat.postMessage before returning HTTP 200. Slack’s Events API requires an ACK within about 3 seconds and retries on timeout; with App Hosting minInstances: 0, cold starts plus the API call can overrun that window, so Slack retries and the bot posts the same reply again. There is also no event_id / retry dedupe.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit bdb0052. Configure here.

@greptile-apps

greptile-apps Bot commented Aug 17, 2026

Copy link
Copy Markdown

Greptile Summary

The PR restores the @dsgt FAQ Slack bot by adding a signed HTTP webhook to the existing Firebase App Hosting deployment.

  • Adds mention, direct-message, and /dsgt FAQ handling.
  • Configures App Hosting secrets and exposes the handler through the mainweb Next.js route.
  • Adds Slack application setup, deployment documentation, and webhook tests.

Confidence Score: 4/5

The PR is not yet safe to merge because Slack event acknowledgements still wait for outbound message delivery, allowing retries to produce duplicate replies.

Valid event callbacks remain synchronous with chat.postMessage, and delivery failures are returned as an invalid-JSON response; because the route has no event deduplication or asynchronous acknowledgement boundary, Slack retries can process the same event again.

Files Needing Attention: apps/dsgt-slack/src/http.ts and sites/mainweb/app/(portal)/api/webhooks/slack/route.ts

Important Files Changed

Filename Overview
apps/dsgt-slack/src/http.ts Implements signature verification and Slack request routing, but event acknowledgements remain coupled to outbound reply delivery.
sites/mainweb/app/(portal)/api/webhooks/slack/route.ts Connects the Next.js endpoint directly to the Slack handler without asynchronous processing or event deduplication.
apps/dsgt-slack/src/http.test.ts Covers signatures, challenges, mentions, DMs, and slash commands using immediately successful message-delivery mocks.
apphosting.yaml Adds the Slack bot token, signing secret, and production HTTP-mode configuration to App Hosting.

Sequence Diagram

sequenceDiagram
    participant Slack
    participant Route as Next.js webhook route
    participant Handler as Slack HTTP handler
    participant API as Slack Web API
    Slack->>Route: Signed event_callback
    Route->>Handler: handleSlackWebhook(request)
    Handler->>API: await chat.postMessage(...)
    Note over Slack,API: HTTP acknowledgement remains pending
    API-->>Handler: Success or rejection
    alt Success
        Handler-->>Slack: "200 {ok:true}"
    else Rejection
        Handler-->>Slack: 400 Invalid JSON body
        Slack->>Route: Retry same event
    end
Loading

Reviews (3): Last reviewed commit: "Fix Slack app manifest so Create from ma..." | Re-trigger Greptile

Comment on lines +148 to +153
if (payload.type === "event_callback") {
const event = parseMessageEvent(payload.event);
if (event) {
await handleEvent(event, client);
}
return Response.json({ ok: true });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Webhook acknowledgement waits on replies

When chat.postMessage is slow or rejects, event processing delays the webhook acknowledgement or returns 400 Invalid JSON body, causing Slack to retry the event. Because this path has no retry or event deduplication handling, the retried event can post duplicate bot replies.

The Firebase @dsgt app only answers help, ping, and join. Google Slides,
Forms, and other MCP tools belong on the Grok Bot teammate installed into
the DS@GT Slack workspace.
Replace the polynomial <@[^>]+> matcher with a linear indexOf scan so a
flood of incomplete <@ prefixes cannot backtrack on event text.
Slack rejects Event Subscriptions, Interactivity, and /dsgt when Socket Mode
is off and no Request URL is set. Keep the @dsgt bot user and scopes so the
app can be installed; add those HTTP features in the Slack UI after the
webhook is live.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants