Repository navigation
🔒 [security] approval: bind human sign-off to reviewed code - #23
Conversation
- Verify trusted request and human reply for the current PR head and steps. - Refresh stale blocked requests without treating them as approved. - Pass 34 offline safety suites and independent review.
EricTechPro
left a comment
There was a problem hiding this comment.
Author explanations in the selected Purpose / What changed / Why it matters format: one overview for each changed file, plus notes beside critical approval logic. These explain the implementation; they are not an independent approval and do not replace tests.
| if request is None or any(request.get(k) != v for k, v in expected.items()): | ||
| return hold("the latest request does not cover the current code and human steps") | ||
| if timestamp(request_comment.get("updated_at")) != latest_time: | ||
| return hold("approval request was edited; post a fresh request") |
There was a problem hiding this comment.
Author explanation
Purpose
Make sure the human answered the current request.
What changed
The request must match the current code and required steps. An edited request is rejected too.
Why it matters
The question cannot be changed after the human has already answered it.
| for comment in comments: | ||
| if (not comment.get("id") or not DONE.fullmatch(comment.get("body") or "") | ||
| or comment.get("source") != request_comment.get("source")): | ||
| continue | ||
| created = timestamp(comment.get("created_at")) | ||
| if created <= latest_time or timestamp(comment.get("updated_at")) != created: | ||
| continue | ||
| author = comment.get("user") or {} | ||
| if (author.get("type") == "User" and author.get("login") | ||
| and permission(author["login"]) in ("write", "maintain", "admin")): | ||
| return {"approved": True, "why": "trusted human confirmed the current request", | ||
| "request": request, "requestId": request_comment.get("id"), | ||
| "approvalId": comment.get("id"), "approver": author["login"]} |
There was a problem hiding this comment.
Author explanation
Purpose
Accept a valid answer from someone allowed to approve.
What changed
Check write access or higher, reply time and the same issue or PR discussion. Ignore edited replies and GitHub bot accounts.
Why it matters
An outsider’s reply or an old done must not unlock the merge. An AI using a person’s GitHub account remains indistinguishable from that person.
| APPROVED=false | ||
| approval_check() { | ||
| APPROVAL=$(python3 "$HERE/super-board-approval.py" --repo "$REPO" --pr "$PR" \ | ||
| --head "$HEAD_SHA" --plan "$PLAN") || APPROVAL='{"approved":false}' | ||
| APPROVED=$(echo "$APPROVAL" | jq -r '.approved // false') | ||
| } |
There was a problem hiding this comment.
Author explanation
Purpose
Ask whether this code and its required human steps are approved.
What changed
Call the approval checker instead of trusting the label. A failed checker call leaves approval false.
Why it matters
The merge needs a verified human answer, not just a status label.
| if [ -n "$HUMAN" ] && [ "$APPROVED" != true ]; then | ||
| echo "$HUMAN" | ||
| say "merge policy: a human merges this PR"; exit 7 | ||
| echo "$PLAN" | jq -r '.needs_you[] | "needs-you: " + .' | ||
| approval_request | ||
| say "merge policy: waiting for a trusted human to approve this exact head"; exit 7 |
There was a problem hiding this comment.
Author explanation
Purpose
Hold a change that still needs human approval.
What changed
Print the request for the current change and stop when that approval is missing.
Why it matters
Asking for permission never grants permission to merge.
| gh pr view "$PR" ${REPO:+--repo "$REPO"} --json labels,files,additions,deletions,body > "$META" 2>/dev/null || echo '{}' > "$META" | ||
| PLAN=$(python3 "$HERE/super-board-merge-policy.py" --config "$CONFIG" --meta "$META" --diff "$DIFF") || { | ||
| say "human approval scope could not be refreshed"; exit 7; } | ||
| approval_check | ||
| if [ "$APPROVED" != true ]; then | ||
| approval_request | ||
| say "human approval changed during verification; keep the card Blocked" | ||
| if [ -n "$HUMAN" ]; then exit 7; else exit 8; fi |
There was a problem hiding this comment.
Author explanation
Purpose
Check that approval is still valid after verification runs.
What changed
Read the current PR details again, recalculate the required human steps, and recheck the reply just before merging.
Why it matters
A new requirement or request can arrive while tests run. The earlier check must not silently cover it. This is a final snapshot; GitHub does not lock comments afterward.
There was a problem hiding this comment.
Author explanation
Purpose
Guide the reviewer through the final merge decision.
What changed
Require a verified reply to the current request, then rerun the merge checks. Tell the reviewer to link to one request instead of duplicating it.
Why it matters
The reviewer cannot use an old status label to skip the human decision, even when a task has returned to Review.
There was a problem hiding this comment.
Author explanation
Purpose
Check how task dependencies and human waiting states are reported.
What changed
Change the saved-data checks so a bare done comment or done label must leave approval unconfirmed.
Why it matters
These tests catch the old shortcut returning through the dependency reader. Live approval checking has its own tests.
There was a problem hiding this comment.
Author explanation
Purpose
Exercise the final merge checks with simulated GitHub responses.
What changed
Cover a valid current reply, stale replies, unreadable permissions, and new requests or human steps appearing while checks run.
Why it matters
The tests check that an invalid approval stops before the merge command, including when the approval becomes outdated during verification.
There was a problem hiding this comment.
Author explanation
Purpose
Check where the planner sends board tasks.
What changed
Add a case where code changes while its task is Blocked: it must enter the fresh-approval list and stay out of approved resume and ordinary work lists.
Why it matters
This protects the recovery path: asking again must not become permission to build or merge.
There was a problem hiding this comment.
Author explanation
Purpose
Test the new approval checker without changing a live board or database.
What changed
Cover who may approve, which code and steps were approved, edited or old replies, repeated checks, multiple pages of comments, and planner integration.
Why it matters
The tests check both sides: changed or untrusted answers must be rejected, while a valid answer for unchanged work must continue to count.
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
You approve the AI’s fix. The AI then changes the code. Super Board now waits for a fresh approval before merging.
Previously, an old approval could still let the changed code merge, even though you had never approved that version.
What changes
done, but it must answer the current approval request.Changed code returns for review and a fresh request. Asking again does not grant permission to merge.
Checked
All 34 offline safety test suites passed, including changed-code approval and blocked-task recovery. All eight GitHub checks passed. Independent review found no remaining issues to fix. No live board, worker, or database was used for these tests.
Existing blocked tasks need one fresh approval request and human reply.
Limits
GitHub cannot tell you apart from an AI using your GitHub account. The AI must never write your
donereply.The code is checked at merge time. Approval comments are checked just before that, but GitHub does not lock them against a last-second edit.
Merging manually on GitHub is unchanged.