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.
Identify accounts by their registered name
62576fa8157d431dcf2d360f3ebe481de77bda03 · Keenan Nemetz · 14d ago · parent 642e5994
Identify accounts by their registered name Drop the internal account id and display name. Users, keys, passkeys, invites, sessions, ACL entries, approvals, locks and CI records now all use the registered name as the single identity. The roster migrates in place: old id-keyed tables are rebuilt around the name, and access-rule/lock references are rewritten through the same mapping. Display-name editing and whoami --id are removed.
ci/agent/agent.go +7−10
| @@ -125,11 +125,9 @@ type runnerReply struct { | |||
| 125 | 125 | Run *runnerJob `json:"run,omitempty"` | |
| 126 | 126 | OK bool `json:"ok"` | |
| 127 | 127 | Lease int `json:"lease,omitempty"` | |
| 128 | // The account this session authenticated as and the fingerprints of its keys, | ||
| 129 | // which is how a runner finds out before it starts work whether the key it will | ||
| 130 | // sign with is one the server will accept. | ||
| 131 | Account string `json:"account,omitempty"` | ||
| 132 | Name string `json:"name,omitempty"` | ||
| 128 | // The account name this session authenticated as, so a runner can say whose | ||
| 129 | // results it reports. | ||
| 130 | Name string `json:"name,omitempty"` | ||
| 133 | 131 | // Repos are the repositories this account may run jobs for. A runner answers the | |
| 134 | 132 | // "ping" with these so a --repos filter can be checked against them at startup: | |
| 135 | 133 | // a filter that matches nothing would otherwise look exactly like a quiet instance. | |
| @@ -258,7 +256,7 @@ func Run(ctx context.Context, opts Options) error { | |||
| 258 | 256 | if err := checkRepoFilter(opts.Repos, who); err != nil { | |
| 259 | 257 | return err | |
| 260 | 258 | } | |
| 261 | sess.account, sess.name = who.Account, who.Name | ||
| 259 | sess.name = who.Name | ||
| 262 | 260 | sess.repos, sess.labels = opts.Repos, opts.Labels | |
| 263 | 261 | sess.cacheRoot, sess.cacheMax, sess.cacheReuse = cacheRoot, cacheMax, !opts.NoCache | |
| 264 | 262 | if opts.NoCache { | |
| @@ -325,10 +323,9 @@ type runnerSession struct { | |||
| 325 | 323 | enc *json.Encoder | |
| 326 | 324 | dec *json.Decoder | |
| 327 | 325 | mu sync.Mutex | |
| 328 | // account is the account id the server resolved from the connection. A record | ||
| 326 | // name is the account the server resolved from the connection. A record | ||
| 329 | 327 | // names it, and the gate refuses a record whose signer is not the pusher. | |
| 330 | account string | ||
| 331 | name string | ||
| 328 | name string | ||
| 332 | 329 | // repos is the --repos filter, sent with every lease. It is what the operator | |
| 333 | 330 | // asked for, not the effective list: the server intersects it with the grant on | |
| 334 | 331 | // each request, so an allowlist edit takes effect without a restart. | |
| @@ -612,7 +609,7 @@ func (s *runnerSession) finish(remote string, co checkout, job *runnerJob, log * | |||
| 612 | 609 | RunID: job.ID, Attempt: job.Attempt, Repo: job.Repo, Ref: job.Ref, SHA: job.SHA, | |
| 613 | 610 | Workflow: job.Workflow, WorkflowSHA: job.WorkflowSHA, Job: job.Job, | |
| 614 | 611 | StepsSHA: job.StepsSHA, Exit: exit, Finished: time.Now().UTC(), | |
| 615 | Signer: s.account, Artifacts: artifacts, | ||
| 612 | Signer: s.name, Artifacts: artifacts, | ||
| 616 | 613 | // The machine this attempt ran on. The runner binary's own build target, | |
| 617 | 614 | // which is the honest thing it can say: a live probe would add a subprocess | |
| 618 | 615 | // and a platform quirk for a fact the binary already knows. | |