# AGENTS.md: Flask 3

## Commands
- Run: `flask --app app run --debug` · Test: `pytest -q` · Lint: `ruff check . && ruff format --check .`
- Migrations: `flask db migrate -m "msg"` then `flask db upgrade` (Flask-Migrate).

## Structure
- App factory `create_app(config=None)` in `app/__init__.py`; extensions created at module level and `init_app`'d in the factory.
- One blueprint per feature in `app/<feature>/routes.py`; logic in `app/<feature>/service.py`.
- SQLAlchemy 2.0 style: `db.session.execute(select(User).where(...)).scalars()`, typed models with `Mapped[...]` and `mapped_column`. No legacy `Model.query`.
- Validate input with a schema (marshmallow or pydantic, whatever the repo uses) before touching the DB.
- Config classes in `config.py` read from env; `SECRET_KEY` must come from env.
- Forms/HTML: Jinja autoescaping stays on; CSRF via Flask-WTF on every POST form.
- Return JSON errors from registered error handlers for API blueprints.

## Testing
- Fixtures: `app` (factory with test config, SQLite or a test Postgres), `client = app.test_client()`.
- Every new route gets a test for success and for bad input.

## Don't
- Don't use `app` as a global import inside blueprints; use `current_app`.
- Don't run with `debug=True` in production config.
