Skip to content

Fixes: @students lookup, channel display, and group-editing authorization - #11

Merged
tytremblay merged 2 commits into
mainfrom
fix-group-handle-lookup
Aug 21, 2026
Merged

Fixes: @students lookup, channel display, and group-editing authorization#11
tytremblay merged 2 commits into
mainfrom
fix-group-handle-lookup

Conversation

@tytremblay

Copy link
Copy Markdown
Contributor

Two fixes, one of which is a live monitoring outage.

@students never resolved, so no student was rostered

resolveGroup decided up front whether a reference was a handle or a Slack id, using a pattern for ids: S followed by alphanumerics.

students uppercased is STUDENTS — an S and seven more characters. So the single most important handle in this project was read as an opaque id, matched against no group, and reported as a group that does not exist.

That broke /hawkmod config set student-group @students and /hawkmod group. Worse, it broke syncRolesFromUserGroups: with the student group set to students, the sync could not resolve it, so nobody was rostered as a student and nobody was monitored as one. It reported this as a workspace_config violation saying the group did not exist — true of the lookup, false of the workspace.

It went unnoticed because the test workspace used hawkmod-test-students, which doesn't begin with S followed only by alphanumerics. mentors was never affected either. Only handles that happen to look like ids — students, staff, seniors — and one of those is the one that matters.

Matching now tries handle or id and never guesses which it was given. The two can't realistically collide: a handle would have to be spelled exactly like some other group's id. There's nothing to gain by telling them apart, and this can't fail the way guessing did.

A failed lookup now logs the handles that do exist, which is how this should have been found in the first place.

Channel names instead of raw ids

/hawkmod config reported the alert channel as C0BPAV78LKZ, which tells a reader nothing — and the whole point of that listing is answering "what is it actually using".

Channels stay stored by id. That part was right: an id survives the channel being renamed, where a stored #name would quietly stop resolving the day somebody tidied it up. So the id is kept and the name is resolved at display time, falling back to the raw value if Slack can't be asked — a settings listing that throws is worse than one that's briefly ugly.

User groups render as @handle for the same reason, and the confirmation after a change now describes both the new value and the old one.

Tests

Nine cases pinning matchesGroup, including the regression explicitly:

it("matches handles that look like a Slack id", ...)  // students, staff, seniors, scouting

npm run typecheck && npm test && npm run format:check && npm run build — 103 tests, all green.

After merging

/hawkmod config set student-group @students will work. If the role sync has been failing, there should be an open workspace_config finding claiming the group doesn't exist — that will clear on the next sync, and /hawkmod sync forces it immediately.

Worth checking /hawkmod status afterwards: if no student has been rostered while this was broken, the roster will fill in on the first successful sync.

🤖 Generated with Claude Code

tytremblay and others added 2 commits August 20, 2026 23:05
Resolution decided up front whether a reference was a handle or a Slack id,
using a pattern for ids: `S` followed by alphanumerics. `students`
uppercased is `STUDENTS` — an `S` and seven more characters — so the single
most important handle in this project was read as an opaque id, matched
against no group, and reported as a group that does not exist.

That broke `/hawkmod group`, and worse, it broke `syncRolesFromUserGroups`:
with STUDENT_USERGROUP=students the sync could not resolve the group, so
nobody was rostered as a student and nobody was monitored as one. It
reported this honestly as a `workspace_config` violation saying the group
did not exist, which was true of the lookup and false of the workspace.

It went unnoticed because the test workspace used
`hawkmod-test-students`, which does not begin with `s` followed by
alphanumerics alone. `mentors` was never affected either. Only the handles
that happen to look like ids — students, staff, seniors — and one of those
is the one that matters.

Matching now tries handle *or* id and never guesses which it was given.
The two cannot realistically collide: a handle would have to be spelled
exactly like some other group's id. There is nothing to gain by telling
them apart, and this cannot fail the way guessing did.

A failed lookup now logs the handles that do exist, which is how this
should have been found in the first place.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`/hawkmod config` reported the alert channel as C0BPAV78LKZ, which tells a
reader nothing about which channel it is — the whole point of the listing
being to answer "what is it actually using".

Channels stay stored by id. That part was right: an id survives the channel
being renamed, where a stored `#name` would quietly stop resolving the day
somebody tidied it up. So the id is kept and the name is shown, resolved at
display time, falling back to the raw value if Slack cannot be asked — a
settings listing that throws is worse than one that is briefly ugly.

User groups render as @handle for the same reason, and the confirmation
after a change now describes both the new value and the old one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tytremblay
tytremblay merged commit 818f400 into main Aug 21, 2026
1 check passed
@tytremblay tytremblay changed the title Fix: @students never resolved, so no student was rostered Fixes: @students lookup, channel display, and group-editing authorization Aug 21, 2026
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