# Guests and Slack Connect

Guests whose own tokens see only their channels and the people in them, and Slack Connect channels shared with members of another organization, as a bot reads them.

A workspace can hold guests, people with limited access such as a freelancer, and Slack Connect channels shared with another organization's own workspace. A guest's own token sees only the guest's channels and the people in them. In a shared channel, your bot reads the other organization's members, who each carry their own team. In `design_studio`:

- Mina Okoro (`UWDC0000037`) is a single-channel guest in `#proj-harborview-dental`.
- `#ext-harborview-dental` (`CWDC0000051`) is shared with Harborview Dental (`TEXT0000001`).
- Kim Ross (`UEXT0000002`) is one of Harborview Dental's contacts.

```bash
curl -s -X POST "$RYSTIC_URL/_rystic/scenario" -d '{"name":"design_studio"}' -o /dev/null
curl -s "$RYSTIC_URL/api/conversations.list?types=public_channel,private_channel" -H 'Authorization: Bearer xoxp-guest' -H 'X-Rystic-Actor: UWDC0000037' | jq -c '[.channels[].name]'
# -> ["proj-harborview-dental"]
curl -s "$RYSTIC_URL/api/conversations.history?channel=CWDC0000001" -H 'Authorization: Bearer xoxp-guest' -H 'X-Rystic-Actor: UWDC0000037' | jq -c .
# -> {"error":"channel_not_found","ok":false}
curl -s "$RYSTIC_URL/api/conversations.info?channel=CWDC0000051" -H 'Authorization: Bearer xoxb-local' | jq -c '.channel | {is_ext_shared, shared_team_ids, connected_team_ids, conversation_host_id}'
# -> {"is_ext_shared":true,"shared_team_ids":["TWDC0000001","TEXT0000001"],"connected_team_ids":["TEXT0000001"],"conversation_host_id":"TWDC0000001"}
curl -s "$RYSTIC_URL/api/users.info?user=UEXT0000002" -H 'Authorization: Bearer xoxb-local' | jq -c '.user | {real_name, team_id}'
# -> {"real_name":"Kim Ross","team_id":"TEXT0000001"}
```

### Guests

A guest is a user whose record has `is_restricted: true`; a single-channel guest also has `is_ultra_restricted: true`. Act as one with a bound token or `X-Rystic-Actor` ([Identities](https://www.rystic.ai/docs/simulators/slack/features/identities.md)). A guest's own token:

- lists only its conversations in `conversations.list` and `users.conversations`;
- gets `channel_not_found` for any conversation it is not in, a public channel included, from `conversations.history`, `conversations.replies`, `conversations.info` and `conversations.members`;
- sees in `users.list` only itself, Slackbot and the people who share a conversation with it, and gets `user_not_visible` from `users.info` on anyone else;
- searches only its conversations' messages with `search.messages` and `search.all`, and with `search.files` only files it uploaded or that were shared into them;
- gets `restricted_action` from `conversations.create` and `conversations.invite`. The one exception is a multi-channel guest inviting someone into a private channel it is in, which Slack's guest roles allow.

**Differs from Slack:** a guest's `search.all` file results hold every file ([Search](https://www.rystic.ai/docs/simulators/slack/features/search.md)). Slack's guest roles show a guest only the file history of the channels it can access.

Your bot reads every guest as it reads anyone, `is_restricted` and `is_ultra_restricted` included, and every other token keeps its own view. `design_studio` holds single-channel guests (Greta, Nils and Mina) and multi-channel guests (Theo, Ava, Imani, Sven and Rafael Duarte, `UWDC0000038`, on the Harborview and Northbank builds).

### Slack Connect channels

A shared channel carries these fields:

- `is_shared`, `is_ext_shared` and `shared_team_ids`;
- `is_pending_ext_shared: false`;
- `context_team_id`, the workspace it is listed in;
- in `conversations.info` only, `connected_team_ids` and `conversation_host_id`. `conversations.list` leaves `connected_team_ids` out, as Slack's guide says it does.

The other organization's members are in the channel's `conversations.members`, never in `users.list`. `users.info` returns one who shares a conversation with your token, with their own `team_id` and `profile.team`. `team.info?team=TEXT0000001` names their workspace.

A message from one of them names their team three times, as `team`, `user_team` and `source_team`. It does so in `conversations.history` and in its `message` event, whose envelope still names your workspace (`TWDC0000001`). A post made as one of them, with `X-Rystic-Actor`, does the same.

### Seeding guests and other teams

- A guest is a `state_user` record with `is_restricted`, plus `is_ultra_restricted` for a single-channel guest, and its `state_membership` rows.
- Another organization is a `state_connected_team` record (`id`, `name`, `domain`). Its members are `state_user` records whose `team_id` is that team's.
- A shared channel is a `state_channel` record carrying the fields above.
- A member's message names their team as `team`, `user_team` and `source_team`.

### Not modeled

- Slack Connect administration: invitations, approvals and organization policies (`conversations.inviteShared` and the other shared-invite methods, `team.externalTeams.*`) are not served.
- DMs with external members, a stranger's `is_stranger` and Enterprise Grid's organization-wide sharing.
- A guest's limits beyond the methods above: posting, reacting or pinning in a conversation it is not in, joining one and opening a DM behave as they would for a member. A workspace preference letting multi-channel guests create private channels is not modeled.
- Measurement: these behaviors follow Slack's documentation. The measuring workspace holds no guest account and shares no channel with another organization, so no fidelity round has checked them yet.

---

Source: https://www.rystic.ai/docs/simulators/slack/features/guests-and-connect · Markdown: https://www.rystic.ai/docs/simulators/slack/features/guests-and-connect.md
