Overflow Tap: speak Overflow's Dashboard API, as its own helper app does

The first cut guessed a write route on Overflow's public API, which documents
only reads for Tap. With the helper app's bundle in hand (Overflow ProPresenter
Integration 1.2.3, read 2026-10-11) the module now makes exactly the calls the
helper makes, against the Dashboard's own backend:

  POST /nonprofit-dashboard/authentication/login/jwt      a Dashboard sign-in → JWT
  GET  /nonprofit-dashboard/propresenter/nonprofits/{id}/keywords
                                                          the Keyword Mappings
  POST …/nonprofits/{id}/keywords?syncNonprofit=true      { keywords } = the switch

So the keyword → destination → Tap groups mapping stays where Overflow keeps
it (Dashboard › Integrations › ProPresenter › Keyword Mappings) and is read
from there: on start, every five minutes, on the tile's refresh button, and
from every trigger's answer. Admin config shrinks to the ProPresenter endpoint,
the Overflow Dashboard login (plus a Nonprofit ID only for an @overflow.co
staff login) and the alert switch; the API-key, Tap-groups, keyword-text and
match-mode fields are gone.

Behaviour follows the helper: both the presentation layer (/v1/status/slide)
and the announcement layer (/v1/announcement/slide_index + /active) are
watched; when a layer's set of matched keywords changes to a non-empty set it
is sent; matching is per word, case-insensitive, punctuation around the word
ignored. The session token is cached across re-inits for the same login so an
admin saving config repeatedly cannot trip Overflow's "too many attempts";
a 401 signs in again once; a refused sign-in is not retried within 20 s.

tools/overflow-tap-mock.js now plays the Dashboard API (any email/password
signs in; --fail-switch, --expire=<s>, --login=<email>:<password>) and gives
the mock ProPresenter an announcement layer (--no-announcements for an older
one). Verified against it: sign-in, keyword load, triggers on both layers,
token expiry → re-login, 500 → NOT SWITCHED + alert + retries, wrong login →
the reason on the tile and in the health line, and recovery. keywords.selftest.js
pins the matching rule (8 cases).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Waters Church
2026-10-11 10:25:02 -04:00
co-authored by Claude Fable 5.1
parent 6b51044be6
commit 459d8b9c38
9 changed files with 738 additions and 622 deletions
+28 -24
View File
@@ -510,26 +510,27 @@ below. Nothing is installed without someone clicking.
read from the account), and a folded **Timing** group for the poll
intervals and a position trim.
Tile settings: cue name, previous cue, playhead, cue list.
- **Overflow Tap** — what Overflow's own ProPresenter helper app does,
inside ProdDash: the live slide's notes are read from ProPresenter, and
when they carry one of the admin page's keywords, the chosen Overflow Tap
groups are pointed at that keyword's destination — so a tap on a disc
follows what is on screen. A slide with no keyword changes nothing. The
tile is one keyword, big: what Tap is on (and since when), its destination
and the groups moved, a chip saying whether the slide on screen carries a
keyword, and the last four switches with their times; a failed switch
turns the tile red with the reason and, if switched on in admin, flashes
an alert channel. Admin config: the ProPresenter endpoint, the Overflow
API credentials (Developers › API Keys in the Overflow Dashboard), the Tap
groups to switch (read from the account), the keywords — one per line as
`give = Give Online`, optionally `@ Lobby, Kids Wing` to switch only
those groups — and how a keyword matches (whole word, anywhere, or on its
own line). Tile settings are four switches: destination, groups, slide
match, history. **One thing is still unverified:** Overflow's public API
documents only *reads* for Tap, so the call that moves a group (`PATCH
/api/v3/tap/groups/{id}` with the new `destinationId`) is the natural
shape, not a documented one; every switch is confirmed by reading the
group back, so a refusal shows on the tile rather than passing silently.
- **Overflow Tap** — what Overflow's own "ProPresenter Integration" helper
app does, inside ProdDash, speaking the same Dashboard API it does: the
live slide's notes are read from ProPresenter (the presentation layer and
the announcement layer), and when they carry one of the keywords mapped in
the Overflow Dashboard, Overflow is told — and points that keyword's Tap
groups at its destination, so a tap on a disc follows what is on screen.
A slide with no keyword changes nothing. Keywords match as the helper
matches them: as a whole word of the notes, any case, punctuation around
it ignored (`give` fires on "Give!" and not on "forgiveness"). The tile is
one keyword, big: what Tap is on (and since when), its destination and the
groups moved, a chip saying whether the slide on screen carries a keyword,
and the last four switches with their times; a failed switch turns the
tile red with the reason, is retried, and — if switched on in admin —
flashes an alert channel. Admin config: the ProPresenter endpoint and an
**Overflow Dashboard login** (email and password; Google sign-in has no
password, so set one with "Forgot Your Password?"). The keywords, their
destinations and their Tap groups stay where Overflow keeps them —
Integrations › ProPresenter › Keyword Mappings in the Dashboard — and are
read from there on start, every few minutes, and on the tile's refresh
button. Tile settings are four switches: destination, groups, slide
match, history.
- **Band Lineup** — the backstage stage board: everyone on stage in their mic
slot with photo, name and mic/pack label, on one shared board that every
screen sees the same way — whoever edits it changes it everywhere, over SSE.
@@ -582,10 +583,13 @@ run ProdDash with `SLACK_API_BASE=http://127.0.0.1:24716/api`) and
board — a plan, its team members, birthdays and photos — run ProdDash with
`BAND_LINEUP_API_BASE=http://127.0.0.1:24710`) and
`node tools/overflow-tap-mock.js` (a ProPresenter whose slide notes carry
keywords on `127.0.0.1:1602` plus the Overflow Tap API on `127.0.0.1:24720`
— run ProdDash with `OVERFLOW_TAP_API_BASE=http://127.0.0.1:24720`;
`--read-only` makes the switch fail the way the public API does today). See
the testing section of the [module guide](docs/MODULE-GUIDE.md).
keywords on `127.0.0.1:1602`, announcement layer included, plus the Overflow
Dashboard API on `127.0.0.1:24720` — run ProdDash with
`OVERFLOW_TAP_API_BASE=http://127.0.0.1:24720` and sign the module in with
any email and password; `--fail-switch` refuses every switch,
`--expire=20` makes sessions expire, `--login=<email>:<password>` accepts
one login only). See the testing section of the
[module guide](docs/MODULE-GUIDE.md).
## Install as a desktop web app