From c88a3330cf6b2085f6c506e4facbfd9f08211ecf Mon Sep 17 00:00:00 2001 From: wshallwshall Date: Tue, 28 Jul 2026 18:46:51 -0500 Subject: [PATCH] =?UTF-8?q?docs:=20enforce=5Fadmins=20is=20now=20TRUE=20?= =?UTF-8?q?=E2=80=94=20the=20push=20guard's=20notes=20said=20the=20opposit?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `enforce_admins` was enabled on MEFORORG/MessageFoundry main on 2026-07-28 (verified from the protection endpoint, not the write response). A direct push to `main` is now refused SERVER-SIDE and `gh pr merge --admin` no longer works. push_guard.py's header and its refusal message both stated the opposite -- "enforce_admins is false, so the owner bypasses it. Nothing else would have stopped this." That was accurate when written and is now exactly backwards, and it is the kind of claim someone reads while deciding whether the hook still matters. WHY THE HOOK STAYS. It is defence-in-depth now rather than the only guard, and it still earns its place: it fails FAST and LOCALLY with an explanation instead of after a round-trip, and it covers `cla-signatures`, which branch protection does not. The header also records why the reasoning INVERTED, because that is the reusable part. It used to argue `enforce_admins=true` was deliberately deferred: an intermittent harness-monitor failure was blocking consecutive PRs, and removing the admin override while a flake can strand a merge trades an accidental-push risk for a cannot-ship risk. That failure was a LIVELOCK, not a flake -- so the premise dissolved rather than the trade-off being re-argued. The cannot-ship risk is real and now accepted, with the revert command in the note. COMMENTS ONLY -- no logic touched. Verified: 8 tests pass, and the guard still exits 1 on a push to `main` and 0 on a feature branch. (Read those exit codes WITHOUT a pipe: my first check piped stdout to Select-String and reported exit 0 for a push it had just REFUSED -- the same "exit code read through a pipe belongs to the pipe" trap already recorded for the leak scanner.) --- scripts/hooks/push_guard.py | 37 +++++++++++++++++++++++-------------- tests/test_push_guard.py | 9 ++++++--- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/scripts/hooks/push_guard.py b/scripts/hooks/push_guard.py index d2b15987..b12ba5d7 100644 --- a/scripts/hooks/push_guard.py +++ b/scripts/hooks/push_guard.py @@ -6,23 +6,31 @@ publication, immediately and irreversibly (deleting a ref later does not un-publish content that was fetched, mirrored or indexed in between). -Branch protection on the server requires a PR and 12 status checks -- but ``enforce_admins`` is false, -so the repository owner BYPASSES all of it. The realistic trigger is not malice, it is one click: -VS Code's Sync/Push button does not distinguish "my feature branch" from "main", and the editor is -where most pushes originate. +Branch protection on the server requires a PR and 12 status checks. ``enforce_admins`` is now TRUE +(enabled 2026-07-28), so a direct push to ``main`` is refused server-side and ``gh pr merge --admin`` +no longer works. This hook is therefore DEFENCE-IN-DEPTH rather than the only guard -- it still earns +its place by failing FAST and LOCALLY, with an explanation, instead of after a round-trip; and it +covers ``cla-signatures``, which branch protection does not. + +The realistic trigger was never malice, it is one click: VS Code's Sync/Push button does not +distinguish "my feature branch" from "main", and the editor is where most pushes originate. This is the guard the old mirror clone's Gate-Provenance pre-push hook used to provide. That clone was quarantined at cutover, and nothing replaced it. WHAT THIS IS NOT. A guardrail, not a security boundary: ``git push --no-verify`` skips it, and it is -local-only, so a different machine is unprotected. It removes the ACCIDENT, not the capability. The -durable server-side fix is ``enforce_admins=true``, which was deliberately NOT enabled while an -intermittent harness-monitor failure was blocking consecutive PRs -- removing the admin override while -a flake can strand a merge trades an accidental-push risk for a cannot-ship risk. That failure turned -out to be a livelock in ``MessagesPanel._apply`` rather than a flake, and is fixed -(``tests/test_console_messages_refresh.py``), so the argument against ``enforce_admins`` is weaker now -than when this was written. (An earlier revision of this note cited "BACKLOG #17" for it; that is the -py3.11 pytest/aiosqlite deadlock, OBSOLETE and unrelated.) +local-only, so a different machine relies on the server-side rule alone. + +HISTORY, because the reasoning inverted. This note used to say ``enforce_admins=true`` was deliberately +NOT enabled, because an intermittent harness-monitor failure was blocking consecutive PRs and removing +the admin override while a flake can strand a merge trades an accidental-push risk for a cannot-ship +risk. That failure turned out to be a LIVELOCK in ``MessagesPanel._apply``, not a flake +(``tests/test_console_messages_refresh.py``), so the premise dissolved and the setting was flipped. The +cannot-ship risk is real but now accepted: a required check that goes permanently red blocks every +merge until it is fixed or protection is relaxed -- +``gh api -X DELETE repos/MEFORORG/MessageFoundry/branches/main/protection/enforce_admins``. +(An earlier revision cited "BACKLOG #17" for the failure; that is the py3.11 pytest/aiosqlite deadlock, +OBSOLETE and unrelated.) Stdlib only, like the other gates -- most worktrees have no project .venv. @@ -71,8 +79,9 @@ def main(argv: list[str]) -> int: print("", file=sys.stderr) print( " This repo IS the published artifact — a push to main is publication, immediately, and\n" - " cannot be taken back. Server-side branch protection requires a PR and 12 checks, but\n" - " enforce_admins is false, so the owner bypasses it. Nothing else would have stopped this.\n" + " cannot be taken back. Branch protection would refuse this server-side too (a PR + 12\n" + " checks, enforce_admins ON); this hook just tells you now, locally, instead of after a\n" + " round-trip — and it also covers cla-signatures, which protection does not.\n" "\n" " Push a branch and open a PR instead:\n" " git switch -c && git push -u origin \n" diff --git a/tests/test_push_guard.py b/tests/test_push_guard.py index 6a3f2543..b628b084 100644 --- a/tests/test_push_guard.py +++ b/tests/test_push_guard.py @@ -2,9 +2,12 @@ Since the MEFORORG cutover this repository IS the published artifact — a push to ``main`` is publication, immediately, with no publish step left to catch anything. Server-side branch protection -requires a PR and 12 status checks, but ``enforce_admins`` is false, so the repository owner bypasses -all of it. The realistic trigger is one click on VS Code's Sync button while the current branch happens -to be ``main``. +requires a PR and 12 status checks, and since 2026-07-28 ``enforce_admins`` is TRUE, so the owner no +longer bypasses it either. This hook is now defence-in-depth: it fails FAST and LOCALLY with an +explanation rather than after a round-trip, and it covers ``cla-signatures``, which branch protection +does not. (It was written while ``enforce_admins`` was false and the hook WAS the only guard.) The +realistic trigger is unchanged: one click on VS Code's Sync button while the current branch happens to +be ``main``. Every test feeds the script the EXACT stdin contract git uses for a pre-push hook — `` ``, one line per ref — so what is asserted is the