Skip to content
quarry Artifact [2e6c9e34bc]
Login

Artifact [2e6c9e34bc]

Artifact 2e6c9e34bcaa60a57a2b186683e5a58f1bf965d0405b1445b06ce53d6969a5d0:


Summary

Today the settings page is a table of text inputs holding fossil capability strings. To let someone chat you type C. That is a users' manual in the shape of a form. This RFC keeps RFC 0004's model — fossil letters as the stored truth, lossless both ways — and replaces the interface: five named roles described by who they are for, a short list of abilities written as sentences for deviating from a role, and the raw string always one click away with its meaning decoded beside it. Roles gate nothing on their own; they are a way of writing cap strings. The legacy repo_role table, which still gates the web verifier in parallel with the letters, is retired so the page's sentences have one verifier to be true against.

Motivation

Three facts from the forge as it is:

The field agrees on the shape of the fix. GitHub: five roles named by who they are for, custom roles as a base plus permissions. GitLab: five roles, custom roles as a base plus granular permissions, the base immutable. Forgejo: teams with none/read/write per unit. Fossil itself: four inherited categories and a user editor that tags each letter with the category that already grants it. The permission-settings UX literature says a permissions page "is not just a list of toggles. It is an explanation system." Every good product here shows what is needed for the decision at hand and keeps the rest on demand.

Decisions

The proposal that preceded this RFC left four questions open. They are decided here, with the reasoning, so the build does not reopen them.

Five roles, not six: Contributor folds into Reader. Contributor differed from Reader by two letters, b and B (attachments). On this forge landings are the default path for everyone who may post — a landing is a forum thread — so "someone whose work lands through landings" is every Reader, not a distinct kind of person. Attachments ride the same moderation as posts (3 is the moderated write). A role that differs by a distinction nobody will remember is a role nobody will choose correctly.

Readers chat. C is in the Reader string and in the signed-in category of the public preset. Chat is the forum in real time; anyone who may post in one may speak in the other, and the moderation letter is the same (5). A forge that wants quieter chat removes one letter from one constant, once, in a diff someone reviews.

No teams in this RFC. GitHub, GitLab and Forgejo assign roles to teams as well as people, and quarry will (ticket 8318bd2819ca). The model here is team-shaped already — a team is a name that expands to a role on a set of repositories — and nothing below needs changing to add one. Building the people layer first and the team layer on it is the order that does not have to be undone.

Site admin stays an account flag, mapped to s everywhere, and is shown. The fleet's account page lists a person's role per repository; the site-admin flag appears beside them as what it is, so "why can dan do this" is answered on one page.

The model

Three layers. Each compiles to the one below; the bottom is what is stored.

Layer 1 — Roles

A role is a name, a sentence about who it is for, and a fixed cap string.

Role Who it is for Cap string What that adds
Reader reads, asks, discusses — most accounts on a public project u3bBC7 reader category (kptw: edit wiki, own password, ticket reports, edit tickets) plus forum posting, attachments, chat, email alerts
Developer checks in — on any branch that is not protected uv3bBC7 Reader plus the developer category (ei: check-in, see addresses). RFC 0007 decides which branches; this decides whether.
Maintainer a developer who also keeps the place tidy uv45bBlqCA7 Developer plus posting without moderation, moderating the forum, wiki and tickets, and announcements. Usually also an owner of protected branches — a protection row, not a letter.
Admin changes this repository's settings a everything except setup, private branches, unversioned writes — fossil's Admin-vs-Setup rule
Custom anything that is not exactly one of the above the string as written inferred on read: the nearest role and the difference, e.g. Developer, plus moderate forum, minus chat

Roles are constants in one file with a table-driven test asserting each letter set. A role is never stored; it is recovered by matching the string.

Visibility — the two categories as presets

Visibility nobody anonymous Meaning
Public project gjorzh2 mnc3C fossil's stock defaults plus forum reading for visitors, forum posting and chat for anyone signed in
Members only — gjorzh2mnc3C visitors see nothing; a sign-in sees a public project
Private — — only people with explicit roles; RFC 0004's invisible-not-403 posture

Fossil's stock nobody is gjorz; anonymous adds hmnc. Public project differs by h for visitors (the hyperlink anti-bot letter is quarry's own posture), 2 for visitors, and 3C for the signed-in. Those additions are the whole reason forum and chat work for a new account without anyone typing a letter. A forge that wants fossil's exact defaults picks Custom.

Layer 2 — Abilities

A sentence, a letter set, a group. Toggling one on a person whose role lacks it makes the role Custom with the difference stated; toggling it back restores the role. The compiler owns implications — w ⇒ rcn, 5 ⇒ 4 ⇒ 3 ⇒ 2, k ⇒ jm, i ⇒ o — so the abilities layer cannot produce a string fossil reads differently from the way the page said it.

Group Ability Letters
Code Read the code, clone, download archives ogzh
Code Check in and push i (⇒ o)
Code See private branches · push unversioned files x · y (advanced)
Tickets Read tickets · file tickets · comment on tickets r · n · c
Tickets Edit tickets w (⇒ rcn)
Tickets Moderate ticket comments · create report formats q · t
Wiki Read the wiki and notes j
Wiki Edit wiki pages · create new pages k (⇒ jm) · f
Wiki Approve wiki appends l
Forum Read the forum · post (moderated) 2 · 3 (⇒ 2)
Forum Post without moderation · moderate · grant exemptions 4 (⇒ 3) · 5 (⇒ 4) · 6
Talk Chat · send announcements · receive email alerts C · A · 7
Files Attach to tickets and wiki · to forum posts b · B
People See people's email addresses e (advanced)
Repository Change this repository's settings a

Not abilities: d (legacy, unused), D (debug), s (site admin — an account flag), u and v (a role's business; the fossil trap where v does not imply u is what the compiler hides), L (virtual). All reachable in Layer 3.

Layer 3 — Letters, settings, configuration

Advanced (fossil): the raw string for every person and category with a decoder beneath each input; the fossil settings names quarry passes to the store (ignore-glob, binary-glob, crlf-glob, manifest, autosync, …) as name and value, versionable ones marked and tree-overridden ones flagged; export and import of fossil's configuration areas (user, skin, ticket, project, shun, …), the files fossil configuration pull/push move.

Information architecture

Settings, by the question asked rather than by implementation order:

Section Answers Holds
Who can see this is it public? the three visibility presets; Custom reveals the category strings decoded
People who can do what? one row per person: role chip, deviation chips, owns trunk chip, effective sentence; a row opens the editor
Branches which are guarded, by whom? RFC 0007's rules; owners link to their People rows
Repository what is it? description, homepage, topics, the clone line
Integrations what does it talk to? webhooks, mirror posture
Advanced (fossil) the letters and the knobs raw strings with decoders · fossil settings · config areas
Danger zone the irreversible remove, delete

Plus: a per-person page (/r/{repo}/people/{name}) that is the editor on its own URL — fossil's /setup_uedit, in sentences; the fleet account page with the same editor per repository; and a fleet default for what a new repository starts as.

Progressive enhancement

The baseline is forms: a radio for the role, checkboxes for abilities, a text input for the string, a reload on save showing the effective sentence computed server-side and a line saying what changed. Script adds the same things live: the sentence as you click, the string and the checkboxes as two views of one signal, the change line and the lockout refusal before Save. Script never makes a control possible.

Bulletproofing

One system

repo_role is retired. The verifier asks what the ops ask — does the effective set contain the letter this needs — with the three floors mapped once: signed-in ⇒ L, repository admin ⇒ a, site admin ⇒ s. account grant --role stays as a command and writes the role's string. The migration runs one last time and the table goes.

Build order

Rung Work
1 This RFC
2 The compiler: roles, abilities, implication closure, decode, infer; table-driven tests
3 One system: verifier on letters; grant writes strings; migration; repo_role gone
4 People section and the per-person editor as forms; account.explain; the lockout guard
5 Visibility presets, the take-private guard, the fleet default
6 Settings page reorganised; Advanced (fossil) with decoders
7 Datastar: live sentence, two-way string ⇄ checkboxes, pre-save preview
8 fossil settings editor; configuration-area export/import — surface shipped; the store read/write is blocked on zit#153 (settings/config refuse -R on a bare store), so the section renders an honest note until that lands

Rung 3 before 4, deliberately: sentences built on two verifiers are promises the other one can break.

Rung 8's UI, ops, and store methods are built and tested; the store methods return a typed "no working tree" result because zit's settings and config verbs still refuse -R on a bare store, though the repository and global tiers they touch need no checkout (fossil's own fossil settings -R reads them). That is a zit limitation, filed as zit#153; the section says so rather than faking an editor, and fills in with no quarry change once the fix ships. Per the store-interface rule (0001 §2) the fix belongs upstream, not in a per-repo throwaway checkout here.

What this is not

Not a new capability letter (RFC 0004 §4 forbids inventing one). Not a change to what any letter means in fossil. Not portable: roles are how this forge writes strings; the strings are what travels.