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.
Docs: rewrite the README and organize the guides
520470e19cd906bd6fff987e2d132d793ce56486 · Keenan Nemetz · 16d ago · parent c5902451
Docs: rewrite the README and organize the guides Replace the long README with a landing page, split feature details into focused guides, and remove the roadmap and spike notes. Update comments that referenced them.
docs/architecture.md +105
| @@ -0,0 +1,105 @@ | |||
| 1 | # Architecture and design | ||
| 2 | |||
| 3 | This page is for people who want to understand how Vole works and why it makes | ||
| 4 | the choices it does. If you only want to use Vole, the guides are enough. | ||
| 5 | |||
| 6 | The goal is not novelty. The goal is a forge that stays understandable, works on | ||
| 7 | hardware you control, and keeps the important parts in Git. | ||
| 8 | |||
| 9 | Vole is built for one team on one server. It does not try to be a hosted service, | ||
| 10 | and it does not connect to other Vole instances. That keeps the design small. | ||
| 11 | |||
| 12 | ## Trust: your key is your identity | ||
| 13 | |||
| 14 | Vole uses one rule everywhere: | ||
| 15 | |||
| 16 | > Your SSH key proves who you are. Vole checks every change before accepting it, | ||
| 17 | > and records the decision in `data/audit.log`. | ||
| 18 | |||
| 19 | There is no second login system for writes. The web interface is read-only. | ||
| 20 | Approvals, comments, and CI results all belong to the account whose key pushed | ||
| 21 | them. | ||
| 22 | |||
| 23 | Vole does not require or check Git commit signatures. A signature would only | ||
| 24 | repeat what the SSH connection already established, and it cannot reliably prove | ||
| 25 | who authored a commit. Vole would rather keep one clear path than add a second | ||
| 26 | one that can disagree with the first. | ||
| 27 | |||
| 28 | ## What that means | ||
| 29 | |||
| 30 | On the server, Vole can show a complete history of who pushed what. A clone of a | ||
| 31 | repository, by itself, cannot prove who pushed a commit. The instance promises a | ||
| 32 | complete record; it does not promise offline proof. | ||
| 33 | |||
| 34 | That trade-off is wrong if you plan to mirror the repository somewhere controlled | ||
| 35 | by someone else. For a team running its own forge, it keeps the system simple and | ||
| 36 | auditable. | ||
| 37 | |||
| 38 | ## Where data lives | ||
| 39 | |||
| 40 | | Data | Where it lives | Rebuildable? | | ||
| 41 | |---|---|---| | ||
| 42 | | Repositories | `data/repos/<name>.git` | It is the source | | ||
| 43 | | Issues, requests, approvals, release pointers, CI records | The `vole` branch in each repository | It is the source | | ||
| 44 | | Accounts, SSH keys, access rules, locks | `data/users.db` | No; back it up | | ||
| 45 | | Web/search index | `data/index.db` | Yes, with `vole index rebuild` | | ||
| 46 | | CI queue and run index | `data/runs.db` | Partly; in-progress work is lost | | ||
| 47 | | LFS files, CI logs, build artifacts | `data/lfs/` | No; stored by content | | ||
| 48 | | Privileged-action history | `data/audit.log` | It is the record | | ||
| 49 | | SSH host key | `data/ssh_host_ed25519_key` | No; it is the secret | | ||
| 50 | |||
| 51 | Git holds the project history. SQLite holds the user database, the CI queue, and | ||
| 52 | generated indexes. Anything that can be rebuilt comes from Git or stored files. | ||
| 53 | Anything that cannot be rebuilt is small and easy to back up. | ||
| 54 | |||
| 55 | The `vole` branch contains: | ||
| 56 | |||
| 57 | ```text | ||
| 58 | issues/<ulid>/issue.md | ||
| 59 | issues/<ulid>/comments/<ulid>.md | ||
| 60 | requests/<ulid>/request.md | ||
| 61 | requests/<ulid>/comments/<ulid>.md | ||
| 62 | requests/<ulid>/approvals/<account-id>.md | ||
| 63 | releases/<tag>/<artifact> | ||
| 64 | runs/<run-id>/<attempt>/... | ||
| 65 | ``` | ||
| 66 | |||
| 67 | People write the issue and request files. Vole writes the run records. All of it | ||
| 68 | is checked when it is pushed. | ||
| 69 | |||
| 70 | ## Why these choices | ||
| 71 | |||
| 72 | | Choice | Reason | | ||
| 73 | |---|---| | ||
| 74 | | Use the Git command-line tool | Full push behavior and hooks without reimplementing Git | | ||
| 75 | | SSH for writes, HTTP for anonymous reads | One authenticated way to change data; reads stay simple | | ||
| 76 | | Check everything before accepting a push | One place for policy; the web has no writes to protect | | ||
| 77 | | Store metadata in Git, rules in SQLite | Project content travels with clones; local settings stay local | | ||
| 78 | | No web login | The web is read-only, so there is no password store or session to build | | ||
| 79 | | One program with separate serve and runner modes | Easy to deploy anywhere | | ||
| 80 | | Keep the host key as the only secret | No signing key to manage or leak | | ||
| 81 | |||
| 82 | ## Using Vole as a library | ||
| 83 | |||
| 84 | Vole is also a Go library. You can build tools that talk to an instance or embed | ||
| 85 | parts of Vole without running the `vole` command. | ||
| 86 | |||
| 87 | | Package | What it does | | ||
| 88 | |---|---| | ||
| 89 | | `client` | Talks to an instance: metadata writes, identity lookups, file transfer, reviews, and site deploys | | ||
| 90 | | `core/id`, `core/git`, `core/lfs` | Shared primitives and storage | | ||
| 91 | | `forge` | Instance setup and administration | | ||
| 92 | | `forge/config`, `forge/identity`, `forge/access`, `forge/repo`, `forge/index` | Settings, accounts, permissions, repositories, and search | | ||
| 93 | | `metadata` | Issues, requests, releases, comments, approvals, and validation | | ||
| 94 | | `ci` | Workflow validation and the job queue; `ci/agent` is the embeddable runner | | ||
| 95 | | `server` | Network listeners and web pages, with adapters for SSH, Git HTTP, sites, and hooks | | ||
| 96 | |||
| 97 | `cmd/vole` is only the command-line front end. Logic shared by more than one | ||
| 98 | caller lives in the packages above. | ||
| 99 | |||
| 100 | ## Scope | ||
| 101 | |||
| 102 | Vole is built for one team on one server. It does not support multiple tenants, | ||
| 103 | federation, container-isolated CI steps, custom domains with automatic | ||
| 104 | certificates, horizontal scaling, or a Kubernetes deployment story. These are not | ||
| 105 | part of Vole today. | ||