Slack reference¶
States, scopes, console screens, metrics and audit actions of the Slack controller. Mechanics: How a Slack pass decides. Setup: Connect a Slack workspace.
Held, retrying and reported rows¶
| State | Means |
|---|---|
held |
Work is waiting for a person. The reason names it: no Slack account yet, a deactivated or bot account, an account of another workspace, no address in the owning directory's served domains, no workspace owner, an invisible private channel of that name (invite the bot), an archived channel of that name (unarchive or rename it), or a visibility that disagrees with the policy |
retrying |
A removal the directory could not vouch for, or a change Slack refused with Slack's words; tried again next pass |
reported |
Said, never acted on: a guest, an account of another workspace, an account with no address |
ignored |
On the channel's ignore list |
The console shows a row held only for a missing Slack account as waiting for them; every other hold is needs you.
roster.slack_action.held is audited once, when the row becomes held, and not again after a restart. A hold is identified by its channel, person, change and a stable reason code. Reworded text under the same code is logged, not audited. A new code is a new hold.
Bot scopes¶
connection.BotScopes is the one list.
| Scope | For |
|---|---|
users:read |
users.info |
users:read.email |
users.lookupByEmail, and the address in users.info |
channels:read |
conversations.list, .info and .members of public channels |
groups:read |
the same, for private channels the bot is in |
channels:manage |
conversations.create, .invite, .kick and .archive in public channels |
groups:write |
conversations.create, .invite, .kick and .archive in private channels |
channels:join |
conversations.join, which adopts a public channel |
conversations.connect:write |
conversations.inviteShared, .acceptSharedInvite |
conversations.connect:manage |
conversations.listConnectInvites |
What the Slack area shows¶
SYSTEMS, Slack is one entry with five tabs.
| Tab | Address | Shows |
|---|---|---|
| Workspaces | #/slack |
Per workspace: connection (not connected, created, not installed, installed, scopes missing), team, owning directory, acts or dry run, last pass, managed channel count, breaker banner with Confirm, leavers |
| Channels | #/slack/channels |
Every managed channel of every workspace, with New channel for operators. Filters: workspace, kind (policy, console, Slack Connect), state (ok, pending, waiting, held, invalid, not reported), name or Slack-id search. Filters live in the address: ?workspace=&kind=&state=&q= |
| Slack Connect | #/slack/connect |
Slack Connect channels |
| Discovered | #/slack/discovered |
Slack Connect channels |
| Apps | #/slack/apps |
Slack Apps |
Pending is a channel the controller is about to create, adopt or accept. The old addresses #/slack-apps and #/slack-connect open the matching tab.
A channel page, #/slack/channels/<workspace>/<name>, shows:
| Part | Shows |
|---|---|
| Feed | Internal groups, or directory groups and addresses |
| Channel | Mode, privacy, and whether it is created, adopted or held |
| People | Each person as in step, will invite, will remove, held with the reason, retrying or reported |
| Slack Connect | Each side of the channel |
| Safety | The removal breaker with Confirm, and the audit history |
A person's page lists each channel's state and reason.
Confirming a breaker from the console¶
A pass that would remove over half of a workspace's or channel's members shows a banner and Confirm (operators only).
Confirming writes _confirm.<workspace>.json into the records ConfigMap. A channel writes _confirm.<workspace>.<channel>.json. It records roster.slack_removals.confirmed.
It lapses after 24 hours. The console refuses a fingerprint that is not the latest report's.
API¶
| Service | Calls |
|---|---|
SlackService |
GetSlackStatus, BeginSlackWorkspaceConnect, RequestSlackPass, ChangeSlackWorkspaceOwner, DisconnectSlackWorkspace, ConfirmSlackRemovals |
SlackChannelService |
ListSlackChannels, CreateSlackChannel, UpdateSlackChannel, DeleteSlackChannel |
SlackSharedChannelService |
ListSlackSharedChannels, CreateSlackSharedChannel, UpdateSlackSharedChannel, DeleteSlackSharedChannel |
SlackAppService |
ListSlackApps, CreateSlackApp, InstallSlackApp |
AccessService |
ListServedDomains, ResolveDirectoryGroups |
See the contracts.
Metrics¶
Over OTLP:
| Metric | Labels |
|---|---|
slack_roster.passes |
workspace, outcome |
slack_roster.changes |
workspace, action, outcome |
slack_roster.rows, slack_roster.channels |
workspace, state |
slack_roster.user_cache |
workspace, result |
slack_roster.breaker_trips, slack_roster.leavers, slack_roster.shared_invalid |
workspace |
The metric prefix is a legacy identifier, renamed in v1.75–v1.76.
Guest-side probe logs¶
| Level | Message | When |
|---|---|---|
| info | guest-side probe with probed, visible, invisible |
once per pass that probed a side |
| debug | a workspace's side of a shared channel is not visible to its bot |
channel_not_found or not_in_channel; the side stays unknown |
| warn | probing a workspace for a shared channel failed; its side stays unknown |
any other error; the pass goes on |
Audit¶
Every action is in audit actions.
| Recorded by | Actions |
|---|---|
| controller | roster.slack_channel.created, .adopted; roster.slack_member.invited, .removed; roster.slack_shared.invited, .accepted; roster.slack_action.held; roster.slack_leaver.reported |
| console | roster.slack_workspace.connected, .owner_changed, .connect_refused, .disconnected; roster.slack_app.created, .installed, .install_refused; roster.slack_console_channel.created, .updated, .deleted; roster.slack_shared_channel.created, .updated, .deleted; roster.slack_channel.archived; roster.slack_removals.confirmed |