Documentation Index
Fetch the complete documentation index at: https://www.osohq.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
The ReBAC pattern organizes permissions based on relationships between resources. For example, granting a user access to a folder automatically grants access to its files.
When to use ReBAC: You need to grant permissions on resources based on their relationship to users or other resources.
Files & folders pattern
The most common ReBAC pattern cascades permissions through nested resources like files in folders, and folders in repositories.
actor User { }
resource Repository {
roles = ["reader", "maintainer"];
}
resource Folder {
roles = ["reader", "writer"];
relations = {
repository: Repository,
folder: Folder,
};
"reader" if "reader" on "repository";
"writer" if "maintainer" on "repository";
role if role on "folder";
}
resource File {
permissions = ["read", "write"];
roles = ["reader", "writer"];
relations = {
folder: Folder,
};
role if role on "folder";
"read" if "reader";
"write" if "writer";
}
test "folder roles apply to files" {
setup {
has_role(User{"alice"}, "reader", Repository{"anvil"});
has_relation(Folder{"python"}, "repository", Repository{"anvil"});
has_relation(Folder{"tests"}, "folder", Folder{"python"});
has_relation(File{"test.py"}, "folder", Folder{"tests"});
}
assert allow(User{"alice"}, "read", File{"test.py"});
}
How it works:
- Repository readers get reader role on all folders
- Repository maintainers get writer role on all folders
- Users inherit roles recursively through nested folders
- Files inherit roles from their parent folder
User-resource relationships
Grant special permissions based on relationships between users and resources. In this example, issue creators can update their own issues, but only repository maintainers can close any issue.
actor User { }
resource Repository {
roles = ["maintainer"];
}
resource Issue {
roles = ["reader", "admin"];
permissions = ["read", "comment", "update", "close"];
relations = { repository: Repository, creator: User };
# repository maintainers can administer issues
"admin" if "maintainer" on "repository";
"reader" if "admin";
"reader" if "creator";
"read" if "reader";
"comment" if "reader";
"update" if "creator";
"close" if "creator";
"close" if "admin";
}
test "issue creator can update and close issues" {
setup {
has_relation(Issue{"537"}, "repository", Repository{"anvil"});
has_relation(Issue{"42"}, "repository", Repository{"anvil"});
has_relation(Issue{"537"}, "creator", User{"alice"});
}
assert allow(User{"alice"}, "close", Issue{"537"});
assert allow(User{"alice"}, "update", Issue{"537"});
assert_not allow(User{"alice"}, "close", Issue{"42"});
}
test "repository maintainers can close issues" {
setup {
has_relation(Issue{"537"}, "repository", Repository{"anvil"});
has_relation(Issue{"42"}, "repository", Repository{"anvil"});
has_relation(Issue{"537"}, "creator", User{"alice"});
has_role(User{"bob"}, "maintainer", Repository{"anvil"});
}
assert allow(User{"bob"}, "close", Issue{"537"});
assert_not allow(User{"bob"}, "update", Issue{"537"});
assert allow(User{"bob"}, "close", Issue{"42"});
}
Bidirectional role inheritance
Sometimes you need roles to flow both ways between resources. Child resources can inherit from parents, and parents can inherit from children.
This pattern requires writing longhand rules instead of using the relations feature.
actor User {}
resource ParentResource {
roles = ["admin", "member"];
permissions = ["read", "write"];
"read" if "member";
"write" if "admin";
"member" if "admin";
}
resource ChildResource {
roles = ["admin", "member"];
permissions = ["read", "write"];
relations = { parent: ParentResource };
"read" if "member";
"write" if "admin";
"member" if "admin";
# ChildResource inherits admin from ParentResource
"admin" if "admin" on "parent";
}
# ParentResource inherits member from ChildResource
has_role(user: User, "member", parent_resource: ParentResource) if
child_resource matches ChildResource and
has_role(user, "member", child_resource) and
has_relation(child_resource, "parent", parent_resource);
test "inherit role on parent from child" {
setup {
has_relation(ChildResource{"anvil"}, "parent", ParentResource{"acme"});
has_role(User{"alice"}, "member", ChildResource{"anvil"});
}
assert allow(User{"alice"}, "read", ParentResource{"acme"});
}
ReBAC patterns
ReBAC patterns solve complex authorization scenarios by modeling real-world relationships.
| Pattern | Description |
|---|
| User groups | Controlling permissions by membership in a group |
| Impersonation | Allowing one user to inherit a subset of another user’s permissions |
| Organization hierarchies | Cascading permissions through user relationships |
Next steps
With your ReBAC policy defined:
- Add facts: Store resource attributes and user context in Oso Cloud
- Make authorization requests: Check permissions in your application code
- Test scenarios: Verify policies work with different relationship combinations