# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview SAPL (Sistema de Apoio ao Processo Legislativo) is a Django-based legislative management system used by Brazilian municipal and state legislative houses. It manages bills, parliamentary sessions, committees, norms, protocols, and related legislative workflows. ## Design references @/Users/eribeiro/projects/sapl-docs/rfc/files-metafields-impl.md ## Commands ### Development ```bash # Run dev server python manage.py runserver # Docker (dev, without bundled DB) docker-compose -f docker/docker-compose-dev.yml up # Docker (dev, with PostgreSQL container) docker-compose -f docker/docker-compose-dev-db.yml up ``` ### Database Setup (local PostgreSQL) ```bash sudo -u postgres psql -c "CREATE ROLE sapl LOGIN ENCRYPTED PASSWORD 'sapl' NOSUPERUSER INHERIT CREATEDB NOCREATEROLE NOREPLICATION;" sudo -u postgres psql -c "CREATE DATABASE sapl WITH OWNER=sapl ENCODING='UTF8' LC_COLLATE='pt_BR.UTF-8' LC_CTYPE='pt_BR.UTF-8' CONNECTION LIMIT=-1 TEMPLATE template0;" python manage.py migrate ``` ### Testing ```bash # All tests (reuses DB by default for speed) pytest # Single test file or test function pytest sapl/materia/tests/test_materia.py pytest sapl/materia/tests/test_materia.py::test_function_name # Force DB recreation pytest --create-db # With coverage pytest --cov=sapl ``` Tests require `DJANGO_SETTINGS_MODULE=sapl.settings` (set in `pytest.ini`). All tests must be marked with `@pytest.mark.django_db`. The `conftest.py` root fixture provides an `app` fixture (WebTest `DjangoTestApp`). ### Linting / Formatting ```bash flake8 . isort . autopep8 --in-place ``` ### Restore Database from Backup ```bash ./scripts/restore_db.sh -f /path/to/dump ./scripts/restore_db.sh -f /path/to/dump -p 5433 # Docker port ``` ## Architecture ### Django Apps Apps are under `sapl/` and follow domain boundaries: | App | Domain | |-----|--------| | `base` | `CasaLegislativa` (legislative house config), `AppConfig`, `Autor` (authorship) | | `parliamentary` | `Parlamentar`, `Legislatura`, `SessaoLegislativa`, `Coligacao` | | `materia` | Bills (`MateriaLegislativa`), types, tracking, annexes | | `norma` | Laws/norms (`NormaJuridica`) and hierarchies | | `sessao` | Plenary sessions, agenda, attendance, voting | | `comissoes` | Committees (`Comissao`) and meetings (`Reuniao`) | | `protocoloadm` | Administrative protocols and document intake | | `compilacao` | Structured/articulated texts (LexML-like tree structure) | | `lexml` | LexML XML standard integration | | `audiencia` | Public hearings | | `painel` | Real-time session display panel | | `relatorios` | PDF report generation | | `api` | REST API entry point (auto-generated ViewSets) | | `crud` | Generic CRUD base views | | `rules` | Business rules and permission definitions | ### REST API The API uses a custom `drfautoapi` package (`drfautoapi/drfautoapi.py`) that auto-generates DRF ViewSets, Serializers, and FilterSets from Django models. Authentication is Token + Session. Permissions use a custom `SaplModelPermissions` class that maps HTTP methods to Django model permissions. OpenAPI 3.0 docs are generated by drf-spectacular. ### Caching - **Default:** File-based (`/var/tmp/django_cache`) - **Production:** Redis via django-redis; configured at startup by `configure_redis_cache()` in `sapl/settings.py` - **Cache key prefix:** `cache:{POD_NAMESPACE}:` (namespace-isolated for multi-tenant k8s) - **Rate limiter state** is shared via Redis keys ### Feature Flags django-waffle is used for feature flags. Switches (global on/off) can be toggled via: ```bash python manage.py waffle_switch on|off ``` ### Key Environment Variables | Variable | Purpose | |----------|---------| | `DATABASE_URL` | PostgreSQL connection string | | `SECRET_KEY` | Django secret key | | `DEBUG` | Debug mode | | `REDIS_URL` | Redis host:port | | `CACHE_BACKEND` | `file` or `redis` | | `POD_NAMESPACE` | K8s namespace (used in cache key prefix) | | `USE_SOLR` | Enable Haystack/Solr full-text search | | `SOLR_URL` / `SOLR_COLLECTION` | Solr connection | ### Docker Build The production build requires a MaxMind GeoLite2-ASN license key (for nginx ASN-based bot blocking): ```bash docker build --secret id=maxmind_key,src=.env -f docker/Dockerfile -t sapl:local . ``` Optional build args: `WITH_NGINX`, `WITH_GRAPHVIZ`, `WITH_POPPLER`, `WITH_PSQL_CLIENT`. ### Key File Locations | File | Purpose | |------|---------| | `sapl/settings.py` | All Django settings, including cache/rate-limit setup | | `pytest.ini` | Test configuration (DJANGO_SETTINGS_MODULE, addopts) | | `conftest.py` | Root pytest fixtures | | `drfautoapi/drfautoapi.py` | Auto-API generation logic | | `docker/startup_scripts/start.sh` | Container entrypoint (migrations, waffle, gunicorn) | | `requirements/requirements.txt` | Production deps | | `requirements/test-requirements.txt` | Test deps | | `requirements/dev-requirements.txt` | Dev/lint deps |