Reviewer requests must be blocked (server + UI) on merged/closed PRs #599
Labels
No labels
actions
bug
cli
duplicate
enhancement
fork
forum
git storage
help wanted
insights
invalid
issues
moderation
oidc
ownership transfer
packages
pr/merge protection rules
projects
pull requests
question
releases
sponsorships
tags
webhooks
wiki
wontfix
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
crueber/walhub#599
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Reviewer requests must be blocked (server + UI) on merged/closed PRs
What's requested
Adding and removing requested reviewers must be refused — server-side with a 4xx, and in the UI by hiding/disabling the reviewers picker — once a pull request is closed or merged.
Evidence (static analysis, current tree; no local repro per standing rule)
Server — no state check at all.
internal/review/threads.go:AddRequests(POST…/api/pulls/{num}/review-requests, line 507) validates auth, read access, author-or-triage+ role, and reviewer list shape — but never inspects the PR's state. It callss.prHeadOf(...)(line 514) which returns thePRHeaderandPRSidecar, both of which carry exactly the fields needed:PRHeader.State(internal/review/model.go:183) andPRSidecar.Merged(internal/review/model.go:213). The check is missing, not hard.RemoveRequests(DELETE, line 570) has the same gap (line 577).closedand the sidecar'sMergedflag is set (internal/pulls/merge.gostep 6, "merged event (state → closed …)"), so today a merged PR happily acceptsPOST/DELETEonreview-requests.json, mutating the CAS'd current-state index and emittingreview_requestednotifications for a PR that can never be reviewed again.UI — role-gated only.
web/src/pages/Pull.jsx:canReview = () => roleAtLeast(role(), "write")(line 1061) is the only gate; the reviewers panel is rendered withcanEdit={canReview()}(line 1415) regardless of PR state, so the "request a reviewer…" input stays live on merged/closed PRs.<Show when={thread()?.state === "open" || pr()?.merged}>.Spec note:
docs/features/04_code_review.md§5 ("Review requests") specifies auth and dedup rules but is silent on PR lifecycle state — this ticket adds the rule rather than amending a stated one.Architecture notes
AddRequests/RemoveRequestsright after theprHeadOfcall:if h.State != StateOpen || side.Merged → 422 ErrUnprocessable("review requests are only accepted on open pull requests"), consistent with how the review surface words other 422s.GETstays allowed (history is still viewable).selfOnlybranch, threads.go:597) is also blocked — recommend yes, uniformly.<Show>pattern in the same file.Acceptance criteria
POST …/review-requestson a closed PR returns 422 (message names the reason); on a merged PR likewise.DELETE …/review-requestson a closed/merged PR returns 422, including the self-removal path (per the decision noted above).GET …/review-requestsstill works on closed/merged PRs.review-requests.jsonshape or the notify event classes for open PRs.Fixed by #607 (merged): AddRequests/RemoveRequests refuse 422 on closed/merged PRs (incl. uniform self-removal) via the shared threadLocked predicate — no new reads, before summary/notify; GET stays open. Picker gated on live lock (chips stay visible); spec §5 rule added. Verified: review 96.0% cover, -race green, 1538 web unit green (smoke excluded, pre-existing), vite/esbuild green, independent review APPROVE.