- Bind review decision state to in-process session (pid + profile lock); drop /tmp file path.
- Fail closed on review_pr.py CLI; route live reviews through gated MCP tools only.
- Require operator_authorized on review correction; allow re-mark after correction.
- Validate remote/org/repo on mark and submit; wire review mutation proof into build_final_report.
- Add security regression tests for spoofed locks, correction flow, and CLI bypass.
Refs #211
Addresses the sysadmin REQUEST_CHANGES on PR #203 (reviewed head
10d2644790):
1. Lock redesigned; /tmp file removed entirely. The mutation authority is
now an in-process record (_MUTATION_AUTHORITY) plus an environment
session lock (GITEA_SESSION_PROFILE_LOCK) exported at server launch:
- in-process record cannot be spoofed by other local processes, cannot
go stale across sessions, and cannot race concurrent agents;
- the env lock is inherited by child CLI processes, so review_pr.py can
refuse an ad-hoc GITEA_MCP_PROFILE role escalation without any shared
file; a missing env lock (direct operator CLI use) stays allowed;
- silent except-pass writes are gone; an unresolvable profile fails
closed.
2. Standard reviewer workflow unbroken: verify_mutation_authority seeds
itself from the live config-resolved context at the first mutation gate
(approved preflight path whoami -> eligibility -> review/merge), and now
runs as the final gate after eligibility, reusing the identity that
eligibility proved (no extra /user call).
3. Trailing whitespace removed from review_pr.py (git diff --check clean).
4. Module-global verify_mutation_authority no-op bypass removed from
tests/test_mcp_server.py; replaced with a tests/conftest.py autouse
fixture that only resets per-process state (_MUTATION_AUTHORITY,
_IDENTITY_CACHE, session lock env) between tests — the gate itself
stays live in every test.
5. Tests rewritten for the new design: seeding on first verify, unresolved
profile fails closed, remote/profile/identity mismatches fail closed,
session-lock env mismatch rejected, foreign-pid authority reseeded,
unauthorized author->reviewer pivot blocked, authorized pivot allowed;
CLI: mismatch blocked, match allowed, no-lock allowed.
6. Rebased onto current master (c6fd0fd).
Closes#199
Refs #194
Co-Authored-By: Claude Fable 5 <[email protected]>
Stale documentation only — no behavior change. The module docstring and the
--merge / --merge-method argparse help text no longer advertise a working CLI
merge. They now state CLI merge is disabled/fail-closed and that merge is
handled solely by the gated gitea_merge_pr MCP workflow (#16).
CLI merge remains disabled: --merge still fails closed with no API call, and
review_pr.py contains no /merge call. No MCP merge gate was changed.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Reviewer found the MCP merge surface is gated but two local CLI scripts remain
ungated merge paths that LLM automations in this project have been using.
Close them (Option B — minimal safe fix; full gated CLI merge left to a
follow-up):
- review_pr.py: `--merge` now fails closed BEFORE any API call with a clear
message directing callers to the gated `gitea_merge_pr` MCP workflow. The
review-only path is unchanged. The merge execution block was removed.
- merge_pr.py: main() is now a fail-closed no-op — reads no credentials and
makes no merge API call; prints that merge is only available via the gated
workflow.
- README: the `review_pr.py` row and Quick Examples no longer advertise a CLI
`--merge` path; added an audit-logging clarification that #16 returns
structured gate/merge results but does not add durable audit logging, which
is tracked by #18.
Tests updated/added:
- test_review_pr.py: `--merge` fails closed with no API call; message points to
the gated workflow.
- test_merge_pr.py: merge fails closed with no API call, even with
--force/--do/--title/--message; message points to the gated workflow.
- test_mcp_server.py: README no longer advertises the ungated CLI merge example.
The gated MCP `gitea_merge_pr` is unchanged and still gated; `gitea_review_pr`
still fails closed on merge=True; `gitea_submit_pr_review` still cannot merge.
No secrets, auth headers, raw env, or credential paths are exposed. No
Jenkins/Ops/GlitchTip/Release/deploy/CI behavior added. #17/#18 not started.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>