Архитектура проекта
Документ описывает, как устроена система (раздел «Архитектура ПО»), и как разложен репозиторий и деплой (последующие разделы). Соглашения для контрибьюторов и проверяемые гейты — в CONTRIBUTING.md.
Архитектура ПО
Заголовок раздела «Архитектура ПО»Рантайм-процессы
Заголовок раздела «Рантайм-процессы»Приложение запускается двумя процессами, разделяющими одну проводку:
- backend (
main_backend.py) — aiohttp: HTTP API Mini App и админки, Telegram-вебхук, вебхуки платёжных провайдеров и панели. Поднимает два aiohttp-приложения на разных портах: вебхуки и Subscription WebApp (Mini App +/api/*). - worker (
main_worker.py) — фоновые задачи: тарифный воркер, синхронизация с панелью, обработчики очереди вебхуков.
Оба процесса вызывают run_setup(ctx) и register_core_reactions(ctx) — то есть оба
слушают шину доменных событий и активируют плагины. Любое изменение событийного слоя должно
одинаково работать в обоих.
Слои и поток запроса
Заголовок раздела «Слои и поток запроса»- Роуты регистрируются явно (
setup_subscription_webapp_routes,setup_admin_routes) и плагинами в рантайме (Plugin.setup_web). - DAL (
db/dal) — единственная точка доступа к БД; сервисы не пишут SQL мимо него. - Сервисы (
bot/services) держат бизнес-логику и публикуют события в ключевых точках.
Три типизированных контракта
Заголовок раздела «Три типизированных контракта»Архитектура держится на трёх явных, машинопроверяемых контрактах — это единый источник правды:
- HTTP API — pydantic request/response-модели + реестр
route_contracts, из которого генерируетсяopenapi.json. Подробно: architecture/http-api.md. - Шина доменных событий — одна pydantic-модель на событие (
bot/infra/event_payloads.py), публикация черезemit_model; payload — flat-dict из примитивов. Каталог: architecture/events.md. - Плагины — ABC
Plugin+PluginContext, обнаружение через entry-point группуminishop.plugins. Контракт: development/plugin-contract.md.
Расширяемость
Заголовок раздела «Расширяемость»Внешний код расширяет приложение через плагины (отдельные пакеты, entry points), не форкая ядро:
HTTP-роуты (setup_web), aiogram-роутеры (setup_bot), фоновые задачи, обработчики очереди,
миграции (неймспейснутые цепочки), локали, провайдер entitlements. Встроенные плагины активны
всегда; внешние гейтятся PLUGINS_ENABLED.
Контракт фронт↔бэк
Заголовок раздела «Контракт фронт↔бэк»OpenAPI-спек (docs/openapi.json) генерируется из живого роутера, из него генерируются
TypeScript-типы фронта (frontend/src/lib/api/openapi.generated.ts), а типизированный клиент
publicApi.ts выводит формы запроса/ответа по пути вызова. Оба артефакта защищены drift-guard
в CI — изменение контракта на бэке, не отражённое во фронте, валит сборку.
Раскладка репозитория
Заголовок раздела «Раскладка репозитория»Репозиторий разделён по зонам ответственности рантайма:
Основной docker-compose.yml находится в корне репозитория, чтобы docker compose up оставался простым продакшен-путем. Он собирает три прикладных образа из deploy/docker/Dockerfile:
backend: aiohttp API и вебхуки.worker: worker тарифов, синхронизация с панелью, обработчики очередей вебхуков.frontend: статические Svelte-ассеты, которые отдает nginx.
Сервис migrate - одноразовый контейнер на базе backend-образа. Он входит в стандартный Compose-граф: Postgres и Redis переходят в healthy-состояние, migrate применяет Base.metadata.create_all и ожидающие schema_migrations, а затем backend и worker стартуют только после успешного завершения migrate. Так миграции остаются автоматическими для docker compose up, но не запускаются внутри каждой backend-реплики.
Python-импорты намеренно остаются в пространствах bot.*, config.* и db.*. Контейнеры рантайма выставляют PYTHONPATH=/app/backend; локальные тесты используют такую же раскладку через pytest.ini.
Основные команды: