Add a web landing page and a Slack-signed-in configuration page - #56
Merged
Conversation
bot.<domain> now serves a branded landing page at / and a settings editor at /config — the same settings, validation, and usergroup handle→id resolution as /hawkbot config, through one shared write path (slack/settingsWrite.ts, extracted from commands/config.ts). Sign in with Slack (OpenID Connect, `openid profile`) establishes who the browser is; the existing HawkBot Admin check decides what they may do, live on every page load. The OIDC token is used for one userInfo call and discarded — never stored, never logged. Sessions are stateless HMAC-signed cookies (12h, SLACK_STATE_SECRET); CSRF is SameSite=Lax plus an Origin check on every POST. ADR-0015 records why identity-only OIDC scopes are the one deliberate exception to "no user scopes", and CLAUDE.md rule 1 is sharpened to match. Deploying needs the manifest's new /auth/slack/callback redirect URL and the openid/profile user scopes; no bot reinstall. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
bot.redhawkrobotics.org(routed by hawk_suite) now serves:/— a branded landing page: what Hawk Bot is, what it deliberately cannot do, and a link into configuration./config— a settings editor for the same workspace settings as/hawkbot config: one card per setting declared indomain/settings.ts, with its live value (channel/usergroup ids annotated with resolved names, as in the slash command), a Save form, and an Unset button. Same validation, same usergroup handle→id resolution, one shared write path (src/slack/settingsWrite.ts, extracted fromcommands/config.ts).How access works
openid profile, identity only. The token Slack returns can callopenid.connect.userInfoand nothing else; it's used for that single call and discarded, never stored or logged.SLACK_STATE_SECRET); nothing new is stored in the database. CSRF:SameSite=Laxplus an Origin check on every state-changing POST. A sign-in from any other Slack workspace proves nothing here — the session's team must match the installed team.Load-bearing rule #1, addressed head-on
Slack manifests list OIDC scopes under user scopes. ADR-0015 records why identity-only OIDC scopes don't violate what the "no user scopes" rule protects (the app remains unable to read anything a person couldn't watch it read), and CLAUDE.md rule 1 is sharpened to "no user token scopes" with this as the sole named exception. The considered-and-rejected alternatives (magic-link DM, allow-list) are in the ADR.
Deploying
Two Slack app manifest updates (both already in
docs/slack-app-manifest.yaml): the new redirect URLhttps://bot.redhawkrobotics.org/auth/slack/callback, and theopenid+profileuser scopes. No bot reinstall — OIDC consent happens per person at first sign-in. No new environment variables.Tests
19 new pure tests (
test/webSession.test.ts,test/webPages.test.ts): session/state token round-trip, tamper, expiry, and cross-purpose rejection; cookie parse/serialize; HTML escaping and page rendering. Typecheck, format check, full suite (230), and build all pass.🤖 Generated with Claude Code