- 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
- 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.
Open questions
- Should the moderation letters (
4,5,6) relax with posting, or stay the parent's? A companion taking outside contribution is exactly where moderation matters most, which argues for relaxing them together — but it also means a companion moderator who holds nothing on the parent. - Does a companion's relaxed grant survive unbinding? The store becomes a repository in its own right, and its grants would become its own. That is probably correct and should be said.
- Should the wiki be splittable for the same reason? 0015 declined on the grounds that nobody had asked. The policy argument is new evidence, not a request.