Repository navigation
Add per-operation approval policy overrides - #27
Merged
Merged
Conversation
A repository's approval policy becomes its default. Operators can override the threshold, approving roles, or requester-may-vote for one operation type (protected_ref_update, force_update, ref_delete, out_of_scope_push, protected_path_update, lease_takeover), e.g. two votes for a force push and one for a takeover. Unset override fields inherit the default; --inherit removes the override. - Migration 006: operation_approval_policies/roles tables and an approval_effective_policy view; the vote-eligibility triggers now enforce the effective policy, so direct writers are held to it too. - registry.approval_policy takes the operation type; request, vote and consumption all use the effective policy, so raising an override invalidates approvals that no longer meet it. - CLI: repo policy --operation <type> [--inherit]; the plain view lists overrides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0142xh1CDDPxBvB1EHu6PN3m
Deep-Sixed
marked this pull request as ready for review
September 29, 2026 23:36
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2ba93177fd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Review fixes: - vote() reopens an approved instance that no longer meets the effective policy (threshold raised, approvers demoted), audited as approval.reopened, so eligible agents can top it up. Previously request_approval() kept returning that live instance while vote() refused every vote on it, leaving the exact operation unusable until the policy was weakened. Applies to default-policy changes too. - verify_contract() requires the approval_effective_policy view the vote-eligibility triggers read from. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0142xh1CDDPxBvB1EHu6PN3m
Renumber 006_operation_policies.sql to 008, since 006 and 007 now hold the ref-update transaction tables. Check the required views by name before the schema fingerprint, as tables and triggers already are, so a dropped policy view is reported as such. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8BpCkArA34hB1aSyVcnZp
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8BpCkArA34hB1aSyVcnZp
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8BpCkArA34hB1aSyVcnZp
Deep-Sixed
pushed a commit
that referenced
this pull request
Sep 30, 2026
Renumber the quorum migration to 009 and let a per-operation override set quorum mode as well as threshold, roles and requester voting: a NULL approval_quorum on an override inherits the repository default. The repo policy CLI accepts --quorum with --operation and shows quorum on overrides. Reopening a stale approval (#27) uses the same requirement as voting and consumption, so a quorum raised by new approvers reopens it for the missing votes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8BpCkArA34hB1aSyVcnZp
Deep-Sixed
pushed a commit
that referenced
this pull request
Sep 30, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8BpCkArA34hB1aSyVcnZp
This was referenced Sep 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #23. A repository's approval policy becomes its default. Operators can now override it for a single operation type. For example, a force push or a branch deletion can need two votes while a lease takeover needs one.
What changes
protected_ref_update,force_update,ref_delete,out_of_scope_push,protected_path_update,lease_takeover.--inheritremoves an override.008_operation_policies.sql(renumbered from006;006and007now hold the ref-update transaction tables from Bind push authorization to Git's reference transaction #30 and Measure claim scopes against the mainline, not every ref #29):operation_approval_policies,operation_approval_roles, and anapproval_effective_policyview.registry.approval_policy(conn, repo_id, operation_type)returns the effective policy. Requests, votes, and consumption all use it, so raising an override invalidates approvals that no longer meet it.approval.reopened. Eligible agents can then add the missing votes, or deny it. Before this, such an approval was stuck until the policy was loosened. That also happened when the default threshold was raised, before this PR.quorumgit repo policy <repo> --operation <type> [--threshold n] [--role r]… [--[no-]requester-may-vote] [--inherit]. The plainrepo policy <repo>view now lists overrides.Testing
tests/test_operation_policies.py(9 tests):--inheritremoves an override, and changes are audited006–008.main:pytest240 passed.ruff checkandpyrightare clean.🤖 Generated with Claude Code
https://claude.ai/code/session_0142xh1CDDPxBvB1EHu6PN3m
https://claude.ai/code/session_01Q8BpCkArA34hB1aSyVcnZp