Flow
Each rollout step and the test that backs it
1Intercept narrowly
Pull request creation, API calls, other repos and non-main merges reach the real tool with the exact same arguments.
2Resolve, then classify
A link that resolves to the protected repo gets queued, even when a flag names another repo.
3Pin the head
A push between the lookup and the submit makes the submit fail.
4Refuse unsupported options
Each refused option causes no write and says nothing was submitted.
5Atomic intake
Many processes at once produce one record and the same answer.
6Safe install
An unmanaged wrapper stops the installer before it writes any file.
Plain merging skipped the merge queue I built for the ordering system. The queue tests the exact result of each change on top of current main before it publishes anything. The one-line merge command just told the hosting service to merge right now. It was still the fastest way in.
What gets caught and what passes through
I put a wrapper with the same name in front of the real command-line tool. Almost everything goes straight through: reads, new pull requests, pushes, other repos, merges into other branches. If you do this, write a test for each of those that checks the real tool got the exact same arguments. Only a plain merge into my main branch gets caught.
Ask the tool which pull request it is
Don't decide from the flags. They come in too many spellings and orders, and a link can point at a different repo than the flag says. My wrapper asks the real tool, read-only, which pull request this is and where it's going. If it isn't my main branch, the command runs as typed.
Which merge options get refused
Allow a short list of options and refuse the rest, even ones you've never seen. Mine allows plain merge, auto-merge, and an expected commit. Squash, rebase, admin bypass, custom messages, and branch deletion get refused, and nothing gets submitted. Then pin the exact commit you looked at and send it with the request, so a push in between makes it fail.
A help flag inside the message
My first version had a hole. It looked for a help flag anywhere, including inside the text of a message. A merge whose message was just a help flag looked harmless, so it would have gone straight to the real tool, and I'm fairly sure that would have merged it. The follow-up changes what counts as a help flag.
Values are skipped without being read, and a help flag only counts if it comes before the end-of-options marker.
A new test puts help text in the message and expects a refusal. None of my earlier tests had put help-shaped text inside a value.
Writing requests through a hard link
Write the request to a temp file, flush it, then hard-link it to its final name. Only one writer can win. Everyone else reads the winner's record, even if it says blocked. My old version wrote the final file directly, so a reader could see half a file and a blocked request looked new.
An installer that won't clobber
A timer wakes the queue every few seconds, and an idle queue does nothing. The installer checks every file before writing any, refuses to replace a wrapper it didn't create, and copies everything outside my working folders. Its status check flags drift.
Good faith, one machine
This only stops people acting in good faith on one machine. A full path, an alias, or a raw API call gets around it, and it moves no credentials. If you copy this, pair it with branch protection on the server. I haven't set that up yet.