vole
Clone
Read only, no credentials:
https://rodent.software/vole.git
Write over SSH with a registered key:
git clone ssh://git@rodent.software:2222/vole.git
A free and open-source forge that lives in your Git repo.
Add browser auth, contributor access, and gated CI
6c84d387e5f608360e30484a1a5b1cff41076850 · Keenan Nemetz · 16d ago · parent c36d5073
Add browser auth, contributor access, and gated CI Browser sign-in now uses passkeys. Enrollment links are one-time, sessions are hashed in users.db, and issue/comment/approval writes use the session account. HTTPS public_url is required for WebAuthn. Add the contributor role between read and maintain. Contributors can discuss and open change requests, and may push only refs/heads/contrib/<account-id>/. Contributor CI is held per commit until a maintainer allows the exact tip from the repository page. Rename the write role to maintain. write remains accepted as the historical spelling, and access.Write remains as a Go alias so existing callers and ACL rows keep working. Update the web, CLI, queue schema, and guides for the new flows, and cover the role, namespace, auth, and CI-gating paths in tests.
server/web/runners.go +3−3
| @@ -76,7 +76,7 @@ func (w *Web) RunnersPage(rw http.ResponseWriter, r *http.Request) { | |||
| 76 | 76 | } | |
| 77 | 77 | if s.Repo != "" { | |
| 78 | 78 | m, err := w.Repos.Open(s.Repo) | |
| 79 | if err != nil || !w.public(m) { | ||
| 79 | if err != nil || !w.canRead(r, m) { | ||
| 80 | 80 | continue // a private repository's build is not an anonymous reader's business | |
| 81 | 81 | } | |
| 82 | 82 | if run, err := w.Runs.Get(s.RunID); err == nil && run != nil { | |
| @@ -96,7 +96,7 @@ func (w *Web) RunnersPage(rw http.ResponseWriter, r *http.Request) { | |||
| 96 | 96 | } | |
| 97 | 97 | for name, d := range depths { | |
| 98 | 98 | m, err := w.Repos.Open(name) | |
| 99 | if err != nil || !w.public(m) { | ||
| 99 | if err != nil || !w.canRead(r, m) { | ||
| 100 | 100 | continue | |
| 101 | 101 | } | |
| 102 | 102 | queue = append(queue, queueView{Name: name, Queued: d.Queued, Running: d.Running, Cap: perRepoCap}) | |
| @@ -110,7 +110,7 @@ func (w *Web) RunnersPage(rw http.ResponseWriter, r *http.Request) { | |||
| 110 | 110 | Queue []queueView | |
| 111 | 111 | Window string | |
| 112 | 112 | }{ | |
| 113 | Page: w.base("Runners"), | ||
| 113 | Page: w.page(r, "Runners"), | ||
| 114 | 114 | Sessions: sessions, | |
| 115 | 115 | Queue: queue, | |
| 116 | 116 | Window: presenceWindow.String(), | |