Skip to content

ci(guardrails): protect the guardrails-release branch and tag name with rulesets #9531

Closed as not planned

Description

@kyle-sexton

Refs: #9504

Problem

After #9504, every consumer repository's lefthook remotes: entry fetches the guardrails git hooks from this repository's guardrails-release ref and runs them on developer machines, refetching every 24h. Only .github/workflows/release-move-guardrails-ref.yml should move that ref, but today nothing enforces it:

  • Any account or workflow token with contents: write can push, force-push or delete refs/heads/guardrails-release. The workflow's "Refuse any ref but main" step lives in a file a non-main branch can edit, so a branch workflow with a write token is enough.
  • lefthook fetches ref by its short name (git fetch --depth 1 origin -- <ref>, lefthook v2.2.2 internal/git/wrapper/fetch.go), and git resolves a short name to refs/tags/<name> before refs/heads/<name>. A tag named guardrails-release therefore replaces the branch for every consumer. A full refs/heads/... ref cannot be used, because lefthook's initial clone --branch rejects it. feat(guardrails): serve the git hooks to lefthook repositories as a remote #9504's workflow now refuses to move the branch while such a tag exists, but that only detects it at release time.
  • Deleting the branch and re-dispatching the workflow recreates it at any commit on main, including an older release.

Today the repository's rulesets cover only the default branch and refs/heads/release/plugins (gh api repos/melodic-software/claude-code-plugins/rulesets).

Proposed fix (melodic-software/github-iac)

  1. A branch ruleset on refs/heads/guardrails-release: restrict creation, update and deletion, and block non-fast-forward.
  2. A tag ruleset blocking creation of refs/tags/guardrails-release (or refs/tags/guardrails-*).
  3. A bypass for the move workflow only. Use a dedicated GitHub App whose key is in an environment limited to main, and have the workflow mint that app's token, as release-plugins does with its own Integration. Do not use the GitHub Actions app, because that would give every workflow the bypass. The workflow's GITHUB_TOKEN push then changes to the app token.

Acceptance

  • A push to, a deletion of, or a non-fast-forward of guardrails-release from any actor other than the move workflow is rejected.
  • Creating the tag guardrails-release is rejected.
  • The move workflow still creates and moves the branch.

Activity

  1. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 24, 2026
  2. github-actions commented on Oct 24, 2026

    @github-actions
    Contributor

    Proposed work class: none

    Thanks for the report. Automated triage handed this issue to a maintainer.

    Unconfirmed model suggestion: work-class: structural
    Basis: automated intake triage; a maintainer confirms or changes it.

    Automated triage. A maintainer reviews it.

  3. added
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    and removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 24, 2026
  4. kyle-sexton commented on Oct 24, 2026

    @kyle-sexton
    MemberAuthor

    Closing: the owner decided consumers track main instead of a release branch (PR #9504, commit ab4c635). guardrails-release and its move workflow are removed, and main changes only through reviewed pull requests under its existing rulesets, with the lefthook remote's end-to-end test required in PR CI. No branch or tag remains to protect.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.status: needs-decisionAwaiting a human or maintainer judgment call.

    Type

    Fields

    No fields configured for Task.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions