Draft: PoC (do not merge): one GitLab Duo group per Slack workspace
Proof of concept. Do not review or merge. Throwaway code to explore the experience proposed in gitlab-org#23704 (comment 4003608381) (video and discussion there). We'll rebuild it properly once we agree on the direction.
What it does
- One GitLab Duo group per Slack workspace. All Slack sessions from a workspace run and bill in that group, instead of each user's default Duo namespace.
- Installing the app on a top-level group makes it the Duo group, and turns on the Slack flow there.
- Reworked Slack integration page, following Nick's design: cards for Slack workspace, GitLab Duo, Notifications (list with "+") and Slash commands. Every read-only state says who can change it.
- Marketplace picker (
/-/profile/slack/edit): top-level groups first. - Self-managed: the admin picks the Duo group in the Admin area.
Try it in your GDK (about 5 minutes, no Slack app needed)
The seed script creates test users, groups and fake Slack workspaces for every state, so you can click through without a Slack app.
cd gitlab
git fetch origin && git checkout duo/feature/slack-duo-group-poc
bin/rails db:migrate # adds one table: slack_workspace_duo_groups
bin/rails runner scripts/slack_duo_poc/seed.rb # prints the table below
gdk restart rails-webPassword for every user: Sl4ck-Duo-Poc-2026!
| Sign in as | Open | You see |
|---|---|---|
slack-newbie |
/-/profile/slack/edit |
Marketplace picker, groups first |
slack-newbie |
/groups/empty-co/-/settings/integrations/gitlab_slack_application/edit |
Nothing installed yet |
slack-maintainer |
/fresh-co/web/-/settings/integrations/gitlab_slack_application/edit |
A Maintainer installed Slack on a project. Duo is off: "ask an Owner" |
slack-newbie |
/groups/fresh-co/-/settings/integrations/gitlab_slack_application/edit |
The Owner turns Duo on without a group install |
slack-newbie |
/groups/duo-co/-/settings/integrations/gitlab_slack_application/edit |
Duo on and Ready |
slack-maintainer |
/duo-co/web/-/settings/integrations/gitlab_slack_application/edit |
Read-only Duo, notifications inherited from the group |
slack-other |
/groups/other-co/-/settings/integrations/gitlab_slack_application/edit |
"Managed in another group" |
slack-newbie |
/groups/acme-corp/-/settings/integrations/gitlab_slack_application/edit |
Instance-wide install: the admin decides (self-managed mode only) |
slack-admin |
/admin/application_settings/integrations/gitlab_slack_application/edit |
The admin picks the Duo group (self-managed mode only) |
Moments you can trigger:
bin/rails runner scripts/slack_duo_poc/seed.rb break # someone turns off the Slack flow in Duo Co -> reload, click Fix
bin/rails runner scripts/slack_duo_poc/seed.rb install # simulates "Add to Slack" on Empty Co -> Duo turns on by itself
bin/rails runner scripts/slack_duo_poc/seed.rb # back to the start state, any timeGitLab.com mode (optional)
GitLab.com has no instance-wide integrations, so the last two rows of the table only work in self-managed mode. To see the GitLab.com behaviour:
echo 'export GITLAB_SIMULATE_SAAS=1' >> ../env.runit
gdk restart rails-web rails-background-jobs
GITLAB_SIMULATE_SAAS=1 bin/rails runner scripts/slack_duo_poc/seed.rbRemove the line from env.runit and restart again to go back.
Real Slack install (optional)
You need a Slack app configured in Admin > Settings > GitLab for Slack app that points at your GDK. Events don't matter for setup, so you don't need a tunnel. Then sign in as slack-newbie, open /-/profile/slack/edit, pick Empty Co and approve in Slack.
Clean up
bin/rails runner scripts/slack_duo_poc/seed.rb cleanup # removes fake installs and Duo claims (keeps users and groups)
bin/rails db:migrate:down VERSION=20261012163609 # before switching back to master
git checkout masterKnown gaps
- No migration for existing workspaces, no moving Duo between groups, and no re-approval for older installs that lack the Duo permissions.
- Guests pass the new membership check but are still blocked later: #632568 (closed).
- Error replies in Slack are still private: #632567 (closed).
- New code has few tests. The pipeline was skipped on purpose.