Docs
Search docs

Resolve an ambiguous GitHub ref transaction with provider proof

POST/api/repos/{owner}/{repo}/github-ref-transactions/{id}/resolve

resolveGithubRefTransaction

Settles a `github_managed` repository's `ambiguous` write-through transaction — one whose outcome on GitHub nobody could prove — as `projected`, `rejected` or `cancelled`. Requires repo admin. `observed_remote_refs` states the OID GitHub holds for EVERY ref the transaction names (`null` = absent), exactly those refs; it is verified against a live read of GitHub's refs before anything changes, and a mismatch answers `409 github_ref_proof_mismatch` with the row untouched. `projected` additionally requires GitHub to hold every recorded target (`409 conflict` otherwise — resolve as `cancelled` and the managed observation converges on what GitHub holds). `projected` projects the recorded targets as a provider observation (no native CI) when local refs still sit at the transaction's expected old values, records the current operation when they are already at the targets, and answers `409 conflict` when they moved. The verified proof, the resolving admin and the time are recorded; the transaction's staged objects are released once it is terminal. Only `ambiguous` transactions are resolved here (`409 conflict` otherwise).

Requires authentication using a bearer token or a session cookie — see tokens and scopes.

curl

curl -X POST 'https://neosource.dev/api/repos/OWNER/REPO/github-ref-transactions/ID/resolve' \
  -H 'Authorization: Bearer $NEOSOURCE_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"resolution":"string","observed_remote_refs":[]}'

fetch

fetch("https://neosource.dev/api/repos/OWNER/REPO/github-ref-transactions/ID/resolve", {
  method: "POST",
  headers: {
    Authorization: "Bearer $NEOSOURCE_TOKEN",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({"resolution":"string","observed_remote_refs":[]}),
});

Path parameters

ownerrequired

Repository owner or organization slug.

string

reporequired

Repository name.

string

idrequired

The ref transaction id (a UUID), as a paused push or a band-2 notice names it.

string

Request bodyrequired

application/json

ResolveGithubRefTransactionRequest

object

Body of `POST /api/repos/{owner}/{repo}/github-ref-transactions/{id}/resolve`.

observed_remote_refsrequired

array

The remote OIDs the admin observed on GitHub, one per ref the transaction names — exactly those refs, no more, no fewer. Verified against a live GitHub read before anything changes.

items

GithubObservedRemoteRef

object

One ref as the admin observed it on GitHub — the proof half of [`ResolveGithubRefTransactionRequest`].

oid

string | null

The 40-hex git OID GitHub holds for it, or `null` when GitHub has no such ref.

refnamerequired

string

The full refname, exactly as the transaction names it (`refs/heads/…` or `refs/tags/…`).

additional propertiesnot allowed
resolutionrequired

GithubIntentResolution

string

What a repository admin settles an `ambiguous` ref transaction as — the closed `resolution` of `POST …/github-ref-transactions/{id}/resolve`. Each resolution names exactly one target state ([`Self::target`]), and each target is an edge out of `ambiguous` in [`GithubIntentState::successors`]: the admin picks the outcome they proved, never an arbitrary state.

"projected""rejected""cancelled"

additional propertiesnot allowed

Responses

200Resolved

application/json

GithubRefTransactionResponse

object

A GitHub ref transaction (ADR 0115 Phase 3) — the write-through's durable intent, as the resolve and cancel routes answer it.

accepted_at

integer | nullint64

attemptsrequired

integerint32

authority_epochrequired

integerint64

The GitHub authority epoch the transaction was prepared under.

commandsrequired

array

The canonical command set, sorted by refname.

items

GithubRefCommandResponse

object

One command of a GitHub ref transaction: `refname` from `expected_old` to `new` (`null` = absent: a create has no `expected_old`, a delete no `new`).

expected_old

string | null

new

string | null

refnamerequired

string

created_atrequired

integerint64

Millis since the Unix epoch.

last_error

string | null

projected_at

integer | nullint64

resolved_at

integer | nullint64

When a repository admin resolved or cancelled it.

resolved_by

string | null

The account id of the admin who did.

staterequired

GithubIntentState

string

The state machine shared by `github_ref_transactions.state` and `github_mutation_intents.state`. ONE enum for both tables: their CHECK constraints are byte-identical and the plan describes a single lifecycle — prepare durably, submit at most once, land or fail, project. Splitting them would be two copies of the edge table with nothing comparing them. ```text prepared → submitting, cancelled submitting → accepted, ambiguous, rejected accepted → projected, ambiguous ambiguous → projected, rejected, cancelled projected / rejected / cancelled → (terminal) ``` [`Self::successors`] is the ONLY statement of that table; `can_transition_to`, `predecessors_of` and `is_terminal` are all derived from it, and the stores' SQL guards bind `predecessors_of(target)` rather than restating an edge list in SQL where nothing could compare the two.

"prepared""submitting""accepted""ambiguous""projected""rejected""cancelled"

transaction_idrequired

string

Standard errors

Bodies documented once for the whole API — see standard errors.

  • 400Bad Request — one of: invalid_input
  • 401Authentication required
  • 403Forbidden — one of: forbidden
  • 404Not Found — one of: not_found
  • 409Conflict — one of: conflict, github_ref_proof_mismatch
  • 423Locked — one of: busy
  • 429Rate limited — retry after the `Retry-After` header
  • 500Internal server error
  • 502Bad Gateway — one of: upstream
  • 503Service temporarily unavailable / at capacity — retry after the `Retry-After` header
  • 504Gateway timeout — the request exceeded the server's handling budget