Skip to content

Branch Protection Baseline (GitHub Team — Repository Rulesets)

Review-first guide. This document describes the live branch protection configuration on BookingZone repos using GitHub repository rulesets (not classic branch protection). Do not modify rulesets without owner approval.

Last verified: 2026-09-25


Overview

BookingZone uses GitHub Team, which supports repository-level rulesets but not organization-level rulesets (requires GitHub Enterprise). Protection is applied per-repo via a single ruleset named bz-protect-canonical.


Ruleset: bz-protect-canonical

Status: Active on all target repos.

Protected refs by repo

Repo Refs
reservation-api-server main, develop, release/**
admin-web-app main, develop, release/**
venuplus-app main, develop, release/**
customer-web-app main, develop, release/**
bz-platform-context main
reservation-browser-tests main

Release ref pattern: Repos currently use release/YYYY.MM.DD.N (e.g., release/2026.09.24.1). ADR-0007 prefers semver release/x.y.z. The ruleset uses release/** to accommodate both patterns — the naming gap should be addressed in a future standardization effort, not silently changed here.

Rules enforced (all repos)

Rule Setting
Deletion Blocked
Non-fast-forward (force push) Blocked
Required linear history Yes
Pull request required Yes
Required approvals 0 (solo merges allowed; raise later)
Dismiss stale reviews Yes
Require conversation resolution Yes
Allowed merge methods Squash only
Bypass actors RepositoryRole: Admin (actor_id 5, always)

Required status checks

Status checks use strict=false and do_not_enforce_on_create=true.

Repo Required checks
reservation-api-server branch-name / check-branch-name, discipline / spec-discipline
admin-web-app branch-name / check-branch-name, discipline / spec-discipline
customer-web-app branch-name / check-branch-name, discipline / spec-discipline
venuplus-app branch-name / check-branch-name, discipline / spec-discipline
bz-platform-context branch-name / check-branch-name
reservation-browser-tests None (no process-guard callers yet)

Repository merge settings

Applied to all six repos:

{
  "allow_squash_merge": true,
  "allow_merge_commit": false,
  "allow_rebase_merge": false,
  "delete_branch_on_merge": true,
  "allow_auto_merge": true,
  "squash_merge_commit_title": "PR_TITLE",
  "squash_merge_commit_message": "PR_BODY"
}

Disabled legacy rulesets

Repo Ruleset name ID Status
customer-web-app Main Branch 3684145 Disabled
reservation-api-server develop-rule 16825918 Disabled

What is NOT applied (and why)

Feature Reason
Organization rulesets Requires GitHub Enterprise + admin:org scope. aerospace-apps is on GitHub Team.
Organization required workflows Requires GitHub Enterprise.
1 required approval Solo merges are allowed for now; raise approval requirement later when team grows.
Required Unit Tests / Ruff / verify checks Path-skips and currently red tips would lock merges. Add only after green + stable job names.

Verification commands

List all rulesets on a repo

gh api repos/aerospace-apps/<repo>/rulesets --jq '.[] | {id, name, enforcement}'

Get full ruleset details

gh api repos/aerospace-apps/<repo>/rulesets/<ruleset_id>

Check repo merge settings

gh api repos/aerospace-apps/<repo> --jq '{
  allow_squash_merge,
  allow_merge_commit,
  allow_rebase_merge,
  delete_branch_on_merge,
  allow_auto_merge,
  squash_merge_commit_title,
  squash_merge_commit_message
}'

List required status checks for a ruleset

gh api repos/aerospace-apps/<repo>/rulesets/<ruleset_id> \
  --jq '.rules[] | select(.type == "required_status_checks") | .parameters.required_status_checks'

Apply / update commands (execute only after approval)

Create a new ruleset

gh api \
  --method POST \
  -H "Accept: application/vnd.github+json" \
  repos/aerospace-apps/<repo>/rulesets \
  --input ruleset.json

Update an existing ruleset

gh api \
  --method PUT \
  -H "Accept: application/vnd.github+json" \
  repos/aerospace-apps/<repo>/rulesets/<ruleset_id> \
  --input ruleset.json

Example ruleset JSON shape (bz-protect-canonical)

{
  "name": "bz-protect-canonical",
  "target": "branch",
  "enforcement": "active",
  "conditions": {
    "ref_name": {
      "include": ["refs/heads/main", "refs/heads/develop", "refs/heads/release/**"],
      "exclude": []
    }
  },
  "rules": [
    { "type": "deletion" },
    { "type": "non_fast_forward" },
    { "type": "required_linear_history" },
    {
      "type": "pull_request",
      "parameters": {
        "required_approving_review_count": 0,
        "dismiss_stale_reviews_on_push": true,
        "require_last_push_approval": false,
        "required_review_thread_resolution": true,
        "allowed_merge_methods": ["squash"]
      }
    },
    {
      "type": "required_status_checks",
      "parameters": {
        "strict_required_status_checks_policy": false,
        "do_not_enforce_on_create": true,
        "required_status_checks": [
          { "context": "branch-name / check-branch-name" },
          { "context": "discipline / spec-discipline" }
        ]
      }
    }
  ],
  "bypass_actors": [
    {
      "actor_id": 5,
      "actor_type": "RepositoryRole",
      "bypass_mode": "always"
    }
  ]
}

Adjust conditions.ref_name.include and rules[].parameters.required_status_checks per repo as shown in the tables above.

Update repo merge settings

gh api \
  --method PATCH \
  -H "Accept: application/vnd.github+json" \
  repos/aerospace-apps/<repo> \
  -f allow_squash_merge=true \
  -f allow_merge_commit=false \
  -f allow_rebase_merge=false \
  -f delete_branch_on_merge=true \
  -f allow_auto_merge=true \
  -f squash_merge_commit_title=PR_TITLE \
  -f squash_merge_commit_message=PR_BODY

Break-glass policy

The bz-protect-canonical ruleset grants Admin bypass (actor_id: 5, bypass_mode: always). Repository admins can push directly or merge without passing checks in emergencies.

When to use

  1. Critical production incident requiring immediate hotfix.
  2. CI infrastructure is down and blocking a time-sensitive deploy.

Procedure

  1. Only repo admins may bypass.
  2. Post incident note in #engineering Slack channel immediately.
  3. Open a follow-up issue within 24 hours explaining why bypass was needed.
  4. Do not disable the ruleset — use the bypass mechanism.

Rollout checklist

When adding a new repo to this protection scheme:

  • Verify repo is on GitHub Team (not Free).
  • Create bz-protect-canonical ruleset with appropriate refs.
  • Configure required status checks (only if CI callers exist and are green).
  • Apply repo merge settings (squash-only, delete branch on merge, auto-merge).
  • Disable any legacy branch protection rules or rulesets.
  • Update this document with the new repo.
  • Add the repo to repo-registry.md if not already present.

Human + AI git best practices

Always

  • Create short-lived feature branches from origin/develop (or origin/main for docs repos).
  • Use PRs for every change.
  • Keep PRs small and scoped.
  • Use conventional commit style in PR titles (becomes squash message).
  • Keep local main/develop fast-forward only.

Never

  • Never commit directly on protected branches.
  • Never push directly to protected branches.
  • Never run plain git pull on protected branches (use --ff-only).
  • Never force-push to protected branches (ruleset blocks this anyway).

AI-specific guardrails

  • AI-authored PRs require human reviewer approval (when approvals are raised).
  • Use normal branch naming; no special AI prefix required.
  • Keep AI provenance in PR description (or co-author trailer).
  • Do not allow AI tools to bypass hooks/policies except break-glass.

Local safety defaults (developer machine)

Run once per repo:

git config --local pull.ff only
git config --local merge.ff only
git config --local fetch.prune true

Optional shared hooks (.githooks/):

  • pre-commit to block direct commits on protected branches.
  • pre-push to block direct pushes to protected branches.