Entity Relationships
Cedar's entity model supports hierarchical relationships that map naturally to real-world authorization patterns.
Entity Hierarchy
The in keyword creates parent-child relationships:
entity Document in [Folder] {}
This allows policies to express containment:
permit (principal, action, resource)
when { resource in principal.folders };
Multiple Parents
Entities can have multiple parent types:
entity File in [Folder, Project, SharedDrive] {}
A File instance can be in any combination of these parents.
Transitive Containment
Cedar's in operator is transitive. If:
- Document D is in Folder F
- Folder F is in Workspace W
Then D in W is true.
This enables natural hierarchical policies:
// Workspace access implies access to all folders and documents
permit (principal, action == DocShare::Action::"Document::Read", resource)
when { resource in principal.workspaces };
Entity Attributes
Entities can have attributes for fine-grained conditions:
entity Document in [Folder] {
owner: User,
editors: Set<User>,
locked: Bool,
classification: String
}
Use attributes in policy conditions:
permit (principal, action == DocShare::Action::"Document::Write", resource)
when {
principal in resource.editors &&
resource.locked == false
};
Generated Entity Classes
cedar4s generates case classes for each entity:
// Generated from schema
object Entities {
case class Document(
id: String,
folderId: String, // From `in [Folder]`
owner: String,
editors: Set[String],
locked: Boolean,
classification: String
)
}
Your EntityFetcher implementation creates these from your domain models.
Parent Resolution
When you use deferred checks (.on(id)), cedar4s resolves parent IDs automatically:
// cedar4s calls your DocumentFetcher, extracts folderId
import myapp.cedar.MyApp.*
Document.Read.on(documentId).require
The EntityStore uses the generated entity's parent fields to build the complete resource reference.