open-git progress
what open-git must add before tripwire works there as well as it works on github. every item below is a real gap found while running tripwire against open-git.com, not a guess.
last checked: 2026-08-23, against docs/openapi.json (14 paths) and a live
integration on open-git.com.
what works today
these parts are done. they need no change from open-git.
| capability | how |
|---|---|
| sign in | oauth2, through the genericOAuth plugin |
| install the bot | /integrations/<owner>/<slug>/install |
| mint a token | POST /api/v1/app/installations/{id}/access_tokens |
| receive events | signed webhooks, x-hub-signature-256 |
| read an installation | GET /api/v1/app/installations/{id} returns owner and name |
| block a merge | POST /api/v1/repos/{owner}/{repo}/commits/{sha}/checks |
| comment | POST /api/v1/repos/{owner}/{repo}/pulls/{number}/comments |
| connect a repository | installing the bot is the connection, no manual step |
tripwire posts one check named tripwire on each commit. the check is the
whole merge gate. open-git blocks a merge on checks and reads no reviews.
installing the bot connects every repository it grants.
the installation event names them by uuid only. tripwire reads the installation to get the owner and the name. the repositories then appear in the dashboard on their own.
the whole path is verified against open-git.com: a signed delivery arrives, the event normalizes, one rule evaluates, and a check is written back. a title edited with no new commits re-evaluates and flips the same commit's check.
1. reads, the largest gap
tripwire has 9 built-in rules. only 1 of them runs on open-git.
the other 8 read a diff, a commit list, or a contributor profile. open-git's v1 api serves none of the three. the rules do not fail. they decline, and the change request goes to review.
1.1 the diff of a pull request
add: GET /api/v1/repos/{owner}/{repo}/pulls/{number}/files
for each file, return the path, the status, the added line count, the deleted line count, and the patch text.
this unblocks 4 rules:
crypto-addressfinds a wallet address in the changehoneypotfinds a change to a protected pathmax-files-changedcounts the filesai-reviewreads the change and reasons about it
a diff route already exists at /api/repos/{repoId}/pulls/{prId}/diff. it is
not usable here. it authenticates with a browser session, it is keyed by an
internal uuid, and an installation token cannot reach it.
1.2 a contributor profile
add: GET /api/v1/users/{username}
return the account creation date, the bio text, the follower count, and the public repository count.
this unblocks 2 rules:
account-agerefuses an account that is too newprofile-readmelooks for an empty or spam profile
/api/viewer exists but returns the caller only. a rule must read the
contributor, who is a different person.
1.3 the author of a pull request
change: add author to each entry from
GET /api/v1/repos/{owner}/{repo}/pulls
the list returns body, head_sha, id, number, state, title and
url. it names no author, so tripwire cannot count a person's pull requests.
this unblocks 2 rules:
min-merged-prscounts merged work, to trust a known contributorpr-rate-limitcounts recent pull requests, to catch a spray attack
pr-rate-limit also needs a creation time on each entry.
1.4 the commits of a pull request
add: GET /api/v1/repos/{owner}/{repo}/pulls/{number}/commits
return the sha, the message, the author, and the authored time.
no built-in rule needs this yet. a custom rule can, and github supplies it.
1.5 file contents
add: GET /api/v1/repos/{owner}/{repo}/contents/{path}?ref=<sha>
ai-review reads a file to understand a change. it degrades without one.
2. actions
2.1 edit a comment
add: PATCH /api/v1/repos/{owner}/{repo}/pulls/{number}/comments/{id}
add: GET /api/v1/repos/{owner}/{repo}/pulls/{number}/comments
the comment endpoint creates only. tripwire cannot find its own comment, and it cannot edit one.
tripwire therefore comments only when a verdict changes. a change request that stays blocked gets one comment, not one for each push. this avoids a wall of identical comments, but it also means an old comment stays visible after the verdict changes.
with an edit route, tripwire keeps one comment and rewrites it.
2.2 dismiss a review
add: a way to dismiss or resolve a review
tripwire can request changes. it cannot withdraw that request. a stale "changes requested" review would stay on the change request forever.
tripwire does not file reviews on open-git for this reason. the check does the gating instead.
2.3 labels
add: POST /api/v1/repos/{owner}/{repo}/pulls/{number}/labels
a workflow can add a label on github. that action does nothing on open-git.
2.4 request a reviewer
add: POST /api/v1/repos/{owner}/{repo}/pulls/{number}/requested_reviewers
a moderation workflow asks a human to look. it cannot do that here.
2.5 close a pull request
add: a way to close a pull request through the api
there is no close route. PUT .../merge merges, and the session route reads
only. a test harness cannot clean up after itself.
3. webhook payloads
3.1 branch names and the draft flag
change: add base_ref, head_ref and draft to the pull request payload
the payload carries id, number, author, title, body and head_sha.
tripwire records these three as absent rather than guessing. any custom rule about a target branch or a draft change request skips.
3.2 repository names on installation events
change: send repository objects, not bare ids
installation.created and installation.repos_changed list repositories as
uuids only:
{ "action": "repos_changed",
"installation_id": "…",
"repositories": ["e2cb113f-…", "99bde44f-…"] }
a uuid alone cannot build a repository row. tripwire calls
GET /api/v1/app/installations/{id} after each event to get the owner and the
name. this works, but it is one extra call for data the event could carry.
3.3 visibility of a repository
change: add visibility to each repository, wherever repositories are
returned: the installation response, the installation events, and the pull
request payload.
open-git already stores this. repositories.visibility is a real column
with a ('public','private') check. it is simply not sent. this is the
cheapest item on the list: one field on responses that already exist.
what tripwire does meanwhile: it asks for the repository page with no credentials. a 200 means public. anything else means not confirmed public.
that works, and it is safe in one direction only, which is why it is written that way: a private repository answers 404 to an anonymous request, so it can never be read as public.
it is still a guess about a fact open-git knows. it costs one request for each repository at install time, and it breaks the day an unauthenticated private repository answers 200 for any reason.
3.4 an actor on installation events
change: add the person who installed or changed the installation
tripwire records who did what. an installation event names nobody.
4. api surface
4.1 list the installations of a bot
add: GET /api/v1/app/installations
a bot can read one installation by id. it cannot list its own. recovery after a lost id needs a list.
summary
| gap | blocks |
|---|---|
| diff of a pull request | 4 rules |
| contributor profile | 2 rules |
| author on the pulls list | 2 rules |
| commits of a pull request | custom rules |
| file contents | ai-review quality |
| edit a comment | one clean comment per change request |
| dismiss a review | review-based blocking |
| labels | the label action |
| request a reviewer | the moderation handoff |
| close a pull request | test cleanup |
| refs and draft flag | branch and draft rules |
| names on installation events | one extra api call for each event |
| repository visibility | public run pages (worked around, badly) |
| actor on installation events | the audit trail |
| list installations | recovery |
the first three rows are the important ones. they take tripwire from 1 working rule to 9.