Skip to content

bug: git-sync write access is never validated — a read-only credential fails silently forever (ls-remote and the REST permissions.push field both lie) #2107

Description

@AndriiPasternak31

Summary

Nothing on the platform validates that an agent's git credential can write. A credential with
read-only scope fails every sync forever, and every health surface reports the agent as fine.

Observed

An agent hard-failed 64 consecutive auto-sync cycles from the moment it was created, with
9 unpushed commits, and the only surface that ever noticed was a single operator-queue item.

last_sync_status     : failed
consecutive_failures : 64
last_error_summary   : remote: Write access to repository not granted.

The credential is a fine-grained PAT whose Contents permission is read-only on that repo.

Why every existing check passes

  • git ls-remote probes succeed. Read access short-circuits before write is ever exercised, so
    a reachability probe is not an access probe.
  • The REST API says push: true. GET /repos/{owner}/{repo} returns a permissions object
    reflecting the authenticated user's role on the repo, not the token's granted permission set.
    For a fine-grained PAT those are different things, and the field reads like proof of write access
    while the push returns 403. Anything that checks permissions.push will be wrong here.
  • The compatibility checker has no push check — the git-related checks read .gitignore text.
  • Sync health reports the failure count but nothing acts on it, so 64 identical failures produce
    the same signal as one.

Suggested fix

A write-access probe that exercises the actual operation, at agent creation and in the sync loop's
health reporting:

git push --dry-run origin <sha>:refs/heads/__trinity_write_probe

--dry-run performs the full auth/permission negotiation and creates nothing. Failing it at
creation time turns "silently broken forever" into "broken before the agent ever ran". A compat
catalogue check would surface the same thing on the panel.

Related: nothing distinguishes "sync failing for 1 cycle" from "sync has never once succeeded".
The second is a provisioning bug and deserves a different signal from a transient failure.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions