Fine-Grained Auth
Data Model
Resources, subjects, roles, permissions, and grants.
FGA has five pieces. Learn how they connect. Then model your app.
Resources#
A resource is a node in a tree. Every resource has a type, a parent (except root), and a name.
// SqlOSFgaResource
{
Id: "chain_walmart",
ParentId: "org::acme",
Name: "Walmart",
ResourceTypeId: "chain"
}Resources form a tree. Grants on a parent apply below it. Resource hierarchy.
Subjects#
A subject is the entity being authorized. SqlOS supports four subject types:
| Type | Use case |
|---|---|
user | Human users synced from AuthServer |
agent | Automated bots or AI agents |
service_account | Service-to-service access with API keys |
user_group | Groups of users sharing permissions |
See Subject Types.
Roles#
A role bundles permissions. Name them to match how your app works:
| Role | Permissions |
|---|---|
| Company Admin | CHAIN_VIEW, CHAIN_EDIT, LOCATION_VIEW, LOCATION_EDIT, INVENTORY_VIEW, INVENTORY_EDIT |
| Store Manager | LOCATION_VIEW, LOCATION_EDIT, INVENTORY_VIEW, INVENTORY_EDIT |
| Store Clerk | INVENTORY_VIEW |
See Roles.
Permissions#
A permission is a string key for one resource type. Common style: RESOURCETYPE_ACTION in caps.
| Permission | Resource type | Action |
|---|---|---|
CHAIN_VIEW | chain | Read |
CHAIN_EDIT | chain | Write |
LOCATION_VIEW | location | Read |
INVENTORY_EDIT | inventory | Write |
See Permissions.
Grants#
A grant = subject + role + resource. Parent grant flows down the tree to children.
Subject: "jane"
Role: "Company Admin"
Resource: "org::acme"
→ jane can CHAIN_VIEW, CHAIN_EDIT on all chains under org::acme
→ jane can LOCATION_VIEW, LOCATION_EDIT on all locations under those chains
→ jane can INVENTORY_VIEW, INVENTORY_EDIT on all inventory itemsSee Grants.
How authorization works#
Example: check CHAIN_VIEW on chain_walmart.
- Load grants for the subject.
- See if any role on the path includes
CHAIN_VIEW. - Walk up:
chain_walmart→org::acme→root. - Match on any ancestor? Allow.
SQL Server runs this as a TVF. EF uses it in Where. No giant loads into memory.