Skip to main content

What are Resource Hierarchies?

Resource hierarchies allow you to model parent-child relationships between resources. A folder contains documents, a project contains tasks, an order contains line items. These relationships enable hierarchical permission propagation and structured queries.

Hierarchy Edge Properties

PropertyTypeDescription
parentResourceIdstringThe parent resource
childResourceIdstringThe child resource
relationshipTypestring?Type of relationship (e.g., “contains”, “references”)
cascadeCascadeModeEnumPermission inheritance: inherit or none
createdAtstringWhen the relationship was created

Cascade Modes

The cascade property controls how permissions propagate through the hierarchy:

Inherit

Permissions on the parent automatically apply to the child:
curl -X POST 'https://api.example.com/resource-hierarchy' \
  -d '{
    "parentResourceId": "resource_folder_123",
    "childResourceId": "resource_doc_456",
    "relationshipType": "contains",
    "cascade": "inherit"
  }'
With cascade: "inherit":
  • If a user can read the folder, they can read documents inside
  • Permissions flow down the hierarchy automatically
  • Ideal for folder/document, project/task relationships

None

No permission inheritance—child resources require explicit access:
curl -X POST 'https://api.example.com/resource-hierarchy' \
  -d '{
    "parentResourceId": "resource_issue_1",
    "childResourceId": "resource_issue_2",
    "relationshipType": "references",
    "cascade": "none"
  }'
With cascade: "none":
  • Parent access does not grant child access
  • Each resource requires its own permissions
  • Ideal for references, links, dependencies

Creating Resource Hierarchies

# Create a folder
curl -X POST 'https://api.example.com/resources' \
  -d '{
    "resourceTypeId": "rtype_folder",
    "scopeId": "scope_engineering",
    "externalResourceId": "folder-123",
    "displayName": "Engineering Docs"
  }'

# Create a document
curl -X POST 'https://api.example.com/resources' \
  -d '{
    "resourceTypeId": "rtype_document",
    "scopeId": "scope_engineering",
    "externalResourceId": "doc-456",
    "displayName": "API Design Doc"
  }'

# Link document to folder
curl -X POST 'https://api.example.com/resource-hierarchy' \
  -d '{
    "parentResourceId": "resource_folder_123",
    "childResourceId": "resource_doc_456",
    "relationshipType": "contains"
  }'

Resource Type Hierarchies

Before creating resource hierarchies, define which resource types can contain which:
# Folders can contain Documents
curl -X POST 'https://api.example.com/resource-type-hierarchy' \
  -d '{
    "parentTypeId": "rtype_folder",
    "childTypeId": "rtype_document"
  }'

# Folders can contain Folders (nested)
curl -X POST 'https://api.example.com/resource-type-hierarchy' \
  -d '{
    "parentTypeId": "rtype_folder",
    "childTypeId": "rtype_folder"
  }'

# Projects can contain Tasks
curl -X POST 'https://api.example.com/resource-type-hierarchy' \
  -d '{
    "parentTypeId": "rtype_project",
    "childTypeId": "rtype_task"
  }'

Hierarchical Permission Patterns

Pattern 1: Folder Access Grants Document Access

When a user can access a folder, they can access its contents:
// Check if user can read the folder
const folderAccess = await bedrock.evaluate({
  actor: { subjectId: "subject_jane", subjectType: "user" },
  scopeId: "scope_engineering",
  action: "read",
  resource: { resourceId: "resource_folder_123" }
});

// If folder access granted, documents inside are also accessible
if (folderAccess.allowed) {
  // User can read documents in this folder
}

Pattern 2: Inherited Permissions

Define permissions that propagate through the hierarchy:
# Permission to read folder and all contents
curl -X POST 'https://api.example.com/permissions' \
  -d '{
    "scopeId": "scope_org",
    "action": "read",
    "resourceType": "folder",
    "resourcePattern": "*",
    "key": "folder:read:*",
    "label": "Read Folder and Contents",
    "logic": {
      "or": [
        {"==": [{"var": "resource.type"}, "folder"]},
        {"in": [{"var": "resource.parentId"}, {"var": "subject.accessibleFolders"}]}
      ]
    }
  }'

Common Hierarchy Patterns

Document Management

Workspace
└── Folder
    ├── Document
    │   └── Comment
    └── Folder (nested)
        └── Document
# Define type hierarchy
curl -X POST 'https://api.example.com/resource-type-hierarchy/batch' \
  -d '[
    {"parentTypeId": "rtype_workspace", "childTypeId": "rtype_folder"},
    {"parentTypeId": "rtype_folder", "childTypeId": "rtype_folder"},
    {"parentTypeId": "rtype_folder", "childTypeId": "rtype_document"},
    {"parentTypeId": "rtype_document", "childTypeId": "rtype_comment"}
  ]'

Project Management

Project
├── Epic
│   └── Issue
│       └── Subtask
└── Sprint
    └── Issue (linked)

E-Commerce

Store
└── Category
    └── Product
        ├── Variant
        └── Review

Construction

Job Site
├── Work Order
│   └── Task
└── Daily Log
    └── Entry

Querying Hierarchies

# Get children of a resource
curl -X GET 'https://api.example.com/resources/resource_folder_123/children'

# Get parent of a resource
curl -X GET 'https://api.example.com/resources/resource_doc_456/parent'

# Get all descendants (recursive)
curl -X GET 'https://api.example.com/resources/resource_folder_123/descendants'

Relationship Types

Use relationshipType to distinguish different kinds of relationships:
TypeUse Case
containsParent physically contains child (folder → document)
referencesParent references child (issue → linked issue)
ownsParent owns child (user → created documents)
depends-onParent depends on child (task → blocking task)
# Different relationship types
curl -X POST 'https://api.example.com/resource-hierarchy/batch' \
  -d '[
    {"parentResourceId": "folder_1", "childResourceId": "doc_1", "relationshipType": "contains"},
    {"parentResourceId": "issue_1", "childResourceId": "issue_2", "relationshipType": "references"},
    {"parentResourceId": "task_1", "childResourceId": "task_2", "relationshipType": "depends-on"}
  ]'

Best Practices

Always define resource type hierarchies before creating resource instance hierarchies.
Choose relationship types that reflect your domain model.
Very deep hierarchies can impact query performance. Consider flattening when possible.
Plan how permissions will propagate through your hierarchy before building it.

Ancestor Traversal

When evaluating permissions with cascade: "inherit", the engine traverses ancestors:
# Get all ancestors of a resource
curl -X GET 'https://api.example.com/resource-hierarchy/ancestors/resource_doc_456'
Response:
[
  {
    "id": "resource_folder_123",
    "displayName": "Engineering Docs",
    "cascade": "inherit"
  },
  {
    "id": "resource_workspace_root",
    "displayName": "Workspace",
    "cascade": "inherit"
  }
]
The evaluation engine checks permissions on each ancestor until access is granted or all ancestors are exhausted.

Next Steps