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.
Phase 7: the CLI knows who you are and where you wrote it
a63475ce8a689107f6572150d7c58be1d623f6f0 · Keenan Nemetz · 17d ago · parent 79c88d72
Phase 7: the CLI knows who you are and where you wrote it Three things a first-time user hit in a row, all measured against a live instance before they were fixed. 1. Identity was guessed. Every issue and request was stamped with a name from `git config user.name`, sanitised: "Keenan Nemetz" became `keenan-nemetz`, an account that does not exist, and nothing complained — the issue page showed it, and the assignee rule accepted it because that rule only checks the shape. `vole-whoami` is a new SSH verb, and `vole whoami` is the CLI command that reads it: the instance is the only place a key maps to an account, and it is one call on the connection already open. `vole issue` and `vole request` stamp the account's current name and id, and `--author` is gone from both, because a name you can type is a name you can get wrong. Read commands still need no identity — `issue list` and `issue show` keep working with the instance unreachable — and the git-config guess survives only as a warned fallback for `--no-push`. 2. `--remote ssh://…` did not fetch. `fetch` checked for a configured remote name, so a URL was skipped: the first write in a fresh repository succeeded (nothing to fast-forward from) and every later one pushed from a tip that had never been updated, was rejected, and then retried as a "lost race" that never happened, reporting `already exists`. A URL is now fetched like a named remote, so `git init` plus a URL is the real no-clone filing path the roadmap described. 3. A command answered with an id and stopped. `new` and `comment` now print the page they wrote, and a comment link lands on that comment: the instance reports its own `public_url` in the same whoami reply (new optional config key), and the web puts an `id="c-<ulid>"` anchor on every comment. Empty states on the issues and requests pages print the command that fills them, because four of the five things a reader wants to do are writes the web cannot take, and "no comments yet" is a dead end. Verified live, not only in tests: `vole whoami` in a clone whose `user.name` is "Keenan Nemetz" printed `keenan` while the issue it then filed carried `author: keenan` on the branch; two repositories that never clone both wrote through the URL (the exact case that failed before); and a comment printed a `#c-01M5N3M0…` permalink whose anchor is on the served page. Tests: TestWhoAmIAnswersFromTheInstance (including `--author` now being an unknown option), TestReadCommandsNeedNoIdentity (closes the SSH listener, then lists), TestRequestAuthorComesFromTheKey, TestAURLRemoteIsFetchedBeforeWriting, TestEmptyStatesPrintAWorkingCommand, and the comment-empty-state assertion added to TestIssuePushedThenRendered. scripts/ci.sh green (gofmt, vet, build, markdown links, go test -race ./...).
README.md +25−3
| @@ -99,6 +99,13 @@ git clone http://127.0.0.1:8080/git/demo.git # read only, no credentials | |||
| 99 | 99 | Repositories are private by default. A private repo is a `404` on the web and | |
| 100 | 100 | over HTTP — not a `403` — so the read-only surface never confirms that it exists. | |
| 101 | 101 | ||
| 102 | Nothing in the configuration knows where the instance is reachable from outside, | ||
| 103 | so tell it once if the web is served through a proxy or another address: | ||
| 104 | |||
| 105 | ```toml | ||
| 106 | public_url = "https://forge.example.com" # optional; the CLI prints links to it | ||
| 107 | ``` | ||
| 108 | |||
| 102 | 109 | ## Filing an issue | |
| 103 | 110 | ||
| 104 | 111 | An issue is one file on the `vole` branch. No client tooling is required: | |
| @@ -145,6 +152,7 @@ The id must be a ULID (26 characters, Crockford base32 — uppercase, no `I`, `L | |||
| 145 | 152 | Or use the CLI, which is the same thing with the paperwork done: | |
| 146 | 153 | ||
| 147 | 154 | ```sh | |
| 155 | vole whoami # which account your key is; no guessing | ||
| 148 | 156 | vole issue new --title "Nothing renders on the docs page" -m "Steps..." -l bug -a wilbur | |
| 149 | 157 | vole issue comment -m "Also affects search" 01M5JR2JK29KKMAA1T9MDNTPBP # prints the comment id | |
| 150 | 158 | vole issue edit-comment 01M5JR2JK29KKMAA1T9MDNTPBP 01M5N1PRC4GJPZNEEG8PR8J4D6 -m "Corrected." | |
| @@ -171,9 +179,23 @@ Options come before arguments — `vole issue comment -m text <id>`, not the oth | |||
| 171 | 179 | way round — and a usage mistake exits 129, as git does. | |
| 172 | 180 | ||
| 173 | 181 | The CLI writes the files, commits to the `issues` branch, validates locally and | |
| 174 | pushes. `#<ulid>` in a body links to that issue, and commits whose message | ||
| 175 | mentions an id are listed as backlinks on the issue. The list page filters by | ||
| 176 | state and label and searches titles and bodies. | ||
| 182 | pushes. Its author is the account your key resolves to — the CLI asks the instance | ||
| 183 | once (`vole-whoami`) instead of trusting `git config user.name`, which on a normal | ||
| 184 | machine is a real name that is not an account name. There is no `--author` flag to | ||
| 185 | get wrong. | ||
| 186 | |||
| 187 | A repository with no configured remote works too: `git init` in an empty directory | ||
| 188 | and pass the URL. | ||
| 189 | |||
| 190 | ```sh | ||
| 191 | git init bug-report && cd bug-report | ||
| 192 | vole issue new --title "the docs page is blank" --remote ssh://git@forge.example.com/demo.git | ||
| 193 | ``` | ||
| 194 | |||
| 195 | `#<ulid>` in a body links to that issue, and commits whose message mentions an id | ||
| 196 | are listed as backlinks on the issue. The list page filters by state, label and | ||
| 197 | assignee, and searches titles and bodies. When `public_url` is set, `new` and | ||
| 198 | `comment` print the page they wrote, and the comment link lands on that comment. | ||
| 177 | 199 | ||
| 178 | 200 | A comment is `issues/<id>/comments/<ulid>.md` with `author` and `created` | |
| 179 | 201 | frontmatter. Closing an issue is editing `state` to `closed`. The push is | |