Skip to content

Implement Slack app setup wizard #12

@jonaskay

Description

@jonaskay

Summary

Add setup handlers to the webhook service that automate Slack app creation and OAuth installation. After setup, the service is ready to receive Slack events with no manual credential handling beyond the initial config token.

The flow:

  1. Operator generates a config token at api.slack.com (manual, one-time).
  2. GET /setup/slack — operator pastes config token into a form.
  3. POST /setup/slack — server calls apps.manifest.create, writes credentials to Secret Manager, redirects operator to Slack's OAuth install page.
  4. GET /slack/callback — exchanges OAuth code for a bot token, writes it to Secret Manager, renders success page.

Context

  • No Terraform, Secret Manager client, or setup flow exists yet.
  • Signature verification (internal/slack/verify.go) already exists and is wired into the webhook service.

What to build

1. Terraform: Secret Manager secrets and IAM bindings

Create terraform/secrets.tf with five secrets:

  • threadops-slack-config-token
  • threadops-slack-client-id
  • threadops-slack-client-secret
  • threadops-slack-signing-secret
  • threadops-slack-bot-token

Grant the webhook service account secretAccessor and secretVersionAdder on all five. Expose SLACK_BOT_TOKEN and SLACK_SIGNING_SECRET as env vars on the Cloud Run service (resolved from Secret Manager).

2. Secret Manager client wrapper

Create internal/secretsmanager/client.go with typed read/write methods for each Slack secret. Uses the cloud.google.com/go/secretmanager SDK.

3. Slack app manifest

Create internal/slacksetup/manifest.go — a Manifest(baseURL string) function returning the app manifest as map[string]any. Scopes: app_mentions:read, channels:history, groups:history, chat:write.

4. Setup HTTP handlers

Create internal/slacksetup/handler.go with three handlers:

  • ServeSetupForm (GET /setup/slack) — renders form for config token input. Protected by THREADOPS_SETUP_TOKEN.
  • ServeCreateApp (POST /setup/slack) — calls apps.manifest.create, writes credentials to Secret Manager, redirects to OAuth URL.
  • ServeOAuthCallback (GET /slack/callback) — exchanges code via oauth.v2.access, writes bot token to Secret Manager, renders success page.

5. Route registration

Modify services/webhook/main.go to register the three setup routes behind a THREADOPS_SETUP_ENABLED=true check.

6. Config token rotation (optional / follow-up)

internal/slacksetup/rotation.go — utility to rotate expiring config tokens via tooling.tokens.rotate. Requires an additional threadops-slack-config-refresh-token secret. Can be deferred to a follow-up issue.

Security considerations

  • Setup routes gated by THREADOPS_SETUP_TOKEN (query param or cookie).
  • /slack/callback is self-protecting (requires valid single-use OAuth code) but should also be behind the setup-enabled check.
  • Operator must complete the full flow in one session while setup is enabled, then disable it and redeploy.

Test plan

  • Unit test Manifest() output structure and URL construction
  • Unit test setup handlers with a fake Secret Manager client and HTTP recorder (mock Slack API responses)
  • Unit test OAuth callback with success and error cases
  • Manual e2e: run setup flow against a Slack test workspace

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions