feat(mcp): refuse owner_repo= forge writes to a populated repo outside the session's scope #616

Merged
hexajon merged 1 commit from issue-418-forge-write-guard into main 2026-09-24 14:49:04 +00:00
Owner

Summary

This builds the ADR 0019 amendment of 2026-09-08. A content write through owner_repo= to a repo outside the session's scope now reads the forge repo first. An empty repo is allowed. A populated repo is refused, with no override, and the refusal names the remedy: clone, change in a worktree, and madt_finish, or use the CLI. A failed read refuses too.

ADR 0043 records the scope: the launch repo and the child clones of the launch directory are in scope, so owner_repo= naming one of them behaves like omitting it.

Guarded: madt_files create, update, delete, and batch, and madt_branches_remote create. madt_commit has no owner_repo=, and madt_api_call stays a documented gap, as the amendment says. Both tool descriptions state the refusal.

Tests cover the decision table (in-scope and omitted owner_repo= make no forge read), each guarded handler (it refuses before it uses the service, and the test fails with a guard removed), and the scope scan against a temp workspace with a child clone and a symlinked child.

Closes #418

Closes #418

## Summary This builds the ADR 0019 amendment of 2026-09-08. A content write through `owner_repo=` to a repo outside the session's scope now reads the forge repo first. An empty repo is allowed. A populated repo is refused, with no override, and the refusal names the remedy: clone, change in a worktree, and `madt_finish`, or use the CLI. A failed read refuses too. ADR 0043 records the scope: the launch repo and the child clones of the launch directory are in scope, so `owner_repo=` naming one of them behaves like omitting it. Guarded: `madt_files` create, update, delete, and batch, and `madt_branches_remote` create. `madt_commit` has no `owner_repo=`, and `madt_api_call` stays a documented gap, as the amendment says. Both tool descriptions state the refusal. Tests cover the decision table (in-scope and omitted `owner_repo=` make no forge read), each guarded handler (it refuses before it uses the service, and the test fails with a guard removed), and the scope scan against a temp workspace with a child clone and a symlinked child. Closes #418 Closes #418
feat(mcp): refuse owner_repo= forge writes to a populated repo outside the session's scope
All checks were successful
ci / mcp-conformance (pull_request) Successful in 2m15s
drift / govulncheck (pull_request) Has been skipped
drift / surface-diff (pull_request) Successful in 38s
drift / forgejo-smoke (pull_request) Has been skipped
ci / mcp-conformance (push) Successful in 1s
drift / govulncheck (push) Has been skipped
drift / surface-diff (push) Successful in -7s
drift / forgejo-smoke (push) Has been skipped
ci / gate (push) Successful in 15m24s
ci / gate (pull_request) Successful in 27m13s
bccf0c2ba3
Closes #418
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sixfold-space/madtea!616
No description provided.