# Row-Level Policies

Row-level security is frequently reimplemented incorrectly — a missed filter on the LIST endpoint leaks data, or an inconsistent check between READ and UPDATE creates privilege escalation. auen makes policies declarative so they're applied consistently across all operations.

## Implementing a policy

```python
class OwnerPolicy:
    def can_create(self, user, obj_in):
        return True

    def can_read(self, user, db_obj):
        return db_obj.author_id == user

    def can_update(self, user, db_obj, obj_in):
        return db_obj.author_id == user

    def can_delete(self, user, db_obj):
        return db_obj.author_id == user

    def filter_list_query(self, user, query):
        return query.where(Book.author_id == user)
```

The most critical method is `filter_list_query`, which prevents data leaks on LIST endpoints by modifying the database query itself rather than filtering results in Python.

## Default behavior

- **No auth + no policy**: all operations allowed
- **Auth + no policy**: all authenticated users can access everything
- **Auth + policy**: access controlled per-row
