# Microsoft Teams

Bucker has two ways into Teams, and they are not equivalent.

| | Workflows webhook (`msteams` channel) | Teams app (`teams` integration) |
| --- | --- | --- |
| Setup | Paste a Power Automate Workflows URL | Azure bot registration plus an uploaded app package |
| Buttons | None; links only | Resolve, mute, reopen, route and the rest of the chat button set |
| Typed commands | No | Yes (`@Bucker issue CHECKOUT-42`, `here`, `snooze`, `help`, ...) |
| Threads, edit in place | No | Yes |
| Needs a tenant admin | No | Yes, once |

The webhook is the floor: it works on any tenant with a URL. The app is the interactive path
and is described here. Neither is an approval surface. A fix can be started from Teams and is
never approved from it.

## What you do (the human steps)

Nothing below can be done by Bucker on your behalf.

1. **Register an Azure bot** (Azure Bot resource, single-tenant). Note its **Microsoft App ID**
   and your **Entra tenant id**, and create a **client secret**.
2. Set the bot's **messaging endpoint** to
   `https://api.bucker.io/webhooks/teams/<integrationId>/messages`. You get `<integrationId>` in the next step; create the integration first with
   placeholders if the portal insists on a value, then edit the endpoint.
3. **Connect the integration** in Settings, Integrations, Microsoft Teams: app id, tenant id and
   the client secret. The secret is stored encrypted and never shown again.
4. **Download the app manifest** with
   `GET /orgs/<org>/integrations/<integrationId>/teams/manifest`, add `color.png` (192x192) and
   `outline.png` (32x32) beside it, zip the three files and upload the package in the Teams admin
   centre (or sideload it for a trial).
5. **Link your account**: type `link` to the bot and follow the answer. A button press from an
   unlinked person does nothing but say so.
6. In a channel, `@Bucker here <project>` binds it so that project's alerts post there.

## How it is secured

- Every inbound call carries a Bot Framework JWT. Bucker checks the signature against
  Microsoft's published keys, the issuer, **this integration's app id** as the audience, expiry,
  and that the token's `serviceUrl` equals the one in the activity body.
- The activity's tenant must equal the tenant the integration was connected for; another tenant
  that sideloaded the app is refused.
- A button's value is a signed mint that names the org, the action and the target; a value minted
  for another org is refused. The person who pressed it must have a live chat link to a Bucker
  user, and the action runs with that user's permissions, in their name.
- Messages Bucker sends are posted at the `serviceUrl` Microsoft gave for that conversation, with
  a token obtained for your bot's app id and secret.

## Limits worth knowing

- Teams rate-limits a bot to about one message per second per conversation; Bucker paces to that.
- There is no clicker-only ("ephemeral") reply in Teams; an answer to a button press appears in
  the conversation.
- The audit row for a button action carries `slack-interactivity` as its user agent, a name from
  before a second chat platform existed. The row's chat metadata records the Entra user and tenant
  that pressed the button, which is the part that identifies the platform.
