ADR-0024: Who sees a restricted item¶
Status: Accepted Date: 2026-10-12 Deciders: Alex Nodeland
Amends ADR-0003, generalizing who sees a restricted item from its roles to grantr:restrict, and ADR-0015 and ADR-0016.
Context¶
ADR-0003 makes a thread or artifact visible to its workspace unless it is restricted, and a restricted one visible only to those granted a role on it, the workspace's admins, and the tenant's owners and admins. It names people by built-in role. A tenant's custom roles, the application's principal and the agent acting for no one need a rule too, and the flag needs a place to live and a command that sets it.
Decision¶
- On a restricted item, a grant around it holds only if its role holds
grantr:restrict. Grants on the item itself hold as ever. The built-in roles that hold it are the workspace'sadminand the tenant'sownerandadmin, so ADR-0003's list follows, and a custom role follows the same rule: who may restrict an item sees it. hiddenis the check's rule over a workspace's restricted items: each one on which the subject holds nothing. The application's own principal, holdingapplication, sees everything, as relayr and reflexr act for the whole deployment; the agent acting for no one sees no restricted item.resourcesfollows the same rule, so a listing of threads or artifacts leaves out those the subject can't see.Grants.restrict(tenant, on, restricted=..., by=...)sets or clears the flag, and needsgrantr:restricton the item. Only a thread or artifact is restricted, and a change that changes nothing isInvalid. It recordsRestrictedorUnrestricted.restrictions(tenant, workspace, by=...)lists a workspace's restricted items, withgrantr:restricton it.- grantr doesn't know whether an item exists, so the application checks it with artifactr, reading the thread or artifact as the caller, before it restricts one.
- The flag is a row in
grantr_resources, keyed by the tenant and the item, which makes the item known to grantr (ADR-0015). A check on a thread or artifact reads it by primary key;hiddenreads a workspace's by an index on the tenant, workspace and flag. Deleting a tenant deletes its rows.
Options considered¶
| Option | For | Against |
|---|---|---|
| Ancestor grants hold if their role may restrict (chosen) | One rule for built-in and custom roles; who may lift a restriction already sees what it hides | A custom role with grantr:restrict sees every restricted item where it is granted |
| Name the built-in roles that see through | Exactly ADR-0003's words | A custom admin role is blind to what it restricts |
| The item's creator restricts it too (lattice RFC-0001's open question) | Whoever starts a private thread can close it | grantr doesn't know who created an item; an application can grant its creator a custom role holding grantr:restrict on it instead |
A separate see_restricted action |
Seeing and restricting apart | One more action for every catalog and matrix, with no request for it |
Consequences¶
- Easier: the matrix says who sees restricted items, in the
grantr:restrictcolumn. - Harder: a check on a thread or artifact reads one more row, by primary key, when some grant that applies is around it rather than on it.
- Harder:
hiddenreads a workspace's restricted items on every read, and the subject's grants only when there are any. - Harder: a stored rule, which holds
ruleon its workspace, and a service principal acting with a key, don't see a restricted item unless granted a role on it.