Understand how Oso uses facts
Every authorization decision in Oso combines:- Your policy (written in Polar): the logic that defines who can do what.
- Facts: the current state of your application that the policy uses to decide.
- Centralized facts in Oso Cloud.
- Context facts sent with the request.
- Local facts queried from your application database (if using Local Authorization).
- Check API: performs authorization decisions using data stored in your centralized authorization data store. Available via CLI and SDKs for Node, Python, Go, Java, Ruby, and .NET.
- Local Check API: performs checks using your local facts while still considering centralized authorization data. See Local Authorization for details.
Know the fact structure
A fact has:- Name (predicate) — usually in
verb_objectform for readability, e.g.has_role,has_relation,is_public. - Arguments — 1-5 arguments, each either:
- A typed ID reference to an application object:
User{"alice"}. - A literal value:
"admin",42.
- A typed ID reference to an application object:
Choose where to store facts
| Data Type | Storage Recommendation |
|---|---|
| Affects multiple services | Store in Oso Cloud. |
| Single-service only | Keep in your application DB. |
| Changes frequently | Keep in your application DB. |
| High cardinality (e.g. millions of files) | Keep in your application DB. |
Global attributes (e.g. is_superadmin, is_banned) | Store in Oso Cloud. |
| Ephemeral/request-specific (e.g. IP, time of day) | Send as context facts. |
Centralize shared facts in Oso Cloud
Centralized facts are optimized for authorization lookups and can be faster than application DB queries.When to centralize
- Organization/resource roles:
has_role(User, "admin", Organization). - Global flags:
is_superadmin(User),is_banned(User).
Manage facts with the API
| Action | API Names | Notes |
|---|---|---|
| Transaction | batch, bulk | Atomic inserts/deletes (recommended). |
| Write | insert, tell | Add facts. |
| Delete | delete | Remove facts. |
| Read | get | Fetch centralized facts (no inference). |
Pass context facts for request-specific data
Context facts exist only for the duration of a request. Use them for:- External data (e.g. IDP token claims).
- Ephemeral attributes (e.g.
is_weekend,request_came_from_eu).
Reference facts in Polar policies
Validate and declare fact types
Oso infers fact types from policy usage:are_friends(User, Dog) will be accepted.
Invalid facts (wrong type, missing args, misspelled predicates) are rejected.
Declare unused types explicitly:
Keep facts in sync
Keep centralized facts in sync with your application database:- Insert: When adding roles, relationships, or attributes.
- Delete: When removing them.
- Bulk operations: For initial loads or periodic sync.
- Use transactional APIs (
batch,bulk) to apply multiple changes atomically.
- Invite collaborator →
insert has_role(User{"coder"}, "collaborator", Repo{"anvils"}). - User leaves org →
delete has_role(User{"alice"}, "member", Org{"acme"}).
Facts in different authorization models
Facts can represent:- RBAC. Role assignments:
has_role(User, "admin", Org). - ABAC. Attributes:
has_department(User, "engineering"). - ReBAC. Relationships:
has_relation(Document, "folder", Folder).