Skip to content

feat(kix): show co-maintainers' projects in their inbox - #174

Merged
kixelated merged 5 commits into
mainfrom
quest/m0/kix/members
Oct 21, 2026
Merged

kixelated merged 5 commits into
mainfrom
quest/m0/kix/members

Conversation

@kixelated

@kixelated kixelated commented Oct 21, 2026 •

Copy link
Copy Markdown
Owner

Completes quest/m0/kix/members.md: every current maintainer of an enrolled project sees it in their decision inbox, not only the user who enrolled it.

Changes

  • New github_project_members(repository, user) table (migration 0012_project_members.sql). It is backfilled from enrolledBy and cascades when a project is disconnected or a user is deleted.
  • GitHubService.#maintainer is the one per-request maintainer check, and it now keeps membership in step with its answer:
    • Passed: the user joins the project if it is enrolled. Enrolling a project adds the enroller in the same batch.
    • Denied (new NotMaintainer error): the user's membership and their inbox_items read and skip state for the project are deleted.
    • Could not complete (any GitHub HTTP failure, such as a 429 rate limit or an outage): the request fails and membership stays as it is.
  • projects(user) lists the user's memberships instead of matching enrolledBy. The inbox hides a project whose check is denied and still reports one whose check could not complete as "Unavailable".
  • Membership only decides which projects are listed. Every action still rechecks authority.
  • Updated the inbox copy and cloudflare/README.md, and deleted the quest.

Decisions (routine, made unattended)

  1. Joining happens in the shared check. Any passed maintainer check on an enrolled project adds membership: the setup page, the activity page, and inbox actions. Hooking every check costs no extra GitHub calls and keeps one code path. A co-maintainer joins by opening the project from /projects.
  2. What counts as a denial. GitHub reporting a role below maintain counts, and so does a missing linked GitHub account. A GitHub identity changed mismatch and every non-2xx response count as checks that could not complete.
  3. enrolledBy stays as a record of who enrolled the project. Dropping it would mean rebuilding github_projects, and several tables reference it with ON DELETE CASCADE. Nothing reads it for the inbox anymore.
  4. A revoked maintainer is hidden at once. The inbox no longer shows an "Unavailable" line for them. A maintainer who later regains the role rejoins by opening the project again.

Validation

just check and just test pass in the Nix shell (Worker tests: 262 passed). New tests cover:

  • a co-maintainer joining
  • a non-maintainer never joining
  • a revoked maintainer dropping out along with their read state
  • a rate-limited check keeping membership and read state
  • disconnect removing all memberships
  • a replacement maintainer joining through the setup page even when its preview fails

Follow-ups

  • kixelated/quest#165 is still open. Its devices() in src/push/notify.ts joins push_subscriptions on github_projects.enrolledBy. Once both PRs land, it should join github_project_members instead, so every member's devices get notified. Its 0012_push.sql also collides with this PR's migration number, so whichever lands second takes the next free number.

🤖 Generated with Claude Code

(Written by Claude Opus 5.5)

kixelated and others added 2 commits October 21, 2026 11:57
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Inbox membership lives in github_project_members. A user joins an enrolled
project by passing the maintainer check on one of its pages, and the
enroller joins on enrollment. A check GitHub denies drops the membership with
the user's read and skip state; one that cannot complete, such as a rate limit,
fails without changing it. Disconnecting cascades.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated

Copy link
Copy Markdown
Owner Author

The quest is done. github_project_members decides which projects each user's inbox lists, and the shared maintainer check keeps it up to date: passing the check joins the user, GitHub denying it drops their membership and read state, and a check that can't complete (such as a rate limit) leaves membership unchanged. just check and just test pass.

I made four routine decisions without input, listed in the description: joining happens on any passed check, what counts as a denial, keeping enrolledBy as a record, and hiding a revoked project at once. One follow-up: once kixelated/quest#165 lands, its devices() should join github_project_members instead of enrolledBy, and the two PRs' migrations need distinct numbers.

(Written by Claude Opus 5.5)

@kixelated
kixelated marked this pull request as ready for review October 21, 2026 19:04
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-21T20:12:50.947666Z 3739bb5 Manual request
🔒 Security Review ✅ Completed 2026-10-21T20:13:31.153417Z 3739bb5 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 998edcb33b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread cloudflare/src/github/service.ts
kixelated and others added 3 commits October 21, 2026 12:34
Keep the done-notice assertions from #173 on the rate-limited inbox, since a revoked maintainer's project is now hidden rather than reported.
GitHub answers 404 for a user removed from the repository. Every caller has already read the repository with the same token, so that 404 now ends the user's membership and read state like any other denial, instead of leaving the project Unavailable forever.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	cloudflare/test/inbox.test.ts
#	quest/m0/kix/README.md
@kixelated

Copy link
Copy Markdown
Owner Author

@codex review

(Written by Claude Opus 5.5)

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: 3739bb5680

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 3739bb5680

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@kixelated

Copy link
Copy Markdown
Owner Author

Merge summary

  • Merged main twice: after kixelated/quest#173 and kixelated/quest#162, then after kixelated/quest#171.
  • Fixed Codex's finding: GitHub's permission endpoint answers 404 for a user removed from the repository, and that now counts as a maintainer denial (NotMaintainer). Every caller has already read the repository with the same token, and the user ID has resolved, so the 404 can only mean the user is no collaborator. A new test covers a removed maintainer.
  • Codex reviewed 3739bb5 and found no issues, and its security review found none either. just check and just test pass, and CI is green.

The decisions in the PR description still hold.

Follow-up: kixelated/quest#165 is still open. Whichever PR lands second should switch push devices() to join github_project_members and take the next free migration number.

(Written by Claude Opus 5.5)

@kixelated
kixelated merged commit e15781e into main Oct 21, 2026
5 checks passed
@kixelated
kixelated deleted the quest/m0/kix/members branch October 21, 2026 21:05
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