# Backend Architecture Notes

## Stack

- **FastAPI REST API + SQLite** — async SQLAlchemy via sqlmodel, auto-created on startup with migrations.
- **`packages/core`** (`notify_bridge_core`): Shared library — providers, models, notifications, templates. No DB dependency. Includes `jinja2` dependency.
- **`packages/server`** (`notify_bridge_server`): FastAPI REST API + SQLite. Depends on core.

## Environment Variables

- `NOTIFY_BRIDGE_DATA_DIR`, `NOTIFY_BRIDGE_SECRET_KEY`, `NOTIFY_BRIDGE_DATABASE_URL`

## Key Constraints

- **SQLAlchemy async + aiohttp**: Cannot nest `async with aiohttp.ClientSession()` inside a route that has an active SQLAlchemy async session — greenlet context breaks. Eagerly load all DB data before entering aiohttp context.
- **Jinja2 SandboxedEnvironment**: All template rendering MUST use `from jinja2.sandbox import SandboxedEnvironment`.
- **System-owned entities**: `user_id=0` means system-owned (e.g. default templates).
- **FastAPI route ordering**: Static path routes MUST be registered BEFORE parameterized routes.
- **`__pycache__`**: Add to `.gitignore`. Never commit.

## API

- All CRUD routes under `/api/`, auth via JWT Bearer, `NOTIFY_BRIDGE_` env prefix.
