Skip to content

Protect default branches and standardize organization merge governance #22

Description

@szmyty

Why

A 2026-09-02 fleet audit observed:

  • 29 of 29 main branches are unprotected.
  • The organization has no repository rulesets.
  • All 29 repositories allow merge commits, squash merges, and rebase merges.
  • Auto-merge is disabled and merged branches are not deleted automatically.
  • Commit, release, security, and quality workflows therefore cannot yet act as reliable organization gates.

This is the largest confirmed enforcement gap in the current architecture.

Existing implementation to recover

A tested implementation already exists at empathy/mantle/bin/ghprotect, with Bats coverage under empathy/mantle/tests/bin/ghprotect.bats.

Version 3.0.0 already provides useful safety properties:

  • Preview/dry-run is the default.
  • --execute and typed confirmation gate mutations.
  • It targets ~DEFAULT_BRANCH, so default-branch renames remain covered.
  • It creates or updates one exactly named managed ruleset.
  • It refuses ambiguous duplicate rulesets.
  • It prevents deletion and non-fast-forward pushes and requires linear history.

The current implementation is intentionally incomplete for fleet rollout:

  • bypass_actors is empty.
  • It does not yet require pull requests, reviews, conversations, or status checks.
  • It operates one repository at a time.
  • It remains inside Empathy's historical Mantle staging copy rather than the canonical Mantle repository.

This work should preserve and graduate the implementation, not rewrite it from scratch.

Scope

Canonical policy and rollout

  • Define an organization ruleset strategy with explicit public/private and repository-class exceptions.
  • Prefer a centrally managed organization ruleset targeting eligible repositories when the GitHub plan/API supports it.
  • Provide a Pace-managed repository-ruleset fallback using the same desired-state contract when organization rulesets are unavailable or insufficient.
  • Decide the preferred merge method(s) in coordination with the canonical change-history contract.
  • Protect default branches from direct pushes, force pushes, and deletion.
  • Require pull requests, conversation resolution, and selected stable checks.
  • Decide review requirements without blocking the current single-maintainer workflow unnecessarily.
  • Roll out required checks only after each check is stable and available to the target repository.
  • Decide auto-merge and delete-head-branch defaults.
  • Pilot before organization-wide enforcement and publish a rollback plan.

Trusted automation and Copilot

Automation must be able to contribute and merge without receiving a blanket escape from governance.

  • Inventory the exact GitHub Apps/integration IDs used by Copilot coding agent, ChatGPT/Codex, Dependabot, release automation, Pages/deployment automation, and any other approved bots.
  • Prefer normal pull requests, required checks, and auto/agent merge whenever the actor can satisfy the rules.
  • When bypass is genuinely required, grant it to the specific GitHub App/integration rather than a broad write/admin role.
  • Prefer ruleset bypass_mode: pull_request so the actor must still open a pull request and leaves a pull-request/audit trail.
  • Add GitHub Copilot as an explicit bypass actor where its cloud agent is incompatible with a selected rule, while preserving its ability to update and merge its pull requests.
  • Include Dependabot and approved release/deployment apps only where their tested workflows require bypass.
  • Avoid bypass_mode: exempt unless a documented constraint makes it necessary, because exempt actors do not produce a ruleset bypass audit entry.
  • Do not allow trusted bots to push arbitrary unreviewed changes directly to main merely for convenience.
  • Define a machine-readable actor matrix: actor/app ID, repositories, allowed operation, bypass mode, justification, owner, expiry/review date, and test evidence.
  • Test bot and Copilot behavior in the pilot before activating enforcement for the fleet.

Tool ownership

  • Graduate ghprotect and its tests from Empathy into canonical Mantle, preserving useful behavior and provenance.
  • Extend ghprotect to consume the canonical ruleset and trusted-actor profile rather than hard-coding organization policy.
  • Keep preview, plan, apply, verify, and rollback behavior idempotent.
  • Let Hygiene own the policy, Mantle own the local CLI, Pace own fleet convergence, Relay own CI verification, and Observatory own adoption/drift reporting.
  • Coordinate the graduation with Empathy#79.

Acceptance criteria

  • Current branch, merge, ruleset, and automation-actor settings are captured as an immutable baseline.
  • GitHub plan/API capability detection chooses organization-level or per-repository materialization explicitly.
  • One canonical desired-state ruleset/profile exists with documented repository exceptions.
  • ghprotect and its Bats tests are preserved and graduated to canonical Mantle.
  • The tool can preview, apply, verify, update, and roll back the desired state idempotently.
  • Pull requests, selected stable checks, conversation resolution, deletion protection, and force-push protection are configured.
  • Required checks have stable names and are present before enforcement.
  • The actor matrix covers Copilot, ChatGPT/Codex, Dependabot, releases, Pages/deployments, and every other approved bot.
  • Copilot and approved bots can create/update pull requests and merge through a tested, auditable path.
  • App-specific pull_request bypass is used instead of broad role bypass wherever GitHub supports it.
  • Administrator/break-glass bypass is least-privilege, documented, and auditable.
  • Merge-method policy preserves the canonical final commit format.
  • Pilot repositories prove contributor, bot, release, deployment, and emergency paths.
  • The rollout is staged, observable, and reversible.
  • Observatory can report ruleset adoption, exceptions, bypass use, and drift.

Dependencies

  • Hygiene#37 — canonical commit/change-history contract
  • Relay#56 — reusable commit and PR-title checks
  • Relay#5 — repository structure validation
  • Pace#2 — dry-run fleet upgrades
  • Pace#20 — staged EgoLint rollout
  • Empathy#79 — graduate historical incubations

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions