chadtmiller.com/knotless
git that lives in your Atmosphere account
1
10
A private repository's merge queue lands through the gateway
Merged Approved
This pull makes the gateway read the repository, its queue and each pull's head as the owner for a runner's landing and for a collaborator's gated push. It also makes the runner eject a batch's pulls once the same batch fails to land three times in a row. I found nothing that must change.
- Session lookup: the gateway keeps owners' sessions in
app.ctx's config directory, keyed by DID (session::load(&app.ctx, did)).as_owneronly setsidentifieron a clone of that context, so it picks up the delegated session as intended. Clearing the password stops it falling back to a login. - Delegation:
writerhas already requiredsession::ensurefor the owner, so the owner has delegated by the timeas_owneris used. - Failure counter: it is keyed on the batch's base plus each pull's URI and head, so a moved branch or a different batch resets it. It is cleared on a landing, on an ejection, and when the line goes idle, and idleness now accounts for it. The rule that a 403 ejects at once is unchanged.
- Tests and docs: the tests cover the private landing path and the third-failure ejection. The docs pages for the gateway and the merge queue are updated, as AGENTS.md asks.
Changeset: nonefits, since only the server and runner change.
I didn't read the checks, and the gateway test passes without running anywhere but the spaces alpha. Please make sure CI's spaces-alpha test run passes before it lands.
All checks have passed
8 passed, 2 skipped
Merged as 80dfda1
What changes
The gateway reads a landing as the owner. When a runner lands a merge queue through
dev.knotless.pushRefs, and when a collaborator's push is held to the merge gate, the gateway now reads the repository, its queue and each pull's head with a context acting as the owner, through the session they delegated. A private repository's queue is in its space, which takes a member's credential to read; the gateway's own context has nobody logged in, so reading it failed withnot logged in: run knotless login <handle>, a 500 for every landing.A landing that keeps failing ends. The runner ejected a batch's pulls only when the gateway refused it (403); any other failure dropped the batch, which was rebuilt, checked and failed again for ever. Now the same batch (same tip, same heads) failing to land three times in a row has its pulls ejected, saying
its batch passed its checks but failed to land 3 times in a row: <error>.Why
chadtmiller.com/group-host, private, names runner.knotless.dev, which may not push, so it lands through knotless.dev's gateway. Every batch passed its checks and every landing failed with a 500 (
not logged in), the runner retrying every 40 seconds or so. The failing read wasTarget::queue_entriesinlanding_refusal: for a private repository it joins the space assession::me, which the gateway does not have. Reading as the owner, whose session the gateway holds once they delegate, is what the gateway already writes as.How it was checked
runners_land_a_private_merge_queue_through_a_gateway(knotless-serve gateway tests, spaces alpha only): a private repository, its named runner a member that may not push, the owner delegated; two queued pulls land through the gateway, their branches deleted and both merged.a_runner_named_lands_through_the_gateway(knotless-run) goes on: once the owner delegates, the gateway, having no appview of its own, fails each landing with a 500, and the pull is ejected after the third, saying why.Shortcomings
landing_refusalstill reads a pull whose head is in the repository itself by opening it again, rather than from the snapshot it holds: that works now the gateway reads as the owner, and is left as it was.Changeset: none
🤖 Generated with Claude Code