> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bedrock.quarry-systems.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Resource Collections

> Dynamic grouping of resources using match rules

## What are Resource Collections?

**Resource Collections** dynamically group resources based on match rules. Instead of manually adding resources to a group, you define criteria and any matching resources are automatically included.

Collections are powerful for:

* Applying policies to groups of resources
* Querying resources by attributes
* Building dynamic access control rules

## Collection Properties

| Property         | Type                      | Description                          |
| ---------------- | ------------------------- | ------------------------------------ |
| `id`             | `string`                  | Unique identifier                    |
| `scopeId`        | `string`                  | Scope where collection is defined    |
| `resourceTypeId` | `string`                  | Type of resources in this collection |
| `name`           | `string`                  | Display name                         |
| `match`          | `ResourceMatchDefinition` | Rules for matching resources         |

<Note>
  Supported match operators: **`fields`** — `eq`/`ne`/`gt`/`gte`/`lt`/`lte`/`in`/`nin`/`contains`/`startsWith`/`endsWith`/`regex` (plus bare-value equality, e.g. `{"status": "active"}`); **`time`** — `before`/`after`/`between` (absolute ISO timestamps); **`patterns`** — matched as a **regex** (`new RegExp`), not a glob; plus **`tags`**, **`condition`** (json-logic), and the **`any`/`all`/`none`** combinators.
</Note>

## Match Definition

The `match` object defines how resources are matched:

```typescript theme={null}
interface ResourceMatchDefinition {
  // Match by field values
  fields?: Record<string, unknown>;
  
  // Match by tag assignments
  tags?: Record<string, string | string[]>;
  
  // Match by glob patterns
  patterns?: Record<string, string>;
  
  // Match by time-based rules
  time?: TimeMatchRule;
  
  // Match by JSON Logic condition
  condition?: Record<string, unknown>;
  
  // Combine multiple definitions (OR)
  any?: ResourceMatchDefinition[];
  
  // Combine multiple definitions (AND)
  all?: ResourceMatchDefinition[];
  
  // Exclude matching definitions (NOT)
  none?: ResourceMatchDefinition[];
}
```

## Creating Collections

### Match by Fields

```bash theme={null}
# All active documents
curl -X POST 'https://api.example.com/resource-collections' \
  -H 'Content-Type: application/json' \
  -d '{
    "scopeId": "scope_org",
    "resourceTypeId": "rtype_document",
    "name": "Active Documents",
    "match": {
      "fields": {
        "status": "active"
      }
    }
  }'
```

### Match by Tags

```bash theme={null}
# All finance department documents
curl -X POST 'https://api.example.com/resource-collections' \
  -d '{
    "scopeId": "scope_org",
    "resourceTypeId": "rtype_document",
    "name": "Finance Documents",
    "match": {
      "tags": {
        "department": "finance"
      }
    }
  }'
```

```bash theme={null}
# Documents with any of these classifications
curl -X POST 'https://api.example.com/resource-collections' \
  -d '{
    "scopeId": "scope_org",
    "resourceTypeId": "rtype_document",
    "name": "Sensitive Documents",
    "match": {
      "tags": {
        "classification": ["confidential", "restricted", "top-secret"]
      }
    }
  }'
```

### Match by Patterns

```bash theme={null}
# All quarterly reports
curl -X POST 'https://api.example.com/resource-collections' \
  -d '{
    "scopeId": "scope_org",
    "resourceTypeId": "rtype_report",
    "name": "Quarterly Reports",
    "match": {
      "patterns": {
        "name": "Q*-Report-*"
      }
    }
  }'
```

### Match by Time

```bash theme={null}
# Documents created this year
curl -X POST 'https://api.example.com/resource-collections' \
  -d '{
    "scopeId": "scope_org",
    "resourceTypeId": "rtype_document",
    "name": "This Year Documents",
    "match": {
      "time": {
        "field": "createdAt",
        "after": "2024-01-01T00:00:00Z"
      }
    }
  }'
```

```bash theme={null}
# Documents modified in the last 30 days
curl -X POST 'https://api.example.com/resource-collections' \
  -d '{
    "scopeId": "scope_org",
    "resourceTypeId": "rtype_document",
    "name": "Recently Modified",
    "match": {
      "time": {
        "field": "updatedAt",
        "after": "-30d"
      }
    }
  }'
```

### Match by JSON Logic Condition

```bash theme={null}
# High-value orders
curl -X POST 'https://api.example.com/resource-collections' \
  -d '{
    "scopeId": "scope_org",
    "resourceTypeId": "rtype_order",
    "name": "High-Value Orders",
    "match": {
      "condition": {
        ">": [{"var": "data.totalAmount"}, 10000]
      }
    }
  }'
```

## Combining Match Rules

### All (AND)

All conditions must match:

```bash theme={null}
# Active finance documents created this year
curl -X POST 'https://api.example.com/resource-collections' \
  -d '{
    "scopeId": "scope_org",
    "resourceTypeId": "rtype_document",
    "name": "Active Finance Docs 2024",
    "match": {
      "all": [
        {"fields": {"status": "active"}},
        {"tags": {"department": "finance"}},
        {"time": {"field": "createdAt", "after": "2024-01-01T00:00:00Z"}}
      ]
    }
  }'
```

### Any (OR)

Any condition can match:

```bash theme={null}
# Documents from finance OR legal
curl -X POST 'https://api.example.com/resource-collections' \
  -d '{
    "scopeId": "scope_org",
    "resourceTypeId": "rtype_document",
    "name": "Finance or Legal Docs",
    "match": {
      "any": [
        {"tags": {"department": "finance"}},
        {"tags": {"department": "legal"}}
      ]
    }
  }'
```

### None (NOT)

Exclude matching resources:

```bash theme={null}
# All documents except archived
curl -X POST 'https://api.example.com/resource-collections' \
  -d '{
    "scopeId": "scope_org",
    "resourceTypeId": "rtype_document",
    "name": "Non-Archived Documents",
    "match": {
      "none": [
        {"fields": {"status": "archived"}}
      ]
    }
  }'
```

### Complex Combinations

```bash theme={null}
# Active documents from finance or legal, excluding drafts
curl -X POST 'https://api.example.com/resource-collections' \
  -d '{
    "scopeId": "scope_org",
    "resourceTypeId": "rtype_document",
    "name": "Published Finance/Legal Docs",
    "match": {
      "all": [
        {"fields": {"status": "active"}},
        {
          "any": [
            {"tags": {"department": "finance"}},
            {"tags": {"department": "legal"}}
          ]
        }
      ],
      "none": [
        {"fields": {"isDraft": true}}
      ]
    }
  }'
```

## Using Collections with Policies

Collections are most powerful when combined with [Resource Policies](/resources/resource-policies):

```bash theme={null}
# Create a collection
curl -X POST 'https://api.example.com/resource-collections' \
  -d '{
    "id": "collection_finance_docs",
    "scopeId": "scope_org",
    "resourceTypeId": "rtype_document",
    "name": "Finance Documents",
    "match": {
      "tags": {"department": "finance"}
    }
  }'

# Create a policy targeting the collection
curl -X POST 'https://api.example.com/resource-policies' \
  -d '{
    "scopeId": "scope_org",
    "name": "Finance Team Access",
    "target": {
      "kind": "collection",
      "collectionId": "collection_finance_docs"
    },
    "actions": ["read", "update"],
    "effect": "allow",
    "subjectCondition": {
      "==": [{"var": "subject.meta.department"}, "finance"]
    }
  }'
```

## Querying Collections

### Get Collections for a Scope

```bash theme={null}
curl -X GET 'https://api.example.com/resource-collections?scopeId=scope_org'
```

### Get Collection by ID

```bash theme={null}
curl -X GET 'https://api.example.com/resource-collections/collection_finance_docs'
```

## Collection Matching at Evaluation Time

When evaluating permissions, the engine:

1. Gets the resource being accessed
2. Finds all collections in scope
3. Evaluates each collection's match definition against the resource
4. Applies policies from matching collections

```typescript theme={null}
// Resource: { type: "document", tags: { department: "finance" }, status: "active" }
// Collection: { match: { tags: { department: "finance" } } }
// → Resource matches collection
// → Collection's policies apply
```

## Best Practices

<AccordionGroup>
  <Accordion title="Keep match definitions simple">
    Complex nested rules are hard to debug. Use multiple collections if needed.
  </Accordion>

  <Accordion title="Use descriptive names">
    Collection names should clearly describe what resources are included.
  </Accordion>

  <Accordion title="Test match definitions">
    Verify your match rules capture the intended resources before applying policies.
  </Accordion>

  <Accordion title="Consider performance">
    Very broad collections (matching many resources) may impact evaluation performance.
  </Accordion>

  <Accordion title="Name collections clearly">
    Collections have no description field—put the intent in the `name`.
  </Accordion>
</AccordionGroup>

## Related Concepts

<CardGroup cols={2}>
  <Card title="Resource Policies" icon="shield-check" href="/resources/resource-policies">
    Apply access rules to collections
  </Card>

  <Card title="Tags" icon="tags" href="/tags/tags">
    Tag resources for collection matching
  </Card>

  <Card title="Evaluation" icon="gears" href="/concepts/evaluation">
    How collections affect permission checks
  </Card>
</CardGroup>
