Auth
The server uses Oso Cloud for authorization. Every mutation and sensitive query is protected by auth guards that check permissions against the Oso Cloud policy engine.
OsoClient
Section titled “OsoClient”Wrapper around the Oso Cloud SDK:
pub struct OsoClient { client: oso_cloud::Oso,}
impl OsoClient { pub fn new(url: &str, api_key: &str) -> Self;
pub async fn authorize(&self, actor: &str, action: &str, resource: &str) -> Result<bool>; pub async fn tell(&self, fact: &str, args: &[&str]) -> Result<()>; pub async fn delete(&self, fact: &str, args: &[&str]) -> Result<()>; pub async fn bulk_tell(&self, facts: Vec<(String, Vec<String>)>) -> Result<()>; pub async fn bulk_delete(&self, facts: Vec<(String, Vec<String>)>) -> Result<()>; pub async fn bulk(&self, tells: Vec<...>, deletes: Vec<...>) -> Result<()>; pub async fn query(&self, fact: &str, args: &[&str]) -> Result<Vec<...>>;}Guards
Section titled “Guards”Two async-graphql guards protect resolvers:
SignedIn
Section titled “SignedIn”Checks that an AuthUser exists in the GraphQL context (set from X-Uid header):
pub struct SignedIn;
impl Guard for SignedIn { async fn check(&self, ctx: &Context<'_>) -> Result<()> { ctx.data::<AuthUser>() .map(|_| ()) .map_err(|_| "Unauthorized".into()) }}HasPermission
Section titled “HasPermission”Checks Oso Cloud authorization for a specific action on a resource:
pub struct HasPermission { action: String, id_arg: String, // which GraphQL argument contains the resource ID}
impl HasPermission { pub fn new(action: &str) -> Self; pub fn with_id_arg(action: &str, id_arg: &str) -> Self;}Usage in resolvers:
#[graphql(guard = "SignedIn.and(HasPermission::new(\"read\"))")]async fn resource(&self, ctx: &Context<'_>, id: ID) -> Result<Resource> { // ...}
#[graphql(guard = "SignedIn.and(HasPermission::with_id_arg(\"delete\", \"resource_id\"))")]async fn delete_resource(&self, ctx: &Context<'_>, resource_id: ID) -> Result<bool> { // ...}Fact Management
Section titled “Fact Management”Authorization repos manage Oso Cloud facts alongside database writes. Facts are written before database operations (Oso-first ordering).
ResourceAuthRepo
Section titled “ResourceAuthRepo”Manages resource ownership and sharing facts:
tell("has_role", [user, "owner", resource])on createdelete("has_role", [user, "owner", resource])on deletetell("has_role", [user, permission, resource])on share
FolderAuthRepo
Section titled “FolderAuthRepo”Manages folder ownership facts:
tell("has_role", [user, "owner", folder])on createdelete("has_role", [user, "owner", folder])on delete
AuthUser
Section titled “AuthUser”Extracted from HTTP headers in the GraphQL handler:
pub struct AuthUser { pub id: String,}The handler checks X-Impersonate-Uid first (for admin impersonation), falling back to X-Uid.