You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat: classify onboarding requests mentioned to the Slack bot (CM-1841) - #4884
New POST /v1/slack/events endpoint (Slack Events API): signature check, url_verification challenge, immediate ack, bot messages ignored. Events are deduplicated by event_id on Redis (5 minutes), so a Slack retry is handled only if the first delivery was not; if Redis is down the event is handled anyway. Only mounted when CROWD_SLACK_SIGNING_SECRET is set, same as the interactivity route.
On an app_mention, the bot runs the same classifier as the discovery worker (LLM parser, PCC, CDP) and replies in the thread with the outcome and the step of the flow reached. Slack links (<url|label>) and the mention are normalised before parsing, and the permalink points to the message with the mention. Untrusted values in the reply are escaped so they cannot trigger <!channel>-style mentions, and a reply Slack does not deliver is logged.
Read-only for now: every reply is labelled [DRY RUN] and nothing is written or onboarded. Interactive steps and actions come in the next PRs.
The Slack alert builder moved from the worker to @crowd/project-onboarding (new dependency on @crowd/slack, no cycle) so the worker alerts and the bot replies use the same text.
Slack app setup needed before this works
Event Subscriptions on, Request URL <api>/v1/slack/events, bot event app_mention.
Bot scope app_mentions:read (and chat:write, already used), then reinstall the app and invite the bot to the channel.
Env on the backend: CROWD_SLACK_BOT_TOKEN, CROWD_SLACK_SIGNING_SECRET, plus Bedrock and Snowflake credentials.
Medium Risk
Introduces a new unauthenticated Slack ingress path and runs the full classifier (Snowflake/Bedrock) on mentions; mitigations include signature checks, deduplication, and dry-run-only replies, but PCC SQL changes can alter match ranking.
Overview
Adds Slack Events API support via POST /v1/slack/events, mounted next to interactivity (before DB/tenant middleware) when a signing secret is configured. The handler verifies signatures, answers url_verification, acks within Slack’s window, deduplicates deliveries with Redis (SET NX, 15‑minute TTL), and on user app_mention asynchronously runs the same onboarding request classifier as the discovery worker, replying in the thread.
Bot replies are read-only: always [DRY RUN], with mention/link/HTML normalization on input, sanitized failure text, escaped untrusted fields in alert copy, and shared buildRequestClassificationAlert logic moved into @crowd/project-onboarding (worker updated to import it). pccLookup rewrites the Snowflake leaf-project check from a NOT IN subquery to a LEFT JOIN on parent IDs.
Reviewed by Cursor Bugbot for commit 8ff6cb6. Bugbot is set up for automated code reviews on this repo. Configure here.
Slack escapes literal &, <, and > in incoming event text as &, <, and >. Because this normalization only removes Slack's structural mention/link markup, a project such as R&D reaches the classifier as R&D and can fail PCC/CDP name matching. Decode Slack's three entities after unwrapping links, and add a regression case for an ampersand-containing project name.
classifyOnboardingRequest puts arbitrary caught exception text into an ambiguous resolution (services/libs/project-onboarding/src/classifyRequest.ts:46-49), and this user-facing path renders that reason verbatim. Snowflake, database, or Bedrock failures can therefore expose internal service details in the Slack channel. Keep the detailed failure in server logs and substitute a generic message for resolve failures before building the reply.
Add per-user daily LLM reservation for webhook mentions
Every mention reaches Bedrock without the daily LLM reservation used by the existing Slack onboarding path (backend/src/services/slack/onboardProjectCommand.ts:228-244). The webhook's 200-per-minute IP limiter is not a per-user or daily cost guard, so sustained mentions can continuously consume model quota. Carry the Slack event's user ID through and reserve an appropriate daily allowance before classification.
Slack Events API text encodes literal &, <, and > as &, <, and >. This normalization removes Slack control markup but never decodes those entities, so a project such as R&D reaches the parser/PCC lookup as R&D and can be misclassified. Decode the three Slack entities after stripping mentions and links.
Add top-level Slack text fallback for screen readers
This Block Kit reply has no top-level text fallback before it is passed to chat.postMessage. Slack screen readers default to the top-level text and do not read interior blocks, so users of assistive technology can miss the classification. Include a concise fallback containing the title, outcome, and step reached.
Every mention reaches the Bedrock-backed classifier without the per-actor daily LLM cap used by the existing Slack onboarding flow (backend/src/services/slack/onboardProjectCommand.ts:228-244). The HTTP limiter allows 200 requests/minute per source IP and does not isolate Slack users, so one member can generate an unbounded daily LLM bill. Pass event.user through and reserve a per-user classification/LLM budget before invoking the classifier.
Snowflake rejects a NOT IN subquery in the select list. Fixes the query added in #4877.
Signed-off-by: Umberto Sgueglia <usgueglia@contractor.linuxfoundation.org>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
POST /v1/slack/eventsendpoint (Slack Events API): signature check,url_verificationchallenge, immediate ack, bot messages ignored. Events are deduplicated byevent_idon Redis (5 minutes), so a Slack retry is handled only if the first delivery was not; if Redis is down the event is handled anyway. Only mounted whenCROWD_SLACK_SIGNING_SECRETis set, same as the interactivity route.app_mention, the bot runs the same classifier as the discovery worker (LLM parser, PCC, CDP) and replies in the thread with the outcome and the step of the flow reached. Slack links (<url|label>) and the mention are normalised before parsing, and the permalink points to the message with the mention. Untrusted values in the reply are escaped so they cannot trigger<!channel>-style mentions, and a reply Slack does not deliver is logged.[DRY RUN]and nothing is written or onboarded. Interactive steps and actions come in the next PRs.@crowd/project-onboarding(new dependency on@crowd/slack, no cycle) so the worker alerts and the bot replies use the same text.Slack app setup needed before this works
<api>/v1/slack/events, bot eventapp_mention.app_mentions:read(andchat:write, already used), then reinstall the app and invite the bot to the channel.CROWD_SLACK_BOT_TOKEN,CROWD_SLACK_SIGNING_SECRET, plus Bedrock and Snowflake credentials.pnpm-lock.yamlmatchespnpm install --lockfile-only.Test plan
vitest(backend slack, worker, lib),tsc(backend and worker),pnpm lint --deny-warnings,pnpm format