Skip to content

fix(opf): push the v1 commit the OPF rewrite verified, not the branch tip - #2669

Open
peyton-alt wants to merge 1 commit into
mainfrom
peyton/opf-v1-pinned-push
Open

peyton-alt wants to merge 1 commit into
mainfrom
peyton/opf-v1-pinned-push

Conversation

@peyton-alt

@peyton-alt peyton-alt commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

https://entire.io/gh/entireio/cli/trails/1491

Problem

On the git-branch backend with the OpenAI Privacy Filter (OPF) on, pre-push rewrites the unpushed entire/checkpoints/v1 commits and then pushes v1 by name. pushRefIfNeeded re-reads the branch, and git push resolves it again. If another session appends a checkpoint between the rewrite and the push, that untrailered, unscanned commit becomes the pushed tip.

This is on main today. It was found in an adversarial review of the OPF PRs (#2533, #2631) and gets more likely once checkpoints are delivered in the background.

Fix

  • The OPF rewrite's returned hash is now kept, and v1 is pushed as <verified>:refs/heads/entire/checkpoints/v1. The local branch is never re-read. A zero hash (no v1 yet) pushes nothing.
  • If the remote rejects the pinned push, v1 is still synced with the remote (so the next push doesn't hit a divergence error), but it is not retried. The rebased tip holds whatever the local branch held at sync time, which may include unscanned commits. The user is told it will go out on their next push. This only happens if the remote moves during the push, because the rewrite fetches the live remote tip moments earlier.
  • With OPF skipped or off, v1 still pushes by name, unchanged.

git push <remote> <sha>:refs/heads/... still updates the remote-tracking ref, and its porcelain output parses the same.

Tests

  • TestPrePush_V1PushesTheVerifiedCommitNotALaterAppend appends a checkpoint between the rewrite and the push. The remote gets the verified commit, and the append stays local and untrailered. It fails on main.
  • TestDoPushRefAt_PinnedRejectionSyncsWithoutRetry: a rejected pinned push syncs the local ref without pushing the rebased tip.
  • The diverged-clones setup moved into a helper shared with TestFetchAndRebase_DivergedBranches.

mise run check passes.

Known gap (unchanged)

When Entire's own push is deferred on an empty remote, a user who runs git push origin entire/checkpoints/v1 themselves still pushes by name.

🤖 Generated with Claude Code


Note

High Risk
Changes what checkpoint metadata reaches the remote under OPF—a prior bug could ship unscanned privacy-sensitive content; the fix is security-critical but narrowly scoped to the OPF pre-push path.

Overview
Fixes a privacy gap on the git-branch backend when OPF runs at pre-push: after rewriting entire/checkpoints/v1, the push used the branch name and could ship a newer local checkpoint another session appended between rewrite and push—content that was never OPF-scanned.

Pre-push now pins the hash returned by the rewrite and pushes v1 as <verified>:refs/heads/entire/checkpoints/v1 via pushVerifiedRefIfNeeded, without re-reading the local branch tip. OPF-off behavior is unchanged (still push by name).

If that pinned push is rejected, the code still syncs the local branch to the remote but does not retry with the rebased tip (which might include unscanned commits); the user is told the ref will go out on the next push.

Tests cover the concurrent-append scenario and pinned-push rejection; security docs note that post-rewrite appends stay local until the next push.

Reviewed by Cursor Bugbot for commit c97efe2. Configure here.

… tip

After the pre-push OPF rewrite, the git-branch path pushed
entire/checkpoints/v1 by name, so a checkpoint another session appended
between the rewrite and the push shipped without being scanned. v1 now
ships as the exact commit the rewrite verified; a later append stays
local and is rewritten on the next push.

If the remote rejects the pinned push, v1 is still synced with the
remote but not retried, since the rebased tip holds unverified commits.
OPF skipped or off keeps pushing by name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entire-Checkpoint: 01M47E6JTDJH7F4C49AM56YT9B
@peyton-alt
peyton-alt requested a review from a team as a code owner October 6, 2026 01:46
Copilot AI balanced review requested due to automatic review settings October 6, 2026 01:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Pinned-push recovery can overwrite a checkpoint appended concurrently during synchronization.

Review effort: Balanced
Findings: 1 High severity

Open (1)
What changed in this PR

Pins OPF-protected v1 delivery to the exact verified commit, preventing concurrent unscanned checkpoints from reaching the remote.

Changes:

  • Adds hash-pinned push and rejection recovery.
  • Routes OPF-rewritten v1 pushes through the pinned path.
  • Adds concurrency/rejection tests and updates security documentation.
File Description
docs/​security-and-privacy.md Documents pinned concurrent-push behavior.
cmd/​entire/​cli/​strategy/​push_common.go Implements pinned pushes and recovery.
cmd/​entire/​cli/​strategy/​push_common_test.go Tests rejected pinned pushes.
cmd/​entire/​cli/​strategy/​manual_commit_push.go Uses the verified OPF hash.
cmd/​entire/​cli/​strategy/​manual_commit_opf_rewrite_test.go Tests concurrent post-rewrite appends.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +347 to +349
if !src.IsZero() {
fmt.Fprintf(os.Stderr, "[entire] %s will be pushed on your next push\n", refLabel)
return false, nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants