From babe8263ebcc11d1abdfc189461843768c6e54dc Mon Sep 17 00:00:00 2001 From: Waters Church Date: Mon, 14 Sep 2026 11:49:40 -0400 Subject: [PATCH] Slack module: channel transcript + PIN-gated sending as the location MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each campus signs its booth machine into Slack as the account named for the location, so a message from ProdDash reads as "Apollo Beach" rather than as whoever is at the desk. modules/slack (1.0.0) is three tiles from one module: the live transcript of one channel, a free-text Send tile and a Quick-replies grid — the last two behind a PIN pad, auto-locking after a configurable idle time. Server: one user (xoxp-) or bot (xoxb-) token, identified with auth.test; conversations.history polled every N seconds (thread replies via conversations.replies, capped per poll), diffed and fanned out as one `state` SSE snapshot; mrkdwn rendered to safe text on the server; sends through chat.postMessage (username/icon for a bot with "Send as"); PIN compared in constant time with a 5-wrong → 30 s lockout, 32-byte unlock tokens with a sliding expiry, 1 message/s, every send logged; readable messages for invalid_auth / token_revoked / missing_scope / not_in_channel / ratelimited; health reflects token → channel → poll → sending. SLACK_API_BASE points it at tools/slack-mock.js (new). Shell: the admin config form gains a multi-line field type `text` (a textarea; one item per line by convention) — used for the quick replies. Documented in the module guide; the mock is listed in CLAUDE.md. Co-Authored-By: Claude Fable 5.1 --- CLAUDE.md | 1 + docs/MODULE-GUIDE.md | 5 +- modules/slack/client.js | 765 ++++++++++++++++++++++++++++ modules/slack/module.json | 100 ++++ modules/slack/server.js | 1007 +++++++++++++++++++++++++++++++++++++ modules/slack/style.css | 424 ++++++++++++++++ public/admin/admin.css | 16 + public/admin/admin.js | 11 + tools/slack-mock.js | 309 ++++++++++++ 9 files changed, 2637 insertions(+), 1 deletion(-) create mode 100644 modules/slack/client.js create mode 100644 modules/slack/module.json create mode 100644 modules/slack/server.js create mode 100644 modules/slack/style.css create mode 100644 tools/slack-mock.js diff --git a/CLAUDE.md b/CLAUDE.md index ba8b906..655a735 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -37,6 +37,7 @@ title-bar controls). The rules that matter most: - Verify against the guide's testing section and resilience checklist. Mocks for the existing upstreams: `node tools/prodcom-mock.js` (ProdCom) and `node band-lineup-display/tmp/pp-mock.js 1599` (ProPresenter). + `node tools/slack-mock.js 24716` (Slack; run ProdDash with `SLACK_API_BASE=http://127.0.0.1:24716/api`). ## Reference code (read-only forks — don't develop these here) diff --git a/docs/MODULE-GUIDE.md b/docs/MODULE-GUIDE.md index 7593f1a..71969b5 100644 --- a/docs/MODULE-GUIDE.md +++ b/docs/MODULE-GUIDE.md @@ -104,7 +104,7 @@ the app); its settings are kept for a later reinstall. Both schemas map field names to specs: ``` -{ "type": "string" | "number" | "boolean" | "switch" | "select" | "color" | "password" | "endpoint", +{ "type": "string" | "text" | "number" | "boolean" | "switch" | "select" | "color" | "password" | "endpoint", "label": "Shown next to the field", "default": , "group": "Section heading", // optional; see below @@ -125,6 +125,9 @@ shown or enabled, off means hidden or disabled, and the label shouldn't say so twice. `color` renders a swatch picker and stores a `#rrggbb` string (give it a hex default; the tile applies it as a CSS custom property — see `pco-plan`). +`text` is a multi-line string — a `