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

# Permissions & Authorization

> Complete guide to SnackBase's collection-centric access control rules

SnackBase uses a database-centric rule engine that compiles expression-based rules into efficient SQL WHERE clauses for granular row-level security (RLS).

## Overview

In snackbase v0.2, permissions have shifted from a role-based model to a **Collection-centric** model. Instead of defining what each role can do, you define **Rules** directly on the collection.

Each collection has 5 distinct operations that can be controlled:

1. **list**: Controls which records appear in list results (row-level filtering).
2. **view**: Controls access to a single record by ID.
3. **create**: Validates whether a new record can be created.
4. **update**: Controls whether an existing record can be modified.
5. **delete**: Controls whether a record can be removed.

### Role Management

While rules are defined on collections, they still leverage user roles. Roles are now used as labels/identifiers within rule expressions (e.g., `@request.auth.role = "admin"`).

### Performance

Rule expressions are compiled into native SQL. This means:

* **No performance overhead**: Checks happen at the database level.
* **Scalable**: Works efficiently even with millions of records.
* **SQL-Native**: Supports complex joining logic via SQL Macros.

## Rule Syntax

### Variables

| Variable          | Description                            | Example                             |
| :---------------- | :------------------------------------- | :---------------------------------- |
| `@request.auth.*` | The authenticated user's data          | `id`, `email`, `role`, `account_id` |
| `@request.data.*` | The incoming data (create/update only) | `@request.data.status`              |
| `fieldname`       | Direct access to record fields         | `created_by`, `status`, `title`     |

### Operators

| Category       | Operator  | Description           | Example                              |            |                                |   |                                  |
| :------------- | :-------- | :-------------------- | :----------------------------------- | ---------- | ------------------------------ | - | -------------------------------- |
| **Comparison** | `=`       | Equal to              | `created_by = @request.auth.id`      |            |                                |   |                                  |
|                | `!=`      | Not equal to          | `status != "archived"`               |            |                                |   |                                  |
|                | `<` `>`   | Less/Greater than     | `priority > 10`                      |            |                                |   |                                  |
|                | `<=` `>=` | Less/Greater or equal | `amount >= 100`                      |            |                                |   |                                  |
|                | `~`       | LIKE (string match)   | `title ~ "draft%"`                   |            |                                |   |                                  |
| **Logical**    | `&&`      | Logical AND           | `status = "public" && active = true` |            |                                |   |                                  |
|                | \`        |                       | \`                                   | Logical OR | \`@request.auth.role = "admin" |   | created\_by = @request.auth.id\` |
|                | `!`       | Logical NOT           | `!is_locked`                         |            |                                |   |                                  |

### Literals

* **Strings**: `"text"` or `'text'`
* **Numbers**: `123`, `45.67`
* **Booleans**: `true`, `false`

## Built-in Macros

Macros are reusable expression fragments that simplify common patterns.

* `@has_role("role_name")`: Convenience for `@request.auth.role = "role_name"`
* `@has_group("group_name")`: Checks if user is in a specific group
* `@owns_record()`: Convenience for `created_by = @request.auth.id`
* `@is_creator()`: Same as `@owns_record()`

## SQL Macros

SQL macros allow you to create custom permission logic using raw SQL queries.

### Example: `@is_project_member(project_id)`

* **SQL Query**:
  ```sql theme={null}
  SELECT count(*) > 0 FROM project_members
  WHERE project_id = $1 AND user_id = @request.auth.id
  ```

* **Usage in Rule**:
  ```python theme={null}
  @is_project_member(project_id)
  ```

## System Fields

| Field        | Description                               |
| :----------- | :---------------------------------------- |
| `id`         | Auto-generated record identifier          |
| `account_id` | Account/tenant identifier (auto-set)      |
| `created_at` | Record creation timestamp (auto-set)      |
| `updated_at` | Record update timestamp (auto-set)        |
| `created_by` | User ID who created the record (auto-set) |
| `updated_by` | User ID who last updated the record       |

## Field-Level Access Control

You can restrict field visibility per operation. This is now managed via `list_fields`, `view_fields`, etc. in the collection rules.

```json theme={null}
{
  "list_fields": ["id", "title", "status"],
  "view_fields": "*"
}
```

## API Management

Collection rules are managed via the Collections API:

* `GET /api/v1/collections/{name}/rules`
* `PUT /api/v1/collections/{name}/rules`

## Common Patterns

### 1. Public Read Access

* **list\_rule**: `true`
* **view\_rule**: `true`
* **modify\_rules**: `@request.auth.role = "admin"`

### 2. Owner-Only Access

* **list\_rule**: `created_by = @request.auth.id`
* **view\_rule**: `created_by = @request.auth.id`
* **update\_rule**: `created_by = @request.auth.id`

## Related Guides

* [Writing Rules](./guides/writing-rules)
* [Macros Reference](./macros)
* [Deployment Guide](./deployment)
