Skip to content

fix(api)!: answer stale commit and notes guards with 409 ref_guard_failed - #661

Merged
ThomasK33 merged 5 commits into
mainfrom
issue647-stale-guard-409
Nov 4, 2026
Merged

ThomasK33 merged 5 commits into
mainfrom
issue647-stale-guard-409

Conversation

@ThomasK33

@ThomasK33 ThomasK33 commented Nov 4, 2026 •

Copy link
Copy Markdown
Member

A stale ref guard on the four write forms that still answered our 412 deviation now answers upstream's 409 ref_guard_failed:

  • commit-pack, diff-commit and restore-commit with a stale expected_target_sha (or the deprecated expected_head_sha).
  • The legacy notes body forms with a stale expected_notes_ref_sha (or the deprecated expected_ref_sha): POST .../notes and the deprecated DELETE .../notes body.

This is part 2 of the desk decision on #647. Gate G1 of #352 fired on 2026-11-04 with the stable SDK 0.1.0 releases.

What the 409 body holds

The body keeps the members it had and adds the problem members, as upstream's spec of 2026-10-27 says (CommitWriteRefGuardProblemDetails, RestoreCommitRefGuardProblemDetails, NotesWriteRefGuardProblemDetails):

  • code: ref_guard_failed, type, title, status, detail, error and instance.
  • guard: expected_target_sha or expected_notes_ref_sha, also when the request sent the deprecated alias.
  • current_sha: the commit the guard was checked against. For a commit write that is the target tip, or the base_branch tip when the target branch is new. For a notes write it is the notes ref tip, or 40 zeros when the notes ref does not exist.
  • result with status: conflict (and the note members for notes). On the commit routes, result has every member that upstream's RefUpdateResult requires: target_branch, branch, old_sha, new_sha (empty), success and status, plus message. result.old_sha repeats current_sha, except on a new branch, where it stays 40 zeros as RefUpdateResult.old_sha defines.

The body is sent as application/problem+json, like the merge and notes guard bodies since #660, which this branch merged from main. On the commit routes, commit is null, as the schema descriptions say.

Code

  • wcFailRefGuard in handlers_write_commit.go builds the commit-write body from refGuardProblem, the same builder that the merge and notes guards use, and writes it with writeProblemJSON. All three commit routes reach it through wcPlanCommit, so there is one call site.
  • wrefHandleNote drops the per-form staleGuardStatus and always calls wrefNoteGuardFail.
  • The guard message now starts with expected_target_sha, as the merge guard's does, so the expectedProblemCodes oracle maps it to ref_guard_failed.

Tests

  • TestCommitRefGuardContentType pins application/problem+json on the commit guard body, and the commit-pack stale-guard test checks the header end to end. The notes callers use feat(api)!: send application/problem+json on problem bodies #660's assertNotesRefGuard, which checks the header too.
  • New oracle assertCommitRefGuard (problem_test.go) checks the result members (their set must equal the vendored RefUpdateResult properties), the guard members and, through assertProblemFields, the problem members. TestProblemMembersMatchUpstream now pins the allOf members of CommitWriteRefGuardProblemDetails and RestoreCommitRefGuardProblemDetails to result.
  • The stale-guard cases in write_commit_test.go, upstream_names_test.go, upstream_ops_test.go and write_refs_test.go now expect the 409 body. TestGuardSHAUppercase checks the full body on all three commit routes. The base-branch case checks current_sha = base tip and old_sha = 40 zeros.
  • Mutation control: with the two handler files reverted to origin/main, 7 of the changed tests fail on both backends.

Docs

Dogfood

A local osv.sh node built from this head, driven by the Go SDK github.com/pierrecomputer/sdk/go v0.1.0 (tag go/v0.1.0 = 5f1a4bc). Each stale guard came back as a *pierre.RefGuardError (status 409, unwraps to *pierre.ConflictError) with the expected guard and current_sha:

Form Baseline 63f81faa This head
commit-pack RefUpdateError 412 precondition_failed RefGuardError, current_sha = tip
commit-pack with base_branch RefUpdateError 412 RefGuardError, current_sha = base tip
diff-commit RefUpdateError 412 RefGuardError, current_sha = tip
restore-commit RefUpdateError 412 RefGuardError, current_sha = tip
notes create, unborn notes ref RefUpdateError 412 RefGuardError, current_sha = 40 zeros
notes create, existing notes ref RefUpdateError 412 RefGuardError, current_sha = notes tip
notes delete, query guard RefGuardError 409 RefGuardError 409 (unchanged)

The branch tip did not move in either run. The table rows are from head ac24914c. The probe passed again on heads 9773c1e6, 3fc8d5ec, 3b3b85c0 and 809fbe54 (main merged in twice), and a jsonschema check of each 409 body against the vendored CommitWriteRefGuardProblemDetails, RestoreCommitRefGuardProblemDetails and NotesWriteRefGuardProblemDetails passed for all 7 bodies on each. On 3b3b85c0 and 809fbe54 every 409 came with Content-Type: application/problem+json and every 200 with application/json. The same check fails on ac24914c (no target_branch and new_sha, Codex round 1) and on the baseline. The updated commit-pack recipe passed with 46 of 46 checks.

The old Go SDK 1.17.1 (code-storage-go), same probe shape, against origin/main 3c6bfde3 and heads 3b3b85c0 and 809fbe54 (same result on both):

Form 3c6bfde3 This head
commit-pack, diff-commit, restore-commit RefUpdateError precondition_failed RefUpdateError conflict
notes create RefUpdateError precondition_failed APIError 409, message = raw body (it parses note bodies only for application/json)

SDK 0.1.0 signs its tokens with sub: pierre-sdk-go, which open.storage rejects with 401 today. That is tracked in #658. The probe therefore gave the SDK tokens from openstorage mint through option.WithGetToken, with the scopes and repo claim that the SDK asked for. The requests and the error parsing are the SDK's own.

Validation

Fixes #647

BREAKING CHANGE: a stale expected_target_sha or expected_head_sha on commit-pack, diff-commit and restore-commit, and a stale expected_notes_ref_sha or expected_ref_sha on POST .../notes and the DELETE .../notes body, now answer 409 with code: ref_guard_failed, guard, current_sha and result.status: conflict, instead of 412 precondition_failed. Go SDK 1.17.1 (code-storage-go) callers now get a RefUpdateError with status conflict on the three commit routes. On a note create they get an APIError with status 409 whose message is the raw body, because that SDK reads note bodies only for application/json. Go SDK 0.1.0 (github.com/pierrecomputer/sdk/go) callers get a RefGuardError on every form.


Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high

…iled

A stale expected_target_sha on commit-pack, diff-commit and
restore-commit, and a stale expected_notes_ref_sha on the legacy notes
body forms, now answer 409 ref_guard_failed with guard and current_sha
next to the result members (spec 2026-10-27), instead of 412
precondition_failed. Gate G1 of #352 fired with SDK 0.1.0.

Fixes #647

Change-Id: I93474abed354d3e72fe06c6bfa85b8d6cf6ab737
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-04T13:00:01.558812Z 809fbe5 Manual request
🔒 Security Review ✅ Completed 2026-11-04T13:01:40.262475Z 809fbe5 Manual request
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review

Security review completed. No security issues were found in this pull request.

Reviewed commit: ac24914ccc

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ac24914ccc

ℹ️ 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".

Comment thread internal/api/handlers_write_commit.go Resolved
Codex round 1 (P2): the commit-write guard body reused wcResult, which
has no target_branch and omits an empty new_sha, both required by
upstream's RefUpdateResult.

Change-Id: Ia67c186558025c8ac1eaa5c1ef10860154cf9452
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 9773c1e6b1

ℹ️ 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".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review

Security review completed. No security issues were found in this pull request.

Reviewed commit: 9773c1e6b1

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

The spec's CommitWriteRefGuardProblemDetails and
RestoreCommitRefGuardProblemDetails descriptions say commit is null.

Change-Id: I33fca2be10a1bd7a3af54316d30873e9d46e14e9
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: 3fc8d5ec66

ℹ️ 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".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review

Security review completed. No security issues were found in this pull request.

Reviewed commit: 3fc8d5ec66

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Change-Id: Ic1aa09ca7c3db9fa050f31cb62ea7d0afb921536
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 3b3b85c015

ℹ️ 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".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review

Security review completed. No security issues were found in this pull request.

Reviewed commit: 3b3b85c015

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@ThomasK33
ThomasK33 added this pull request to the merge queue Nov 4, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Nov 4, 2026
Change-Id: I4f85fb7af15375ecb69be9e2f73c6e9a49abf9a0
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex security review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. You're on a roll.

Reviewed commit: 809fbe546c

ℹ️ 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".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review

Security review completed. No security issues were found in this pull request.

Reviewed commit: 809fbe546c

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@ThomasK33
ThomasK33 added this pull request to the merge queue Nov 4, 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.

Upstream drift (SDK main fa4c317): the new SDKs branch on ref_guard_failed; end the #533 412 stale-guard deviations when G1 fires

1 participant