Main Branch Protection Policy¶
This document defines the required branch protection baseline for the main branch and enforcement procedures.
Objective¶
Establish a consistent, auditable baseline for main branch protection that prevents accidental or unauthorized changes, requires code review, and ensures all changes pass required checks before merge.
Baseline Controls¶
1. Required Pull Request Reviews¶
- Minimum reviewers: per active governance profile baseline (max required approvals across risk tiers in
.github/governance/policy-packs.json;solo-dev= 0,team-dev= 1,regulated-team= 2) - Dismissal of stale reviews: Enabled
- Require code owner reviews: Disabled (repo has no CODEOWNERS enforcement requirement)
- Restrict who can dismiss reviews: Admins only
- Apply to admins: Yes
2. Required Status Checks Before Merge¶
The following status checks must pass before a pull request can be merged to main:
| Check | Description | Purpose |
|---|---|---|
lint-and-validate |
Linting and repository validation | Catch lint errors and enforce repo standards |
test |
Test suite | Catch regressions and quality issues |
validate-commit-messages |
Commit message format validation | Enforce conventional commits |
validate-unix |
Unix-environment validation | Ensure cross-platform compatibility |
validate-windows |
Windows-environment validation | Ensure Windows compatibility |
release-label-gate |
Release label gate | Require release label for delivery tracking |
Additional checks may run and fail without blocking merge (advisory-only checks), but the
above six are required for all PRs to main.
Repositories enabling solo-dev self-merge must additionally require the
BaseCoat merge eligibility commit status. They must not require an
independent PR approval after the last push through size:XL, and they must
leave require_extra_approval_for_unattributed_changes off so Copilot-authored
commits do not sit in GitHub Review required. The repo-local eligibility status
is a fail-closed policy and check aggregator, not an executor-specific identity.
See docs/guides/solo-dev-profile.md.
3. Restricted Direct Pushes¶
- Allow force pushes: No
- Allow deletions: No
- Require branches to be up to date before merging: Yes
- Require status checks to pass on up-to-date branches: Yes
4. Bypass Rules¶
- Admins can bypass protection: No for normal delivery; include administrators in classic protection or keep the ruleset bypass list empty
- GitHub Apps bypass: Not allowed
- Automation bypass: Not allowed (all automation must work within protection constraints)
The solo-dev profile changes approval counts, not bypass posture. Its
workflow-based self-merge path must use GitHub auto-merge after required checks;
it must never use administrator bypass.
Enforcement¶
Automated Enforcement¶
The governance-enforce workflow (triggered on main branch changes to this file or related governance docs) validates that:
- This policy document exists and is current
- Repository API confirms branch protection is active
- All baseline controls are enforced via
gh apior Terraform
Manual Enforcement (Repository Settings)¶
To apply branch protection via GitHub UI:
- Navigate to Settings > Branches
- Click Add rule under Branch protection rules
- Pattern:
main - Enable:
- ✓ Require a pull request before merging
- ✓ Require approvals (0 for
solo-dev, 1 forteam-dev, 2 forregulated-team— see.github/governance/policy-packs.json) - ✓ Dismiss stale pull request approvals when new commits are pushed
- ✓ Require status checks to pass before merging
- ✓ Require branches to be up to date before merging
- Search for and select required status checks:
validate-basecoatcidocs- Restrict who can push to matching branches:
- [ ] No one (if all changes must go through PR)
- Or [ ] Specify teams/individuals allowed to push directly
- Disable:
- ☐ Allow force pushes
- ☐ Allow deletions
- Include administrators and leave bypass actors empty.
Validation¶
Audit Evidence¶
The governance-audit workflow queries the repository API to confirm:
Expected payload shape:
required_status_checks.strict === truerequired_status_checks.contextsincludes at leastlint-and-validate,test,validate-commit-messages,validate-unix,validate-windows,release-label-gateallow_force_pushes.enabled === falseallow_deletions.enabled === falseenforce_admins.enabled === true
Remediation¶
If validation fails:
- Missing protection rules: Re-apply via Settings UI or run
branch-protection-enforce.ymlmanually - Incomplete status checks: Update workflow triggers in
.github/workflows/*to ensure all required checks run - Admin bypass enabled: Review and disable if not permitted by security policy
References¶
- GitHub Branch Protection API
- Repository Settings
- Governance Contract:
docs/reference/governance-contract.md - Governance Audit:
.github/workflows/governance-audit.yml - Solo-dev setup:
docs/guides/solo-dev-profile.md