ADR-0014: An operator enters a tenant by granting themselves¶
Status: Accepted; its last owner amended below Date: 2026-10-12 Deciders: Alex Nodeland
Amends ADR-0009.
Context¶
Lattice RFC-0001 says an operator doesn't see inside a tenant's workspaces, but can grant themselves a role there, in the audit log. Under ADR-0010's rules a grant needs grantr:grant on the resource and every action of the role, and an operator holds only grantr:create_tenant and grantr:grant_operator, on the deployment.
Decision¶
- An operator may grant themselves any role in an existing tenant.
grantsees that the grantee is the maker and that the maker holdsgrantr:grant_operator, and then skips the check ofgrantr:grantand the bound. - It makes them a member first, if they aren't one, and both steps are in the tenant's audit log, made by the operator.
- Anyone may give up a grant of their own, with no check: revoking it takes access away from no one else.
- A tenant keeps an owner: revoking, removing or deleting the last grant of
owneron a tenant is refused, so a tenant is never left unmanaged.
Options considered¶
| Option | For | Against |
|---|---|---|
| An operator's own grant, audited in the tenant (chosen) | What the RFC says; the tenant's admins see who entered | One exception to the bound |
Give operator every tenant action |
No exception | Puts operators inside every tenant, which ADR-0009 rules out |
| Operators ask an owner | No exception | A tenant with no reachable owner can't be helped |
Consequences¶
- Easier: an operator can step into a tenant to help, visibly, and leave by revoking their own grants.
- Harder:
granthas two paths, and the contract test covers both.
Amendment (2026-10-16): the last owner is a member who holds owner¶
"A tenant keeps an owner" counted grants of owner, and a grant to a group counts whoever is in the group, no one included. So once a group held the only other owner grant, a tenant could be left with no member who holds owner, and only an operator granting themselves a role could manage it again (lattice #253): define_group emptying the group, remove_member removing its only member, or revoke of the last owner grant a person held while an empty group held another.
- An owner is a member who holds
owneron the tenant, by a grant of their own or through a group's. A change that would leave none, where there was one, is refused asInvalid, naming the last owners. - Every command that can take it checks it:
revoke,remove_member,delete_group, and nowdefine_group, last, after the command's own checks and the bound, as before. - The exceptions stand. Anyone may give up a grant of their own, unless it leaves no owner, as before; an operator granting themselves a role is not checked, so an operator can still bring a tenant that has no owner back under management. A tenant that has no owner already, as one left so before this amendment, is not held to it, so its other changes go on until an operator steps in.
| Option | For | Against |
|---|---|---|
| Count the members who hold owner (chosen) | What "never left unmanaged" means; one rule for every command | A command reads the owner grants' groups |
| Refuse an owner grant to a group | Grants stay countable | Takes away a way of sharing ownership that works |
Keep counting grants, and check define_group too |
Smallest change | An empty group's grant still counts, so revoke and remove_member still leave no owner |
Consequences: the access state machine's invariant is now that a member holds owner, through a group or not, and its model refuses what grantr refuses. Portalr's grants page still hides only the revoke of the last owner grant, so a refusal there comes from grantr, as Invalid.