Artifact a3b83f7a6c5a8223194b386cda7b0dc18a19640f87663915eb56f5bc1ef83fab:
- File docs/rfcs/0017-write-tiers.md — part of check-in [f4ffa17411] at 2026-09-12 23:13:29 on branch rfc0017-decided — RFC 0017: settle which letters relax, what unbinding does, and the wiki scope (user: dmestas, size: 10992) [annotate] [blame] [check-ins using]
- Feature Name:
write-tiers(the bar for a write scales with how permanent the write is; a tier that costs less may ask less) - Start Date: 2026-09-12
- Status: Draft; its three open questions are settled (see the last three sections). Implementation follows teams (ticket 8318bd2819ca), by decision: teams ships against the store tier first, and the companion half of its membership floor arrives with this RFC.
- Depends on: RFC 0004 (capability letters are the native model); RFC 0001 §8 (the OLTP tier is forge-local state, the DAG is truth); RFC 0015 (companions — this RFC amends §"What the parent keeps"); RFC 0008 (roles as the interface over the letters)
- Amends: RFC 0015, which says the companion's name never reaches a gate. It reaches one here, for writes only.
- Precedent: local tickets already exist as a lower tier
(
docs/local-tickets.md,local_ticket,ticket.intake), with the explicit rationale that an append-only artifact history "has no answer but 'it is in there now'". This RFC states the rule that tier was an instance of.
Summary
quarry stores writes in three places with wildly different costs, and asks the same price for all of them.
A check-in, a ticket artifact, a wiki page and a forum post in the repository's own store are permanent, synchronized to every clone, and unsayable-again. A post in a companion store is permanent but separable — it is not in the store anybody clones for the code. A local ticket is in the forge's database: mutable, deletable, and carried by nobody.
Those are not the same act, and requiring the same authority for all three has a visible consequence: a project that wants to take outside contribution has to choose between letting strangers write its DAG and letting them do nothing at all.
This RFC states one rule — the bar may differ per tier, and a tier that costs less may ask less — and applies it to the two tiers that exist. It introduces no new capability letter.
The tiers, and what a write costs in each
| tier | where | permanence | who carries it |
|---|---|---|---|
| store | the repository's own DAG | permanent, unsayable | everyone who clones |
| companion | a bound store (RFC 0015) | permanent, separable | whoever clones that |
| local | forge OLTP | mutable, deletable | nobody |
The ordering is the whole RFC. A store write is the most expensive thing a stranger can do to a project, because it is the one nobody can undo and everybody downloads. A companion write is permanent but costs the code store nothing: it does not enter the repository people clone to build, it does not grow the artifact history CI walks, and it can be detached. A local write costs almost nothing and can be discarded.
So the bar should follow the cost. Anything else is either too generous at the top — strangers writing the DAG — or too mean at the bottom, which is where quarry is today.
Rule
An authority that governs writes MAY be set per tier. A lower tier MAY hold a lower bar than the tier above it. A lower tier MUST NOT be able to raise the bar of the tier above it, and MUST NOT be able to grant anything the tier above it denies about visibility.
Two halves, and the second is what keeps it safe.
Writes may relax downward. A companion may let more people post than the parent lets push. The local tier may let more people file than the store lets mint.
Visibility never relaxes. Whether a reader may know a repository exists, and read it, stays the parent's answer in every tier. Otherwise a private repository's companion becomes a side door: bind a forum, grant a stranger, and they learn the repository exists and can read discussion of code they cannot see. RFC 0015 already says the parent answers "a name they may not see", and that does not change.
The rule is a union, like every other authority in quarry (RFC 0004): a tier adds letters, never subtracts them. A relaxed companion cannot take posting away from somebody the parent already granted it to.
What changes in RFC 0015
0015 §"What the parent keeps" currently says every forum question — may this account post, reply, moderate, announce — is answered by the parent's capability set, and that the companion's name never reaches the gate. That is amended to split the question:
- Read and visibility stay exactly as specified: answered by the parent, through the parent's name, including its not-found answer.
- Write letters — post, reply, attach, and the moderation letters above them — become the union of the parent's and the companion's own.
So the companion gains what 0015 §"What the companion gets" does not currently list: its own grants, for writes only. It still has no identity model of its own; accounts remain forge-global, and the companion's People surface is a section on the parent's settings page rather than a page on a store that has no page.
This is the point of a companion that 0015 did not state. 0015 justifies the separation on lease contention and store size — "a busy thread never waits on a push". The other reason is policy: it is a lower burden to take outside contribution somewhere that is not the store holding the code, and until a companion can hold a lower bar, that reason is unavailable.
forum.bind therefore becomes an access decision and not only an
operational one, and must say so where it is offered.
What changes for local tickets
ticket.intake (local) and ticket.new (store) both gate on n, so
the local tier cannot be more relaxed than the store today. The letter
n means "file tickets", and fossil had one tier to file into.
n becomes the store door and only the store door. ticket.intake
gates on r — read tickets — on the reasoning that quarry's local tier
is deletable and promotable, so the bar for filing into it should be
"you can see the tracker", not "you may write the DAG".
Practically this changes little for existing deployments: fossil's stock
nobody category holds r, so anonymous intake on a public project
behaves as before. What it makes possible is a repository that takes
tickets from anyone while minting nothing in its store until an admin
promotes one — which is what the local tier was built for and could not
express.
No new capability letter
The tempting shape is a new letter meaning "may mint a permanent object
in this store", gating ticket.new, forum.post and wiki creation.
quarry has invented a letter before — 8, for CI, on the grounds that
fossil has no CI and an unused digit cannot collide with an imported
user table.
It is rejected here. Every existing grant holding 3 or n would lose
thread and ticket creation until backfilled, and Reader — which holds
3 — would silently become reply-only. A migration that changes what
an existing role means is a poor trade for a distinction the tiers
already draw structurally: a write's tier is a property of where it
lands, which the forge knows without asking the letters.
What this does not propose
- A separate identity model for any tier. Accounts stay forge-global.
- Any relaxation of read or visibility anywhere.
- A companion for anything but the forum. 0015 defines one feature and this RFC adds none.
- Moving existing artifacts between tiers. Promotion (local → store) exists; demotion does not and is not proposed.
- Letting a tier restrict. Every tier adds.
Consequences to state plainly
Three routes to one authority. A person may hold a letter directly, through a category, or through a lower tier's own grant. Any page that answers "who may do this" must name the route, not just the result — the same obligation the union rule already creates elsewhere.
Binding a forum widens who may post. That is the feature, and it must be said at the moment of binding rather than discovered afterwards.
A relaxed companion is still permanent. Separable is not deletable: a companion's history is a DAG like any other, and shunning is the only removal. The local tier is the one that forgets.
Which letters a companion may relax
Posting relaxes. Judgement does not.
| letter | what it is | relaxes? |
|---|---|---|
3 |
post in the forum | yes |
B |
attach files to forum posts | yes |
4 |
post without moderation | yes |
5 |
moderate the forum | no |
6 |
grant moderation exemptions | no |
4 relaxes because it is about the contributor: a companion exists to
take outside contribution, and a queue nobody can clear is not an open
door. Deciding what gets removed (5) and who is trusted to skip the
queue (6) is judgement about the project, and judgement stays with
people who hold something on the parent.
The consequence, stated rather than discovered: a companion can be relaxed to the point where anybody may post unmoderated, and only somebody with standing on the parent can then take a post down. A project that wants community moderation of a community forum cannot have it under this rule. That is deliberate — a moderator who holds nothing on the parent can shape what the project's forum says about the project — and it is the one place this RFC chooses the cautious side.
Unbinding drops the relaxed grants
When a companion is unbound it becomes a repository in its own right, and the grants it held as a companion are removed, not inherited.
The argument for inheriting them is that nothing is lost and nobody is surprised. It was rejected: a grant made in the context of "this is X's forum, and the bar here is low because it is not X's code" does not obviously mean the same thing once the store is a repository of its own. Carrying it over would silently turn a relaxed forum grant into a standing grant on a new repository.
Dropping them is the safe direction — it removes access rather than creating it — but it is not a quiet operation, and the surface must not treat it as one. Unbinding MUST name who loses access before it happens. The forge knows exactly who: the accounts holding a write grant on that store. A confirmation that lists them is the difference between a decision and an accident.
The wiki stays whole, for now
RFC 0015 declined to split the wiki because nobody had asked. The policy
argument in this RFC is new evidence rather than a request, so the scope
does not change: forum remains the only companion feature.
Recorded so the next person does not have to rediscover it: the wiki could be split on exactly these grounds, and the reason not to is that the demand is hypothetical, not that the rule fails to reach it. The wiki's tabs, search and embedded-docs surfaces all assume one store, so the work is larger than the forum split was and should be paid for by a real want.
Open questions
None outstanding. Three questions this RFC opened were settled above: which letters relax, what unbinding does, and whether the wiki follows.