vole
Clone
Read only, no credentials:
https://rodent.software/git/vole.git
Write over SSH with a registered key:
git clone ssh://git@0.0.0.0:2222/vole.git
A free and open-source forge that lives in your Git repo.
Name branches after the account, and labels after the display
474a812d199a109ba894124cd6f26be12c73285d · Keenan Nemetz · 15d ago · parent ade6107e
Name branches after the account, and labels after the display
A contributor's folder was `refs/heads/contrib/<account-id>/`, which told a
reader nothing without decoding a ULID. It is now the account name,
refs/heads/contrib/<name>/<branch>
and the name is therefore fixed at creation: renaming an account would strand
every ref under its old folder, so `vole admin user rename` is gone and the
users row itself — kept after retirement — is what stops a name being reissued.
What people see is now a separate, mutable display name, validated by the same
rules wherever it is set (CLI, remote admin, registration, `/account`) and shown
on pages, approvals, listings and refusals. Nothing is authorized by it and
nothing on disk is keyed by it: metadata authors stay account names because the
push boundary resolves them for ownership, and approvals stay account ids.
`user_names`, `Snapshot.Reserved` and `Account.Former` are dropped: with a fixed
name there are no former names to remember, and the UNIQUE column already does
the reserving. Opening an older roster adds the `display` column and drops the
alias table in place; contributor refs written under the old id namespace are
left where they are, readable, and landable by a maintainer.
server/web/writes.go +4−1
| @@ -212,7 +212,10 @@ func (w *Web) CreateChangeRequest(rw http.ResponseWriter, r *http.Request) { | |||
| 212 | 212 | } | |
| 213 | 213 | headRef := "refs/heads/" + head | |
| 214 | 214 | if acl.RoleFor(pr.account.ID) == access.Contributor { | |
| 215 | if !access.IsContributorRef(pr.account.ID, headRef) { | ||
| 215 | // A contributor's head must be a branch the hook would let them push. The | ||
| 216 | // namespace is the account name, which cannot change, so this agrees with | ||
| 217 | // the gate without a roster lookup. | ||
| 218 | if !access.IsContributorRef(pr.account.Name, headRef) { | ||
| 216 | 219 | http.Error(rw, "contributors may only open requests from their own branch namespace", http.StatusForbidden) | |
| 217 | 220 | return | |
| 218 | 221 | } | |