# Contributing to PyAuthz

Thank you for your interest in contributing to PyAuthz! This guide covers everything you need to get started.

## Development Setup

```bash
# Clone the repo
git clone https://github.com/marci/pyauthz.git
cd pyauthz

# Create a virtual environment
python -m venv .venv
.venv/Scripts/activate  # Windows
# source .venv/bin/activate  # macOS/Linux

# Install in editable mode with dev dependencies
pip install -e ".[dev]"

# Install framework extras if working on integrations
pip install fastapi httpx flask strawberry-graphql
```

## Running Tests

```bash
# Run all tests
pytest

# Run specific test file
pytest tests/test_engine.py

# Run with coverage
pytest --cov=pyauthz --cov-report=term-missing

# Run only core tests (faster)
pytest tests/

# Run framework integration tests
pytest tests_fastapi/ tests_flask/
```

## Code Quality

We use `ruff` for linting and formatting:

```bash
# Lint
ruff check .

# Auto-fix lint issues
ruff check --fix .

# Format
ruff format .
```

All code must pass `ruff check` and `ruff format --check` before merge.

## Project Structure

```
pyauthz/
├── core/           # Engine, decision, errors, conditions, cache, etc.
├── models/         # Pydantic data models (Subject, Resource, Role, etc.)
├── policies/       # Combiner algorithms
├── storage/        # Storage backends (memory, YAML loader, watcher)
├── filtering/      # Query filter compilation (AST, SQL, Django)
├── audit/          # Audit logging
├── testing/        # Testing utilities (AuthScenario, assertions)
├── cli/            # CLI tool (pyauthz check, simulate)
├── middleware/     # Shared middleware types
pyauthz_fastapi/    # FastAPI integration package
pyauthz_flask/      # Flask integration package
pyauthz_django/     # Django integration package
pyauthz_strawberry/ # Strawberry GraphQL integration package
tests/              # Core test suite
tests_fastapi/      # FastAPI integration tests
tests_flask/        # Flask integration tests
```

## Architecture

See [ARCHITECTURE.md](ARCHITECTURE.md) for a detailed overview of how the engine works, the evaluation pipeline, and design decisions.

## Making Changes

1. **Read the code first.** Understand the existing patterns before modifying.
2. **Write tests.** Every new feature or bug fix should include tests. Tests go in `tests/test_<module>.py`.
3. **Keep it simple.** PyAuthz values simplicity over cleverness. If there's a simple way to do it, prefer that.
4. **Don't break the public API.** The `pyauthz.__init__` exports define the public API. Changes to these are breaking changes.

## Commit Messages

- Explain *why*, not just *what*
- One logical change per commit
- Use imperative mood: "Add cache invalidation" not "Added cache invalidation"

## Adding a New Combiner

1. Create the combiner function in `pyauthz/policies/combiners.py`
2. Register it in the `COMBINERS` dict
3. Add tests in `tests/test_combiners.py`
4. Update the engine docstring and README

## Adding a New Framework Integration

1. Create a new namespace package at the project root: `pyauthz_<framework>/`
2. Follow the patterns from `pyauthz_fastapi/` or `pyauthz_flask/`
3. Add tests in `tests_<framework>/`
4. Add the framework to dev dependencies in `pyproject.toml`

## Adding a New Storage Backend

1. Implement the `StorageBackend` protocol from `pyauthz/storage/base.py`
2. Add tests that verify thread safety and correctness
3. Add the dependency to optional extras in `pyproject.toml`

## Reporting Issues

- Use GitHub Issues for bugs and feature requests
- Include a minimal reproduction case for bugs
- Include Python version, OS, and PyAuthz version
