Skip to content

Add a web landing page and a Slack-signed-in configuration page - #56

Merged
tytremblay merged 1 commit into
mainfrom
feat/web-landing-and-config-page
Aug 22, 2026
Merged

Add a web landing page and a Slack-signed-in configuration page#56
tytremblay merged 1 commit into
mainfrom
feat/web-landing-and-config-page

Conversation

@tytremblay

Copy link
Copy Markdown
Contributor

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 in domain/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 from commands/config.ts).

How access works

  • Sign in with Slack (OpenID Connect) answers who the browser is — scopes openid profile, identity only. The token Slack returns can call openid.connect.userInfo and nothing else; it's used for that single call and discarded, never stored or logged.
  • HawkBot Admin (ADR-0004: admin usergroup member, or workspace Owner) answers what they may do, checked live on every page load — removal from the group takes effect within the existing 5-minute cache.
  • Sessions are stateless HMAC-signed cookies (12 h, signed with SLACK_STATE_SECRET); nothing new is stored in the database. CSRF: SameSite=Lax plus 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 URL https://bot.redhawkrobotics.org/auth/slack/callback, and the openid + profile user 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

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>
@tytremblay
tytremblay merged commit b174b0a into main Aug 22, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant