`branch_head_sha` existed to keep callers compiling while the branch-head
lookup moved onto the repository reader. Its last caller now opens a
reader directly, so the wrapper only made the typed API worse: it joined
an already-validated owner and repo into a slug so the reader could split
them apart again, invented an "invalid repository coordinate" error for a
value validated upstream, opened a fresh credential session per call, and
flattened `RepositoryReadError` into `anyhow` while keeping one variant —
leaving callers unable to tell a rate limit from a rejected token.
Its integration test pinned the wrapper rather than the behavior. Replace
it with one that asserts the same 404-means-not-observable semantics
through `resolve_commit`, which is where that contract actually lives.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Share the twin's handler scaffolding, collapse the reader's parallel URL
and error machinery, and resolve branch-head credentials once per verify.
Twin GitHub server:
- Add handlers/support.rs holding the response envelope, installation-token
authorization, Accept matching, and commit-SHA checks. The commits and
contents handlers carried byte-identical copies of all six items, and
pulls.rs had its own copy of the two response mappers.
- Add AppState::find_repository and repository_mut, replacing four
open-coded repository lookups.
- Add head_refs and heads_selector so the heads/{branch} mapping is
spelled once instead of in add_repository, the fixture conversion, and
the branch handler.
- Key repository files by commit SHA then path rather than by a
(String, String) tuple, which drops two allocations and two full-map
scans per content request.
Repository reader:
- Use DisplaySafeUrl, which removes the file-scope disallowed_types
suppression and the direct url dependency. The suppression covered the
whole module and everything later added to it.
- Build {api_base}/repos/{owner}/{repo} once when the session opens, so
the URL builders become infallible methods and three unreachable
cannot-be-a-base error paths disappear.
- Collapse the per-operation NotFound and Unavailable variants into ones
carrying the operation, derive its rendering with strum, and mark the
error non_exhaustive.
- Return the status classification as one Err(match), size the body
buffer from Content-Length, and lowercase the resolved SHA in place.
Pull request pipeline:
- Open one reader before the branch-head retry loop instead of once per
attempt. With App credentials each attempt previously minted a fresh
installation token, costing two extra round trips per retry. Only the
ref lookup is retried now; credential failures surface immediately.
Tests keep their coverage: one helper opens readers across eight call
sites, and the repository file fixtures become a table.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>