# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is a FastAPI + Telegram Bot backend application for managing Telegram channel integrations. The project uses: - **FastAPI** for HTTP API endpoints - **aiogram** for Telegram bot functionality - **SQLAlchemy 2.0** (async) for database operations - **PostgreSQL** with asyncpg driver - **Alembic** for database migrations - **uv** for Python package management ## Development Commands ### Environment Setup ```bash # Install dependencies (using uv) uv sync # Start PostgreSQL (via Docker Compose) docker-compose up -d # Run database migrations uv run alembic upgrade head ``` ### Running the Application ```bash # Start the FastAPI server uv run uvicorn src.main:app --host 0.0.0.0 --port 8000 --reload ``` ### Code Quality ```bash # Run linter (Ruff) uv run ruff check . # Format code uv run ruff format . # Type checking (mypy with strict mode) uv run mypy . ``` ### Testing ```bash # Run all tests uv run pytest # Run a single test file uv run pytest tests/test_file.py # Run a specific test uv run pytest tests/test_file.py::test_function_name ``` ### Database Migrations ```bash # Create a new migration uv run alembic revision --autogenerate -m "description" # Apply migrations uv run alembic upgrade head # Rollback one migration uv run alembic downgrade -1 ``` ## Architecture ### Layered Architecture The codebase follows a clean architecture pattern with clear separation of concerns: 1. **Domain Layer** (`src/domain/`) - SQLAlchemy ORM models that represent database entities - All models inherit from `domain.Base` which provides: - Auto-generated `id` (UUID primary key) - Timestamps: `created_at`, `updated_at`, `deleted_at` - Automatic table naming (pluralized lowercase class name) - Timezone-aware datetime fields 2. **Use Case Layer** (`src/usecase/`) - Business logic functions organized by feature - Each use case is a standalone function - Depends on Protocol interfaces (Database, TelegramWriter, JWTEncoder) - Use cases are assembled in the `Usecase` dataclass for dependency injection 3. **Adapter Layer** (`src/adapter/`) - Concrete implementations of protocol interfaces: - `Postgres`: Database operations (implements Database protocol) - `Telegram`: Telegram bot integration (implements TelegramWriter protocol) - `JWT`: Token encoding/decoding (implements JWTEncoder protocol) 4. **Controller Layer** (`src/controller/`) - **HTTP controllers** (`src/controller/http/`): FastAPI route handlers - **Telegram callbacks** (`src/controller/telegram_callback/`): Telegram event handlers - Controllers call use cases to perform business logic 5. **DTO Layer** (`src/dto/`) - Pydantic models for request/response validation - Separate from domain models to decouple API contracts from database schema ### Key Architectural Patterns **Dependency Injection via Protocols:** - Use cases depend on Protocol interfaces, not concrete implementations - Allows for easy testing and swapping implementations - See `src/usecase/__init__.py` for protocol definitions **Transaction Management:** - Database uses context-aware transactions via `DatabaseBase.transaction()` - Session stored in ContextVar (`_session_ctx`) for implicit session access - Always use `async with database.transaction()` for database operations - The session is accessible via `database.session` within transaction context **Shared Base Classes:** - `shared/datebase_base.py`: Base database class with connection pooling and migration checking - `shared/telegram_base.py`: Base Telegram bot class with polling lifecycle - `shared/logger/`: Structured logging with JSON and console formatters **Configuration:** - All config in `src/config.py` using Pydantic Settings - Environment variables loaded from `.env` file - Nested config via double underscore: `DB__URL`, `TELEGRAM__TOKEN` ### Application Lifecycle 1. **Startup** (in `src/main.py`): - Logger initialized - Adapters instantiated (Postgres, Telegram, JWT) - Usecase dataclass created with adapter dependencies - FastAPI lifespan context: - Connect to database (includes migration check) - Start Telegram bot polling 2. **Request Flow**: - HTTP: FastAPI route → Controller → Usecase → Adapter → Database - Telegram: Event → Telegram callback → Usecase → Adapter → Database 3. **Shutdown**: - Stop Telegram bot polling - Close database connections ### Important Implementation Details **Database Session Management:** - DO NOT create sessions manually - Use `async with database.transaction()` which handles begin/commit/rollback - Access session via `database.session` property within transaction context - Session lifecycle is managed by ContextVars for thread-safety **Telegram Bot Integration:** - Bot runs in polling mode (not webhook) - Routers registered in `src/controller/telegram_callback/` - Base class handles graceful shutdown of polling task **Authentication:** - JWT-based authentication for HTTP endpoints - Login flow: Telegram bot → Login token → JWT access token - Use `get_current_user` dependency for protected routes **Code Style:** - Single quotes for strings (configured in Ruff) - Line length: 120 characters - Python 3.13+ syntax - Strict mypy typing enabled