Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1165,7 +1165,11 @@ Uninstall dispatches `app_uninstalled` and `tokens_revoked` to matching event su
### Inspector
- `GET /` - tabbed local inspector for conversations, messages, files, views, auth records, incoming webhooks, event subscriptions, and event deliveries

When a supported Slack write emits an `event_callback`, the payload contains the inner `event` plus outer `team_id`, `event_id`, and `event_time`. The team comes from the presented Slack token's installation; development tokens without a stored Slack record fall back to the affected channel, user, or file's team, then the seeded workspace team (or `T000000001`). Incoming webhook posts use their webhook record's team, or the target channel's team when no record matches. `event_time` is an integer Unix timestamp in seconds. Each logical event gets a new `event_id`, shared across deliveries to multiple subscribers.
When a supported Slack write emits an `event_callback`, the payload contains the inner `event` plus outer `token`, `api_app_id`, `authorizations`, `team_id`, `event_id`, and `event_time`. The team comes from the presented Slack token's installation; development tokens without a stored Slack record fall back to the affected channel, user, or file's team, then the seeded workspace team (or `T000000001`). Incoming webhook posts use their webhook record's team, or the target channel's team when no record matches. `event_time` is an integer Unix timestamp in seconds. Each logical event gets a new `event_id`, shared across deliveries to multiple subscribers.

Callbacks identify each workspace installation with its recipient `api_app_id` and bot authorization. With multiple installed apps, each receives a separate envelope; configured webhook subscriptions are shared and can route by `api_app_id`. Without an installation, callbacks use `A000000001` and a local user authorization. The legacy `token` field defaults to `emulate-verification-token`; set `slack.verification_token` to match receivers that check it. Use `slack.signing_secret` for request signature verification.

Every inner event includes `event_ts`. Message events include `channel_type` (`channel`, `group`, `im`, or `mpim`). Posts made with an issued or seeded bot token include the bot's `bot_id`, `app_id`, and `bot_profile` when the corresponding bot record exists. These fields persist in history, replies, and updates so handlers can identify their own messages. Removing an installed bot with `conversations.kick` or `conversations.leave` also emits `channel_left` or `group_left`, with `actor_id` and `event_ts`, for the affected app.

To test bot handlers, invite an installed app's `bot_user_id` with `conversations.invite`, subscribe to `app_mention`, then post text containing `<@BOT_USER_ID>` with `chat.postMessage`. Channel mentions produce one callback per mentioned app, with outer `api_app_id`, inner `event_ts`, and the original message and thread identity. DMs and MPIMs use `message` events.

Expand Down
7 changes: 6 additions & 1 deletion apps/web/content/docs/slack.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,11 @@ Uninstall dispatches `app_uninstalled` and `tokens_revoked` to matching event su

For supported Slack writes that emit events, the emulator dispatches `event_callback` payloads to configured webhook URLs matching Slack's Events API format:

Each callback includes outer `team_id`, `event_id`, and integer Unix-seconds `event_time` alongside the inner `event`. For authenticated Web API writes, `team_id` comes from the presented Slack token's installation. Development tokens without a stored Slack record fall back to the affected channel, user, or file's team, then the seeded workspace team (or `T000000001`). Incoming webhook posts use their webhook record's team, or the target channel's team when no record matches. Each logical event gets a distinct `event_id` shared by deliveries to multiple subscribers.
Each callback includes outer `token`, `api_app_id`, `authorizations`, `team_id`, `event_id`, and integer Unix-seconds `event_time` alongside the inner `event`. For authenticated Web API writes, `team_id` comes from the presented Slack token's installation. Development tokens without a stored Slack record fall back to the affected channel, user, or file's team, then the seeded workspace team (or `T000000001`). Incoming webhook posts use their webhook record's team, or the target channel's team when no record matches. Each logical event gets a distinct `event_id` shared by deliveries to multiple subscribers.

Callbacks identify each workspace installation with its recipient `api_app_id` and bot authorization. With multiple installed apps, each receives a separate envelope; configured webhook subscriptions are shared and can route by `api_app_id`. Without an installation, callbacks use `A000000001` and a local user authorization. The legacy `token` field defaults to `emulate-verification-token`; set `slack.verification_token` to match receivers that check it. Use `slack.signing_secret` for request signature verification.

Every inner event includes `event_ts`. Message events include `channel_type` (`channel`, `group`, `im`, or `mpim`). Posts made with an issued or seeded bot token include the bot's `bot_id`, `app_id`, and `bot_profile` when the corresponding bot record exists. These fields persist in history, replies, and updates so handlers can identify their own messages. Removing an installed bot with `conversations.kick` or `conversations.leave` also emits `channel_left` or `group_left`, with `actor_id` and `event_ts`, for the affected app.

To test bot handlers, invite an installed app's `bot_user_id` with `conversations.invite`, subscribe to `app_mention`, then post text containing `<@BOT_USER_ID>` with `chat.postMessage`. Channel mentions produce one callback per mentioned app, with outer `api_app_id`, inner `event_ts`, and the original message and thread identity. DMs and MPIMs use `message` events.

Expand All @@ -168,6 +172,7 @@ To test bot handlers, invite an installed app's `bot_user_id` with `conversation
- `channel_rename` / `group_rename` and matching name message subtypes on `conversations.rename`
- `message` with public `channel_topic` / `channel_purpose` or private `group_topic` / `group_purpose` subtypes on topic and purpose writes
- `member_joined_channel` / `member_left_channel` on invite, join, leave, and kick writes
- `channel_left` / `group_left` when an installed bot leaves or is removed
- `im_created`, `im_open`, `im_close`, `im_marked`, and group open/close/marked events for DM and MPIM writes
- `user_change` on profile writes
- `presence_change` on presence writes
Expand Down
6 changes: 5 additions & 1 deletion packages/@emulators/slack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,11 @@ A modal receiver must acknowledge within three seconds. An empty HTTP 200 closes
### Inspector
- `GET /` — tabbed local inspector for conversations, messages, files, views, auth records, incoming webhooks, event subscriptions, and event deliveries

When a supported write emits an `event_callback`, the payload includes the inner `event` and outer `team_id`, `event_id`, and integer Unix-seconds `event_time`. The team comes from the presented Slack token's installation; development tokens without a stored Slack record fall back to the affected channel, user, or file's team, then the seeded workspace team (or `T000000001`). Incoming webhook posts use their webhook record's team, or the target channel's team when no record matches. Each logical event has a distinct `event_id` shared by deliveries to multiple subscribers.
When a supported write emits an `event_callback`, the payload includes the inner `event` and outer `token`, `api_app_id`, `authorizations`, `team_id`, `event_id`, and integer Unix-seconds `event_time`. The team comes from the presented Slack token's installation; development tokens without a stored Slack record fall back to the affected channel, user, or file's team, then the seeded workspace team (or `T000000001`). Incoming webhook posts use their webhook record's team, or the target channel's team when no record matches. Each logical event has a distinct `event_id` shared by deliveries to multiple subscribers.

Each workspace installation receives an envelope attributed to its `api_app_id` and bot authorization. Event subscriptions are shared across apps; receivers can route by `api_app_id`. Without an installation, callbacks use `A000000001` and a local user authorization. The legacy `token` defaults to `emulate-verification-token`; override it with `slack.verification_token`. Use `slack.signing_secret` for signature verification.

Inner events include `event_ts`. Message events identify `channel`, `group`, `im`, or `mpim` in `channel_type`. Posts made with issued or seeded bot tokens and incoming webhook or interaction replies include `bot_id`, `app_id`, and `bot_profile` when the bot record exists, preserving bot identity in callbacks, updates, history, and replies. Removing an installed bot with `conversations.kick` or `conversations.leave` also emits `channel_left` or `group_left`, with `actor_id` and `event_ts`, for the affected app.

Slack message text is limited to 40,000 Unicode characters across chat writes, incoming webhooks, and file upload initial comments. Longer text is truncated at a Unicode code point boundary before it is stored or dispatched. Successful Web API responses include `warning: "message_truncated"` and `response_metadata` with the matching warning and explanatory message. Rich fields such as `blocks` and `attachments` are preserved unchanged.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ describe("Slack app mentions", () => {
type: "event_callback",
team_id: "T000000001",
api_app_id: appId,
authorizations: [expect.objectContaining({ user_id: botUserId, is_bot: true })],
event_id: expect.stringMatching(/^Ev[0-9a-f]{32}$/),
event_time: expect.any(Number),
event: expect.objectContaining({
Expand Down
Loading
Loading