Skip to content

fix(slack): Clear usergroup when no accepted students have Slack IDs - #62

Merged
tylermenezes merged 1 commit into
mainfrom
detail/bug-fix/fix-slack-clear-usergroup-when-no-accepted-student-621cee
Sep 18, 2026
Merged

tylermenezes merged 1 commit into
mainfrom
detail/bug-fix/fix-slack-clear-usergroup-when-no-accepted-student-621cee

Conversation

@detail-app

@detail-app detail-app Bot commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Detail bug report: View on Detail

Bug

updateSlackUserGroups keeps a Slack usergroup in sync with an event's currently-accepted students who have linked Slack IDs. When the roster became empty (e.g., all previously-added students left the program), a if (ids.length > 0) guard skipped the Slack API call entirely, so departed members stayed in the usergroup indefinitely.

There was no way for the codebase to clear a usergroup: Slack's usergroups.users.update rejects an empty users list (the guard only suppressed that error, it didn't clear the group), and no usergroups.disable/enable existed anywhere in the repo. The stale group was then @-mentioned via <!subteam^...> on student-targeted scheduled announcements, addressing users who had left the program. Introduced in 93061ab7, which wrapped the call in the guard and turned a previously-visible no_users_provided error into a silent leak.

Fix

  • When the roster is empty and a usergroup exists, call slack.usergroups.disable (the only Slack API way to actually clear a group) and persist slackUserGroupId = null on the event, both in the DB and in-memory.
  • Made usergroups.create lazy — only when at least one accepted student has a Slack ID — so empty events don't create placeholder groups, and the cleared id lets the group be recreated fresh when students later re-join.
  • Clearing the id also makes sendScheduledAnnouncements skip the stale <!subteam^...> mention (it already gated that token on slackUserGroupId).
  • Added an optional second slack parameter (defaulting to the real client) so the logic is unit-testable offline; existing single-argument callers (slackSync.ts, slackArchive.ts) are unaffected.

Testing

  • Unit tests, typecheck, and the existing Slack reporting regression test all pass.
  • Added an offline unit test (src/slack/updateSlackUserGroups.test.ts, following the repo's existing custom-harness convention) covering: empty-roster disable+clear, populated-roster update-only, lazy create+update, the no-op case (no group yet), accepted students without Slack IDs, multi-project flattening with null/empty slackId filtering, and the re-join recreate path.
  • End-to-end against a real Postgres database (no DB server was available in the environment, so one was stood up via Docker and the schema applied with prisma db push): seeded an active event with a populated usergroup, moved all students off ACCEPTED, and confirmed usergroups.disable was called and Event.slackUserGroupId persisted as null in the real database; restoring a student recreated a fresh group with a new id. Also ran the real sendScheduledAnnouncements task against the database and confirmed a STUDENT-targeted Slack announcement posted the body with no <!subteam^...> mention when the id was cleared, and still appended the mention in the non-null contrast case.
  • Could not fully verify against a real Slack workspace: no Slack bot token exists in this environment, so every real Slack API call returns invalid_auth. I confirmed the fix's usergroups.disable call is actually issued through the real @slack/web-api WebClient via the real hourly slackSync entry point (the call reaches Slack and fails only on authentication), but could not inspect the usergroup inside a real workspace to confirm Slack marks it disabled. That step requires an operator's Slack workspace token with the usergroups:write scope.
  • Lint is not a CI gate here, and the installed @typescript-eslint/parser is incompatible with the repo's TypeScript 5.x across the whole tree (reproduces on untouched files), so it could not be run.

Automatic Fixes PRs can be configured here.

@detail-app
detail-app Bot requested a review from tylermenezes September 18, 2026 02:55
@tylermenezes
tylermenezes merged commit 522a2d9 into main Sep 18, 2026
1 check passed
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