# Slack

Throughline can reach your crew in Slack instead of — or alongside —
WhatsApp: briefs, readiness nudges, call-sheet changes, and a DM where
someone can ask the production's own assistant a question and get the
show's own answer. Slack is a transport and a surface, never the record —
everything it says is computed from the production's own graph, and
everything a crew member tells it is filed there, exactly like every other
channel.

You can see all of this with no Slack workspace at all. **Settings → Slack**
has a simulator — one button, **Turn on the simulator** — that runs the
identical routing, identity matching, and health reporting with nothing
leaving the building: it's the real adapter with the one call that reaches
Slack itself swapped out.

## Installing the app

1. In the production's **Settings → Slack** panel, choose a mode — this
   changes only the install path and where the credential lives; routing,
   gating, and rendering behave identically either way:
   - **Bring your own workspace** — the production's own Slack.
   - **Managed by Throughline** — a workspace Critical Period runs for the show,
     under our own org, paid up front. The same install button; Slack tells
     us it was an org-wide install and the card says so.
2. Click **Add to Slack**, approve on Slack's own consent screen, and you
   land back on that same Settings panel with the workspace named — the
   handshake begins and ends on one screen. The bot token never touches your
   clipboard or a log — it goes straight into the production's own encrypted
   [key custody](keys.html), shown afterward only as **Slack (the app's own
   token)**, a last-4 stub, and who connected it.
3. For each person who wants Slack, bind their Slack account once — on
   **their own contact card in Crew**, where the Slack line sits beside
   their email, phone and time zone, because that is what it is: another way
   this person is reachable. Open the card, paste their member ID (in Slack:
   their profile → ⋮ → Copy member ID), and set their preferred channel to
   Slack — or they can just tell their assistant "reach me on Slack."
   Binding is admin-only. Throughline never guesses which Slack account is
   which crew member; a binding is a claim a human makes, and the card says
   who made it.

Once bound, everything the product would have sent to a person's phone goes
to their Slack DM instead, through the same routing every sender already
uses — no per-feature work, and nobody else's experience changes. Someone
staying on WhatsApp and someone reading Slack are on the same call sheet,
sent once, by one function.

**What it never reads.** The app makes exactly one read call: a channel's
member list — who's in the room, checked before a scoped message may reach
it — never a transcript. It holds no channel-history permission at all, so a
room's backscroll is not something it *can* read, on any plan; a DM reaches
the assistant only because somebody chose to write one. And it never posts
as a person — every message carries the assistant's own name.

## Per-department display names

One installation, one bot token — and every department still reads as its
own correspondent. A message to `#tl-costume` is signed **Stitch ·
Costume**; the same installation, writing in `#tl-locations`, is the
locations seat. The department's name and icon are a property of each
individual message, not a separate app registration, so connecting Slack
never means an admin completing department after department of OAuth
installs, and there's exactly one token to rotate and one health line to
watch.

The app's own name still appears beneath the department's, so the signature
is never hidden — and a per-message display name doesn't create a separate
member: the workspace's own member list shows one app, not one per
department.

## Channels provision themselves

Turn Slack on and the crew list provisions its own rooms — nobody clicks
through sixty people by hand.

- **A small, prefixed channel set per show:** `#tl-general` for
  announcements, `#tl-<department>` for department traffic, `#tl-urgent` for
  interrupt-tier traffic, which department heads are seated into, a
  `#tl-day-<n>` per shoot day opened with exactly that day's own admitted
  recipients, and `#tl-e<season><episode>` for an episodic show's live
  episodes.
- **Provisioning follows the crew list, not a separate step.** The moment a
  crew member's access goes active, they're seated into `#tl-general`,
  their department's channel, and `#tl-urgent` if they lead it — with a
  workspace account provisioned for them first if they don't have one yet.
- **A sensitive seat holds instead of provisioning automatically** — a
  minor, or anyone under administrative review. Nothing is created for
  them; the seat waits in a coordinator's queue naming exactly which
  channels it would join, until a person confirms it. That confirmation is
  itself part of the record.
- **Wrap archives, it doesn't delete.** The show wraps and every live
  channel archives, with the workspace's own export filed back into the
  production's record on the same footing as every other document it keeps
  — and the export application is filed during prep, not discovered as a
  problem at wrap.

## Notification tiers

Slack integrations have a well-worn failure mode: every event posts, a
channel floods within a day, and the team mutes the whole app rather than
tuning it — because there was no urgency model to tune in the first place.
Throughline routes by urgency instead of by event type:

| Tier | What lands here | How it arrives |
|---|---|---|
| **Interrupt** | Call-time changes, weather holds, a readiness flag going red | A DM, immediately — never batched, never folded into a digest |
| **Ambient** | Script revisions, dailies, an approval raised or moved on someone else's card | A DM — an approval's own updates land on its one message, updated in place rather than posted fresh |
| **Digest** | Scores, general activity, non-urgent department notes | Rounded up and sent at most once a day rather than message by message |

Everything reaches a person as a DM today: it's the delivery that works
whatever state a show's channels are in. Routing ambient traffic into its
department's own channel, and cross-posting an interrupt to `#tl-urgent`,
are the next step rather than something already happening — the tier a
message carries is what that step will read.

## One message per work object

An approval gets exactly one Slack message — updated in place as its state
changes, rather than a fresh post every time something happens to it. An
approval that gets nudged, aligned on, and decided over the course of a day
shows up as one message with one history, not three separate pings to piece
back together. Dailies and a weekly budget line send once by construction,
so there is nothing there to thread in the first place.

Cards act rather than only inform. Tap **Approve** on an approval card and
it decides for real, resolved through the same identity ladder and the same
permission check the web app makes — an unauthorized press moves nothing and
hears the browser's own refusal. A call sheet's **Confirmed** button writes
its confirmation through the identical function a WhatsApp reply writes
through, so one shared record answers "who has seen the call sheet"
regardless of which channel a person answered on.

## Quiet hours

Throughline won't message a crew member during quiet hours, and the comms
window is derived from the day rather than only typed:

- **On a shoot day, the window brackets the day**: it opens an hour before
  general call and closes an hour after wrap — so the calls that land
  before the day starts and the notes that follow the wrap both get
  through, and nothing lands in the dead of night. A wrap that runs long
  moves the window with nobody touching a setting; a night shoot that
  wraps past midnight carries it over correctly.
- **On a day with no shooting** — prep, post, the Sunday before a Monday
  call — a daytime band applies instead: 08:00–20:00 on the production's
  own clock by default, and the production can set its own band. There is
  no day the show goes fully silent, and no day it can reach you around
  the clock.
- **A person's own quiet-hour preference** — an hour after which they'd
  rather not hear from the show, until morning on their own clock —
  applies alongside it, on their time zone rather than the server's. A
  typed hour only ever narrows the window, never widens it: it can defer a
  message the day's bracket would have let through, but it can't open an
  hour the bracket already calls quiet.

Deferral is always passive: a message held for quiet hours is never
dropped, only delayed to the next moment the window is open, and it's
re-checked against whatever is true *then* — so a wrap that runs long or a
call time that moves doesn't leave a stale message going out at the old
time.

## When something's wrong

Your production's **Settings → Slack** panel states the installation, the
mode, when Slack last reached us, and the last thing Slack refused us with —
plus who's asking for Slack with no account bound yet, named rather than
counted, each one naming the person to look up in Crew, where the fix is.
So a silent case never
stays silent for long. A revoked token, an unbound account, or a disconnected
workspace all fall back to a person's phone on the very next send.
