Skip to content

Govern ref updates outside refs/heads/ - #25

Closed
Deep-Sixed wants to merge 1 commit into
claude/eloquent-galileo-xu0ah7-push-requestfrom
claude/eloquent-galileo-xu0ah7-ref-namespaces
Closed

Deep-Sixed wants to merge 1 commit into
claude/eloquent-galileo-xu0ah7-push-requestfrom
claude/eloquent-galileo-xu0ah7-ref-namespaces

Conversation

@Deep-Sixed

Copy link
Copy Markdown
Owner

4 of 4 restoring ideas from the retired Codex_Kernel repo. This is a draft, stacked on #22. It will be rebased onto main once #10 merges, because #10 rewrites the same gate code. At that point the migration will also be renumbered, since main now has its own 004_approval_authority.sql.

Problem

Claims only coordinate refs/heads/*. Anything else a push creates or moves (a tag, a note, a custom refs/… ref) went through ungoverned unless it was explicitly protected, deleted or force-moved. Codex_Kernel's gate only accepted refs/heads/ updates.

Change

  • governed_operation: an update to a ref outside refs/heads/ is a non_branch_ref_update, and needs an approval bound to the exact update. Protected, delete and force operations still take precedence as the operation type.
  • quorumgit repo namespace open|close|list <repo> <refs/prefix/> lets a repository open a namespace, for example refs/tags/ for release tooling. Updates there then skip the rule.
    • refs/heads/ can't be opened.
    • Deletes, forced moves and explicitly protected refs inside an open namespace are still governed.
    • Opening and closing are audited.
    • Migration 004_open_ref_namespaces.sql stores the list.
  • approve request --push doesn't peel non-branch refs down to a commit. An annotated tag's derived operation therefore names the tag object, which is what the hook sees.
  • README: documented the rule, the namespace commands and the annotated-tag usage.

Tests

tests/test_ref_namespaces.py adds 11 tests:

  • a lightweight tag push is rejected, then accepted with the exact derived approval;
  • an annotated tag derives the tag object's ID and lands once approved;
  • a custom namespace is governed;
  • open → ungoverned (other namespaces still governed) → closed → governed again;
  • an open namespace still governs deletes and protected refs;
  • namespace validation (4 cases);
  • the audited lifecycle;
  • the CLI.

tests/test_authorization_binding.py: the list of migrations expected after 001 now includes 004.

Local results: pytest 165 passed, ruff clean, pyright 0 errors.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Mc44WsAZx9hzZdWEihDk5a


Generated by Claude Code

Claims only coordinate branches, so tags, notes, and custom refs could be
created or moved with no governance at all. The predecessor Codex_Kernel
gate only accepted refs/heads/ updates; this restores that boundary in
QuorumGit's approval model.

- Any update to a ref outside refs/heads/ is a non_branch_ref_update and
  needs an approval bound to the exact update (protected, delete, and
  force still take precedence as operation types).
- `repo namespace open|close|list` lets a repository opt a namespace such
  as refs/tags/ out of that rule. refs/heads/ cannot be opened; deletes,
  forced moves, and explicitly protected refs stay governed. Changes are
  audited. Migration 004_open_ref_namespaces.sql adds the table.
- `approve request --push` resolves non-branch refs without peeling, so
  an annotated tag's operation names the tag object the hook sees.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mc44WsAZx9hzZdWEihDk5a

Copy link
Copy Markdown
Owner Author

Closing as superseded by #23, now on main. Repositories accept only refs/heads/ until an operator allows a namespace with quorumgit repo allow-ref <name> refs/tags/. Protected refs and protected paths still apply inside allowed namespaces.

The one difference: this PR let a push to a non-allowed namespace through with an exact approval, while main refuses it outright. The repository owner chose main's stricter default.


Generated by Claude Code

@Deep-Sixed Deep-Sixed closed this Sep 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants