Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

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.

forge/config/config.go +9−9

@@ -13,7 +13,7 @@ import (
13 13
14 14 type Config struct {
15 15 DataDir string `toml:"data_dir"`
16 // HTTPAddr serves the read-only web UI and anonymous git clone.
16 // HTTPAddr serves the web UI and anonymous git clone.
17 17 HTTPAddr string `toml:"http_addr"`
18 18 // SSHAddr is the only write githttp.
19 19 SSHAddr string `toml:"ssh_addr"`
@@ -50,11 +50,11 @@ type Config struct {
50 50 // PagesCacheBytes caps the in-memory blob cache. The cache is required, not an
51 51 // optimisation: cold git reads are ~1.2 ms p50, warm ones 0.075 ms.
52 52 PagesCacheBytes int64 `toml:"pages_cache_bytes"`
53 // PublicURL is where this instance is reachable from a browser, when that is
54 // knowable: "https://forge.example.com" behind a proxy, or the listen address
55 // on a LAN. It is optional and used for one thing — telling a client where to
56 // read what it just wrote (the CLI prints the URL of an issue or comment it
57 // created). Empty means the CLI prints ids only, which it did before.
53 // PublicURL is where this instance is reachable from a browser:
54 // "https://forge.example.com" behind a proxy, normally. It is optional for a
55 // read-only instance; browser login is enabled only when it is an https URL,
56 // because WebAuthn is bound to that origin. It is also what the CLI uses to
57 // print a link to something it just created.
58 58 PublicURL string `toml:"public_url"`
59 59
60 60 Path string `toml:"-"`
@@ -179,9 +179,9 @@ http_addr = "127.0.0.1:8080"
179 179 # The only write githttp. Identity is the SSH key presented at handshake.
180 180 ssh_addr = "127.0.0.1:2222"
181 181
182 # Where a browser reads this instance, if that differs from http_addr — a proxy
183 # endpoint, or a LAN address. Optional: the CLI uses it to print the page for
184 # something it just created. Trailing slash is ignored.
182 # Where a browser reads this instance. Set it to the canonical https URL to
183 # enable passkey login; WebAuthn is bound to this origin. The CLI also uses it to
184 # print the page for something it just created. Trailing slash is ignored.
185 185 # public_url = "https://forge.example.com"
186 186
187 187 # Reject individual blobs above this size (pre-receive). Point people at