Model Grant kinds
Building a connector, step 4 of 10. Previous: Model entities.
A Grant kind is one kind of access the system has: group membership, a role assignment, a permission on a project. For each one you declare who can hold it, what it is on, which details distinguish one assignment from another, how Sync finds it, how access flows through it, and whether Owlie may add and remove it. The concepts are explained in the unified access model; this page is the procedure.
1. List every kind of access
List every access relationship the API exposes, whether or not you expect to model it: group, team, role, licence, permission set, application, workspace, project, organization and channel membership or assignment, admin roles, and roles scoped to a project, workspace or organization. Include operations that are Grant writes in disguise, such as "add collaborator" or "promote to admin". You will reject some of these in the next step; keep them on the list with the reason.
2. Map each one
For each kind of access you keep, decide:
- Principal and target.
sourceis the entity that normally holds the Grant (usually the account);principal_typeslists every entity that can hold it, when a group can hold it too, and must includesource.targetis the entity the access is on. - Qualifiers: the details the system records with the assignment, such as a role or a permission
level. Give each one a
name, aschema(string,enum,boolean,number,entity_refand others), whether it isrequired, and whether it is aslot_key: does this value distinguish assignments that can exist side by side? Anentity_refqualifier names the entity its value points to. An enum lists itsvalues. A string can have apatternandexamples; anchor a pattern that guards a URL path segment with^and$. - Discovery:
discovered_viais the entity whose listing returns the relationship, andfetch_modesays how.per-entitymeans Sync calls a relationship listing once per record of that entity (list the members of each group).embeddedmeans the relationship arrives on the entity's own records (each user record carries its department). - Inheritance:
membership,hierarchy,propagatesandvia_membership, decided with the table below.derivedmarks a read-only Grant kind your connector computes itself.
Deciding slots: if a user can have one permission per folder and changing it replaces the old one, the permission is a qualifier but not a slot key. If a user can hold several roles in the same application, each removable on its own, the role is a slot key.
Membership or hierarchy
Both mean "A is inside B". They differ in which direction access flows. With membership, A holds every Grant that B holds as a principal. With hierarchy, every propagating Grant on B also covers A. Decide from your own model, not from the word the system uses. The rows below are Grant kinds of Owlie's Google Workspace, Microsoft Entra ID and Workday connectors:
| Relationship | Does A inherit Grants that B holds? | Do propagating Grants on B cover A? | Flag |
|---|---|---|---|
| user in a Google Workspace group | yes, the admin roles assigned to the group | no | membership |
| user holding a Microsoft Entra ID directory role | yes, the permissions the role holds | no | membership |
| child organizational unit in its parent (Google) | no | yes, an admin role scoped to the parent unit, which propagates, covers it | hierarchy |
| worker in a Workday organization | no, the organization holds no Grant | no | neither |
If neither column is "yes", the Grant kind has neither flag. A hierarchy kind must form a tree: one
parent per entity. via_membership sets how far membership reaches: transitive (through nested
groups, the default), direct, or none.
3. Decide what Owlie may write
A Grant kind can be writable: true only when all of these hold:
- the API has both an add call and a remove call that your connector's credentials can use;
- Sync can list the Grants, so Owlie can see the result (a write Owlie cannot observe is a custom operation, not a Grant kind);
- you know whether an add replaces an existing assignment or sits beside it;
- the vendor documents what it answers for "already there" on add and "not there" on remove. Your connector reports those answers to Owlie, as Grant writes explains.
Owlie also refuses a writable Grant kind in a connector whose provides does not include
provision, and a Grant kind that is both derived and writable.
Owlie's policies assign Grants to accounts. A Grant kind whose principal is a group is still worth syncing and reviewing, but rarely worth making writable.
4. Record the design
Keep one table in your connector's README.md, one row per kind of access, rejected ones included:
| Kind of access | API calls (list / add / remove, with links) | Grant kind | Principal → target | Qualifiers | Discovery | Flags | Writable | "Already there" and "not there" answers | Scopes or roles needed | Status and reason |
|---|
A worked example
Take a fictional product, Fieldnote, that lets a user hold a role inside a specific organization, and the same user can hold the same role in another organization. The Grant kind puts the organization in a qualifier that is a slot key, so the two assignments are separate Grants:
{
"key": "organization_role",
"source": "user",
"principal_types": ["user"],
"target": "role",
"discovered_via": "organization",
"fetch_mode": "per-entity",
"writable": true,
"qualifiers": [
{
"name": "organization",
"schema": "entity_ref",
"entity": "organization",
"required": true,
"slot_key": true,
"source": "attrs.organization"
}
]
}
Sync lists each organization's members with their roles and emits one relationship per member role.
For member usr_alice holding role_viewer in org_A, the relationship names user usr_alice,
role role_viewer, and carries { "organization": "org_A" }, which becomes the qualifier.
Every Grant kind and qualifier field is in Connector manifest.
Rules that keep the model honest
- Keep state out of qualifiers. Expiry dates, justifications and who made a change are not part of the assignment. An expiry the system itself holds is observed state, not a qualifier.
- Never change what a published name means. A qualifier whose meaning changes gets a new name. Changing a Grant kind's principals, target or flags in a published version is a breaking change.
- Every writable Grant kind needs both its add and its remove, and a read-only one has neither. Owlie refuses a connector that breaks this rule.