# BeginSlackWorkspaceInstall

## Permission Scope

slackWorkspaceIntegration

## Overview

beginSlackWorkspaceInstall prepares the Slack OAuth handshake for a tenant administrator. The input is `(clientId, signingSecret, redirectUri?)`. It writes nothing: it produces a time-limited `state` token, HMAC-SHA256-signed with `signingSecret`, and the Slack `oauth/v2/authorize` URL the browser redirects to. The matching `completeSlackWorkspaceInstall` later verifies that `state` signature (with the same `signingSecret`), expiry, pinned actor, and pinned `redirectUri` before exchanging the returned code for a bot token.

## Business Rules

- Authorization is enforced by the command's permission gate on `notification:slackWorkspaceIntegration` (or the command-level `notification:slackWorkspaceIntegration:beginSlackWorkspaceInstall`; a module-level or command-level grant both satisfy it); the command body assumes an authorized caller
- The generated `state` encodes the acting `userId`, an optional `redirectUri`, and an expiry, and is HMAC-SHA256-signed with the supplied `signingSecret`; it is opaque to the caller and signature-verified on completion (a forged or tampered state is rejected)
- An existing `ACTIVE` connection does not block beginning a re-install flow
- The requested OAuth scope is `chat:write,channels:read`
- No persistence occurs — the command is a pure URL/state builder

## Process Flow

```mermaid
flowchart TD
    A[Receive beginSlackWorkspaceInstall] --> D[Generate state token with userId, redirectUri, expiry]
    D --> E[Build Slack authorize URL with client_id, scope, state, optional redirect_uri]
    E --> F[Return authorizeUrl and opaque state]
```

## External Dependencies

- Slack OAuth authorize endpoint (`https://slack.com/oauth/v2/authorize`) - browser redirect target for workspace install

## Error Scenarios

- None — authorization is enforced by the command's permission gate, and the command performs no further validation

## Test Cases

- returns a Slack authorize URL carrying a state token
- signs the state so a different secret cannot verify it
- includes redirect_uri in the authorize URL when supplied
