A role is a ceiling, never a grant. Naming cfo on a grant does not hand anyone spend authority — it states the most that grant may carry. What the grantee ends up holding is the intersection of three things, and the role can only ever shrink it:
effective = requested ∩ what the grantor holds ∩ the role's ceiling
That is why roles here are ceilings rather than templates. A template hands out capabilities, which makes the role a source of privilege — an agent could name a role and come away with more authority than whoever granted it. A ceiling cannot do that, by construction: it only ever appears on the narrowing side.
ceo
May carry spend authority
Ceiling: pay:*
delegating budget is this role's actual function; bounded to pay so a capability verb added later is not retroactively pre-authorised
cto
Cannot carry spend authority, ever
Ceiling: nothing — every capability requested under this role is refused
NO SPEND, EVER. The engineering role holds no pay capability at any denomination — the agent writing the code cannot move the money, whatever it asks for or its grantor holds
cfo
May carry spend authority
Ceiling: pay:*
the money role; same spend ceiling as CEO, distinguished by who may mint it
cmo
Cannot carry spend authority, ever
Ceiling: nothing — every capability requested under this role is refused
NO SPEND, EVER. Same reasoning as CTO: publishing authority is not spending authority
The ceilings are narrow because the capability vocabulary this system actually enforces is narrow: it is essentially pay:* and its denominations. Inventing deploy:* or publish:* would read as governance and enforce air. The useful thing these say today is the negative one — and it is enforceable right now: the agent writing your code cannot move your money, whatever it asks for and whatever its grantor holds.
The role field accepts free text, because grants already carry human labels like “Researcher / Data” and refusing those would break live authority to no benefit. What must never happen is a reader taking an unrecognised string for a boundary. So a role resolves to one of three states, and they are rendered differently everywhere they appear:
When this page or a grant listing cannot reach the catalog, a role shows as not checked rather than as a label — because “the backend does not recognise this name” is a measurement, and claiming it from a failed request would be inventing the reassuring half of an answer nobody got.