f04cf44975
Replace the ungated gitea_merge_pr with a gated merge workflow. This is now
the only merge path the MCP server exposes; the merge API is called only
after every safety gate passes.
Gates (fail-closed at each step):
1. Merge method is merge | squash | rebase.
2. Explicit confirmation: confirmation must equal "MERGE PR <n>" (without it,
zero API calls are made).
3. Reuse gitea_check_pr_eligibility (#14) with action 'merge': proves the
authenticated identity, the active profile (and that it allows merge), the
PR author, blocks self-merge, requires the PR open, and fails closed when
the PR is not mergeable or mergeability is unknown.
4. Optional expected_head_sha: refuse if the PR head moved.
5. Optional expected_changed_files: refuse if the PR's changed file set differs.
6. Redundant self-merge block (auth user == PR author).
The force/ignore-checks option was removed — Gitea's own mergeable signal
(which reflects branch-protection required reviews/checks) must be positive,
so required approval/check state is honoured, never bypassed.
Output reports performed, authenticated user, profile name, PR author, PR
number, head SHA checked, merge method, gates passed/blocked, and merge
result / merge commit — never a token, auth header, or credential. Error text
is scrubbed via _redact.
Surface audit: no ungated merge path remains. The /merge endpoint appears only
inside gitea_merge_pr; gitea_review_pr fails closed on merge=True before any
API call; gitea_submit_pr_review has no merge parameter and 'merge' is not a
reviewable action. Tests assert all three.
Tests cover: merge succeeds only when all gates pass; self-author blocked;
unknown identity/profile blocked; profile without merge permission blocked;
missing/wrong confirmation blocked (no API call); head-SHA mismatch blocked;
changed-files mismatch blocked; closed PR blocked; non-mergeable blocked;
unknown mergeability fail-closed; no merge call when gates fail; invalid merge
method rejected; output and error redaction; and the no-ungated-merge-path audit.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>