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 instance-wide roles and refine access UI
5b814e9958090cfd1fa826efb2d375bf613547c1 · Keenan Nemetz · 14d ago · parent 9579c1f9
Add instance-wide roles and refine access UI Instance roles now live on accounts, apply to public repositories, and the Admin role is the unified instance-admin permission with access to every repository. Repository ACLs can raise an instance role but not lower it. Adds role assignment to the users UI and CLI, open-registration role config, a reusable role picker, and separates adding a repository account from saving access rules.
docs/users-and-access.md +61−36
| @@ -65,16 +65,20 @@ is no password reset to phish. Retiring an account deletes its sessions | |||
| 65 | 65 | immediately, and removing a passkey deletes the sessions that passkey created. | |
| 66 | 66 | ||
| 67 | 67 | With `open_registration = true`, `/register` creates a new account and its first | |
| 68 | passkey without an administrator. New accounts have no repository-specific ACL | ||
| 69 | entry; the repository's default role applies. For an open-source project, the | ||
| 70 | usual setup is a public repository whose default role is `contributor`: | ||
| 68 | passkey without an administrator. Set `open_registration_role` to the | ||
| 69 | instance-wide role those accounts should have; `contribute` is the usual choice | ||
| 70 | for an open-source instance: | ||
| 71 | 71 | ||
| 72 | ```sh | ||
| 73 | vole admin acl default demo contributor | ||
| 72 | ```toml | ||
| 73 | open_registration = true | ||
| 74 | open_registration_role = "contribute" | ||
| 74 | 75 | ``` | |
| 75 | 76 | ||
| 76 | A registered account can add its own SSH key from **Account**, which is what lets | ||
| 77 | it push to `refs/heads/contrib/<name>/`. Open registration has no email | ||
| 77 | That role applies to every **public** repository, so a new contributor can read, | ||
| 78 | discuss, and push to `refs/heads/contrib/<name>/` without being added to each | ||
| 79 | repository. It does not open private repositories. `admin` is refused here; grant | ||
| 80 | instance admin explicitly. A registered account can add its own SSH key from | ||
| 81 | **Account**, which is what lets it push. Open registration has no email | ||
| 78 | 82 | verification, so leave it off on a private instance unless you want that policy. | |
| 79 | 83 | ||
| 80 | 84 | Admins can inspect and revoke sessions: | |
| @@ -107,25 +111,23 @@ vole admin --remote origin repo create demo --owner bob | |||
| 107 | 111 | vole admin --remote origin acl default demo read | |
| 108 | 112 | ``` | |
| 109 | 113 | ||
| 110 | An instance admin is not the same as a repository admin. A repository admin can | ||
| 111 | manage that repository's branches and reviews; an instance admin can create users | ||
| 112 | and repositories and change access rules anywhere. Only instance admins may use | ||
| 113 | `--remote`. | ||
| 114 | |||
| 115 | Instance admins may also browse and clone any repository, private ones included, | ||
| 116 | without an ACL entry of their own. That overlay is read-only: it does not grant | ||
| 117 | push, comment, or repository-settings rights, which still need the matching ACL | ||
| 118 | role. SSH Git and SSH LFS use the key's account for this check; anonymous HTTP | ||
| 119 | clone has no identity, so a private repository still answers `404` there. | ||
| 114 | An instance admin is the instance-wide `admin` role. They can create users and | ||
| 115 | repositories, change access rules anywhere, and use `--remote`. They are also a | ||
| 116 | repository admin on every repository, private ones included: they can push, | ||
| 117 | change settings, and manage access without a repository-specific entry. SSH Git | ||
| 118 | and SSH LFS use the key's account for this check; anonymous HTTP clone has no | ||
| 119 | identity, so a private repository still answers `404` there. | ||
| 120 | 120 | ||
| 121 | 121 | Instance admins also get a **Users** page in the top navigation. It covers | |
| 122 | accounts: create an account from an enrollment link, grant or revoke instance | ||
| 123 | admin, retire an account, start a fresh enrollment link, and inspect or revoke | ||
| 124 | SSH keys and browser sessions. Repository creation is a **New repository** action | ||
| 122 | accounts: create an account from an enrollment link, set its instance-wide role | ||
| 123 | (including `admin`), retire an account, start a fresh enrollment link, and | ||
| 124 | inspect or revoke SSH keys and browser sessions. Repository creation is a **New repository** action | ||
| 125 | 125 | on the home page, and per-repository access rules live on that repository's | |
| 126 | 126 | **Settings** tab, visible there to instance admins. | |
| 127 | 127 | ||
| 128 | The first instance admin must be granted on the host. Vole refuses to remove or | ||
| 128 | The first instance admin must be granted on the host. Instance admin is the | ||
| 129 | instance-wide `admin` role, so `vole admin user role alice admin` and | ||
| 130 | `vole admin user grant-admin alice` mean the same thing. Vole refuses to remove or | ||
| 129 | 131 | retire the last active instance admin, so a remote mistake cannot lock everyone | |
| 130 | 132 | out. Add `--json` to any remote command for a machine-readable response: | |
| 131 | 133 | ||
| @@ -138,20 +140,31 @@ recovery operations, not remote administration. | |||
| 138 | 140 | ||
| 139 | 141 | ## Roles | |
| 140 | 142 | ||
| 141 | Each repository has a default role for everyone and optional roles for specific | ||
| 142 | accounts. | ||
| 143 | A role can be granted in two places: | ||
| 144 | |||
| 145 | - **instance-wide**, on the account: it applies to every public repository; | ||
| 146 | - **per repository**: an explicit entry for that repository. | ||
| 147 | |||
| 148 | The effective role is the higher of the repository's default role, the | ||
| 149 | repository entry for the account, and the account's instance-wide role. Instance | ||
| 150 | roles only take effect on public repositories. The exception is `admin`: an | ||
| 151 | instance admin is an admin on every repository, including private ones. | ||
| 152 | |||
| 153 | Each repository also has a default role for everyone and optional roles for | ||
| 154 | specific accounts. | ||
| 143 | 155 | ||
| 144 | 156 | | Role | What it allows | | |
| 145 | 157 | |---|---| | |
| 146 | 158 | | `none` | No access | | |
| 147 | 159 | | `read` | Clone, fetch, and browse the repository | | |
| 148 | | `contributor` | Read, file issues and comments, push only `refs/heads/contrib/<name>/*`, and open change requests from those branches | | ||
| 149 | | `maintain` | Everything a contributor can do, plus push shared branches, triage issues, and approve change requests | | ||
| 160 | | `contribute` | Read, file issues and comments, push only `refs/heads/contrib/<name>/*`, and open change requests from those branches | | ||
| 161 | | `maintain` | Everything the contribute role can do, plus push shared branches, triage issues, and approve change requests | | ||
| 150 | 162 | | `admin` | Everything a maintainer can do, plus manage access, push protected branches, override locks, and repair metadata | | |
| 151 | 163 | ||
| 152 | 164 | A new repository is private. Its default role is `none`, and its owner is an | |
| 153 | 165 | admin. Private repositories return `404` to anonymous visitors, so people cannot | |
| 154 | tell whether they exist. | ||
| 166 | tell whether they exist. An instance-wide `read`, `contribute`, or `maintain` | ||
| 167 | grant does not open a private repository; an instance admin does. | ||
| 155 | 168 | ||
| 156 | 169 | To publish a repository, give the default role `read`: | |
| 157 | 170 | ||
| @@ -161,18 +174,25 @@ vole admin acl default demo read | |||
| 161 | 174 | ||
| 162 | 175 | A repository admin can also change the description, default branch, and | |
| 163 | 176 | visibility, and rename or delete the repository, from its **Settings** tab in | |
| 164 | the browser. Visibility | ||
| 177 | the browser. An instance admin has those rights on every repository too. | ||
| 178 | Visibility | ||
| 165 | 179 | toggles the default role between `none` and `read`; explicit role entries are | |
| 166 | left alone. Access rules and review policy remain instance-admin operations: | ||
| 167 | instance admins can edit them on the repository's **Settings** tab, or with | ||
| 168 | `vole admin acl`. | ||
| 180 | left alone. The Accounts table shows only accounts with an explicit role or | ||
| 181 | runner entry; use **Add account** below it to grant another account a | ||
| 182 | repository-specific role. Access rules and review policy remain instance-admin | ||
| 183 | operations: instance admins can edit them on the repository's **Settings** tab, | ||
| 184 | or with `vole admin acl`. | ||
| 169 | 185 | ||
| 170 | 186 | ## Changing access | |
| 171 | 187 | ||
| 172 | 188 | ```sh | |
| 189 | vole admin user create carol --role contribute --key carol.pub | ||
| 190 | vole admin user role alice maintain | ||
| 191 | vole admin user role bob none | ||
| 192 | |||
| 173 | 193 | vole admin acl show demo | |
| 174 | 194 | vole admin acl set demo alice maintain | |
| 175 | vole admin acl set demo bob contributor | ||
| 195 | vole admin acl set demo bob contribute | ||
| 176 | 196 | vole admin acl set demo carol read | |
| 177 | 197 | vole admin acl default demo read | |
| 178 | 198 | vole admin acl protect demo refs/heads/main | |
| @@ -181,9 +201,14 @@ vole admin acl checks demo on | |||
| 181 | 201 | vole admin acl runners demo ci-runner-1 | |
| 182 | 202 | ``` | |
| 183 | 203 | ||
| 184 | - `set` gives one account a role. The roles are `none`, `read`, `contributor`, | ||
| 185 | `maintain` and `admin`. `contribute` and `contrib` are accepted as aliases for | ||
| 186 | `contributor`; `write` is accepted as the historical spelling of `maintain`. | ||
| 204 | - `user create --role` and `user role` set the account's instance-wide role. | ||
| 205 | On a public repository that role applies without a per-repository entry; on a | ||
| 206 | private repository it does not, unless the role is `admin`. | ||
| 207 | - `set` gives one account a role in one repository. The roles are `none`, | ||
| 208 | `read`, `contribute`, `maintain` and `admin`. `contributor` and `contrib` are | ||
| 209 | accepted as aliases for `contribute`; `write` is accepted as the historical | ||
| 210 | spelling of `maintain`. A repository entry can raise the instance-wide role but | ||
| 211 | cannot lower it. | ||
| 187 | 212 | - `default` changes the role for everyone else. `read` or higher makes the | |
| 188 | 213 | repository public. | |
| 189 | 214 | - `protect` replaces the list of protected branch patterns. Admins can still push | |
| @@ -196,7 +221,7 @@ vole admin acl runners demo ci-runner-1 | |||
| 196 | 221 | ||
| 197 | 222 | ## Contributors and their branches | |
| 198 | 223 | ||
| 199 | The `contributor` role is for open-source projects that accept outside patches. | ||
| 224 | The `contribute` role is for open-source projects that accept outside patches. | ||
| 200 | 225 | A contributor can read, file issues and comments, and open a change request from | |
| 201 | 226 | the browser. Their Git writes are confined to a branch folder named after their | |
| 202 | 227 | account name: | |
| @@ -228,7 +253,7 @@ Contributor branches are ordinary branches except for one rule: CI does not run | |||
| 228 | 253 | for them automatically. A maintainer or admin opens the change request for the | |
| 229 | 254 | branch and chooses **Allow CI** there. The approval names the exact | |
| 230 | 255 | commit, so every new push waits again. Treat runner isolation as part of the trust decision before granting | |
| 231 | `contributor` on a public project. | ||
| 256 | `contribute` on a public project. | ||
| 232 | 257 | ||
| 233 | 258 | ## When rules are checked | |
| 234 | 259 | ||